This commit is contained in:
nub31
2025-08-12 20:01:43 +02:00
parent ad33cd7318
commit 1ef1df545f
10 changed files with 204 additions and 37 deletions

View File

@@ -1,5 +1,27 @@
interface Printable
{
func print()
}
struct Human : Printable {
name: cstring
func print_name()
{
puts(this^.name)
}
func print()
{
puts("example")
}
}
func main(args: []cstring): i64 func main(args: []cstring): i64
{ {
puts("test") let human: Human = alloc Human {
name = "oliver"
}
human.print()
return 0 return 0
} }

View File

@@ -18,12 +18,14 @@ public partial class QBEGenerator
ArrowFuncNode arrowFunc => EmitArrowFunc(arrowFunc), ArrowFuncNode arrowFunc => EmitArrowFunc(arrowFunc),
BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression), BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression), FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
InterfaceFuncAccessNode interfaceFuncAccess => EmitInterfaceFuncAccess(interfaceFuncAccess),
ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent), ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent), LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
VariableIdentNode variableIdent => EmitVariableIdent(variableIdent), VariableIdentNode variableIdent => EmitVariableIdent(variableIdent),
LiteralNode literal => EmitLiteral(literal), LiteralNode literal => EmitLiteral(literal),
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression), UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess), StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
StructFuncAccessNode structFuncAccess => EmitStructFuncAccess(structFuncAccess),
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex), ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
_ => throw new ArgumentOutOfRangeException(nameof(expression)) _ => throw new ArgumentOutOfRangeException(nameof(expression))
}; };
@@ -321,16 +323,22 @@ public partial class QBEGenerator
private Val EmitStructInitializer(StructInitializerNode structInitializer, string? destination = null) private Val EmitStructInitializer(StructInitializerNode structInitializer, string? destination = null)
{ {
var @struct = _definitionTable.LookupStruct(structInitializer.StructType.Name); var structDef = _definitionTable.LookupStruct(structInitializer.StructType.Name);
if (destination == null) if (destination == null)
{ {
destination = TmpName(); destination = TmpName();
var size = structInitializer.StructType.Size(_definitionTable); var size = structInitializer.StructType.Size(_definitionTable);
if (structDef.InterfaceImplementations.Any())
{
size += 8;
}
_writer.Indented($"{destination} =l alloc8 {size}"); _writer.Indented($"{destination} =l alloc8 {size}");
} }
foreach (var field in @struct.Fields) foreach (var field in structDef.Fields)
{ {
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression)) if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
{ {
@@ -340,7 +348,7 @@ public partial class QBEGenerator
Debug.Assert(valueExpression != null); Debug.Assert(valueExpression != null);
var offset = TmpName(); var offset = TmpName();
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(@struct, field.Name)}"); _writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDef, field.Name)}");
EmitCopyIntoOrInitialize(valueExpression, offset); EmitCopyIntoOrInitialize(valueExpression, offset);
} }
@@ -413,6 +421,20 @@ public partial class QBEGenerator
return new Val(output, structFieldAccess.Type, ValKind.Pointer); return new Val(output, structFieldAccess.Type, ValKind.Pointer);
} }
private Val EmitStructFuncAccess(StructFuncAccessNode structFuncAccess)
{
var target = EmitExpression(structFuncAccess.Target);
var structDef = _definitionTable.LookupStruct(structFuncAccess.StructType.Name);
var func = StructFuncName(structDef.Name, structFuncAccess.Func);
return new Val(func, structFuncAccess.Type, ValKind.Direct, target);
}
private Val EmitInterfaceFuncAccess(InterfaceFuncAccessNode interfaceFuncAccess)
{
throw new NotImplementedException();
}
private Val EmitFuncCall(FuncCallNode funcCall) private Val EmitFuncCall(FuncCallNode funcCall)
{ {
var expression = EmitExpression(funcCall.Expression); var expression = EmitExpression(funcCall.Expression);
@@ -420,6 +442,12 @@ public partial class QBEGenerator
var parameterStrings = new List<string>(); var parameterStrings = new List<string>();
if (expression.ThisArg != null)
{
Debug.Assert(expression.ThisArg.Kind == ValKind.Pointer);
parameterStrings.Add($"l {expression.ThisArg.Name}");
}
foreach (var parameter in funcCall.Parameters) foreach (var parameter in funcCall.Parameters)
{ {
var copy = EmitCreateCopyOrInitialize(parameter); var copy = EmitCreateCopyOrInitialize(parameter);

View File

@@ -51,10 +51,20 @@ public partial class QBEGenerator
foreach (var structDef in _definitionTable.GetStructs()) foreach (var structDef in _definitionTable.GetStructs())
{ {
EmitStructDefinition(structDef); EmitStructTypeDefinition(structDef);
_writer.NewLine(); _writer.NewLine();
} }
foreach (var structDef in _syntaxTree.Definitions.OfType<StructNode>())
{
foreach (var func in structDef.Functions)
{
var funcName = StructFuncName(structDef.Name, func.Name);
EmitFuncDefinition(funcName, func.Signature.Parameters, func.Signature.ReturnType, func.Body);
_writer.NewLine();
}
}
foreach (var funcDef in _syntaxTree.Definitions.OfType<LocalFuncNode>()) foreach (var funcDef in _syntaxTree.Definitions.OfType<LocalFuncNode>())
{ {
EmitFuncDefinition(LocalFuncName(funcDef), funcDef.Signature.Parameters, funcDef.Signature.ReturnType, funcDef.Body); EmitFuncDefinition(LocalFuncName(funcDef), funcDef.Signature.Parameters, funcDef.Signature.ReturnType, funcDef.Body);
@@ -67,6 +77,22 @@ public partial class QBEGenerator
_writer.NewLine(); _writer.NewLine();
} }
foreach (var structDef in _syntaxTree.Definitions.OfType<StructNode>().Where(x => x.InterfaceImplementations.Count > 0))
{
_writer.Write($"data {StructVtableName(structDef.Name)} = {{ ");
foreach (var interfaceImplementation in structDef.InterfaceImplementations)
{
var interfaceDef = _definitionTable.LookupInterface(interfaceImplementation.Name);
foreach (var func in interfaceDef.Functions)
{
_writer.Write($"l {StructFuncName(structDef.Name, func.Name)}, ");
}
}
_writer.WriteLine("}");
}
foreach (var cStringLiteral in _cStringLiterals) foreach (var cStringLiteral in _cStringLiterals)
{ {
_writer.WriteLine($"data {cStringLiteral.Name} = {{ b \"{cStringLiteral.Value}\", b 0 }}"); _writer.WriteLine($"data {cStringLiteral.Name} = {{ b \"{cStringLiteral.Value}\", b 0 }}");
@@ -315,7 +341,7 @@ public partial class QBEGenerator
if (complexType is CustomTypeNode customType) if (complexType is CustomTypeNode customType)
{ {
return CustomTypeName(customType); return CustomTypeName(customType.Name);
} }
return "l"; return "l";
@@ -359,7 +385,7 @@ public partial class QBEGenerator
_writer.WriteLine("}"); _writer.WriteLine("}");
} }
private void EmitStructDefinition(StructNode structDef) private void EmitStructTypeDefinition(StructNode structDef)
{ {
_writer.WriteLine($"type {CustomTypeName(structDef.Name)} = {{ "); _writer.WriteLine($"type {CustomTypeName(structDef.Name)} = {{ ");
@@ -398,7 +424,7 @@ public partial class QBEGenerator
if (complexType is CustomTypeNode customType) if (complexType is CustomTypeNode customType)
{ {
return CustomTypeName(customType); return CustomTypeName(customType.Name);
} }
return "l"; return "l";
@@ -432,11 +458,16 @@ public partial class QBEGenerator
}; };
} }
private int OffsetOf(StructNode structDefinition, string member) private int OffsetOf(StructNode structDef, string member)
{ {
var offset = 0; var offset = 0;
foreach (var field in structDefinition.Fields) if (structDef.InterfaceImplementations.Any())
{
offset = 8;
}
foreach (var field in structDef.Fields)
{ {
if (field.Name == member) if (field.Name == member)
{ {
@@ -484,16 +515,21 @@ public partial class QBEGenerator
return $"${funcDef.CallName}"; return $"${funcDef.CallName}";
} }
private string CustomTypeName(CustomTypeNode customType)
{
return CustomTypeName(customType.Name);
}
private string CustomTypeName(string name) private string CustomTypeName(string name)
{ {
return $":{name}"; return $":{name}";
} }
private string StructFuncName(string structName, string funcName)
{
return $"${structName}_{funcName}";
}
private string StructVtableName(string structName)
{
return $"${structName}_vtable";
}
#endregion #endregion
} }
@@ -509,7 +545,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, ValKind Kind, Val? ThisArg = null);
public class Scope(Scope? parent = null) public class Scope(Scope? parent = null)
{ {

View File

@@ -32,6 +32,13 @@ public sealed class TypedDefinitionTable
.First(x => x.Name == name); .First(x => x.Name == name);
} }
public InterfaceNode LookupInterface(string name)
{
return _definitions
.OfType<InterfaceNode>()
.First(x => x.Name == name);
}
public IEnumerable<StructNode> GetStructs() public IEnumerable<StructNode> GetStructs()
{ {
return _definitions.OfType<StructNode>(); return _definitions.OfType<StructNode>();

View File

@@ -66,14 +66,14 @@ public sealed class Parser
return new SyntaxTree(GetTokens(_tokenIndex), definitions); return new SyntaxTree(GetTokens(_tokenIndex), definitions);
} }
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null) private FuncSignatureSyntax ParseFuncSignature(TypeSyntax? thisArg = null)
{ {
var startIndex = _tokenIndex; var startIndex = _tokenIndex;
List<FuncParameterSyntax> parameters = []; List<FuncParameterSyntax> parameters = [];
if (thisArg != null) if (thisArg != null)
{ {
parameters.Add(thisArg); parameters.Add(new FuncParameterSyntax([], "this", new PointerTypeSyntax([], thisArg)));
} }
ExpectSymbol(Symbol.OpenParen); ExpectSymbol(Symbol.OpenParen);
@@ -150,6 +150,16 @@ public sealed class Parser
private DefinitionSyntax ParseStruct(int startIndex) private DefinitionSyntax ParseStruct(int startIndex)
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();
var interfaceImplementations = new List<TypeSyntax>();
if (TryExpectSymbol(Symbol.Colon))
{
do
{
var interfaceType = ParseType();
interfaceImplementations.Add(interfaceType);
} while (TryExpectSymbol(Symbol.Comma));
}
ExpectSymbol(Symbol.OpenBrace); ExpectSymbol(Symbol.OpenBrace);
@@ -165,8 +175,7 @@ public sealed class Parser
if (TryExpectSymbol(Symbol.Func)) if (TryExpectSymbol(Symbol.Func))
{ {
var funcName = ExpectIdentifier().Value; var funcName = ExpectIdentifier().Value;
var thisArg = new FuncParameterSyntax([], "this", new CustomTypeSyntax([], name.Value)); var funcSignature = ParseFuncSignature(new CustomTypeSyntax([], name.Value));
var funcSignature = ParseFuncSignature(thisArg);
var funcBody = ParseBlock(); var funcBody = ParseBlock();
funcs.Add(new StructFuncSyntax(GetTokens(memberStartIndex), funcName, funcSignature, funcBody)); funcs.Add(new StructFuncSyntax(GetTokens(memberStartIndex), funcName, funcSignature, funcBody));
@@ -188,7 +197,7 @@ public sealed class Parser
} }
} }
return new StructSyntax(GetTokens(startIndex), name.Value, fields, funcs); return new StructSyntax(GetTokens(startIndex), name.Value, fields, funcs, interfaceImplementations);
} }
private InterfaceSyntax ParseInterface(int startIndex) private InterfaceSyntax ParseInterface(int startIndex)

