debug for compilation flows
This commit is contained in:
@@ -2,10 +2,12 @@ package compiler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"monkey/ast"
|
"monkey/ast"
|
||||||
"monkey/code"
|
"monkey/code"
|
||||||
"monkey/object"
|
"monkey/object"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EmittedInstruction struct {
|
type EmittedInstruction struct {
|
||||||
@@ -20,6 +22,9 @@ type CompilationScope struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Compiler struct {
|
type Compiler struct {
|
||||||
|
Debug bool
|
||||||
|
|
||||||
|
l int
|
||||||
constants []object.Object
|
constants []object.Object
|
||||||
|
|
||||||
symbolTable *SymbolTable
|
symbolTable *SymbolTable
|
||||||
@@ -61,8 +66,16 @@ func NewWithState(s *SymbolTable, constants []object.Object) *Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Compiler) Compile(node ast.Node) error {
|
func (c *Compiler) Compile(node ast.Node) error {
|
||||||
|
if c.Debug {
|
||||||
|
log.Printf(
|
||||||
|
"%s Compiling %T: %s\n",
|
||||||
|
strings.Repeat(" ", c.l), node, node.String(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
switch node := node.(type) {
|
switch node := node.(type) {
|
||||||
case *ast.Program:
|
case *ast.Program:
|
||||||
|
c.l++
|
||||||
for _, s := range node.Statements {
|
for _, s := range node.Statements {
|
||||||
err := c.Compile(s)
|
err := c.Compile(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -71,7 +84,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *ast.ExpressionStatement:
|
case *ast.ExpressionStatement:
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Expression)
|
err := c.Compile(node.Expression)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -82,12 +97,16 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
|
|
||||||
case *ast.InfixExpression:
|
case *ast.InfixExpression:
|
||||||
if node.Operator == "<" || node.Operator == "<=" {
|
if node.Operator == "<" || node.Operator == "<=" {
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Right)
|
err := c.Compile(node.Right)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err = c.Compile(node.Left)
|
err = c.Compile(node.Left)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -99,12 +118,16 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Left)
|
err := c.Compile(node.Left)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err = c.Compile(node.Right)
|
err = c.Compile(node.Right)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -142,7 +165,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *ast.PrefixExpression:
|
case *ast.PrefixExpression:
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Right)
|
err := c.Compile(node.Right)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -160,7 +185,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
if c.lastInstructionIs(code.OpPop) {
|
if c.lastInstructionIs(code.OpPop) {
|
||||||
c.removeLastPop()
|
c.removeLastPop()
|
||||||
}
|
}
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Condition)
|
err := c.Compile(node.Condition)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -168,7 +195,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
// Emit an `OpJumpNotTruthy` with a bogus value
|
// Emit an `OpJumpNotTruthy` with a bogus value
|
||||||
jumpNotTruthyPos := c.emit(code.OpJumpNotTruthy, 9999)
|
jumpNotTruthyPos := c.emit(code.OpJumpNotTruthy, 9999)
|
||||||
|
|
||||||
|
c.l++
|
||||||
err = c.Compile(node.Consequence)
|
err = c.Compile(node.Consequence)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -186,7 +215,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
if node.Alternative == nil {
|
if node.Alternative == nil {
|
||||||
c.emit(code.OpNull)
|
c.emit(code.OpNull)
|
||||||
} else {
|
} else {
|
||||||
err = c.Compile(node.Alternative)
|
c.l++
|
||||||
|
err := c.Compile(node.Alternative)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -200,12 +231,14 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
c.changeOperand(jumpPos, afterAlternativePos)
|
c.changeOperand(jumpPos, afterAlternativePos)
|
||||||
|
|
||||||
case *ast.BlockStatement:
|
case *ast.BlockStatement:
|
||||||
|
c.l++
|
||||||
for _, s := range node.Statements {
|
for _, s := range node.Statements {
|
||||||
err := c.Compile(s)
|
err := c.Compile(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c.l--
|
||||||
|
|
||||||
case *ast.AssignmentStatement:
|
case *ast.AssignmentStatement:
|
||||||
symbol, ok := c.symbolTable.Resolve(node.Name.Value)
|
symbol, ok := c.symbolTable.Resolve(node.Name.Value)
|
||||||
@@ -213,7 +246,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
return fmt.Errorf("undefined variable %s", node.Value)
|
return fmt.Errorf("undefined variable %s", node.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Value)
|
err := c.Compile(node.Value)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -230,7 +265,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
symbol = c.symbolTable.Define(node.Name.Value)
|
symbol = c.symbolTable.Define(node.Name.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Value)
|
err := c.Compile(node.Value)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -255,7 +292,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
|
|
||||||
case *ast.ArrayLiteral:
|
case *ast.ArrayLiteral:
|
||||||
for _, el := range node.Elements {
|
for _, el := range node.Elements {
|
||||||
|
c.l++
|
||||||
err := c.Compile(el)
|
err := c.Compile(el)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -273,11 +312,15 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
|
c.l++
|
||||||
err := c.Compile(k)
|
err := c.Compile(k)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
c.l++
|
||||||
err = c.Compile(node.Pairs[k])
|
err = c.Compile(node.Pairs[k])
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -286,12 +329,16 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
c.emit(code.OpHash, len(node.Pairs)*2)
|
c.emit(code.OpHash, len(node.Pairs)*2)
|
||||||
|
|
||||||
case *ast.IndexExpression:
|
case *ast.IndexExpression:
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Left)
|
err := c.Compile(node.Left)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err = c.Compile(node.Index)
|
err = c.Compile(node.Index)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -309,7 +356,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
c.symbolTable.Define(p.Value)
|
c.symbolTable.Define(p.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Body)
|
err := c.Compile(node.Body)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -340,7 +389,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
c.emit(code.OpClosure, fnIndex, len(freeSymbols))
|
c.emit(code.OpClosure, fnIndex, len(freeSymbols))
|
||||||
|
|
||||||
case *ast.ReturnStatement:
|
case *ast.ReturnStatement:
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.ReturnValue)
|
err := c.Compile(node.ReturnValue)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -348,7 +399,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
c.emit(code.OpReturn)
|
c.emit(code.OpReturn)
|
||||||
|
|
||||||
case *ast.CallExpression:
|
case *ast.CallExpression:
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Function)
|
err := c.Compile(node.Function)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -365,7 +418,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
case *ast.WhileExpression:
|
case *ast.WhileExpression:
|
||||||
jumpConditionPos := len(c.currentInstructions())
|
jumpConditionPos := len(c.currentInstructions())
|
||||||
|
|
||||||
|
c.l++
|
||||||
err := c.Compile(node.Condition)
|
err := c.Compile(node.Condition)
|
||||||
|
c.l--
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -373,10 +428,12 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
// Emit an `OpJump`with a bogus value
|
// Emit an `OpJump`with a bogus value
|
||||||
jumpIfFalsePos := c.emit(code.OpJumpNotTruthy, 0xFFFF)
|
jumpIfFalsePos := c.emit(code.OpJumpNotTruthy, 0xFFFF)
|
||||||
|
|
||||||
|
c.l++
|
||||||
err = c.Compile(node.Consequence)
|
err = c.Compile(node.Consequence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
c.l--
|
||||||
|
|
||||||
c.emit(code.OpJump, jumpConditionPos)
|
c.emit(code.OpJump, jumpConditionPos)
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ func (r *REPL) Exec(f io.Reader) (state *VMState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := compiler.NewWithState(state.symbols, state.constants)
|
c := compiler.NewWithState(state.symbols, state.constants)
|
||||||
|
c.Debug = r.opts.Debug
|
||||||
err = c.Compile(program)
|
err = c.Compile(program)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Woops! Compilation failed:\n %s\n", err)
|
fmt.Fprintf(os.Stderr, "Woops! Compilation failed:\n %s\n", err)
|
||||||
@@ -197,6 +198,7 @@ func (r *REPL) StartExecLoop(in io.Reader, out io.Writer, state *VMState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := compiler.NewWithState(state.symbols, state.constants)
|
c := compiler.NewWithState(state.symbols, state.constants)
|
||||||
|
c.Debug = r.opts.Debug
|
||||||
err := c.Compile(program)
|
err := c.Compile(program)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Woops! Compilation failed:\n %s\n", err)
|
fmt.Fprintf(os.Stderr, "Woops! Compilation failed:\n %s\n", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user