vm.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. var True = &object.Boolean{Value: true}
  14. var False = &object.Boolean{Value: false}
  15. type VM struct {
  16. constants []object.Object
  17. instructions code.Instructions
  18. stack []object.Object
  19. sp int // Always points to the next value. Top of stack is stack[sp-1]
  20. }
  21. func New(byteCode *compiler.ByteCode) *VM {
  22. return &VM{
  23. instructions: byteCode.Instructions,
  24. constants: byteCode.Constants,
  25. stack: make([]object.Object, StackSize),
  26. sp: 0,
  27. }
  28. }
  29. // func (vm *VM) StackTop() object.Object {
  30. // if vm.sp == 0 {
  31. // return nil
  32. // }
  33. // return vm.stack[vm.sp-1]
  34. // }
  35. func (vm *VM) Run() error {
  36. for ip := 0; ip < len(vm.instructions); ip++ {
  37. op := code.Opcode(vm.instructions[ip])
  38. switch op {
  39. case code.OpConstant:
  40. constIndex := code.ReadUint16(vm.instructions[ip+1:])
  41. ip += 2
  42. // 执行
  43. err := vm.push(vm.constants[constIndex])
  44. if err != nil {
  45. return err
  46. }
  47. case code.OpTrue:
  48. err := vm.push(True)
  49. if err != nil {
  50. return err
  51. }
  52. case code.OpFalse:
  53. err := vm.push(False)
  54. if err != nil {
  55. return err
  56. }
  57. case code.OpAdd, code.OpSub, code.OpMul, code.OpDiv:
  58. err := vm.executeBinaryOperation(op)
  59. if err != nil {
  60. return err
  61. }
  62. case code.OpPop:
  63. vm.pop()
  64. }
  65. }
  66. return nil
  67. }
  68. func (vm *VM) push(o object.Object) error {
  69. if vm.sp >= StackSize {
  70. return fmt.Errorf("stack overflow")
  71. }
  72. vm.stack[vm.sp] = o
  73. vm.sp++
  74. return nil
  75. }
  76. func (vm *VM) pop() object.Object {
  77. o := vm.stack[vm.sp-1]
  78. vm.sp--
  79. return o
  80. }
  81. func (vm *VM) executeBinaryOperation(op code.Opcode) error {
  82. right := vm.pop()
  83. left := vm.pop()
  84. leftType := left.Type()
  85. rightType := right.Type()
  86. if leftType == object.IntegerObj && rightType == object.IntegerObj {
  87. return vm.executeBinaryIntegerOperation(op, left, right)
  88. }
  89. return fmt.Errorf("unsupported types of binary operation: %s %s", leftType, rightType)
  90. }
  91. func (vm *VM) LastPopStackElem() object.Object {
  92. return vm.stack[vm.sp]
  93. }
  94. func (vm *VM) executeBinaryIntegerOperation(
  95. op code.Opcode,
  96. left, right object.Object,
  97. ) error {
  98. leftValue := left.(*object.Integer).Value
  99. rightValue := right.(*object.Integer).Value
  100. var result int64
  101. switch op {
  102. case code.OpAdd:
  103. result = leftValue + rightValue
  104. case code.OpSub:
  105. result = leftValue - rightValue
  106. case code.OpMul:
  107. result = leftValue * rightValue
  108. case code.OpDiv:
  109. result = leftValue / rightValue
  110. default:
  111. return fmt.Errorf("unknown integer operator: %d", op)
  112. }
  113. return vm.push(&object.Integer{Value: result})
  114. }