| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // 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
- var True = &object.Boolean{Value: true}
- var False = &object.Boolean{Value: false}
- 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.OpTrue:
- err := vm.push(True)
- if err != nil {
- return err
- }
- case code.OpFalse:
- err := vm.push(False)
- if err != nil {
- return err
- }
- case code.OpAdd, code.OpSub, code.OpMul, code.OpDiv:
- err := vm.executeBinaryOperation(op)
- if err != nil {
- return err
- }
- case code.OpPop:
- vm.pop()
- }
- }
- 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
- }
- func (vm *VM) executeBinaryOperation(op code.Opcode) error {
- right := vm.pop()
- left := vm.pop()
- leftType := left.Type()
- rightType := right.Type()
- if leftType == object.IntegerObj && rightType == object.IntegerObj {
- return vm.executeBinaryIntegerOperation(op, left, right)
- }
- return fmt.Errorf("unsupported types of binary operation: %s %s", leftType, rightType)
- }
- func (vm *VM) LastPopStackElem() object.Object {
- return vm.stack[vm.sp]
- }
- func (vm *VM) executeBinaryIntegerOperation(
- op code.Opcode,
- left, right object.Object,
- ) error {
- leftValue := left.(*object.Integer).Value
- rightValue := right.(*object.Integer).Value
- var result int64
- switch op {
- case code.OpAdd:
- result = leftValue + rightValue
- case code.OpSub:
- result = leftValue - rightValue
- case code.OpMul:
- result = leftValue * rightValue
- case code.OpDiv:
- result = leftValue / rightValue
- default:
- return fmt.Errorf("unknown integer operator: %d", op)
- }
- return vm.push(&object.Integer{Value: result})
- }
|