...
This commit is contained in:
@@ -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>();
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
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++;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace NubLang.Parsing.Syntax;
|
|||||||
|
|
||||||
public abstract record TypeSyntax(List<Token> Tokens) : SyntaxNode(Tokens);
|
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);
|
public record PointerTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
{
|
||||||
result.Functions.Add(new NubStructFuncType(function.Name, function.Hook, parameters, ResolveType(function.ReturnType)));
|
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);
|
ReferencedStructTypes.Add(result);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user