compiler.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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.Boolean:
  59. if node.Value {
  60. c.emit(code.OpTrue)
  61. } else {
  62. c.emit(code.OpFalse)
  63. }
  64. case *ast.IntegerLiteral:
  65. integer := &object.Integer{Value: node.Value}
  66. c.emit(code.OpConstant, c.addConstant(integer))
  67. }
  68. return nil
  69. }
  70. func (c *Compiler) addConstant(obj object.Object) int {
  71. c.constants = append(c.constants, obj)
  72. return len(c.constants) - 1
  73. }
  74. func (c *Compiler) addInstruction(ins []byte) int {
  75. posNewInstruction := len(c.instructions)
  76. c.instructions = append(c.instructions, ins...)
  77. return posNewInstruction
  78. }
  79. // emit generate an instruction and add it to the results,
  80. // either by printing it, writing it to a file or
  81. // by adding it to a collection in memory
  82. //
  83. // op code.Opcode
  84. //
  85. // operands [operand]int
  86. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  87. ins := code.Make(op, operands...)
  88. pos := c.addInstruction(ins)
  89. return pos
  90. }
  91. func (c *Compiler) ByteCode() *ByteCode {
  92. return &ByteCode{
  93. Instructions: c.instructions,
  94. Constants: c.constants,
  95. }
  96. }
  97. type ByteCode struct {
  98. Instructions code.Instructions
  99. Constants []object.Object
  100. }