private PsudoInstruction CompileCase(PsudoMethod method, string variable, int start, out int endLine) { int nextStart = codeLines.ToList().FindIndex(start + 1, item => item.Contains(":") || Regex.IsMatch(item, @"^[\s]*\b(endcase)\b[\s]*", RegexOptions.IgnoreCase) ); if (nextStart < 0) { throw new Exception("CASE found with no ENDCASE"); } string[] parts = codeLines[start].Split(':'); string lineBackup = codeLines[start]; // Do this to help the compiler codeLines[start] = parts[1].Trim(); if (parts[0].Trim().ToLower().Contains("other")) { BlockInstruction ins = new BlockInstruction(start, method); ins.Instructions = CompileBlock(method, start, nextStart - 1); endLine = nextStart; codeLines[start] = lineBackup; return(ins); } else { string decision = variable + "==" + parts[0].Trim(); DecisionInstruction ins = new DecisionInstruction(start, method, decision); ins.Instructions = CompileBlock(method, start, nextStart - 1); if (codeLines[nextStart].ToLower().Contains("endcase")) { endLine = nextStart; ins.FalseInstruction = new NoOpInstruction(endLine, method); } else { ins.FalseInstruction = CompileCase(method, variable, nextStart, out endLine); } ins.EndInstruction = new NoOpInstruction(endLine, method); codeLines[start] = lineBackup; return(ins); } }
internal static BlockInstruction Create(BinaryParsingReader reader) { BuiltinLanguageType blockType = (BuiltinLanguageType)reader.ReadVarInt7(); BlockInstruction result = _perTypeBlock[(int)blockType + 128]; if (null != result) { _reuseCount++; } else { result = new BlockInstruction() { BlockType = blockType }; _perTypeBlock[(int)blockType + 128] = result; } return(result); }
internal Instruction ReadInstruction() { OpCodes opcode = (OpCodes)this.ReadByte(); Instruction result = Instruction.FixedOpCodes[(int)opcode]; if (null != result) { return(result); } switch (opcode) { case OpCodes.Block: return(BlockInstruction.Create(this)); case OpCodes.Loop: return(LoopInstruction.Create(this)); case OpCodes.If: // block_type return(IfInstruction.Create(this)); case OpCodes.Br: case OpCodes.BrIf: // varuint32 return(BranchInstruction.Create(this, opcode)); case OpCodes.BrTable: // custom return(BranchTableInstruction.Create(this)); case OpCodes.Call: case OpCodes.CallIndirect: // varuint32 + varuint1 return(CallInstruction.Create(this, opcode)); case OpCodes.GetLocal: case OpCodes.SetLocal: case OpCodes.TeeLocal: // local_index return(LocalAccessorInstruction.Create(this, opcode)); case OpCodes.GetGlobal: case OpCodes.SetGlobal: // global_index return(GlobalAccessorInstruction.Create(this, (OpCodes.GetGlobal == opcode))); case OpCodes.I32Load: case OpCodes.I64Load: case OpCodes.F32Load: case OpCodes.F64Load: case OpCodes.I32Load8_s: case OpCodes.I32Load8_u: case OpCodes.I32Load16_s: case OpCodes.I32Load16_u: case OpCodes.I64Load8_s: case OpCodes.I64Load8_u: case OpCodes.I64Load16_s: case OpCodes.I64Load16_u: case OpCodes.I64Load32_s: case OpCodes.I64Load32_u: case OpCodes.I32Store: case OpCodes.I64Store: case OpCodes.F32Store: case OpCodes.F64Store: case OpCodes.I32Store8: case OpCodes.I32Store16: case OpCodes.I64Store8: case OpCodes.I64Store16: case OpCodes.I64Store32: // memory_immediate return(MemoryAccessInstruction.Create(this, opcode)); case OpCodes.CurrentMemory: case OpCodes.GrowMemory: // varuint1 return(MemoryControlInstruction.Create(this, opcode)); case OpCodes.I32Const: // varint32 return(ConstantValueInstruction <int> .Create(this, OpCodes.I32Const, this.ReadVarInt32())); case OpCodes.I64Const: // varint64 return(ConstantValueInstruction <long> .Create(this, OpCodes.I64Const, this.ReadVarInt64())); case OpCodes.F32Const: // uint32 return(ConstantValueInstruction <float> .Create(this, OpCodes.F32Const, this.ReadVarFloat32())); case OpCodes.F64Const: // uint64 return(ConstantValueInstruction <double> .Create(this, OpCodes.F64Const, this.ReadVarFloat64())); case OpCodes.F32eq: case OpCodes.F32ge: case OpCodes.F32gt: case OpCodes.F32le: case OpCodes.F32lt: case OpCodes.F32ne: case OpCodes.F64eq: case OpCodes.F64ge: case OpCodes.F64gt: case OpCodes.F64le: case OpCodes.F64lt: case OpCodes.F64ne: case OpCodes.I32eq: case OpCodes.I32ge_s: case OpCodes.I32ge_u: case OpCodes.I32gt_s: case OpCodes.I32gt_u: case OpCodes.I32le_s: case OpCodes.I32le_u: case OpCodes.I32lt_s: case OpCodes.I32lt_u: case OpCodes.I32ne: case OpCodes.I64eq: case OpCodes.I64ge_s: case OpCodes.I64ge_u: case OpCodes.I64gt_s: case OpCodes.I64gt_u: case OpCodes.I64le_s: case OpCodes.I64le_u: case OpCodes.I64lt_s: case OpCodes.I64lt_u: case OpCodes.I64ne: return(RelationalInstruction.GetInstruction(opcode)); case OpCodes.F32Convert_sI32: case OpCodes.F32Convert_uI32: case OpCodes.F32Convert_sI64: case OpCodes.F32Convert_uI64: case OpCodes.F32demoteF64: case OpCodes.F64Convert_sI32: case OpCodes.F64Convert_uI32: case OpCodes.F64Convert_sI64: case OpCodes.F64Convert_uI64: case OpCodes.F64PromoteF32: case OpCodes.I32Trunc_sF32: case OpCodes.I32Trunc_uF32: case OpCodes.I32Trunc_sF64: case OpCodes.I32Trunc_uF64: case OpCodes.I32wrapI64: case OpCodes.I64Extend_sI32: case OpCodes.I64Extend_uI32: case OpCodes.I64Trunc_sF32: case OpCodes.I64Trunc_uF32: case OpCodes.I64Trunc_sF64: case OpCodes.I64Trunc_uF64: return(ConversionInstruction.GetInstruction(opcode)); default: throw new NotSupportedException(); } }
protected PsudoInstruction CompileDecision(PsudoMethod method, int line, out int endLine) { if (Regex.IsMatch(codeLines[line], @"^[\s]*\b(if|elseif)\b[\s]*", RegexOptions.IgnoreCase)) { string decision = codeLines[line].Trim(); if (decision.ToLower().Contains("elseif")) { decision = decision.Substring(6); } else { decision = decision.Substring(2); } while (!decision.ToLower().Contains("then")) { if (line + 1 == codeLines.Length || Regex.IsMatch(codeLines[line + 1], @"^[\s]*\b(else|elseif|endif)\b[\s]*", RegexOptions.IgnoreCase) ) { throw new Exception("IF found without THEN"); } decision += " " + codeLines[line + 1]; line += 1; } decision = decision.Trim(); decision = decision.Substring(0, decision.Length - 4).Trim(); DecisionInstruction ins = new DecisionInstruction(line, method, decision); int next = -1; int end = -1; int nested = 0; for (int num = line + 1; num < codeLines.Length; num++) { string item = codeLines[num]; if (Regex.IsMatch(item, @"^[\s]*\b(if)\b[\s]*", RegexOptions.IgnoreCase)) { nested++; } if (Regex.IsMatch(item, @"^[\s]*\b(endif)\b[\s]*", RegexOptions.IgnoreCase)) { if (nested == 0) { if (next < 0) { next = num; } end = num; } else { nested--; } } if (nested == 0 && next < 0) { if (Regex.IsMatch(item, @"^[\s]*\b(elseif|else)\b[\s]*", RegexOptions.IgnoreCase)) { next = num; } } } if (end < 0) { throw new Exception("IF found with no ENDIF"); } ins.Instructions = CompileBlock(method, line + 1, next - 1); int temp; ins.FalseInstruction = CompileDecision(method, next, out temp); ins.EndInstruction = CompileDecision(method, end, out temp); endLine = end; return(ins); } else if (Regex.IsMatch(codeLines[line], @"^[\s]*\b(else)\b[\s]*", RegexOptions.IgnoreCase)) { BlockInstruction ins = new BlockInstruction(line, method); int next = codeLines.ToList().FindIndex(line, item => Regex.IsMatch(item, @"^[\s]*\b(endif)\b[\s]*", RegexOptions.IgnoreCase)); ins.Instructions = CompileBlock(method, line + 1, next - 1); endLine = next; return(ins); } else if (Regex.IsMatch(codeLines[line], @"^[\s]*\b(endif)\b[\s]*", RegexOptions.IgnoreCase)) { endLine = line; return(new NoOpInstruction(line, method)); } else if (Regex.IsMatch(codeLines[line], @"^[\s]*\b(case of|case)\b[\s]*", RegexOptions.IgnoreCase)) { // Trim of case/case of string variable = Regex.Replace(codeLines[line], @"\b(case of|case)\b", "").Trim(); int start = codeLines.ToList().FindIndex(line + 1, item => item.Contains(":")); if (start < 0) { throw new Exception("CASE Statement contains no options or options are formmed incorrectly"); } return(CompileCase(method, variable, start, out endLine)); } endLine = line; return(null); }