package compiler // Opcode represents a single bytecode instruction type Opcode uint8 const ( // Stack Operations OpLoadConst Opcode = iota // Load constant onto stack [idx] OpLoadLocal // Load local variable [slot] OpStoreLocal // Store top of stack to local [slot] OpLoadGlobal // Load global variable [idx] OpStoreGlobal // Store top of stack to global [idx] OpPop // Pop top value from stack OpDup // Duplicate top value on stack // Specialized Local Operations (no operands needed) OpLoadLocal0 // Load local slot 0 OpLoadLocal1 // Load local slot 1 OpLoadLocal2 // Load local slot 2 OpStoreLocal0 // Store to local slot 0 OpStoreLocal1 // Store to local slot 1 OpStoreLocal2 // Store to local slot 2 // Specialized Constants (no operands needed) OpLoadTrue // Load true constant OpLoadFalse // Load false constant OpLoadNil // Load nil constant OpLoadZero // Load number 0 OpLoadOne // Load number 1 // Arithmetic Operations OpAdd // a + b OpSub // a - b OpMul // a * b OpDiv // a / b OpNeg // -a OpMod // a % b // Specialized Arithmetic OpAddConst // local + constant [constIdx] OpSubConst // local - constant [constIdx] OpInc // increment local [slot] OpDec // decrement local [slot] // Comparison Operations OpEq // a == b OpNeq // a != b OpLt // a < b OpLte // a <= b OpGt // a > b OpGte // a >= b // Logical Operations OpNot // not a OpAnd // a and b OpOr // a or b // Control Flow OpJump // Unconditional jump [offset] OpJumpIfTrue // Jump if top of stack is true [offset] OpJumpIfFalse // Jump if top of stack is false [offset] OpCall // Call function [argCount] OpReturn // Return from function OpReturnNil // Return nil from function // Specialized Control Flow OpTestAndJump // Test local and jump [slot, offset] OpLoopBack // Optimized loop back jump [offset] // Table Operations OpNewTable // Create new empty table OpGetIndex // table[key] -> value OpSetIndex // table[key] = value OpGetField // table.field -> value [fieldIdx] OpSetField // table.field = value [fieldIdx] OpTableInsert // Insert value into table at next index // Specialized Table Operations OpGetLocalField // local.field -> value [slot, fieldIdx] OpSetLocalField // local.field = value [slot, fieldIdx] OpGetConstField // table.constField -> value [fieldName] // Struct Operations OpNewStruct // Create new struct instance [structId] OpGetProperty // struct.field -> value [fieldIdx] OpSetProperty // struct.field = value [fieldIdx] OpCallMethod // Call method on struct [methodIdx, argCount] // Function Operations OpClosure // Create closure from function [funcIdx, upvalueCount] OpGetUpvalue // Get upvalue [idx] OpSetUpvalue // Set upvalue [idx] OpCloseUpvalue // Close upvalue (move to heap) // Specialized Function Operations OpCallLocal0 // Call function in local slot 0 [argCount] OpCallLocal1 // Call function in local slot 1 [argCount] // Array Operations OpNewArray // Create new array with size [size] OpArrayAppend // Append value to array OpArrayGet // Optimized array[index] access OpArraySet // Optimized array[index] = value OpArrayLen // Get array length // Type Operations OpGetType // Get type of value on stack OpCast // Cast value to type [typeId] OpIsType // Check if value is type [typeId] // Type Checks (faster than generic OpGetType) OpIsNumber // Check if top of stack is number OpIsString // Check if top of stack is string OpIsTable // Check if top of stack is table OpIsBool // Check if top of stack is bool OpIsNil // Check if top of stack is nil // I/O Operations OpEcho // Echo value to output OpExit // Exit with code // Special Operations OpNoop // No operation OpBreak // Break from loop OpContinue // Continue loop iteration // Debug Operations OpDebugPrint // Debug print stack top OpDebugStack // Debug print entire stack ) // Instruction represents a single bytecode instruction with operands type Instruction struct { Op Opcode Operands []uint16 // Variable length operands } // Chunk represents a compiled chunk of bytecode type Chunk struct { Code []uint8 // Raw bytecode stream Constants []Value // Constant pool Lines []int // Line numbers for debugging Functions []Function // Function definitions Structs []Struct // Struct definitions } // Value represents a runtime value in the VM type Value struct { Type ValueType Data any // Actual value data } // ValueType represents the type of a runtime value type ValueType uint8 const ( ValueNil ValueType = iota ValueBool ValueNumber ValueString ValueTable ValueFunction ValueStruct ValueArray ValueUpvalue ) // Function represents a compiled function type Function struct { Name string // Function name (empty for anonymous) Arity int // Number of parameters Variadic bool // Whether function accepts variable args LocalCount int // Number of local variable slots UpvalCount int // Number of upvalues Chunk Chunk // Function bytecode Defaults []Value // Default parameter values } // Struct represents a compiled struct definition type Struct struct { Name string // Struct name Fields []StructField // Field definitions Methods map[string]uint16 // Method name -> function index ID uint16 // Unique struct identifier } // StructField represents a field in a struct type StructField struct { Name string // Field name Type ValueType // Field type Offset uint16 // Offset in struct layout } // Table represents a key-value table/map type Table struct { Array map[int]Value // Array part (integer keys) Hash map[string]Value // Hash part (string keys) Meta *Table // Metatable for operations } // Array represents a dynamic array type Array struct { Elements []Value // Array elements Count int // Current element count Capacity int // Current capacity } // StructInstance represents an instance of a struct type StructInstance struct { StructID uint16 // Reference to struct definition Fields map[string]Value // Field values } // Upvalue represents a captured variable type Upvalue struct { Location *Value // Pointer to actual value location Closed Value // Closed-over value (when moved to heap) IsClosed bool // Whether upvalue has been closed } // Instruction encoding helpers // EncodeInstruction encodes an instruction into bytecode func EncodeInstruction(op Opcode, operands ...uint16) []uint8 { bytes := []uint8{uint8(op)} for _, operand := range operands { bytes = append(bytes, uint8(operand&0xFF), uint8(operand>>8)) } return bytes } // DecodeInstruction decodes bytecode into instruction func DecodeInstruction(code []uint8, offset int) (Opcode, []uint16, int) { if offset >= len(code) { return OpNoop, nil, offset } op := Opcode(code[offset]) operands := []uint16{} nextOffset := offset + 1 // Decode operands based on instruction type operandCount := GetOperandCount(op) for range operandCount { if nextOffset+1 >= len(code) { break } operand := uint16(code[nextOffset]) | (uint16(code[nextOffset+1]) << 8) operands = append(operands, operand) nextOffset += 2 } return op, operands, nextOffset } // GetOperandCount returns the number of operands for an instruction func GetOperandCount(op Opcode) int { switch op { // No operand instructions case OpPop, OpDup, OpAdd, OpSub, OpMul, OpDiv, OpNeg, OpMod, OpEq, OpNeq, OpLt, OpLte, OpGt, OpGte, OpNot, OpAnd, OpOr, OpReturn, OpReturnNil, OpNewTable, OpGetIndex, OpSetIndex, OpTableInsert, OpArrayAppend, OpArrayGet, OpArraySet, OpArrayLen, OpGetType, OpIsNumber, OpIsString, OpIsTable, OpIsBool, OpIsNil, OpEcho, OpExit, OpNoop, OpBreak, OpContinue, OpDebugPrint, OpDebugStack, OpLoadLocal0, OpLoadLocal1, OpLoadLocal2, OpStoreLocal0, OpStoreLocal1, OpStoreLocal2, OpLoadTrue, OpLoadFalse, OpLoadNil, OpLoadZero, OpLoadOne: return 0 // Single operand instructions case OpLoadConst, OpLoadLocal, OpStoreLocal, OpLoadGlobal, OpStoreGlobal, OpJump, OpJumpIfTrue, OpJumpIfFalse, OpCall, OpGetField, OpSetField, OpNewStruct, OpGetProperty, OpSetProperty, OpNewArray, OpCast, OpIsType, OpAddConst, OpSubConst, OpInc, OpDec, OpGetConstField, OpCallLocal0, OpCallLocal1: return 1 // Two operand instructions case OpCallMethod, OpClosure, OpTestAndJump, OpGetLocalField, OpSetLocalField: return 2 default: return 0 } } // Instruction size calculation func InstructionSize(op Opcode) int { return 1 + (GetOperandCount(op) * 2) // 1 byte opcode + 2 bytes per operand } // Check if instruction is a specialized version of another func IsSpecializedInstruction(op Opcode) bool { switch op { case OpLoadLocal0, OpLoadLocal1, OpLoadLocal2, OpStoreLocal0, OpStoreLocal1, OpStoreLocal2, OpLoadTrue, OpLoadFalse, OpLoadNil, OpLoadZero, OpLoadOne, OpAddConst, OpSubConst, OpInc, OpDec, OpGetLocalField, OpSetLocalField, OpGetConstField, OpCallLocal0, OpCallLocal1, OpTestAndJump, OpLoopBack: return true default: return false } } var opcodeNames = map[Opcode]string{ OpLoadConst: "OP_LOAD_CONST", OpLoadLocal: "OP_LOAD_LOCAL", OpStoreLocal: "OP_STORE_LOCAL", OpLoadLocal0: "OP_LOAD_LOCAL_0", OpLoadLocal1: "OP_LOAD_LOCAL_1", OpLoadLocal2: "OP_LOAD_LOCAL_2", OpStoreLocal0: "OP_STORE_LOCAL_0", OpStoreLocal1: "OP_STORE_LOCAL_1", OpStoreLocal2: "OP_STORE_LOCAL_2", OpLoadTrue: "OP_LOAD_TRUE", OpLoadFalse: "OP_LOAD_FALSE", OpLoadNil: "OP_LOAD_NIL", OpLoadZero: "OP_LOAD_ZERO", OpLoadOne: "OP_LOAD_ONE", OpAdd: "OP_ADD", OpSub: "OP_SUB", OpMul: "OP_MUL", OpDiv: "OP_DIV", OpAddConst: "OP_ADD_CONST", OpSubConst: "OP_SUB_CONST", OpInc: "OP_INC", OpDec: "OP_DEC", OpJump: "OP_JUMP", OpJumpIfTrue: "OP_JUMP_TRUE", OpJumpIfFalse: "OP_JUMP_FALSE", OpTestAndJump: "OP_TEST_AND_JUMP", OpLoopBack: "OP_LOOP_BACK", OpReturn: "OP_RETURN", OpGetLocalField: "OP_GET_LOCAL_FIELD", OpSetLocalField: "OP_SET_LOCAL_FIELD", OpCallLocal0: "OP_CALL_LOCAL_0", OpCallLocal1: "OP_CALL_LOCAL_1", OpEcho: "OP_ECHO", }