...
This commit is contained in:
@@ -127,7 +127,7 @@ public static class QBEGenerator
|
|||||||
return $"${funcDef.CallName}";
|
return $"${funcDef.CallName}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ImplFuncName(BoundTraitImplNode implDef, string funcName)
|
private static string ImplFuncName()
|
||||||
{
|
{
|
||||||
return $"$impl{++_implFuncNameIndex}";
|
return $"$impl{++_implFuncNameIndex}";
|
||||||
}
|
}
|
||||||
@@ -405,22 +405,12 @@ public static class QBEGenerator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case NubCustomType customType:
|
case NubStructType structType:
|
||||||
{
|
{
|
||||||
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
|
var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
|
||||||
if (structDef.HasValue)
|
return structDef.Fields.Max(f => AlignmentOf(f.Type));
|
||||||
{
|
|
||||||
return structDef.Value.Fields.Max(f => AlignmentOf(f.Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
var traitDef = _definitionTable.LookupTrait(customType.Namespace, customType.Name);
|
|
||||||
if (traitDef.HasValue)
|
|
||||||
{
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnreachableException();
|
|
||||||
}
|
}
|
||||||
|
case NubTraitType:
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
case NubArrayType:
|
case NubArrayType:
|
||||||
case NubCStringType:
|
case NubCStringType:
|
||||||
@@ -452,15 +442,13 @@ public static class QBEGenerator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case NubCustomType customType:
|
case NubStructType structType:
|
||||||
{
|
|
||||||
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
|
|
||||||
if (structDef.HasValue)
|
|
||||||
{
|
{
|
||||||
|
var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
|
||||||
var size = 0;
|
var size = 0;
|
||||||
var maxAlignment = 1;
|
var maxAlignment = 1;
|
||||||
|
|
||||||
foreach (var field in structDef.Value.Fields)
|
foreach (var field in structDef.Fields)
|
||||||
{
|
{
|
||||||
var fieldAlignment = AlignmentOf(field.Type);
|
var fieldAlignment = AlignmentOf(field.Type);
|
||||||
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
||||||
@@ -473,15 +461,8 @@ public static class QBEGenerator
|
|||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
case NubTraitType:
|
||||||
var traitDef = _definitionTable.LookupTrait(customType.Namespace, customType.Name);
|
|
||||||
if (traitDef.HasValue)
|
|
||||||
{
|
|
||||||
return 16;
|
return 16;
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnreachableException();
|
|
||||||
}
|
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
case NubArrayType:
|
case NubArrayType:
|
||||||
case NubCStringType:
|
case NubCStringType:
|
||||||
@@ -800,18 +781,22 @@ public static class QBEGenerator
|
|||||||
_writer.WriteDebugLocation(expression);
|
_writer.WriteDebugLocation(expression);
|
||||||
return expression switch
|
return expression switch
|
||||||
{
|
{
|
||||||
BoundAddressOfNode addressOf => EmitAddressOf(addressOf),
|
|
||||||
BoundAnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc),
|
|
||||||
BoundArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
|
||||||
BoundArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
BoundArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||||
BoundBinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
|
||||||
BoundDereferenceNode dereference => EmitDereference(dereference),
|
|
||||||
BoundFuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
|
||||||
BoundIdentifierNode identifier => EmitIdentifier(identifier),
|
|
||||||
BoundLiteralNode literal => EmitLiteral(literal),
|
|
||||||
BoundStructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
|
BoundStructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
|
||||||
|
BoundAddressOfNode addressOf => EmitAddressOf(addressOf),
|
||||||
|
BoundDereferenceNode dereference => EmitDereference(dereference),
|
||||||
|
BoundAnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc),
|
||||||
|
BoundBinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
||||||
|
BoundFuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
||||||
|
BoundExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
|
||||||
|
BoundLocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
|
||||||
|
BoundVariableIdentNode variableIdent => EmitVariableIdent(variableIdent),
|
||||||
|
BoundLiteralNode literal => EmitLiteral(literal),
|
||||||
BoundUnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
BoundUnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
||||||
BoundMemberAccessNode memberAccess => EmitMemberAccess(memberAccess),
|
BoundStructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
||||||
|
BoundTraitFuncAccessNode traitFuncAccess => EmitTraitFuncAccess(traitFuncAccess),
|
||||||
|
BoundTraitImplFuncAccessNode traitImplFuncAccess => EmitTraitImplFuncAccess(traitImplFuncAccess),
|
||||||
|
BoundArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1011,19 +996,21 @@ public static class QBEGenerator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitIdentifier(BoundIdentifierNode identifier)
|
private static Val EmitExternFuncIdent(BoundExternFuncIdentNode externFuncIdent)
|
||||||
{
|
{
|
||||||
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_syntaxTree.Namespace), identifier.Name).TryGetValue(out var func))
|
var func = _definitionTable.LookupExternFunc(externFuncIdent.Namespace, externFuncIdent.Name);
|
||||||
{
|
return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct);
|
||||||
return new Val(FuncName(func), identifier.Type, ValKind.Direct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!identifier.Namespace.HasValue)
|
private static Val EmitLocalFuncIdent(BoundLocalFuncIdentNode localFuncIdent)
|
||||||
{
|
{
|
||||||
return _variables.Single(v => v.Name == identifier.Name).Val;
|
var func = _definitionTable.LookupExternFunc(localFuncIdent.Namespace, localFuncIdent.Name);
|
||||||
|
return new Val(ExternFuncName(func), localFuncIdent.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnreachableException();
|
private static Val EmitVariableIdent(BoundVariableIdentNode variableIdent)
|
||||||
|
{
|
||||||
|
return _variables.Single(v => v.Name == variableIdent.Name).Val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitLiteral(BoundLiteralNode literal)
|
private static Val EmitLiteral(BoundLiteralNode literal)
|
||||||
@@ -1115,7 +1102,7 @@ public static class QBEGenerator
|
|||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var structDefinition = _definitionTable.LookupStruct(structType.Namespace, structType.Name).GetValue();
|
var @struct = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
|
||||||
|
|
||||||
if (destination == null)
|
if (destination == null)
|
||||||
{
|
{
|
||||||
@@ -1124,7 +1111,7 @@ public static class QBEGenerator
|
|||||||
_writer.Indented($"{destination} =l alloc8 {size}");
|
_writer.Indented($"{destination} =l alloc8 {size}");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var field in structDefinition.Fields)
|
foreach (var field in @struct.Fields)
|
||||||
{
|
{
|
||||||
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
|
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
|
||||||
{
|
{
|
||||||
@@ -1134,7 +1121,7 @@ public static class QBEGenerator
|
|||||||
Debug.Assert(valueExpression != null);
|
Debug.Assert(valueExpression != null);
|
||||||
|
|
||||||
var offset = TmpName();
|
var offset = TmpName();
|
||||||
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDefinition, field.Name)}");
|
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(@struct, field.Name)}");
|
||||||
EmitCopyIntoOrInitialize(valueExpression, offset);
|
EmitCopyIntoOrInitialize(valueExpression, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1188,70 +1175,40 @@ public static 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 static Val EmitMemberAccess(BoundMemberAccessNode memberAccess)
|
private static Val EmitStructFieldAccess(BoundStructFieldAccessNode structFieldAccess)
|
||||||
{
|
{
|
||||||
var item = EmitUnwrap(EmitExpression(memberAccess.Expression));
|
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
|
||||||
|
|
||||||
var implementation = _definitionTable.LookupTraitImplementationForType(memberAccess.Expression.Type, memberAccess.Member);
|
var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Namespace, structFieldAccess.StructType.Name);
|
||||||
if (implementation.HasValue)
|
var offset = OffsetOf(structDef, structFieldAccess.Field);
|
||||||
{
|
|
||||||
var name = ImplFuncName(implementation.Value.Item1, memberAccess.Member);
|
|
||||||
_implFunctions.TryAdd(implementation.Value.Item2, name);
|
|
||||||
return new Val(name, memberAccess.Type, ValKind.Direct, new MethodCallContext(item, memberAccess.Expression.Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
var output = TmpName();
|
var output = TmpName();
|
||||||
|
_writer.Indented($"{output} =l add {target}, {offset}");
|
||||||
|
|
||||||
if (memberAccess.Expression.Type is NubCustomType customType)
|
|
||||||
{
|
|
||||||
var function = _definitionTable.LookupFunctionOnTrait(customType.Namespace, customType.Name, memberAccess.Member);
|
|
||||||
if (function.HasValue)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("VTable lookup is not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
|
|
||||||
if (structDef.HasValue)
|
|
||||||
{
|
|
||||||
var offset = OffsetOf(structDef.Value, memberAccess.Member);
|
|
||||||
_writer.Indented($"{output} =l add {item}, {offset}");
|
|
||||||
|
|
||||||
if (memberAccess.Type is NubCustomType inner)
|
|
||||||
{
|
|
||||||
// If the accessed member is an inline struct, it will not be a pointer
|
// If the accessed member is an inline struct, it will not be a pointer
|
||||||
if (_definitionTable.LookupStruct(inner.Namespace, inner.Name).HasValue)
|
if (structFieldAccess.Type is NubStructType)
|
||||||
{
|
{
|
||||||
return new Val(output, memberAccess.Type, ValKind.Direct);
|
return new Val(output, structFieldAccess.Type, ValKind.Direct);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Val(output, memberAccess.Type, ValKind.Pointer);
|
return new Val(output, structFieldAccess.Type, ValKind.Pointer);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memberAccess.Member == "count")
|
private static Val EmitTraitFuncAccess(BoundTraitFuncAccessNode traitFuncAccess)
|
||||||
{
|
{
|
||||||
switch (memberAccess.Expression.Type)
|
throw new NotImplementedException();
|
||||||
{
|
|
||||||
case NubArrayType:
|
|
||||||
{
|
|
||||||
_writer.Indented($"{output} =l loadl {item}");
|
|
||||||
return new Val(output, memberAccess.Type, ValKind.Direct);
|
|
||||||
}
|
|
||||||
case NubStringType:
|
|
||||||
{
|
|
||||||
_writer.Indented($"{output} =l call $nub_string_length(l {item})");
|
|
||||||
return new Val(output, memberAccess.Type, ValKind.Direct);
|
|
||||||
}
|
|
||||||
case NubCStringType:
|
|
||||||
{
|
|
||||||
_writer.Indented($"{output} =l call $nub_cstring_length(l {item})");
|
|
||||||
return new Val(output, memberAccess.Type, ValKind.Direct);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnreachableException();
|
private static Val EmitTraitImplFuncAccess(BoundTraitImplFuncAccessNode traitImplFuncAccess)
|
||||||
|
{
|
||||||
|
var target = EmitExpression(traitImplFuncAccess.Target);
|
||||||
|
|
||||||
|
var impl = _definitionTable.LookupTraitImpl(traitImplFuncAccess.Target.Type);
|
||||||
|
var funcImpl = _definitionTable.LookupTraitFuncImpl(impl, traitImplFuncAccess.FuncName);
|
||||||
|
|
||||||
|
var name = ImplFuncName();
|
||||||
|
_implFunctions.TryAdd(funcImpl, name);
|
||||||
|
return new Val(name, traitImplFuncAccess.Type, ValKind.Direct, new MethodCallContext(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitFuncCall(BoundFuncCallNode funcCall)
|
private static Val EmitFuncCall(BoundFuncCallNode funcCall)
|
||||||
@@ -1263,7 +1220,8 @@ public static class QBEGenerator
|
|||||||
|
|
||||||
if (expression.FuncCallContext != null)
|
if (expression.FuncCallContext != null)
|
||||||
{
|
{
|
||||||
parameterStrings.Add($"{FuncQBETypeName(expression.FuncCallContext.ThisArgType)} {expression.FuncCallContext.ThisArgName}");
|
var thisArg = EmitUnwrap(expression.FuncCallContext.ThisArg);
|
||||||
|
parameterStrings.Add($"{FuncQBETypeName(expression.FuncCallContext.ThisArg.Type)} {thisArg}");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var parameter in funcCall.Parameters)
|
foreach (var parameter in funcCall.Parameters)
|
||||||
@@ -1316,7 +1274,7 @@ internal class Variable(string name, Val val)
|
|||||||
|
|
||||||
internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
|
internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
|
||||||
|
|
||||||
internal record MethodCallContext(string ThisArgName, NubType ThisArgType);
|
internal record MethodCallContext(Val ThisArg);
|
||||||
|
|
||||||
internal enum ValKind
|
internal enum ValKind
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using Common;
|
using Common;
|
||||||
using Syntax.Diagnostics;
|
using Syntax.Diagnostics;
|
||||||
using Syntax.Node;
|
using Syntax.Node;
|
||||||
@@ -49,11 +50,11 @@ public sealed class Binder
|
|||||||
{
|
{
|
||||||
return node switch
|
return node switch
|
||||||
{
|
{
|
||||||
ExternFuncNode definition => BindExternFuncDefinition(definition),
|
ExternFuncNode topLevel => BindExternFuncDefinition(topLevel),
|
||||||
TraitImplNode definition => BindTraitImplementation(definition),
|
TraitImplNode topLevel => BindTraitImplementation(topLevel),
|
||||||
TraitNode definition => BindTraitDefinition(definition),
|
TraitNode topLevel => BindTraitDefinition(topLevel),
|
||||||
LocalFuncNode definition => BindLocalFuncDefinition(definition),
|
LocalFuncNode topLevel => BindLocalFuncDefinition(topLevel),
|
||||||
StructNode definition => BindStruct(definition),
|
StructNode topLevel => BindStruct(topLevel),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ public sealed class Binder
|
|||||||
_variables[parameter.Name] = parameter.Type;
|
_variables[parameter.Name] = parameter.Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, function.Parameters, function.ReturnType, BindBlock(function.Body)));
|
functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, function.Parameters, BindType(function.ReturnType), BindBlock(function.Body)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions);
|
return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions);
|
||||||
@@ -82,7 +83,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
foreach (var func in node.Functions)
|
foreach (var func in node.Functions)
|
||||||
{
|
{
|
||||||
functions.Add(new BoundTraitFuncNode(node.Tokens, func.Name, func.Parameters, func.ReturnType));
|
functions.Add(new BoundTraitFuncNode(node.Tokens, func.Name, func.Parameters, BindType(func.ReturnType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions);
|
return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions);
|
||||||
@@ -109,13 +110,13 @@ public sealed class Binder
|
|||||||
|
|
||||||
private BoundExternFuncNode BindExternFuncDefinition(ExternFuncNode node)
|
private BoundExternFuncNode BindExternFuncDefinition(ExternFuncNode node)
|
||||||
{
|
{
|
||||||
return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, node.Parameters, node.ReturnType);
|
return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, node.Parameters, BindType(node.ReturnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node)
|
private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node)
|
||||||
{
|
{
|
||||||
_variables.Clear();
|
_variables.Clear();
|
||||||
_functionReturnType = node.ReturnType;
|
_functionReturnType = BindType(node.ReturnType);
|
||||||
|
|
||||||
foreach (var parameter in node.Parameters)
|
foreach (var parameter in node.Parameters)
|
||||||
{
|
{
|
||||||
@@ -124,7 +125,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var body = BindBlock(node.Body);
|
var body = BindBlock(node.Body);
|
||||||
|
|
||||||
return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, node.ReturnType, node.Exported);
|
return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, BindType(node.ReturnType), node.Exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundBlock BindBlock(BlockNode node)
|
private BoundBlock BindBlock(BlockNode node)
|
||||||
@@ -269,7 +270,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var body = BindBlock(expression.Body);
|
var body = BindBlock(expression.Body);
|
||||||
|
|
||||||
return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(expression.ReturnType, parameterTypes), expression.Parameters, body, expression.ReturnType);
|
return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(BindType(expression.ReturnType), parameterTypes), expression.Parameters, body, BindType(expression.ReturnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression)
|
private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression)
|
||||||
@@ -303,7 +304,7 @@ public sealed class Binder
|
|||||||
var boundExpression = BindExpression(expression.Expression);
|
var boundExpression = BindExpression(expression.Expression);
|
||||||
|
|
||||||
var funcType = (NubFuncType)boundExpression.Type;
|
var funcType = (NubFuncType)boundExpression.Type;
|
||||||
var returnType = ((NubFuncType)boundExpression.Type).ReturnType;
|
var returnType = BindType(funcType.ReturnType);
|
||||||
|
|
||||||
var parameters = new List<BoundExpressionNode>();
|
var parameters = new List<BoundExpressionNode>();
|
||||||
|
|
||||||
@@ -322,9 +323,10 @@ public sealed class Binder
|
|||||||
return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters);
|
return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundIdentifierNode BindIdentifier(IdentifierNode expression)
|
private BoundExpressionNode BindIdentifier(IdentifierNode expression)
|
||||||
{
|
{
|
||||||
var localFuncs = _definitionTable.LookupLocalFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray();
|
var @namespace = expression.Namespace.Or(_syntaxTree.Namespace);
|
||||||
|
var localFuncs = _definitionTable.LookupLocalFunc(@namespace, expression.Name).ToArray();
|
||||||
if (localFuncs.Length > 0)
|
if (localFuncs.Length > 0)
|
||||||
{
|
{
|
||||||
if (localFuncs.Length > 1)
|
if (localFuncs.Length > 1)
|
||||||
@@ -334,11 +336,11 @@ public sealed class Binder
|
|||||||
|
|
||||||
var localFunc = localFuncs[0];
|
var localFunc = localFuncs[0];
|
||||||
|
|
||||||
var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList());
|
var type = new NubFuncType(BindType(localFunc.ReturnType), localFunc.Parameters.Select(p => p.Type).ToList());
|
||||||
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name);
|
return new BoundLocalFuncIdentNode(expression.Tokens, type, @namespace, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
var externFuncs = _definitionTable.LookupExternFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray();
|
var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray();
|
||||||
if (externFuncs.Length > 0)
|
if (externFuncs.Length > 0)
|
||||||
{
|
{
|
||||||
if (externFuncs.Length > 1)
|
if (externFuncs.Length > 1)
|
||||||
@@ -348,13 +350,13 @@ public sealed class Binder
|
|||||||
|
|
||||||
var externFunc = externFuncs[0];
|
var externFunc = externFuncs[0];
|
||||||
|
|
||||||
var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList());
|
var type = new NubFuncType(BindType(externFunc.ReturnType), externFunc.Parameters.Select(p => p.Type).ToList());
|
||||||
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name);
|
return new BoundExternFuncIdentNode(expression.Tokens, type, @namespace, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expression.Namespace.HasValue)
|
if (!expression.Namespace.HasValue)
|
||||||
{
|
{
|
||||||
return new BoundIdentifierNode(expression.Tokens, _variables[expression.Name], expression.Namespace, expression.Name);
|
return new BoundVariableIdentNode(expression.Tokens, _variables[expression.Name], expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build());
|
throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build());
|
||||||
@@ -374,9 +376,9 @@ public sealed class Binder
|
|||||||
return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind);
|
return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundMemberAccessNode BindMemberAccess(MemberAccessNode expression)
|
private BoundExpressionNode BindMemberAccess(MemberAccessNode expression)
|
||||||
{
|
{
|
||||||
var boundExpression = BindExpression(expression.Expression);
|
var boundExpression = BindExpression(expression.Target);
|
||||||
|
|
||||||
var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray();
|
var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray();
|
||||||
|
|
||||||
@@ -389,8 +391,8 @@ public sealed class Binder
|
|||||||
|
|
||||||
var impl = traitFuncImpls[0];
|
var impl = traitFuncImpls[0];
|
||||||
|
|
||||||
var type = new NubFuncType(impl.ReturnType, impl.Parameters.Select(p => p.Type).ToList());
|
var type = new NubFuncType(BindType(impl.ReturnType), impl.Parameters.Select(p => BindType(p.Type)).ToList());
|
||||||
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member);
|
return new BoundTraitImplFuncAccessNode(expression.Tokens, type, boundExpression, expression.Member);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boundExpression.Type is NubCustomType customType)
|
if (boundExpression.Type is NubCustomType customType)
|
||||||
@@ -415,8 +417,8 @@ public sealed class Binder
|
|||||||
|
|
||||||
var traitFunc = traitFuncs[0];
|
var traitFunc = traitFuncs[0];
|
||||||
|
|
||||||
var type = new NubFuncType(traitFunc.ReturnType, traitFunc.Parameters.Select(p => p.Type).ToList());
|
var type = new NubFuncType(BindType(traitFunc.ReturnType), traitFunc.Parameters.Select(p => BindType(p.Type)).ToList());
|
||||||
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member);
|
return new BoundTraitFuncAccessNode(expression.Tokens, type, new NubTraitType(trait.Namespace, trait.Name), boundExpression, expression.Member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,16 +442,11 @@ public sealed class Binder
|
|||||||
|
|
||||||
var field = fields[0];
|
var field = fields[0];
|
||||||
|
|
||||||
return new BoundMemberAccessNode(expression.Tokens, field.Type, boundExpression, expression.Member);
|
return new BoundStructFieldAccessNode(expression.Tokens, field.Type, new NubStructType(@struct.Namespace, @struct.Name), boundExpression, expression.Member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boundExpression.Type is NubStringType or NubCStringType or NubArrayType && expression.Member == "count")
|
|
||||||
{
|
|
||||||
return new BoundMemberAccessNode(expression.Tokens, NubPrimitiveType.U64, boundExpression, expression.Member);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new BindException(Diagnostic.Error($"{boundExpression.Type} has not member with the name {expression.Member}").Build());
|
throw new BindException(Diagnostic.Error($"{boundExpression.Type} has not member with the name {expression.Member}").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,6 +528,48 @@ public sealed class Binder
|
|||||||
|
|
||||||
return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand);
|
return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NubType BindType(NubType type)
|
||||||
|
{
|
||||||
|
if (type is NubCustomType customType)
|
||||||
|
{
|
||||||
|
var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray();
|
||||||
|
if (structs.Length > 1)
|
||||||
|
{
|
||||||
|
throw new BindException(Diagnostic.Error($"Struct {type} has multiple definitions").Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray();
|
||||||
|
if (traits.Length > 1)
|
||||||
|
{
|
||||||
|
throw new BindException(Diagnostic.Error($"Trait {type} has multiple definitions").Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (structs.Length == 0 && traits.Length == 0)
|
||||||
|
{
|
||||||
|
throw new BindException(Diagnostic.Error($"Failed to resolve type {type} to a struct or trait").Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (structs.Length > 0 && traits.Length > 0)
|
||||||
|
{
|
||||||
|
throw new BindException(Diagnostic.Error($"Unable to determine if type {type} is a struct or trait").WithHelp($"Make {type} is not defined as bot a struct and trait").Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (structs.Length == 1)
|
||||||
|
{
|
||||||
|
return new NubStructType(customType.Namespace, customType.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traits.Length == 1)
|
||||||
|
{
|
||||||
|
return new NubTraitType(customType.Namespace, customType.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnreachableException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BindException : Exception
|
public class BindException : Exception
|
||||||
|
|||||||
@@ -61,3 +61,63 @@ public sealed class DefinitionTable
|
|||||||
return trait.Functions.Where(x => x.Name == name);
|
return trait.Functions.Where(x => x.Name == name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class BoundDefinitionTable
|
||||||
|
{
|
||||||
|
private readonly List<BoundTopLevelNode> _topLevelNodes;
|
||||||
|
|
||||||
|
public BoundDefinitionTable(IEnumerable<BoundSyntaxTree> syntaxTrees)
|
||||||
|
{
|
||||||
|
_topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundLocalFuncNode LookupLocalFunc(string @namespace, string name)
|
||||||
|
{
|
||||||
|
return _topLevelNodes
|
||||||
|
.OfType<BoundLocalFuncNode>()
|
||||||
|
.First(x => x.Namespace == @namespace && x.Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundExternFuncNode LookupExternFunc(string @namespace, string name)
|
||||||
|
{
|
||||||
|
return _topLevelNodes
|
||||||
|
.OfType<BoundExternFuncNode>()
|
||||||
|
.First(x => x.Namespace == @namespace && x.Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundStructNode LookupStruct(string @namespace, string name)
|
||||||
|
{
|
||||||
|
return _topLevelNodes
|
||||||
|
.OfType<BoundStructNode>()
|
||||||
|
.First(x => x.Namespace == @namespace && x.Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundStructFieldNode LookupStructField(BoundStructNode structNode, string field)
|
||||||
|
{
|
||||||
|
return structNode.Fields.First(x => x.Name == field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundTraitImplNode LookupTraitImpl(NubType itemType)
|
||||||
|
{
|
||||||
|
return _topLevelNodes
|
||||||
|
.OfType<BoundTraitImplNode>()
|
||||||
|
.First(x => x.TraitType == itemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundTraitFuncImplNode LookupTraitFuncImpl(BoundTraitImplNode traitImpl, string name)
|
||||||
|
{
|
||||||
|
return traitImpl.Functions.First(x => x.Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundTraitNode LookupTrait(string @namespace, string name)
|
||||||
|
{
|
||||||
|
return _topLevelNodes
|
||||||
|
.OfType<BoundTraitNode>()
|
||||||
|
.First(x => x.Namespace == @namespace && x.Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundTraitFuncNode LookupTraitFunc(BoundTraitNode trait, string name)
|
||||||
|
{
|
||||||
|
return trait.Functions.First(x => x.Name == name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,9 @@ public record FuncCallNode(IEnumerable<Token> Tokens, ExpressionNode Expression,
|
|||||||
public record BoundFuncCallNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, List<BoundExpressionNode> Parameters) : BoundExpressionNode(Tokens, Type);
|
public record BoundFuncCallNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, List<BoundExpressionNode> Parameters) : BoundExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record IdentifierNode(IEnumerable<Token> Tokens, Optional<string> Namespace, string Name) : ExpressionNode(Tokens);
|
public record IdentifierNode(IEnumerable<Token> Tokens, Optional<string> Namespace, string Name) : ExpressionNode(Tokens);
|
||||||
public record BoundIdentifierNode(IEnumerable<Token> Tokens, NubType Type, Optional<string> Namespace, string Name) : BoundExpressionNode(Tokens, Type);
|
public record BoundVariableIdentNode(IEnumerable<Token> Tokens, NubType Type, string Name) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundLocalFuncIdentNode(IEnumerable<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundExternFuncIdentNode(IEnumerable<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record ArrayInitializerNode(IEnumerable<Token> Tokens, ExpressionNode Capacity, NubType ElementType) : ExpressionNode(Tokens);
|
public record ArrayInitializerNode(IEnumerable<Token> Tokens, ExpressionNode Capacity, NubType ElementType) : ExpressionNode(Tokens);
|
||||||
public record BoundArrayInitializerNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type);
|
public record BoundArrayInitializerNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type);
|
||||||
@@ -53,8 +55,10 @@ public record BoundAddressOfNode(IEnumerable<Token> Tokens, NubType Type, BoundE
|
|||||||
public record LiteralNode(IEnumerable<Token> Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens);
|
public record LiteralNode(IEnumerable<Token> Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens);
|
||||||
public record BoundLiteralNode(IEnumerable<Token> Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type);
|
public record BoundLiteralNode(IEnumerable<Token> Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Expression, string Member) : ExpressionNode(Tokens);
|
public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Target, string Member) : ExpressionNode(Tokens);
|
||||||
public record BoundMemberAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, string Member) : BoundExpressionNode(Tokens, Type);
|
public record BoundStructFieldAccessNode(IEnumerable<Token> Tokens, NubType Type, NubStructType StructType, BoundExpressionNode Target, string Field) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundTraitImplFuncAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundTraitFuncAccessNode(IEnumerable<Token> Tokens, NubType Type, NubTraitType TraitType, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type);
|
||||||
|
|
||||||
public record StructInitializerNode(IEnumerable<Token> Tokens, NubType StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(Tokens);
|
public record StructInitializerNode(IEnumerable<Token> Tokens, NubType StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(Tokens);
|
||||||
public record BoundStructInitializerNode(IEnumerable<Token> Tokens, NubType Type, NubType StructType, Dictionary<string, BoundExpressionNode> Initializers) : BoundExpressionNode(Tokens, Type);
|
public record BoundStructInitializerNode(IEnumerable<Token> Tokens, NubType Type, NubType StructType, Dictionary<string, BoundExpressionNode> Initializers) : BoundExpressionNode(Tokens, Type);
|
||||||
|
|||||||
@@ -86,6 +86,18 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
|
|||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name);
|
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class NubStructType(string @namespace, string name) : NubCustomType(@namespace, name)
|
||||||
|
{
|
||||||
|
public override bool Equals(NubType? other) => other is NubStructType custom && Namespace == custom.Namespace && Name == custom.Name;
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubStructType), Namespace, Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NubTraitType(string @namespace, string name) : NubCustomType(@namespace, name)
|
||||||
|
{
|
||||||
|
public override bool Equals(NubType? other) => other is NubTraitType custom && Namespace == custom.Namespace && Name == custom.Name;
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubTraitType), Namespace, Name);
|
||||||
|
}
|
||||||
|
|
||||||
public class NubPointerType(NubType baseType) : NubSimpleType
|
public class NubPointerType(NubType baseType) : NubSimpleType
|
||||||
{
|
{
|
||||||
public NubType BaseType { get; } = baseType;
|
public NubType BaseType { get; } = baseType;
|
||||||
|
|||||||
Reference in New Issue
Block a user