...
This commit is contained in:
@@ -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
|
||||
{
|
||||
puts("test")
|
||||
let human: Human = alloc Human {
|
||||
name = "oliver"
|
||||
}
|
||||
human.print()
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -18,12 +18,14 @@ public partial class QBEGenerator
|
||||
ArrowFuncNode arrowFunc => EmitArrowFunc(arrowFunc),
|
||||
BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
||||
FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
||||
InterfaceFuncAccessNode interfaceFuncAccess => EmitInterfaceFuncAccess(interfaceFuncAccess),
|
||||
ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
|
||||
LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
|
||||
VariableIdentNode variableIdent => EmitVariableIdent(variableIdent),
|
||||
LiteralNode literal => EmitLiteral(literal),
|
||||
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
||||
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
||||
StructFuncAccessNode structFuncAccess => EmitStructFuncAccess(structFuncAccess),
|
||||
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||
};
|
||||
@@ -321,16 +323,22 @@ public partial class QBEGenerator
|
||||
|
||||
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)
|
||||
{
|
||||
destination = TmpName();
|
||||
var size = structInitializer.StructType.Size(_definitionTable);
|
||||
|
||||
if (structDef.InterfaceImplementations.Any())
|
||||
{
|
||||
size += 8;
|
||||
}
|
||||
|
||||
_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))
|
||||
{
|
||||
@@ -340,7 +348,7 @@ public partial class QBEGenerator
|
||||
Debug.Assert(valueExpression != null);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -413,6 +421,20 @@ public partial class QBEGenerator
|
||||
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)
|
||||
{
|
||||
var expression = EmitExpression(funcCall.Expression);
|
||||
@@ -420,6 +442,12 @@ public partial class QBEGenerator
|
||||
|
||||
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)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
|
||||
@@ -51,10 +51,20 @@ public partial class QBEGenerator
|
||||
|
||||
foreach (var structDef in _definitionTable.GetStructs())
|
||||
{
|
||||
EmitStructDefinition(structDef);
|
||||
EmitStructTypeDefinition(structDef);
|
||||
_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>())
|
||||
{
|
||||
EmitFuncDefinition(LocalFuncName(funcDef), funcDef.Signature.Parameters, funcDef.Signature.ReturnType, funcDef.Body);
|
||||
@@ -67,6 +77,22 @@ public partial class QBEGenerator
|
||||
_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)
|
||||
{
|
||||
_writer.WriteLine($"data {cStringLiteral.Name} = {{ b \"{cStringLiteral.Value}\", b 0 }}");
|
||||
@@ -315,7 +341,7 @@ public partial class QBEGenerator
|
||||
|
||||
if (complexType is CustomTypeNode customType)
|
||||
{
|
||||
return CustomTypeName(customType);
|
||||
return CustomTypeName(customType.Name);
|
||||
}
|
||||
|
||||
return "l";
|
||||
@@ -359,7 +385,7 @@ public partial class QBEGenerator
|
||||
_writer.WriteLine("}");
|
||||
}
|
||||
|
||||
private void EmitStructDefinition(StructNode structDef)
|
||||
private void EmitStructTypeDefinition(StructNode structDef)
|
||||
{
|
||||
_writer.WriteLine($"type {CustomTypeName(structDef.Name)} = {{ ");
|
||||
|
||||
@@ -398,7 +424,7 @@ public partial class QBEGenerator
|
||||
|
||||
if (complexType is CustomTypeNode customType)
|
||||
{
|
||||
return CustomTypeName(customType);
|
||||
return CustomTypeName(customType.Name);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
foreach (var field in structDefinition.Fields)
|
||||
if (structDef.InterfaceImplementations.Any())
|
||||
{
|
||||
offset = 8;
|
||||
}
|
||||
|
||||
foreach (var field in structDef.Fields)
|
||||
{
|
||||
if (field.Name == member)
|
||||
{
|
||||
@@ -484,16 +515,21 @@ public partial class QBEGenerator
|
||||
return $"${funcDef.CallName}";
|
||||
}
|
||||
|
||||
private string CustomTypeName(CustomTypeNode customType)
|
||||
{
|
||||
return CustomTypeName(customType.Name);
|
||||
}
|
||||
|
||||
private string CustomTypeName(string name)
|
||||
{
|
||||
return $":{name}";
|
||||
}
|
||||
|
||||
private string StructFuncName(string structName, string funcName)
|
||||
{
|
||||
return $"${structName}_{funcName}";
|
||||
}
|
||||
|
||||
private string StructVtableName(string structName)
|
||||
{
|
||||
return $"${structName}_vtable";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -509,7 +545,7 @@ public class CStringLiteral(string value, string 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)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,13 @@ public sealed class TypedDefinitionTable
|
||||
.First(x => x.Name == name);
|
||||
}
|
||||
|
||||
public InterfaceNode LookupInterface(string name)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<InterfaceNode>()
|
||||
.First(x => x.Name == name);
|
||||
}
|
||||
|
||||
public IEnumerable<StructNode> GetStructs()
|
||||
{
|
||||
return _definitions.OfType<StructNode>();
|
||||
|
||||
@@ -66,14 +66,14 @@ public sealed class Parser
|
||||
return new SyntaxTree(GetTokens(_tokenIndex), definitions);
|
||||
}
|
||||
|
||||
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
||||
private FuncSignatureSyntax ParseFuncSignature(TypeSyntax? thisArg = null)
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
List<FuncParameterSyntax> parameters = [];
|
||||
|
||||
if (thisArg != null)
|
||||
{
|
||||
parameters.Add(thisArg);
|
||||
parameters.Add(new FuncParameterSyntax([], "this", new PointerTypeSyntax([], thisArg)));
|
||||
}
|
||||
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
@@ -150,6 +150,16 @@ public sealed class Parser
|
||||
private DefinitionSyntax ParseStruct(int startIndex)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -165,8 +175,7 @@ public sealed class Parser
|
||||
if (TryExpectSymbol(Symbol.Func))
|
||||
{
|
||||
var funcName = ExpectIdentifier().Value;
|
||||
var thisArg = new FuncParameterSyntax([], "this", new CustomTypeSyntax([], name.Value));
|
||||
var funcSignature = ParseFuncSignature(thisArg);
|
||||
var funcSignature = ParseFuncSignature(new CustomTypeSyntax([], name.Value));
|
||||
var funcBody = ParseBlock();
|
||||
|
||||
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)
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -33,9 +33,14 @@ public class DefinitionTable
|
||||
.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)
|
||||
|
||||
@@ -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 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;
|
||||
@@ -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 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 StructInitializerNode(CustomTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType);
|
||||
|
||||
@@ -61,11 +61,11 @@ public sealed class TypeChecker
|
||||
|
||||
private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node)
|
||||
{
|
||||
var functions = new List<InterfacenFuncNode>();
|
||||
var functions = new List<InterfaceFuncNode>();
|
||||
|
||||
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);
|
||||
@@ -87,7 +87,48 @@ public sealed class TypeChecker
|
||||
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)
|
||||
@@ -163,11 +204,6 @@ public sealed class TypeChecker
|
||||
{
|
||||
TypeNode? type = null;
|
||||
|
||||
if (statement.ExplicitType.HasValue)
|
||||
{
|
||||
type = CheckType(statement.ExplicitType.Value);
|
||||
}
|
||||
|
||||
var assignment = Optional<ExpressionNode>.Empty();
|
||||
if (statement.Assignment.HasValue)
|
||||
{
|
||||
@@ -176,6 +212,11 @@ public sealed class TypeChecker
|
||||
type = boundValue.Type;
|
||||
}
|
||||
|
||||
if (statement.ExplicitType.HasValue)
|
||||
{
|
||||
type = CheckType(statement.ExplicitType.Value);
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new NotImplementedException("Diagnostics not implemented");
|
||||
@@ -373,9 +414,9 @@ public sealed class TypeChecker
|
||||
var @interface = interfaces[0];
|
||||
|
||||
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());
|
||||
}
|
||||
@@ -411,6 +452,21 @@ public sealed class TypeChecker
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user