This commit is contained in:
nub31
2025-07-22 23:20:56 +02:00
parent 62c9d86cda
commit d993581361
26 changed files with 1002 additions and 1003 deletions

View File

@@ -1,78 +0,0 @@
using NubLang.Syntax.Binding;
using NubLang.Syntax.Binding.Node;
namespace NubLang.Generation;
public sealed class BoundDefinitionTable
{
private readonly List<BoundDefinition> _definitions;
public BoundDefinitionTable(IEnumerable<BoundSyntaxTree> syntaxTrees)
{
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
}
public BoundLocalFunc LookupLocalFunc(string name)
{
return _definitions
.OfType<BoundLocalFunc>()
.First(x => x.Name == name);
}
public BoundExternFunc LookupExternFunc(string name)
{
return _definitions
.OfType<BoundExternFunc>()
.First(x => x.Name == name);
}
public BoundStruct LookupStruct(string name)
{
return _definitions
.OfType<BoundStruct>()
.First(x => x.Name == name);
}
public BoundStructField LookupStructField(BoundStruct @struct, string field)
{
return @struct.Fields.First(x => x.Name == field);
}
public IEnumerable<BoundTraitImpl> LookupTraitImpls(NubType itemType)
{
return _definitions
.OfType<BoundTraitImpl>()
.Where(x => x.ForType == itemType);
}
public BoundTraitFuncImpl LookupTraitFuncImpl(NubType forType, string name)
{
return _definitions
.OfType<BoundTraitImpl>()
.Where(x => x.ForType == forType)
.SelectMany(x => x.Functions)
.First(x => x.Name == name);
}
public BoundTrait LookupTrait(string name)
{
return _definitions
.OfType<BoundTrait>()
.First(x => x.Name == name);
}
public BoundTraitFunc LookupTraitFunc(BoundTrait trait, string name)
{
return trait.Functions.First(x => x.Name == name);
}
public IEnumerable<BoundStruct> GetStructs()
{
return _definitions.OfType<BoundStruct>();
}
public IEnumerable<BoundTrait> GetTraits()
{
return _definitions.OfType<BoundTrait>();
}
}

View File

