// Author: simon // Author: ynwdlxm@163.com // Date: 2022/10/22 13:55 // Desc: Stack VM implement package vm import ( "fmt" "github/runnignwater/monkey/code" "github/runnignwater/monkey/compiler" "github/runnignwater/monkey/object" ) const StackSize = 2048 type VM struct { constants []object.Object instructions code.Instructions stack []object.Object sp int // Always points to the next value. Top of stack is stack[sp-1] } func New(byteCode *compiler.ByteCode) *VM { return &VM{ instructions: byteCode.Instructions, constants: byteCode.Constants, stack: make([]object.Object, StackSize), sp: 0, } } func (vm *VM) StackTop() object.Object { if vm.sp == 0 { return nil } return vm.stack[vm.sp-1] } func (vm *VM) Run() error { for ip := 0; ip < len(vm.instructions); ip++ { op := code.Opcode(vm.instructions[ip]) switch op { case code.OpConstant: constIndex := code.ReadUint16(vm.instructions[ip+1:]) ip += 2 // 执行 err := vm.push(vm.constants[constIndex]) if err != nil { return err } case code.OpAdd: right := vm.pop() left := vm.pop() leftValue := left.(*object.Integer).Value rightValue := right.(*object.Integer).Value result := leftValue + rightValue err := vm.push(&object.Integer{Value: result}) if err != nil { return err } } } return nil } func (vm *VM) push(o object.Object) error { if vm.sp >= StackSize { return fmt.Errorf("stack overflow") } vm.stack[vm.sp] = o vm.sp++ return nil } func (vm *VM) pop() object.Object { o := vm.stack[vm.sp-1] vm.sp-- return o }