...
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Reflection;
|
|||||||
using CLI;
|
using CLI;
|
||||||
using Generation.QBE;
|
using Generation.QBE;
|
||||||
using Syntax;
|
using Syntax;
|
||||||
|
using Syntax.Diagnostics;
|
||||||
using Syntax.Parsing;
|
using Syntax.Parsing;
|
||||||
using Syntax.Tokenization;
|
using Syntax.Tokenization;
|
||||||
using Syntax.Typing;
|
using Syntax.Typing;
|
||||||
@@ -23,7 +24,7 @@ if (Directory.Exists(BIN_INT_DIR))
|
|||||||
Directory.CreateDirectory(BIN_DIR);
|
Directory.CreateDirectory(BIN_DIR);
|
||||||
Directory.CreateDirectory(BIN_INT_DIR);
|
Directory.CreateDirectory(BIN_INT_DIR);
|
||||||
|
|
||||||
var error = false;
|
var diagnostics = new List<Diagnostic>();
|
||||||
var compilationUnits = new List<CompilationUnit>();
|
var compilationUnits = new List<CompilationUnit>();
|
||||||
var sourceTexts = new Dictionary<CompilationUnit, SourceText>();
|
var sourceTexts = new Dictionary<CompilationUnit, SourceText>();
|
||||||
|
|
||||||
@@ -34,41 +35,44 @@ foreach (var file in args)
|
|||||||
Console.Error.WriteLine($"File '{file}' does not exist");
|
Console.Error.WriteLine($"File '{file}' does not exist");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var content = File.ReadAllText(file);
|
|
||||||
|
|
||||||
var sourceText = new SourceText(file, content);
|
|
||||||
|
|
||||||
var tokenizeResult = Tokenizer.Tokenize(sourceText);
|
|
||||||
tokenizeResult.PrintAllDiagnostics();
|
|
||||||
error = error || tokenizeResult.HasErrors;
|
|
||||||
|
|
||||||
var parseResult = Parser.ParseFile(tokenizeResult.Value);
|
|
||||||
parseResult.PrintAllDiagnostics();
|
|
||||||
error = error || parseResult.HasErrors;
|
|
||||||
|
|
||||||
if (parseResult.Value != null)
|
|
||||||
{
|
|
||||||
compilationUnits.Add(parseResult.Value);
|
|
||||||
sourceTexts[parseResult.Value] = sourceText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
foreach (var file in args)
|
||||||
{
|
{
|
||||||
return 1;
|
var content = File.ReadAllText(file);
|
||||||
|
var sourceText = new SourceText(file, content);
|
||||||
|
|
||||||
|
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
|
||||||
|
diagnostics.AddRange(tokenizerDiagnostics);
|
||||||
|
|
||||||
|
var compilationUnit = Parser.ParseFile(tokenizeResult, out var parseDiagnostics);
|
||||||
|
diagnostics.AddRange(parseDiagnostics);
|
||||||
|
|
||||||
|
if (compilationUnit != null)
|
||||||
|
{
|
||||||
|
compilationUnits.Add(compilationUnit);
|
||||||
|
sourceTexts[compilationUnit] = sourceText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var definitionTable = new DefinitionTable(compilationUnits);
|
var definitionTable = new DefinitionTable(compilationUnits);
|
||||||
|
|
||||||
foreach (var compilationUnit in compilationUnits)
|
foreach (var compilationUnit in compilationUnits)
|
||||||
{
|
{
|
||||||
var typeCheckResult = TypeChecker.Check(compilationUnit, definitionTable);
|
TypeChecker.Check(compilationUnit, definitionTable, out var typeCheckerDiagnostics);
|
||||||
typeCheckResult.PrintAllDiagnostics();
|
diagnostics.AddRange(typeCheckerDiagnostics);
|
||||||
error = error || typeCheckResult.HasErrors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
foreach (var diagnostic in diagnostics)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(diagnostic.FormatANSI());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -83,11 +87,11 @@ foreach (var compilationUnit in compilationUnits)
|
|||||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||||
Debug.Assert(!string.IsNullOrWhiteSpace(outputDirectory));
|
Debug.Assert(!string.IsNullOrWhiteSpace(outputDirectory));
|
||||||
Directory.CreateDirectory(outputDirectory);
|
Directory.CreateDirectory(outputDirectory);
|
||||||
|
|
||||||
var ssa = QBEGenerator.Emit(compilationUnit, definitionTable);
|
var ssa = QBEGenerator.Emit(compilationUnit, definitionTable);
|
||||||
var ssaPath = Path.ChangeExtension(outputPath, "ssa");
|
var ssaPath = Path.ChangeExtension(outputPath, "ssa");
|
||||||
File.WriteAllText(ssaPath, ssa);
|
File.WriteAllText(ssaPath, ssa);
|
||||||
|
|
||||||
var asm = await QBE.Invoke(ssa);
|
var asm = await QBE.Invoke(ssa);
|
||||||
if (asm == null)
|
if (asm == null)
|
||||||
{
|
{
|
||||||
@@ -143,4 +147,4 @@ foreach (var resourceName in runtimeResources)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var linkSuccess = await GCC.Link(objectFiles, Path.Combine(BIN_DIR, "out"));
|
var linkSuccess = await GCC.Link(objectFiles, Path.Combine(BIN_DIR, "out"));
|
||||||
return linkSuccess ? 0 : 1;
|
return linkSuccess ? 0 : 1;
|
||||||
@@ -426,7 +426,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterVars.Add(new Variable(parameter.Name, new Ident(parameterName, parameter.Type)));
|
parameterVars.Add(new Variable(parameter.Name, new Val(parameterName, parameter.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitBlock(body, parameterVars);
|
EmitBlock(body, parameterVars);
|
||||||
@@ -659,14 +659,14 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
var tmp = VarName();
|
var tmp = VarName();
|
||||||
_builder.AppendLine($" {tmp} =l alloc8 {SizeOf(variableDeclaration.Type)}");
|
_builder.AppendLine($" {tmp} =l alloc8 {SizeOf(variableDeclaration.Type)}");
|
||||||
_variables.Push(new Variable(variableDeclaration.Name, new Ident(tmp, variableDeclaration.Type)));
|
_variables.Push(new Variable(variableDeclaration.Name, new Val(tmp, variableDeclaration.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVariableAssignment(VariableAssignmentNode variableAssignment)
|
private static void EmitVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||||
{
|
{
|
||||||
var value = EmitUnwrap(EmitExpression(variableAssignment.Value));
|
var value = EmitUnwrap(EmitExpression(variableAssignment.Value));
|
||||||
var variable = _variables.Single(x => x.Name == variableAssignment.Identifier.Name);
|
var variable = _variables.Single(x => x.Name == variableAssignment.Identifier.Name);
|
||||||
EmitCopy(variableAssignment.Value.Type, value, variable.Ident.Name);
|
EmitCopy(variableAssignment.Value.Type, value, variable.Val.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitWhile(WhileNode whileStatement)
|
private static void EmitWhile(WhileNode whileStatement)
|
||||||
@@ -690,7 +690,7 @@ public static class QBEGenerator
|
|||||||
_breakLabels.Pop();
|
_breakLabels.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitExpression(ExpressionNode expression)
|
private static Val EmitExpression(ExpressionNode expression)
|
||||||
{
|
{
|
||||||
return expression switch
|
return expression switch
|
||||||
{
|
{
|
||||||
@@ -711,11 +711,11 @@ public static class QBEGenerator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitAnonymousFunc(AnonymousFuncNode anonymousFunc)
|
private static Val EmitAnonymousFunc(AnonymousFuncNode anonymousFunc)
|
||||||
{
|
{
|
||||||
var name = $"$anon_func{++_anonymousFuncIndex}";
|
var name = $"$anon_func{++_anonymousFuncIndex}";
|
||||||
_anonymousFunctions.Enqueue((anonymousFunc, name));
|
_anonymousFunctions.Enqueue((anonymousFunc, name));
|
||||||
return new Ident(name, anonymousFunc.Type, IdentKind.Func);
|
return new Val(name, anonymousFunc.Type, ValKind.Func);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EmitArrayIndexPointer(ArrayIndexAccessNode arrayIndexAccess)
|
private static string EmitArrayIndexPointer(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
@@ -738,12 +738,12 @@ public static class QBEGenerator
|
|||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
private static Val EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointer}");
|
_builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointer}");
|
||||||
return new Ident(outputName, arrayIndexAccess.Type);
|
return new Val(outputName, arrayIndexAccess.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitArrayBoundsCheck(string array, string index)
|
private static void EmitArrayBoundsCheck(string array, string index)
|
||||||
@@ -770,7 +770,7 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine(notOobLabel);
|
_builder.AppendLine(notOobLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
|
private static Val EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
|
||||||
{
|
{
|
||||||
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
||||||
var elementSize = SizeOf(arrayInitializer.ElementType);
|
var elementSize = SizeOf(arrayInitializer.ElementType);
|
||||||
@@ -788,24 +788,24 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine($" {dataPointer} =l add {arrayPointer}, 8");
|
_builder.AppendLine($" {dataPointer} =l add {arrayPointer}, 8");
|
||||||
_builder.AppendLine($" call $nub_memset(l {dataPointer}, w 0, l {capacityInBytes})");
|
_builder.AppendLine($" call $nub_memset(l {dataPointer}, w 0, l {capacityInBytes})");
|
||||||
|
|
||||||
return new Ident(arrayPointer, arrayInitializer.Type);
|
return new Val(arrayPointer, arrayInitializer.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitDereference(DereferenceNode dereference)
|
private static Val EmitDereference(DereferenceNode dereference)
|
||||||
{
|
{
|
||||||
var result = EmitUnwrap(EmitExpression(dereference.Expression));
|
var result = EmitUnwrap(EmitExpression(dereference.Expression));
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(dereference.Type)} {QBELoad(dereference.Type)} {result}");
|
_builder.AppendLine($" {outputName} {QBEAssign(dereference.Type)} {QBELoad(dereference.Type)} {result}");
|
||||||
return new Ident(outputName, dereference.Type);
|
return new Val(outputName, dereference.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitAddressOf(AddressOfNode addressOf)
|
private static Val EmitAddressOf(AddressOfNode addressOf)
|
||||||
{
|
{
|
||||||
switch (addressOf.Expression)
|
switch (addressOf.Expression)
|
||||||
{
|
{
|
||||||
case ArrayIndexAccessNode arrayIndexAccess:
|
case ArrayIndexAccessNode arrayIndexAccess:
|
||||||
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
||||||
return new Ident(pointer, addressOf.Type);
|
return new Val(pointer, addressOf.Type);
|
||||||
case DereferenceNode dereference:
|
case DereferenceNode dereference:
|
||||||
return EmitExpression(dereference.Expression);
|
return EmitExpression(dereference.Expression);
|
||||||
case IdentifierNode identifier:
|
case IdentifierNode identifier:
|
||||||
@@ -814,21 +814,21 @@ public static class QBEGenerator
|
|||||||
throw new NotSupportedException("There is nothing to address in another namespace");
|
throw new NotSupportedException("There is nothing to address in another namespace");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _variables.Single(x => x.Name == identifier.Name).Ident;
|
return _variables.Single(x => x.Name == identifier.Name).Val;
|
||||||
case MemberAccessNode memberAccess:
|
case MemberAccessNode memberAccess:
|
||||||
var ptr = EmitMemberAccessPointer(memberAccess);
|
var ptr = EmitMemberAccessPointer(memberAccess);
|
||||||
return new Ident(ptr, addressOf.Type);
|
return new Val(ptr, addressOf.Type);
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
private static Val EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
||||||
{
|
{
|
||||||
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
||||||
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
var output = new Ident(outputName, binaryExpression.Type);
|
var output = new Val(outputName, binaryExpression.Type);
|
||||||
|
|
||||||
switch (binaryExpression.Operator)
|
switch (binaryExpression.Operator)
|
||||||
{
|
{
|
||||||
@@ -1037,31 +1037,31 @@ public static class QBEGenerator
|
|||||||
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitIdentifier(IdentifierNode identifier)
|
private static Val EmitIdentifier(IdentifierNode identifier)
|
||||||
{
|
{
|
||||||
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_compilationUnit.Namespace), identifier.Name).TryGetValue(out var func))
|
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_compilationUnit.Namespace), identifier.Name).TryGetValue(out var func))
|
||||||
{
|
{
|
||||||
return new Ident(FuncName(func), identifier.Type, IdentKind.Func);
|
return new Val(FuncName(func), identifier.Type, ValKind.Func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!identifier.Namespace.HasValue)
|
if (!identifier.Namespace.HasValue)
|
||||||
{
|
{
|
||||||
return _variables.Single(v => v.Name == identifier.Name).Ident;
|
return _variables.Single(v => v.Name == identifier.Name).Val;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitLiteral(LiteralNode literal)
|
private static Val EmitLiteral(LiteralNode literal)
|
||||||
{
|
{
|
||||||
if (literal.Type.IsInteger)
|
if (literal.Type.IsInteger)
|
||||||
{
|
{
|
||||||
switch (literal.Kind)
|
switch (literal.Kind)
|
||||||
{
|
{
|
||||||
case LiteralKind.Integer:
|
case LiteralKind.Integer:
|
||||||
return new Ident(literal.Literal, literal.Type, IdentKind.Literal);
|
return new Val(literal.Literal, literal.Type, ValKind.Literal);
|
||||||
case LiteralKind.Float:
|
case LiteralKind.Float:
|
||||||
return new Ident(literal.Literal.Split(".").First(), literal.Type, IdentKind.Literal);
|
return new Val(literal.Literal.Split(".").First(), literal.Type, ValKind.Literal);
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
@@ -1071,14 +1071,14 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture);
|
var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||||
return new Ident(bits.ToString(), literal.Type, IdentKind.Literal);
|
return new Val(bits.ToString(), literal.Type, ValKind.Literal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type.IsFloat32)
|
if (literal.Type.IsFloat32)
|
||||||
{
|
{
|
||||||
var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture);
|
var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.SingleToInt32Bits(value);
|
var bits = BitConverter.SingleToInt32Bits(value);
|
||||||
return new Ident(bits.ToString(), literal.Type, IdentKind.Literal);
|
return new Val(bits.ToString(), literal.Type, ValKind.Literal);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (literal.Kind)
|
switch (literal.Kind)
|
||||||
@@ -1086,15 +1086,15 @@ public static class QBEGenerator
|
|||||||
case LiteralKind.String:
|
case LiteralKind.String:
|
||||||
var cStringLiteral = new CStringLiteral(literal.Literal, CStringName());
|
var cStringLiteral = new CStringLiteral(literal.Literal, CStringName());
|
||||||
_cStringLiterals.Add(cStringLiteral);
|
_cStringLiterals.Add(cStringLiteral);
|
||||||
return new Ident(cStringLiteral.Name, literal.Type, IdentKind.Literal);
|
return new Val(cStringLiteral.Name, literal.Type, ValKind.Literal);
|
||||||
case LiteralKind.Bool:
|
case LiteralKind.Bool:
|
||||||
return new Ident(bool.Parse(literal.Literal) ? "1" : "0", literal.Type, IdentKind.Literal);
|
return new Val(bool.Parse(literal.Literal) ? "1" : "0", literal.Type, ValKind.Literal);
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitStructInitializer(StructInitializerNode structInitializer)
|
private static Val EmitStructInitializer(StructInitializerNode structInitializer)
|
||||||
{
|
{
|
||||||
var structDefinition = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name).GetValue();
|
var structDefinition = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name).GetValue();
|
||||||
|
|
||||||
@@ -1126,10 +1126,10 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Ident(output, structInitializer.StructType);
|
return new Val(output, structInitializer.StructType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitUnaryExpression(UnaryExpressionNode unaryExpression)
|
private static Val EmitUnaryExpression(UnaryExpressionNode unaryExpression)
|
||||||
{
|
{
|
||||||
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
|
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
@@ -1142,16 +1142,16 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
||||||
_builder.AppendLine($" {outputName} =l neg {operand}");
|
_builder.AppendLine($" {outputName} =l neg {operand}");
|
||||||
return new Ident(outputName, unaryExpression.Type);
|
return new Val(outputName, unaryExpression.Type);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }:
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }:
|
||||||
_builder.AppendLine($" {outputName} =w neg {operand}");
|
_builder.AppendLine($" {outputName} =w neg {operand}");
|
||||||
return new Ident(outputName, unaryExpression.Type);
|
return new Val(outputName, unaryExpression.Type);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
||||||
_builder.AppendLine($" {outputName} =d neg {operand}");
|
_builder.AppendLine($" {outputName} =d neg {operand}");
|
||||||
return new Ident(outputName, unaryExpression.Type);
|
return new Val(outputName, unaryExpression.Type);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
||||||
_builder.AppendLine($" {outputName} =s neg {operand}");
|
_builder.AppendLine($" {outputName} =s neg {operand}");
|
||||||
return new Ident(outputName, unaryExpression.Type);
|
return new Val(outputName, unaryExpression.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1162,7 +1162,7 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }:
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }:
|
||||||
_builder.AppendLine($" {outputName} =w xor {operand}, 1");
|
_builder.AppendLine($" {outputName} =w xor {operand}, 1");
|
||||||
return new Ident(outputName, unaryExpression.Type);
|
return new Val(outputName, unaryExpression.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1206,16 +1206,16 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitMemberAccess(MemberAccessNode memberAccess)
|
private static Val EmitMemberAccess(MemberAccessNode memberAccess)
|
||||||
{
|
{
|
||||||
var pointer = EmitMemberAccessPointer(memberAccess);
|
var pointer = EmitMemberAccessPointer(memberAccess);
|
||||||
|
|
||||||
var output = VarName();
|
var output = VarName();
|
||||||
_builder.AppendLine($" {output} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {pointer}");
|
_builder.AppendLine($" {output} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {pointer}");
|
||||||
return new Ident(output, memberAccess.Type);
|
return new Val(output, memberAccess.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
|
private static Val EmitFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
|
||||||
{
|
{
|
||||||
var totalSize = SizeOf(fixedArrayInitializer.Type);
|
var totalSize = SizeOf(fixedArrayInitializer.Type);
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
@@ -1229,10 +1229,10 @@ public static class QBEGenerator
|
|||||||
var dataSize = totalSize - 8;
|
var dataSize = totalSize - 8;
|
||||||
_builder.AppendLine($" call $nub_memset(l {dataPtr}, w 0, l {dataSize})");
|
_builder.AppendLine($" call $nub_memset(l {dataPtr}, w 0, l {dataSize})");
|
||||||
|
|
||||||
return new Ident(outputName, fixedArrayInitializer.Type);
|
return new Val(outputName, fixedArrayInitializer.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ident EmitFuncCall(FuncCallNode funcCall)
|
private static Val EmitFuncCall(FuncCallNode funcCall)
|
||||||
{
|
{
|
||||||
var funcType = (NubFuncType)funcCall.Expression.Type;
|
var funcType = (NubFuncType)funcCall.Expression.Type;
|
||||||
|
|
||||||
@@ -1277,12 +1277,12 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
return new Ident(outputName, funcCall.Type);
|
return new Val(outputName, funcCall.Type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" call {funcPointer}({string.Join(", ", parameterStrings)})");
|
_builder.AppendLine($" call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
return new Ident(string.Empty, funcCall.Type);
|
return new Val(string.Empty, funcCall.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1298,27 +1298,27 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EmitUnwrap(Ident ident)
|
private static string EmitUnwrap(Val val)
|
||||||
{
|
{
|
||||||
if (ident.Type.IsVoid)
|
if (val.Type.IsVoid)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Cannot unwrap temporary of void type");
|
throw new InvalidOperationException("Cannot unwrap temporary of void type");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ident.Kind)
|
switch (val.Kind)
|
||||||
{
|
{
|
||||||
case IdentKind.Func:
|
case ValKind.Func:
|
||||||
case IdentKind.Literal:
|
case ValKind.Literal:
|
||||||
return ident.Name;
|
return val.Name;
|
||||||
case IdentKind.Variable:
|
case ValKind.Variable:
|
||||||
if (IsPointerType(ident.Type))
|
if (IsPointerType(val.Type))
|
||||||
{
|
{
|
||||||
return ident.Name;
|
return val.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var result = VarName();
|
var result = VarName();
|
||||||
_builder.AppendLine($" {result} {QBEAssign(ident.Type)} {QBELoad(ident.Type)} {ident.Name}");
|
_builder.AppendLine($" {result} {QBEAssign(val.Type)} {QBELoad(val.Type)} {val.Name}");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -1333,17 +1333,17 @@ internal class CStringLiteral(string value, string name)
|
|||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Variable(string name, Ident ident)
|
internal class Variable(string name, Val val)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public Ident Ident { get; } = ident;
|
public Val Val { get; } = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Ident(string name, NubType type, IdentKind kind = IdentKind.Variable)
|
internal class Val(string name, NubType type, ValKind kind = ValKind.Variable)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public NubType Type { get; } = type;
|
public NubType Type { get; } = type;
|
||||||
public IdentKind Kind { get; } = kind;
|
public ValKind Kind { get; } = kind;
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@@ -1351,7 +1351,7 @@ internal class Ident(string name, NubType type, IdentKind kind = IdentKind.Varia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum IdentKind
|
internal enum ValKind
|
||||||
{
|
{
|
||||||
Func,
|
Func,
|
||||||
Variable,
|
Variable,
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public static class ConsoleColors
|
|||||||
public static string ColorizeSource(string source)
|
public static string ColorizeSource(string source)
|
||||||
{
|
{
|
||||||
var sourceText = new SourceText(string.Empty, source);
|
var sourceText = new SourceText(string.Empty, source);
|
||||||
var tokens = Tokenizer.Tokenize(sourceText).Value;
|
var tokens = Tokenizer.Tokenize(sourceText, out _);
|
||||||
var result = new StringBuilder();
|
var result = new StringBuilder();
|
||||||
var lastCharIndex = 0;
|
var lastCharIndex = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class Diagnostic
|
|||||||
Help = help;
|
Help = help;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Format()
|
public string FormatANSI()
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
namespace Syntax.Diagnostics;
|
|
||||||
|
|
||||||
public class DiagnosticsResult(List<Diagnostic> diagnostics)
|
|
||||||
{
|
|
||||||
public bool HasErrors => diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error);
|
|
||||||
|
|
||||||
public void PrintAllDiagnostics()
|
|
||||||
{
|
|
||||||
foreach (var diagnostic in diagnostics)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(diagnostic.Format());
|
|
||||||
Console.Error.WriteLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DiagnosticsResult<TResult>(List<Diagnostic> diagnostics, TResult value) : DiagnosticsResult(diagnostics)
|
|
||||||
{
|
|
||||||
public TResult Value { get; } = value;
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Definitions;
|
namespace Syntax.Parsing.Definitions;
|
||||||
|
|
||||||
public abstract class DefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string @namespace) : Node(tokens)
|
public abstract class DefinitionNode(IEnumerable<Token> tokens, Optional<string> documentation, string @namespace) : Node(tokens)
|
||||||
{
|
{
|
||||||
public Optional<string> Documentation { get; } = documentation;
|
public Optional<string> Documentation { get; } = documentation;
|
||||||
public string Namespace { get; set; } = @namespace;
|
public string Namespace { get; set; } = @namespace;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public interface IFuncSignature
|
|||||||
public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string @namespace, string name, List<FuncParameter> parameters, BlockNode body, NubType returnType, bool exported) : DefinitionNode(tokens, documentation, @namespace), IFuncSignature
|
public class LocalFuncDefinitionNode(IEnumerable<Token> tokens, Optional<string> documentation, string @namespace, string name, List<FuncParameter> parameters, BlockNode body, NubType returnType, bool exported) : DefinitionNode(tokens, documentation, @namespace), IFuncSignature
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public List<FuncParameter> Parameters { get; } = parameters;
|
public List<FuncParameter> Parameters { get; } = parameters;
|
||||||
@@ -33,7 +33,7 @@ public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<strin
|
|||||||
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ExternFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string @namespace, string name, string callName, List<FuncParameter> parameters, NubType returnType) : DefinitionNode(tokens, documentation, @namespace), IFuncSignature
|
public class ExternFuncDefinitionNode(IEnumerable<Token> tokens, Optional<string> documentation, string @namespace, string name, string callName, List<FuncParameter> parameters, NubType returnType) : DefinitionNode(tokens, documentation, @namespace), IFuncSignature
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public string CallName { get; } = callName;
|
public string CallName { get; } = callName;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class StructField(string name, NubType type, Optional<ExpressionNode> val
|
|||||||
public Optional<ExpressionNode> Value { get; } = value;
|
public Optional<ExpressionNode> Value { get; } = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StructDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string @namespace, string name, List<StructField> fields) : DefinitionNode(tokens, documentation, @namespace)
|
public class StructDefinitionNode(IEnumerable<Token> tokens, Optional<string> documentation, string @namespace, string name, List<StructField> fields) : DefinitionNode(tokens, documentation, @namespace)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public List<StructField> Fields { get; } = fields;
|
public List<StructField> Fields { get; } = fields;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class AddressOfNode(IReadOnlyList<Token> tokens, LValueNode expression) : ExpressionNode(tokens)
|
public class AddressOfNode(IEnumerable<Token> tokens, LValueNode expression) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public LValueNode Expression { get; } = expression;
|
public LValueNode Expression { get; } = expression;
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class AnonymousFuncNode(IReadOnlyList<Token> tokens, List<FuncParameter> parameters, BlockNode body, NubType returnType) : ExpressionNode(tokens)
|
public class AnonymousFuncNode(IEnumerable<Token> tokens, List<FuncParameter> parameters, BlockNode body, NubType returnType) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public List<FuncParameter> Parameters { get; } = parameters;
|
public List<FuncParameter> Parameters { get; } = parameters;
|
||||||
public BlockNode Body { get; } = body;
|
public BlockNode Body { get; } = body;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class ArrayIndexAccessNode(IReadOnlyList<Token> tokens, ExpressionNode array, ExpressionNode index) : LValueNode(tokens)
|
public class ArrayIndexAccessNode(IEnumerable<Token> tokens, ExpressionNode array, ExpressionNode index) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Array { get; } = array;
|
public ExpressionNode Array { get; } = array;
|
||||||
public ExpressionNode Index { get; } = index;
|
public ExpressionNode Index { get; } = index;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class ArrayInitializerNode(IReadOnlyList<Token> tokens, ExpressionNode capacity, NubType elementType) : ExpressionNode(tokens)
|
public class ArrayInitializerNode(IEnumerable<Token> tokens, ExpressionNode capacity, NubType elementType) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Capacity { get; } = capacity;
|
public ExpressionNode Capacity { get; } = capacity;
|
||||||
public NubType ElementType { get; } = elementType;
|
public NubType ElementType { get; } = elementType;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class BinaryExpressionNode(IReadOnlyList<Token> tokens, ExpressionNode left, BinaryExpressionOperator @operator, ExpressionNode right) : ExpressionNode(tokens)
|
public class BinaryExpressionNode(IEnumerable<Token> tokens, ExpressionNode left, BinaryExpressionOperator @operator, ExpressionNode right) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Left { get; } = left;
|
public ExpressionNode Left { get; } = left;
|
||||||
public BinaryExpressionOperator Operator { get; } = @operator;
|
public BinaryExpressionOperator Operator { get; } = @operator;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class DereferenceNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : LValueNode(tokens)
|
public class DereferenceNode(IEnumerable<Token> tokens, ExpressionNode expression) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression { get; } = expression;
|
public ExpressionNode Expression { get; } = expression;
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public abstract class ExpressionNode(IReadOnlyList<Token> tokens) : Node(tokens)
|
public abstract class ExpressionNode(IEnumerable<Token> tokens) : Node(tokens)
|
||||||
{
|
{
|
||||||
private NubType? _type;
|
private NubType? _type;
|
||||||
public NubType Type
|
public NubType Type
|
||||||
@@ -13,4 +13,4 @@ public abstract class ExpressionNode(IReadOnlyList<Token> tokens) : Node(tokens)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class LValueNode(IReadOnlyList<Token> tokens) : ExpressionNode(tokens);
|
public abstract class LValueNode(IEnumerable<Token> tokens) : ExpressionNode(tokens);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class FixedArrayInitializerNode(IReadOnlyList<Token> tokens, NubType elementType, int capacity) : ExpressionNode(tokens)
|
public class FixedArrayInitializerNode(IEnumerable<Token> tokens, NubType elementType, int capacity) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public NubType ElementType { get; } = elementType;
|
public NubType ElementType { get; } = elementType;
|
||||||
public int Capacity { get; } = capacity;
|
public int Capacity { get; } = capacity;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class FuncCallNode(IReadOnlyList<Token> tokens, ExpressionNode expression, List<ExpressionNode> parameters) : ExpressionNode(tokens)
|
public class FuncCallNode(IEnumerable<Token> tokens, ExpressionNode expression, List<ExpressionNode> parameters) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression = expression;
|
public ExpressionNode Expression = expression;
|
||||||
public List<ExpressionNode> Parameters { get; } = parameters;
|
public List<ExpressionNode> Parameters { get; } = parameters;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class IdentifierNode(IReadOnlyList<Token> tokens, Optional<string> @namespace, string name) : LValueNode(tokens)
|
public class IdentifierNode(IEnumerable<Token> tokens, Optional<string> @namespace, string name) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public Optional<string> Namespace { get; } = @namespace;
|
public Optional<string> Namespace { get; } = @namespace;
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class LiteralNode(IReadOnlyList<Token> tokens, string literal, LiteralKind kind) : ExpressionNode(tokens)
|
public class LiteralNode(IEnumerable<Token> tokens, string literal, LiteralKind kind) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public string Literal { get; } = literal;
|
public string Literal { get; } = literal;
|
||||||
public LiteralKind Kind { get; } = kind;
|
public LiteralKind Kind { get; } = kind;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class MemberAccessNode(IReadOnlyList<Token> tokens, ExpressionNode expression, string member) : LValueNode(tokens)
|
public class MemberAccessNode(IEnumerable<Token> tokens, ExpressionNode expression, string member) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression { get; } = expression;
|
public ExpressionNode Expression { get; } = expression;
|
||||||
public string Member { get; } = member;
|
public string Member { get; } = member;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class StructInitializerNode(IReadOnlyList<Token> tokens, NubStructType structType, Dictionary<string, ExpressionNode> initializers) : ExpressionNode(tokens)
|
public class StructInitializerNode(IEnumerable<Token> tokens, NubStructType structType, Dictionary<string, ExpressionNode> initializers) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public NubStructType StructType { get; } = structType;
|
public NubStructType StructType { get; } = structType;
|
||||||
public Dictionary<string, ExpressionNode> Initializers { get; } = initializers;
|
public Dictionary<string, ExpressionNode> Initializers { get; } = initializers;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Expressions;
|
namespace Syntax.Parsing.Expressions;
|
||||||
|
|
||||||
public class UnaryExpressionNode(IReadOnlyList<Token> tokens, UnaryExpressionOperator @operator, ExpressionNode operand) : ExpressionNode(tokens)
|
public class UnaryExpressionNode(IEnumerable<Token> tokens, UnaryExpressionOperator @operator, ExpressionNode operand) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public UnaryExpressionOperator Operator { get; } = @operator;
|
public UnaryExpressionOperator Operator { get; } = @operator;
|
||||||
public ExpressionNode Operand { get; } = operand;
|
public ExpressionNode Operand { get; } = operand;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing;
|
namespace Syntax.Parsing;
|
||||||
|
|
||||||
public abstract class Node(IReadOnlyList<Token> tokens)
|
public abstract class Node(IEnumerable<Token> tokens)
|
||||||
{
|
{
|
||||||
public IReadOnlyList<Token> Tokens { get; set; } = tokens;
|
public IEnumerable<Token> Tokens { get; set; } = tokens;
|
||||||
}
|
}
|
||||||
@@ -14,10 +14,10 @@ public static class Parser
|
|||||||
{
|
{
|
||||||
private static string _namespace = null!;
|
private static string _namespace = null!;
|
||||||
private static List<Diagnostic> _diagnostics = [];
|
private static List<Diagnostic> _diagnostics = [];
|
||||||
private static List<Token> _tokens = [];
|
private static IEnumerable<Token> _tokens = [];
|
||||||
private static int _index;
|
private static int _index;
|
||||||
|
|
||||||
public static DiagnosticsResult<CompilationUnit?> ParseFile(List<Token> tokens)
|
public static CompilationUnit? ParseFile(IEnumerable<Token> tokens, out IEnumerable<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_tokens = tokens;
|
_tokens = tokens;
|
||||||
_namespace = null!;
|
_namespace = null!;
|
||||||
@@ -33,7 +33,8 @@ public static class Parser
|
|||||||
catch (ParseException ex)
|
catch (ParseException ex)
|
||||||
{
|
{
|
||||||
_diagnostics.Add(ex.Diagnostic);
|
_diagnostics.Add(ex.Diagnostic);
|
||||||
return new DiagnosticsResult<CompilationUnit?>(_diagnostics, null);
|
diagnostics = _diagnostics;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -46,7 +47,8 @@ public static class Parser
|
|||||||
definitions.Add(definition);
|
definitions.Add(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DiagnosticsResult<CompilationUnit?>(_diagnostics, new CompilationUnit(_namespace, definitions));
|
diagnostics = _diagnostics;
|
||||||
|
return new CompilationUnit(_namespace, definitions);
|
||||||
}
|
}
|
||||||
catch (ParseException ex)
|
catch (ParseException ex)
|
||||||
{
|
{
|
||||||
@@ -54,7 +56,8 @@ public static class Parser
|
|||||||
RecoverToNextDefinition();
|
RecoverToNextDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DiagnosticsResult<CompilationUnit?>(_diagnostics, null);
|
diagnostics = _diagnostics;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DefinitionNode ParseDefinition()
|
private static DefinitionNode ParseDefinition()
|
||||||
@@ -63,7 +66,7 @@ public static class Parser
|
|||||||
List<ModifierToken> modifiers = [];
|
List<ModifierToken> modifiers = [];
|
||||||
|
|
||||||
List<string> documentationParts = [];
|
List<string> documentationParts = [];
|
||||||
while (_index < _tokens.Count && _tokens[_index] is DocumentationToken commentToken)
|
while (_index < _tokens.Count() && _tokens.ElementAt(_index) is DocumentationToken commentToken)
|
||||||
{
|
{
|
||||||
documentationParts.Add(commentToken.Documentation);
|
documentationParts.Add(commentToken.Documentation);
|
||||||
_index++;
|
_index++;
|
||||||
@@ -898,14 +901,14 @@ public static class Parser
|
|||||||
private static Optional<Token> Peek(int offset = 0)
|
private static Optional<Token> Peek(int offset = 0)
|
||||||
{
|
{
|
||||||
var peekIndex = _index + offset;
|
var peekIndex = _index + offset;
|
||||||
while (peekIndex < _tokens.Count && _tokens[peekIndex] is DocumentationToken)
|
while (peekIndex < _tokens.Count() && _tokens.ElementAt(peekIndex) is DocumentationToken)
|
||||||
{
|
{
|
||||||
peekIndex++;
|
peekIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peekIndex < _tokens.Count)
|
if (peekIndex < _tokens.Count())
|
||||||
{
|
{
|
||||||
return _tokens[peekIndex];
|
return _tokens.ElementAt(peekIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional<Token>.Empty();
|
return Optional<Token>.Empty();
|
||||||
@@ -913,7 +916,7 @@ public static class Parser
|
|||||||
|
|
||||||
private static void Next()
|
private static void Next()
|
||||||
{
|
{
|
||||||
while (_index < _tokens.Count && _tokens[_index] is DocumentationToken)
|
while (_index < _tokens.Count() && _tokens.ElementAt(_index) is DocumentationToken)
|
||||||
{
|
{
|
||||||
_index++;
|
_index++;
|
||||||
}
|
}
|
||||||
@@ -921,9 +924,9 @@ public static class Parser
|
|||||||
_index++;
|
_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyList<Token> GetTokensForNode(int startIndex)
|
private static IEnumerable<Token> GetTokensForNode(int startIndex)
|
||||||
{
|
{
|
||||||
return _tokens[startIndex..Math.Min(_index, _tokens.Count - 1)];
|
return _tokens.Skip(startIndex).Take(Math.Min(_index, _tokens.Count() - 1) - startIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class ArrayIndexAssignmentNode(IReadOnlyList<Token> tokens, ArrayIndexAccessNode arrayIndexAccess, ExpressionNode value) : StatementNode(tokens)
|
public class ArrayIndexAssignmentNode(IEnumerable<Token> tokens, ArrayIndexAccessNode arrayIndexAccess, ExpressionNode value) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public ArrayIndexAccessNode ArrayIndexAccess { get; } = arrayIndexAccess;
|
public ArrayIndexAccessNode ArrayIndexAccess { get; } = arrayIndexAccess;
|
||||||
public ExpressionNode Value { get; } = value;
|
public ExpressionNode Value { get; } = value;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class BlockNode(IReadOnlyList<Token> tokens, List<StatementNode> statements) : Node(tokens)
|
public class BlockNode(IEnumerable<Token> tokens, List<StatementNode> statements) : Node(tokens)
|
||||||
{
|
{
|
||||||
public List<StatementNode> Statements { get; } = statements;
|
public List<StatementNode> Statements { get; } = statements;
|
||||||
}
|
}
|
||||||
@@ -2,4 +2,4 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class BreakNode(IReadOnlyList<Token> tokens) : StatementNode(tokens);
|
public class BreakNode(IEnumerable<Token> tokens) : StatementNode(tokens);
|
||||||
@@ -2,4 +2,4 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class ContinueNode(IReadOnlyList<Token> tokens) : StatementNode(tokens);
|
public class ContinueNode(IEnumerable<Token> tokens) : StatementNode(tokens);
|
||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class DereferenceAssignmentNode(IReadOnlyList<Token> tokens, DereferenceNode dereference, ExpressionNode value) : StatementNode(tokens)
|
public class DereferenceAssignmentNode(IEnumerable<Token> tokens, DereferenceNode dereference, ExpressionNode value) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public DereferenceNode Dereference { get; } = dereference;
|
public DereferenceNode Dereference { get; } = dereference;
|
||||||
public ExpressionNode Value { get; } = value;
|
public ExpressionNode Value { get; } = value;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class IfNode(IReadOnlyList<Token> tokens, ExpressionNode condition, BlockNode body, Optional<Variant<IfNode, BlockNode>> @else) : StatementNode(tokens)
|
public class IfNode(IEnumerable<Token> tokens, ExpressionNode condition, BlockNode body, Optional<Variant<IfNode, BlockNode>> @else) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Condition { get; } = condition;
|
public ExpressionNode Condition { get; } = condition;
|
||||||
public BlockNode Body { get; } = body;
|
public BlockNode Body { get; } = body;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class MemberAssignmentNode(IReadOnlyList<Token> tokens, MemberAccessNode expression, ExpressionNode value) : StatementNode(tokens)
|
public class MemberAssignmentNode(IEnumerable<Token> tokens, MemberAccessNode expression, ExpressionNode value) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public MemberAccessNode MemberAccess { get; } = expression;
|
public MemberAccessNode MemberAccess { get; } = expression;
|
||||||
public ExpressionNode Value { get; } = value;
|
public ExpressionNode Value { get; } = value;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class ReturnNode(IReadOnlyList<Token> tokens, Optional<ExpressionNode> value) : StatementNode(tokens)
|
public class ReturnNode(IEnumerable<Token> tokens, Optional<ExpressionNode> value) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public Optional<ExpressionNode> Value { get; } = value;
|
public Optional<ExpressionNode> Value { get; } = value;
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class StatementExpressionNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : StatementNode(tokens)
|
public class StatementExpressionNode(IEnumerable<Token> tokens, ExpressionNode expression) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression { get; } = expression;
|
public ExpressionNode Expression { get; } = expression;
|
||||||
}
|
}
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public abstract class StatementNode(IReadOnlyList<Token> tokens) : Node(tokens);
|
public abstract class StatementNode(IEnumerable<Token> tokens) : Node(tokens);
|
||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class VariableAssignmentNode(IReadOnlyList<Token> tokens, IdentifierNode identifier, ExpressionNode value) : StatementNode(tokens)
|
public class VariableAssignmentNode(IEnumerable<Token> tokens, IdentifierNode identifier, ExpressionNode value) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public IdentifierNode Identifier { get; } = identifier;
|
public IdentifierNode Identifier { get; } = identifier;
|
||||||
public ExpressionNode Value { get; } = value;
|
public ExpressionNode Value { get; } = value;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class VariableDeclarationNode(IReadOnlyList<Token> tokens, string name, NubType type) : StatementNode(tokens)
|
public class VariableDeclarationNode(IEnumerable<Token> tokens, string name, NubType type) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public NubType Type { get; } = type;
|
public NubType Type { get; } = type;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Statements;
|
namespace Syntax.Parsing.Statements;
|
||||||
|
|
||||||
public class WhileNode(IReadOnlyList<Token> tokens, ExpressionNode condition, BlockNode body) : StatementNode(tokens)
|
public class WhileNode(IEnumerable<Token> tokens, ExpressionNode condition, BlockNode body) : StatementNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Condition { get; } = condition;
|
public ExpressionNode Condition { get; } = condition;
|
||||||
public BlockNode Body { get; } = body;
|
public BlockNode Body { get; } = body;
|
||||||
|
|||||||
@@ -62,19 +62,21 @@ public static class Tokenizer
|
|||||||
|
|
||||||
private static SourceText _sourceText;
|
private static SourceText _sourceText;
|
||||||
private static int _index;
|
private static int _index;
|
||||||
|
|
||||||
public static DiagnosticsResult<List<Token>> Tokenize(SourceText sourceText)
|
public static IEnumerable<Token> Tokenize(SourceText sourceText, out IEnumerable<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_sourceText = sourceText;
|
_sourceText = sourceText;
|
||||||
_index = 0;
|
_index = 0;
|
||||||
|
|
||||||
List<Token> tokens = [];
|
List<Token> tokens = [];
|
||||||
while (ParseToken().TryGetValue(out var token))
|
while (ParseToken().TryGetValue(out var token))
|
||||||
{
|
{
|
||||||
tokens.Add(token);
|
tokens.Add(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DiagnosticsResult<List<Token>>([], tokens);
|
// TODO: Implement diagnostics
|
||||||
|
diagnostics = [];
|
||||||
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ConsumeWhitespace()
|
private static void ConsumeWhitespace()
|
||||||
@@ -99,7 +101,7 @@ public static class Tokenizer
|
|||||||
{
|
{
|
||||||
Next();
|
Next();
|
||||||
Next();
|
Next();
|
||||||
|
|
||||||
if (Peek().TryGetValue(out var thirdChar) && thirdChar == '/')
|
if (Peek().TryGetValue(out var thirdChar) && thirdChar == '/')
|
||||||
{
|
{
|
||||||
Next();
|
Next();
|
||||||
@@ -109,6 +111,7 @@ public static class Tokenizer
|
|||||||
buffer += character;
|
buffer += character;
|
||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
Next();
|
Next();
|
||||||
return new DocumentationToken(CreateSpan(startIndex), buffer);
|
return new DocumentationToken(CreateSpan(startIndex), buffer);
|
||||||
}
|
}
|
||||||
@@ -117,6 +120,7 @@ public static class Tokenizer
|
|||||||
{
|
{
|
||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
Next();
|
Next();
|
||||||
return ParseToken();
|
return ParseToken();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public static class TypeChecker
|
|||||||
private static NubType? _currentFunctionReturnType;
|
private static NubType? _currentFunctionReturnType;
|
||||||
private static Queue<AnonymousFuncNode> _anonymousFunctions = [];
|
private static Queue<AnonymousFuncNode> _anonymousFunctions = [];
|
||||||
|
|
||||||
public static DiagnosticsResult Check(CompilationUnit compilationUnit, DefinitionTable definitionTable)
|
public static void Check(CompilationUnit compilationUnit, DefinitionTable definitionTable, out IEnumerable<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_compilationUnit = compilationUnit;
|
_compilationUnit = compilationUnit;
|
||||||
_definitionTable = definitionTable;
|
_definitionTable = definitionTable;
|
||||||
@@ -43,8 +43,8 @@ public static class TypeChecker
|
|||||||
CheckFuncDef(func.Parameters, func.Body, func.ReturnType);
|
CheckFuncDef(func.Parameters, func.Body, func.ReturnType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DiagnosticsResult(_diagnostics);
|
diagnostics = _diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckStructDef(StructDefinitionNode structDef)
|
private static void CheckStructDef(StructDefinitionNode structDef)
|
||||||
|
|||||||
Reference in New Issue
Block a user