View File

@@ -63,7 +63,7 @@ public record StructFuncSyntax(IEnumerable<Token> Tokens, string Name, FuncSigna
} }
} }
public record StructSyntax(IEnumerable<Token> Tokens, string Name, IReadOnlyList<StructFieldSyntax> Fields, IReadOnlyList<StructFuncSyntax> Functions) : DefinitionSyntax(Tokens) public record StructSyntax(IEnumerable<Token> Tokens, string Name, IReadOnlyList<StructFieldSyntax> Fields, IReadOnlyList<StructFuncSyntax> Functions, IReadOnlyList<TypeSyntax> InterfaceImplementations) : DefinitionSyntax(Tokens)
{ {
public override IEnumerable<SyntaxNode> GetChildren() public override IEnumerable<SyntaxNode> GetChildren()
{ {

View File

@@ -33,9 +33,14 @@ public class DefinitionTable
.Where(x => x.Name == type.Name); .Where(x => x.Name == type.Name);
} }
public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax structNode, string field) public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax @struct, string field)
{ {
return structNode.Fields.Where(x => x.Name == field); return @struct.Fields.Where(x => x.Name == field);
}
public IEnumerable<StructFuncSyntax> LookupStructFunc(StructSyntax @struct, string func)
{
return @struct.Functions.Where(x => x.Name == func);
} }
public IEnumerable<InterfaceSyntax> LookupInterface(CustomTypeNode type) public IEnumerable<InterfaceSyntax> LookupInterface(CustomTypeNode type)

