WIP: dev #1

Draft
nub31 wants to merge 103 commits from dev into master
2 changed files with 73 additions and 42 deletions
Showing only changes of commit 7daccba9f3 - Show all commits

View File

@@ -180,7 +180,7 @@ public class ModuleGraph
var astModuleCache = new Dictionary<Ast, Module>(); var astModuleCache = new Dictionary<Ast, Module>();
// First pass: Register modules from ast // Second pass: Register modules from ast
foreach (var ast in asts) foreach (var ast in asts)
{ {
if (!modules.ContainsKey(ast.ModuleName.Ident)) 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) foreach (var ast in asts)
{ {
var module = astModuleCache[ast]; 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) foreach (var ast in asts)
{ {
var module = astModuleCache[ast]; var module = astModuleCache[ast];
@@ -219,7 +219,7 @@ public class ModuleGraph
} }
} }
// Fourth pass: Register identifiers // Fifth pass: Register identifiers
foreach (var ast in asts) foreach (var ast in asts)
{ {
var module = astModuleCache[ast]; var module = astModuleCache[ast];

View File

@@ -19,7 +19,7 @@ public class TypeChecker
private readonly string moduleName; private readonly string moduleName;
private readonly NodeDefinitionFunc function; private readonly NodeDefinitionFunc function;
private readonly ModuleGraph moduleGraph; private readonly ModuleGraph moduleGraph;
private readonly Scope scope = new(null); private readonly Scope scope = new();
private TypedNodeDefinitionFunc? CheckFunction(out List<Diagnostic> diagnostics) private TypedNodeDefinitionFunc? CheckFunction(out List<Diagnostic> diagnostics)
{ {
@@ -30,19 +30,25 @@ public class TypeChecker
TypedNodeStatement? body = null; TypedNodeStatement? body = null;
NubType? returnType = null; NubType? returnType = null;
using (scope.EnterScope())
{
foreach (var parameter in function.Parameters) foreach (var parameter in function.Parameters)
{ {
scope.DeclareIdentifier(parameter.Name.Ident, ResolveType(parameter.Type)); NubType parameterType;
try try
{ {
parameters.Add(CheckDefinitionFuncParameter(parameter)); parameterType = ResolveType(parameter.Type);
} }
catch (CompileException e) catch (CompileException e)
{ {
diagnostics.Add(e.Diagnostic); diagnostics.Add(e.Diagnostic);
invalidParameter = true; invalidParameter = true;
continue;
} }
scope.DeclareIdentifier(parameter.Name.Ident, parameterType);
parameters.Add(new TypedNodeDefinitionFunc.Param(parameter.Tokens, parameter.Name, parameterType));
} }
try try
@@ -68,10 +74,6 @@ public class TypeChecker
return new TypedNodeDefinitionFunc(function.Tokens, moduleName, function.Name, parameters, body, returnType); 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) private TypedNodeStatement CheckStatement(NodeStatement node)
@@ -96,7 +98,11 @@ public class TypeChecker
private TypedNodeStatementBlock CheckStatementBlock(NodeStatementBlock statement) 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) private TypedNodeStatementFuncCall CheckStatementExpression(NodeStatementExpression statement)
@@ -406,20 +412,45 @@ public class TypeChecker
return customType; return customType;
} }
private class Scope(Scope? parent) private sealed class Scope
{ {
private readonly Dictionary<string, NubType> identifiers = new(); private readonly Stack<Dictionary<string, NubType>> scopes = new();
public IDisposable EnterScope()
{
scopes.Push([]);
return new ScopeGuard(this);
}
public void DeclareIdentifier(string name, NubType type) public void DeclareIdentifier(string name, NubType type)
{ {
identifiers.Add(name, type); scopes.Peek().Add(name, type);
} }
public NubType? GetIdentifierType(string name) public NubType? GetIdentifierType(string name)
{ {
return identifiers.TryGetValue(name, out var type) foreach (var scope in scopes)
? type {
: parent?.GetIdentifierType(name); 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();
}
} }
} }
} }