compiler.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. err := c.Compile(node.Left)
  39. if err != nil {
  40. return err
  41. }
  42. err = c.Compile(node.Right)
  43. if err != nil {
  44. return err
  45. }
  46. switch node.Operator {
  47. case "+":
  48. c.emit(code.OpAdd)
  49. default:
  50. return fmt.Errorf("unknown operator %s", node.Operator)
  51. }
  52. case *ast.IntegerLiteral:
  53. integer := &object.Integer{Value: node.Value}
  54. c.emit(code.OpConstant, c.addConstant(integer))
  55. }
  56. return nil
  57. }
  58. func (c *Compiler) addConstant(obj object.Object) int {
  59. c.constants = append(c.constants, obj)
  60. return len(c.constants) - 1
  61. }
  62. func (c *Compiler) addInstruction(ins []byte) int {
  63. posNewInstruction := len(c.instructions)
  64. c.instructions = append(c.instructions, ins...)
  65. return posNewInstruction
  66. }
  67. // emit generate an instruction and add it to the results,
  68. // either by printing it, writing it to a file or
  69. // by adding it to a collection in memory
  70. //
  71. // op code.Opcode
  72. //
  73. // operands [operand]int
  74. func (c *Compiler) emit(op code.Opcode, operands ...int) int {
  75. ins := code.Make(op, operands...)
  76. pos := c.addInstruction(ins)
  77. return pos
  78. }
  79. func (c *Compiler) ByteCode() *ByteCode {
  80. return &ByteCode{
  81. Instructions: c.instructions,
  82. Constants: c.constants,
  83. }
  84. }
  85. type ByteCode struct {
  86. Instructions code.Instructions
  87. Constants []object.Object
  88. }