diff options
| author | Mel <einebeere@gmail.com> | 2022-07-26 02:37:38 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-07-26 02:37:38 +0200 |
| commit | 41490ae52e3b1ff20980c5e0837d257043b3ca92 (patch) | |
| tree | 9d2574dbcdc6f82a9b89cfcf64f7e25634484a5a /pkg/lang/compiler/compiler.go | |
| parent | b6fa4bc82398b09307f2e6b75e27422d1d1ecb33 (diff) | |
| download | jinx-41490ae52e3b1ff20980c5e0837d257043b3ca92.tar.zst jinx-41490ae52e3b1ff20980c5e0837d257043b3ca92.zip | |
Store functions in locals and remove hoisting
Diffstat (limited to 'pkg/lang/compiler/compiler.go')
| -rw-r--r-- | pkg/lang/compiler/compiler.go | 57 |
1 files changed, 16 insertions, 41 deletions
diff --git a/pkg/lang/compiler/compiler.go b/pkg/lang/compiler/compiler.go index e446dd6..0424862 100644 --- a/pkg/lang/compiler/compiler.go +++ b/pkg/lang/compiler/compiler.go @@ -24,15 +24,6 @@ func New(ast ast.Program) *Compiler { } func (comp *Compiler) Compile() (code.Code, error) { - // Pre-declare all top-level functions - for _, stmt := range comp.ast.Stmts { - if stmt.Kind == ast.StmtKindFnDecl { - if err := comp.preDeclareFunction(stmt.Value.(ast.StmtFnDecl)); err != nil { - return code.Code{}, err - } - } - } - target := code.NewBuilder() for _, stmt := range comp.ast.Stmts { @@ -50,14 +41,6 @@ func (comp *Compiler) Compile() (code.Code, error) { return target.Build() } -func (comp *Compiler) preDeclareFunction(fnDeclStmt ast.StmtFnDecl) error { - if _, ok := comp.scopes.DeclareFunction(fnDeclStmt.Name.Value, uint(len(fnDeclStmt.Args))); !ok { - return fmt.Errorf("function %s already declared", fnDeclStmt.Name.Value) - } - - return nil -} - func (comp *Compiler) compileStmt(t *code.Builder, stmt ast.Stmt) error { var err error switch stmt.Kind { @@ -106,23 +89,13 @@ func (comp *Compiler) compileStmt(t *code.Builder, stmt ast.Stmt) error { } func (comp *Compiler) compileFnDeclStmt(t *code.Builder, fnDeclStmt ast.StmtFnDecl) error { - marker, ok := comp.scopes.DeclareFunction(fnDeclStmt.Name.Value, uint(len(fnDeclStmt.Args))) + _, ok := comp.scopes.Declare(fnDeclStmt.Name.Value) if !ok { - // If we are in the root scope, the function was simply predeclared :) - if comp.scopes.IsRootScope() { - symbolID, ok := comp.scopes.Lookup(fnDeclStmt.Name.Value) - if !ok { - panic("function said it was declared but apparently it was lying") - } - - symbol := comp.scopes.GetFunction(symbolID) - - marker = symbol.Data().Marker() - } else { - return fmt.Errorf("function %s already declared", fnDeclStmt.Name.Value) - } + return fmt.Errorf("function %s already declared", fnDeclStmt.Name.Value) } + marker := comp.scopes.CreateFunctionSubUnit(fnDeclStmt.Name.Value) + functionTarget := code.NewBuilder() functionTarget.PutMarker(marker) @@ -144,6 +117,18 @@ func (comp *Compiler) compileFnDeclStmt(t *code.Builder, fnDeclStmt ast.StmtFnDe comp.funcs = append(comp.funcs, &functionTarget) + // Put the function value on the stack + + t.AppendOp(code.OpPushFunction) + t.AppendMarkerReference(marker) + + if len(fnDeclStmt.Args) != 0 { + t.AppendOp(code.OpSetArgCount) + t.AppendInt(int64(len(fnDeclStmt.Args))) + } + + // TODO: Attach the function environment + return nil } @@ -654,16 +639,6 @@ func (comp *Compiler) compileIdentExpr(t *code.Builder, expr ast.ExprIdent) erro t.AppendOp(code.OpGetLocal) t.AppendInt(int64(symbol.Data().LocalIndex())) - case scope.SymbolKindFunction: - symbol := comp.scopes.GetFunction(symbolId) - - t.AppendOp(code.OpPushFunction) - t.AppendMarkerReference(symbol.Data().Marker()) - - if symbol.Data().Args() != 0 { - t.AppendOp(code.OpSetArgCount) - t.AppendInt(int64(symbol.Data().Args())) - } default: panic(fmt.Errorf("unknown symbol kind: %v", symbolId.SymbolKind())) } |
