compiler.go 2.1 KB

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