...
This commit is contained in:
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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}";
|
||||
}
|
||||
|
||||
78
src/compiler/NubLang/Generation/TypedDefinitionTable.cs
Normal file
78
src/compiler/NubLang/Generation/TypedDefinitionTable.cs
Normal 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>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user