View File

@@ -12,8 +12,10 @@ public record ExternFuncNode(string Name, string CallName, FuncSignatureNode Sig
public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value) : Node; public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value) : Node;
public record StructNode(string Name, IReadOnlyList<StructFieldNode> Fields) : DefinitionNode; public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
public record InterfacenFuncNode(string Name, FuncSignatureNode Signature) : Node; public record StructNode(string Name, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<CustomTypeNode> InterfaceImplementations) : DefinitionNode;
public record InterfaceNode(string Name, IReadOnlyList<InterfacenFuncNode> Functions) : DefinitionNode; public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node;
public record InterfaceNode(string Name, IReadOnlyList<InterfaceFuncNode> Functions) : DefinitionNode;

View File

@@ -48,6 +48,8 @@ public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : Expre
public record StructFieldAccessNode(TypeNode Type, CustomTypeNode StructType, ExpressionNode Target, string Field) : ExpressionNode(Type); public record StructFieldAccessNode(TypeNode Type, CustomTypeNode StructType, ExpressionNode Target, string Field) : ExpressionNode(Type);
public record StructFuncAccessNode(TypeNode Type, CustomTypeNode StructType, ExpressionNode Target, string Func) : ExpressionNode(Type);
public record InterfaceFuncAccessNode(TypeNode Type, CustomTypeNode InterfaceType, ExpressionNode Target, string FuncName) : ExpressionNode(Type); public record InterfaceFuncAccessNode(TypeNode Type, CustomTypeNode InterfaceType, ExpressionNode Target, string FuncName) : ExpressionNode(Type);
public record StructInitializerNode(CustomTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType); public record StructInitializerNode(CustomTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType);

