Rework this param
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
extern func puts(fmt: cstring)
|
extern func puts(text: cstring)
|
||||||
|
|
||||||
struct Human
|
struct Human
|
||||||
{
|
{
|
||||||
name: cstring
|
name: cstring
|
||||||
|
|
||||||
func str(): cstring
|
func print()
|
||||||
{
|
{
|
||||||
return this.name
|
puts(this.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ func main(args: []cstring): i64
|
|||||||
name = "oliver"
|
name = "oliver"
|
||||||
}
|
}
|
||||||
|
|
||||||
puts(human.str())
|
human.print()
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public partial class QBEGenerator
|
|||||||
BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
||||||
FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
||||||
InterfaceFuncAccessNode interfaceFuncAccess => EmitInterfaceFuncAccess(interfaceFuncAccess),
|
InterfaceFuncAccessNode interfaceFuncAccess => EmitInterfaceFuncAccess(interfaceFuncAccess),
|
||||||
|
InterfaceFuncCallNode interfaceFuncCall => EmitInterfaceFuncCall(interfaceFuncCall),
|
||||||
InterfaceInitializerNode interfaceInitializer => EmitInterfaceInitializer(interfaceInitializer),
|
InterfaceInitializerNode interfaceInitializer => EmitInterfaceInitializer(interfaceInitializer),
|
||||||
ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
|
ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
|
||||||
LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
|
LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
|
||||||
@@ -26,6 +27,7 @@ public partial class QBEGenerator
|
|||||||
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
||||||
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
||||||
StructFuncAccessNode structFuncAccess => EmitStructFuncAccess(structFuncAccess),
|
StructFuncAccessNode structFuncAccess => EmitStructFuncAccess(structFuncAccess),
|
||||||
|
StructFuncCallNode structFuncCall => EmitStructFuncCall(structFuncCall),
|
||||||
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
};
|
};
|
||||||
@@ -419,6 +421,33 @@ public partial class QBEGenerator
|
|||||||
return new Val(func, structFuncAccess.Type, ValKind.Direct);
|
return new Val(func, structFuncAccess.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Val EmitStructFuncCall(StructFuncCallNode structFuncCall)
|
||||||
|
{
|
||||||
|
var expression = EmitExpression(structFuncCall.Expression);
|
||||||
|
var thisParameter = EmitUnwrap(EmitExpression(structFuncCall.ThisParam));
|
||||||
|
|
||||||
|
List<string> parameterStrings = [$"l {thisParameter}"];
|
||||||
|
|
||||||
|
foreach (var parameter in structFuncCall.Parameters)
|
||||||
|
{
|
||||||
|
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||||
|
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var funcPointer = EmitUnwrap(expression);
|
||||||
|
if (structFuncCall.Type is VoidTypeNode)
|
||||||
|
{
|
||||||
|
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
|
return new Val(string.Empty, structFuncCall.Type, ValKind.Direct);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var outputName = TmpName();
|
||||||
|
_writer.Indented($"{outputName} {QBEAssign(structFuncCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
|
return new Val(outputName, structFuncCall.Type, ValKind.Direct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Val EmitInterfaceFuncAccess(InterfaceFuncAccessNode interfaceFuncAccess)
|
private Val EmitInterfaceFuncAccess(InterfaceFuncAccessNode interfaceFuncAccess)
|
||||||
{
|
{
|
||||||
var target = EmitUnwrap(EmitExpression(interfaceFuncAccess.Target));
|
var target = EmitUnwrap(EmitExpression(interfaceFuncAccess.Target));
|
||||||
@@ -439,6 +468,11 @@ public partial class QBEGenerator
|
|||||||
return new Val(func, interfaceFuncAccess.Type, ValKind.Direct);
|
return new Val(func, interfaceFuncAccess.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Val EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
private Val EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
|
private Val EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
|
||||||
{
|
{
|
||||||
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
|
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
|
||||||
|
|||||||
@@ -53,17 +53,13 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
foreach (var structDef in _syntaxTree.Definitions.OfType<StructNode>())
|
foreach (var structDef in _syntaxTree.Definitions.OfType<StructNode>())
|
||||||
{
|
{
|
||||||
foreach (var func in structDef.Functions)
|
EmitStructDefinition(structDef);
|
||||||
{
|
|
||||||
var funcName = StructFuncName(structDef.Name, func.Name);
|
|
||||||
EmitFuncDefinition(funcName, func.Signature.Parameters, func.Signature.ReturnType, func.Body);
|
|
||||||
_writer.NewLine();
|
_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);
|
EmitLocalFuncDefinition(funcDef);
|
||||||
_writer.NewLine();
|
_writer.NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,37 +339,40 @@ public partial class QBEGenerator
|
|||||||
return "l";
|
return "l";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitFuncDefinition(string name, IReadOnlyList<FuncParameterNode> parameters, TypeNode returnType, BlockNode body)
|
private void EmitLocalFuncDefinition(LocalFuncNode funcDef)
|
||||||
{
|
{
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
_tmpIndex = 0;
|
_tmpIndex = 0;
|
||||||
|
|
||||||
_writer.Write("export function ");
|
_writer.Write("export function ");
|
||||||
|
|
||||||
if (returnType is not VoidTypeNode)
|
if (funcDef.Signature.ReturnType is not VoidTypeNode)
|
||||||
{
|
{
|
||||||
_writer.Write(FuncQBETypeName(returnType) + ' ');
|
_writer.Write(FuncQBETypeName(funcDef.Signature.ReturnType) + ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.Write(name);
|
_writer.Write(LocalFuncName(funcDef));
|
||||||
|
|
||||||
var parameterStrings = parameters.Select(x => FuncQBETypeName(x.Type) + $" %{x.Name}");
|
_writer.Write("(");
|
||||||
|
foreach (var parameter in funcDef.Signature.Parameters)
|
||||||
|
{
|
||||||
|
_writer.Write(FuncQBETypeName(parameter.Type) + $" %{parameter.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
_writer.Write($"({string.Join(", ", parameterStrings)})");
|
_writer.WriteLine(") {");
|
||||||
_writer.WriteLine(" {");
|
|
||||||
_writer.WriteLine("@start");
|
_writer.WriteLine("@start");
|
||||||
|
|
||||||
var scope = new Scope();
|
var scope = new Scope();
|
||||||
|
|
||||||
foreach (var parameter in 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, ValKind.Direct));
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitBlock(body, scope);
|
EmitBlock(funcDef.Body, scope);
|
||||||
|
|
||||||
// Implicit return for void functions if no explicit return has been set
|
// Implicit return for void functions if no explicit return has been set
|
||||||
if (returnType is VoidTypeNode && body.Statements is [.., not ReturnNode])
|
if (funcDef.Signature.ReturnType is VoidTypeNode && funcDef.Body.Statements is [.., not ReturnNode])
|
||||||
{
|
{
|
||||||
_writer.Indented("ret");
|
_writer.Indented("ret");
|
||||||
}
|
}
|
||||||
@@ -381,6 +380,57 @@ public partial class QBEGenerator
|
|||||||
_writer.WriteLine("}");
|
_writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EmitStructDefinition(StructNode structDef)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < structDef.Functions.Count; i++)
|
||||||
|
{
|
||||||
|
var function = structDef.Functions[i];
|
||||||
|
_labelIndex = 0;
|
||||||
|
_tmpIndex = 0;
|
||||||
|
|
||||||
|
_writer.Write("export function ");
|
||||||
|
|
||||||
|
if (function.Signature.ReturnType is not VoidTypeNode)
|
||||||
|
{
|
||||||
|
_writer.Write(FuncQBETypeName(function.Signature.ReturnType) + ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.Write(StructFuncName(structDef.Name, function.Name));
|
||||||
|
|
||||||
|
_writer.Write("(l %this, ");
|
||||||
|
foreach (var parameter in function.Signature.Parameters)
|
||||||
|
{
|
||||||
|
_writer.Write(FuncQBETypeName(parameter.Type) + $" %{parameter.Name}, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine(") {");
|
||||||
|
_writer.WriteLine("@start");
|
||||||
|
|
||||||
|
var scope = new Scope();
|
||||||
|
|
||||||
|
scope.Declare("this", new Val("%this", structDef.Type, ValKind.Direct));
|
||||||
|
foreach (var parameter in function.Signature.Parameters)
|
||||||
|
{
|
||||||
|
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct));
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitBlock(function.Body, scope);
|
||||||
|
|
||||||
|
// Implicit return for void functions if no explicit return has been set
|
||||||
|
if (function.Signature.ReturnType is VoidTypeNode && function.Body.Statements is [.., not ReturnNode])
|
||||||
|
{
|
||||||
|
_writer.Indented("ret");
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine("}");
|
||||||
|
|
||||||
|
if (i != structDef.Functions.Count - 1)
|
||||||
|
{
|
||||||
|
_writer.NewLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void EmitStructTypeDefinition(StructNode structDef)
|
private void EmitStructTypeDefinition(StructNode structDef)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"type {StructTypeName(structDef.Name)} = {{ ");
|
_writer.WriteLine($"type {StructTypeName(structDef.Name)} = {{ ");
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<Ex
|
|||||||
|
|
||||||
public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
|
public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
|
||||||
|
|
||||||
public record StructNode(string Name, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<InterfaceTypeNode> InterfaceImplementations) : DefinitionNode;
|
public record StructNode(string Name, StructTypeNode Type, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<InterfaceTypeNode> InterfaceImplementations) : DefinitionNode;
|
||||||
|
|
||||||
public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node;
|
public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, Express
|
|||||||
|
|
||||||
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
||||||
|
|
||||||
|
public record StructFuncCallNode(TypeNode Type, ExpressionNode Expression, ExpressionNode ThisParam, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
||||||
|
|
||||||
|
public record InterfaceFuncCallNode(TypeNode Type, ExpressionNode Expression, ExpressionNode ThisParam, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
||||||
|
|
||||||
public record VariableIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
public record VariableIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
||||||
|
|
||||||
public record LocalFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
public record LocalFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public sealed class TypeChecker
|
|||||||
private readonly Stack<Scope> _scopes = [];
|
private readonly Stack<Scope> _scopes = [];
|
||||||
private readonly Stack<TypeNode> _funcReturnTypes = [];
|
private readonly Stack<TypeNode> _funcReturnTypes = [];
|
||||||
private readonly List<Diagnostic> _diagnostics = [];
|
private readonly List<Diagnostic> _diagnostics = [];
|
||||||
|
private readonly Dictionary<string, TypeNode> _typeCache = new();
|
||||||
|
|
||||||
private Scope Scope => _scopes.Peek();
|
private Scope Scope => _scopes.Peek();
|
||||||
|
|
||||||
@@ -91,13 +92,19 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
foreach (var func in node.Functions)
|
foreach (var func in node.Functions)
|
||||||
{
|
{
|
||||||
var parameters = new List<FuncParameterNode>();
|
var scope = new Scope();
|
||||||
|
|
||||||
|
scope.Declare(new Variable("this", GetStructType(node)));
|
||||||
foreach (var parameter in func.Signature.Parameters)
|
foreach (var parameter in func.Signature.Parameters)
|
||||||
{
|
{
|
||||||
parameters.Add(new FuncParameterNode(parameter.Name, CheckType(parameter.Type)));
|
scope.Declare(new Variable(parameter.Name, CheckType(parameter.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
funcs.Add(new StructFuncNode(func.Name, CheckFuncSignature(func.Signature), CheckFuncBody(func.Body, CheckType(func.Signature.ReturnType), parameters)));
|
_funcReturnTypes.Push(CheckType(func.Signature.ReturnType));
|
||||||
|
var body = CheckBlock(func.Body, scope);
|
||||||
|
_funcReturnTypes.Pop();
|
||||||
|
|
||||||
|
funcs.Add(new StructFuncNode(func.Name, CheckFuncSignature(func.Signature), body));
|
||||||
}
|
}
|
||||||
|
|
||||||
var interfaceImplementations = new List<InterfaceTypeNode>();
|
var interfaceImplementations = new List<InterfaceTypeNode>();
|
||||||
@@ -128,7 +135,7 @@ public sealed class TypeChecker
|
|||||||
interfaceImplementations.Add(interfaceType);
|
interfaceImplementations.Add(interfaceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StructNode(node.Name, structFields, funcs, interfaceImplementations);
|
return new StructNode(node.Name, GetStructType(node), structFields, funcs, interfaceImplementations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExternFuncNode CheckExternFuncDefinition(ExternFuncSyntax node)
|
private ExternFuncNode CheckExternFuncDefinition(ExternFuncSyntax node)
|
||||||
@@ -139,7 +146,16 @@ public sealed class TypeChecker
|
|||||||
private LocalFuncNode CheckLocalFuncDefinition(LocalFuncSyntax node)
|
private LocalFuncNode CheckLocalFuncDefinition(LocalFuncSyntax node)
|
||||||
{
|
{
|
||||||
var signature = CheckFuncSignature(node.Signature);
|
var signature = CheckFuncSignature(node.Signature);
|
||||||
var body = CheckFuncBody(node.Body, signature.ReturnType, signature.Parameters);
|
|
||||||
|
var scope = new Scope();
|
||||||
|
foreach (var parameter in signature.Parameters)
|
||||||
|
{
|
||||||
|
scope.Declare(new Variable(parameter.Name, parameter.Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
_funcReturnTypes.Push(signature.ReturnType);
|
||||||
|
var body = CheckBlock(node.Body, scope);
|
||||||
|
_funcReturnTypes.Pop();
|
||||||
|
|
||||||
return new LocalFuncNode(node.Name, signature, body);
|
return new LocalFuncNode(node.Name, signature, body);
|
||||||
}
|
}
|
||||||
@@ -320,11 +336,14 @@ public sealed class TypeChecker
|
|||||||
return new DereferenceNode(dereferencedType, boundExpression);
|
return new DereferenceNode(dereferencedType, boundExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncCallNode CheckFuncCall(FuncCallSyntax expression)
|
private ExpressionNode CheckFuncCall(FuncCallSyntax expression)
|
||||||
{
|
{
|
||||||
var boundExpression = CheckExpression(expression.Expression);
|
var boundExpression = CheckExpression(expression.Expression);
|
||||||
|
|
||||||
var funcType = (FuncTypeNode)boundExpression.Type;
|
if (boundExpression.Type is not FuncTypeNode funcType)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic.Error($"Cannot call non-function type {boundExpression.Type}").Build());
|
||||||
|
}
|
||||||
|
|
||||||
var parameters = new List<ExpressionNode>();
|
var parameters = new List<ExpressionNode>();
|
||||||
|
|
||||||
@@ -332,7 +351,7 @@ public sealed class TypeChecker
|
|||||||
{
|
{
|
||||||
if (i >= funcType.Parameters.Count)
|
if (i >= funcType.Parameters.Count)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Diagnostics not implemented");
|
_diagnostics.Add(Diagnostic.Error($"Expected {funcType.Parameters.Count} parameters").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedType = funcType.Parameters[i];
|
var expectedType = funcType.Parameters[i];
|
||||||
@@ -340,6 +359,16 @@ public sealed class TypeChecker
|
|||||||
parameters.Add(CheckExpression(parameter, expectedType));
|
parameters.Add(CheckExpression(parameter, expectedType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (boundExpression is StructFuncAccessNode structFuncAccess)
|
||||||
|
{
|
||||||
|
return new StructFuncCallNode(funcType.ReturnType, structFuncAccess, structFuncAccess.Target, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boundExpression is InterfaceFuncAccessNode interfaceFuncAccess)
|
||||||
|
{
|
||||||
|
return new InterfaceFuncCallNode(funcType.ReturnType, interfaceFuncAccess, interfaceFuncAccess.Target, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
return new FuncCallNode(funcType.ReturnType, boundExpression, parameters);
|
return new FuncCallNode(funcType.ReturnType, boundExpression, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,21 +645,6 @@ public sealed class TypeChecker
|
|||||||
return new BlockNode(statements);
|
return new BlockNode(statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockNode CheckFuncBody(BlockSyntax block, TypeNode returnType, IReadOnlyList<FuncParameterNode> parameters)
|
|
||||||
{
|
|
||||||
_funcReturnTypes.Push(returnType);
|
|
||||||
|
|
||||||
var scope = new Scope();
|
|
||||||
foreach (var parameter in parameters)
|
|
||||||
{
|
|
||||||
scope.Declare(new Variable(parameter.Name, parameter.Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
var body = CheckBlock(block, scope);
|
|
||||||
_funcReturnTypes.Pop();
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TypeNode CheckType(TypeSyntax node)
|
private TypeNode CheckType(TypeSyntax node)
|
||||||
{
|
{
|
||||||
return node switch
|
return node switch
|
||||||
@@ -649,15 +663,8 @@ public sealed class TypeChecker
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, TypeNode> _typeCache = new();
|
|
||||||
|
|
||||||
private TypeNode CheckCustomType(CustomTypeSyntax type)
|
private TypeNode CheckCustomType(CustomTypeSyntax type)
|
||||||
{
|
{
|
||||||
if (_typeCache.TryGetValue(type.Name, out var cachedType))
|
|
||||||
{
|
|
||||||
return cachedType;
|
|
||||||
}
|
|
||||||
|
|
||||||
var structs = _definitionTable.LookupStruct(type.Name).ToArray();
|
var structs = _definitionTable.LookupStruct(type.Name).ToArray();
|
||||||
if (structs.Length > 0)
|
if (structs.Length > 0)
|
||||||
{
|
{
|
||||||
@@ -666,25 +673,47 @@ public sealed class TypeChecker
|
|||||||
throw new TypeCheckerException(Diagnostic.Error($"Struct {type.Name} has multiple definitions").Build());
|
throw new TypeCheckerException(Diagnostic.Error($"Struct {type.Name} has multiple definitions").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
var @struct = structs[0];
|
return GetStructType(structs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
var result = new StructTypeNode(type.Name, [], [], []);
|
var interfaces = _definitionTable.LookupInterface(type.Name).ToArray();
|
||||||
_typeCache.Add(type.Name, result);
|
if (interfaces.Length > 0)
|
||||||
|
{
|
||||||
|
if (interfaces.Length > 1)
|
||||||
|
{
|
||||||
|
throw new TypeCheckerException(Diagnostic.Error($"Interface {type.Name} has multiple definitions").Build());
|
||||||
|
}
|
||||||
|
|
||||||
var fields = @struct.Fields.Select(x => CheckType(x.Type)).ToList();
|
return GetInterfaceType(interfaces[0]);
|
||||||
|
}
|
||||||
|
|
||||||
var funcs = @struct.Functions
|
throw new TypeCheckerException(Diagnostic.Error($"Type {type.Name} is not defined").Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StructTypeNode GetStructType(StructSyntax structDef)
|
||||||
|
{
|
||||||
|
if (_typeCache.TryGetValue(structDef.Name, out var cachedType))
|
||||||
|
{
|
||||||
|
return (StructTypeNode)cachedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new StructTypeNode(structDef.Name, [], [], []);
|
||||||
|
_typeCache.Add(structDef.Name, result);
|
||||||
|
|
||||||
|
var fields = structDef.Fields.Select(x => CheckType(x.Type)).ToList();
|
||||||
|
|
||||||
|
var funcs = structDef.Functions
|
||||||
.Select(x => new FuncTypeNode(x.Signature.Parameters.Select(p => CheckType(p.Type)).ToList(), CheckType(x.Signature.ReturnType)))
|
.Select(x => new FuncTypeNode(x.Signature.Parameters.Select(p => CheckType(p.Type)).ToList(), CheckType(x.Signature.ReturnType)))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var interfaceImplementations = new List<InterfaceTypeNode>();
|
var interfaceImplementations = new List<InterfaceTypeNode>();
|
||||||
|
|
||||||
foreach (var structInterfaceImplementation in @struct.InterfaceImplementations)
|
foreach (var structInterfaceImplementation in structDef.InterfaceImplementations)
|
||||||
{
|
{
|
||||||
var checkedInterfaceType = CheckType(structInterfaceImplementation);
|
var checkedInterfaceType = CheckType(structInterfaceImplementation);
|
||||||
if (checkedInterfaceType is not InterfaceTypeNode interfaceType)
|
if (checkedInterfaceType is not InterfaceTypeNode interfaceType)
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic.Error($"{type.Name} cannot implement non-interface type {checkedInterfaceType}").Build());
|
throw new TypeCheckerException(Diagnostic.Error($"{structDef.Name} cannot implement non-interface type {checkedInterfaceType}").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
interfaceImplementations.Add(interfaceType);
|
interfaceImplementations.Add(interfaceType);
|
||||||
@@ -696,29 +725,23 @@ public sealed class TypeChecker
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
var interfaces = _definitionTable.LookupInterface(type.Name).ToArray();
|
private InterfaceTypeNode GetInterfaceType(InterfaceSyntax interfaceDef)
|
||||||
if (interfaces.Length > 0)
|
|
||||||
{
|
{
|
||||||
if (interfaces.Length > 1)
|
if (_typeCache.TryGetValue(interfaceDef.Name, out var cachedType))
|
||||||
{
|
{
|
||||||
throw new TypeCheckerException(Diagnostic.Error($"Interface {type.Name} has multiple definitions").Build());
|
return (InterfaceTypeNode)cachedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
var @interface = interfaces[0];
|
var result = new InterfaceTypeNode(interfaceDef.Name, []);
|
||||||
|
_typeCache.Add(interfaceDef.Name, result);
|
||||||
|
|
||||||
var result = new InterfaceTypeNode(type.Name, []);
|
var functions = interfaceDef.Functions
|
||||||
_typeCache.Add(type.Name, result);
|
|
||||||
|
|
||||||
var functions = @interface.Functions
|
|
||||||
.Select(x => new FuncTypeNode(x.Signature.Parameters.Select(y => CheckType(y.Type)).ToList(), CheckType(x.Signature.ReturnType)))
|
.Select(x => new FuncTypeNode(x.Signature.Parameters.Select(y => CheckType(y.Type)).ToList(), CheckType(x.Signature.ReturnType)))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
result.Functions = functions;
|
result.Functions = functions;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new TypeCheckerException(Diagnostic.Error($"Type {type.Name} is not defined").Build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Variable(string Name, TypeNode Type);
|
public record Variable(string Name, TypeNode Type);
|
||||||
|
|||||||
Reference in New Issue
Block a user