compiler.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 EmittedInstruction struct {
  13. Opcode code.Opcode
  14. Position int
  15. }
  16. type Compiler struct {
  17. instructions code.Instructions // hold the generated bytecode
  18. constants []object.Object // slice that serves as our constant pool
  19. lastInstruction EmittedInstruction
  20. previousInstruction EmittedInstruction
  21. symbolTable *SymbolTable
  22. }
  23. func New() *Compiler {
  24. return &Compiler{
  25. instructions: code.Instructions{},
  26. constants: []object.Object{},
  27. lastInstruction: EmittedInstruction{},
  28. previousInstruction: EmittedInstruction{},
  29. symbolTable: NewSymbolTable(),
  30. }
  31. }
  32. func NewWithState(s *SymbolTable, constants []object.Object) *Compiler {
  33. compiler := New()
  34. compiler.symbolTable = s
  35. compiler.constants = constants
  36. return compiler
  37. }
  38. func (c *Compiler) Compile(node ast.Node) error {
  39. switch node := node.(type) {
  40. case *ast.Program:
  41. for _, s := range node.Statements {
  42. err := c.Compile(s)
  43. if err != nil {
  44. return err
  45. }
  46. }
  47. case *ast.ExpressionStatement:
  48. err := c.Compile(node.Expression)
  49. if err != nil {
  50. return err
  51. }
  52. c.emit(code.OpPop)
  53. case *ast.InfixExpression:
  54. if node.Operator == "<" {
  55. err := c.Compile(node.Right)
  56. if err != nil {
  57. return err
  58. }
  59. err = c.Compile(node.Left)
  60. if err != nil {
  61. return err
  62. }
  63. c.emit(code.OpGreaterThan)
  64. return nil
  65. }
  66. err := c.Compile(node.Left)
  67. if err != nil {
  68. return err
  69. }
  70. err = c.Compile(node.Right)
  71. if err != nil {
  72. return err
  73. }
  74. switch node.Operator {
  75. case "+":
  76. c.emit(code.OpAdd)
  77. case "-":
  78. c.emit(code.OpSub)
  79. case "*":
  80. c.emit(code.OpMul)
  81. case "/":
  82. c.emit(code.OpDiv)
  83. case ">":
  84. c.emit(code.OpGreaterThan)
  85. case "==":
  86. c.emit(code.OpEqual)
  87. case "!=":
  88. c.emit(code.OpNotEqual)
  89. default:
  90. return fmt.Errorf("unknown operator %s", node.Operator)
  91. }
  92. case *ast.PrefixExpression:
  93. err := c.Compile(node.Right)
  94. if err != nil {
  95. return err
  96. }
  97. switch node.Operator {
  98. case "!":
  99. c.emit(code.OpBang)
  100. case "-":
  101. c.emit(code.OpMinus)
  102. default:
  103. return fmt.Errorf("unknown operator %s", node.Operator)
  104. }
  105. case *ast.IfExpression:
  106. err := c.Compile(node.Condition)
  107. if err != nil {
  108. return err
  109. }
  110. // Emit an 'OpJumNotTruthy` with a bogus value
  111. jumpNotTruthyPos := c.emit(code.OpJumpNotTruthy, 9999)
  112. err = c.Compile(node.Consequence)
  113. if err != nil {
  114. return err
  115. }
  116. if c.lastInstructionIsPop() {
  117. c.removeLastPop()
  118. }
  119. // Emit an `OpJump` with a bogus value
  120. jumpPos := c.emit(code.OpJump, 9999)
  121. afterConsequencePos := len(c.instructions)
  122. c.changOperand(jumpNotTruthyPos, afterConsequencePos)
  123. if node.Alternative == nil {
  124. c.emit(code.OpNull)
  125. } else {
  126. err := c.Compile(node.Alternative)
  127. if err != nil {
  128. return err
  129. }
  130. if c.lastInstructionIsPop() {
  131. c.removeLastPop()
  132. }
  133. }
  134. afterAlternativePos := len(c.instructions)
  135. c.changOperand(jumpPos, afterAlternativePos)
  136. case *ast.BlockStatement:
  137. for _, s := range node.Statements {
  138. err := c.Compile(s)
  139. if err != nil {
  140. return err
  141. }
  142. }
  143. case *ast.LetStatement:
  144. err := c.Compile(node.Value)
  145. if err != nil {
  146. return err
  147. }
  148. symbol := c.symbolTable.Define(node.Name.Value)
  149. c.emit(code.OpSetGlobal, symbol.Index)
  150. case *ast.Identifier:
  151. symbol, ok := c.symbolTable.Resolve(node.Value)
  152. if !ok {
  153. return fmt.Errorf("undefined variable %s", node.Value)
  154. }
  155. c.emit(code.OpGetGlobal, symbol.Index)
  156. case *ast.Boolean:
  157. if node.Value {
  158. c.emit(code.OpTrue)
  159. } else {
  160. c.emit(code.OpFalse)
  161. }
  162. case *ast.IntegerLiteral:
  163. integer := &object.Integer{Value: node.Value}
  164. c.emit(code.OpConstant, c.addConstant(integer))
  165. }
  166. return nil
  167. }
  168. func (c *Compiler) addConstant(obj object.Object) int {
  169. c.constants = append(c.constants, obj)
  170. return len(c.constants) - 1
  171. }
  172. func (c *Compiler) addInstruction(ins []byte) int {
  173. posNewInstruction := len(c.instructions)
  174. c.instructions = append(c.instructions, ins...)
  175. return posNewInstruction
  176. }
  177. // emit generate an instruction and add it to the results,
  178. // either by printing it, writing it to a file or
  179. // by adding it to a collection in memory
  180. //
  181. // op code.Opcode
  182. //
  183. // operands [operand]int
  184. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  185. ins := code.Make(op, operands...)
  186. pos := c.addInstruction(ins)
  187. c.setLastInstruction(op, pos)
  188. return pos
  189. }
  190. func (c *Compiler) setLastInstruction(op code.Opcode, pos int) {
  191. previous := c.lastInstruction
  192. last := EmittedInstruction{Opcode: op, Position: pos}
  193. c.previousInstruction = previous
  194. c.lastInstruction = last
  195. }
  196. func (c *Compiler) lastInstructionIsPop() bool {
  197. return c.lastInstruction.Opcode == code.OpPop
  198. }
  199. func (c *Compiler) removeLastPop() {
  200. c.instructions = c.instructions[:c.lastInstruction.Position]
  201. c.lastInstruction = c.previousInstruction
  202. }
  203. func (c *Compiler) replaceInstruction(pos int, newInstruction []byte) {
  204. for i := 0; i < len(newInstruction); i++ {
  205. c.instructions[pos+i] = newInstruction[i]
  206. }
  207. }
  208. func (c *Compiler) changOperand(opPos int, operand int) {
  209. op := code.Opcode(c.instructions[opPos])
  210. newInstruction := code.Make(op, operand)
  211. c.replaceInstruction(opPos, newInstruction)
  212. }
  213. func (c *Compiler) ByteCode() *ByteCode {
  214. return &ByteCode{
  215. Instructions: c.instructions,
  216. Constants: c.constants,
  217. }
  218. }
  219. type ByteCode struct {
  220. Instructions code.Instructions
  221. Constants []object.Object
  222. }