compiler.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. if node.Operator == "<" {
  39. err := c.Compile(node.Right)
  40. if err != nil {
  41. return err
  42. }
  43. err = c.Compile(node.Left)
  44. if err != nil {
  45. return err
  46. }
  47. c.emit(code.OpGreaterThan)
  48. return nil
  49. }
  50. err := c.Compile(node.Left)
  51. if err != nil {
  52. return err
  53. }
  54. err = c.Compile(node.Right)
  55. if err != nil {
  56. return err
  57. }
  58. switch node.Operator {
  59. case "+":
  60. c.emit(code.OpAdd)
  61. case "-":
  62. c.emit(code.OpSub)
  63. case "*":
  64. c.emit(code.OpMul)
  65. case "/":
  66. c.emit(code.OpDiv)
  67. case ">":
  68. c.emit(code.OpGreaterThan)
  69. case "==":
  70. c.emit(code.OpEqual)
  71. case "!=":
  72. c.emit(code.OpNotEqual)
  73. default:
  74. return fmt.Errorf("unknown operator %s", node.Operator)
  75. }
  76. case *ast.PrefixExpression:
  77. err := c.Compile(node.Right)
  78. if err != nil {
  79. return err
  80. }
  81. switch node.Operator {
  82. case "!":
  83. c.emit(code.OpBang)
  84. case "-":
  85. c.emit(code.OpMinus)
  86. default:
  87. return fmt.Errorf("unknown operator %s", node.Operator)
  88. }
  89. case *ast.Boolean:
  90. if node.Value {
  91. c.emit(code.OpTrue)
  92. } else {
  93. c.emit(code.OpFalse)
  94. }
  95. case *ast.IntegerLiteral:
  96. integer := &object.Integer{Value: node.Value}
  97. c.emit(code.OpConstant, c.addConstant(integer))
  98. }
  99. return nil
  100. }
  101. func (c *Compiler) addConstant(obj object.Object) int {
  102. c.constants = append(c.constants, obj)
  103. return len(c.constants) - 1
  104. }
  105. func (c *Compiler) addInstruction(ins []byte) int {
  106. posNewInstruction := len(c.instructions)
  107. c.instructions = append(c.instructions, ins...)
  108. return posNewInstruction
  109. }
  110. // emit generate an instruction and add it to the results,
  111. // either by printing it, writing it to a file or
  112. // by adding it to a collection in memory
  113. //
  114. // op code.Opcode
  115. //
  116. // operands [operand]int
  117. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  118. ins := code.Make(op, operands...)
  119. pos := c.addInstruction(ins)
  120. return pos
  121. }
  122. func (c *Compiler) ByteCode() *ByteCode {
  123. return &ByteCode{
  124. Instructions: c.instructions,
  125. Constants: c.constants,
  126. }
  127. }
  128. type ByteCode struct {
  129. Instructions code.Instructions
  130. Constants []object.Object
  131. }