From fc46e1287f89edfd8a283c8ee093d7ce295777d3 Mon Sep 17 00:00:00 2001 From: nub31 Date: Mon, 7 Jul 2025 18:38:27 +0200 Subject: [PATCH] binder scopes --- example/src/main.nub | 3 +- src/compiler/NubLang/Syntax/Binding/Binder.cs | 65 +++++++++---------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/example/src/main.nub b/example/src/main.nub index 952c9a7..1316bb9 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -34,8 +34,9 @@ func main(args: []cstring): i64 // } // human.print() + let x = 23 - print_result(12, func(num) { return num == 12 }) + print_result(12, func(num) { return num == x }) return 0 } diff --git a/src/compiler/NubLang/Syntax/Binding/Binder.cs b/src/compiler/NubLang/Syntax/Binding/Binder.cs index 261a784..85ab7b9 100644 --- a/src/compiler/NubLang/Syntax/Binding/Binder.cs +++ b/src/compiler/NubLang/Syntax/Binding/Binder.cs @@ -11,9 +11,10 @@ public sealed class Binder private readonly SyntaxTree _syntaxTree; private readonly DefinitionTable _definitionTable; - private readonly Stack _variables = []; + private readonly Stack _scopes = []; private readonly Stack _funcReturnTypes = []; - private readonly Stack _variableScopes = []; + + private Scope Scope => _scopes.Peek(); public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable) { @@ -23,9 +24,8 @@ public sealed class Binder public BoundSyntaxTree Bind() { - _variables.Clear(); _funcReturnTypes.Clear(); - _variableScopes.Clear(); + _scopes.Clear(); var diagnostics = new List(); var definitions = new List(); @@ -60,7 +60,6 @@ public sealed class Binder private BoundTraitImpl BindTraitImplementation(TraitImplSyntax node) { - _variables.Clear(); var functions = new List(); foreach (var func in node.Functions) @@ -112,8 +111,6 @@ public sealed class Binder private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node) { - _variables.Clear(); - var signature = BindFuncSignature(node.Signature); var body = BindFuncBody(node.Body, signature.ReturnType, signature.Parameters); @@ -208,7 +205,7 @@ public sealed class Binder throw new NotImplementedException("Diagnostics not implemented"); } - _variables.Push(new Variable(statement.Name, type)); + Scope.Declare(new Variable(statement.Name, type)); return new BoundVariableDeclaration(statement.Tokens, statement.Name, assignment, type); } @@ -357,14 +354,14 @@ public sealed class Binder if (!expression.Namespace.HasValue) { - var variable = _variables.FirstOrDefault(x => x.Name == expression.Name); + var variable = Scope.Lookup(expression.Name); if (variable != null) { return new BoundVariableIdent(expression.Tokens, variable.Type, variable.Name); } } - throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build()); + throw new BindException(Diagnostic.Error($"No identifier with the name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build()); } private BoundLiteral BindLiteral(LiteralSyntax expression, NubType? expectedType = null) @@ -573,29 +570,18 @@ public sealed class Binder }; } - private BoundBlock BindBlock(BlockSyntax node, IEnumerable? variables = null) + private BoundBlock BindBlock(BlockSyntax node, Scope? scope = null) { - _variableScopes.Push(_variables.Count); - if (variables != null) - { - foreach (var variable in variables) - { - _variables.Push(variable); - } - } - var statements = new List(); + _scopes.Push(scope ?? Scope.SubScope()); + foreach (var statement in node.Statements) { statements.Add(BindStatement(statement)); } - var count = _variableScopes.Pop(); - while (_variableScopes.Count > count) - { - _variableScopes.Pop(); - } + _scopes.Pop(); return new BoundBlock(node.Tokens, statements); } @@ -603,7 +589,14 @@ public sealed class Binder private BoundBlock BindFuncBody(BlockSyntax block, NubType returnType, IEnumerable parameters) { _funcReturnTypes.Push(returnType); - var body = BindBlock(block, parameters.Select(x => new Variable(x.Name, x.Type))); + + var scope = new Scope(); + foreach (var parameter in parameters) + { + scope.Declare(new Variable(parameter.Name, parameter.Type)); + } + + var body = BindBlock(block, scope); _funcReturnTypes.Pop(); return body; } @@ -611,22 +604,24 @@ public sealed class Binder public record Variable(string Name, NubType Type); -public class Scope(Scope? parent) +public class Scope(Scope? parent = null) { - private List _variables = []; + private readonly List _variables = []; - public Variable Lookup(string name) + public Variable? Lookup(string name) { var variable = _variables.FirstOrDefault(x => x.Name == name); - if (variable == null) + if (variable != null) { - if (parent != null) - { - return parent.Lookup(name); - } + return variable; } - throw new BindException(Diagnostic.Error($"Variable {name} is not available in the current scope").Build()); + return parent?.Lookup(name); + } + + public void Declare(Variable variable) + { + _variables.Add(variable); } public Scope SubScope()