...
This commit is contained in:
@@ -372,12 +372,12 @@ public class QBEGenerator
|
||||
|
||||
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 destination = TmpName();
|
||||
_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)
|
||||
{
|
||||
if (@return.Value.HasValue)
|
||||
if (@return.Value != null)
|
||||
{
|
||||
var result = EmitExpression(@return.Value.Value);
|
||||
var result = EmitExpression(@return.Value);
|
||||
EmitScopeCleanup();
|
||||
_writer.Indented($"ret {result}");
|
||||
}
|
||||
@@ -584,9 +584,9 @@ public class QBEGenerator
|
||||
var name = $"%{variableDeclaration.Name}";
|
||||
_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));
|
||||
@@ -1234,7 +1234,7 @@ public class QBEGenerator
|
||||
private NubStructType TypeOfStruct(StructNode definition)
|
||||
{
|
||||
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();
|
||||
|
||||
var functionTypes = new List<NubStructFuncType>();
|
||||
|
||||
@@ -4,42 +4,34 @@ namespace NubLang.Modules;
|
||||
|
||||
public class Module
|
||||
{
|
||||
private readonly List<ModuleStruct> _structs = [];
|
||||
private readonly List<StructTemplateSyntax> _structTemplates = [];
|
||||
private readonly List<ModuleFunction> _functions = [];
|
||||
private readonly List<DefinitionSyntax> _definitions = [];
|
||||
|
||||
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)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<ModuleFunction> Functions(bool includePrivate)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -10,8 +10,7 @@ public class ModuleRepository
|
||||
{
|
||||
foreach (var syntaxTree in syntaxTrees)
|
||||
{
|
||||
var moduleName = syntaxTree.Metadata.ModuleName;
|
||||
var module = GetOrCreate(moduleName);
|
||||
var module = GetOrCreate(syntaxTree.Metadata.ModuleName);
|
||||
ProcessSyntaxTree(module, syntaxTree);
|
||||
}
|
||||
}
|
||||
@@ -20,47 +19,7 @@ public class ModuleRepository
|
||||
{
|
||||
foreach (var definition in syntaxTree.Definitions)
|
||||
{
|
||||
switch (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));
|
||||
}
|
||||
}
|
||||
module.Register(definition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ public sealed class Parser
|
||||
ExpectSymbol(Symbol.Colon);
|
||||
var fieldType = ParseType();
|
||||
|
||||
var fieldValue = Optional<ExpressionSyntax>.Empty();
|
||||
ExpressionSyntax? fieldValue = null;
|
||||
|
||||
if (TryExpectSymbol(Symbol.Assign))
|
||||
{
|
||||
@@ -267,13 +267,13 @@ public sealed class Parser
|
||||
{
|
||||
var name = ExpectIdentifier().Value;
|
||||
|
||||
var explicitType = Optional<TypeSyntax>.Empty();
|
||||
TypeSyntax? explicitType = null;
|
||||
if (TryExpectSymbol(Symbol.Colon))
|
||||
{
|
||||
explicitType = ParseType();
|
||||
}
|
||||
|
||||
var assignment = Optional<ExpressionSyntax>.Empty();
|
||||
ExpressionSyntax? assignment = null;
|
||||
if (TryExpectSymbol(Symbol.Assign))
|
||||
{
|
||||
assignment = ParseExpression();
|
||||
@@ -290,7 +290,7 @@ public sealed class Parser
|
||||
|
||||
private ReturnSyntax ParseReturn(int startIndex)
|
||||
{
|
||||
var value = Optional<ExpressionSyntax>.Empty();
|
||||
ExpressionSyntax? value = null;
|
||||
|
||||
if (!TryExpectSymbol(Symbol.Semi))
|
||||
{
|
||||
@@ -305,7 +305,7 @@ public sealed class Parser
|
||||
var condition = ParseExpression();
|
||||
var body = ParseBlock();
|
||||
|
||||
var elseStatement = Optional<Variant<IfSyntax, BlockSyntax>>.Empty();
|
||||
Variant<IfSyntax, BlockSyntax>? elseStatement = null;
|
||||
|
||||
var elseStartIndex = _tokenIndex;
|
||||
if (TryExpectSymbol(Symbol.Else))
|
||||
@@ -456,7 +456,7 @@ public sealed class Parser
|
||||
Symbol.Minus => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Negate, ParsePrimaryExpression()),
|
||||
Symbol.Bang => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Invert, ParsePrimaryExpression()),
|
||||
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.At => ParseCompilerMacro(startIndex),
|
||||
_ => throw new ParseException(Diagnostic
|
||||
@@ -605,7 +605,7 @@ public sealed class Parser
|
||||
|
||||
private StructInitializerSyntax ParseStructInitializer(int startIndex)
|
||||
{
|
||||
var type = Optional.Empty<TypeSyntax>();
|
||||
TypeSyntax? type = null;
|
||||
if (!TryExpectSymbol(Symbol.OpenBrace))
|
||||
{
|
||||
type = ParseType();
|
||||
@@ -921,19 +921,6 @@ public sealed class Parser
|
||||
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()
|
||||
{
|
||||
_tokenIndex++;
|
||||
|
||||
@@ -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 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);
|
||||
|
||||
|
||||
@@ -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 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);
|
||||
|
||||
|
||||
@@ -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 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 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);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace NubLang.Parsing.Syntax;
|
||||
|
||||
public abstract record TypeSyntax(List<Token> Tokens) : SyntaxNode(Tokens);
|
||||
|
||||
public record FuncTypeSyntax(List<Token> Tokens, List<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);
|
||||
public record FuncTypeSyntax(List<Token> Tokens, List<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);
|
||||
|
||||
public record PointerTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
||||
|
||||
|
||||
@@ -82,17 +82,18 @@ public sealed class Tokenizer
|
||||
{
|
||||
_index = 0;
|
||||
|
||||
while (Peek().TryGetValue(out var current))
|
||||
while (Peek() != null)
|
||||
{
|
||||
var current = Peek()!.Value;
|
||||
if (char.IsWhiteSpace(current))
|
||||
{
|
||||
Next();
|
||||
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();
|
||||
}
|
||||
@@ -106,9 +107,9 @@ public sealed class Tokenizer
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -133,8 +134,9 @@ public sealed class Tokenizer
|
||||
var isFloat = false;
|
||||
var buffer = string.Empty;
|
||||
|
||||
while (Peek().TryGetValue(out var next))
|
||||
while (Peek() != null)
|
||||
{
|
||||
var next = Peek()!.Value;
|
||||
if (next == '.')
|
||||
{
|
||||
if (isFloat)
|
||||
@@ -168,11 +170,12 @@ public sealed class Tokenizer
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!Peek().TryGetValue(out var next))
|
||||
if (Peek() == null)
|
||||
{
|
||||
throw new Exception("Unclosed string literal");
|
||||
}
|
||||
|
||||
|
||||
var next = Peek()!.Value;
|
||||
if (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)
|
||||
{
|
||||
return _sourceFile.GetText()[_index + offset];
|
||||
}
|
||||
|
||||
return Optional<char>.Empty();
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Next()
|
||||
|
||||
@@ -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 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;
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ public record StatementFuncCallNode(FuncCallNode FuncCall) : 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 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;
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public sealed class TypeChecker
|
||||
private StructNode CheckStructDefinition(StructSyntax node)
|
||||
{
|
||||
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();
|
||||
|
||||
var fieldFunctions = node.Functions
|
||||
@@ -132,10 +132,10 @@ public sealed class TypeChecker
|
||||
|
||||
private StructFieldNode CheckStructField(StructFieldSyntax field)
|
||||
{
|
||||
var value = Optional.Empty<ExpressionNode>();
|
||||
if (field.Value.HasValue)
|
||||
ExpressionNode? value = null;
|
||||
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);
|
||||
@@ -161,13 +161,13 @@ public sealed class TypeChecker
|
||||
{
|
||||
if (signature.ReturnType is NubVoidType)
|
||||
{
|
||||
body.Statements.Add(new ReturnNode(Optional<ExpressionNode>.Empty()));
|
||||
body.Statements.Add(new ReturnNode(null));
|
||||
}
|
||||
else
|
||||
{
|
||||
Diagnostics.Add(Diagnostic
|
||||
.Error("Not all code paths return a value")
|
||||
.At(node.Body.Tokens.LastOrDefault())
|
||||
.At(node.Body)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
@@ -194,10 +194,10 @@ public sealed class TypeChecker
|
||||
{
|
||||
var condition = CheckExpression(statement.Condition, new NubBoolType());
|
||||
var body = CheckBlock(statement.Body);
|
||||
var elseStatement = Optional.Empty<Variant<IfNode, BlockNode>>();
|
||||
if (statement.Else.TryGetValue(out var elseSyntax))
|
||||
Variant<IfNode, BlockNode>? elseStatement = null;
|
||||
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);
|
||||
@@ -205,11 +205,11 @@ public sealed class TypeChecker
|
||||
|
||||
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);
|
||||
@@ -232,14 +232,14 @@ public sealed class TypeChecker
|
||||
NubType? type = 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;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ public sealed class TypeChecker
|
||||
|
||||
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)
|
||||
@@ -593,8 +593,8 @@ public sealed class TypeChecker
|
||||
|
||||
if (function != null)
|
||||
{
|
||||
var parameters = function.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.ReturnType));
|
||||
var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
|
||||
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);
|
||||
if (function != null)
|
||||
{
|
||||
var parameters = function.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.ReturnType));
|
||||
var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
|
||||
return new FuncIdentifierNode(type, expression.Module, expression.Name, function.ExternSymbol);
|
||||
}
|
||||
|
||||
@@ -695,9 +695,9 @@ public sealed class TypeChecker
|
||||
{
|
||||
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)
|
||||
{
|
||||
throw new UnreachableException("Parser fucked up");
|
||||
@@ -823,7 +823,7 @@ public sealed class TypeChecker
|
||||
return false;
|
||||
}
|
||||
|
||||
return !ifNode.Else.TryGetValue(out var elseStatement) || elseStatement.Match(AlwaysReturns, AlwaysReturns);
|
||||
return !ifNode.Else.HasValue || ifNode.Else.Value.Match(AlwaysReturns, AlwaysReturns);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
@@ -878,20 +878,30 @@ public sealed class TypeChecker
|
||||
|
||||
var includePrivate = customType.Module == CurrentModule;
|
||||
|
||||
var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name);
|
||||
if (structType != null)
|
||||
var strctDef = module.Structs(includePrivate).FirstOrDefault(x => x.Name == customType.Name);
|
||||
if (strctDef != null)
|
||||
{
|
||||
var result = new NubStructType(customType.Module, structType.Name, [], []);
|
||||
var result = new NubStructType(customType.Module, strctDef.Name, [], []);
|
||||
_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);
|
||||
|
||||
foreach (var function in structType.Functions)
|
||||
{
|
||||
var parameters = function.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
result.Functions.Add(new NubStructFuncType(function.Name, function.Hook, parameters, ResolveType(function.ReturnType)));
|
||||
}
|
||||
var functions = strctDef.Functions
|
||||
.Select(x =>
|
||||
{
|
||||
var parameters = x.Signature.Parameters
|
||||
.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);
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user