vm.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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:
  46. right := vm.pop()
  47. left := vm.pop()
  48. leftValue := left.(*object.Integer).Value
  49. rightValue := right.(*object.Integer).Value
  50. result := leftValue + rightValue
  51. err := vm.push(&object.Integer{Value: result})
  52. if err != nil {
  53. return err
  54. }
  55. }
  56. }
  57. return nil
  58. }
  59. func (vm *VM) push(o object.Object) error {
  60. if vm.sp >= StackSize {
  61. return fmt.Errorf("stack overflow")
  62. }
  63. vm.stack[vm.sp] = o
  64. vm.sp++
  65. return nil
  66. }
  67. func (vm *VM) pop() object.Object {
  68. o := vm.stack[vm.sp-1]
  69. vm.sp--
  70. return o
  71. }