about summary refs log tree commit diff
path: root/pkg/lang
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang')
-rw-r--r--pkg/lang/compiler/compiler.go57
-rw-r--r--pkg/lang/compiler/compiler_test.go8
-rw-r--r--pkg/lang/compiler/scope/scope_chain.go37
-rw-r--r--pkg/lang/compiler/scope/scopes.go2
-rw-r--r--pkg/lang/compiler/scope/symbol.go21
5 files changed, 24 insertions, 101 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()))
 	}
diff --git a/pkg/lang/compiler/compiler_test.go b/pkg/lang/compiler/compiler_test.go
index b8a6264..07586a6 100644
--- a/pkg/lang/compiler/compiler_test.go
+++ b/pkg/lang/compiler/compiler_test.go
@@ -434,15 +434,17 @@ func TestForIn(t *testing.T) {
 
 func TestSimpleFunction(t *testing.T) {
 	src := `
-	var result = the_meaning_of_life()
-
 	fn the_meaning_of_life() {
 		return 42
 	}
+
+	var result = the_meaning_of_life()
 	`
 
 	expected := `
 	push_function @the_meaning_of_life
+
+	get_local 0
 	call 0
 	halt
 
@@ -466,6 +468,8 @@ func TestFunctionArgs(t *testing.T) {
 	expected := `
 	push_function @add
 	set_arg_count 2
+
+	get_local 0
 	push_int 4
 	push_int 5
 	call 2
diff --git a/pkg/lang/compiler/scope/scope_chain.go b/pkg/lang/compiler/scope/scope_chain.go
index d0108ee..f4b9f46 100644
--- a/pkg/lang/compiler/scope/scope_chain.go
+++ b/pkg/lang/compiler/scope/scope_chain.go
@@ -137,35 +137,6 @@ func (sc *ScopeChain) Declare(name string) (int, bool) {
 	return indexInScope, true
 }
 
-func (sc *ScopeChain) DeclareFunction(name string, args uint) (code.Marker, bool) {
-	if _, ok := sc.nameToSymbol[name]; ok {
-		return "", false
-	}
-
-	current := sc.Current()
-	index := len(current.functionSymbols)
-
-	symbolID := SymbolID{
-		symbolKind:   SymbolKindFunction,
-		scopeID:      sc.CurrentScopeID(),
-		indexInScope: index,
-	}
-
-	unitName := sc.CreateFunctionSubUnit(name)
-
-	current.functionSymbols = append(current.functionSymbols, Symbol[SymbolFunction]{
-		name: name,
-		data: SymbolFunction{
-			marker: unitName,
-			args:   args,
-		},
-	})
-
-	sc.nameToSymbol[name] = symbolID
-
-	return unitName, true
-}
-
 func (sc *ScopeChain) DeclareAnonymous() int {
 	current := sc.Current()
 	index := len(current.variableSymbols)
@@ -221,11 +192,3 @@ func (sc *ScopeChain) GetVariable(id SymbolID) Symbol[SymbolVariable] {
 
 	return sc.symbolScopes[id.scopeID].variableSymbols[id.indexInScope]
 }
-
-func (sc *ScopeChain) GetFunction(id SymbolID) Symbol[SymbolFunction] {
-	if id.symbolKind != SymbolKindFunction {
-		panic("incorrect symbol id kind given")
-	}
-
-	return sc.symbolScopes[id.scopeID].functionSymbols[id.indexInScope]
-}
diff --git a/pkg/lang/compiler/scope/scopes.go b/pkg/lang/compiler/scope/scopes.go
index 5cfcd5d..e34b45a 100644
--- a/pkg/lang/compiler/scope/scopes.go
+++ b/pkg/lang/compiler/scope/scopes.go
@@ -14,13 +14,11 @@ const (
 
 type SymbolScope struct {
 	variableSymbols []Symbol[SymbolVariable]
-	functionSymbols []Symbol[SymbolFunction]
 }
 
 func NewSymbolScope() SymbolScope {
 	return SymbolScope{
 		variableSymbols: make([]Symbol[SymbolVariable], 0),
-		functionSymbols: make([]Symbol[SymbolFunction], 0),
 	}
 }
 
diff --git a/pkg/lang/compiler/scope/symbol.go b/pkg/lang/compiler/scope/symbol.go
index df91899..3b50108 100644
--- a/pkg/lang/compiler/scope/symbol.go
+++ b/pkg/lang/compiler/scope/symbol.go
@@ -1,7 +1,5 @@
 package scope
 
-import "jinx/pkg/lang/vm/code"
-
 type SymbolID struct {
 	symbolKind   SymbolKind
 	scopeID      ScopeID
@@ -15,16 +13,14 @@ func (id SymbolID) SymbolKind() SymbolKind {
 type SymbolKind int
 
 const (
+	// A variable symbol is bound to a local on the stack.
 	SymbolKindVariable SymbolKind = iota
-	SymbolKindFunction
 )
 
 func (s SymbolKind) String() string {
 	switch s {
 	case SymbolKindVariable:
 		return "variable"
-	case SymbolKindFunction:
-		return "function"
 	default:
 		panic("unknown symbol kind")
 	}
@@ -40,7 +36,7 @@ func (s Symbol[D]) Data() D {
 }
 
 type SymbolData interface {
-	SymbolVariable | SymbolFunction
+	SymbolVariable
 }
 
 type SymbolVariable struct {
@@ -50,16 +46,3 @@ type SymbolVariable struct {
 func (sv SymbolVariable) LocalIndex() int {
 	return sv.localIndex
 }
-
-type SymbolFunction struct {
-	marker code.Marker
-	args   uint
-}
-
-func (sf SymbolFunction) Marker() code.Marker {
-	return sf.marker
-}
-
-func (sf SymbolFunction) Args() uint {
-	return sf.args
-}