compiler.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Author: simon
  2. // Author: ynwdlxm@163.com
  3. // Date: 2022/10/19 14:39
  4. // Desc: Compiler
  5. package compiler
  6. import (
  7. "fmt"
  8. "github/runnignwater/monkey/ast"
  9. "github/runnignwater/monkey/code"
  10. "github/runnignwater/monkey/object"
  11. )
  12. type Compiler struct {
  13. instructions code.Instructions // hold the generated bytecode
  14. constants []object.Object // slice that serves as our constant pool
  15. }
  16. func New() *Compiler {
  17. return &Compiler{
  18. instructions: code.Instructions{},
  19. constants: []object.Object{},
  20. }
  21. }
  22. func (c *Compiler) Compile(node ast.Node) error {
  23. switch node := node.(type) {
  24. case *ast.Program:
  25. for _, s := range node.Statements {
  26. err := c.Compile(s)
  27. if err != nil {
  28. return err
  29. }
  30. }
  31. case *ast.ExpressionStatement:
  32. err := c.Compile(node.Expression)
  33. if err != nil {
  34. return err
  35. }
  36. c.emit(code.OpPop)
  37. case *ast.InfixExpression:
  38. err := c.Compile(node.Left)
  39. if err != nil {
  40. return err
  41. }
  42. err = c.Compile(node.Right)
  43. if err != nil {
  44. return err
  45. }
  46. switch node.Operator {
  47. case "+":
  48. c.emit(code.OpAdd)
  49. case "-":
  50. c.emit(code.OpSub)
  51. case "*":
  52. c.emit(code.OpMul)
  53. case "/":
  54. c.emit(code.OpDiv)
  55. default:
  56. return fmt.Errorf("unknown operator %s", node.Operator)
  57. }
  58. case *ast.IntegerLiteral:
  59. integer := &object.Integer{Value: node.Value}
  60. c.emit(code.OpConstant, c.addConstant(integer))
  61. }
  62. return nil
  63. }
  64. func (c *Compiler) addConstant(obj object.Object) int {
  65. c.constants = append(c.constants, obj)
  66. return len(c.constants) - 1
  67. }
  68. func (c *Compiler) addInstruction(ins []byte) int {
  69. posNewInstruction := len(c.instructions)
  70. c.instructions = append(c.instructions, ins...)
  71. return posNewInstruction
  72. }
  73. // emit generate an instruction and add it to the results,
  74. // either by printing it, writing it to a file or
  75. // by adding it to a collection in memory
  76. //
  77. // op code.Opcode
  78. //
  79. // operands [operand]int
  80. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  81. ins := code.Make(op, operands...)
  82. pos := c.addInstruction(ins)
  83. return pos
  84. }
  85. func (c *Compiler) ByteCode() *ByteCode {
  86. return &ByteCode{
  87. Instructions: c.instructions,
  88. Constants: c.constants,
  89. }
  90. }
  91. type ByteCode struct {
  92. Instructions code.Instructions
  93. Constants []object.Object
  94. }