From 7daccba9f3aaffbf11baf5b26ce1ee2c3e5cc173 Mon Sep 17 00:00:00 2001 From: nub31 Date: Tue, 10 Feb 2026 23:26:22 +0100 Subject: [PATCH] proper scopes --- compiler/ModuleGraph.cs | 8 +-- compiler/TypeChecker.cs | 107 ++++++++++++++++++++++++++-------------- 2 files changed, 73 insertions(+), 42 deletions(-) diff --git a/compiler/ModuleGraph.cs b/compiler/ModuleGraph.cs index a6d6987..65679e2 100644 --- a/compiler/ModuleGraph.cs +++ b/compiler/ModuleGraph.cs @@ -180,7 +180,7 @@ public class ModuleGraph var astModuleCache = new Dictionary(); - // First pass: Register modules from ast + // Second pass: Register modules from ast foreach (var ast in asts) { if (!modules.ContainsKey(ast.ModuleName.Ident)) @@ -191,7 +191,7 @@ public class ModuleGraph } } - // Second pass: Register struct types without fields + // Third pass: Register struct types without fields foreach (var ast in asts) { var module = astModuleCache[ast]; @@ -204,7 +204,7 @@ public class ModuleGraph } } - // Third pass: Resolve struct fields + // Fourth pass: Resolve struct fields foreach (var ast in asts) { var module = astModuleCache[ast]; @@ -219,7 +219,7 @@ public class ModuleGraph } } - // Fourth pass: Register identifiers + // Fifth pass: Register identifiers foreach (var ast in asts) { var module = astModuleCache[ast]; diff --git a/compiler/TypeChecker.cs b/compiler/TypeChecker.cs index e8b9daa..349e7a0 100644 --- a/compiler/TypeChecker.cs +++ b/compiler/TypeChecker.cs @@ -19,7 +19,7 @@ public class TypeChecker private readonly string moduleName; private readonly NodeDefinitionFunc function; private readonly ModuleGraph moduleGraph; - private readonly Scope scope = new(null); + private readonly Scope scope = new(); private TypedNodeDefinitionFunc? CheckFunction(out List diagnostics) { @@ -30,48 +30,50 @@ public class TypeChecker TypedNodeStatement? body = null; NubType? returnType = null; - foreach (var parameter in function.Parameters) + using (scope.EnterScope()) { - scope.DeclareIdentifier(parameter.Name.Ident, ResolveType(parameter.Type)); + foreach (var parameter in function.Parameters) + { + NubType parameterType; + + try + { + parameterType = ResolveType(parameter.Type); + } + catch (CompileException e) + { + diagnostics.Add(e.Diagnostic); + invalidParameter = true; + continue; + } + + scope.DeclareIdentifier(parameter.Name.Ident, parameterType); + parameters.Add(new TypedNodeDefinitionFunc.Param(parameter.Tokens, parameter.Name, parameterType)); + } try { - parameters.Add(CheckDefinitionFuncParameter(parameter)); + body = CheckStatement(function.Body); } catch (CompileException e) { diagnostics.Add(e.Diagnostic); - invalidParameter = true; } - } - try - { - body = CheckStatement(function.Body); - } - catch (CompileException e) - { - diagnostics.Add(e.Diagnostic); - } + try + { + returnType = ResolveType(function.ReturnType); + } + catch (CompileException e) + { + diagnostics.Add(e.Diagnostic); + } - try - { - returnType = ResolveType(function.ReturnType); + if (body == null || returnType == null || invalidParameter) + return null; + + return new TypedNodeDefinitionFunc(function.Tokens, moduleName, function.Name, parameters, body, returnType); } - catch (CompileException e) - { - diagnostics.Add(e.Diagnostic); - } - - if (body == null || returnType == null || invalidParameter) - return null; - - return new TypedNodeDefinitionFunc(function.Tokens, moduleName, function.Name, parameters, body, returnType); - } - - private TypedNodeDefinitionFunc.Param CheckDefinitionFuncParameter(NodeDefinitionFunc.Param node) - { - return new TypedNodeDefinitionFunc.Param(node.Tokens, node.Name, ResolveType(node.Type)); } private TypedNodeStatement CheckStatement(NodeStatement node) @@ -96,7 +98,11 @@ public class TypeChecker private TypedNodeStatementBlock CheckStatementBlock(NodeStatementBlock statement) { - return new TypedNodeStatementBlock(statement.Tokens, statement.Statements.Select(CheckStatement).ToList()); + using (scope.EnterScope()) + { + var statements = statement.Statements.Select(CheckStatement).ToList(); + return new TypedNodeStatementBlock(statement.Tokens, statements); + } } private TypedNodeStatementFuncCall CheckStatementExpression(NodeStatementExpression statement) @@ -406,20 +412,45 @@ public class TypeChecker return customType; } - private class Scope(Scope? parent) + private sealed class Scope { - private readonly Dictionary identifiers = new(); + private readonly Stack> scopes = new(); + + public IDisposable EnterScope() + { + scopes.Push([]); + return new ScopeGuard(this); + } public void DeclareIdentifier(string name, NubType type) { - identifiers.Add(name, type); + scopes.Peek().Add(name, type); } public NubType? GetIdentifierType(string name) { - return identifiers.TryGetValue(name, out var type) - ? type - : parent?.GetIdentifierType(name); + foreach (var scope in scopes) + { + if (scope.TryGetValue(name, out var type)) + { + return type; + } + } + + return null; + } + + private void ExitScope() + { + scopes.Pop(); + } + + private sealed class ScopeGuard(Scope owner) : IDisposable + { + public void Dispose() + { + owner.ExitScope(); + } } } }