compiler.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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.lastInstructionIs(code.OpPop) {
  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.lastInstructionIs(code.OpPop) {
  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. if symbol.Scope == GlobalScope {
  159. c.emit(code.OpSetGlobal, symbol.Index)
  160. } else {
  161. c.emit(code.OpSetLocal, symbol.Index)
  162. }
  163. case *ast.Identifier:
  164. symbol, ok := c.symbolTable.Resolve(node.Value)
  165. if !ok {
  166. return fmt.Errorf("undefined variable %s", node.Value)
  167. }
  168. if symbol.Scope == GlobalScope {
  169. c.emit(code.OpGetGlobal, symbol.Index)
  170. } else {
  171. c.emit(code.OpGetLocal, symbol.Index)
  172. }
  173. case *ast.Boolean:
  174. if node.Value {
  175. c.emit(code.OpTrue)
  176. } else {
  177. c.emit(code.OpFalse)
  178. }
  179. case *ast.IntegerLiteral:
  180. integer := &object.Integer{Value: node.Value}
  181. c.emit(code.OpConstant, c.addConstant(integer))
  182. case *ast.StringLiteral:
  183. str := &object.String{Value: node.Value}
  184. c.emit(code.OpConstant, c.addConstant(str))
  185. case *ast.ArrayLiteral:
  186. for _, el := range node.Element {
  187. err := c.Compile(el)
  188. if err != nil {
  189. return err
  190. }
  191. }
  192. c.emit(code.OpArray, len(node.Element))
  193. case *ast.HashLiteral:
  194. var keys []ast.Expression
  195. for k := range node.Pairs {
  196. keys = append(keys, k)
  197. }
  198. sort.Slice(keys, func(i, j int) bool {
  199. return keys[i].String() < keys[j].String()
  200. })
  201. for _, k := range keys {
  202. err := c.Compile(k)
  203. if err != nil {
  204. return err
  205. }
  206. err = c.Compile(node.Pairs[k])
  207. if err != nil {
  208. return err
  209. }
  210. }
  211. c.emit(code.OpHash, len(node.Pairs)*2)
  212. case *ast.IndexExpression:
  213. err := c.Compile(node.Left)
  214. if err != nil {
  215. return err
  216. }
  217. err = c.Compile(node.Index)
  218. if err != nil {
  219. return err
  220. }
  221. c.emit(code.OpIndex)
  222. case *ast.ReturnStatement:
  223. err := c.Compile(node.ReturnValue)
  224. if err != nil {
  225. return err
  226. }
  227. c.emit(code.OpReturnValue)
  228. case *ast.FunctionLiteral:
  229. c.enterScope()
  230. err := c.Compile(node.Body)
  231. if err != nil {
  232. return err
  233. }
  234. if c.lastInstructionIs(code.OpPop) {
  235. c.replaceLastPopWithReturn()
  236. }
  237. if !c.lastInstructionIs(code.OpReturnValue) {
  238. c.emit(code.OpReturn)
  239. }
  240. instructions := c.leaveScope()
  241. compiledFn := &object.CompileFunction{Instructions: instructions}
  242. c.emit(code.OpConstant, c.addConstant(compiledFn))
  243. case *ast.CallExpression:
  244. err := c.Compile(node.Function)
  245. if err != nil {
  246. return err
  247. }
  248. c.emit(code.OpCall)
  249. }
  250. return nil
  251. }
  252. func (c *Compiler) addConstant(obj object.Object) int {
  253. c.constants = append(c.constants, obj)
  254. return len(c.constants) - 1
  255. }
  256. func (c *Compiler) addInstruction(ins []byte) int {
  257. posNewInstruction := len(c.currentInstructions())
  258. updatedInstructions := append(c.currentInstructions(), ins...)
  259. c.scopes[c.scopeIndex].instructions = updatedInstructions
  260. return posNewInstruction
  261. }
  262. // emit generate an instruction and add it to the results,
  263. // either by printing it, writing it to a file or
  264. // by adding it to a collection in memory
  265. //
  266. // op code.Opcode
  267. //
  268. // operands [operand]int
  269. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  270. ins := code.Make(op, operands...)
  271. pos := c.addInstruction(ins)
  272. c.setLastInstruction(op, pos)
  273. return pos
  274. }
  275. func (c *Compiler) setLastInstruction(op code.Opcode, pos int) {
  276. previous := c.scopes[c.scopeIndex].lastInstruction
  277. last := EmittedInstruction{Opcode: op, Position: pos}
  278. c.scopes[c.scopeIndex].previousInstruction = previous
  279. c.scopes[c.scopeIndex].lastInstruction = last
  280. }
  281. func (c *Compiler) lastInstructionIsPop() bool {
  282. return c.scopes[c.scopeIndex].lastInstruction.Opcode == code.OpPop
  283. }
  284. func (c *Compiler) lastInstructionIs(op code.Opcode) bool {
  285. if len(c.currentInstructions()) == 0 {
  286. return false
  287. }
  288. return c.scopes[c.scopeIndex].lastInstruction.Opcode == op
  289. }
  290. func (c *Compiler) removeLastPop() {
  291. last := c.scopes[c.scopeIndex].lastInstruction
  292. previous := c.scopes[c.scopeIndex].previousInstruction
  293. oldIns := c.currentInstructions()
  294. newIns := oldIns[:last.Position]
  295. c.scopes[c.scopeIndex].instructions = newIns
  296. c.scopes[c.scopeIndex].lastInstruction = previous
  297. }
  298. func (c *Compiler) replaceInstruction(pos int, newInstruction []byte) {
  299. ins := c.currentInstructions()
  300. for i := 0; i < len(newInstruction); i++ {
  301. ins[pos+i] = newInstruction[i]
  302. }
  303. }
  304. func (c *Compiler) changOperand(opPos int, operand int) {
  305. op := code.Opcode(c.currentInstructions()[opPos])
  306. newInstruction := code.Make(op, operand)
  307. c.replaceInstruction(opPos, newInstruction)
  308. }
  309. func (c *Compiler) currentInstructions() code.Instructions {
  310. return c.scopes[c.scopeIndex].instructions
  311. }
  312. func (c *Compiler) enterScope() {
  313. scope := CompilationScope{
  314. instructions: code.Instructions{},
  315. lastInstruction: EmittedInstruction{},
  316. previousInstruction: EmittedInstruction{},
  317. }
  318. c.scopes = append(c.scopes, scope)
  319. c.scopeIndex++
  320. c.symbolTable = NewEnclosedSymbolTable(c.symbolTable)
  321. }
  322. func (c *Compiler) leaveScope() code.Instructions {
  323. ins := c.currentInstructions()
  324. c.scopes = c.scopes[:len(c.scopes)-1]
  325. c.scopeIndex--
  326. c.symbolTable = c.symbolTable.Outer
  327. return ins
  328. }
  329. func (c *Compiler) replaceLastPopWithReturn() {
  330. lastPop := c.scopes[c.scopeIndex].lastInstruction.Position
  331. c.replaceInstruction(lastPop, code.Make(code.OpReturnValue))
  332. c.scopes[c.scopeIndex].lastInstruction.Opcode = code.OpReturnValue
  333. }
  334. func (c *Compiler) ByteCode() *ByteCode {
  335. return &ByteCode{
  336. Instructions: c.currentInstructions(),
  337. Constants: c.constants,
  338. }
  339. }
  340. type ByteCode struct {
  341. Instructions code.Instructions
  342. Constants []object.Object
  343. }