This commit is contained in:
nub31
2025-09-21 20:44:57 +02:00
parent cf2214a299
commit 58b1a5c017
13 changed files with 101 additions and 232 deletions

View File

@@ -372,12 +372,12 @@ public class QBEGenerator
foreach (var field in structDef.Fields) foreach (var field in structDef.Fields)
{ {
if (field.Value.TryGetValue(out var value)) if (field.Value != null)
{ {
var offset = OffsetOf(TypeOfStruct(structDef), field.Name); var offset = OffsetOf(TypeOfStruct(structDef), field.Name);
var destination = TmpName(); var destination = TmpName();
_writer.Indented($"{destination} =l add %struct, {offset}"); _writer.Indented($"{destination} =l add %struct, {offset}");
EmitCopyInto(value, destination); EmitCopyInto(field.Value, destination);
} }
} }
@@ -566,9 +566,9 @@ public class QBEGenerator
private void EmitReturn(ReturnNode @return) private void EmitReturn(ReturnNode @return)
{ {
if (@return.Value.HasValue) if (@return.Value != null)
{ {
var result = EmitExpression(@return.Value.Value); var result = EmitExpression(@return.Value);
EmitScopeCleanup(); EmitScopeCleanup();
_writer.Indented($"ret {result}"); _writer.Indented($"ret {result}");
} }
@@ -584,9 +584,9 @@ public class QBEGenerator
var name = $"%{variableDeclaration.Name}"; var name = $"%{variableDeclaration.Name}";
_writer.Indented($"{name} =l alloc8 {SizeOf(variableDeclaration.Type)}"); _writer.Indented($"{name} =l alloc8 {SizeOf(variableDeclaration.Type)}");
if (variableDeclaration.Assignment.HasValue) if (variableDeclaration.Assignment != null)
{ {
EmitCopyInto(variableDeclaration.Assignment.Value, name); EmitCopyInto(variableDeclaration.Assignment, name);
} }
Scope.Variables.Push(new Variable(variableDeclaration.Name, variableDeclaration.Type)); Scope.Variables.Push(new Variable(variableDeclaration.Name, variableDeclaration.Type));
@@ -1234,7 +1234,7 @@ public class QBEGenerator
private NubStructType TypeOfStruct(StructNode definition) private NubStructType TypeOfStruct(StructNode definition)
{ {
var fieldTypes = definition.Fields var fieldTypes = definition.Fields
.Select(x => new NubStructFieldType(x.Name, x.Type, x.Value.HasValue)) .Select(x => new NubStructFieldType(x.Name, x.Type, x.Value != null))
.ToList(); .ToList();
var functionTypes = new List<NubStructFuncType>(); var functionTypes = new List<NubStructFuncType>();

View File

@@ -4,42 +4,34 @@ namespace NubLang.Modules;
public class Module public class Module
{ {
private readonly List<ModuleStruct> _structs = []; private readonly List<DefinitionSyntax> _definitions = [];
private readonly List<StructTemplateSyntax> _structTemplates = [];
private readonly List<ModuleFunction> _functions = [];
public void RegisterStruct(bool exported, string name, List<ModuleStructField> fields, List<ModuleStructFunction> functions) public void Register(DefinitionSyntax definition)
{ {
_structs.Add(new ModuleStruct(exported, name, fields, functions)); _definitions.Add(definition);
} }
public void RegisterStructTemplate(StructTemplateSyntax structTemplate) public List<StructSyntax> Structs(bool includePrivate)
{ {
_structTemplates.Add(structTemplate); return _definitions
.OfType<StructSyntax>()
.Where(x => x.Exported || includePrivate)
.ToList();
} }
public void RegisterFunction(bool exported, string name, string? externSymbol, List<ModuleFunctionParameter> parameters, TypeSyntax returnType) public List<StructTemplateSyntax> StructTemplates(bool includePrivate)
{ {
_functions.Add(new ModuleFunction(exported, name, externSymbol, parameters, returnType)); return _definitions
.OfType<StructTemplateSyntax>()
.Where(x => x.Exported || includePrivate)
.ToList();
} }
public List<ModuleStruct> StructTypes(bool includePrivate) public List<FuncSyntax> Functions(bool includePrivate)
{ {
return _structs.Where(x => x.Exported || includePrivate).ToList(); return _definitions
} .OfType<FuncSyntax>()
.Where(x => x.Exported || includePrivate)
public List<ModuleFunction> Functions(bool includePrivate) .ToList();
{
return _functions.Where(x => x.Exported || includePrivate).ToList();
} }
} }
public record ModuleStructField(string Name, TypeSyntax Type, bool HasDefaultValue);
public record ModuleStructFunction(string Name, string? Hook, List<ModuleFunctionParameter> Parameters, TypeSyntax ReturnType);
public record ModuleStruct(bool Exported, string Name, List<ModuleStructField> Fields, List<ModuleStructFunction> Functions);
public record ModuleFunctionParameter(string Name, TypeSyntax Type);
public record ModuleFunction(bool Exported, string Name, string? ExternSymbol, List<ModuleFunctionParameter> Parameters, TypeSyntax ReturnType);

View File

@@ -10,8 +10,7 @@ public class ModuleRepository
{ {
foreach (var syntaxTree in syntaxTrees) foreach (var syntaxTree in syntaxTrees)
{ {
var moduleName = syntaxTree.Metadata.ModuleName; var module = GetOrCreate(syntaxTree.Metadata.ModuleName);
var module = GetOrCreate(moduleName);
ProcessSyntaxTree(module, syntaxTree); ProcessSyntaxTree(module, syntaxTree);
} }
} }
@@ -20,47 +19,7 @@ public class ModuleRepository
{ {
foreach (var definition in syntaxTree.Definitions) foreach (var definition in syntaxTree.Definitions)
{ {
switch (definition) module.Register(definition);
{
case FuncSyntax funcDef:
{
var parameters = funcDef.Signature.Parameters
.Select(x => new ModuleFunctionParameter(x.Name, x.Type))
.ToList();
module.RegisterFunction(funcDef.Exported, funcDef.Name, funcDef.ExternSymbol, parameters, funcDef.Signature.ReturnType);
break;
}
case StructSyntax structDef:
{
var fields = structDef.Fields
.Select(x => new ModuleStructField(x.Name, x.Type, x.Value.HasValue))
.ToList();
var functions = structDef.Functions
.Select(x =>
{
var parameters = x.Signature.Parameters
.Select(y => new ModuleFunctionParameter(y.Name, y.Type))
.ToList();
return new ModuleStructFunction(x.Name, x.Hook, parameters, x.Signature.ReturnType);
})
.ToList();
module.RegisterStruct(structDef.Exported, structDef.Name, fields, functions);
break;
}
case StructTemplateSyntax structDef:
{
module.RegisterStructTemplate(structDef);
break;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(definition));
}
}
} }
} }

View File

@@ -1,82 +0,0 @@
using System.Diagnostics.CodeAnalysis;
namespace NubLang;
public static class Optional
{
public static Optional<TValue> Empty<TValue>() => new();
/// <summary>
/// Alias for creating an Optional which allows for implicit types
/// </summary>
public static Optional<TValue> OfNullable<TValue>(TValue? value)
{
return value ?? Optional<TValue>.Empty();
}
/// <summary>
/// Converts a nullable type to an Optional
/// </summary>
public static Optional<TValue> ToOptional<TValue>(this TValue? value)
{
return OfNullable(value);
}
}
public readonly struct Optional<TValue>
{
public static Optional<TValue> Empty() => new();
public static Optional<TValue> OfNullable(TValue? value)
{
return value ?? Empty();
}
public Optional()
{
Value = default;
HasValue = false;
}
public Optional(TValue value)
{
Value = value;
HasValue = true;
}
public TValue? Value { get; }
[MemberNotNullWhen(true, nameof(Value))]
public bool HasValue { get; }
[MemberNotNullWhen(true, nameof(Value))]
public bool TryGetValue([NotNullWhen(true)] out TValue? value)
{
if (HasValue)
{
value = Value;
return true;
}
value = default;
return false;
}
public TValue GetValue()
{
return Value ?? throw new InvalidOperationException("Value is not set");
}
public static implicit operator Optional<TValue>(TValue value) => new(value);
public TValue Or(TValue other)
{
if (HasValue)
{
return Value;
}
return other;
}
}

View File

@@ -206,7 +206,7 @@ public sealed class Parser
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
var fieldType = ParseType(); var fieldType = ParseType();
var fieldValue = Optional<ExpressionSyntax>.Empty(); ExpressionSyntax? fieldValue = null;
if (TryExpectSymbol(Symbol.Assign)) if (TryExpectSymbol(Symbol.Assign))
{ {
@@ -267,13 +267,13 @@ public sealed class Parser
{ {
var name = ExpectIdentifier().Value; var name = ExpectIdentifier().Value;
var explicitType = Optional<TypeSyntax>.Empty(); TypeSyntax? explicitType = null;
if (TryExpectSymbol(Symbol.Colon)) if (TryExpectSymbol(Symbol.Colon))
{ {
explicitType = ParseType(); explicitType = ParseType();
} }
var assignment = Optional<ExpressionSyntax>.Empty(); ExpressionSyntax? assignment = null;
if (TryExpectSymbol(Symbol.Assign)) if (TryExpectSymbol(Symbol.Assign))
{ {
assignment = ParseExpression(); assignment = ParseExpression();
@@ -290,7 +290,7 @@ public sealed class Parser
private ReturnSyntax ParseReturn(int startIndex) private ReturnSyntax ParseReturn(int startIndex)
{ {
var value = Optional<ExpressionSyntax>.Empty(); ExpressionSyntax? value = null;
if (!TryExpectSymbol(Symbol.Semi)) if (!TryExpectSymbol(Symbol.Semi))
{ {
@@ -305,7 +305,7 @@ public sealed class Parser
var condition = ParseExpression(); var condition = ParseExpression();
var body = ParseBlock(); var body = ParseBlock();
var elseStatement = Optional<Variant<IfSyntax, BlockSyntax>>.Empty(); Variant<IfSyntax, BlockSyntax>? elseStatement = null;
var elseStartIndex = _tokenIndex; var elseStartIndex = _tokenIndex;
if (TryExpectSymbol(Symbol.Else)) if (TryExpectSymbol(Symbol.Else))
@@ -456,7 +456,7 @@ public sealed class Parser
Symbol.Minus => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Negate, ParsePrimaryExpression()), Symbol.Minus => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Negate, ParsePrimaryExpression()),
Symbol.Bang => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Invert, ParsePrimaryExpression()), Symbol.Bang => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Invert, ParsePrimaryExpression()),
Symbol.OpenBracket => ParseArrayInitializer(startIndex), Symbol.OpenBracket => ParseArrayInitializer(startIndex),
Symbol.OpenBrace => new StructInitializerSyntax(GetTokens(startIndex), Optional<TypeSyntax>.Empty(), ParseStructInitializerBody()), Symbol.OpenBrace => new StructInitializerSyntax(GetTokens(startIndex), null, ParseStructInitializerBody()),
Symbol.Struct => ParseStructInitializer(startIndex), Symbol.Struct => ParseStructInitializer(startIndex),
Symbol.At => ParseCompilerMacro(startIndex), Symbol.At => ParseCompilerMacro(startIndex),
_ => throw new ParseException(Diagnostic _ => throw new ParseException(Diagnostic
@@ -605,7 +605,7 @@ public sealed class Parser
private StructInitializerSyntax ParseStructInitializer(int startIndex) private StructInitializerSyntax ParseStructInitializer(int startIndex)
{ {
var type = Optional.Empty<TypeSyntax>(); TypeSyntax? type = null;
if (!TryExpectSymbol(Symbol.OpenBrace)) if (!TryExpectSymbol(Symbol.OpenBrace))
{ {
type = ParseType(); type = ParseType();
@@ -921,19 +921,6 @@ public sealed class Parser
return literal; return literal;
} }
private bool TryExpectLiteral(LiteralKind kind, [NotNullWhen(true)] out LiteralToken? literal)
{
if (CurrentToken is LiteralToken identifierToken)
{
literal = identifierToken;
Next();
return true;
}
literal = null;
return false;
}
private void Next() private void Next()
{ {
_tokenIndex++; _tokenIndex++;

View File

@@ -10,7 +10,7 @@ public record FuncSignatureSyntax(List<Token> Tokens, List<FuncParameterSyntax>
public record FuncSyntax(List<Token> Tokens, string Name, bool Exported, string? ExternSymbol, FuncSignatureSyntax Signature, BlockSyntax? Body) : DefinitionSyntax(Tokens, Name, Exported); public record FuncSyntax(List<Token> Tokens, string Name, bool Exported, string? ExternSymbol, FuncSignatureSyntax Signature, BlockSyntax? Body) : DefinitionSyntax(Tokens, Name, Exported);
public record StructFieldSyntax(List<Token> Tokens, string Name, TypeSyntax Type, Optional<ExpressionSyntax> Value) : SyntaxNode(Tokens); public record StructFieldSyntax(List<Token> Tokens, string Name, TypeSyntax Type, ExpressionSyntax? Value) : SyntaxNode(Tokens);
public record StructFuncSyntax(List<Token> Tokens, string Name, string? Hook, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens); public record StructFuncSyntax(List<Token> Tokens, string Name, string? Hook, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens);

View File

@@ -54,7 +54,7 @@ public record LiteralSyntax(List<Token> Tokens, string Value, LiteralKind Kind)
public record StructFieldAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens); public record StructFieldAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens);
public record StructInitializerSyntax(List<Token> Tokens, Optional<TypeSyntax> StructType, Dictionary<string, ExpressionSyntax> Initializers) : ExpressionSyntax(Tokens); public record StructInitializerSyntax(List<Token> Tokens, TypeSyntax? StructType, Dictionary<string, ExpressionSyntax> Initializers) : ExpressionSyntax(Tokens);
public record DereferenceSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens); public record DereferenceSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);

View File

@@ -8,13 +8,13 @@ public record BlockSyntax(List<Token> Tokens, List<StatementSyntax> Statements)
public record StatementExpressionSyntax(List<Token> Tokens, ExpressionSyntax Expression) : StatementSyntax(Tokens); public record StatementExpressionSyntax(List<Token> Tokens, ExpressionSyntax Expression) : StatementSyntax(Tokens);
public record ReturnSyntax(List<Token> Tokens, Optional<ExpressionSyntax> Value) : StatementSyntax(Tokens); public record ReturnSyntax(List<Token> Tokens, ExpressionSyntax? Value) : StatementSyntax(Tokens);
public record AssignmentSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Value) : StatementSyntax(Tokens); public record AssignmentSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Value) : StatementSyntax(Tokens);
public record IfSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body, Optional<Variant<IfSyntax, BlockSyntax>> Else) : StatementSyntax(Tokens); public record IfSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body, Variant<IfSyntax, BlockSyntax>? Else) : StatementSyntax(Tokens);
public record VariableDeclarationSyntax(List<Token> Tokens, string Name, Optional<TypeSyntax> ExplicitType, Optional<ExpressionSyntax> Assignment) : StatementSyntax(Tokens); public record VariableDeclarationSyntax(List<Token> Tokens, string Name, TypeSyntax? ExplicitType, ExpressionSyntax? Assignment) : StatementSyntax(Tokens);
public record ContinueSyntax(List<Token> Tokens) : StatementSyntax(Tokens); public record ContinueSyntax(List<Token> Tokens) : StatementSyntax(Tokens);

View File

@@ -82,17 +82,18 @@ public sealed class Tokenizer
{ {
_index = 0; _index = 0;
while (Peek().TryGetValue(out var current)) while (Peek() != null)
{ {
var current = Peek()!.Value;
if (char.IsWhiteSpace(current)) if (char.IsWhiteSpace(current))
{ {
Next(); Next();
continue; continue;
} }
if (current == '/' && Peek(1).TryGetValue(out var nextChar) && nextChar == '/') if (current == '/' && Peek(1) == '/')
{ {
while (Peek().TryGetValue(out var ch) && ch != '\n') while (Peek().HasValue && Peek() != '\n')
{ {
Next(); Next();
} }
@@ -106,9 +107,9 @@ public sealed class Tokenizer
{ {
var buffer = string.Empty; var buffer = string.Empty;
while (Peek().TryGetValue(out var next) && (char.IsLetterOrDigit(next) || next == '_')) while (Peek() != null && (char.IsLetterOrDigit(Peek()!.Value) || Peek() == '_'))
{ {
buffer += next; buffer += Peek();
Next(); Next();
} }
@@ -133,8 +134,9 @@ public sealed class Tokenizer
var isFloat = false; var isFloat = false;
var buffer = string.Empty; var buffer = string.Empty;
while (Peek().TryGetValue(out var next)) while (Peek() != null)
{ {
var next = Peek()!.Value;
if (next == '.') if (next == '.')
{ {
if (isFloat) if (isFloat)
@@ -168,11 +170,12 @@ public sealed class Tokenizer
while (true) while (true)
{ {
if (!Peek().TryGetValue(out var next)) if (Peek() == null)
{ {
throw new Exception("Unclosed string literal"); throw new Exception("Unclosed string literal");
} }
var next = Peek()!.Value;
if (next == '"') if (next == '"')
{ {
Next(); Next();
@@ -224,14 +227,14 @@ public sealed class Tokenizer
} }
} }
private Optional<char> Peek(int offset = 0) private char? Peek(int offset = 0)
{ {
if (_index + offset < _sourceFile.GetText().Length) if (_index + offset < _sourceFile.GetText().Length)
{ {
return _sourceFile.GetText()[_index + offset]; return _sourceFile.GetText()[_index + offset];
} }
return Optional<char>.Empty(); return null;
} }
private void Next() private void Next()

View File

@@ -8,7 +8,7 @@ public record FuncSignatureNode(List<FuncParameterNode> Parameters, NubType Retu
public record FuncNode(string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name); public record FuncNode(string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name);
public record StructFieldNode(string Name, NubType Type, Optional<ExpressionNode> Value) : Node; public record StructFieldNode(string Name, NubType Type, ExpressionNode? Value) : Node;
public record StructFuncNode(string Name, string? Hook, FuncSignatureNode Signature, BlockNode Body) : Node; public record StructFuncNode(string Name, string? Hook, FuncSignatureNode Signature, BlockNode Body) : Node;

View File

@@ -10,13 +10,13 @@ public record StatementFuncCallNode(FuncCallNode FuncCall) : StatementNode;
public record StatementStructFuncCallNode(StructFuncCallNode StructFuncCall) : StatementNode; public record StatementStructFuncCallNode(StructFuncCallNode StructFuncCall) : StatementNode;
public record ReturnNode(Optional<ExpressionNode> Value) : TerminalStatementNode; public record ReturnNode(ExpressionNode? Value) : TerminalStatementNode;
public record AssignmentNode(LValueExpressionNode Target, ExpressionNode Value) : StatementNode; public record AssignmentNode(LValueExpressionNode Target, ExpressionNode Value) : StatementNode;
public record IfNode(ExpressionNode Condition, BlockNode Body, Optional<Variant<IfNode, BlockNode>> Else) : StatementNode; public record IfNode(ExpressionNode Condition, BlockNode Body, Variant<IfNode, BlockNode>? Else) : StatementNode;
public record VariableDeclarationNode(string Name, Optional<ExpressionNode> Assignment, NubType Type) : StatementNode; public record VariableDeclarationNode(string Name, ExpressionNode? Assignment, NubType Type) : StatementNode;
public record ContinueNode : TerminalStatementNode; public record ContinueNode : TerminalStatementNode;

View File

@@ -87,7 +87,7 @@ public sealed class TypeChecker
private StructNode CheckStructDefinition(StructSyntax node) private StructNode CheckStructDefinition(StructSyntax node)
{ {
var fieldTypes = node.Fields var fieldTypes = node.Fields
.Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value.HasValue)) .Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value != null))
.ToList(); .ToList();
var fieldFunctions = node.Functions var fieldFunctions = node.Functions
@@ -132,10 +132,10 @@ public sealed class TypeChecker
private StructFieldNode CheckStructField(StructFieldSyntax field) private StructFieldNode CheckStructField(StructFieldSyntax field)
{ {
var value = Optional.Empty<ExpressionNode>(); ExpressionNode? value = null;
if (field.Value.HasValue) if (field.Value != null)
{ {
value = CheckExpression(field.Value.Value, ResolveType(field.Type)); value = CheckExpression(field.Value, ResolveType(field.Type));
} }
return new StructFieldNode(field.Name, ResolveType(field.Type), value); return new StructFieldNode(field.Name, ResolveType(field.Type), value);
@@ -161,13 +161,13 @@ public sealed class TypeChecker
{ {
if (signature.ReturnType is NubVoidType) if (signature.ReturnType is NubVoidType)
{ {
body.Statements.Add(new ReturnNode(Optional<ExpressionNode>.Empty())); body.Statements.Add(new ReturnNode(null));
} }
else else
{ {
Diagnostics.Add(Diagnostic Diagnostics.Add(Diagnostic
.Error("Not all code paths return a value") .Error("Not all code paths return a value")
.At(node.Body.Tokens.LastOrDefault()) .At(node.Body)
.Build()); .Build());
} }
} }
@@ -194,10 +194,10 @@ public sealed class TypeChecker
{ {
var condition = CheckExpression(statement.Condition, new NubBoolType()); var condition = CheckExpression(statement.Condition, new NubBoolType());
var body = CheckBlock(statement.Body); var body = CheckBlock(statement.Body);
var elseStatement = Optional.Empty<Variant<IfNode, BlockNode>>(); Variant<IfNode, BlockNode>? elseStatement = null;
if (statement.Else.TryGetValue(out var elseSyntax)) if (statement.Else.HasValue)
{ {
elseStatement = elseSyntax.Match<Variant<IfNode, BlockNode>>(elif => CheckIf(elif), el => CheckBlock(el)); elseStatement = statement.Else.Value.Match<Variant<IfNode, BlockNode>>(elif => CheckIf(elif), el => CheckBlock(el));
} }
return new IfNode(condition, body, elseStatement); return new IfNode(condition, body, elseStatement);
@@ -205,11 +205,11 @@ public sealed class TypeChecker
private ReturnNode CheckReturn(ReturnSyntax statement) private ReturnNode CheckReturn(ReturnSyntax statement)
{ {
var value = Optional.Empty<ExpressionNode>(); ExpressionNode? value = null;
if (statement.Value.TryGetValue(out var valueExpression)) if (statement.Value != null)
{ {
value = CheckExpression(valueExpression, _funcReturnTypes.Peek()); value = CheckExpression(statement.Value, _funcReturnTypes.Peek());
} }
return new ReturnNode(value); return new ReturnNode(value);
@@ -232,14 +232,14 @@ public sealed class TypeChecker
NubType? type = null; NubType? type = null;
ExpressionNode? assignmentNode = null; ExpressionNode? assignmentNode = null;
if (statement.ExplicitType.TryGetValue(out var explicitType)) if (statement.ExplicitType != null)
{ {
type = ResolveType(explicitType); type = ResolveType(statement.ExplicitType);
} }
if (statement.Assignment.TryGetValue(out var assignment)) if (statement.Assignment != null)
{ {
assignmentNode = CheckExpression(assignment, type); assignmentNode = CheckExpression(statement.Assignment, type);
type ??= assignmentNode.Type; type ??= assignmentNode.Type;
} }
@@ -250,7 +250,7 @@ public sealed class TypeChecker
CurrentScope.DeclareVariable(new Variable(statement.Name, type, VariableKind.LValue)); CurrentScope.DeclareVariable(new Variable(statement.Name, type, VariableKind.LValue));
return new VariableDeclarationNode(statement.Name, Optional.OfNullable(assignmentNode), type); return new VariableDeclarationNode(statement.Name, assignmentNode, type);
} }
private WhileNode CheckWhile(WhileSyntax statement) private WhileNode CheckWhile(WhileSyntax statement)
@@ -593,8 +593,8 @@ public sealed class TypeChecker
if (function != null) if (function != null)
{ {
var parameters = function.Parameters.Select(x => ResolveType(x.Type)).ToList(); var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
var type = new NubFuncType(parameters, ResolveType(function.ReturnType)); var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
return new FuncIdentifierNode(type, CurrentModule, expression.Name, function.ExternSymbol); return new FuncIdentifierNode(type, CurrentModule, expression.Name, function.ExternSymbol);
} }
@@ -618,8 +618,8 @@ public sealed class TypeChecker
var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name); var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
if (function != null) if (function != null)
{ {
var parameters = function.Parameters.Select(x => ResolveType(x.Type)).ToList(); var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
var type = new NubFuncType(parameters, ResolveType(function.ReturnType)); var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
return new FuncIdentifierNode(type, expression.Module, expression.Name, function.ExternSymbol); return new FuncIdentifierNode(type, expression.Module, expression.Name, function.ExternSymbol);
} }
@@ -695,9 +695,9 @@ public sealed class TypeChecker
{ {
NubStructType? structType = null; NubStructType? structType = null;
if (expression.StructType.TryGetValue(out var customType)) if (expression.StructType != null)
{ {
var checkedType = ResolveType(customType); var checkedType = ResolveType(expression.StructType);
if (checkedType is not NubStructType checkedStructType) if (checkedType is not NubStructType checkedStructType)
{ {
throw new UnreachableException("Parser fucked up"); throw new UnreachableException("Parser fucked up");
@@ -823,7 +823,7 @@ public sealed class TypeChecker
return false; return false;
} }
return !ifNode.Else.TryGetValue(out var elseStatement) || elseStatement.Match(AlwaysReturns, AlwaysReturns); return !ifNode.Else.HasValue || ifNode.Else.Value.Match(AlwaysReturns, AlwaysReturns);
} }
default: default:
return false; return false;
@@ -878,20 +878,30 @@ public sealed class TypeChecker
var includePrivate = customType.Module == CurrentModule; var includePrivate = customType.Module == CurrentModule;
var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); var strctDef = module.Structs(includePrivate).FirstOrDefault(x => x.Name == customType.Name);
if (structType != null) if (strctDef != null)
{ {
var result = new NubStructType(customType.Module, structType.Name, [], []); var result = new NubStructType(customType.Module, strctDef.Name, [], []);
_typeCache[key] = result; _typeCache[key] = result;
var fields = structType.Fields.Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.HasDefaultValue)).ToList(); var fields = strctDef.Fields
.Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value != null))
.ToList();
result.Fields.AddRange(fields); result.Fields.AddRange(fields);
foreach (var function in structType.Functions) var functions = strctDef.Functions
.Select(x =>
{ {
var parameters = function.Parameters.Select(x => ResolveType(x.Type)).ToList(); var parameters = x.Signature.Parameters
result.Functions.Add(new NubStructFuncType(function.Name, function.Hook, parameters, ResolveType(function.ReturnType))); .Select(y => ResolveType(y.Type))
} .ToList();
return new NubStructFuncType(x.Name, x.Hook, parameters, ResolveType(x.Signature.ReturnType));
})
.ToList();
result.Functions.AddRange(functions);
ReferencedStructTypes.Add(result); ReferencedStructTypes.Add(result);
return result; return result;