...
This commit is contained in:
15
compiler/NubLang/Ast/CompilationUnit.cs
Normal file
15
compiler/NubLang/Ast/CompilationUnit.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace NubLang.Ast;
|
||||
|
||||
public sealed class CompilationUnit
|
||||
{
|
||||
public CompilationUnit(List<FuncNode> functions, List<NubStructType> importedStructTypes, List<FuncPrototypeNode> importedFunctions)
|
||||
{
|
||||
Functions = functions;
|
||||
ImportedStructTypes = importedStructTypes;
|
||||
ImportedFunctions = importedFunctions;
|
||||
}
|
||||
|
||||
public List<FuncNode> Functions { get; }
|
||||
public List<NubStructType> ImportedStructTypes { get; }
|
||||
public List<FuncPrototypeNode> ImportedFunctions { get; }
|
||||
}
|
||||
@@ -10,15 +10,9 @@ public abstract record DefinitionNode(List<Token> Tokens, string Module, string
|
||||
|
||||
public record FuncParameterNode(List<Token> Tokens, string Name, NubType Type) : Node(Tokens);
|
||||
|
||||
public record FuncSignatureNode(List<Token> Tokens, List<FuncParameterNode> Parameters, NubType ReturnType) : Node(Tokens);
|
||||
public record FuncPrototypeNode(List<Token> Tokens, string Module, string Name, string? ExternSymbol, List<FuncParameterNode> Parameters, NubType ReturnType) : Node(Tokens);
|
||||
|
||||
public record FuncNode(List<Token> Tokens, string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Tokens, Module, Name);
|
||||
|
||||
public record StructFieldNode(List<Token> Tokens, string Name, NubType Type, ExpressionNode? Value) : Node(Tokens);
|
||||
|
||||
public record StructFuncNode(List<Token> Tokens, string Name, FuncSignatureNode Signature, BlockNode Body) : Node(Tokens);
|
||||
|
||||
public record StructNode(List<Token> Tokens, string Module, string Name, List<StructFieldNode> Fields, List<StructFuncNode> Functions) : DefinitionNode(Tokens, Module, Name);
|
||||
public record FuncNode(List<Token> Tokens, FuncPrototypeNode Prototype, BlockNode? Body) : DefinitionNode(Tokens, Prototype.Module, Prototype.Name);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -32,8 +26,6 @@ public record BlockNode(List<Token> Tokens, List<StatementNode> Statements) : St
|
||||
|
||||
public record StatementFuncCallNode(List<Token> Tokens, FuncCallNode FuncCall) : StatementNode(Tokens);
|
||||
|
||||
public record StatementStructFuncCallNode(List<Token> Tokens, StructFuncCallNode StructFuncCall) : StatementNode(Tokens);
|
||||
|
||||
public record ReturnNode(List<Token> Tokens, ExpressionNode? Value) : TerminalStatementNode(Tokens);
|
||||
|
||||
public record AssignmentNode(List<Token> Tokens, LValueExpressionNode Target, ExpressionNode Value) : StatementNode(Tokens);
|
||||
@@ -108,8 +100,6 @@ public record UnaryExpressionNode(List<Token> Tokens, NubType Type, UnaryOperato
|
||||
|
||||
public record FuncCallNode(List<Token> Tokens, NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record StructFuncCallNode(List<Token> Tokens, NubType Type, string Module, string StructName, string FuncName, ExpressionNode StructExpression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record LValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record RValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
@@ -100,7 +100,7 @@ public class NubFuncType(List<NubType> parameters, NubType returnType) : NubType
|
||||
}
|
||||
}
|
||||
|
||||
public class NubStructType(string module, string name, List<NubStructFieldType> fields, List<NubStructFuncType> functions) : NubType
|
||||
public class NubStructType(string module, string name, List<NubStructFieldType> fields) : NubType
|
||||
{
|
||||
public override bool IsValueType => true;
|
||||
public override bool IsScalar => false;
|
||||
@@ -108,9 +108,8 @@ public class NubStructType(string module, string name, List<NubStructFieldType>
|
||||
public string Module { get; } = module;
|
||||
public string Name { get; } = name;
|
||||
public List<NubStructFieldType> Fields { get; set; } = fields;
|
||||
public List<NubStructFuncType> Functions { get; set; } = functions;
|
||||
|
||||
public override string ToString() => $"{Module}.{Name}";
|
||||
public override string ToString() => $"{Module}::{Name}";
|
||||
public override bool Equals(NubType? other) => other is NubStructType structType && Name == structType.Name && Module == structType.Module;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubStructType), Module, Name);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using NubLang.Diagnostics;
|
||||
using NubLang.Modules;
|
||||
using NubLang.Syntax;
|
||||
|
||||
namespace NubLang.Ast;
|
||||
@@ -8,64 +7,69 @@ namespace NubLang.Ast;
|
||||
public sealed class TypeChecker
|
||||
{
|
||||
private readonly SyntaxTree _syntaxTree;
|
||||
private readonly Dictionary<string, Module> _visibleModules;
|
||||
private readonly Dictionary<string, Module> _importedModules;
|
||||
|
||||
private readonly Stack<Scope> _scopes = [];
|
||||
private readonly Stack<NubType> _funcReturnTypes = [];
|
||||
private readonly Dictionary<(string Module, string Name), NubType> _typeCache = new();
|
||||
private readonly HashSet<(string Module, string Name)> _resolvingTypes = [];
|
||||
private readonly HashSet<string> _checkedTemplateStructs = [];
|
||||
|
||||
private Scope CurrentScope => _scopes.Peek();
|
||||
|
||||
public TypeChecker(SyntaxTree syntaxTree, ModuleRepository moduleRepository)
|
||||
public List<Diagnostic> Diagnostics { get; } = [];
|
||||
|
||||
public TypeChecker(SyntaxTree syntaxTree, Dictionary<string, Module> modules)
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
_visibleModules = moduleRepository
|
||||
.Modules()
|
||||
.Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key)
|
||||
_importedModules = modules
|
||||
.Where(x => syntaxTree.Imports.Contains(x.Key) || _syntaxTree.ModuleName == x.Key)
|
||||
.ToDictionary();
|
||||
}
|
||||
|
||||
public List<DefinitionNode> Definitions { get; } = [];
|
||||
public List<Diagnostic> Diagnostics { get; } = [];
|
||||
|
||||
public void Check()
|
||||
public CompilationUnit Check()
|
||||
{
|
||||
_scopes.Clear();
|
||||
_funcReturnTypes.Clear();
|
||||
_typeCache.Clear();
|
||||
_resolvingTypes.Clear();
|
||||
_checkedTemplateStructs.Clear();
|
||||
|
||||
Diagnostics.Clear();
|
||||
Definitions.Clear();
|
||||
|
||||
using (BeginRootScope(_syntaxTree.Metadata.ModuleName))
|
||||
using (BeginRootScope(_syntaxTree.ModuleName))
|
||||
{
|
||||
foreach (var definition in _syntaxTree.Definitions)
|
||||
var functions = new List<FuncNode>();
|
||||
|
||||
foreach (var funcSyntax in _syntaxTree.Definitions.OfType<FuncSyntax>())
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (definition)
|
||||
{
|
||||
case FuncSyntax funcSyntax:
|
||||
Definitions.Add(CheckFuncDefinition(funcSyntax));
|
||||
break;
|
||||
case StructSyntax structSyntax:
|
||||
Definitions.Add(CheckStructDefinition(structSyntax));
|
||||
break;
|
||||
case StructTemplateSyntax:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
functions.Add(CheckFuncDefinition(funcSyntax));
|
||||
}
|
||||
catch (TypeCheckerException e)
|
||||
{
|
||||
Diagnostics.Add(e.Diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
var importedStructTypes = new List<NubStructType>();
|
||||
var importedFunctions = new List<FuncPrototypeNode>();
|
||||
|
||||
foreach (var (name, module) in _importedModules)
|
||||
{
|
||||
foreach (var structSyntax in module.Structs(false))
|
||||
{
|
||||
var fields = structSyntax.Fields
|
||||
.Select(f => new NubStructFieldType(f.Name, ResolveType(f.Type), f.Value != null))
|
||||
.ToList();
|
||||
|
||||
importedStructTypes.Add(new NubStructType(name, structSyntax.Name, fields));
|
||||
}
|
||||
|
||||
foreach (var funcSyntax in module.Functions(false))
|
||||
{
|
||||
importedFunctions.Add(CheckFuncPrototype(funcSyntax.Prototype));
|
||||
}
|
||||
}
|
||||
|
||||
return new CompilationUnit(functions, importedStructTypes, importedFunctions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +81,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
else
|
||||
{
|
||||
_scopes.Push(new Scope(_syntaxTree.Metadata.ModuleName));
|
||||
_scopes.Push(new Scope(_syntaxTree.ModuleName));
|
||||
}
|
||||
|
||||
return new ScopeDisposer(this);
|
||||
@@ -101,74 +105,25 @@ public sealed class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
private StructNode CheckStructDefinition(StructSyntax node)
|
||||
{
|
||||
var fieldTypes = node.Fields
|
||||
.Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value != null))
|
||||
.ToList();
|
||||
|
||||
var fieldFunctions = node.Functions
|
||||
.Select(x =>
|
||||
{
|
||||
var parameters = x.Signature.Parameters.Select(y => ResolveType(y.Type)).ToList();
|
||||
var returnType = ResolveType(x.Signature.ReturnType);
|
||||
return new NubStructFuncType(x.Name, parameters, returnType);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var structType = new NubStructType(CurrentScope.Module, node.Name, fieldTypes, fieldFunctions);
|
||||
|
||||
CurrentScope.DeclareVariable(new Variable("this", structType, VariableKind.RValue));
|
||||
|
||||
var fields = node.Fields.Select(CheckStructField).ToList();
|
||||
var functions = node.Functions.Select(CheckStructFunc).ToList();
|
||||
|
||||
return new StructNode(node.Tokens, CurrentScope.Module, node.Name, fields, functions);
|
||||
}
|
||||
|
||||
private StructFuncNode CheckStructFunc(StructFuncSyntax function)
|
||||
{
|
||||
foreach (var parameter in function.Signature.Parameters)
|
||||
{
|
||||
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue));
|
||||
}
|
||||
|
||||
_funcReturnTypes.Push(ResolveType(function.Signature.ReturnType));
|
||||
var body = CheckBlock(function.Body);
|
||||
_funcReturnTypes.Pop();
|
||||
return new StructFuncNode(function.Tokens, function.Name, CheckFuncSignature(function.Signature), body);
|
||||
}
|
||||
|
||||
private StructFieldNode CheckStructField(StructFieldSyntax field)
|
||||
{
|
||||
ExpressionNode? value = null;
|
||||
if (field.Value != null)
|
||||
{
|
||||
value = CheckExpression(field.Value, ResolveType(field.Type));
|
||||
}
|
||||
|
||||
return new StructFieldNode(field.Tokens, field.Name, ResolveType(field.Type), value);
|
||||
}
|
||||
|
||||
private FuncNode CheckFuncDefinition(FuncSyntax node)
|
||||
{
|
||||
foreach (var parameter in node.Signature.Parameters)
|
||||
foreach (var parameter in node.Prototype.Parameters)
|
||||
{
|
||||
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue));
|
||||
}
|
||||
|
||||
var signature = CheckFuncSignature(node.Signature);
|
||||
var prototype = CheckFuncPrototype(node.Prototype);
|
||||
|
||||
BlockNode? body = null;
|
||||
if (node.Body != null)
|
||||
{
|
||||
_funcReturnTypes.Push(signature.ReturnType);
|
||||
_funcReturnTypes.Push(prototype.ReturnType);
|
||||
|
||||
body = CheckBlock(node.Body);
|
||||
|
||||
if (!AlwaysReturns(body))
|
||||
{
|
||||
if (signature.ReturnType is NubVoidType)
|
||||
if (prototype.ReturnType is NubVoidType)
|
||||
{
|
||||
body.Statements.Add(new ReturnNode(node.Tokens.Skip(node.Tokens.Count - 1).ToList(), null));
|
||||
}
|
||||
@@ -184,7 +139,7 @@ public sealed class TypeChecker
|
||||
_funcReturnTypes.Pop();
|
||||
}
|
||||
|
||||
return new FuncNode(node.Tokens, CurrentScope.Module, node.Name, node.ExternSymbol, signature, body);
|
||||
return new FuncNode(node.Tokens, prototype, body);
|
||||
}
|
||||
|
||||
private AssignmentNode CheckAssignment(AssignmentSyntax statement)
|
||||
@@ -231,7 +186,6 @@ public sealed class TypeChecker
|
||||
return expression switch
|
||||
{
|
||||
FuncCallNode funcCall => new StatementFuncCallNode(statement.Tokens, funcCall),
|
||||
StructFuncCallNode structFuncCall => new StatementStructFuncCallNode(statement.Tokens, structFuncCall),
|
||||
_ => throw new TypeCheckerException(Diagnostic.Error("Expressions statements can only be function calls").At(statement).Build())
|
||||
};
|
||||
}
|
||||
@@ -269,7 +223,7 @@ public sealed class TypeChecker
|
||||
return new WhileNode(statement.Tokens, condition, body);
|
||||
}
|
||||
|
||||
private FuncSignatureNode CheckFuncSignature(FuncSignatureSyntax statement)
|
||||
private FuncPrototypeNode CheckFuncPrototype(FuncPrototypeSyntax statement)
|
||||
{
|
||||
var parameters = new List<FuncParameterNode>();
|
||||
foreach (var parameter in statement.Parameters)
|
||||
@@ -277,7 +231,7 @@ public sealed class TypeChecker
|
||||
parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.Name, ResolveType(parameter.Type)));
|
||||
}
|
||||
|
||||
return new FuncSignatureNode(statement.Tokens, parameters, ResolveType(statement.ReturnType));
|
||||
return new FuncPrototypeNode(statement.Tokens, CurrentScope.Module, statement.Name, statement.ExternSymbol, parameters, ResolveType(statement.ReturnType));
|
||||
}
|
||||
|
||||
private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
||||
@@ -290,7 +244,6 @@ public sealed class TypeChecker
|
||||
BinaryExpressionSyntax expression => CheckBinaryExpression(expression, expectedType),
|
||||
UnaryExpressionSyntax expression => CheckUnaryExpression(expression, expectedType),
|
||||
DereferenceSyntax expression => CheckDereference(expression),
|
||||
MemberFuncCallSyntax expression => CheckMemberFuncCall(expression),
|
||||
FuncCallSyntax expression => CheckFuncCall(expression),
|
||||
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
|
||||
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
|
||||
@@ -608,56 +561,6 @@ public sealed class TypeChecker
|
||||
return new FuncCallNode(expression.Tokens, funcType.ReturnType, accessor, parameters);
|
||||
}
|
||||
|
||||
private StructFuncCallNode CheckMemberFuncCall(MemberFuncCallSyntax expression)
|
||||
{
|
||||
// todo(nub31): When adding interfaces, also support other types than structs
|
||||
var target = CheckExpression(expression.Target);
|
||||
if (target.Type is NubStructType structType)
|
||||
{
|
||||
var function = structType.Functions.FirstOrDefault(x => x.Name == expression.Name);
|
||||
if (function == null)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Function {expression.Name} not found on struct {structType}")
|
||||
.At(expression)
|
||||
.Build());
|
||||
}
|
||||
|
||||
if (expression.Parameters.Count != function.Parameters.Count)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Function {function.Name} expects {function.Parameters.Count} parameters but got {expression.Parameters.Count}")
|
||||
.At(expression.Parameters.LastOrDefault(expression))
|
||||
.Build());
|
||||
}
|
||||
|
||||
var parameters = new List<ExpressionNode>();
|
||||
for (var i = 0; i < expression.Parameters.Count; i++)
|
||||
{
|
||||
var parameter = expression.Parameters[i];
|
||||
var expectedType = function.Parameters[i];
|
||||
|
||||
var parameterExpression = CheckExpression(parameter, expectedType);
|
||||
if (parameterExpression.Type != expectedType)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Parameter {i + 1} does not match the type {expectedType} for function {function}")
|
||||
.At(parameter)
|
||||
.Build());
|
||||
}
|
||||
|
||||
parameters.Add(parameterExpression);
|
||||
}
|
||||
|
||||
return new StructFuncCallNode(expression.Tokens, function.ReturnType, structType.Module, structType.Name, expression.Name, target, parameters);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"No function {expression.Name} exists on type {target.Type}")
|
||||
.At(expression)
|
||||
.Build());
|
||||
}
|
||||
|
||||
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression)
|
||||
{
|
||||
var scopeIdent = CurrentScope.LookupVariable(expression.Name);
|
||||
@@ -671,14 +574,14 @@ public sealed class TypeChecker
|
||||
};
|
||||
}
|
||||
|
||||
var module = _visibleModules[CurrentScope.Module];
|
||||
var module = _importedModules[CurrentScope.Module];
|
||||
var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name);
|
||||
|
||||
if (function != null)
|
||||
{
|
||||
var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
|
||||
return new FuncIdentifierNode(expression.Tokens, type, CurrentScope.Module, expression.Name, function.ExternSymbol);
|
||||
var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType));
|
||||
return new FuncIdentifierNode(expression.Tokens, type, CurrentScope.Module, expression.Name, function.Prototype.ExternSymbol);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Symbol {expression.Name} not found").At(expression).Build());
|
||||
@@ -686,7 +589,7 @@ public sealed class TypeChecker
|
||||
|
||||
private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression)
|
||||
{
|
||||
if (!_visibleModules.TryGetValue(expression.Module, out var module))
|
||||
if (!_importedModules.TryGetValue(expression.Module, out var module))
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Module {expression.Module} not found")
|
||||
@@ -700,9 +603,9 @@ public sealed class TypeChecker
|
||||
var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
||||
if (function != null)
|
||||
{
|
||||
var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
|
||||
return new FuncIdentifierNode(expression.Tokens, type, expression.Module, expression.Name, function.ExternSymbol);
|
||||
var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType));
|
||||
return new FuncIdentifierNode(expression.Tokens, type, expression.Module, expression.Name, function.Prototype.ExternSymbol);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
@@ -824,8 +727,6 @@ public sealed class TypeChecker
|
||||
.Error($"Struct {structType.Name} does not have a field named {initializer.Key}")
|
||||
.At(initializer.Value)
|
||||
.Build());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
initializers.Add(initializer.Key, CheckExpression(initializer.Value, typeField.Type));
|
||||
@@ -849,34 +750,12 @@ public sealed class TypeChecker
|
||||
|
||||
private BlockNode CheckBlock(BlockSyntax node)
|
||||
{
|
||||
var statements = new List<StatementNode>();
|
||||
|
||||
var reachable = true;
|
||||
var warnedUnreachable = false;
|
||||
|
||||
using (BeginScope())
|
||||
{
|
||||
var statements = new List<StatementNode>();
|
||||
foreach (var statement in node.Statements)
|
||||
{
|
||||
var checkedStatement = CheckStatement(statement);
|
||||
|
||||
if (reachable)
|
||||
{
|
||||
if (checkedStatement is TerminalStatementNode)
|
||||
{
|
||||
reachable = false;
|
||||
}
|
||||
|
||||
statements.Add(checkedStatement);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!warnedUnreachable)
|
||||
{
|
||||
Diagnostics.Add(Diagnostic.Warning("Statement is unreachable").At(statement).Build());
|
||||
warnedUnreachable = true;
|
||||
}
|
||||
}
|
||||
statements.Add(CheckStatement(statement));
|
||||
}
|
||||
|
||||
return new BlockNode(node.Tokens, statements);
|
||||
@@ -937,27 +816,11 @@ public sealed class TypeChecker
|
||||
PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)),
|
||||
StringTypeSyntax => new NubStringType(),
|
||||
CustomTypeSyntax c => ResolveCustomType(c),
|
||||
StructTemplateTypeSyntax t => ResolveStructTemplateType(t),
|
||||
SubstitutionTypeSyntax s => ResolveTypeSubstitution(s),
|
||||
VoidTypeSyntax => new NubVoidType(),
|
||||
_ => throw new NotSupportedException($"Unknown type syntax: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
private NubType ResolveTypeSubstitution(SubstitutionTypeSyntax substitution)
|
||||
{
|
||||
var type = CurrentScope.LookupTypeSubstitution(substitution.Name);
|
||||
if (type == null)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Template argument {substitution.Name} does not exist")
|
||||
.At(substitution)
|
||||
.Build());
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private NubType ResolveCustomType(CustomTypeSyntax customType)
|
||||
{
|
||||
var key = (customType.Module, customType.Name);
|
||||
@@ -969,14 +832,14 @@ public sealed class TypeChecker
|
||||
|
||||
if (!_resolvingTypes.Add(key))
|
||||
{
|
||||
var placeholder = new NubStructType(customType.Module, customType.Name, [], []);
|
||||
var placeholder = new NubStructType(customType.Module, customType.Name, []);
|
||||
_typeCache[key] = placeholder;
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_visibleModules.TryGetValue(customType.Module, out var module))
|
||||
if (!_importedModules.TryGetValue(customType.Module, out var module))
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Module {customType.Module} not found")
|
||||
@@ -990,7 +853,7 @@ public sealed class TypeChecker
|
||||
var structDef = module.Structs(includePrivate).FirstOrDefault(x => x.Name == customType.Name);
|
||||
if (structDef != null)
|
||||
{
|
||||
var result = new NubStructType(customType.Module, structDef.Name, [], []);
|
||||
var result = new NubStructType(customType.Module, structDef.Name, []);
|
||||
_typeCache[key] = result;
|
||||
|
||||
var fields = structDef.Fields
|
||||
@@ -998,19 +861,6 @@ public sealed class TypeChecker
|
||||
.ToList();
|
||||
|
||||
result.Fields.AddRange(fields);
|
||||
|
||||
var functions = structDef.Functions
|
||||
.Select(x =>
|
||||
{
|
||||
var parameters = x.Signature.Parameters
|
||||
.Select(y => ResolveType(y.Type))
|
||||
.ToList();
|
||||
|
||||
return new NubStructFuncType(x.Name, parameters, ResolveType(x.Signature.ReturnType));
|
||||
})
|
||||
.ToList();
|
||||
|
||||
result.Functions.AddRange(functions);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1024,71 +874,6 @@ public sealed class TypeChecker
|
||||
_resolvingTypes.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
private NubStructType ResolveStructTemplateType(StructTemplateTypeSyntax structTemplate)
|
||||
{
|
||||
if (!_visibleModules.TryGetValue(structTemplate.Module, out var module))
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Module {structTemplate.Module} not found")
|
||||
.WithHelp($"import \"{structTemplate.Module}\"")
|
||||
.At(structTemplate)
|
||||
.Build());
|
||||
}
|
||||
|
||||
var includePrivate = structTemplate.Module == CurrentScope.Module;
|
||||
|
||||
var templateDef = module
|
||||
.StructTemplates(includePrivate)
|
||||
.FirstOrDefault(x => x.Name == structTemplate.Name);
|
||||
|
||||
if (templateDef == null)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"Template type {structTemplate.Name} not found in module {structTemplate.Module}")
|
||||
.At(structTemplate)
|
||||
.Build());
|
||||
}
|
||||
|
||||
var templateParameterTypes = structTemplate.TemplateParameters.Select(ResolveType).ToList();
|
||||
var mangledName = $"{structTemplate.Name}.{NameMangler.Mangle(templateParameterTypes)}";
|
||||
|
||||
using (BeginRootScope(structTemplate.Module))
|
||||
{
|
||||
for (var i = 0; i < templateParameterTypes.Count; i++)
|
||||
{
|
||||
var parameterName = templateDef.TemplateArguments[i];
|
||||
var parameterType = templateParameterTypes[i];
|
||||
CurrentScope.DeclareTypeSubstitution(parameterName, parameterType);
|
||||
}
|
||||
|
||||
var fieldTypes = templateDef.Fields
|
||||
.Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value != null))
|
||||
.ToList();
|
||||
|
||||
var fieldFunctions = templateDef.Functions
|
||||
.Select(x =>
|
||||
{
|
||||
var parameters = x.Signature.Parameters.Select(y => ResolveType(y.Type)).ToList();
|
||||
var returnType = ResolveType(x.Signature.ReturnType);
|
||||
return new NubStructFuncType(x.Name, parameters, returnType);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var structType = new NubStructType(structTemplate.Module, mangledName, fieldTypes, fieldFunctions);
|
||||
|
||||
if (!_checkedTemplateStructs.Contains($"{structTemplate.Module}.{mangledName}"))
|
||||
{
|
||||
CurrentScope.DeclareVariable(new Variable("this", structType, VariableKind.RValue));
|
||||
var fields = templateDef.Fields.Select(CheckStructField).ToList();
|
||||
var functions = templateDef.Functions.Select(CheckStructFunc).ToList();
|
||||
Definitions.Add(new StructNode(templateDef.Tokens, structTemplate.Module, mangledName, fields, functions));
|
||||
_checkedTemplateStructs.Add($"{structTemplate.Module}.{mangledName}");
|
||||
}
|
||||
|
||||
return structType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum VariableKind
|
||||
|
||||
Reference in New Issue
Block a user