@@ -1,49 +1,49 @@
using System.Diagnostics;
using System.Globalization;
using NubLang.Syntax.Binding;
using NubLang.Syntax.Binding.Node;
using NubLang.Syntax.Tokenization;
using NubLang.Tokenization;
using NubLang.TypeChecking;
using NubLang.TypeChecking.Node;
namespace NubLang.Generation.QBE;
public partial class QBEGenerator
{
private Val EmitExpression(BoundExpression expression)
private Val EmitExpression(Expression expression)
{
return expression switch
{
BoundArrayInitializer arrayInitializer => EmitArrayInitializer(arrayInitializer),
BoundStructInitializer structInitializer => EmitStructInitializer(structInitializer),
BoundAddressOf addressOf => EmitAddressOf(addressOf),
BoundDereference dereference => EmitDereference(dereference),
BoundArrowFunc arrowFunc => EmitArrowFunc(arrowFunc),
BoundBinaryExpression binaryExpression => EmitBinaryExpression(binaryExpression),
BoundFuncCall funcCallExpression => EmitFuncCall(funcCallExpression),
BoundExternFuncIdent externFuncIdent => EmitExternFuncIdent(externFuncIdent),
BoundLocalFuncIdent localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
BoundVariableIdent variableIdent => EmitVariableIdent(variableIdent),
BoundLiteral literal => EmitLiteral(literal),
BoundUnaryExpression unaryExpression => EmitUnaryExpression(unaryExpression),
BoundStructFieldAccess structFieldAccess => EmitStructFieldAccess(structFieldAccess),
BoundInterfaceFuncAccess traitFuncAccess => EmitTraitFuncAccess(traitFuncAccess),
BoundArrayIndexAccess arrayIndex => EmitArrayIndexAccess(arrayIndex),
ArrayInitializer arrayInitializer => EmitArrayInitializer(arrayInitializer),
StructInitializer structInitializer => EmitStructInitializer(structInitializer),
AddressOf addressOf => EmitAddressOf(addressOf),
Dereference dereference => EmitDereference(dereference),
ArrowFunc arrowFunc => EmitArrowFunc(arrowFunc),
BinaryExpression binaryExpression => EmitBinaryExpression(binaryExpression),
FuncCall funcCallExpression => EmitFuncCall(funcCallExpression),
ExternFuncIdent externFuncIdent => EmitExternFuncIdent(externFuncIdent),
LocalFuncIdent localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
VariableIdent variableIdent => EmitVariableIdent(variableIdent),
Literal literal => EmitLiteral(literal),
UnaryExpression unaryExpression => EmitUnaryExpression(unaryExpression),
StructFieldAccess structFieldAccess => EmitStructFieldAccess(structFieldAccess),
InterfaceFuncAccess traitFuncAccess => EmitTraitFuncAccess(traitFuncAccess),
ArrayIndexAccess arrayIndex => EmitArrayIndexAccess(arrayIndex),
_ => throw new ArgumentOutOfRangeException(nameof(expression))
};
}
private Val EmitArrowFunc(BoundArrowFunc arrowFunc)
private Val EmitArrowFunc(ArrowFunc arrowFunc)
{
var name = $"$arrow_func{++_arrowFuncIndex}";
_arrowFunctions.Enqueue((arrowFunc, name));
return new Val(name, arrowFunc.Type, ValKind.Direct);
}
private Val EmitArrayIndexAccess(BoundArrayIndexAccess arrayIndexAccess)
private Val EmitArrayIndexAccess(ArrayIndexAccess arrayIndexAccess)
{
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
EmitArrayBoundsCheck(array, index);
EmitArraysCheck(array, index);
var elementType = ((NubArrayType)arrayIndexAccess.Target.Type).ElementType;
@@ -54,7 +54,7 @@ public partial class QBEGenerator
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer);
}
private void EmitArrayBoundsCheck(string array, string index)
private void EmitArraysCheck(string array, string index)
{
var count = TmpName();
_writer.Indented($"{count} =l loadl {array}");
@@ -78,7 +78,7 @@ public partial class QBEGenerator
_writer.Indented(notOobLabel);
}
private Val EmitArrayInitializer(BoundArrayInitializer arrayInitializer)
private Val EmitArrayInitializer(ArrayInitializer arrayInitializer)
{
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
var elementSize = arrayInitializer.ElementType.Size(_definitionTable);
@@ -99,12 +99,12 @@ public partial class QBEGenerator
return new Val(arrayPointer, arrayInitializer.Type, ValKind.Direct);
}
private Val EmitDereference(BoundDereference dereference)
private Val EmitDereference(Dereference dereference)
{
return EmitLoad(dereference.Type, EmitUnwrap(EmitExpression(dereference.Expression)));
}
private Val EmitAddressOf(BoundAddressOf addressOf)
private Val EmitAddressOf(AddressOf addressOf)
{
var value = EmitExpression(addressOf.Expression);
if (value.Kind != ValKind.Pointer)
@@ -115,7 +115,7 @@ public partial class QBEGenerator
return new Val(value.Name, addressOf.Type, ValKind.Direct);
}
private Val EmitBinaryExpression(BoundBinaryExpression binaryExpression)
private Val EmitBinaryExpression(BinaryExpression binaryExpression)
{
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
@@ -128,15 +128,15 @@ public partial class QBEGenerator
return new Val(outputName, binaryExpression.Type, ValKind.Direct);
}
private string EmitBinaryInstructionFor(BoundBinaryOperator op, NubType type, string left, string right)
private string EmitBinaryInstructionFor(BinaryOperator op, NubType type, string left, string right)
{
if (op is
BoundBinaryOperator.Equal or
BoundBinaryOperator.NotEqual or
BoundBinaryOperator.GreaterThan or
BoundBinaryOperator.GreaterThanOrEqual or
BoundBinaryOperator.LessThan or
BoundBinaryOperator.LessThanOrEqual)
BinaryOperator.Equal or
BinaryOperator.NotEqual or
BinaryOperator.GreaterThan or
BinaryOperator.GreaterThanOrEqual or
BinaryOperator.LessThan or
BinaryOperator.LessThanOrEqual)
{
char suffix;
@@ -177,12 +177,12 @@ public partial class QBEGenerator
throw new NotSupportedException($"Unsupported type '{simpleType}' for binary operator '{op}'");
}
if (op is BoundBinaryOperator.Equal)
if (op is BinaryOperator.Equal)
{
return "ceq" + suffix;
}
if (op is BoundBinaryOperator.NotEqual)
if (op is BinaryOperator.NotEqual)
{
return "cne" + suffix;
}
@@ -204,42 +204,42 @@ public partial class QBEGenerator
return op switch
{
BoundBinaryOperator.GreaterThan => 'c' + sign + "gt" + suffix,
BoundBinaryOperator.GreaterThanOrEqual => 'c' + sign + "ge" + suffix,
BoundBinaryOperator.LessThan => 'c' + sign + "lt" + suffix,
BoundBinaryOperator.LessThanOrEqual => 'c' + sign + "le" + suffix,
BinaryOperator.GreaterThan => 'c' + sign + "gt" + suffix,
BinaryOperator.GreaterThanOrEqual => 'c' + sign + "ge" + suffix,
BinaryOperator.LessThan => 'c' + sign + "lt" + suffix,
BinaryOperator.LessThanOrEqual => 'c' + sign + "le" + suffix,
_ => throw new ArgumentOutOfRangeException(nameof(op), op, null)
};
}
return op switch
{
BoundBinaryOperator.Plus => "add",
BoundBinaryOperator.Minus => "sub",
BoundBinaryOperator.Multiply => "mul",
BoundBinaryOperator.Divide => "div",
BinaryOperator.Plus => "add",
BinaryOperator.Minus => "sub",
BinaryOperator.Multiply => "mul",
BinaryOperator.Divide => "div",
_ => throw new ArgumentOutOfRangeException(nameof(op))
};
}
private Val EmitExternFuncIdent(BoundExternFuncIdent externFuncIdent)
private Val EmitExternFuncIdent(ExternFuncIdent externFuncIdent)
{
var func = _definitionTable.LookupExternFunc(externFuncIdent.Name);
return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct);
}
private Val EmitLocalFuncIdent(BoundLocalFuncIdent localFuncIdent)
private Val EmitLocalFuncIdent(LocalFuncIdent localFuncIdent)
{
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name);
return new Val(LocalFuncName(func), localFuncIdent.Type, ValKind.Direct);
}
private Val EmitVariableIdent(BoundVariableIdent variableIdent)
private Val EmitVariableIdent(VariableIdent variableIdent)
{
return Scope.Lookup(variableIdent.Name);
}
private Val EmitLiteral(BoundLiteral literal)
private Val EmitLiteral(Literal literal)
{
switch (literal.Kind)
{
@@ -247,21 +247,21 @@ public partial class QBEGenerator
{
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 })
{
var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture);
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.SingleToInt32Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
}
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 })
{
var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture);
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.DoubleToInt64Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
}
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 })
{
return new Val(literal.Literal, literal.Type, ValKind.Direct);
return new Val(literal.Value, literal.Type, ValKind.Direct);
}
break;
@@ -270,19 +270,19 @@ public partial class QBEGenerator
{
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 })
{
return new Val(literal.Literal.Split(".").First(), literal.Type, ValKind.Direct);
return new Val(literal.Value.Split(".").First(), literal.Type, ValKind.Direct);
}
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 })
{
var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture);
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.SingleToInt32Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
}
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 })
{
var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture);
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.DoubleToInt64Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
}
@@ -293,14 +293,14 @@ public partial class QBEGenerator
{
if (literal.Type is NubStringType)
{
var stringLiteral = new StringLiteral(literal.Literal, StringName());
var stringLiteral = new StringLiteral(literal.Value, StringName());
_stringLiterals.Add(stringLiteral);
return new Val(stringLiteral.Name, literal.Type, ValKind.Direct);
}
if (literal.Type is NubCStringType)
{
var cStringLiteral = new CStringLiteral(literal.Literal, CStringName());
var cStringLiteral = new CStringLiteral(literal.Value, CStringName());
_cStringLiterals.Add(cStringLiteral);
return new Val(cStringLiteral.Name, literal.Type, ValKind.Direct);
}
@@ -311,7 +311,7 @@ public partial class QBEGenerator
{
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.Bool })
{
return new Val(bool.Parse(literal.Literal) ? "1" : "0", literal.Type, ValKind.Direct);
return new Val(bool.Parse(literal.Value) ? "1" : "0", literal.Type, ValKind.Direct);
}
break;
@@ -321,7 +321,7 @@ public partial class QBEGenerator
throw new NotSupportedException($"Cannot create literal of kind '{literal.Kind}' for type {literal.Type}");
}
private Val EmitStructInitializer(BoundStructInitializer structInitializer, string? destination = null)
private Val EmitStructInitializer(StructInitializer structInitializer, string? destination = null)
{
var @struct = _definitionTable.LookupStruct(structInitializer.StructType.Name);
@@ -349,14 +349,14 @@ public partial class QBEGenerator
return new Val(destination, structInitializer.StructType, ValKind.Direct);
}
private Val EmitUnaryExpression(BoundUnaryExpression unaryExpression)
private Val EmitUnaryExpression(UnaryExpression unaryExpression)
{
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
var outputName = TmpName();
switch (unaryExpression.Operator)
{
case BoundUnaryOperator.Negate:
case UnaryOperator.Negate:
{
switch (unaryExpression.Operand.Type)
{
@@ -376,7 +376,7 @@ public partial class QBEGenerator
break;
}
case BoundUnaryOperator.Invert:
case UnaryOperator.Invert:
{
switch (unaryExpression.Operand.Type)
{
@@ -396,7 +396,7 @@ public partial class QBEGenerator
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
}
private Val EmitStructFieldAccess(BoundStructFieldAccess structFieldAccess)
private Val EmitStructFieldAccess(StructFieldAccess structFieldAccess)
{
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
@@ -415,12 +415,12 @@ public partial class QBEGenerator
return new Val(output, structFieldAccess.Type, ValKind.Pointer);
}
private Val EmitTraitFuncAccess(BoundInterfaceFuncAccess interfaceFuncAccess)
private Val EmitTraitFuncAccess(InterfaceFuncAccess interfaceFuncAccess)
{
throw new NotImplementedException();
}
private Val EmitFuncCall(BoundFuncCall funcCall)
private Val EmitFuncCall(FuncCall funcCall)
{
var expression = EmitExpression(funcCall.Expression);
var funcPointer = EmitUnwrap(expression);

View File

@@ -1,36 +1,36 @@
using System.Diagnostics;
using NubLang.Syntax.Binding.Node;
using NubLang.TypeChecking.Node;
namespace NubLang.Generation.QBE;
public partial class QBEGenerator
{
private void EmitStatement(BoundStatement statement)
private void EmitStatement(Statement statement)
{
switch (statement)
{
case BoundAssignment assignment:
case Assignment assignment:
EmitAssignment(assignment);
break;
case BoundBreak:
case Break:
EmitBreak();
break;
case BoundContinue:
case Continue:
EmitContinue();
break;
case BoundIf ifStatement:
case If ifStatement:
EmitIf(ifStatement);
break;
case BoundReturn @return:
case Return @return:
EmitReturn(@return);
break;
case BoundStatementExpression statementExpression:
case StatementExpression statementExpression:
EmitExpression(statementExpression.Expression);
break;
case BoundVariableDeclaration variableDeclaration:
case VariableDeclaration variableDeclaration:
EmitVariableDeclaration(variableDeclaration);
break;
case BoundWhile whileStatement:
case While whileStatement:
EmitWhile(whileStatement);
break;
default:
@@ -38,7 +38,7 @@ public partial class QBEGenerator
}
}
private void EmitAssignment(BoundAssignment assignment)
private void EmitAssignment(Assignment assignment)
{
var destination = EmitExpression(assignment.Target);
Debug.Assert(destination.Kind == ValKind.Pointer);
@@ -57,7 +57,7 @@ public partial class QBEGenerator
_codeIsReachable = false;
}
private void EmitIf(BoundIf ifStatement)
private void EmitIf(If ifStatement)
{
var trueLabel = LabelName();
var falseLabel = LabelName();
@@ -81,7 +81,7 @@ public partial class QBEGenerator
_writer.WriteLine(endLabel);
}
private void EmitReturn(BoundReturn @return)
private void EmitReturn(Return @return)
{
if (@return.Value.HasValue)
{
@@ -94,7 +94,7 @@ public partial class QBEGenerator
}
}
private void EmitVariableDeclaration(BoundVariableDeclaration variableDeclaration)
private void EmitVariableDeclaration(VariableDeclaration variableDeclaration)
{
var name = $"%{variableDeclaration.Name}";
_writer.Indented($"{name} =l alloc8 8");
@@ -108,7 +108,7 @@ public partial class QBEGenerator
Scope.Declare(variableDeclaration.Name, new Val(name, variableDeclaration.Type, ValKind.Pointer));
}
private void EmitWhile(BoundWhile whileStatement)
private void EmitWhile(While whileStatement)
{
var conditionLabel = LabelName();
var iterationLabel = LabelName();

View File

@@ -1,23 +1,23 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using NubLang.Syntax.Binding;
using NubLang.Syntax.Binding.Node;
using NubLang.Syntax.Tokenization;
using NubLang.Tokenization;
using NubLang.TypeChecking;
using NubLang.TypeChecking.Node;
namespace NubLang.Generation.QBE;
public partial class QBEGenerator
{
private readonly BoundSyntaxTree _syntaxTree;
private readonly BoundDefinitionTable _definitionTable;
private readonly TypedSyntaxTree _syntaxTree;
private readonly TypedDefinitionTable _definitionTable;
private readonly QBEWriter _writer;
private readonly List<CStringLiteral> _cStringLiterals = [];
private readonly List<StringLiteral> _stringLiterals = [];
private readonly Stack<string> _breakLabels = [];
private readonly Stack<string> _continueLabels = [];
private readonly Queue<(BoundArrowFunc Func, string Name)> _arrowFunctions = [];
private readonly Queue<(ArrowFunc Func, string Name)> _arrowFunctions = [];
private readonly Stack<Scope> _scopes = [];
private int _tmpIndex;
private int _labelIndex;
@@ -28,7 +28,7 @@ public partial class QBEGenerator
private Scope Scope => _scopes.Peek();
public QBEGenerator(BoundSyntaxTree syntaxTree, BoundDefinitionTable definitionTable)
public QBEGenerator(TypedSyntaxTree syntaxTree, TypedDefinitionTable definitionTable)
{
_syntaxTree = syntaxTree;
_definitionTable = definitionTable;
@@ -62,7 +62,7 @@ public partial class QBEGenerator
_writer.NewLine();
}
foreach (var funcDef in _syntaxTree.Definitions.OfType<BoundLocalFunc>())
foreach (var funcDef in _syntaxTree.Definitions.OfType<LocalFunc>())
{
EmitFuncDefinition(LocalFuncName(funcDef), funcDef.Signature.Parameters, funcDef.Signature.ReturnType, funcDef.Body);
_writer.NewLine();
@@ -191,21 +191,21 @@ public partial class QBEGenerator
return size;
}
private bool EmitTryMoveInto(BoundExpression source, string destinationPointer)
private bool EmitTryMoveInto(Expression source, string destinationPointer)
{
switch (source)
{
case BoundArrayInitializer arrayInitializer:
case ArrayInitializer arrayInitializer:
{
EmitStore(source.Type, EmitUnwrap(EmitArrayInitializer(arrayInitializer)), destinationPointer);
return true;
}
case BoundStructInitializer structInitializer:
case StructInitializer structInitializer:
{
EmitStructInitializer(structInitializer, destinationPointer);
return true;
}
case BoundLiteral { Kind: LiteralKind.String } literal:
case Literal { Kind: LiteralKind.String } literal:
{
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
return true;
@@ -215,7 +215,7 @@ public partial class QBEGenerator
return false;
}
private void EmitCopyIntoOrInitialize(BoundExpression source, string destinationPointer)
private void EmitCopyIntoOrInitialize(Expression source, string destinationPointer)
{
// If the source is a value which is not used yet such as an array/struct initializer or literal, we can skip copying
if (EmitTryMoveInto(source, destinationPointer))
@@ -253,13 +253,13 @@ public partial class QBEGenerator
}
}
private bool EmitTryCreateWithoutCopy(BoundExpression source, [NotNullWhen(true)] out string? destination)
private bool EmitTryCreateWithoutCopy(Expression source, [NotNullWhen(true)] out string? destination)
{
switch (source)
{
case BoundArrayInitializer:
case BoundStructInitializer:
case BoundLiteral { Kind: LiteralKind.String }:
case ArrayInitializer:
case StructInitializer:
case Literal { Kind: LiteralKind.String }:
{
destination = EmitUnwrap(EmitExpression(source));
return true;
@@ -270,7 +270,7 @@ public partial class QBEGenerator
return false;
}
private string EmitCreateCopyOrInitialize(BoundExpression source)
private string EmitCreateCopyOrInitialize(Expression source)
{
// If the source is a value which is not used yet such as an array/struct initializer or literal, we can skip copying
if (EmitTryCreateWithoutCopy(source, out var uncopiedValue))
@@ -328,7 +328,7 @@ public partial class QBEGenerator
return "l";
}
private void EmitFuncDefinition(string name, IReadOnlyList<BoundFuncParameter> parameters, NubType returnType, BoundBlock body)
private void EmitFuncDefinition(string name, IReadOnlyList<FuncParameter> parameters, NubType returnType, Block body)
{
_labelIndex = 0;
_tmpIndex = 0;
@@ -360,7 +360,7 @@ public partial class QBEGenerator
EmitBlock(body, scope);
// Implicit return for void functions if no explicit return has been set
if (returnType is NubVoidType && body.Statements is [.., not BoundReturn])
if (returnType is NubVoidType && body.Statements is [.., not Return])
{
if (returnType is NubVoidType)
{
@@ -371,7 +371,7 @@ public partial class QBEGenerator
_writer.EndFunction();
}
private void EmitStructDefinition(BoundStruct structDef)
private void EmitStructDefinition(Struct structDef)
{
_writer.WriteLine($"type {CustomTypeName(structDef.Name)} = {{ ");
@@ -392,7 +392,7 @@ public partial class QBEGenerator
_writer.WriteLine("}");
return;
string StructDefQBEType(BoundStructField field)
string StructDefQBEType(StructField field)
{
if (field.Type.IsSimpleType(out var simpleType, out var complexType))
{
@@ -417,7 +417,7 @@ public partial class QBEGenerator
}
}
private void EmitTraitVTable(BoundTrait traitDef)
private void EmitTraitVTable(Trait traitDef)
{
_writer.WriteLine($"type {CustomTypeName(traitDef.Name)} = {{");
@@ -429,7 +429,7 @@ public partial class QBEGenerator
_writer.WriteLine("}");
}
private void EmitBlock(BoundBlock block, Scope? scope = null)
private void EmitBlock(Block block, Scope? scope = null)
{
_scopes.Push(scope ?? Scope.SubScope());
@@ -456,7 +456,7 @@ public partial class QBEGenerator
};
}
private int OffsetOf(BoundStruct structDefinition, string member)
private int OffsetOf(Struct structDefinition, string member)
{
var offset = 0;
@@ -498,12 +498,12 @@ public partial class QBEGenerator
return $"$string{++_stringLiteralIndex}";
}
private string LocalFuncName(BoundLocalFunc funcDef)
private string LocalFuncName(LocalFunc funcDef)
{
return $"${funcDef.Name}";
}
private string ExternFuncName(BoundExternFunc funcDef)
private string ExternFuncName(ExternFunc funcDef)
{
return $"${funcDef.CallName}";
}

View File

@@ -0,0 +1,78 @@
using NubLang.TypeChecking;
using NubLang.TypeChecking.Node;
namespace NubLang.Generation;
public sealed class TypedDefinitionTable
{
private readonly List<Definition> _definitions;
public TypedDefinitionTable(IEnumerable<TypedSyntaxTree> syntaxTrees)
{
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
}
public LocalFunc LookupLocalFunc(string name)
{
return _definitions
.OfType<LocalFunc>()
.First(x => x.Name == name);
}
public ExternFunc LookupExternFunc(string name)
{
return _definitions
.OfType<ExternFunc>()
.First(x => x.Name == name);
}
public Struct LookupStruct(string name)
{
return _definitions
.OfType<Struct>()
.First(x => x.Name == name);
}
public StructField LookupStructField(Struct @struct, string field)
{
return @struct.Fields.First(x => x.Name == field);
}
public IEnumerable<TraitImpl> LookupTraitImpls(NubType itemType)
{
return _definitions
.OfType<TraitImpl>()
.Where(x => x.ForType == itemType);
}
public TraitFuncImpl LookupTraitFuncImpl(NubType forType, string name)
{
return _definitions
.OfType<TraitImpl>()
.Where(x => x.ForType == forType)
.SelectMany(x => x.Functions)
.First(x => x.Name == name);
}
public Trait LookupTrait(string name)
{
return _definitions
.OfType<Trait>()
.First(x => x.Name == name);
}
public TraitFunc LookupTraitFunc(Trait trait, string name)
{
return trait.Functions.First(x => x.Name == name);
}
public IEnumerable<Struct> GetStructs()
{
return _definitions.OfType<Struct>();
}
public IEnumerable<Trait> GetTraits()
{
return _definitions.OfType<Trait>();
}
}