This commit is contained in:
nub31
2025-09-08 17:33:13 +02:00
parent bcc64858b1
commit 6c517eb996
3 changed files with 95 additions and 99 deletions

View File

@@ -1,19 +1,30 @@
// c // c
extern func puts(text: cstring) extern func puts(text: cstring)
struct Human { interface Printable
{
func print()
}
struct Human : Printable
{
name: cstring name: cstring
age: u32 age: u32
func print()
{
puts(this.name)
}
} }
func main(args: []cstring): i64 func main(args: []cstring): i64
{ {
let x: Human = struct { let x: Printable = struct Human {
name = "Oliver" name = "Oliver"
age = 23 age = 23
} }
puts(x.name) x.print()
return 0 return 0
} }

View File

@@ -136,7 +136,7 @@ public class QBEGenerator
_writer.Indented($"{store} {value}, {destination}"); _writer.Indented($"{store} {value}, {destination}");
} }
private Val EmitLoad(TypeNode type, string from) private string EmitLoad(TypeNode type, string from)
{ {
string load; string load;
@@ -164,7 +164,7 @@ public class QBEGenerator
_writer.Indented($"{into} {QBEAssign(type)} {load} {from}"); _writer.Indented($"{into} {QBEAssign(type)} {load} {from}");
return new Val(into, type, ValKind.Direct); return into;
} }
private void EmitMemcpy(string source, string destination, string length) private void EmitMemcpy(string source, string destination, string length)
@@ -203,7 +203,7 @@ public class QBEGenerator
{ {
case ArrayInitializerNode arrayInitializer: case ArrayInitializerNode arrayInitializer:
{ {
EmitStore(source.Type, EmitUnwrap(EmitArrayInitializer(arrayInitializer)), destinationPointer); EmitStore(source.Type, EmitArrayInitializer(arrayInitializer), destinationPointer);
return true; return true;
} }
case StructInitializerNode structInitializer: case StructInitializerNode structInitializer:
@@ -218,7 +218,7 @@ public class QBEGenerator
} }
case LiteralNode { Kind: LiteralKind.String } literal: case LiteralNode { Kind: LiteralKind.String } literal:
{ {
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer); EmitStore(source.Type, EmitLiteral(literal), destinationPointer);
return true; return true;
} }
} }
@@ -368,7 +368,7 @@ public class QBEGenerator
foreach (var parameter in funcDef.Signature.Parameters) foreach (var parameter in funcDef.Signature.Parameters)
{ {
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct)); scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, false));
} }
EmitBlock(funcDef.Body, scope); EmitBlock(funcDef.Body, scope);
@@ -410,10 +410,10 @@ public class QBEGenerator
var scope = new Scope(); var scope = new Scope();
scope.Declare("this", new Val("%this", structDef.Type, ValKind.Direct)); scope.Declare("this", new Val("%this", structDef.Type, false));
foreach (var parameter in function.Signature.Parameters) foreach (var parameter in function.Signature.Parameters)
{ {
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct)); scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, false));
} }
EmitBlock(function.Body, scope); EmitBlock(function.Body, scope);
@@ -531,12 +531,12 @@ public class QBEGenerator
private void EmitAssignment(AssignmentNode assignment) private void EmitAssignment(AssignmentNode assignment)
{ {
var destination = EmitExpression(assignment.Target); if (!assignment.Target.IsLValue)
if (destination.Kind != ValKind.Pointer)
{ {
throw new UnreachableException("Destination of assignment must be a pointer. This should be caught in the type checker"); throw new UnreachableException("Destination of assignment must be an lvalue. This should have been caught in the type checker");
} }
var destination = EmitExpression(assignment.Target);
EmitCopyIntoOrInitialize(assignment.Value, destination.Name); EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
} }
@@ -600,7 +600,7 @@ public class QBEGenerator
EmitStore(variableDeclaration.Assignment.Value.Type, value, name); EmitStore(variableDeclaration.Assignment.Value.Type, value, name);
} }
Scope.Declare(variableDeclaration.Name, new Val(name, variableDeclaration.Type, ValKind.Pointer)); Scope.Declare(variableDeclaration.Name, new Val(name, variableDeclaration.Type, true));
} }
private void EmitWhile(WhileNode whileStatement) private void EmitWhile(WhileNode whileStatement)
@@ -626,7 +626,7 @@ public class QBEGenerator
private Val EmitExpression(ExpressionNode expression) private Val EmitExpression(ExpressionNode expression)
{ {
return expression switch var value = expression switch
{ {
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer), ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
StructInitializerNode structInitializer => EmitStructInitializer(structInitializer), StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
@@ -646,9 +646,11 @@ public class QBEGenerator
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex), ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
_ => throw new ArgumentOutOfRangeException(nameof(expression)) _ => throw new ArgumentOutOfRangeException(nameof(expression))
}; };
return new Val(value, expression.Type, expression.IsLValue);
} }
private Val EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess) private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
{ {
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target)); var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index)); var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
@@ -661,7 +663,7 @@ public class QBEGenerator
_writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}"); _writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}");
_writer.Indented($"{pointer} =l add {pointer}, 8"); _writer.Indented($"{pointer} =l add {pointer}, 8");
_writer.Indented($"{pointer} =l add {array}, {pointer}"); _writer.Indented($"{pointer} =l add {array}, {pointer}");
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer); return pointer;
} }
private void EmitArraysCheck(string array, string index) private void EmitArraysCheck(string array, string index)
@@ -688,7 +690,7 @@ public class QBEGenerator
_writer.Indented(notOobLabel); _writer.Indented(notOobLabel);
} }
private Val EmitArrayInitializer(ArrayInitializerNode arrayInitializer) private string 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);
@@ -706,26 +708,26 @@ public class QBEGenerator
_writer.Indented($"{dataPointer} =l add {arrayPointer}, 8"); _writer.Indented($"{dataPointer} =l add {arrayPointer}, 8");
_writer.Indented($"call $nub_memset(l {dataPointer}, w 0, l {capacityInBytes})"); _writer.Indented($"call $nub_memset(l {dataPointer}, w 0, l {capacityInBytes})");
return new Val(arrayPointer, arrayInitializer.Type, ValKind.Direct); return arrayPointer;
} }
private Val EmitDereference(DereferenceNode dereference) private string EmitDereference(DereferenceNode dereference)
{ {
return EmitLoad(dereference.Type, EmitUnwrap(EmitExpression(dereference.Expression))); return EmitLoad(dereference.Type, EmitUnwrap(EmitExpression(dereference.Expression)));
} }
private Val EmitAddressOf(AddressOfNode addressOf) private string EmitAddressOf(AddressOfNode addressOf)
{ {
var value = EmitExpression(addressOf.Expression); var value = EmitExpression(addressOf.Expression);
if (value.Kind != ValKind.Pointer) if (!value.IsLValue)
{ {
throw new UnreachableException("Tried to take address of non-pointer type. This should have been caught in the type checker"); throw new UnreachableException("Tried to take address of rvalue. This should have been caught in the type checker");
} }
return new Val(value.Name, addressOf.Type, ValKind.Direct); return value.Name;
} }
private Val EmitBinaryExpression(BinaryExpressionNode binaryExpression) private string 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));
@@ -735,7 +737,7 @@ public class QBEGenerator
var instruction = EmitBinaryInstructionFor(binaryExpression.Operator, binaryExpression.Left.Type, left, right); var instruction = EmitBinaryInstructionFor(binaryExpression.Operator, binaryExpression.Left.Type, left, right);
_writer.Indented($"{outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}"); _writer.Indented($"{outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}");
return new Val(outputName, binaryExpression.Type, ValKind.Direct); return outputName;
} }
private string EmitBinaryInstructionFor(BinaryOperator op, TypeNode type, string left, string right) private string EmitBinaryInstructionFor(BinaryOperator op, TypeNode type, string left, string right)
@@ -832,24 +834,24 @@ public class QBEGenerator
}; };
} }
private Val EmitExternFuncIdent(ExternFuncIdentNode externFuncIdent) private string EmitExternFuncIdent(ExternFuncIdentNode externFuncIdent)
{ {
var func = _definitionTable.LookupExternFunc(externFuncIdent.Name); var func = _definitionTable.LookupExternFunc(externFuncIdent.Name);
return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct); return ExternFuncName(func);
} }
private Val EmitLocalFuncIdent(LocalFuncIdentNode localFuncIdent) private string EmitLocalFuncIdent(LocalFuncIdentNode localFuncIdent)
{ {
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name); var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name);
return new Val(LocalFuncName(func), localFuncIdent.Type, ValKind.Direct); return LocalFuncName(func);
} }
private Val EmitVariableIdent(VariableIdentNode variableIdent) private string EmitVariableIdent(VariableIdentNode variableIdent)
{ {
return Scope.Lookup(variableIdent.Name); return variableIdent.Name;
} }
private Val EmitLiteral(LiteralNode literal) private string EmitLiteral(LiteralNode literal)
{ {
switch (literal.Kind) switch (literal.Kind)
{ {
@@ -859,19 +861,19 @@ public class QBEGenerator
{ {
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture); var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.SingleToInt32Bits(value); var bits = BitConverter.SingleToInt32Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct); return bits.ToString();
} }
if (literal.Type is FloatTypeNode { Width: 64 }) if (literal.Type is FloatTypeNode { Width: 64 })
{ {
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture); var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.DoubleToInt64Bits(value); var bits = BitConverter.DoubleToInt64Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct); return bits.ToString();
} }
if (literal.Type is IntTypeNode) if (literal.Type is IntTypeNode)
{ {
return new Val(literal.Value, literal.Type, ValKind.Direct); return literal.Value;
} }
break; break;
@@ -880,21 +882,21 @@ public class QBEGenerator
{ {
if (literal.Type is IntTypeNode) if (literal.Type is IntTypeNode)
{ {
return new Val(literal.Value.Split(".").First(), literal.Type, ValKind.Direct); return literal.Value.Split(".").First();
} }
if (literal.Type is FloatTypeNode { Width: 32 }) if (literal.Type is FloatTypeNode { Width: 32 })
{ {
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture); var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.SingleToInt32Bits(value); var bits = BitConverter.SingleToInt32Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct); return bits.ToString();
} }
if (literal.Type is FloatTypeNode { Width: 64 }) if (literal.Type is FloatTypeNode { Width: 64 })
{ {
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture); var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
var bits = BitConverter.DoubleToInt64Bits(value); var bits = BitConverter.DoubleToInt64Bits(value);
return new Val(bits.ToString(), literal.Type, ValKind.Direct); return bits.ToString();
} }
break; break;
@@ -905,14 +907,14 @@ public class QBEGenerator
{ {
var stringLiteral = new StringLiteral(literal.Value, StringName()); var stringLiteral = new StringLiteral(literal.Value, StringName());
_stringLiterals.Add(stringLiteral); _stringLiterals.Add(stringLiteral);
return new Val(stringLiteral.Name, literal.Type, ValKind.Direct); return stringLiteral.Name;
} }
if (literal.Type is CStringTypeNode) if (literal.Type is CStringTypeNode)
{ {
var cStringLiteral = new CStringLiteral(literal.Value, CStringName()); var cStringLiteral = new CStringLiteral(literal.Value, CStringName());
_cStringLiterals.Add(cStringLiteral); _cStringLiterals.Add(cStringLiteral);
return new Val(cStringLiteral.Name, literal.Type, ValKind.Direct); return cStringLiteral.Name;
} }
break; break;
@@ -921,7 +923,7 @@ public class QBEGenerator
{ {
if (literal.Type is BoolTypeNode) if (literal.Type is BoolTypeNode)
{ {
return new Val(bool.Parse(literal.Value) ? "1" : "0", literal.Type, ValKind.Direct); return bool.Parse(literal.Value) ? "1" : "0";
} }
break; break;
@@ -931,7 +933,7 @@ public class QBEGenerator
throw new NotSupportedException($"Cannot create literal of kind '{literal.Kind}' for type {literal.Type}"); throw new NotSupportedException($"Cannot create literal of kind '{literal.Kind}' for type {literal.Type}");
} }
private Val EmitStructInitializer(StructInitializerNode structInitializer, string? destination = null) private string EmitStructInitializer(StructInitializerNode structInitializer, string? destination = null)
{ {
var structDef = _definitionTable.LookupStruct(structInitializer.StructType.Name); var structDef = _definitionTable.LookupStruct(structInitializer.StructType.Name);
@@ -959,10 +961,10 @@ public class QBEGenerator
EmitCopyIntoOrInitialize(valueExpression, offset); EmitCopyIntoOrInitialize(valueExpression, offset);
} }
return new Val(destination, structInitializer.StructType, ValKind.Direct); return destination;
} }
private Val EmitUnaryExpression(UnaryExpressionNode unaryExpression) private string EmitUnaryExpression(UnaryExpressionNode unaryExpression)
{ {
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand)); var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
var outputName = TmpName(); var outputName = TmpName();
@@ -975,16 +977,16 @@ public class QBEGenerator
{ {
case IntTypeNode { Signed: true, Width: 64 }: case IntTypeNode { Signed: true, Width: 64 }:
_writer.Indented($"{outputName} =l neg {operand}"); _writer.Indented($"{outputName} =l neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return outputName;
case IntTypeNode { Signed: true, Width: 8 or 16 or 32 }: case IntTypeNode { Signed: true, Width: 8 or 16 or 32 }:
_writer.Indented($"{outputName} =w neg {operand}"); _writer.Indented($"{outputName} =w neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return outputName;
case FloatTypeNode { Width: 64 }: case FloatTypeNode { Width: 64 }:
_writer.Indented($"{outputName} =d neg {operand}"); _writer.Indented($"{outputName} =d neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return outputName;
case FloatTypeNode { Width: 32 }: case FloatTypeNode { Width: 32 }:
_writer.Indented($"{outputName} =s neg {operand}"); _writer.Indented($"{outputName} =s neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return outputName;
} }
break; break;
@@ -995,7 +997,7 @@ public class QBEGenerator
{ {
case BoolTypeNode: case BoolTypeNode:
_writer.Indented($"{outputName} =w xor {operand}, 1"); _writer.Indented($"{outputName} =w xor {operand}, 1");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return outputName;
} }
break; break;
@@ -1009,7 +1011,7 @@ public class QBEGenerator
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported"); throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
} }
private Val EmitStructFieldAccess(StructFieldAccessNode structFieldAccess) private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
{ {
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target)); var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
@@ -1019,16 +1021,10 @@ public class QBEGenerator
var output = TmpName(); var output = TmpName();
_writer.Indented($"{output} =l add {target}, {offset}"); _writer.Indented($"{output} =l add {target}, {offset}");
// If the accessed member is an inline struct, it will not be a pointer return output;
if (structFieldAccess.Type is StructTypeNode)
{
return new Val(output, structFieldAccess.Type, ValKind.Direct);
}
return new Val(output, structFieldAccess.Type, ValKind.Pointer);
} }
private Val EmitStructFuncCall(StructFuncCallNode structFuncCall) private string EmitStructFuncCall(StructFuncCallNode structFuncCall)
{ {
var structDef = _definitionTable.LookupStruct(structFuncCall.StructType.Name); var structDef = _definitionTable.LookupStruct(structFuncCall.StructType.Name);
var func = StructFuncName(structDef.Name, structFuncCall.Name); var func = StructFuncName(structDef.Name, structFuncCall.Name);
@@ -1046,17 +1042,17 @@ public class QBEGenerator
if (structFuncCall.Type is VoidTypeNode) if (structFuncCall.Type is VoidTypeNode)
{ {
_writer.Indented($"call {func}({string.Join(", ", parameterStrings)})"); _writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
return new Val(string.Empty, structFuncCall.Type, ValKind.Direct); return string.Empty;
} }
else else
{ {
var outputName = TmpName(); var outputName = TmpName();
_writer.Indented($"{outputName} {QBEAssign(structFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})"); _writer.Indented($"{outputName} {QBEAssign(structFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
return new Val(outputName, structFuncCall.Type, ValKind.Direct); return outputName;
} }
} }
private Val EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall) private string EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall)
{ {
var target = EmitUnwrap(EmitExpression(interfaceFuncCall.InterfaceExpression)); var target = EmitUnwrap(EmitExpression(interfaceFuncCall.InterfaceExpression));
@@ -1087,17 +1083,17 @@ public class QBEGenerator
if (interfaceFuncCall.Type is VoidTypeNode) if (interfaceFuncCall.Type is VoidTypeNode)
{ {
_writer.Indented($"call {func}({string.Join(", ", parameterStrings)})"); _writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
return new Val(string.Empty, interfaceFuncCall.Type, ValKind.Direct); return string.Empty;
} }
else else
{ {
var outputName = TmpName(); var outputName = TmpName();
_writer.Indented($"{outputName} {QBEAssign(interfaceFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})"); _writer.Indented($"{outputName} {QBEAssign(interfaceFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
return new Val(outputName, interfaceFuncCall.Type, ValKind.Direct); return outputName;
} }
} }
private Val EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null) private string EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
{ {
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation)); var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
@@ -1126,10 +1122,10 @@ public class QBEGenerator
_writer.Indented($"{objectPointer} =l add {destination}, 8"); _writer.Indented($"{objectPointer} =l add {destination}, 8");
_writer.Indented($"storel {implementation}, {objectPointer}"); _writer.Indented($"storel {implementation}, {objectPointer}");
return new Val(destination, interfaceInitializer.InterfaceType, ValKind.Direct); return destination;
} }
private Val EmitFuncCall(FuncCallNode funcCall) private string EmitFuncCall(FuncCallNode funcCall)
{ {
var expression = EmitExpression(funcCall.Expression); var expression = EmitExpression(funcCall.Expression);
@@ -1145,24 +1141,19 @@ public class QBEGenerator
if (funcCall.Type is VoidTypeNode) if (funcCall.Type is VoidTypeNode)
{ {
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})"); _writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
return new Val(string.Empty, funcCall.Type, ValKind.Direct); return string.Empty;
} }
else else
{ {
var outputName = TmpName(); var outputName = TmpName();
_writer.Indented($"{outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})"); _writer.Indented($"{outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
return new Val(outputName, funcCall.Type, ValKind.Direct); return outputName;
} }
} }
private string EmitUnwrap(Val val) private string EmitUnwrap(Val val)
{ {
return val.Kind switch return val.Name;
{
ValKind.Direct => val.Name,
ValKind.Pointer => EmitLoad(val.Type, val.Name).Name,
_ => throw new ArgumentOutOfRangeException()
};
} }
private static int SizeOf(TypeNode type) private static int SizeOf(TypeNode type)
@@ -1329,7 +1320,7 @@ public class CStringLiteral(string value, string name)
public string Name { get; } = name; public string Name { get; } = name;
} }
public record Val(string Name, TypeNode Type, ValKind Kind); public record Val(string Name, TypeNode Type, bool IsLValue);
public class Scope(Scope? parent = null) public class Scope(Scope? parent = null)
{ {
@@ -1355,10 +1346,4 @@ public class Scope(Scope? parent = null)
{ {
return new Scope(this); return new Scope(this);
} }
}
public enum ValKind
{
Pointer,
Direct,
} }

