vm.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Author: simon
  2. // Author: ynwdlxm@163.com
  3. // Date: 2022/10/22 13:55
  4. // Desc: Stack VM implement
  5. package vm
  6. import (
  7. "fmt"
  8. "github/runnignwater/monkey/code"
  9. "github/runnignwater/monkey/compiler"
  10. "github/runnignwater/monkey/object"
  11. )
  12. const StackSize = 2048
  13. type VM struct {
  14. constants []object.Object
  15. instructions code.Instructions
  16. stack []object.Object
  17. sp int // Always points to the next value. Top of stack is stack[sp-1]
  18. }
  19. func New(byteCode *compiler.ByteCode) *VM {
  20. return &VM{
  21. instructions: byteCode.Instructions,
  22. constants: byteCode.Constants,
  23. stack: make([]object.Object, StackSize),
  24. sp: 0,
  25. }
  26. }
  27. // func (vm *VM) StackTop() object.Object {
  28. // if vm.sp == 0 {
  29. // return nil
  30. // }
  31. // return vm.stack[vm.sp-1]
  32. // }
  33. func (vm *VM) Run() error {
  34. for ip := 0; ip < len(vm.instructions); ip++ {
  35. op := code.Opcode(vm.instructions[ip])
  36. switch op {
  37. case code.OpConstant:
  38. constIndex := code.ReadUint16(vm.instructions[ip+1:])
  39. ip += 2
  40. // 执行
  41. err := vm.push(vm.constants[constIndex])
  42. if err != nil {
  43. return err
  44. }
  45. case code.OpAdd, code.OpSub, code.OpMul, code.OpDiv:
  46. err := vm.executeBinaryOperation(op)
  47. if err != nil {
  48. return err
  49. }
  50. case code.OpPop:
  51. vm.pop()
  52. }
  53. }
  54. return nil
  55. }
  56. func (vm *VM) push(o object.Object) error {
  57. if vm.sp >= StackSize {
  58. return fmt.Errorf("stack overflow")
  59. }
  60. vm.stack[vm.sp] = o
  61. vm.sp++
  62. return nil
  63. }
  64. func (vm *VM) pop() object.Object {
  65. o := vm.stack[vm.sp-1]
  66. vm.sp--
  67. return o
  68. }
  69. func (vm *VM) executeBinaryOperation(op code.Opcode) error {
  70. right := vm.pop()
  71. left := vm.pop()
  72. leftType := left.Type()
  73. rightType := right.Type()
  74. if leftType == object.IntegerObj && rightType == object.IntegerObj {
  75. return vm.executeBinaryIntegerOperation(op, left, right)
  76. }
  77. return fmt.Errorf("unsupported types of binary operation: %s %s", leftType, rightType)
  78. }
  79. func (vm *VM) LastPopStackElem() object.Object {
  80. return vm.stack[vm.sp]
  81. }
  82. func (vm *VM) executeBinaryIntegerOperation(
  83. op code.Opcode,
  84. left, right object.Object,
  85. ) error {
  86. leftValue := left.(*object.Integer).Value
  87. rightValue := right.(*object.Integer).Value
  88. var result int64
  89. switch op {
  90. case code.OpAdd:
  91. result = leftValue + rightValue
  92. case code.OpSub:
  93. result = leftValue - rightValue
  94. case code.OpMul:
  95. result = leftValue * rightValue
  96. case code.OpDiv:
  97. result = leftValue / rightValue
  98. default:
  99. return fmt.Errorf("unknown integer operator: %d", op)
  100. }
  101. return vm.push(&object.Integer{Value: result})
  102. }