...
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
using NubLang.Code;
|
||||||
|
|
||||||
namespace NubLang.CLI;
|
namespace NubLang.CLI;
|
||||||
|
|
||||||
public class Options
|
public class Options
|
||||||
@@ -5,5 +7,5 @@ public class Options
|
|||||||
public string? CustomRuntime { get; set; }
|
public string? CustomRuntime { get; set; }
|
||||||
public string? OutputPath { get; set; }
|
public string? OutputPath { get; set; }
|
||||||
public bool Link { get; set; } = true;
|
public bool Link { get; set; } = true;
|
||||||
public List<string> Files { get; } = [];
|
public List<SourceFile> Files { get; } = [];
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using NubLang.CLI;
|
using NubLang.CLI;
|
||||||
using NubLang;
|
using NubLang.Code;
|
||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Generation;
|
using NubLang.Generation;
|
||||||
@@ -62,16 +62,16 @@ for (var i = 0; i < args.Length; i++)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
options.Files.Add(arg);
|
options.Files.Add(new SourceFile(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var diagnostics = new List<Diagnostic>();
|
var diagnostics = new List<Diagnostic>();
|
||||||
var syntaxTrees = new Dictionary<string, SyntaxTree>();
|
var syntaxTrees = new List<SyntaxTree>();
|
||||||
|
|
||||||
foreach (var file in options.Files)
|
foreach (var file in options.Files)
|
||||||
{
|
{
|
||||||
if (!File.Exists(file))
|
if (!File.Exists(file.Path))
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine($"File '{file}' does not exist");
|
Console.Error.WriteLine($"File '{file}' does not exist");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -80,30 +80,27 @@ foreach (var file in options.Files)
|
|||||||
|
|
||||||
foreach (var file in options.Files)
|
foreach (var file in options.Files)
|
||||||
{
|
{
|
||||||
var content = File.ReadAllText(file);
|
var tokenizer = new Tokenizer(file.GetText());
|
||||||
var sourceText = new SourceText(file, content);
|
|
||||||
|
|
||||||
var tokenizer = new Tokenizer(sourceText);
|
|
||||||
var tokenizeResult = tokenizer.Tokenize(out var tokenizerDiagnostics);
|
var tokenizeResult = tokenizer.Tokenize(out var tokenizerDiagnostics);
|
||||||
diagnostics.AddRange(tokenizerDiagnostics);
|
diagnostics.AddRange(tokenizerDiagnostics);
|
||||||
|
|
||||||
var parser = new Parser(tokenizeResult);
|
var parser = new Parser(tokenizeResult);
|
||||||
var syntaxTree = parser.Parse();
|
var syntaxTree = parser.Parse(out var parserDiagnostics);
|
||||||
diagnostics.AddRange(syntaxTree.Diagnostics);
|
diagnostics.AddRange(parserDiagnostics);
|
||||||
|
|
||||||
syntaxTrees[file] = syntaxTree;
|
syntaxTrees.Add(syntaxTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
var definitionTable = new DefinitionTable(syntaxTrees.Values);
|
var definitionTable = new DefinitionTable(syntaxTrees);
|
||||||
|
|
||||||
var boundSyntaxTrees = new Dictionary<string, BoundSyntaxTree>();
|
var boundSyntaxTrees = new List<BoundSyntaxTree>();
|
||||||
|
|
||||||
foreach (var (file, syntaxTree) in syntaxTrees)
|
foreach (var syntaxTree in syntaxTrees)
|
||||||
{
|
{
|
||||||
var binder = new Binder(syntaxTree, definitionTable);
|
var binder = new Binder(syntaxTree, definitionTable);
|
||||||
var boundSyntaxTree = binder.Bind();
|
var boundSyntaxTree = binder.Bind();
|
||||||
diagnostics.AddRange(boundSyntaxTree.Diagnostics);
|
diagnostics.AddRange(boundSyntaxTree.Diagnostics);
|
||||||
boundSyntaxTrees[file] = boundSyntaxTree;
|
boundSyntaxTrees.Add(boundSyntaxTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var diagnostic in diagnostics)
|
foreach (var diagnostic in diagnostics)
|
||||||
@@ -116,15 +113,15 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees.Values);
|
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees);
|
||||||
|
|
||||||
var objectFiles = new List<string>();
|
var objectFiles = new List<string>();
|
||||||
|
|
||||||
foreach (var file in options.Files)
|
foreach (var syntaxTree in boundSyntaxTrees)
|
||||||
{
|
{
|
||||||
var outFileName = $"{HexString.CreateUnique(8)}_{Path.GetFileNameWithoutExtension(file)}";
|
var outFileName = HexString.CreateUnique(8);
|
||||||
|
|
||||||
var generator = new QBEGenerator(boundSyntaxTrees[file], boundDefinitionTable, file);
|
var generator = new QBEGenerator(syntaxTree, boundDefinitionTable);
|
||||||
var ssa = generator.Emit();
|
var ssa = generator.Emit();
|
||||||
File.WriteAllText(Path.Join(INT_DEBUG_DIR, $"{outFileName}.ssa"), ssa);
|
File.WriteAllText(Path.Join(INT_DEBUG_DIR, $"{outFileName}.ssa"), ssa);
|
||||||
|
|
||||||
|
|||||||
29
src/compiler/NubLang/Code/SourceFile.cs
Normal file
29
src/compiler/NubLang/Code/SourceFile.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace NubLang.Code;
|
||||||
|
|
||||||
|
public class SourceFile
|
||||||
|
{
|
||||||
|
private string? _content;
|
||||||
|
|
||||||
|
public SourceFile(string path)
|
||||||
|
{
|
||||||
|
Path = path ?? throw new ArgumentNullException(nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path { get; }
|
||||||
|
|
||||||
|
public string GetText() => _content ??= File.ReadAllText(Path);
|
||||||
|
public override string ToString() => Path;
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is SourceFile other && other.Path == Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(typeof(SourceFile), Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(SourceFile? left, SourceFile? right) => Equals(left, right);
|
||||||
|
public static bool operator !=(SourceFile? left, SourceFile? right) => !Equals(left, right);
|
||||||
|
}
|
||||||
53
src/compiler/NubLang/Code/SourceLocation.cs
Normal file
53
src/compiler/NubLang/Code/SourceLocation.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
namespace NubLang.Code;
|
||||||
|
|
||||||
|
public readonly struct SourceLocation : IEquatable<SourceLocation>
|
||||||
|
{
|
||||||
|
public static SourceLocation Zero => new(0, 0);
|
||||||
|
|
||||||
|
public SourceLocation(int line, int column)
|
||||||
|
{
|
||||||
|
Line = line;
|
||||||
|
Column = column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Line { get; }
|
||||||
|
public int Column { get; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Line}:{Column}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(SourceLocation other)
|
||||||
|
{
|
||||||
|
var lineComparison = Line.CompareTo(other.Line);
|
||||||
|
if (lineComparison == 0)
|
||||||
|
{
|
||||||
|
return Column.CompareTo(other.Column);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lineComparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is SourceLocation other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(SourceLocation other)
|
||||||
|
{
|
||||||
|
return Line == other.Line && Column == other.Column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(typeof(SourceLocation), Line, Column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(SourceLocation left, SourceLocation right) => Equals(left, right);
|
||||||
|
public static bool operator !=(SourceLocation left, SourceLocation right) => !Equals(left, right);
|
||||||
|
public static bool operator <(SourceLocation left, SourceLocation right) => left.Line < right.Line || (left.Line == right.Line && left.Column < right.Column);
|
||||||
|
public static bool operator >(SourceLocation left, SourceLocation right) => left.Line > right.Line || (left.Line == right.Line && left.Column > right.Column);
|
||||||
|
public static bool operator <=(SourceLocation left, SourceLocation right) => left.Line <= right.Line || (left.Line == right.Line && left.Column <= right.Column);
|
||||||
|
public static bool operator >=(SourceLocation left, SourceLocation right) => left.Line >= right.Line || (left.Line == right.Line && left.Column >= right.Column);
|
||||||
|
}
|
||||||
57
src/compiler/NubLang/Code/SourceSpan.cs
Normal file
57
src/compiler/NubLang/Code/SourceSpan.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
namespace NubLang.Code;
|
||||||
|
|
||||||
|
public readonly struct SourceSpan : IEquatable<SourceSpan>
|
||||||
|
{
|
||||||
|
public static SourceSpan Zero => new(SourceLocation.Zero, SourceLocation.Zero);
|
||||||
|
|
||||||
|
public static SourceSpan Merge(params IEnumerable<SourceSpan> spans)
|
||||||
|
{
|
||||||
|
var spanArray = spans as SourceSpan[] ?? spans.ToArray();
|
||||||
|
|
||||||
|
if (spanArray.Length == 0)
|
||||||
|
{
|
||||||
|
return Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
var minStart = spanArray.Min(s => s.Start);
|
||||||
|
var maxEnd = spanArray.Max(s => s.End);
|
||||||
|
|
||||||
|
return new SourceSpan(minStart, maxEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceSpan(SourceLocation start, SourceLocation end)
|
||||||
|
{
|
||||||
|
if (start > end)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Start location cannot be after end location");
|
||||||
|
}
|
||||||
|
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceLocation Start { get; }
|
||||||
|
public SourceLocation End { get; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (Start == End)
|
||||||
|
{
|
||||||
|
return $"{Start}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Start.Line == End.Line)
|
||||||
|
{
|
||||||
|
return Start.Column == End.Column ? $"{Start}" : $"{Start.Line}:{Start.Column}-{End.Column}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{Start}-{End}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(SourceSpan other) => Start == other.Start && End == other.End;
|
||||||
|
public override bool Equals(object? obj) => obj is SourceSpan other && Equals(other);
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(SourceSpan), Start, End);
|
||||||
|
|
||||||
|
public static bool operator ==(SourceSpan left, SourceSpan right) => Equals(left, right);
|
||||||
|
public static bool operator !=(SourceSpan left, SourceSpan right) => !Equals(left, right);
|
||||||
|
}
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
using System.Text;
|
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Diagnostics;
|
namespace NubLang.Diagnostics;
|
||||||
|
|
||||||
public static class ConsoleColors
|
public static class ConsoleColors
|
||||||
@@ -56,118 +53,4 @@ public static class ConsoleColors
|
|||||||
{
|
{
|
||||||
return IsColorSupported() ? $"{color}{text}{Reset}" : text;
|
return IsColorSupported() ? $"{color}{text}{Reset}" : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetTokenColor(Token token)
|
|
||||||
{
|
|
||||||
switch (token)
|
|
||||||
{
|
|
||||||
case IdentifierToken:
|
|
||||||
return White;
|
|
||||||
case LiteralToken literal:
|
|
||||||
return literal.Kind switch
|
|
||||||
{
|
|
||||||
LiteralKind.String => Green,
|
|
||||||
LiteralKind.Integer or LiteralKind.Float => BrightBlue,
|
|
||||||
LiteralKind.Bool => Blue,
|
|
||||||
_ => White
|
|
||||||
};
|
|
||||||
case SymbolToken symbol:
|
|
||||||
switch (symbol.Symbol)
|
|
||||||
{
|
|
||||||
case Symbol.If:
|
|
||||||
case Symbol.Else:
|
|
||||||
case Symbol.While:
|
|
||||||
case Symbol.Break:
|
|
||||||
case Symbol.Continue:
|
|
||||||
case Symbol.Return:
|
|
||||||
return Magenta;
|
|
||||||
case Symbol.Func:
|
|
||||||
case Symbol.Struct:
|
|
||||||
case Symbol.Namespace:
|
|
||||||
case Symbol.Let:
|
|
||||||
case Symbol.Alloc:
|
|
||||||
return Blue;
|
|
||||||
case Symbol.Assign:
|
|
||||||
case Symbol.Bang:
|
|
||||||
case Symbol.Equal:
|
|
||||||
case Symbol.NotEqual:
|
|
||||||
case Symbol.LessThan:
|
|
||||||
case Symbol.LessThanOrEqual:
|
|
||||||
case Symbol.GreaterThan:
|
|
||||||
case Symbol.GreaterThanOrEqual:
|
|
||||||
case Symbol.Plus:
|
|
||||||
case Symbol.Minus:
|
|
||||||
case Symbol.Star:
|
|
||||||
case Symbol.ForwardSlash:
|
|
||||||
case Symbol.Caret:
|
|
||||||
case Symbol.Ampersand:
|
|
||||||
return White;
|
|
||||||
case Symbol.Colon:
|
|
||||||
case Symbol.Comma:
|
|
||||||
case Symbol.Period:
|
|
||||||
case Symbol.DoubleColon:
|
|
||||||
return Faint;
|
|
||||||
case Symbol.OpenParen:
|
|
||||||
case Symbol.CloseParen:
|
|
||||||
case Symbol.OpenBrace:
|
|
||||||
case Symbol.CloseBrace:
|
|
||||||
case Symbol.OpenBracket:
|
|
||||||
case Symbol.CloseBracket:
|
|
||||||
return Yellow;
|
|
||||||
default:
|
|
||||||
return White;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return White;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ColorizeSource(string source)
|
|
||||||
{
|
|
||||||
var sourceText = new SourceText(string.Empty, source);
|
|
||||||
var tokenizer = new Tokenizer(sourceText);
|
|
||||||
var tokens = tokenizer.Tokenize(out _);
|
|
||||||
var result = new StringBuilder();
|
|
||||||
var lastCharIndex = 0;
|
|
||||||
|
|
||||||
foreach (var token in tokens)
|
|
||||||
{
|
|
||||||
var tokenStartIndex = GetCharacterIndex(sourceText, token.Span.Start);
|
|
||||||
var tokenEndIndex = GetCharacterIndex(sourceText, token.Span.End);
|
|
||||||
|
|
||||||
if (tokenStartIndex > lastCharIndex)
|
|
||||||
{
|
|
||||||
var between = sourceText.Content.Substring(lastCharIndex, tokenStartIndex - lastCharIndex);
|
|
||||||
result.Append(between);
|
|
||||||
}
|
|
||||||
|
|
||||||
var tokenText = sourceText.Content.Substring(tokenStartIndex, tokenEndIndex - tokenStartIndex);
|
|
||||||
|
|
||||||
result.Append(Colorize(tokenText, GetTokenColor(token)));
|
|
||||||
lastCharIndex = tokenEndIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastCharIndex < sourceText.Content.Length)
|
|
||||||
{
|
|
||||||
var remaining = sourceText.Content[lastCharIndex..];
|
|
||||||
result.Append(Colorize(remaining, Faint));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetCharacterIndex(SourceText sourceText, SourceLocation location)
|
|
||||||
{
|
|
||||||
var lines = sourceText.Content.Split('\n');
|
|
||||||
var index = 0;
|
|
||||||
|
|
||||||
for (var i = 0; i < location.Line - 1 && i < lines.Length; i++)
|
|
||||||
{
|
|
||||||
index += lines[i].Length + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
index += location.Column - 1;
|
|
||||||
|
|
||||||
return Math.Min(index, sourceText.Content.Length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using NubLang.Syntax.Parsing.Node;
|
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Diagnostics;
|
namespace NubLang.Diagnostics;
|
||||||
|
|
||||||
@@ -11,7 +9,6 @@ public class Diagnostic
|
|||||||
private readonly DiagnosticSeverity _severity;
|
private readonly DiagnosticSeverity _severity;
|
||||||
private readonly string _message;
|
private readonly string _message;
|
||||||
private string? _help;
|
private string? _help;
|
||||||
private SourceSpan? _sourceSpan;
|
|
||||||
|
|
||||||
public DiagnosticBuilder(DiagnosticSeverity severity, string message)
|
public DiagnosticBuilder(DiagnosticSeverity severity, string message)
|
||||||
{
|
{
|
||||||
@@ -19,31 +16,13 @@ public class Diagnostic
|
|||||||
_message = message;
|
_message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiagnosticBuilder At(Token token)
|
|
||||||
{
|
|
||||||
_sourceSpan = token.Span;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiagnosticBuilder At(SyntaxNode node)
|
|
||||||
{
|
|
||||||
_sourceSpan = SourceSpan.Merge(node.Tokens.Select(t => t.Span));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiagnosticBuilder At(SourceSpan span)
|
|
||||||
{
|
|
||||||
_sourceSpan = span;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiagnosticBuilder WithHelp(string help)
|
public DiagnosticBuilder WithHelp(string help)
|
||||||
{
|
{
|
||||||
_help = help;
|
_help = help;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Diagnostic Build() => new(_severity, _message, _sourceSpan, _help);
|
public Diagnostic Build() => new(_severity, _message, _help);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DiagnosticBuilder Error(string message) => new(DiagnosticSeverity.Error, message);
|
public static DiagnosticBuilder Error(string message) => new(DiagnosticSeverity.Error, message);
|
||||||
@@ -52,14 +31,12 @@ public class Diagnostic
|
|||||||
|
|
||||||
public DiagnosticSeverity Severity { get; }
|
public DiagnosticSeverity Severity { get; }
|
||||||
public string Message { get; }
|
public string Message { get; }
|
||||||
public SourceSpan? Span { get; }
|
|
||||||
public string? Help { get; }
|
public string? Help { get; }
|
||||||
|
|
||||||
private Diagnostic(DiagnosticSeverity severity, string message, SourceSpan? span, string? help)
|
private Diagnostic(DiagnosticSeverity severity, string message, string? help)
|
||||||
{
|
{
|
||||||
Severity = severity;
|
Severity = severity;
|
||||||
Message = message;
|
Message = message;
|
||||||
Span = span;
|
|
||||||
Help = help;
|
Help = help;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,21 +47,9 @@ public class Diagnostic
|
|||||||
var severityText = GetSeverityText(Severity);
|
var severityText = GetSeverityText(Severity);
|
||||||
sb.Append(severityText);
|
sb.Append(severityText);
|
||||||
|
|
||||||
if (Span.HasValue)
|
|
||||||
{
|
|
||||||
var locationText = $" at {Span.Value.Text.Path}:{Span}";
|
|
||||||
sb.Append(ConsoleColors.Colorize(locationText, ConsoleColors.Faint));
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Append(": ");
|
sb.Append(": ");
|
||||||
sb.Append(ConsoleColors.Colorize(Message, ConsoleColors.BrightWhite));
|
sb.Append(ConsoleColors.Colorize(Message, ConsoleColors.BrightWhite));
|
||||||
|
|
||||||
if (Span.HasValue)
|
|
||||||
{
|
|
||||||
sb.AppendLine();
|
|
||||||
AppendSourceContext(sb, Span.Value, Severity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Help))
|
if (!string.IsNullOrEmpty(Help))
|
||||||
{
|
{
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
@@ -104,107 +69,6 @@ public class Diagnostic
|
|||||||
_ => throw new ArgumentOutOfRangeException(nameof(severity), severity, "Unknown diagnostic severity")
|
_ => throw new ArgumentOutOfRangeException(nameof(severity), severity, "Unknown diagnostic severity")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AppendSourceContext(StringBuilder sb, SourceSpan span, DiagnosticSeverity severity)
|
|
||||||
{
|
|
||||||
var lines = span.Text.Content.Split('\n');
|
|
||||||
var startLine = span.Start.Line;
|
|
||||||
var endLine = span.End.Line;
|
|
||||||
|
|
||||||
const int contextLines = 3;
|
|
||||||
|
|
||||||
var lineNumWidth = Math.Min(endLine + contextLines, lines.Length).ToString().Length;
|
|
||||||
|
|
||||||
var contextStart = Math.Max(1, startLine - contextLines);
|
|
||||||
var contextEnd = Math.Min(lines.Length, endLine + contextLines);
|
|
||||||
|
|
||||||
var contextWidth = 0;
|
|
||||||
for (var i = contextStart; i <= contextEnd; i++)
|
|
||||||
{
|
|
||||||
if (lines[i - 1].Length > contextWidth)
|
|
||||||
{
|
|
||||||
contextWidth = lines[i - 1].Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.AppendLine(ConsoleColors.Colorize('╭' + new string('─', lineNumWidth + 2) + '┬' + new string('─', contextWidth + 2) + '╮', ConsoleColors.Faint));
|
|
||||||
|
|
||||||
for (var lineNum = contextStart; lineNum < startLine; lineNum++)
|
|
||||||
{
|
|
||||||
AppendContextLine(sb, lineNum, lines[lineNum - 1], lineNumWidth, contextWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var lineNum = startLine; lineNum <= endLine; lineNum++)
|
|
||||||
{
|
|
||||||
AppendContextLine(sb, lineNum, lines[lineNum - 1], lineNumWidth, contextWidth);
|
|
||||||
AppendErrorIndicators(sb, span, lineNum, lines[lineNum - 1], lineNumWidth, contextWidth, severity);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var lineNum = endLine + 1; lineNum <= contextEnd; lineNum++)
|
|
||||||
{
|
|
||||||
AppendContextLine(sb, lineNum, lines[lineNum - 1], lineNumWidth, contextWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Append(ConsoleColors.Colorize('╰' + new string('─', lineNumWidth + 2) + '┴' + new string('─', contextWidth + 2) + '╯', ConsoleColors.Faint));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AppendContextLine(StringBuilder sb, int lineNum, string line, int lineNumWidth, int contextWidth)
|
|
||||||
{
|
|
||||||
sb.Append(ConsoleColors.Colorize('│' + " ", ConsoleColors.Faint));
|
|
||||||
var lineNumStr = lineNum.ToString().PadLeft(lineNumWidth);
|
|
||||||
sb.Append(ConsoleColors.Colorize(lineNumStr, ConsoleColors.Faint));
|
|
||||||
sb.Append(ConsoleColors.Colorize(" │ ", ConsoleColors.Faint));
|
|
||||||
sb.Append(ConsoleColors.ColorizeSource(line.PadRight(contextWidth)));
|
|
||||||
sb.Append(ConsoleColors.Colorize(" " + '│', ConsoleColors.Faint));
|
|
||||||
sb.AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AppendErrorIndicators(StringBuilder sb, SourceSpan span, int lineNum, string line, int lineNumWidth, int contextWidth, DiagnosticSeverity severity)
|
|
||||||
{
|
|
||||||
var color = severity switch
|
|
||||||
{
|
|
||||||
DiagnosticSeverity.Info => ConsoleColors.Blue,
|
|
||||||
DiagnosticSeverity.Warning => ConsoleColors.Yellow,
|
|
||||||
DiagnosticSeverity.Error => ConsoleColors.Red,
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(severity), severity, null)
|
|
||||||
};
|
|
||||||
|
|
||||||
sb.Append(ConsoleColors.Colorize('│' + " ", ConsoleColors.Faint));
|
|
||||||
sb.Append(new string(' ', lineNumWidth));
|
|
||||||
sb.Append(ConsoleColors.Colorize(" │ ", ConsoleColors.Faint));
|
|
||||||
var indicators = GetIndicatorsForLine(span, lineNum, line);
|
|
||||||
sb.Append(ConsoleColors.Colorize(indicators.PadRight(contextWidth), color));
|
|
||||||
sb.Append(ConsoleColors.Colorize(" " + '│', ConsoleColors.Faint));
|
|
||||||
sb.AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetIndicatorsForLine(SourceSpan span, int lineNum, string line)
|
|
||||||
{
|
|
||||||
const char indicator = '^';
|
|
||||||
|
|
||||||
if (lineNum == span.Start.Line && lineNum == span.End.Line)
|
|
||||||
{
|
|
||||||
var startCol = Math.Max(0, span.Start.Column - 1);
|
|
||||||
var endCol = Math.Min(line.Length, span.End.Column - 1);
|
|
||||||
var length = Math.Max(1, endCol - startCol);
|
|
||||||
|
|
||||||
return new string(' ', startCol) + new string(indicator, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lineNum == span.Start.Line)
|
|
||||||
{
|
|
||||||
var startCol = Math.Max(0, span.Start.Column - 1);
|
|
||||||
return new string(' ', startCol) + new string(indicator, Math.Max(0, line.Length - startCol));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lineNum == span.End.Line)
|
|
||||||
{
|
|
||||||
var endCol = Math.Min(line.Length, span.End.Column - 1);
|
|
||||||
return new string(indicator, Math.Max(0, endCol));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new string(indicator, line.Length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DiagnosticSeverity
|
public enum DiagnosticSeverity
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
private Val EmitExpression(BoundExpression expression)
|
private Val EmitExpression(BoundExpression expression)
|
||||||
{
|
{
|
||||||
_writer.WriteDebugLocation(expression);
|
|
||||||
|
|
||||||
return expression switch
|
return expression switch
|
||||||
{
|
{
|
||||||
BoundArrayInitializer arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
BoundArrayInitializer arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||||
@@ -27,8 +25,7 @@ public partial class QBEGenerator
|
|||||||
BoundLiteral literal => EmitLiteral(literal),
|
BoundLiteral literal => EmitLiteral(literal),
|
||||||
BoundUnaryExpression unaryExpression => EmitUnaryExpression(unaryExpression),
|
BoundUnaryExpression unaryExpression => EmitUnaryExpression(unaryExpression),
|
||||||
BoundStructFieldAccess structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
BoundStructFieldAccess structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
||||||
BoundTraitFuncAccess traitFuncAccess => EmitTraitFuncAccess(traitFuncAccess),
|
BoundInterfaceFuncAccess traitFuncAccess => EmitTraitFuncAccess(traitFuncAccess),
|
||||||
BoundTraitImplFuncAccess traitImplFuncAccess => EmitTraitImplFuncAccess(traitImplFuncAccess),
|
|
||||||
BoundArrayIndexAccess arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
BoundArrayIndexAccess arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
};
|
};
|
||||||
@@ -418,22 +415,11 @@ public partial class QBEGenerator
|
|||||||
return new Val(output, structFieldAccess.Type, ValKind.Pointer);
|
return new Val(output, structFieldAccess.Type, ValKind.Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitTraitFuncAccess(BoundTraitFuncAccess traitFuncAccess)
|
private Val EmitTraitFuncAccess(BoundInterfaceFuncAccess interfaceFuncAccess)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitTraitImplFuncAccess(BoundTraitImplFuncAccess traitImplFuncAccess)
|
|
||||||
{
|
|
||||||
var target = EmitExpression(traitImplFuncAccess.Target);
|
|
||||||
|
|
||||||
var funcImpl = _definitionTable.LookupTraitFuncImpl(traitImplFuncAccess.Target.Type, traitImplFuncAccess.FuncName);
|
|
||||||
|
|
||||||
var name = ImplFuncName();
|
|
||||||
_implFunctions.TryAdd(funcImpl, name);
|
|
||||||
return new Val(name, traitImplFuncAccess.Type, ValKind.Direct, new MethodCallContext(target));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Val EmitFuncCall(BoundFuncCall funcCall)
|
private Val EmitFuncCall(BoundFuncCall funcCall)
|
||||||
{
|
{
|
||||||
var expression = EmitExpression(funcCall.Expression);
|
var expression = EmitExpression(funcCall.Expression);
|
||||||
@@ -441,12 +427,6 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
var parameterStrings = new List<string>();
|
var parameterStrings = new List<string>();
|
||||||
|
|
||||||
if (expression.FuncCallContext != null)
|
|
||||||
{
|
|
||||||
var thisArg = EmitUnwrap(expression.FuncCallContext.ThisArg);
|
|
||||||
parameterStrings.Add($"{FuncQBETypeName(expression.FuncCallContext.ThisArg.Type)} {thisArg}");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var parameter in funcCall.Parameters)
|
foreach (var parameter in funcCall.Parameters)
|
||||||
{
|
{
|
||||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
private void EmitStatement(BoundStatement statement)
|
private void EmitStatement(BoundStatement statement)
|
||||||
{
|
{
|
||||||
_writer.WriteDebugLocation(statement);
|
|
||||||
|
|
||||||
switch (statement)
|
switch (statement)
|
||||||
{
|
{
|
||||||
case BoundAssignment assignment:
|
case BoundAssignment assignment:
|
||||||
|
|||||||
@@ -18,23 +18,21 @@ public partial class QBEGenerator
|
|||||||
private readonly Stack<string> _breakLabels = [];
|
private readonly Stack<string> _breakLabels = [];
|
||||||
private readonly Stack<string> _continueLabels = [];
|
private readonly Stack<string> _continueLabels = [];
|
||||||
private readonly Queue<(BoundArrowFunc Func, string Name)> _arrowFunctions = [];
|
private readonly Queue<(BoundArrowFunc Func, string Name)> _arrowFunctions = [];
|
||||||
private readonly Dictionary<BoundTraitFuncImpl, string> _implFunctions = [];
|
|
||||||
private readonly Stack<Scope> _scopes = [];
|
private readonly Stack<Scope> _scopes = [];
|
||||||
private int _tmpIndex;
|
private int _tmpIndex;
|
||||||
private int _labelIndex;
|
private int _labelIndex;
|
||||||
private int _arrowFuncIndex;
|
private int _arrowFuncIndex;
|
||||||
private int _cStringLiteralIndex;
|
private int _cStringLiteralIndex;
|
||||||
private int _stringLiteralIndex;
|
private int _stringLiteralIndex;
|
||||||
private int _implFuncNameIndex;
|
|
||||||
private bool _codeIsReachable = true;
|
private bool _codeIsReachable = true;
|
||||||
|
|
||||||
private Scope Scope => _scopes.Peek();
|
private Scope Scope => _scopes.Peek();
|
||||||
|
|
||||||
public QBEGenerator(BoundSyntaxTree syntaxTree, BoundDefinitionTable definitionTable, string file)
|
public QBEGenerator(BoundSyntaxTree syntaxTree, BoundDefinitionTable definitionTable)
|
||||||
{
|
{
|
||||||
_syntaxTree = syntaxTree;
|
_syntaxTree = syntaxTree;
|
||||||
_definitionTable = definitionTable;
|
_definitionTable = definitionTable;
|
||||||
_writer = new QBEWriter(file);
|
_writer = new QBEWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Emit()
|
public string Emit()
|
||||||
@@ -44,14 +42,12 @@ public partial class QBEGenerator
|
|||||||
_breakLabels.Clear();
|
_breakLabels.Clear();
|
||||||
_continueLabels.Clear();
|
_continueLabels.Clear();
|
||||||
_arrowFunctions.Clear();
|
_arrowFunctions.Clear();
|
||||||
_implFunctions.Clear();
|
|
||||||
_scopes.Clear();
|
_scopes.Clear();
|
||||||
_tmpIndex = 0;
|
_tmpIndex = 0;
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
_arrowFuncIndex = 0;
|
_arrowFuncIndex = 0;
|
||||||
_cStringLiteralIndex = 0;
|
_cStringLiteralIndex = 0;
|
||||||
_stringLiteralIndex = 0;
|
_stringLiteralIndex = 0;
|
||||||
_implFuncNameIndex = 0;
|
|
||||||
_codeIsReachable = true;
|
_codeIsReachable = true;
|
||||||
|
|
||||||
foreach (var structDef in _definitionTable.GetStructs())
|
foreach (var structDef in _definitionTable.GetStructs())
|
||||||
@@ -78,12 +74,6 @@ public partial class QBEGenerator
|
|||||||
_writer.NewLine();
|
_writer.NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (impl, name) in _implFunctions)
|
|
||||||
{
|
|
||||||
EmitFuncDefinition(name, impl.Signature.Parameters, impl.Signature.ReturnType, impl.Body);
|
|
||||||
_writer.NewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var cStringLiteral in _cStringLiterals)
|
foreach (var cStringLiteral in _cStringLiterals)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"data {cStringLiteral.Name} = {{ b \"{cStringLiteral.Value}\", b 0 }}");
|
_writer.WriteLine($"data {cStringLiteral.Name} = {{ b \"{cStringLiteral.Value}\", b 0 }}");
|
||||||
@@ -207,19 +197,16 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
case BoundArrayInitializer arrayInitializer:
|
case BoundArrayInitializer arrayInitializer:
|
||||||
{
|
{
|
||||||
_writer.WriteDebugLocation(arrayInitializer);
|
|
||||||
EmitStore(source.Type, EmitUnwrap(EmitArrayInitializer(arrayInitializer)), destinationPointer);
|
EmitStore(source.Type, EmitUnwrap(EmitArrayInitializer(arrayInitializer)), destinationPointer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case BoundStructInitializer structInitializer:
|
case BoundStructInitializer structInitializer:
|
||||||
{
|
{
|
||||||
_writer.WriteDebugLocation(structInitializer);
|
|
||||||
EmitStructInitializer(structInitializer, destinationPointer);
|
EmitStructInitializer(structInitializer, destinationPointer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case BoundLiteral { Kind: LiteralKind.String } literal:
|
case BoundLiteral { Kind: LiteralKind.String } literal:
|
||||||
{
|
{
|
||||||
_writer.WriteDebugLocation(literal);
|
|
||||||
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
|
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -521,11 +508,6 @@ public partial class QBEGenerator
|
|||||||
return $"${funcDef.CallName}";
|
return $"${funcDef.CallName}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ImplFuncName()
|
|
||||||
{
|
|
||||||
return $"$impl{++_implFuncNameIndex}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CustomTypeName(NubCustomType customType)
|
private string CustomTypeName(NubCustomType customType)
|
||||||
{
|
{
|
||||||
return CustomTypeName(customType.Namespace, customType.Name);
|
return CustomTypeName(customType.Namespace, customType.Name);
|
||||||
@@ -551,7 +533,7 @@ public class CStringLiteral(string value, string name)
|
|||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
|
public record Val(string Name, NubType Type, ValKind Kind);
|
||||||
|
|
||||||
public class Scope(Scope? parent = null)
|
public class Scope(Scope? parent = null)
|
||||||
{
|
{
|
||||||
@@ -579,8 +561,6 @@ public class Scope(Scope? parent = null)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record MethodCallContext(Val ThisArg);
|
|
||||||
|
|
||||||
public enum ValKind
|
public enum ValKind
|
||||||
{
|
{
|
||||||
Pointer,
|
Pointer,
|
||||||
|
|||||||
@@ -1,22 +1,13 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using NubLang.Syntax.Binding.Node;
|
|
||||||
|
|
||||||
namespace NubLang.Generation.QBE;
|
namespace NubLang.Generation.QBE;
|
||||||
|
|
||||||
internal class QBEWriter
|
internal class QBEWriter
|
||||||
{
|
{
|
||||||
private readonly StringBuilder _builder = new();
|
private readonly StringBuilder _builder = new();
|
||||||
private int _currentLine = -1;
|
|
||||||
|
|
||||||
public QBEWriter(string debugFile)
|
|
||||||
{
|
|
||||||
_builder.AppendLine($"dbgfile \"{debugFile}\"");
|
|
||||||
_builder.AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartFunction(string signature)
|
public void StartFunction(string signature)
|
||||||
{
|
{
|
||||||
_currentLine = -1;
|
|
||||||
_builder.Append(signature);
|
_builder.Append(signature);
|
||||||
_builder.AppendLine(" {");
|
_builder.AppendLine(" {");
|
||||||
_builder.AppendLine("@start");
|
_builder.AppendLine("@start");
|
||||||
@@ -27,26 +18,6 @@ internal class QBEWriter
|
|||||||
_builder.AppendLine("}");
|
_builder.AppendLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteDebugLocation(SourceSpan span)
|
|
||||||
{
|
|
||||||
var line = span.Start.Line;
|
|
||||||
|
|
||||||
if (_currentLine != line)
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" dbgloc {line}");
|
|
||||||
_currentLine = line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteDebugLocation(BoundNode node)
|
|
||||||
{
|
|
||||||
var firstToken = node.Tokens.FirstOrDefault();
|
|
||||||
if (firstToken != null)
|
|
||||||
{
|
|
||||||
// WriteDebugLocation(firstToken.Span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Indented(string value)
|
public void Indented(string value)
|
||||||
{
|
{
|
||||||
_builder.Append('\t');
|
_builder.Append('\t');
|
||||||
|
|||||||
@@ -1,274 +0,0 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace NubLang;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a location in source code with line and column information.
|
|
||||||
/// Lines and columns are 1-based to match typical editor conventions.
|
|
||||||
/// </summary>
|
|
||||||
public readonly struct SourceLocation : IEquatable<SourceLocation>, IComparable<SourceLocation>
|
|
||||||
{
|
|
||||||
public SourceLocation(int line, int column)
|
|
||||||
{
|
|
||||||
if (line < 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(line), "Line must be >= 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (column < 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(column), "Column must be >= 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
Line = line;
|
|
||||||
Column = column;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Line { get; }
|
|
||||||
public int Column { get; }
|
|
||||||
|
|
||||||
public int CompareTo(SourceLocation other)
|
|
||||||
{
|
|
||||||
var lineComparison = Line.CompareTo(other.Line);
|
|
||||||
if (lineComparison == 0)
|
|
||||||
{
|
|
||||||
return Column.CompareTo(other.Column);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lineComparison;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Line}:{Column}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SourceLocation other)
|
|
||||||
{
|
|
||||||
return Line == other.Line && Column == other.Column;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals([NotNullWhen(true)] object? obj)
|
|
||||||
{
|
|
||||||
return obj is SourceLocation other && Equals(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return HashCode.Combine(Line, Column);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SourceLocation left, SourceLocation right) => left.Equals(right);
|
|
||||||
public static bool operator !=(SourceLocation left, SourceLocation right) => !left.Equals(right);
|
|
||||||
public static bool operator <(SourceLocation left, SourceLocation right) => left.CompareTo(right) < 0;
|
|
||||||
public static bool operator >(SourceLocation left, SourceLocation right) => left.CompareTo(right) > 0;
|
|
||||||
public static bool operator <=(SourceLocation left, SourceLocation right) => left.CompareTo(right) <= 0;
|
|
||||||
public static bool operator >=(SourceLocation left, SourceLocation right) => left.CompareTo(right) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents source text with a name (typically filename) and content.
|
|
||||||
/// Equality is based on both name and content for better semantics.
|
|
||||||
/// </summary>
|
|
||||||
public struct SourceText : IEquatable<SourceText>
|
|
||||||
{
|
|
||||||
private int _lines = -1;
|
|
||||||
|
|
||||||
public SourceText(string path, string content)
|
|
||||||
{
|
|
||||||
Path = path ?? throw new ArgumentNullException(nameof(path));
|
|
||||||
Content = content ?? throw new ArgumentNullException(nameof(content));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Path { get; }
|
|
||||||
public string Content { get; }
|
|
||||||
|
|
||||||
public int LineCount()
|
|
||||||
{
|
|
||||||
if (_lines == -1)
|
|
||||||
{
|
|
||||||
_lines = Content.Split('\n').Length + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a specific line from the source text (1-based).
|
|
||||||
/// </summary>
|
|
||||||
public string GetLine(int lineNumber)
|
|
||||||
{
|
|
||||||
if (lineNumber < 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(lineNumber));
|
|
||||||
}
|
|
||||||
|
|
||||||
var lines = Content.Split('\n');
|
|
||||||
return lineNumber <= lines.Length ? lines[lineNumber - 1] : string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SourceText other)
|
|
||||||
{
|
|
||||||
return Path == other.Path && Content == other.Content;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals([NotNullWhen(true)] object? obj)
|
|
||||||
{
|
|
||||||
return obj is SourceText other && Equals(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return HashCode.Combine(Path, Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SourceText left, SourceText right) => left.Equals(right);
|
|
||||||
public static bool operator !=(SourceText left, SourceText right) => !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a span of source code from a start to end location within a source text.
|
|
||||||
/// </summary>
|
|
||||||
public readonly struct SourceSpan : IEquatable<SourceSpan>
|
|
||||||
{
|
|
||||||
public SourceSpan(SourceText text, SourceLocation start, SourceLocation end)
|
|
||||||
{
|
|
||||||
if (start > end)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Start location cannot be after end location");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end.Line > text.LineCount() || end.Line == text.LineCount() && end.Column > text.GetLine(text.LineCount()).Length + 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("End location cannot be after text end location");
|
|
||||||
}
|
|
||||||
|
|
||||||
Text = text;
|
|
||||||
Start = start;
|
|
||||||
End = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceText Text { get; }
|
|
||||||
public SourceLocation Start { get; }
|
|
||||||
public SourceLocation End { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether this span represents a single point (start == end).
|
|
||||||
/// </summary>
|
|
||||||
public bool IsEmpty => Start == End;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether this span is contained within a single line.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsSingleLine => Start.Line == End.Line;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the text content covered by this span.
|
|
||||||
/// </summary>
|
|
||||||
public string GetText()
|
|
||||||
{
|
|
||||||
if (IsEmpty)
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var lines = Text.Content.Split('\n');
|
|
||||||
|
|
||||||
if (IsSingleLine)
|
|
||||||
{
|
|
||||||
var line = lines[Start.Line - 1];
|
|
||||||
var startCol = Math.Min(Start.Column - 1, line.Length);
|
|
||||||
var endCol = Math.Min(End.Column - 1, line.Length);
|
|
||||||
return line.Substring(startCol, Math.Max(0, endCol - startCol));
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = new List<string>();
|
|
||||||
for (var i = Start.Line - 1; i < Math.Min(End.Line, lines.Length); i++)
|
|
||||||
{
|
|
||||||
var line = lines[i];
|
|
||||||
if (i == Start.Line - 1)
|
|
||||||
{
|
|
||||||
result.Add(line[Math.Min(Start.Column - 1, line.Length)..]);
|
|
||||||
}
|
|
||||||
else if (i == End.Line - 1)
|
|
||||||
{
|
|
||||||
result.Add(line[..Math.Min(End.Column - 1, line.Length)]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Join("\n", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Merges multiple source spans from the same file into a single span.
|
|
||||||
/// The result spans from the earliest start to the latest end.
|
|
||||||
/// </summary>
|
|
||||||
public static SourceSpan Merge(IEnumerable<SourceSpan> spans)
|
|
||||||
{
|
|
||||||
var spanArray = spans.ToArray();
|
|
||||||
if (spanArray.Length == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Cannot merge empty collection of spans", nameof(spans));
|
|
||||||
}
|
|
||||||
|
|
||||||
var firstText = spanArray[0].Text;
|
|
||||||
if (spanArray.Any(s => !s.Text.Equals(firstText)))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("All spans must be from the same source text", nameof(spans));
|
|
||||||
}
|
|
||||||
|
|
||||||
var minStart = spanArray.Min(s => s.Start);
|
|
||||||
var maxEnd = spanArray.Max(s => s.End);
|
|
||||||
|
|
||||||
return new SourceSpan(firstText, minStart, maxEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (IsEmpty)
|
|
||||||
{
|
|
||||||
return $"{Start}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsSingleLine)
|
|
||||||
{
|
|
||||||
return Start.Column == End.Column ? $"{Start}" : $"{Start.Line}:{Start.Column}-{End.Column}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{Start}-{End}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SourceSpan other)
|
|
||||||
{
|
|
||||||
return Text.Equals(other.Text) && Start.Equals(other.Start) && End.Equals(other.End);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals([NotNullWhen(true)] object? obj)
|
|
||||||
{
|
|
||||||
return obj is SourceSpan other && Equals(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return HashCode.Combine(Text, Start, End);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SourceSpan left, SourceSpan right)
|
|
||||||
{
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(SourceSpan left, SourceSpan right)
|
|
||||||
{
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -63,10 +63,10 @@ public sealed class Binder
|
|||||||
|
|
||||||
foreach (var function in node.Functions)
|
foreach (var function in node.Functions)
|
||||||
{
|
{
|
||||||
functions.Add(new BoundTraitFunc(node.Tokens, function.Name, BindFuncSignature(function.Signature)));
|
functions.Add(new BoundTraitFunc(function.Name, BindFuncSignature(function.Signature)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundTrait(node.Tokens, node.Namespace, node.Name, functions);
|
return new BoundTrait(node.Namespace, node.Name, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStruct BindStruct(StructSyntax node)
|
private BoundStruct BindStruct(StructSyntax node)
|
||||||
@@ -82,15 +82,15 @@ public sealed class Binder
|
|||||||
value = BindExpression(field.Value.Value, BindType(field.Type));
|
value = BindExpression(field.Value.Value, BindType(field.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
structFields.Add(new BoundStructField(field.Tokens, field.Index, field.Name, BindType(field.Type), value));
|
structFields.Add(new BoundStructField(field.Index, field.Name, BindType(field.Type), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundStruct(node.Tokens, node.Namespace, node.Name, structFields);
|
return new BoundStruct(node.Namespace, node.Name, structFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
||||||
{
|
{
|
||||||
return new BoundExternFunc(node.Tokens, node.Namespace, node.Name, node.CallName, BindFuncSignature(node.Signature));
|
return new BoundExternFunc(node.Namespace, node.Name, node.CallName, BindFuncSignature(node.Signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
||||||
@@ -98,7 +98,7 @@ public sealed class Binder
|
|||||||
var signature = BindFuncSignature(node.Signature);
|
var signature = BindFuncSignature(node.Signature);
|
||||||
var body = BindFuncBody(node.Body, signature.ReturnType, signature.Parameters);
|
var body = BindFuncBody(node.Body, signature.ReturnType, signature.Parameters);
|
||||||
|
|
||||||
return new BoundLocalFunc(node.Tokens, node.Namespace, node.Name, signature, body);
|
return new BoundLocalFunc(node.Namespace, node.Name, signature, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindStatement(StatementSyntax node)
|
private BoundStatement BindStatement(StatementSyntax node)
|
||||||
@@ -106,8 +106,8 @@ public sealed class Binder
|
|||||||
return node switch
|
return node switch
|
||||||
{
|
{
|
||||||
AssignmentSyntax statement => BindAssignment(statement),
|
AssignmentSyntax statement => BindAssignment(statement),
|
||||||
BreakSyntax statement => BindBreak(statement),
|
BreakSyntax => new BoundBreak(),
|
||||||
ContinueSyntax statement => BindContinue(statement),
|
ContinueSyntax => new BoundContinue(),
|
||||||
IfSyntax statement => BindIf(statement),
|
IfSyntax statement => BindIf(statement),
|
||||||
ReturnSyntax statement => BindReturn(statement),
|
ReturnSyntax statement => BindReturn(statement),
|
||||||
StatementExpressionSyntax statement => BindStatementExpression(statement),
|
StatementExpressionSyntax statement => BindStatementExpression(statement),
|
||||||
@@ -121,17 +121,7 @@ public sealed class Binder
|
|||||||
{
|
{
|
||||||
var expression = BindExpression(statement.Target);
|
var expression = BindExpression(statement.Target);
|
||||||
var value = BindExpression(statement.Value, expression.Type);
|
var value = BindExpression(statement.Value, expression.Type);
|
||||||
return new BoundAssignment(statement.Tokens, expression, value);
|
return new BoundAssignment(expression, value);
|
||||||
}
|
|
||||||
|
|
||||||
private BoundBreak BindBreak(BreakSyntax statement)
|
|
||||||
{
|
|
||||||
return new BoundBreak(statement.Tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BoundContinue BindContinue(ContinueSyntax statement)
|
|
||||||
{
|
|
||||||
return new BoundContinue(statement.Tokens);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundIf BindIf(IfSyntax statement)
|
private BoundIf BindIf(IfSyntax statement)
|
||||||
@@ -147,7 +137,7 @@ public sealed class Binder
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundIf(statement.Tokens, BindExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), BindBlock(statement.Body), elseStatement);
|
return new BoundIf(BindExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), BindBlock(statement.Body), elseStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundReturn BindReturn(ReturnSyntax statement)
|
private BoundReturn BindReturn(ReturnSyntax statement)
|
||||||
@@ -159,12 +149,12 @@ public sealed class Binder
|
|||||||
value = BindExpression(statement.Value.Value, _funcReturnTypes.Peek());
|
value = BindExpression(statement.Value.Value, _funcReturnTypes.Peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundReturn(statement.Tokens, value);
|
return new BoundReturn(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatementExpression BindStatementExpression(StatementExpressionSyntax statement)
|
private BoundStatementExpression BindStatementExpression(StatementExpressionSyntax statement)
|
||||||
{
|
{
|
||||||
return new BoundStatementExpression(statement.Tokens, BindExpression(statement.Expression));
|
return new BoundStatementExpression(BindExpression(statement.Expression));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundVariableDeclaration BindVariableDeclaration(VariableDeclarationSyntax statement)
|
private BoundVariableDeclaration BindVariableDeclaration(VariableDeclarationSyntax statement)
|
||||||
@@ -191,12 +181,12 @@ public sealed class Binder
|
|||||||
|
|
||||||
Scope.Declare(new Variable(statement.Name, type));
|
Scope.Declare(new Variable(statement.Name, type));
|
||||||
|
|
||||||
return new BoundVariableDeclaration(statement.Tokens, statement.Name, assignment, type);
|
return new BoundVariableDeclaration(statement.Name, assignment, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundWhile BindWhile(WhileSyntax statement)
|
private BoundWhile BindWhile(WhileSyntax statement)
|
||||||
{
|
{
|
||||||
return new BoundWhile(statement.Tokens, BindExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), BindBlock(statement.Body));
|
return new BoundWhile(BindExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), BindBlock(statement.Body));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindExpression(ExpressionSyntax node, NubType? expectedType = null)
|
private BoundExpression BindExpression(ExpressionSyntax node, NubType? expectedType = null)
|
||||||
@@ -222,19 +212,19 @@ public sealed class Binder
|
|||||||
private BoundAddressOf BindAddressOf(AddressOfSyntax expression)
|
private BoundAddressOf BindAddressOf(AddressOfSyntax expression)
|
||||||
{
|
{
|
||||||
var inner = BindExpression(expression.Expression);
|
var inner = BindExpression(expression.Expression);
|
||||||
return new BoundAddressOf(expression.Tokens, new NubPointerType(inner.Type), inner);
|
return new BoundAddressOf(new NubPointerType(inner.Type), inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundArrowFunc BindArrowFunc(ArrowFuncSyntax expression, NubType? expectedType = null)
|
private BoundArrowFunc BindArrowFunc(ArrowFuncSyntax expression, NubType? expectedType = null)
|
||||||
{
|
{
|
||||||
if (expectedType == null)
|
if (expectedType == null)
|
||||||
{
|
{
|
||||||
throw new BindException(Diagnostic.Error("Cannot infer argument types for arrow function").At(expression).Build());
|
throw new BindException(Diagnostic.Error("Cannot infer argument types for arrow function").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expectedType is not NubFuncType funcType)
|
if (expectedType is not NubFuncType funcType)
|
||||||
{
|
{
|
||||||
throw new BindException(Diagnostic.Error($"Expected {expectedType}, but got arrow function").At(expression).Build());
|
throw new BindException(Diagnostic.Error($"Expected {expectedType}, but got arrow function").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters = new List<BoundFuncParameter>();
|
var parameters = new List<BoundFuncParameter>();
|
||||||
@@ -248,40 +238,40 @@ public sealed class Binder
|
|||||||
|
|
||||||
var expectedParameterType = funcType.Parameters[i];
|
var expectedParameterType = funcType.Parameters[i];
|
||||||
var parameter = expression.Parameters[i];
|
var parameter = expression.Parameters[i];
|
||||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, expectedParameterType));
|
parameters.Add(new BoundFuncParameter(parameter.Name, expectedParameterType));
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = BindFuncBody(expression.Body, funcType.ReturnType, parameters);
|
var body = BindFuncBody(expression.Body, funcType.ReturnType, parameters);
|
||||||
|
|
||||||
return new BoundArrowFunc(expression.Tokens, new NubFuncType(parameters.Select(x => x.Type).ToList(), funcType.ReturnType), parameters, funcType.ReturnType, body);
|
return new BoundArrowFunc(new NubFuncType(parameters.Select(x => x.Type).ToList(), funcType.ReturnType), parameters, funcType.ReturnType, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundArrayIndexAccess BindArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
private BoundArrayIndexAccess BindArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||||
{
|
{
|
||||||
var boundArray = BindExpression(expression.Target);
|
var boundArray = BindExpression(expression.Target);
|
||||||
var elementType = ((NubArrayType)boundArray.Type).ElementType;
|
var elementType = ((NubArrayType)boundArray.Type).ElementType;
|
||||||
return new BoundArrayIndexAccess(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, new NubPrimitiveType(PrimitiveTypeKind.U64)));
|
return new BoundArrayIndexAccess(elementType, boundArray, BindExpression(expression.Index, new NubPrimitiveType(PrimitiveTypeKind.U64)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundArrayInitializer BindArrayInitializer(ArrayInitializerSyntax expression)
|
private BoundArrayInitializer BindArrayInitializer(ArrayInitializerSyntax expression)
|
||||||
{
|
{
|
||||||
var capacity = BindExpression(expression.Capacity, new NubPrimitiveType(PrimitiveTypeKind.U64));
|
var capacity = BindExpression(expression.Capacity, new NubPrimitiveType(PrimitiveTypeKind.U64));
|
||||||
var type = new NubArrayType(BindType(expression.ElementType));
|
var type = new NubArrayType(BindType(expression.ElementType));
|
||||||
return new BoundArrayInitializer(expression.Tokens, type, capacity, BindType(expression.ElementType));
|
return new BoundArrayInitializer(type, capacity, BindType(expression.ElementType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundBinaryExpression BindBinaryExpression(BinaryExpressionSyntax expression)
|
private BoundBinaryExpression BindBinaryExpression(BinaryExpressionSyntax expression)
|
||||||
{
|
{
|
||||||
var boundLeft = BindExpression(expression.Left);
|
var boundLeft = BindExpression(expression.Left);
|
||||||
var boundRight = BindExpression(expression.Right, boundLeft.Type);
|
var boundRight = BindExpression(expression.Right, boundLeft.Type);
|
||||||
return new BoundBinaryExpression(expression.Tokens, boundLeft.Type, boundLeft, BindBinaryOperator(expression.Operator), boundRight);
|
return new BoundBinaryExpression(boundLeft.Type, boundLeft, BindBinaryOperator(expression.Operator), boundRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundDereference BindDereference(DereferenceSyntax expression)
|
private BoundDereference BindDereference(DereferenceSyntax expression)
|
||||||
{
|
{
|
||||||
var boundExpression = BindExpression(expression.Expression);
|
var boundExpression = BindExpression(expression.Expression);
|
||||||
var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType;
|
var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType;
|
||||||
return new BoundDereference(expression.Tokens, dereferencedType, boundExpression);
|
return new BoundDereference(dereferencedType, boundExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundFuncCall BindFuncCall(FuncCallSyntax expression)
|
private BoundFuncCall BindFuncCall(FuncCallSyntax expression)
|
||||||
@@ -304,7 +294,7 @@ public sealed class Binder
|
|||||||
parameters.Add(BindExpression(parameter, expectedType));
|
parameters.Add(BindExpression(parameter, expectedType));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundFuncCall(expression.Tokens, funcType.ReturnType, boundExpression, parameters);
|
return new BoundFuncCall(funcType.ReturnType, boundExpression, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindIdentifier(IdentifierSyntax expression)
|
private BoundExpression BindIdentifier(IdentifierSyntax expression)
|
||||||
@@ -323,7 +313,7 @@ public sealed class Binder
|
|||||||
var returnType = BindType(localFunc.Signature.ReturnType);
|
var returnType = BindType(localFunc.Signature.ReturnType);
|
||||||
var parameterTypes = localFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
var parameterTypes = localFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
||||||
var type = new NubFuncType(parameterTypes, returnType);
|
var type = new NubFuncType(parameterTypes, returnType);
|
||||||
return new BoundLocalFuncIdent(expression.Tokens, type, @namespace, expression.Name);
|
return new BoundLocalFuncIdent(type, @namespace, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray();
|
var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray();
|
||||||
@@ -339,7 +329,7 @@ public sealed class Binder
|
|||||||
var returnType = BindType(externFunc.Signature.ReturnType);
|
var returnType = BindType(externFunc.Signature.ReturnType);
|
||||||
var parameterTypes = externFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
var parameterTypes = externFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
||||||
var type = new NubFuncType(parameterTypes, returnType);
|
var type = new NubFuncType(parameterTypes, returnType);
|
||||||
return new BoundExternFuncIdent(expression.Tokens, type, @namespace, expression.Name);
|
return new BoundExternFuncIdent(type, @namespace, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expression.Namespace.HasValue)
|
if (!expression.Namespace.HasValue)
|
||||||
@@ -347,7 +337,7 @@ public sealed class Binder
|
|||||||
var variable = Scope.Lookup(expression.Name);
|
var variable = Scope.Lookup(expression.Name);
|
||||||
if (variable != null)
|
if (variable != null)
|
||||||
{
|
{
|
||||||
return new BoundVariableIdent(expression.Tokens, variable.Type, variable.Name);
|
return new BoundVariableIdent(variable.Type, variable.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +355,7 @@ public sealed class Binder
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
|
|
||||||
return new BoundLiteral(expression.Tokens, type, expression.Value, expression.Kind);
|
return new BoundLiteral(type, expression.Value, expression.Kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindMemberAccess(MemberAccessSyntax expression)
|
private BoundExpression BindMemberAccess(MemberAccessSyntax expression)
|
||||||
@@ -385,7 +375,7 @@ public sealed class Binder
|
|||||||
// var returnType = BindType(impl.Signature.ReturnType);
|
// var returnType = BindType(impl.Signature.ReturnType);
|
||||||
// var parameterTypes = impl.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
// var parameterTypes = impl.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
||||||
// var type = new NubFuncType(parameterTypes, returnType);
|
// var type = new NubFuncType(parameterTypes, returnType);
|
||||||
// return new BoundTraitImplFuncAccess(expression.Tokens, type, boundExpression, expression.Member);
|
// return new BoundTraitImplFuncAccess(type, boundExpression, expression.Member);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (boundExpression.Type is NubCustomType customType)
|
if (boundExpression.Type is NubCustomType customType)
|
||||||
@@ -413,7 +403,7 @@ public sealed class Binder
|
|||||||
var returnType = BindType(traitFunc.Signature.ReturnType);
|
var returnType = BindType(traitFunc.Signature.ReturnType);
|
||||||
var parameterTypes = traitFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
var parameterTypes = traitFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
||||||
var type = new NubFuncType(parameterTypes, returnType);
|
var type = new NubFuncType(parameterTypes, returnType);
|
||||||
return new BoundTraitFuncAccess(expression.Tokens, type, customType, boundExpression, expression.Member);
|
return new BoundInterfaceFuncAccess(type, customType, boundExpression, expression.Member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +427,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var field = fields[0];
|
var field = fields[0];
|
||||||
|
|
||||||
return new BoundStructFieldAccess(expression.Tokens, BindType(field.Type), customType, boundExpression, expression.Member);
|
return new BoundStructFieldAccess(BindType(field.Type), customType, boundExpression, expression.Member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,7 +477,7 @@ public sealed class Binder
|
|||||||
initializers[field] = BindExpression(initializer, BindType(fields[0].Type));
|
initializers[field] = BindExpression(initializer, BindType(fields[0].Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundStructInitializer(expression.Tokens, structType, initializers);
|
return new BoundStructInitializer(structType, initializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundUnaryExpression BindUnaryExpression(UnaryExpressionSyntax expression)
|
private BoundUnaryExpression BindUnaryExpression(UnaryExpressionSyntax expression)
|
||||||
@@ -523,7 +513,7 @@ public sealed class Binder
|
|||||||
throw new NotImplementedException("Diagnostics not implemented");
|
throw new NotImplementedException("Diagnostics not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundUnaryExpression(expression.Tokens, type, BindBinaryOperator(expression.Operator), boundOperand);
|
return new BoundUnaryExpression(type, BindBinaryOperator(expression.Operator), boundOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundFuncSignature BindFuncSignature(FuncSignatureSyntax node)
|
private BoundFuncSignature BindFuncSignature(FuncSignatureSyntax node)
|
||||||
@@ -532,10 +522,10 @@ public sealed class Binder
|
|||||||
|
|
||||||
foreach (var parameter in node.Parameters)
|
foreach (var parameter in node.Parameters)
|
||||||
{
|
{
|
||||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, BindType(parameter.Type)));
|
parameters.Add(new BoundFuncParameter(parameter.Name, BindType(parameter.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundFuncSignature(node.Tokens, parameters, BindType(node.ReturnType));
|
return new BoundFuncSignature(parameters, BindType(node.ReturnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundBinaryOperator BindBinaryOperator(BinaryOperator op)
|
private BoundBinaryOperator BindBinaryOperator(BinaryOperator op)
|
||||||
@@ -579,7 +569,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
_scopes.Pop();
|
_scopes.Pop();
|
||||||
|
|
||||||
return new BoundBlock(node.Tokens, statements);
|
return new BoundBlock(statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundBlock BindFuncBody(BlockSyntax block, NubType returnType, IReadOnlyList<BoundFuncParameter> parameters)
|
private BoundBlock BindFuncBody(BlockSyntax block, NubType returnType, IReadOnlyList<BoundFuncParameter> parameters)
|
||||||
|
|||||||
@@ -1,26 +1,25 @@
|
|||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Binding.Node;
|
namespace NubLang.Syntax.Binding.Node;
|
||||||
|
|
||||||
public abstract record BoundDefinition(IReadOnlyList<Token> Tokens, string Namespace) : BoundNode(Tokens);
|
public abstract record BoundDefinition(string Namespace) : BoundNode;
|
||||||
|
|
||||||
public record BoundFuncParameter(IReadOnlyList<Token> Tokens, string Name, NubType Type) : BoundNode(Tokens);
|
public record BoundFuncParameter(string Name, NubType Type) : BoundNode;
|
||||||
|
|
||||||
public record BoundFuncSignature(IReadOnlyList<Token> Tokens, IReadOnlyList<BoundFuncParameter> Parameters, NubType ReturnType) : BoundNode(Tokens);
|
public record BoundFuncSignature(IReadOnlyList<BoundFuncParameter> Parameters, NubType ReturnType) : BoundNode;
|
||||||
|
|
||||||
public record BoundLocalFunc(IReadOnlyList<Token> Tokens, string Namespace, string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundDefinition(Tokens, Namespace);
|
public record BoundLocalFunc(string Namespace, string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundDefinition(Namespace);
|
||||||
|
|
||||||
public record BoundExternFunc(IReadOnlyList<Token> Tokens, string Namespace, string Name, string CallName, BoundFuncSignature Signature) : BoundDefinition(Tokens, Namespace);
|
public record BoundExternFunc(string Namespace, string Name, string CallName, BoundFuncSignature Signature) : BoundDefinition(Namespace);
|
||||||
|
|
||||||
public record BoundStructField(IReadOnlyList<Token> Tokens, int Index, string Name, NubType Type, Optional<BoundExpression> Value) : BoundNode(Tokens);
|
public record BoundStructField(int Index, string Name, NubType Type, Optional<BoundExpression> Value) : BoundNode;
|
||||||
|
|
||||||
public record BoundStruct(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<BoundStructField> Fields) : BoundDefinition(Tokens, Namespace);
|
public record BoundStruct(string Namespace, string Name, IReadOnlyList<BoundStructField> Fields) : BoundDefinition(Namespace);
|
||||||
|
|
||||||
public record BoundTraitFunc(IReadOnlyList<Token> Tokens, string Name, BoundFuncSignature Signature) : BoundNode(Tokens);
|
public record BoundTraitFunc(string Name, BoundFuncSignature Signature) : BoundNode;
|
||||||
|
|
||||||
public record BoundTrait(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<BoundTraitFunc> Functions) : BoundDefinition(Tokens, Namespace);
|
public record BoundTrait(string Namespace, string Name, IReadOnlyList<BoundTraitFunc> Functions) : BoundDefinition(Namespace);
|
||||||
|
|
||||||
public record BoundTraitFuncImpl(IReadOnlyList<Token> Tokens, string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundNode(Tokens);
|
public record BoundTraitFuncImpl(string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundNode;
|
||||||
|
|
||||||
public record BoundTraitImpl(IReadOnlyList<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, IReadOnlyList<BoundTraitFuncImpl> Functions) : BoundDefinition(Tokens, Namespace);
|
public record BoundTraitImpl(string Namespace, NubType TraitType, NubType ForType, IReadOnlyList<BoundTraitFuncImpl> Functions) : BoundDefinition(Namespace);
|
||||||
@@ -22,36 +22,34 @@ public enum BoundBinaryOperator
|
|||||||
Divide
|
Divide
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record BoundExpression(IReadOnlyList<Token> Tokens, NubType Type) : BoundNode(Tokens);
|
public abstract record BoundExpression(NubType Type) : BoundNode;
|
||||||
|
|
||||||
public record BoundBinaryExpression(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Left, BoundBinaryOperator Operator, BoundExpression Right) : BoundExpression(Tokens, Type);
|
public record BoundBinaryExpression(NubType Type, BoundExpression Left, BoundBinaryOperator Operator, BoundExpression Right) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundUnaryExpression(IReadOnlyList<Token> Tokens, NubType Type, BoundUnaryOperator Operator, BoundExpression Operand) : BoundExpression(Tokens, Type);
|
public record BoundUnaryExpression(NubType Type, BoundUnaryOperator Operator, BoundExpression Operand) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundFuncCall(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Expression, IReadOnlyList<BoundExpression> Parameters) : BoundExpression(Tokens, Type);
|
public record BoundFuncCall(NubType Type, BoundExpression Expression, IReadOnlyList<BoundExpression> Parameters) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundVariableIdent(IReadOnlyList<Token> Tokens, NubType Type, string Name) : BoundExpression(Tokens, Type);
|
public record BoundVariableIdent(NubType Type, string Name) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundLocalFuncIdent(IReadOnlyList<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpression(Tokens, Type);
|
public record BoundLocalFuncIdent(NubType Type, string Namespace, string Name) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundExternFuncIdent(IReadOnlyList<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpression(Tokens, Type);
|
public record BoundExternFuncIdent(NubType Type, string Namespace, string Name) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundArrayInitializer(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Capacity, NubType ElementType) : BoundExpression(Tokens, Type);
|
public record BoundArrayInitializer(NubType Type, BoundExpression Capacity, NubType ElementType) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundArrayIndexAccess(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Target, BoundExpression Index) : BoundExpression(Tokens, Type);
|
public record BoundArrayIndexAccess(NubType Type, BoundExpression Target, BoundExpression Index) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundArrowFunc(IReadOnlyList<Token> Tokens, NubType Type, IReadOnlyList<BoundFuncParameter> Parameters, NubType ReturnType, BoundBlock Body) : BoundExpression(Tokens, Type);
|
public record BoundArrowFunc(NubType Type, IReadOnlyList<BoundFuncParameter> Parameters, NubType ReturnType, BoundBlock Body) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundAddressOf(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Expression) : BoundExpression(Tokens, Type);
|
public record BoundAddressOf(NubType Type, BoundExpression Expression) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundLiteral(IReadOnlyList<Token> Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpression(Tokens, Type);
|
public record BoundLiteral(NubType Type, string Literal, LiteralKind Kind) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundStructFieldAccess(IReadOnlyList<Token> Tokens, NubType Type, NubCustomType StructType, BoundExpression Target, string Field) : BoundExpression(Tokens, Type);
|
public record BoundStructFieldAccess(NubType Type, NubCustomType StructType, BoundExpression Target, string Field) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundTraitImplFuncAccess(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Target, string FuncName) : BoundExpression(Tokens, Type);
|
public record BoundInterfaceFuncAccess(NubType Type, NubCustomType InterfaceType, BoundExpression Target, string FuncName) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundTraitFuncAccess(IReadOnlyList<Token> Tokens, NubType Type, NubCustomType TraitType, BoundExpression Target, string FuncName) : BoundExpression(Tokens, Type);
|
public record BoundStructInitializer(NubCustomType StructType, Dictionary<string, BoundExpression> Initializers) : BoundExpression(StructType);
|
||||||
|
|
||||||
public record BoundStructInitializer(IReadOnlyList<Token> Tokens, NubCustomType StructType, Dictionary<string, BoundExpression> Initializers) : BoundExpression(Tokens, StructType);
|
public record BoundDereference(NubType Type, BoundExpression Expression) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundDereference(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Expression) : BoundExpression(Tokens, Type);
|
|
||||||
@@ -1,22 +1,21 @@
|
|||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Binding.Node;
|
namespace NubLang.Syntax.Binding.Node;
|
||||||
|
|
||||||
public record BoundStatement(IReadOnlyList<Token> Tokens) : BoundNode(Tokens);
|
public record BoundStatement : BoundNode;
|
||||||
|
|
||||||
public record BoundStatementExpression(IReadOnlyList<Token> Tokens, BoundExpression Expression) : BoundStatement(Tokens);
|
public record BoundStatementExpression(BoundExpression Expression) : BoundStatement;
|
||||||
|
|
||||||
public record BoundReturn(IReadOnlyList<Token> Tokens, Optional<BoundExpression> Value) : BoundStatement(Tokens);
|
public record BoundReturn(Optional<BoundExpression> Value) : BoundStatement;
|
||||||
|
|
||||||
public record BoundAssignment(IReadOnlyList<Token> Tokens, BoundExpression Target, BoundExpression Value) : BoundStatement(Tokens);
|
public record BoundAssignment(BoundExpression Target, BoundExpression Value) : BoundStatement;
|
||||||
|
|
||||||
public record BoundIf(IReadOnlyList<Token> Tokens, BoundExpression Condition, BoundBlock Body, Optional<Variant<BoundIf, BoundBlock>> Else) : BoundStatement(Tokens);
|
public record BoundIf(BoundExpression Condition, BoundBlock Body, Optional<Variant<BoundIf, BoundBlock>> Else) : BoundStatement;
|
||||||
|
|
||||||
public record BoundVariableDeclaration(IReadOnlyList<Token> Tokens, string Name, Optional<BoundExpression> Assignment, NubType Type) : BoundStatement(Tokens);
|
public record BoundVariableDeclaration(string Name, Optional<BoundExpression> Assignment, NubType Type) : BoundStatement;
|
||||||
|
|
||||||
public record BoundContinue(IReadOnlyList<Token> Tokens) : BoundStatement(Tokens);
|
public record BoundContinue : BoundStatement;
|
||||||
|
|
||||||
public record BoundBreak(IReadOnlyList<Token> Tokens) : BoundStatement(Tokens);
|
public record BoundBreak : BoundStatement;
|
||||||
|
|
||||||
public record BoundWhile(IReadOnlyList<Token> Tokens, BoundExpression Condition, BoundBlock Body) : BoundStatement(Tokens);
|
public record BoundWhile(BoundExpression Condition, BoundBlock Body) : BoundStatement;
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Binding.Node;
|
namespace NubLang.Syntax.Binding.Node;
|
||||||
|
|
||||||
public record BoundSyntaxTree(string Namespace, IReadOnlyList<BoundDefinition> Definitions, IReadOnlyList<Diagnostic> Diagnostics);
|
public record BoundSyntaxTree(string Namespace, IReadOnlyList<BoundDefinition> Definitions, IReadOnlyList<Diagnostic> Diagnostics);
|
||||||
|
|
||||||
public abstract record BoundNode(IReadOnlyList<Token> Tokens);
|
public abstract record BoundNode;
|
||||||
|
|
||||||
public record BoundBlock(IReadOnlyList<Token> Tokens, IReadOnlyList<BoundStatement> Statements) : BoundNode(Tokens);
|
public record BoundBlock(IReadOnlyList<BoundStatement> Statements) : BoundNode;
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Parsing.Node;
|
namespace NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
public abstract record DefinitionSyntax(IReadOnlyList<Token> Tokens, string Namespace) : SyntaxNode(Tokens);
|
public abstract record DefinitionSyntax(string Namespace) : SyntaxNode;
|
||||||
|
|
||||||
public record FuncParameterSyntax(IReadOnlyList<Token> Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens)
|
public record FuncParameterSyntax(string Name, TypeSyntax Type) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -13,7 +12,7 @@ public record FuncParameterSyntax(IReadOnlyList<Token> Tokens, string Name, Type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record FuncSignatureSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens)
|
public record FuncSignatureSyntax(IReadOnlyList<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -26,7 +25,7 @@ public record FuncSignatureSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<Fun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record LocalFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Tokens, Namespace)
|
public record LocalFuncSyntax(string Namespace, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Namespace)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -35,7 +34,7 @@ public record LocalFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ExternFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Tokens, Namespace)
|
public record ExternFuncSyntax(string Namespace, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Namespace)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -43,7 +42,7 @@ public record ExternFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StructFieldSyntax(IReadOnlyList<Token> Tokens, int Index, string Name, TypeSyntax Type, Optional<ExpressionSyntax> Value) : SyntaxNode(Tokens)
|
public record StructFieldSyntax(int Index, string Name, TypeSyntax Type, Optional<ExpressionSyntax> Value) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -55,7 +54,7 @@ public record StructFieldSyntax(IReadOnlyList<Token> Tokens, int Index, string N
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StructFuncSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens)
|
public record StructFuncSyntax(string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -64,7 +63,7 @@ public record StructFuncSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StructSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<StructFieldSyntax> Fields, IReadOnlyList<StructFuncSyntax> Functions) : DefinitionSyntax(Tokens, Namespace)
|
public record StructSyntax(string Namespace, string Name, IReadOnlyList<StructFieldSyntax> Fields, IReadOnlyList<StructFuncSyntax> Functions) : DefinitionSyntax(Namespace)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -80,7 +79,7 @@ public record StructSyntax(IReadOnlyList<Token> Tokens, string Namespace, string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record InterfaceFuncSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSignatureSyntax Signature) : SyntaxNode(Tokens)
|
public record InterfaceFuncSyntax(string Name, FuncSignatureSyntax Signature) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -88,7 +87,7 @@ public record InterfaceFuncSyntax(IReadOnlyList<Token> Tokens, string Name, Func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record InterfaceSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<InterfaceFuncSyntax> Functions) : DefinitionSyntax(Tokens, Namespace)
|
public record InterfaceSyntax(string Namespace, string Name, IReadOnlyList<InterfaceFuncSyntax> Functions) : DefinitionSyntax(Namespace)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ public enum BinaryOperator
|
|||||||
Divide
|
Divide
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record ExpressionSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Tokens);
|
public abstract record ExpressionSyntax : SyntaxNode;
|
||||||
|
|
||||||
public record BinaryExpressionSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Left, BinaryOperator Operator, ExpressionSyntax Right) : ExpressionSyntax(Tokens)
|
public record BinaryExpressionSyntax(ExpressionSyntax Left, BinaryOperator Operator, ExpressionSyntax Right) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -34,7 +34,7 @@ public record BinaryExpressionSyntax(IReadOnlyList<Token> Tokens, ExpressionSynt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record UnaryExpressionSyntax(IReadOnlyList<Token> Tokens, UnaryOperator Operator, ExpressionSyntax Operand) : ExpressionSyntax(Tokens)
|
public record UnaryExpressionSyntax(UnaryOperator Operator, ExpressionSyntax Operand) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ public record UnaryExpressionSyntax(IReadOnlyList<Token> Tokens, UnaryOperator O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record FuncCallSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Expression, IReadOnlyList<ExpressionSyntax> Parameters) : ExpressionSyntax(Tokens)
|
public record FuncCallSyntax(ExpressionSyntax Expression, IReadOnlyList<ExpressionSyntax> Parameters) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -54,12 +54,12 @@ public record FuncCallSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Expre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record IdentifierSyntax(IReadOnlyList<Token> Tokens, Optional<string> Namespace, string Name) : ExpressionSyntax(Tokens)
|
public record IdentifierSyntax(Optional<string> Namespace, string Name) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ArrayInitializerSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens)
|
public record ArrayInitializerSyntax(ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -68,7 +68,7 @@ public record ArrayInitializerSyntax(IReadOnlyList<Token> Tokens, ExpressionSynt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ArrayIndexAccessSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens)
|
public record ArrayIndexAccessSyntax(ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -77,12 +77,12 @@ public record ArrayIndexAccessSyntax(IReadOnlyList<Token> Tokens, ExpressionSynt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ArrowFuncParameterSyntax(IReadOnlyList<Token> Tokens, string Name) : ExpressionSyntax(Tokens)
|
public record ArrowFuncParameterSyntax(string Name) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ArrowFuncSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<ArrowFuncParameterSyntax> Parameters, BlockSyntax Body) : ExpressionSyntax(Tokens)
|
public record ArrowFuncSyntax(IReadOnlyList<ArrowFuncParameterSyntax> Parameters, BlockSyntax Body) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -95,7 +95,7 @@ public record ArrowFuncSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<ArrowFu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record AddressOfSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens)
|
public record AddressOfSyntax(ExpressionSyntax Expression) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -103,12 +103,12 @@ public record AddressOfSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Expr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record LiteralSyntax(IReadOnlyList<Token> Tokens, string Value, LiteralKind Kind) : ExpressionSyntax(Tokens)
|
public record LiteralSyntax(string Value, LiteralKind Kind) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record MemberAccessSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens)
|
public record MemberAccessSyntax(ExpressionSyntax Target, string Member) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -116,7 +116,7 @@ public record MemberAccessSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StructInitializerSyntax(IReadOnlyList<Token> Tokens, TypeSyntax StructType, Dictionary<string, ExpressionSyntax> Initializers) : ExpressionSyntax(Tokens)
|
public record StructInitializerSyntax(TypeSyntax StructType, Dictionary<string, ExpressionSyntax> Initializers) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -128,7 +128,7 @@ public record StructInitializerSyntax(IReadOnlyList<Token> Tokens, TypeSyntax St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record DereferenceSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens)
|
public record DereferenceSyntax(ExpressionSyntax Expression) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Parsing.Node;
|
namespace NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
public abstract record StatementSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Tokens);
|
public abstract record StatementSyntax : SyntaxNode;
|
||||||
|
|
||||||
public record StatementExpressionSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Expression) : StatementSyntax(Tokens)
|
public record StatementExpressionSyntax(ExpressionSyntax Expression) : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -13,7 +12,7 @@ public record StatementExpressionSyntax(IReadOnlyList<Token> Tokens, ExpressionS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ReturnSyntax(IReadOnlyList<Token> Tokens, Optional<ExpressionSyntax> Value) : StatementSyntax(Tokens)
|
public record ReturnSyntax(Optional<ExpressionSyntax> Value) : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -24,7 +23,7 @@ public record ReturnSyntax(IReadOnlyList<Token> Tokens, Optional<ExpressionSynta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record AssignmentSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Value) : StatementSyntax(Tokens)
|
public record AssignmentSyntax(ExpressionSyntax Target, ExpressionSyntax Value) : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -33,7 +32,7 @@ public record AssignmentSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Tar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record IfSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body, Optional<Variant<IfSyntax, BlockSyntax>> Else) : StatementSyntax(Tokens)
|
public record IfSyntax(ExpressionSyntax Condition, BlockSyntax Body, Optional<Variant<IfSyntax, BlockSyntax>> Else) : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -53,7 +52,7 @@ public record IfSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Condition,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record VariableDeclarationSyntax(IReadOnlyList<Token> Tokens, string Name, Optional<TypeSyntax> ExplicitType, Optional<ExpressionSyntax> Assignment) : StatementSyntax(Tokens)
|
public record VariableDeclarationSyntax(string Name, Optional<TypeSyntax> ExplicitType, Optional<ExpressionSyntax> Assignment) : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -69,17 +68,17 @@ public record VariableDeclarationSyntax(IReadOnlyList<Token> Tokens, string Name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ContinueSyntax(IReadOnlyList<Token> Tokens) : StatementSyntax(Tokens)
|
public record ContinueSyntax : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record BreakSyntax(IReadOnlyList<Token> Tokens) : StatementSyntax(Tokens)
|
public record BreakSyntax : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record WhileSyntax(IReadOnlyList<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body) : StatementSyntax(Tokens)
|
public record WhileSyntax(ExpressionSyntax Condition, BlockSyntax Body) : StatementSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
using NubLang.Diagnostics;
|
|
||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Parsing.Node;
|
namespace NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
public abstract record SyntaxNode(IReadOnlyList<Token> Tokens)
|
public abstract record SyntaxNode
|
||||||
{
|
{
|
||||||
public abstract IEnumerable<SyntaxNode> GetChildren();
|
public abstract IEnumerable<SyntaxNode> GetChildren();
|
||||||
|
|
||||||
@@ -21,7 +18,7 @@ public abstract record SyntaxNode(IReadOnlyList<Token> Tokens)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record SyntaxTree(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<DefinitionSyntax> Definitions, IReadOnlyList<Diagnostic> Diagnostics) : SyntaxNode(Tokens)
|
public record SyntaxTree(string Namespace, IReadOnlyList<DefinitionSyntax> Definitions) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -32,7 +29,7 @@ public record SyntaxTree(IReadOnlyList<Token> Tokens, string Namespace, IReadOnl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record BlockSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<StatementSyntax> Statements) : SyntaxNode(Tokens)
|
public record BlockSyntax(IReadOnlyList<StatementSyntax> Statements) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using NubLang.Syntax.Tokenization;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Parsing.Node;
|
namespace NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
public enum PrimitiveTypeSyntaxKind
|
public enum PrimitiveTypeSyntaxKind
|
||||||
@@ -17,7 +15,7 @@ public enum PrimitiveTypeSyntaxKind
|
|||||||
Bool
|
Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record TypeSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Tokens)
|
public abstract record TypeSyntax : SyntaxNode
|
||||||
{
|
{
|
||||||
public string MangledName()
|
public string MangledName()
|
||||||
{
|
{
|
||||||
@@ -36,7 +34,7 @@ public abstract record TypeSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Toke
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record FuncTypeSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens)
|
public record FuncTypeSyntax(IReadOnlyList<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -49,7 +47,7 @@ public record FuncTypeSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<TypeSynt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record PointerTypeSyntax(IReadOnlyList<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens)
|
public record PointerTypeSyntax(TypeSyntax BaseType) : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -57,32 +55,32 @@ public record PointerTypeSyntax(IReadOnlyList<Token> Tokens, TypeSyntax BaseType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record VoidTypeSyntax(IReadOnlyList<Token> Tokens) : TypeSyntax(Tokens)
|
public record VoidTypeSyntax : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record PrimitiveTypeSyntax(IReadOnlyList<Token> Tokens, PrimitiveTypeSyntaxKind SyntaxKind) : TypeSyntax(Tokens)
|
public record PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind SyntaxKind) : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CStringTypeSyntax(IReadOnlyList<Token> Tokens) : TypeSyntax(Tokens)
|
public record CStringTypeSyntax : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StringTypeSyntax(IReadOnlyList<Token> Tokens) : TypeSyntax(Tokens)
|
public record StringTypeSyntax : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CustomTypeSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name) : TypeSyntax(Tokens)
|
public record CustomTypeSyntax(string Namespace, string Name) : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ArrayTypeSyntax(IReadOnlyList<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens)
|
public record ArrayTypeSyntax(TypeSyntax BaseType) : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public sealed class Parser
|
|||||||
private string _namespace;
|
private string _namespace;
|
||||||
private readonly IReadOnlyList<Token> _tokens;
|
private readonly IReadOnlyList<Token> _tokens;
|
||||||
|
|
||||||
private readonly List<Diagnostic> _diagnostics = [];
|
private List<Diagnostic> _diagnostics = [];
|
||||||
private int _tokenIndex;
|
private int _tokenIndex;
|
||||||
|
|
||||||
public Parser(IReadOnlyList<Token> tokens)
|
public Parser(IReadOnlyList<Token> tokens)
|
||||||
@@ -20,9 +20,9 @@ public sealed class Parser
|
|||||||
_tokens = tokens;
|
_tokens = tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxTree Parse()
|
public SyntaxTree Parse(out IReadOnlyList<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_diagnostics.Clear();
|
_diagnostics = [];
|
||||||
_tokenIndex = 0;
|
_tokenIndex = 0;
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Namespace))
|
if (TryExpectSymbol(Symbol.Namespace))
|
||||||
@@ -34,22 +34,19 @@ public sealed class Parser
|
|||||||
|
|
||||||
while (Peek().HasValue)
|
while (Peek().HasValue)
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var keyword = ExpectSymbol();
|
var keyword = ExpectSymbol();
|
||||||
|
|
||||||
var definition = keyword.Symbol switch
|
var definition = keyword.Symbol switch
|
||||||
{
|
{
|
||||||
Symbol.Extern => ParseExtern(startIndex),
|
Symbol.Extern => ParseExtern(),
|
||||||
Symbol.Func => ParseFunc(startIndex),
|
Symbol.Func => ParseFunc(),
|
||||||
Symbol.Struct => ParseStruct(startIndex),
|
Symbol.Struct => ParseStruct(),
|
||||||
Symbol.Interface => ParseInterface(startIndex),
|
Symbol.Interface => ParseInterface(),
|
||||||
_ => throw new ParseException(Diagnostic
|
_ => throw new ParseException(Diagnostic
|
||||||
.Error($"Expected 'extern', 'func', 'struct', 'trait' or 'impl' but found '{keyword.Symbol}'")
|
.Error($"Expected 'extern', 'func', 'struct' or 'interface' but found '{keyword.Symbol}'")
|
||||||
.WithHelp("Valid definition keywords are 'extern', 'func', 'struct', 'trait' and 'impl'")
|
.WithHelp("Valid definition keywords are 'extern', 'func', 'struct' and 'interface'")
|
||||||
.At(keyword)
|
|
||||||
.Build())
|
.Build())
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,13 +68,12 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SyntaxTree(_tokens, _namespace, definitions, _diagnostics);
|
diagnostics = _diagnostics;
|
||||||
|
return new SyntaxTree(_namespace, definitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
|
|
||||||
List<FuncParameterSyntax> parameters = [];
|
List<FuncParameterSyntax> parameters = [];
|
||||||
|
|
||||||
if (thisArg != null)
|
if (thisArg != null)
|
||||||
@@ -96,38 +92,36 @@ public sealed class Parser
|
|||||||
_diagnostics.Add(Diagnostic
|
_diagnostics.Add(Diagnostic
|
||||||
.Warning("Missing comma between function parameters")
|
.Warning("Missing comma between function parameters")
|
||||||
.WithHelp("Add a ',' to separate parameters")
|
.WithHelp("Add a ',' to separate parameters")
|
||||||
.At(token)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax([GetTokens(startIndex).Last()]);
|
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax();
|
||||||
|
|
||||||
return new FuncSignatureSyntax(GetTokens(startIndex), parameters, returnType);
|
return new FuncSignatureSyntax(parameters, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncParameterSyntax ParseFuncParameter()
|
private FuncParameterSyntax ParseFuncParameter()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
ExpectSymbol(Symbol.Colon);
|
ExpectSymbol(Symbol.Colon);
|
||||||
var type = ParseType();
|
var type = ParseType();
|
||||||
|
|
||||||
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
|
return new FuncParameterSyntax(name.Value, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefinitionSyntax ParseExtern(int startIndex)
|
private DefinitionSyntax ParseExtern()
|
||||||
{
|
{
|
||||||
var keyword = ExpectSymbol();
|
var keyword = ExpectSymbol();
|
||||||
|
|
||||||
return keyword.Symbol switch
|
return keyword.Symbol switch
|
||||||
{
|
{
|
||||||
Symbol.Func => ParseExternFunc(startIndex),
|
Symbol.Func => ParseExternFunc(),
|
||||||
_ => throw new ParseException(Diagnostic.Error($"Unexpected symbol {keyword.Symbol} after extern declaration").At(keyword).Build())
|
_ => throw new ParseException(Diagnostic.Error($"Unexpected symbol {keyword.Symbol} after extern declaration").Build())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExternFuncSyntax ParseExternFunc(int startIndex)
|
private ExternFuncSyntax ParseExternFunc()
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
|
|
||||||
@@ -140,19 +134,19 @@ public sealed class Parser
|
|||||||
|
|
||||||
var signature = ParseFuncSignature();
|
var signature = ParseFuncSignature();
|
||||||
|
|
||||||
return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, signature);
|
return new ExternFuncSyntax(_namespace, name.Value, callName, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalFuncSyntax ParseFunc(int startIndex)
|
private LocalFuncSyntax ParseFunc()
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
var signature = ParseFuncSignature();
|
var signature = ParseFuncSignature();
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
|
|
||||||
return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, signature, body);
|
return new LocalFuncSyntax(_namespace, name.Value, signature, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefinitionSyntax ParseStruct(int startIndex)
|
private DefinitionSyntax ParseStruct()
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
|
|
||||||
@@ -165,16 +159,14 @@ public sealed class Parser
|
|||||||
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||||
{
|
{
|
||||||
var memberStartIndex = _tokenIndex;
|
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Func))
|
if (TryExpectSymbol(Symbol.Func))
|
||||||
{
|
{
|
||||||
var funcName = ExpectIdentifier().Value;
|
var funcName = ExpectIdentifier().Value;
|
||||||
var thisArg = new FuncParameterSyntax([], "this", new CustomTypeSyntax([], _namespace, name.Value));
|
var thisArg = new FuncParameterSyntax("this", new CustomTypeSyntax(_namespace, name.Value));
|
||||||
var funcSignature = ParseFuncSignature(thisArg);
|
var funcSignature = ParseFuncSignature(thisArg);
|
||||||
var funcBody = ParseBlock();
|
var funcBody = ParseBlock();
|
||||||
|
|
||||||
funcs.Add(new StructFuncSyntax(GetTokens(memberStartIndex), funcName, funcSignature, funcBody));
|
funcs.Add(new StructFuncSyntax(funcName, funcSignature, funcBody));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -189,14 +181,14 @@ public sealed class Parser
|
|||||||
fieldValue = ParseExpression();
|
fieldValue = ParseExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldIndex++, fieldName, fieldType, fieldValue));
|
fields.Add(new StructFieldSyntax(fieldIndex++, fieldName, fieldType, fieldValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StructSyntax(GetTokens(startIndex), _namespace, name.Value, fields, funcs);
|
return new StructSyntax(_namespace, name.Value, fields, funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InterfaceSyntax ParseInterface(int startIndex)
|
private InterfaceSyntax ParseInterface()
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
|
|
||||||
@@ -206,27 +198,23 @@ public sealed class Parser
|
|||||||
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||||
{
|
{
|
||||||
var funcStartIndex = _tokenIndex;
|
|
||||||
|
|
||||||
ExpectSymbol(Symbol.Func);
|
ExpectSymbol(Symbol.Func);
|
||||||
|
|
||||||
var funcName = ExpectIdentifier().Value;
|
var funcName = ExpectIdentifier().Value;
|
||||||
var signature = ParseFuncSignature();
|
var signature = ParseFuncSignature();
|
||||||
|
|
||||||
functions.Add(new InterfaceFuncSyntax(GetTokens(funcStartIndex), funcName, signature));
|
functions.Add(new InterfaceFuncSyntax(funcName, signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new InterfaceSyntax(GetTokens(startIndex), _namespace, name.Value, functions);
|
return new InterfaceSyntax(_namespace, name.Value, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseStatement()
|
private StatementSyntax ParseStatement()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
if (!Peek().TryGetValue(out var token))
|
if (!Peek().TryGetValue(out var token))
|
||||||
{
|
{
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Unexpected end of file while parsing statement")
|
.Error("Unexpected end of file while parsing statement")
|
||||||
.At(_tokens[^1])
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,37 +223,37 @@ public sealed class Parser
|
|||||||
switch (symbol.Symbol)
|
switch (symbol.Symbol)
|
||||||
{
|
{
|
||||||
case Symbol.Return:
|
case Symbol.Return:
|
||||||
return ParseReturn(startIndex);
|
return ParseReturn();
|
||||||
case Symbol.If:
|
case Symbol.If:
|
||||||
return ParseIf(startIndex);
|
return ParseIf();
|
||||||
case Symbol.While:
|
case Symbol.While:
|
||||||
return ParseWhile(startIndex);
|
return ParseWhile();
|
||||||
case Symbol.Let:
|
case Symbol.Let:
|
||||||
return ParseVariableDeclaration(startIndex);
|
return ParseVariableDeclaration();
|
||||||
case Symbol.Break:
|
case Symbol.Break:
|
||||||
return ParseBreak(startIndex);
|
return ParseBreak();
|
||||||
case Symbol.Continue:
|
case Symbol.Continue:
|
||||||
return ParseContinue(startIndex);
|
return ParseContinue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseStatementExpression(startIndex);
|
return ParseStatementExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseStatementExpression(int startIndex)
|
private StatementSyntax ParseStatementExpression()
|
||||||
{
|
{
|
||||||
var expr = ParseExpression();
|
var expr = ParseExpression();
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Assign))
|
if (TryExpectSymbol(Symbol.Assign))
|
||||||
{
|
{
|
||||||
var value = ParseExpression();
|
var value = ParseExpression();
|
||||||
return new AssignmentSyntax(GetTokens(startIndex), expr, value);
|
return new AssignmentSyntax(expr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StatementExpressionSyntax(GetTokens(startIndex), expr);
|
return new StatementExpressionSyntax(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VariableDeclarationSyntax ParseVariableDeclaration(int startIndex)
|
private VariableDeclarationSyntax ParseVariableDeclaration()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.Let);
|
ExpectSymbol(Symbol.Let);
|
||||||
var name = ExpectIdentifier().Value;
|
var name = ExpectIdentifier().Value;
|
||||||
@@ -282,23 +270,23 @@ public sealed class Parser
|
|||||||
assignment = ParseExpression();
|
assignment = ParseExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new VariableDeclarationSyntax(GetTokens(startIndex), name, explicitType, assignment);
|
return new VariableDeclarationSyntax(name, explicitType, assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseBreak(int startIndex)
|
private StatementSyntax ParseBreak()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.Break);
|
ExpectSymbol(Symbol.Break);
|
||||||
Next();
|
Next();
|
||||||
return new BreakSyntax(GetTokens(startIndex));
|
return new BreakSyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseContinue(int startIndex)
|
private StatementSyntax ParseContinue()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.Continue);
|
ExpectSymbol(Symbol.Continue);
|
||||||
return new ContinueSyntax(GetTokens(startIndex));
|
return new ContinueSyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReturnSyntax ParseReturn(int startIndex)
|
private ReturnSyntax ParseReturn()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.Return);
|
ExpectSymbol(Symbol.Return);
|
||||||
|
|
||||||
@@ -309,10 +297,10 @@ public sealed class Parser
|
|||||||
value = ParseExpression();
|
value = ParseExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ReturnSyntax(GetTokens(startIndex), value);
|
return new ReturnSyntax(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IfSyntax ParseIf(int startIndex)
|
private IfSyntax ParseIf()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.If);
|
ExpectSymbol(Symbol.If);
|
||||||
var condition = ParseExpression();
|
var condition = ParseExpression();
|
||||||
@@ -321,26 +309,24 @@ public sealed class Parser
|
|||||||
var elseStatement = Optional<Variant<IfSyntax, BlockSyntax>>.Empty();
|
var elseStatement = Optional<Variant<IfSyntax, BlockSyntax>>.Empty();
|
||||||
if (TryExpectSymbol(Symbol.Else))
|
if (TryExpectSymbol(Symbol.Else))
|
||||||
{
|
{
|
||||||
var newStartIndex = _tokenIndex;
|
|
||||||
elseStatement = TryExpectSymbol(Symbol.If)
|
elseStatement = TryExpectSymbol(Symbol.If)
|
||||||
? (Variant<IfSyntax, BlockSyntax>)ParseIf(newStartIndex)
|
? (Variant<IfSyntax, BlockSyntax>)ParseIf()
|
||||||
: (Variant<IfSyntax, BlockSyntax>)ParseBlock();
|
: (Variant<IfSyntax, BlockSyntax>)ParseBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IfSyntax(GetTokens(startIndex), condition, body, elseStatement);
|
return new IfSyntax(condition, body, elseStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WhileSyntax ParseWhile(int startIndex)
|
private WhileSyntax ParseWhile()
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.While);
|
ExpectSymbol(Symbol.While);
|
||||||
var condition = ParseExpression();
|
var condition = ParseExpression();
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
return new WhileSyntax(GetTokens(startIndex), condition, body);
|
return new WhileSyntax(condition, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionSyntax ParseExpression(int precedence = 0)
|
private ExpressionSyntax ParseExpression(int precedence = 0)
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
var left = ParsePrimaryExpression();
|
var left = ParsePrimaryExpression();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
@@ -355,7 +341,7 @@ public sealed class Parser
|
|||||||
Next();
|
Next();
|
||||||
var right = ParseExpression(GetBinaryOperatorPrecedence(op.Value) + 1);
|
var right = ParseExpression(GetBinaryOperatorPrecedence(op.Value) + 1);
|
||||||
|
|
||||||
left = new BinaryExpressionSyntax(GetTokens(startIndex), left, op.Value, right);
|
left = new BinaryExpressionSyntax(left, op.Value, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
@@ -421,7 +407,6 @@ public sealed class Parser
|
|||||||
|
|
||||||
private ExpressionSyntax ParsePrimaryExpression()
|
private ExpressionSyntax ParsePrimaryExpression()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
ExpressionSyntax expr;
|
ExpressionSyntax expr;
|
||||||
|
|
||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
@@ -429,7 +414,7 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
case LiteralToken literal:
|
case LiteralToken literal:
|
||||||
{
|
{
|
||||||
expr = new LiteralSyntax(GetTokens(startIndex), literal.Value, literal.Kind);
|
expr = new LiteralSyntax(literal.Value, literal.Kind);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IdentifierToken identifier:
|
case IdentifierToken identifier:
|
||||||
@@ -442,7 +427,7 @@ public sealed class Parser
|
|||||||
name = ExpectIdentifier().Value;
|
name = ExpectIdentifier().Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = new IdentifierSyntax(GetTokens(startIndex), @namespace, name);
|
expr = new IdentifierSyntax(@namespace, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolToken symbolToken:
|
case SymbolToken symbolToken:
|
||||||
@@ -455,27 +440,24 @@ public sealed class Parser
|
|||||||
ExpectSymbol(Symbol.OpenParen);
|
ExpectSymbol(Symbol.OpenParen);
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||||
{
|
{
|
||||||
var parameterStartIndex = _tokenIndex;
|
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
parameters.Add(new ArrowFuncParameterSyntax(GetTokens(parameterStartIndex), name.Value));
|
parameters.Add(new ArrowFuncParameterSyntax(name.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockSyntax body;
|
BlockSyntax body;
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Arrow))
|
if (TryExpectSymbol(Symbol.Arrow))
|
||||||
{
|
{
|
||||||
var blockStartIndex = _tokenIndex;
|
|
||||||
var returnValue = ParseExpression();
|
var returnValue = ParseExpression();
|
||||||
var tokens = GetTokens(blockStartIndex);
|
var arrowExpression = new ReturnSyntax(returnValue);
|
||||||
var arrowExpression = new ReturnSyntax(tokens, returnValue);
|
body = new BlockSyntax([arrowExpression]);
|
||||||
body = new BlockSyntax(tokens, [arrowExpression]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
body = ParseBlock();
|
body = ParseBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = new ArrowFuncSyntax(GetTokens(startIndex), parameters, body);
|
expr = new ArrowFuncSyntax(parameters, body);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.OpenParen:
|
case Symbol.OpenParen:
|
||||||
@@ -488,13 +470,13 @@ public sealed class Parser
|
|||||||
case Symbol.Minus:
|
case Symbol.Minus:
|
||||||
{
|
{
|
||||||
var expression = ParsePrimaryExpression();
|
var expression = ParsePrimaryExpression();
|
||||||
expr = new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperator.Negate, expression);
|
expr = new UnaryExpressionSyntax(UnaryOperator.Negate, expression);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.Bang:
|
case Symbol.Bang:
|
||||||
{
|
{
|
||||||
var expression = ParsePrimaryExpression();
|
var expression = ParsePrimaryExpression();
|
||||||
expr = new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperator.Invert, expression);
|
expr = new UnaryExpressionSyntax(UnaryOperator.Invert, expression);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.OpenBracket:
|
case Symbol.OpenBracket:
|
||||||
@@ -502,7 +484,7 @@ public sealed class Parser
|
|||||||
var capacity = ParseExpression();
|
var capacity = ParseExpression();
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var type = ParseType();
|
var type = ParseType();
|
||||||
expr = new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
|
expr = new ArrayInitializerSyntax(capacity, type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.Alloc:
|
case Symbol.Alloc:
|
||||||
@@ -518,7 +500,7 @@ public sealed class Parser
|
|||||||
initializers.Add(name, value);
|
initializers.Add(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = new StructInitializerSyntax(GetTokens(startIndex), type, initializers);
|
expr = new StructInitializerSyntax(type, initializers);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -526,7 +508,6 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Unexpected symbol '{symbolToken.Symbol}' in expression")
|
.Error($"Unexpected symbol '{symbolToken.Symbol}' in expression")
|
||||||
.WithHelp("Expected literal, identifier, or '(' to start expression")
|
.WithHelp("Expected literal, identifier, or '(' to start expression")
|
||||||
.At(symbolToken)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,34 +519,33 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Unexpected token '{token.GetType().Name}' in expression")
|
.Error($"Unexpected token '{token.GetType().Name}' in expression")
|
||||||
.WithHelp("Expected literal, identifier, or parenthesized expression")
|
.WithHelp("Expected literal, identifier, or parenthesized expression")
|
||||||
.At(token)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParsePostfixOperators(startIndex, expr);
|
return ParsePostfixOperators(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionSyntax ParsePostfixOperators(int startIndex, ExpressionSyntax expr)
|
private ExpressionSyntax ParsePostfixOperators(ExpressionSyntax expr)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (TryExpectSymbol(Symbol.Ampersand))
|
if (TryExpectSymbol(Symbol.Ampersand))
|
||||||
{
|
{
|
||||||
expr = new AddressOfSyntax(GetTokens(startIndex), expr);
|
expr = new AddressOfSyntax(expr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Caret))
|
if (TryExpectSymbol(Symbol.Caret))
|
||||||
{
|
{
|
||||||
expr = new DereferenceSyntax(GetTokens(startIndex), expr);
|
expr = new DereferenceSyntax(expr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Period))
|
if (TryExpectSymbol(Symbol.Period))
|
||||||
{
|
{
|
||||||
var structMember = ExpectIdentifier().Value;
|
var structMember = ExpectIdentifier().Value;
|
||||||
expr = new MemberAccessSyntax(GetTokens(startIndex), expr, structMember);
|
expr = new MemberAccessSyntax(expr, structMember);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +553,7 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
var index = ParseExpression();
|
var index = ParseExpression();
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
expr = new ArrayIndexAccessSyntax(GetTokens(startIndex), expr, index);
|
expr = new ArrayIndexAccessSyntax(expr, index);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,12 +568,11 @@ public sealed class Parser
|
|||||||
_diagnostics.Add(Diagnostic
|
_diagnostics.Add(Diagnostic
|
||||||
.Warning("Missing comma between function arguments")
|
.Warning("Missing comma between function arguments")
|
||||||
.WithHelp("Add a ',' to separate arguments")
|
.WithHelp("Add a ',' to separate arguments")
|
||||||
.At(nextToken)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = new FuncCallSyntax(GetTokens(startIndex), expr, parameters);
|
expr = new FuncCallSyntax(expr, parameters);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,7 +584,6 @@ public sealed class Parser
|
|||||||
|
|
||||||
private BlockSyntax ParseBlock()
|
private BlockSyntax ParseBlock()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
ExpectSymbol(Symbol.OpenBrace);
|
ExpectSymbol(Symbol.OpenBrace);
|
||||||
List<StatementSyntax> statements = [];
|
List<StatementSyntax> statements = [];
|
||||||
while (Peek().HasValue && !TryExpectSymbol(Symbol.CloseBrace))
|
while (Peek().HasValue && !TryExpectSymbol(Symbol.CloseBrace))
|
||||||
@@ -621,31 +599,29 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BlockSyntax(GetTokens(startIndex), statements);
|
return new BlockSyntax(statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeSyntax ParseType()
|
private TypeSyntax ParseType()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
|
|
||||||
if (TryExpectIdentifier(out var name))
|
if (TryExpectIdentifier(out var name))
|
||||||
{
|
{
|
||||||
return name.Value switch
|
return name.Value switch
|
||||||
{
|
{
|
||||||
"void" => new VoidTypeSyntax(GetTokens(startIndex)),
|
"void" => new VoidTypeSyntax(),
|
||||||
"string" => new StringTypeSyntax(GetTokens(startIndex)),
|
"string" => new StringTypeSyntax(),
|
||||||
"cstring" => new CStringTypeSyntax(GetTokens(startIndex)),
|
"cstring" => new CStringTypeSyntax(),
|
||||||
"i64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I64),
|
"i64" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.I64),
|
||||||
"i32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I32),
|
"i32" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.I32),
|
||||||
"i16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I16),
|
"i16" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.I16),
|
||||||
"i8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I8),
|
"i8" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.I8),
|
||||||
"u64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U64),
|
"u64" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.U64),
|
||||||
"u32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U32),
|
"u32" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.U32),
|
||||||
"u16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U16),
|
"u16" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.U16),
|
||||||
"u8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U8),
|
"u8" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.U8),
|
||||||
"f64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.F64),
|
"f64" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.F64),
|
||||||
"f32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.F32),
|
"f32" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.F32),
|
||||||
"bool" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.Bool),
|
"bool" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.Bool),
|
||||||
_ => ParseCustomType()
|
_ => ParseCustomType()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -657,14 +633,14 @@ public sealed class Parser
|
|||||||
@namespace = ExpectIdentifier().Value;
|
@namespace = ExpectIdentifier().Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CustomTypeSyntax(GetTokens(startIndex), @namespace, name.Value);
|
return new CustomTypeSyntax(@namespace, name.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Caret))
|
if (TryExpectSymbol(Symbol.Caret))
|
||||||
{
|
{
|
||||||
var baseType = ParseType();
|
var baseType = ParseType();
|
||||||
return new PointerTypeSyntax(GetTokens(startIndex), baseType);
|
return new PointerTypeSyntax(baseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Func))
|
if (TryExpectSymbol(Symbol.Func))
|
||||||
@@ -680,21 +656,20 @@ public sealed class Parser
|
|||||||
_diagnostics.Add(Diagnostic
|
_diagnostics.Add(Diagnostic
|
||||||
.Warning("Missing comma between func type arguments")
|
.Warning("Missing comma between func type arguments")
|
||||||
.WithHelp("Add a ',' to separate arguments")
|
.WithHelp("Add a ',' to separate arguments")
|
||||||
.At(nextToken)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax(GetTokens(startIndex));
|
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax();
|
||||||
|
|
||||||
return new FuncTypeSyntax(GetTokens(startIndex), parameters, returnType);
|
return new FuncTypeSyntax(parameters, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.OpenBracket))
|
if (TryExpectSymbol(Symbol.OpenBracket))
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var baseType = ParseType();
|
var baseType = ParseType();
|
||||||
return new ArrayTypeSyntax(GetTokens(startIndex), baseType);
|
return new ArrayTypeSyntax(baseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Peek().TryGetValue(out var peekToken))
|
if (!Peek().TryGetValue(out var peekToken))
|
||||||
@@ -702,14 +677,12 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Unexpected end of file while parsing type")
|
.Error("Unexpected end of file while parsing type")
|
||||||
.WithHelp("Expected a type name")
|
.WithHelp("Expected a type name")
|
||||||
.At(_tokens[^1])
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Invalid type Syntax")
|
.Error("Invalid type Syntax")
|
||||||
.WithHelp("Expected type name, '^' for pointer, or '[]' for array")
|
.WithHelp("Expected type name, '^' for pointer, or '[]' for array")
|
||||||
.At(peekToken)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,7 +693,6 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Unexpected end of file")
|
.Error("Unexpected end of file")
|
||||||
.WithHelp("Expected more tokens to complete the Syntax")
|
.WithHelp("Expected more tokens to complete the Syntax")
|
||||||
.At(_tokens.Last())
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,7 +708,6 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Expected symbol, but found {token.GetType().Name}")
|
.Error($"Expected symbol, but found {token.GetType().Name}")
|
||||||
.WithHelp("This position requires a symbol like '(', ')', '{', '}', etc.")
|
.WithHelp("This position requires a symbol like '(', ')', '{', '}', etc.")
|
||||||
.At(token)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,7 +722,6 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Expected '{expectedSymbol}', but found '{token.Symbol}'")
|
.Error($"Expected '{expectedSymbol}', but found '{token.Symbol}'")
|
||||||
.WithHelp($"Insert '{expectedSymbol}' here")
|
.WithHelp($"Insert '{expectedSymbol}' here")
|
||||||
.At(token)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -788,7 +758,6 @@ public sealed class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error($"Expected identifier, but found {token.GetType().Name}")
|
.Error($"Expected identifier, but found {token.GetType().Name}")
|
||||||
.WithHelp("Provide a valid identifier name here")
|
.WithHelp("Provide a valid identifier name here")
|
||||||
.At(token)
|
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,11 +779,6 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
_tokenIndex++;
|
_tokenIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Token> GetTokens(int startIndex)
|
|
||||||
{
|
|
||||||
return _tokens.Skip(startIndex).Take(Math.Min(_tokenIndex, _tokens.Count - 1) - startIndex).ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ParseException : Exception
|
public class ParseException : Exception
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
namespace NubLang.Syntax.Tokenization;
|
namespace NubLang.Syntax.Tokenization;
|
||||||
|
|
||||||
public abstract class Token(SourceSpan span)
|
public abstract class Token;
|
||||||
{
|
|
||||||
public SourceSpan Span { get; } = span;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IdentifierToken(SourceSpan span, string value) : Token(span)
|
public class IdentifierToken(string value) : Token
|
||||||
{
|
{
|
||||||
public string Value { get; } = value;
|
public string Value { get; } = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LiteralToken(SourceSpan span, LiteralKind kind, string value) : Token(span)
|
public class LiteralToken(LiteralKind kind, string value) : Token
|
||||||
{
|
{
|
||||||
public LiteralKind Kind { get; } = kind;
|
public LiteralKind Kind { get; } = kind;
|
||||||
public string Value { get; } = value;
|
public string Value { get; } = value;
|
||||||
@@ -24,7 +21,7 @@ public enum LiteralKind
|
|||||||
Bool
|
Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SymbolToken(SourceSpan span, Symbol symbol) : Token(span)
|
public class SymbolToken(Symbol symbol) : Token
|
||||||
{
|
{
|
||||||
public Symbol Symbol { get; } = symbol;
|
public Symbol Symbol { get; } = symbol;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public sealed class Tokenizer
|
|||||||
["extern"] = Symbol.Extern,
|
["extern"] = Symbol.Extern,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<char[], Symbol> Chians = new()
|
private static readonly Dictionary<char[], Symbol> Symbols = new()
|
||||||
{
|
{
|
||||||
[['=', '=']] = Symbol.Equal,
|
[['=', '=']] = Symbol.Equal,
|
||||||
[['!', '=']] = Symbol.NotEqual,
|
[['!', '=']] = Symbol.NotEqual,
|
||||||
@@ -32,36 +32,32 @@ public sealed class Tokenizer
|
|||||||
[['>', '=']] = Symbol.GreaterThanOrEqual,
|
[['>', '=']] = Symbol.GreaterThanOrEqual,
|
||||||
[[':', ':']] = Symbol.DoubleColon,
|
[[':', ':']] = Symbol.DoubleColon,
|
||||||
[['=', '>']] = Symbol.Arrow,
|
[['=', '>']] = Symbol.Arrow,
|
||||||
|
[[':']] = Symbol.Colon,
|
||||||
|
[['(']] = Symbol.OpenParen,
|
||||||
|
[[')']] = Symbol.CloseParen,
|
||||||
|
[['{']] = Symbol.OpenBrace,
|
||||||
|
[['}']] = Symbol.CloseBrace,
|
||||||
|
[['[']] = Symbol.OpenBracket,
|
||||||
|
[[']']] = Symbol.CloseBracket,
|
||||||
|
[[',']] = Symbol.Comma,
|
||||||
|
[['.']] = Symbol.Period,
|
||||||
|
[['=']] = Symbol.Assign,
|
||||||
|
[['<']] = Symbol.LessThan,
|
||||||
|
[['>']] = Symbol.GreaterThan,
|
||||||
|
[['+']] = Symbol.Plus,
|
||||||
|
[['-']] = Symbol.Minus,
|
||||||
|
[['*']] = Symbol.Star,
|
||||||
|
[['/']] = Symbol.ForwardSlash,
|
||||||
|
[['!']] = Symbol.Bang,
|
||||||
|
[['^']] = Symbol.Caret,
|
||||||
|
[['&']] = Symbol.Ampersand,
|
||||||
|
[[';']] = Symbol.Semi,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<char, Symbol> Chars = new()
|
private readonly string _sourceText;
|
||||||
{
|
|
||||||
[':'] = Symbol.Colon,
|
|
||||||
['('] = Symbol.OpenParen,
|
|
||||||
[')'] = Symbol.CloseParen,
|
|
||||||
['{'] = Symbol.OpenBrace,
|
|
||||||
['}'] = Symbol.CloseBrace,
|
|
||||||
['['] = Symbol.OpenBracket,
|
|
||||||
[']'] = Symbol.CloseBracket,
|
|
||||||
[','] = Symbol.Comma,
|
|
||||||
['.'] = Symbol.Period,
|
|
||||||
['='] = Symbol.Assign,
|
|
||||||
['<'] = Symbol.LessThan,
|
|
||||||
['>'] = Symbol.GreaterThan,
|
|
||||||
['+'] = Symbol.Plus,
|
|
||||||
['-'] = Symbol.Minus,
|
|
||||||
['*'] = Symbol.Star,
|
|
||||||
['/'] = Symbol.ForwardSlash,
|
|
||||||
['!'] = Symbol.Bang,
|
|
||||||
['^'] = Symbol.Caret,
|
|
||||||
['&'] = Symbol.Ampersand,
|
|
||||||
[';'] = Symbol.Semi,
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly SourceText _sourceText;
|
|
||||||
private int _index;
|
private int _index;
|
||||||
|
|
||||||
public Tokenizer(SourceText sourceText)
|
public Tokenizer(string sourceText)
|
||||||
{
|
{
|
||||||
_sourceText = sourceText;
|
_sourceText = sourceText;
|
||||||
}
|
}
|
||||||
@@ -122,15 +118,15 @@ public sealed class Tokenizer
|
|||||||
|
|
||||||
if (Keywords.TryGetValue(buffer, out var keywordSymbol))
|
if (Keywords.TryGetValue(buffer, out var keywordSymbol))
|
||||||
{
|
{
|
||||||
return new SymbolToken(CreateSpan(startIndex), keywordSymbol);
|
return new SymbolToken(keywordSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer is "true" or "false")
|
if (buffer is "true" or "false")
|
||||||
{
|
{
|
||||||
return new LiteralToken(CreateSpan(startIndex), LiteralKind.Bool, buffer);
|
return new LiteralToken(LiteralKind.Bool, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IdentifierToken(CreateSpan(startIndex), buffer);
|
return new IdentifierToken(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (char.IsDigit(current))
|
if (char.IsDigit(current))
|
||||||
@@ -162,15 +158,12 @@ public sealed class Tokenizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(CreateSpan(startIndex), isFloat ? LiteralKind.Float : LiteralKind.Integer, buffer);
|
return new LiteralToken(isFloat ? LiteralKind.Float : LiteralKind.Integer, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Revisit this
|
foreach (var chain in Symbols)
|
||||||
foreach (var chain in Chians)
|
|
||||||
{
|
{
|
||||||
if (current != chain.Key[0]) continue;
|
for (var i = 0; i < chain.Key.Length; i++)
|
||||||
|
|
||||||
for (var i = 1; i < chain.Key.Length; i++)
|
|
||||||
{
|
{
|
||||||
var c = Peek(i);
|
var c = Peek(i);
|
||||||
if (!c.HasValue || c.Value != chain.Key[i]) break;
|
if (!c.HasValue || c.Value != chain.Key[i]) break;
|
||||||
@@ -182,17 +175,11 @@ public sealed class Tokenizer
|
|||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SymbolToken(CreateSpan(startIndex), chain.Value);
|
return new SymbolToken(chain.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Chars.TryGetValue(current, out var charSymbol))
|
|
||||||
{
|
|
||||||
Next();
|
|
||||||
return new SymbolToken(CreateSpan(startIndex), charSymbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == '"')
|
if (current == '"')
|
||||||
{
|
{
|
||||||
Next();
|
Next();
|
||||||
@@ -215,42 +202,17 @@ public sealed class Tokenizer
|
|||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(CreateSpan(startIndex), LiteralKind.String, buffer);
|
return new LiteralToken(LiteralKind.String, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception($"Unknown character {current}");
|
throw new Exception($"Unknown character {current}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceLocation CreateLocation(int index)
|
|
||||||
{
|
|
||||||
var line = 1;
|
|
||||||
var column = 1;
|
|
||||||
for (var i = 0; i < Math.Min(index, _sourceText.Content.Length - 1); i++)
|
|
||||||
{
|
|
||||||
if (_sourceText.Content[i] == '\n')
|
|
||||||
{
|
|
||||||
column = 1;
|
|
||||||
line += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
column += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceLocation(line, column);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SourceSpan CreateSpan(int startIndex)
|
|
||||||
{
|
|
||||||
return new SourceSpan(_sourceText, CreateLocation(startIndex), CreateLocation(_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<char> Peek(int offset = 0)
|
private Optional<char> Peek(int offset = 0)
|
||||||
{
|
{
|
||||||
if (_index + offset < _sourceText.Content.Length)
|
if (_index + offset < _sourceText.Length)
|
||||||
{
|
{
|
||||||
return _sourceText.Content[_index + offset];
|
return _sourceText[_index + offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional<char>.Empty();
|
return Optional<char>.Empty();
|
||||||
@@ -258,9 +220,9 @@ public sealed class Tokenizer
|
|||||||
|
|
||||||
private Optional<char> Next()
|
private Optional<char> Next()
|
||||||
{
|
{
|
||||||
if (_index < _sourceText.Content.Length)
|
if (_index < _sourceText.Length)
|
||||||
{
|
{
|
||||||
return _sourceText.Content[_index++];
|
return _sourceText[_index++];
|
||||||
}
|
}
|
||||||
|
|
||||||
_index++;
|
_index++;
|
||||||
|
|||||||
Reference in New Issue
Block a user