internal static void Disassemble(this ByteCodeChunk self, Source[] sources, StringBuilder sb) { var currentSourceIndex = -1; sb.Append("== "); sb.Append(self.bytes.count); sb.AppendLine(" bytes =="); sb.AppendLine("line byte instruction"); for (var index = 0; index < self.bytes.count;) { var sourceIndex = self.FindSourceIndex(index); var source = sources[sourceIndex]; if (sourceIndex != currentSourceIndex) { sb.Append(source.uri.value); currentSourceIndex = sourceIndex; } PrintFunctionName(self, index, sb); PrintLineNumber(self, source.content, index, sb); index = DisassembleInstruction(self, index, sb); sb.AppendLine(); } sb.AppendLine("== end =="); }
private static int TwoByteInstruction(ByteCodeChunk chunk, Instruction instruction, int index, StringBuilder sb) { sb.Append(instruction.ToString()); sb.Append(' '); sb.Append(chunk.bytes.buffer[index + 1]); return(index + 2); }
public static void FormatStructType(this ByteCodeChunk self, ushort structTypeIndex, StringBuilder sb) { if (structTypeIndex >= self.structTypes.count) { sb.Append("<!>"); return; } var type = self.structTypes.buffer[structTypeIndex]; sb.Append(type.name); sb.Append('{'); for (var i = 0; i < type.fields.length; i++) { var fieldIndex = type.fields.index + i; var field = self.structTypeFields.buffer[fieldIndex]; sb.Append(field.name); sb.Append(':'); field.type.Format(self, sb); if (i < type.fields.length - 1) { sb.Append(','); } } sb.Append('}'); }
public static void FormatFunctionType(this ByteCodeChunk self, ushort functionTypeIndex, StringBuilder sb) { if (functionTypeIndex >= self.functionTypes.count) { sb.Append("<!>"); return; } var type = self.functionTypes.buffer[functionTypeIndex]; sb.Append("fn("); for (var i = 0; i < type.parameters.length; i++) { var paramIndex = type.parameters.index + i; var paramType = self.functionParamTypes.buffer[paramIndex]; paramType.Format(self, sb); if (i < type.parameters.length - 1) { sb.Append(','); } } sb.Append(')'); if (!type.returnType.IsKind(TypeKind.Unit)) { sb.Append(':'); type.returnType.Format(self, sb); } }
public ByteCodeChunkDebugView(ByteCodeChunk chunk) { var sb = new StringBuilder(); chunk.Disassemble(sb); lines = sb.ToString().Split(new string[] { "\n", "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries); }
private static int LoadLiteralInstruction(ByteCodeChunk chunk, Instruction instruction, int index, StringBuilder sb) { var literalIndex = BytesHelper.BytesToUShort( chunk.bytes.buffer[index + 1], chunk.bytes.buffer[index + 2] ); var value = chunk.literalData.buffer[literalIndex]; var type = chunk.literalKinds.buffer[literalIndex]; sb.Append(instruction.ToString()); sb.Append(' '); switch (type) { case TypeKind.Int: sb.Append(value.asInt); break; case TypeKind.Float: sb.Append(value.asFloat); break; case TypeKind.String: sb.Append('"'); sb.Append(chunk.stringLiterals.buffer[value.asInt]); sb.Append('"'); break; } return(index + 3); }
private static int LoadNativeFunctionInstruction(ByteCodeChunk chunk, Instruction instruction, int index, StringBuilder sb) { sb.Append(instruction.ToString()); sb.Append(' '); var functionIndex = BytesHelper.BytesToUShort( chunk.bytes.buffer[index + 1], chunk.bytes.buffer[index + 2] ); FormatNativeFunction(chunk, functionIndex, sb); return(index + 3); }
public static int FindSourceIndex(this ByteCodeChunk self, int codeIndex) { for (var i = 0; i < self.sourceStartIndexes.count; i++) { if (codeIndex >= self.sourceStartIndexes.buffer[i]) { return(i); } } return(-1); }
public static void FormatNativeFunction(this ByteCodeChunk self, int functionIndex, StringBuilder sb) { if (functionIndex >= self.nativeFunctions.count) { sb.Append("<!>"); return; } var function = self.nativeFunctions.buffer[functionIndex]; sb.Append(function.name); sb.Append(' '); FormatFunctionType(self, function.typeIndex, sb); }
private static void PrintFunctionName(ByteCodeChunk self, int codeIndex, StringBuilder sb) { for (var i = 0; i < self.functions.count; i++) { var function = self.functions.buffer[i]; if (function.codeIndex == codeIndex) { sb.Append(" // "); self.FormatFunction(i, sb); sb.AppendLine(); break; } } }
private static int JumpInstruction(ByteCodeChunk chunk, Instruction instruction, int sign, int index, StringBuilder sb) { sb.Append(instruction.ToString()); sb.Append(' '); var offset = BytesHelper.BytesToUShort( chunk.bytes.buffer[index + 1], chunk.bytes.buffer[index + 2] ); sb.Append(offset); sb.Append(" (goto "); sb.Append(index + 3 + offset * sign); sb.Append(")"); return(index + 3); }
public static void Disassemble(this ByteCodeChunk self, StringBuilder sb) { sb.Append("== "); sb.Append(self.bytes.count); sb.AppendLine(" bytes =="); sb.AppendLine("byte instruction"); for (var index = 0; index < self.bytes.count;) { PrintFunctionName(self, index, sb); index = DisassembleInstruction(self, index, sb); sb.AppendLine(); } sb.AppendLine("== end =="); }
private static int TypeInstruction(ByteCodeChunk chunk, Instruction instruction, int index, StringBuilder sb) { sb.Append(instruction.ToString()); sb.Append(' '); var type = ValueType.Read( chunk.bytes.buffer[index + 1], chunk.bytes.buffer[index + 2], chunk.bytes.buffer[index + 3], chunk.bytes.buffer[index + 4] ); type.Format(chunk, sb); return(index + 5); }
public static void FormatFunction(this ByteCodeChunk self, int functionIndex, StringBuilder sb) { if (functionIndex >= self.functions.count) { sb.Append("<!>"); return; } var function = self.functions.buffer[functionIndex]; if (string.IsNullOrEmpty(function.name)) { sb.Append("<anonymous>"); } else { sb.Append(function.name); } sb.Append(' '); FormatFunctionType(self, function.typeIndex, sb); }
private static void PrintLineNumber(ByteCodeChunk self, string source, int index, StringBuilder sb) { var currentSourceIndex = self.sourceSlices.buffer[index].index; var currentPosition = FormattingHelper.GetLineAndColumn(source, currentSourceIndex); var lastLineIndex = -1; if (index > 0) { var lastSourceIndex = self.sourceSlices.buffer[index - 1].index; lastLineIndex = FormattingHelper.GetLineAndColumn(source, lastSourceIndex).lineIndex; } if (currentPosition.lineIndex == lastLineIndex) { sb.Append(" | "); } else { sb.AppendFormat("{0,4} ", currentPosition.lineIndex); } }
public static void FormatTupleType(this ByteCodeChunk self, ushort tupleTypeIndex, StringBuilder sb) { if (tupleTypeIndex >= self.tupleTypes.count) { sb.Append("<!>"); return; } sb.Append('{'); var type = self.tupleTypes.buffer[tupleTypeIndex]; for (var i = 0; i < type.elements.length; i++) { var elementIndex = type.elements.index + i; var elementType = self.tupleElementTypes.buffer[elementIndex]; elementType.Format(self, sb); if (i < type.elements.length - 1) { sb.Append(','); } } sb.Append('}'); }
public static int DisassembleInstruction(this ByteCodeChunk self, int index, StringBuilder sb) { sb.AppendFormat("{0:0000} ", index); var instructionCode = self.bytes.buffer[index]; var instruction = (Instruction)instructionCode; switch (instruction) { case Instruction.Halt: case Instruction.Pop: case Instruction.LoadUnit: case Instruction.LoadFalse: case Instruction.LoadTrue: case Instruction.IntToFloat: case Instruction.FloatToInt: case Instruction.LoadArrayLength: case Instruction.NegateInt: case Instruction.NegateFloat: case Instruction.AddInt: case Instruction.AddFloat: case Instruction.SubtractInt: case Instruction.SubtractFloat: case Instruction.MultiplyInt: case Instruction.MultiplyFloat: case Instruction.DivideInt: case Instruction.DivideFloat: case Instruction.Not: case Instruction.EqualBool: case Instruction.EqualInt: case Instruction.EqualFloat: case Instruction.EqualString: case Instruction.GreaterInt: case Instruction.GreaterFloat: case Instruction.LessInt: case Instruction.LessFloat: case Instruction.DebugHook: case Instruction.DebugPushFrame: case Instruction.DebugPopFrame: return(OneByteInstruction(instruction, index, sb)); case Instruction.Call: case Instruction.CallNative: case Instruction.Return: case Instruction.PopMultiple: case Instruction.SetLocal: case Instruction.LoadLocal: case Instruction.IncrementLocalInt: case Instruction.CreateArrayFromDefault: case Instruction.CreateStackReference: case Instruction.RepeatLoopCheck: case Instruction.DebugPopTypeMultiple: case Instruction.DebugPopLocalVariableNameMultiple: return(TwoByteInstruction(self, instruction, index, sb)); case Instruction.Move: case Instruction.SetLocalMultiple: case Instruction.CreateArrayFromStack: case Instruction.LoadLocalMultiple: case Instruction.CreateArrayElementReference: case Instruction.DebugPushLocalVariableName: return(ThreeByteInstruction(self, instruction, index, sb)); case Instruction.SetArrayElement: case Instruction.LoadArrayElement: case Instruction.SetReference: case Instruction.LoadReference: return(FourByteInstruction(self, instruction, index, sb)); case Instruction.LoadLiteral: return(LoadLiteralInstruction(self, instruction, index, sb)); case Instruction.LoadFunction: return(LoadFunctionInstruction(self, instruction, index, sb)); case Instruction.LoadNativeFunction: return(LoadNativeFunctionInstruction(self, instruction, index, sb)); case Instruction.JumpForward: case Instruction.JumpForwardIfFalse: case Instruction.JumpForwardIfTrue: case Instruction.PopAndJumpForwardIfFalse: return(JumpInstruction(self, instruction, 1, index, sb)); case Instruction.JumpBackward: return(JumpInstruction(self, instruction, -1, index, sb)); case Instruction.Print: case Instruction.DebugPushType: return(TypeInstruction(self, instruction, index, sb)); default: sb.Append("Unknown instruction "); sb.Append(instruction.ToString()); return(index + 1); } }