View File

@@ -61,11 +61,11 @@ public sealed class TypeChecker
private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node) private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node)
{ {
var functions = new List<InterfacenFuncNode>(); var functions = new List<InterfaceFuncNode>();
foreach (var function in node.Functions) foreach (var function in node.Functions)
{ {
functions.Add(new InterfacenFuncNode(function.Name, CheckFuncSignature(function.Signature))); functions.Add(new InterfaceFuncNode(function.Name, CheckFuncSignature(function.Signature)));
} }
return new InterfaceNode(node.Name, functions); return new InterfaceNode(node.Name, functions);
@@ -87,7 +87,48 @@ public sealed class TypeChecker
structFields.Add(new StructFieldNode(field.Index, field.Name, CheckType(field.Type), value)); structFields.Add(new StructFieldNode(field.Index, field.Name, CheckType(field.Type), value));
} }
return new StructNode(node.Name, structFields); var funcs = new List<StructFuncNode>();
foreach (var func in node.Functions)
{
var parameters = new List<FuncParameterNode>();
foreach (var parameter in func.Signature.Parameters)
{
parameters.Add(new FuncParameterNode(parameter.Name, CheckType(parameter.Type)));
}
funcs.Add(new StructFuncNode(func.Name, CheckFuncSignature(func.Signature), CheckFuncBody(func.Body, CheckType(func.Signature.ReturnType), parameters)));
}
var interfaceImplementations = new List<CustomTypeNode>();
foreach (var interfaceImplementation in node.InterfaceImplementations)
{
var interfaceType = CheckType(interfaceImplementation);
if (interfaceType is not CustomTypeNode customType)
{
_diagnostics.Add(Diagnostic.Error("Interface implementation is not a custom type").Build());
continue;
}
var interfaceDefs = _definitionTable.LookupInterface(customType).ToArray();
if (interfaceDefs.Length == 0)
{
_diagnostics.Add(Diagnostic.Error($"Interface {customType.Name} is not defined").Build());
continue;
}
if (interfaceDefs.Length > 1)
{
_diagnostics.Add(Diagnostic.Error($"Interface {customType.Name} has multiple definitions").Build());
continue;
}
interfaceImplementations.Add(customType);
}
return new StructNode(node.Name, structFields, funcs, interfaceImplementations);
} }
private ExternFuncNode CheckExternFuncDefinition(ExternFuncSyntax node) private ExternFuncNode CheckExternFuncDefinition(ExternFuncSyntax node)
@@ -163,11 +204,6 @@ public sealed class TypeChecker
{ {
TypeNode? type = null; TypeNode? type = null;
if (statement.ExplicitType.HasValue)
{
type = CheckType(statement.ExplicitType.Value);
}
var assignment = Optional<ExpressionNode>.Empty(); var assignment = Optional<ExpressionNode>.Empty();
if (statement.Assignment.HasValue) if (statement.Assignment.HasValue)
{ {
@@ -176,6 +212,11 @@ public sealed class TypeChecker
type = boundValue.Type; type = boundValue.Type;
} }
if (statement.ExplicitType.HasValue)
{
type = CheckType(statement.ExplicitType.Value);
}
if (type == null) if (type == null)
{ {
throw new NotImplementedException("Diagnostics not implemented"); throw new NotImplementedException("Diagnostics not implemented");
@@ -373,9 +414,9 @@ public sealed class TypeChecker
var @interface = interfaces[0]; var @interface = interfaces[0];
var interfaceFuncs = _definitionTable.LookupInterfaceFunc(@interface, expression.Member).ToArray(); var interfaceFuncs = _definitionTable.LookupInterfaceFunc(@interface, expression.Member).ToArray();
if (interfaces.Length > 0) if (interfaceFuncs.Length > 0)
{ {
if (interfaces.Length > 1) if (interfaceFuncs.Length > 1)
{ {
throw new CheckException(Diagnostic.Error($"Interface {customType} has multiple functions with the name {expression.Member}").Build()); throw new CheckException(Diagnostic.Error($"Interface {customType} has multiple functions with the name {expression.Member}").Build());
} }
@@ -411,6 +452,21 @@ public sealed class TypeChecker
return new StructFieldAccessNode(CheckType(field.Type), customType, boundExpression, expression.Member); return new StructFieldAccessNode(CheckType(field.Type), customType, boundExpression, expression.Member);
} }
var funcs = _definitionTable.LookupStructFunc(@struct, expression.Member).ToArray();
if (funcs.Length > 0)
{
if (funcs.Length > 1)
{
throw new CheckException(Diagnostic.Error($"Struct {customType} has multiple functions with the name {expression.Member}").Build());
}
var func = funcs[0];
var parameters = func.Signature.Parameters.Select(x => CheckType(x.Type)).ToList();
var returnType = CheckType(func.Signature.ReturnType);
return new StructFuncAccessNode(new FuncTypeNode(parameters, returnType), customType, boundExpression, expression.Member);
}
} }
} }