View File

@@ -22,36 +22,36 @@ public enum BinaryOperator
Divide Divide
} }
public abstract record ExpressionNode(TypeNode Type) : Node; public abstract record ExpressionNode(TypeNode Type, bool IsLValue) : Node;
public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : ExpressionNode(Type); public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : ExpressionNode(Type, false);
public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand) : ExpressionNode(Type); public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand) : ExpressionNode(Type, false);
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type); public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type, false);
public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type); public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type, false);
public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type); public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type, false);
public record VariableIdentNode(TypeNode Type, string Name) : ExpressionNode(Type); public record VariableIdentNode(TypeNode Type, string Name) : ExpressionNode(Type, true);
public record LocalFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type); public record LocalFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type, false);
public record ExternFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type); public record ExternFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type, false);
public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : ExpressionNode(Type); public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : ExpressionNode(Type, true);
public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index) : ExpressionNode(Type); public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index) : ExpressionNode(Type, true);
public record AddressOfNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type); public record AddressOfNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type, false);
public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : ExpressionNode(Type); public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : ExpressionNode(Type, false);
public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field) : ExpressionNode(Type); public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field) : ExpressionNode(Type, true);
public record StructInitializerNode(StructTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType); public record StructInitializerNode(StructTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType, true);
public record DereferenceNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type); public record DereferenceNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type, false);
public record InterfaceInitializerNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation) : ExpressionNode(Type); public record InterfaceInitializerNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation) : ExpressionNode(Type, true);