compiler.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  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. numLocals := c.symbolTable.numDefinitions
  241. instructions := c.leaveScope()
  242. compiledFn := &object.CompileFunction{
  243. Instructions: instructions,
  244. NumLocals: numLocals,
  245. }
  246. c.emit(code.OpConstant, c.addConstant(compiledFn))
  247. case *ast.CallExpression:
  248. err := c.Compile(node.Function)
  249. if err != nil {
  250. return err
  251. }
  252. c.emit(code.OpCall)
  253. }
  254. return nil
  255. }
  256. func (c *Compiler) addConstant(obj object.Object) int {
  257. c.constants = append(c.constants, obj)
  258. return len(c.constants) - 1
  259. }
  260. func (c *Compiler) addInstruction(ins []byte) int {
  261. posNewInstruction := len(c.currentInstructions())
  262. updatedInstructions := append(c.currentInstructions(), ins...)
  263. c.scopes[c.scopeIndex].instructions = updatedInstructions
  264. return posNewInstruction
  265. }
  266. // emit generate an instruction and add it to the results,
  267. // either by printing it, writing it to a file or
  268. // by adding it to a collection in memory
  269. //
  270. // op code.Opcode
  271. //
  272. // operands [operand]int
  273. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  274. ins := code.Make(op, operands...)
  275. pos := c.addInstruction(ins)
  276. c.setLastInstruction(op, pos)
  277. return pos
  278. }
  279. func (c *Compiler) setLastInstruction(op code.Opcode, pos int) {
  280. previous := c.scopes[c.scopeIndex].lastInstruction
  281. last := EmittedInstruction{Opcode: op, Position: pos}
  282. c.scopes[c.scopeIndex].previousInstruction = previous
  283. c.scopes[c.scopeIndex].lastInstruction = last
  284. }
  285. func (c *Compiler) lastInstructionIsPop() bool {
  286. return c.scopes[c.scopeIndex].lastInstruction.Opcode == code.OpPop
  287. }
  288. func (c *Compiler) lastInstructionIs(op code.Opcode) bool {
  289. if len(c.currentInstructions()) == 0 {
  290. return false
  291. }
  292. return c.scopes[c.scopeIndex].lastInstruction.Opcode == op
  293. }
  294. func (c *Compiler) removeLastPop() {
  295. last := c.scopes[c.scopeIndex].lastInstruction
  296. previous := c.scopes[c.scopeIndex].previousInstruction
  297. oldIns := c.currentInstructions()
  298. newIns := oldIns[:last.Position]
  299. c.scopes[c.scopeIndex].instructions = newIns
  300. c.scopes[c.scopeIndex].lastInstruction = previous
  301. }
  302. func (c *Compiler) replaceInstruction(pos int, newInstruction []byte) {
  303. ins := c.currentInstructions()
  304. for i := 0; i < len(newInstruction); i++ {
  305. ins[pos+i] = newInstruction[i]
  306. }
  307. }
  308. func (c *Compiler) changOperand(opPos int, operand int) {
  309. op := code.Opcode(c.currentInstructions()[opPos])
  310. newInstruction := code.Make(op, operand)
  311. c.replaceInstruction(opPos, newInstruction)
  312. }
  313. func (c *Compiler) currentInstructions() code.Instructions {
  314. return c.scopes[c.scopeIndex].instructions
  315. }
  316. func (c *Compiler) enterScope() {
  317. scope := CompilationScope{
  318. instructions: code.Instructions{},
  319. lastInstruction: EmittedInstruction{},
  320. previousInstruction: EmittedInstruction{},
  321. }
  322. c.scopes = append(c.scopes, scope)
  323. c.scopeIndex++
  324. c.symbolTable = NewEnclosedSymbolTable(c.symbolTable)
  325. }
  326. func (c *Compiler) leaveScope() code.Instructions {
  327. ins := c.currentInstructions()
  328. c.scopes = c.scopes[:len(c.scopes)-1]
  329. c.scopeIndex--
  330. c.symbolTable = c.symbolTable.Outer
  331. return ins
  332. }
  333. func (c *Compiler) replaceLastPopWithReturn() {
  334. lastPop := c.scopes[c.scopeIndex].lastInstruction.Position
  335. c.replaceInstruction(lastPop, code.Make(code.OpReturnValue))
  336. c.scopes[c.scopeIndex].lastInstruction.Opcode = code.OpReturnValue
  337. }
  338. func (c *Compiler) ByteCode() *ByteCode {
  339. return &ByteCode{
  340. Instructions: c.currentInstructions(),
  341. Constants: c.constants,
  342. }
  343. }
  344. type ByteCode struct {
  345. Instructions code.Instructions
  346. Constants []object.Object
  347. }