compiler.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. "sort"
  12. )
  13. type EmittedInstruction struct {
  14. Opcode code.Opcode
  15. Position int
  16. }
  17. type Compiler struct {
  18. constants []object.Object // slice that serves as our constant pool
  19. symbolTable *SymbolTable
  20. scopes []CompilationScope
  21. scopeIndex int
  22. }
  23. type CompilationScope struct {
  24. instructions code.Instructions // hold the generated bytecode
  25. lastInstruction EmittedInstruction
  26. previousInstruction EmittedInstruction
  27. }
  28. func New() *Compiler {
  29. mainScope := CompilationScope{
  30. instructions: code.Instructions{},
  31. lastInstruction: EmittedInstruction{},
  32. previousInstruction: EmittedInstruction{},
  33. }
  34. return &Compiler{
  35. constants: []object.Object{},
  36. symbolTable: NewSymbolTable(),
  37. scopes: []CompilationScope{mainScope},
  38. scopeIndex: 0,
  39. }
  40. }
  41. func NewWithState(s *SymbolTable, constants []object.Object) *Compiler {
  42. compiler := New()
  43. compiler.symbolTable = s
  44. compiler.constants = constants
  45. return compiler
  46. }
  47. func (c *Compiler) Compile(node ast.Node) error {
  48. switch node := node.(type) {
  49. case *ast.Program:
  50. for _, s := range node.Statements {
  51. err := c.Compile(s)
  52. if err != nil {
  53. return err
  54. }
  55. }
  56. case *ast.ExpressionStatement:
  57. err := c.Compile(node.Expression)
  58. if err != nil {
  59. return err
  60. }
  61. c.emit(code.OpPop)
  62. case *ast.InfixExpression:
  63. if node.Operator == "<" {
  64. err := c.Compile(node.Right)
  65. if err != nil {
  66. return err
  67. }
  68. err = c.Compile(node.Left)
  69. if err != nil {
  70. return err
  71. }
  72. c.emit(code.OpGreaterThan)
  73. return nil
  74. }
  75. err := c.Compile(node.Left)
  76. if err != nil {
  77. return err
  78. }
  79. err = c.Compile(node.Right)
  80. if err != nil {
  81. return err
  82. }
  83. switch node.Operator {
  84. case "+":
  85. c.emit(code.OpAdd)
  86. case "-":
  87. c.emit(code.OpSub)
  88. case "*":
  89. c.emit(code.OpMul)
  90. case "/":
  91. c.emit(code.OpDiv)
  92. case ">":
  93. c.emit(code.OpGreaterThan)
  94. case "==":
  95. c.emit(code.OpEqual)
  96. case "!=":
  97. c.emit(code.OpNotEqual)
  98. default:
  99. return fmt.Errorf("unknown operator %s", node.Operator)
  100. }
  101. case *ast.PrefixExpression:
  102. err := c.Compile(node.Right)
  103. if err != nil {
  104. return err
  105. }
  106. switch node.Operator {
  107. case "!":
  108. c.emit(code.OpBang)
  109. case "-":
  110. c.emit(code.OpMinus)
  111. default:
  112. return fmt.Errorf("unknown operator %s", node.Operator)
  113. }
  114. case *ast.IfExpression:
  115. err := c.Compile(node.Condition)
  116. if err != nil {
  117. return err
  118. }
  119. // Emit an 'OpJumNotTruthy` with a bogus value
  120. jumpNotTruthyPos := c.emit(code.OpJumpNotTruthy, 9999)
  121. err = c.Compile(node.Consequence)
  122. if err != nil {
  123. return err
  124. }
  125. if c.lastInstructionIsPop() {
  126. c.removeLastPop()
  127. }
  128. // Emit an `OpJump` with a bogus value
  129. jumpPos := c.emit(code.OpJump, 9999)
  130. afterConsequencePos := len(c.currentInstructions())
  131. c.changOperand(jumpNotTruthyPos, afterConsequencePos)
  132. if node.Alternative == nil {
  133. c.emit(code.OpNull)
  134. } else {
  135. err := c.Compile(node.Alternative)
  136. if err != nil {
  137. return err
  138. }
  139. if c.lastInstructionIsPop() {
  140. c.removeLastPop()
  141. }
  142. }
  143. afterAlternativePos := len(c.currentInstructions())
  144. c.changOperand(jumpPos, afterAlternativePos)
  145. case *ast.BlockStatement:
  146. for _, s := range node.Statements {
  147. err := c.Compile(s)
  148. if err != nil {
  149. return err
  150. }
  151. }
  152. case *ast.LetStatement:
  153. err := c.Compile(node.Value)
  154. if err != nil {
  155. return err
  156. }
  157. symbol := c.symbolTable.Define(node.Name.Value)
  158. c.emit(code.OpSetGlobal, symbol.Index)
  159. case *ast.Identifier:
  160. symbol, ok := c.symbolTable.Resolve(node.Value)
  161. if !ok {
  162. return fmt.Errorf("undefined variable %s", node.Value)
  163. }
  164. c.emit(code.OpGetGlobal, symbol.Index)
  165. case *ast.Boolean:
  166. if node.Value {
  167. c.emit(code.OpTrue)
  168. } else {
  169. c.emit(code.OpFalse)
  170. }
  171. case *ast.IntegerLiteral:
  172. integer := &object.Integer{Value: node.Value}
  173. c.emit(code.OpConstant, c.addConstant(integer))
  174. case *ast.StringLiteral:
  175. str := &object.String{Value: node.Value}
  176. c.emit(code.OpConstant, c.addConstant(str))
  177. case *ast.ArrayLiteral:
  178. for _, el := range node.Element {
  179. err := c.Compile(el)
  180. if err != nil {
  181. return err
  182. }
  183. }
  184. c.emit(code.OpArray, len(node.Element))
  185. case *ast.HashLiteral:
  186. var keys []ast.Expression
  187. for k := range node.Pairs {
  188. keys = append(keys, k)
  189. }
  190. sort.Slice(keys, func(i, j int) bool {
  191. return keys[i].String() < keys[j].String()
  192. })
  193. for _, k := range keys {
  194. err := c.Compile(k)
  195. if err != nil {
  196. return err
  197. }
  198. err = c.Compile(node.Pairs[k])
  199. if err != nil {
  200. return err
  201. }
  202. }
  203. c.emit(code.OpHash, len(node.Pairs)*2)
  204. case *ast.IndexExpression:
  205. err := c.Compile(node.Left)
  206. if err != nil {
  207. return err
  208. }
  209. err = c.Compile(node.Index)
  210. if err != nil {
  211. return err
  212. }
  213. c.emit(code.OpIndex)
  214. case *ast.ReturnStatement:
  215. err := c.Compile(node.ReturnValue)
  216. if err != nil {
  217. return err
  218. }
  219. c.emit(code.OpReturnValue)
  220. case *ast.FunctionLiteral:
  221. c.enterScope()
  222. err := c.Compile(node.Body)
  223. if err != nil {
  224. return err
  225. }
  226. instructions := c.leaveScope()
  227. compiledFn := &object.CompileFunction{Instructions: instructions}
  228. c.emit(code.OpConstant, c.addConstant(compiledFn))
  229. }
  230. return nil
  231. }
  232. func (c *Compiler) addConstant(obj object.Object) int {
  233. c.constants = append(c.constants, obj)
  234. return len(c.constants) - 1
  235. }
  236. func (c *Compiler) addInstruction(ins []byte) int {
  237. posNewInstruction := len(c.currentInstructions())
  238. updatedInstructions := append(c.currentInstructions(), ins...)
  239. c.scopes[c.scopeIndex].instructions = updatedInstructions
  240. return posNewInstruction
  241. }
  242. // emit generate an instruction and add it to the results,
  243. // either by printing it, writing it to a file or
  244. // by adding it to a collection in memory
  245. //
  246. // op code.Opcode
  247. //
  248. // operands [operand]int
  249. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  250. ins := code.Make(op, operands...)
  251. pos := c.addInstruction(ins)
  252. c.setLastInstruction(op, pos)
  253. return pos
  254. }
  255. func (c *Compiler) setLastInstruction(op code.Opcode, pos int) {
  256. previous := c.scopes[c.scopeIndex].lastInstruction
  257. last := EmittedInstruction{Opcode: op, Position: pos}
  258. c.scopes[c.scopeIndex].previousInstruction = previous
  259. c.scopes[c.scopeIndex].lastInstruction = last
  260. }
  261. func (c *Compiler) lastInstructionIsPop() bool {
  262. return c.scopes[c.scopeIndex].lastInstruction.Opcode == code.OpPop
  263. }
  264. func (c *Compiler) removeLastPop() {
  265. last := c.scopes[c.scopeIndex].lastInstruction
  266. previous := c.scopes[c.scopeIndex].previousInstruction
  267. oldIns := c.currentInstructions()
  268. newIns := oldIns[:last.Position]
  269. c.scopes[c.scopeIndex].instructions = newIns
  270. c.scopes[c.scopeIndex].lastInstruction = previous
  271. }
  272. func (c *Compiler) replaceInstruction(pos int, newInstruction []byte) {
  273. ins := c.currentInstructions()
  274. for i := 0; i < len(newInstruction); i++ {
  275. ins[pos+i] = newInstruction[i]
  276. }
  277. }
  278. func (c *Compiler) changOperand(opPos int, operand int) {
  279. op := code.Opcode(c.currentInstructions()[opPos])
  280. newInstruction := code.Make(op, operand)
  281. c.replaceInstruction(opPos, newInstruction)
  282. }
  283. func (c *Compiler) currentInstructions() code.Instructions {
  284. return c.scopes[c.scopeIndex].instructions
  285. }
  286. func (c *Compiler) enterScope() {
  287. scope := CompilationScope{
  288. instructions: code.Instructions{},
  289. lastInstruction: EmittedInstruction{},
  290. previousInstruction: EmittedInstruction{},
  291. }
  292. c.scopes = append(c.scopes, scope)
  293. c.scopeIndex++
  294. }
  295. func (c *Compiler) leaveScope() code.Instructions {
  296. ins := c.currentInstructions()
  297. c.scopes = c.scopes[:len(c.scopes)-1]
  298. c.scopeIndex--
  299. return ins
  300. }
  301. func (c *Compiler) ByteCode() *ByteCode {
  302. return &ByteCode{
  303. Instructions: c.currentInstructions(),
  304. Constants: c.constants,
  305. }
  306. }
  307. type ByteCode struct {
  308. Instructions code.Instructions
  309. Constants []object.Object
  310. }