This commit is contained in:
nub31
2025-07-06 00:15:35 +02:00
parent 3d68dfe811
commit 0afb18e4a6
9 changed files with 480 additions and 235 deletions

View File

@@ -132,20 +132,25 @@ public static class QBEGenerator
return $"$impl{++_implFuncNameIndex}"; return $"$impl{++_implFuncNameIndex}";
} }
private static string CustomTypeName(NubCustomType customType) private static string StructTypeName(BoundNubStructType structType)
{ {
return $":{customType.Namespace}_{customType.Name}"; return $":{structType.Namespace}_{structType.Name}";
} }
private static void EmitStore(NubType type, string value, string destination) private static string TraitTypeName(BoundNubTraitType traitType)
{
return $":{traitType.Namespace}_{traitType.Name}";
}
private static void EmitStore(BoundNubType type, string value, string destination)
{ {
var store = type switch var store = type switch
{ {
NubComplexType => "storel", BoundNubComplexType => "storel",
NubSimpleType simpleType => simpleType switch BoundNubSimpleType simpleType => simpleType switch
{ {
NubFuncType or NubPointerType => "loadl", BoundNubFuncType or BoundNubPointerType => "loadl",
NubPrimitiveType primitiveType => primitiveType.Kind switch BoundNubPrimitiveType primitiveType => primitiveType.Kind switch
{ {
PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "storel", PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "storel",
PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "storew", PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "storew",
@@ -163,16 +168,16 @@ public static class QBEGenerator
_writer.Indented($"{store} {value}, {destination}"); _writer.Indented($"{store} {value}, {destination}");
} }
private static Val EmitLoad(NubType type, string from) private static Val EmitLoad(BoundNubType type, string from)
{ {
var into = TmpName(); var into = TmpName();
var load = type switch var load = type switch
{ {
NubComplexType => "loadl", BoundNubComplexType => "loadl",
NubSimpleType simpleType => simpleType switch BoundNubSimpleType simpleType => simpleType switch
{ {
NubFuncType or NubPointerType => "loadl", BoundNubFuncType or BoundNubPointerType => "loadl",
NubPrimitiveType primitiveType => primitiveType.Kind switch BoundNubPrimitiveType primitiveType => primitiveType.Kind switch
{ {
PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "loadl", PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "loadl",
PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "loadw", PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "loadw",
@@ -199,7 +204,7 @@ public static class QBEGenerator
_writer.Indented($"call $nub_memcpy(l {source}, l {destination}, l {length})"); _writer.Indented($"call $nub_memcpy(l {source}, l {destination}, l {length})");
} }
private static string EmitArraySizeInBytes(NubArrayType type, string array) private static string EmitArraySizeInBytes(BoundNubArrayType type, string array)
{ {
var size = TmpName(); var size = TmpName();
_writer.Indented($"{size} =l loadl {array}"); _writer.Indented($"{size} =l loadl {array}");
@@ -263,22 +268,23 @@ public static class QBEGenerator
switch (source.Type) switch (source.Type)
{ {
case NubComplexType complexType: case BoundNubComplexType complexType:
{ {
var size = complexType switch var size = complexType switch
{ {
NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value), BoundNubArrayType arrayType => EmitArraySizeInBytes(arrayType, value),
NubCStringType => EmitCStringSizeInBytes(value), BoundNubCStringType => EmitCStringSizeInBytes(value),
NubStringType => EmitStringSizeInBytes(value), BoundNubStringType => EmitStringSizeInBytes(value),
NubCustomType customType => SizeOf(customType).ToString(), BoundNubStructType structType => SizeOf(structType).ToString(),
BoundNubTraitType traitType => SizeOf(traitType).ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(complexType)) _ => throw new ArgumentOutOfRangeException(nameof(complexType))
}; };
switch (complexType) switch (complexType)
{ {
case NubArrayType: case BoundNubArrayType:
case NubCStringType: case BoundNubCStringType:
case NubStringType: case BoundNubStringType:
{ {
var buffer = TmpName(); var buffer = TmpName();
_writer.Indented($"{buffer} =l alloc8 {size}"); _writer.Indented($"{buffer} =l alloc8 {size}");
@@ -286,7 +292,8 @@ public static class QBEGenerator
EmitStore(source.Type, buffer, destinationPointer); EmitStore(source.Type, buffer, destinationPointer);
return; return;
} }
case NubCustomType: case BoundNubStructType:
case BoundNubTraitType:
{ {
EmitMemcpy(value, destinationPointer, size); EmitMemcpy(value, destinationPointer, size);
return; return;
@@ -297,7 +304,7 @@ public static class QBEGenerator
} }
} }
} }
case NubSimpleType simpleType: case BoundNubSimpleType simpleType:
{ {
EmitStore(simpleType, value, destinationPointer); EmitStore(simpleType, value, destinationPointer);
return; return;
@@ -338,16 +345,17 @@ public static class QBEGenerator
switch (source.Type) switch (source.Type)
{ {
case NubComplexType complexType: case BoundNubComplexType complexType:
{ {
var destination = TmpName(); var destination = TmpName();
var size = complexType switch var size = complexType switch
{ {
NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value), BoundNubArrayType arrayType => EmitArraySizeInBytes(arrayType, value),
NubCStringType => EmitCStringSizeInBytes(value), BoundNubCStringType => EmitCStringSizeInBytes(value),
NubStringType => EmitStringSizeInBytes(value), BoundNubStringType => EmitStringSizeInBytes(value),
NubCustomType customType => SizeOf(customType).ToString(), BoundNubStructType structType => SizeOf(structType).ToString(),
BoundNubTraitType traitType => SizeOf(traitType).ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(complexType)) _ => throw new ArgumentOutOfRangeException(nameof(complexType))
}; };
@@ -355,7 +363,7 @@ public static class QBEGenerator
EmitMemcpy(value, destination, size); EmitMemcpy(value, destination, size);
return destination; return destination;
} }
case NubSimpleType: case BoundNubSimpleType:
{ {
return value; return value;
} }
@@ -366,15 +374,15 @@ public static class QBEGenerator
} }
} }
private static string QBEAssign(NubType type) private static string QBEAssign(BoundNubType type)
{ {
return type switch return type switch
{ {
NubComplexType => "=l", BoundNubComplexType => "=l",
NubSimpleType simpleType => simpleType switch BoundNubSimpleType simpleType => simpleType switch
{ {
NubFuncType or NubFuncType => "=l", BoundNubFuncType or BoundNubFuncType => "=l",
NubPrimitiveType primitiveType => primitiveType.Kind switch BoundNubPrimitiveType primitiveType => primitiveType.Kind switch
{ {
PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "=l", PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "=l",
PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "=w", PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "=w",
@@ -390,11 +398,11 @@ public static class QBEGenerator
}; };
} }
private static int AlignmentOf(NubType type) private static int AlignmentOf(BoundNubType type)
{ {
switch (type) switch (type)
{ {
case NubPrimitiveType primitiveType: case BoundNubPrimitiveType primitiveType:
{ {
return primitiveType.Kind switch return primitiveType.Kind switch
{ {
@@ -405,17 +413,17 @@ public static class QBEGenerator
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
} }
case NubStructType structType: case BoundNubStructType structType:
{ {
var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name); var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
return structDef.Fields.Max(f => AlignmentOf(f.Type)); return structDef.Fields.Max(f => AlignmentOf(f.Type));
} }
case NubTraitType: case BoundNubTraitType:
case NubPointerType: case BoundNubPointerType:
case NubArrayType: case BoundNubArrayType:
case NubCStringType: case BoundNubCStringType:
case NubStringType: case BoundNubStringType:
case NubFuncType: case BoundNubFuncType:
return 8; return 8;
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
@@ -427,11 +435,11 @@ public static class QBEGenerator
return (offset + alignment - 1) & ~(alignment - 1); return (offset + alignment - 1) & ~(alignment - 1);
} }
private static int SizeOf(NubType type) private static int SizeOf(BoundNubType type)
{ {
switch (type) switch (type)
{ {
case NubPrimitiveType primitiveType: case BoundNubPrimitiveType primitiveType:
{ {
return primitiveType.Kind switch return primitiveType.Kind switch
{ {
@@ -442,7 +450,7 @@ public static class QBEGenerator
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
} }
case NubStructType structType: case BoundNubStructType structType:
{ {
var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name); var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
var size = 0; var size = 0;
@@ -461,13 +469,13 @@ public static class QBEGenerator
return size; return size;
} }
case NubTraitType: case BoundNubTraitType:
return 16; return 16;
case NubPointerType: case BoundNubPointerType:
case NubArrayType: case BoundNubArrayType:
case NubCStringType: case BoundNubCStringType:
case NubStringType: case BoundNubStringType:
case NubFuncType: case BoundNubFuncType:
return 8; return 8;
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
@@ -494,16 +502,17 @@ public static class QBEGenerator
throw new UnreachableException($"Member '{member}' not found in struct"); throw new UnreachableException($"Member '{member}' not found in struct");
} }
private static string FuncQBETypeName(NubType type) private static string FuncQBETypeName(BoundNubType type)
{ {
return type switch return type switch
{ {
NubCustomType customType => CustomTypeName(customType), BoundNubStructType structType => StructTypeName(structType),
NubComplexType => "l", BoundNubTraitType traitType => TraitTypeName(traitType),
NubSimpleType simpleType => simpleType switch BoundNubComplexType => "l",
BoundNubSimpleType simpleType => simpleType switch
{ {
NubPointerType or NubFuncType => "l", BoundNubPointerType or BoundNubFuncType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch BoundNubPrimitiveType primitiveType => primitiveType.Kind switch
{ {
PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w",
@@ -521,7 +530,7 @@ public static class QBEGenerator
}; };
} }
private static void EmitFuncDefinition(BoundNode debugNode, string name, List<FuncParameter> parameters, NubType returnType, BoundBlock body, bool exported) private static void EmitFuncDefinition(BoundNode debugNode, string name, List<BoundFuncParameterNode> parameters, BoundNubType returnType, BoundBlock body, bool exported)
{ {
_variables.Clear(); _variables.Clear();
_variableScopes.Clear(); _variableScopes.Clear();
@@ -536,7 +545,7 @@ public static class QBEGenerator
} }
builder.Append("function "); builder.Append("function ");
if (returnType is not NubVoidType) if (returnType is not BoundNubVoidType)
{ {
builder.Append(FuncQBETypeName(returnType) + ' '); builder.Append(FuncQBETypeName(returnType) + ' ');
} }
@@ -556,7 +565,7 @@ public static class QBEGenerator
if (body.Statements.LastOrDefault() is not BoundReturnNode) if (body.Statements.LastOrDefault() is not BoundReturnNode)
{ {
if (returnType is NubVoidType) if (returnType is BoundNubVoidType)
{ {
_writer.Indented("ret"); _writer.Indented("ret");
} }
@@ -567,7 +576,7 @@ public static class QBEGenerator
// private static void EmitStructDefinition(BoundStructNode structDef) // private static void EmitStructDefinition(BoundStructNode structDef)
// { // {
// var structType = new NubCustomType(structDef.Namespace, structDef.Name); // var structType = new BoundNubCustomType(structDef.Namespace, structDef.Name);
// _writer.WriteLine($"type {CustomTypeName(structType)} = {{ "); // _writer.WriteLine($"type {CustomTypeName(structType)} = {{ ");
// //
// var types = new Dictionary<string, string>(); // var types = new Dictionary<string, string>();
@@ -591,12 +600,12 @@ public static class QBEGenerator
// { // {
// return field.Type switch // return field.Type switch
// { // {
// NubCustomType customType => CustomTypeName(customType), // BoundNubCustomType customType => CustomTypeName(customType),
// NubComplexType => "l", // BoundNubComplexType => "l",
// NubSimpleType simpleType => simpleType switch // BoundNubSimpleType simpleType => simpleType switch
// { // {
// NubPointerType or NubFuncType => "l", // BoundNubPointerType or BoundNubFuncType => "l",
// NubPrimitiveType primitiveType => primitiveType.Kind switch // BoundNubPrimitiveType primitiveType => primitiveType.Kind switch
// { // {
// PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", // PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l",
// PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", // PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w",
@@ -615,7 +624,7 @@ public static class QBEGenerator
// //
// private static void EmitTraitVTable(BoundTraitNode traitDef) // private static void EmitTraitVTable(BoundTraitNode traitDef)
// { // {
// _writer.WriteLine($"type {CustomTypeName(new NubCustomType(traitDef.Namespace, traitDef.Name))} = {{"); // _writer.WriteLine($"type {CustomTypeName(new BoundNubCustomType(traitDef.Namespace, traitDef.Name))} = {{");
// //
// foreach (var func in traitDef.Functions) // foreach (var func in traitDef.Functions)
// { // {
@@ -810,10 +819,10 @@ public static class QBEGenerator
private static Val EmitArrayIndexAccess(BoundArrayIndexAccessNode arrayIndexAccess) private static Val EmitArrayIndexAccess(BoundArrayIndexAccessNode arrayIndexAccess)
{ {
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Array)); var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index)); var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
var elementType = ((NubArrayType)arrayIndexAccess.Array.Type).ElementType; var elementType = ((BoundNubArrayType)arrayIndexAccess.Target.Type).ElementType;
var pointer = TmpName(); var pointer = TmpName();
_writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}"); _writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}");
@@ -892,7 +901,7 @@ public static class QBEGenerator
return new Val(outputName, binaryExpression.Type, ValKind.Direct); return new Val(outputName, binaryExpression.Type, ValKind.Direct);
} }
private static string EmitBinaryInstructionFor(BinaryExpressionOperator op, NubType type, string left, string right) private static string EmitBinaryInstructionFor(BinaryExpressionOperator op, BoundNubType type, string left, string right)
{ {
if (op is if (op is
BinaryExpressionOperator.Equal or BinaryExpressionOperator.Equal or
@@ -1097,17 +1106,12 @@ public static class QBEGenerator
private static Val EmitStructInitializer(BoundStructInitializerNode structInitializer, string? destination = null) private static Val EmitStructInitializer(BoundStructInitializerNode structInitializer, string? destination = null)
{ {
if (structInitializer.StructType is not NubCustomType structType) var @struct = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name);
{
throw new UnreachableException();
}
var @struct = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
if (destination == null) if (destination == null)
{ {
destination = TmpName(); destination = TmpName();
var size = SizeOf(structType); var size = SizeOf(structInitializer.StructType);
_writer.Indented($"{destination} =l alloc8 {size}"); _writer.Indented($"{destination} =l alloc8 {size}");
} }
@@ -1125,7 +1129,7 @@ public static class QBEGenerator
EmitCopyIntoOrInitialize(valueExpression, offset); EmitCopyIntoOrInitialize(valueExpression, offset);
} }
return new Val(destination, structType, ValKind.Direct); return new Val(destination, structInitializer.StructType, ValKind.Direct);
} }
private static Val EmitUnaryExpression(BoundUnaryExpressionNode unaryExpression) private static Val EmitUnaryExpression(BoundUnaryExpressionNode unaryExpression)
@@ -1139,16 +1143,16 @@ public static class QBEGenerator
{ {
switch (unaryExpression.Operand.Type) switch (unaryExpression.Operand.Type)
{ {
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }: case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
_writer.Indented($"{outputName} =l neg {operand}"); _writer.Indented($"{outputName} =l neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return new Val(outputName, unaryExpression.Type, ValKind.Direct);
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }: case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }:
_writer.Indented($"{outputName} =w neg {operand}"); _writer.Indented($"{outputName} =w neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return new Val(outputName, unaryExpression.Type, ValKind.Direct);
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }: case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
_writer.Indented($"{outputName} =d neg {operand}"); _writer.Indented($"{outputName} =d neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return new Val(outputName, unaryExpression.Type, ValKind.Direct);
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }: case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
_writer.Indented($"{outputName} =s neg {operand}"); _writer.Indented($"{outputName} =s neg {operand}");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return new Val(outputName, unaryExpression.Type, ValKind.Direct);
} }
@@ -1159,7 +1163,7 @@ public static class QBEGenerator
{ {
switch (unaryExpression.Operand.Type) switch (unaryExpression.Operand.Type)
{ {
case NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }: case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.Bool }:
_writer.Indented($"{outputName} =w xor {operand}, 1"); _writer.Indented($"{outputName} =w xor {operand}, 1");
return new Val(outputName, unaryExpression.Type, ValKind.Direct); return new Val(outputName, unaryExpression.Type, ValKind.Direct);
} }
@@ -1186,7 +1190,7 @@ public static class QBEGenerator
_writer.Indented($"{output} =l add {target}, {offset}"); _writer.Indented($"{output} =l add {target}, {offset}");
// If the accessed member is an inline struct, it will not be a pointer // If the accessed member is an inline struct, it will not be a pointer
if (structFieldAccess.Type is NubStructType) if (structFieldAccess.Type is BoundNubStructType)
{ {
return new Val(output, structFieldAccess.Type, ValKind.Direct); return new Val(output, structFieldAccess.Type, ValKind.Direct);
} }
@@ -1203,8 +1207,7 @@ public static class QBEGenerator
{ {
var target = EmitExpression(traitImplFuncAccess.Target); var target = EmitExpression(traitImplFuncAccess.Target);
var impl = _definitionTable.LookupTraitImpl(traitImplFuncAccess.Target.Type); var funcImpl = _definitionTable.LookupTraitFuncImpl(traitImplFuncAccess.Target.Type, traitImplFuncAccess.FuncName);
var funcImpl = _definitionTable.LookupTraitFuncImpl(impl, traitImplFuncAccess.FuncName);
var name = ImplFuncName(); var name = ImplFuncName();
_implFunctions.TryAdd(funcImpl, name); _implFunctions.TryAdd(funcImpl, name);
@@ -1272,7 +1275,7 @@ internal class Variable(string name, Val val)
public Val Val { get; } = val; public Val Val { get; } = val;
} }
internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null); internal record Val(string Name, BoundNubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
internal record MethodCallContext(Val ThisArg); internal record MethodCallContext(Val ThisArg);

View File

@@ -14,8 +14,8 @@ public sealed class Binder
private readonly DefinitionTable _definitionTable; private readonly DefinitionTable _definitionTable;
// TODO: Implement proper variable tracking and scoping // TODO: Implement proper variable tracking and scoping
private Dictionary<string, NubType> _variables = new(); private Dictionary<string, BoundNubType> _variables = new();
private NubType? _functionReturnType; private BoundNubType? _functionReturnType;
public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable) public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable)
{ {
@@ -66,24 +66,34 @@ public sealed class Binder
foreach (var function in node.Functions) foreach (var function in node.Functions)
{ {
var parameters = new List<BoundFuncParameterNode>();
foreach (var parameter in function.Parameters) foreach (var parameter in function.Parameters)
{ {
_variables[parameter.Name] = parameter.Type; _variables[parameter.Name] = BindType(parameter.Type);
parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type)));
} }
functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, function.Parameters, BindType(function.ReturnType), BindBlock(function.Body))); functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, 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, BindType(node.TraitType), BindType(node.ForType), functions);
} }
private BoundTraitNode BindTraitDefinition(TraitNode node) private BoundTraitNode BindTraitDefinition(TraitNode node)
{ {
var functions = new List<BoundTraitFuncNode>(); var functions = new List<BoundTraitFuncNode>();
foreach (var func in node.Functions) foreach (var function in node.Functions)
{ {
functions.Add(new BoundTraitFuncNode(node.Tokens, func.Name, func.Parameters, BindType(func.ReturnType))); var parameters = new List<BoundFuncParameterNode>();
foreach (var parameter in function.Parameters)
{
parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type)));
}
functions.Add(new BoundTraitFuncNode(node.Tokens, function.Name, parameters, BindType(function.ReturnType)));
} }
return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions); return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions);
@@ -99,10 +109,10 @@ public sealed class Binder
if (field.Value.HasValue) if (field.Value.HasValue)
{ {
value = BindExpression(field.Value.Value, field.Type); value = BindExpression(field.Value.Value, BindType(field.Type));
} }
structFields.Add(new BoundStructFieldNode(field.Tokens, field.Index, field.Name, field.Type, value)); structFields.Add(new BoundStructFieldNode(field.Tokens, field.Index, field.Name, BindType(field.Type), value));
} }
return new BoundStructNode(node.Tokens, node.Namespace, node.Name, structFields); return new BoundStructNode(node.Tokens, node.Namespace, node.Name, structFields);
@@ -110,7 +120,14 @@ 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, BindType(node.ReturnType)); var parameters = new List<BoundFuncParameterNode>();
foreach (var parameter in node.Parameters)
{
parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type)));
}
return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, parameters, BindType(node.ReturnType));
} }
private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node) private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node)
@@ -118,14 +135,17 @@ public sealed class Binder
_variables.Clear(); _variables.Clear();
_functionReturnType = BindType(node.ReturnType); _functionReturnType = BindType(node.ReturnType);
var parameters = new List<BoundFuncParameterNode>();
foreach (var parameter in node.Parameters) foreach (var parameter in node.Parameters)
{ {
_variables[parameter.Name] = parameter.Type; _variables[parameter.Name] = BindType(parameter.Type);
parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type)));
} }
var body = BindBlock(node.Body); var body = BindBlock(node.Body);
return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, BindType(node.ReturnType), node.Exported); return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, parameters, body, BindType(node.ReturnType), node.Exported);
} }
private BoundBlock BindBlock(BlockNode node) private BoundBlock BindBlock(BlockNode node)
@@ -186,7 +206,7 @@ public sealed class Binder
); );
} }
return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body), elseStatement); return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, BoundNubPrimitiveType.Bool), BindBlock(statement.Body), elseStatement);
} }
private BoundReturnNode BindReturn(ReturnNode statement) private BoundReturnNode BindReturn(ReturnNode statement)
@@ -208,11 +228,11 @@ public sealed class Binder
private BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement) private BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement)
{ {
NubType? type = null; BoundNubType? type = null;
if (statement.ExplicitType.HasValue) if (statement.ExplicitType.HasValue)
{ {
type = statement.ExplicitType.Value; type = BindType(statement.ExplicitType.Value);
} }
var assignment = Optional<BoundExpressionNode>.Empty(); var assignment = Optional<BoundExpressionNode>.Empty();
@@ -230,15 +250,15 @@ public sealed class Binder
_variables[statement.Name] = type; _variables[statement.Name] = type;
return new BoundVariableDeclarationNode(statement.Tokens, statement.Name, statement.ExplicitType, assignment, type); return new BoundVariableDeclarationNode(statement.Tokens, statement.Name, assignment, type);
} }
private BoundWhileNode BindWhile(WhileNode statement) private BoundWhileNode BindWhile(WhileNode statement)
{ {
return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body)); return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, BoundNubPrimitiveType.Bool), BindBlock(statement.Body));
} }
private BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null) private BoundExpressionNode BindExpression(ExpressionNode node, BoundNubType? expectedType = null)
{ {
return node switch return node switch
{ {
@@ -261,28 +281,33 @@ public sealed class Binder
private BoundAddressOfNode BindAddressOf(AddressOfNode expression) private BoundAddressOfNode BindAddressOf(AddressOfNode expression)
{ {
var inner = BindExpression(expression.Expression); var inner = BindExpression(expression.Expression);
return new BoundAddressOfNode(expression.Tokens, new NubPointerType(inner.Type), inner); return new BoundAddressOfNode(expression.Tokens, new BoundNubPointerType(inner.Type), inner);
} }
private BoundAnonymousFuncNode BindAnonymousFunc(AnonymousFuncNode expression) private BoundAnonymousFuncNode BindAnonymousFunc(AnonymousFuncNode expression)
{ {
var parameterTypes = expression.Parameters.Select(x => x.Type).ToList(); var parameters = new List<BoundFuncParameterNode>();
foreach (var parameter in expression.Parameters)
{
parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type)));
}
var body = BindBlock(expression.Body); var body = BindBlock(expression.Body);
return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(BindType(expression.ReturnType), parameterTypes), expression.Parameters, body, BindType(expression.ReturnType)); return new BoundAnonymousFuncNode(expression.Tokens, new BoundNubFuncType(BindType(expression.ReturnType), parameters.Select(x => x.Type).ToList()), parameters, body, BindType(expression.ReturnType));
} }
private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression) private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression)
{ {
var boundArray = BindExpression(expression.Array); var boundArray = BindExpression(expression.Target);
var elementType = ((NubArrayType)boundArray.Type).ElementType; var elementType = ((BoundNubArrayType)boundArray.Type).ElementType;
return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, NubPrimitiveType.U64)); return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, BoundNubPrimitiveType.U64));
} }
private BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression) private BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression)
{ {
return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity, NubPrimitiveType.U64), expression.ElementType); return new BoundArrayInitializerNode(expression.Tokens, new BoundNubArrayType(BindType(expression.ElementType)), BindExpression(expression.Capacity, BoundNubPrimitiveType.U64), BindType(expression.ElementType));
} }
private BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression) private BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression)
@@ -295,7 +320,7 @@ public sealed class Binder
private BoundDereferenceNode BindDereference(DereferenceNode expression) private BoundDereferenceNode BindDereference(DereferenceNode expression)
{ {
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Expression);
var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType; var dereferencedType = ((BoundNubPointerType)boundExpression.Type).BaseType;
return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression); return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression);
} }
@@ -303,8 +328,7 @@ public sealed class Binder
{ {
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Expression);
var funcType = (NubFuncType)boundExpression.Type; var funcType = (BoundNubFuncType)boundExpression.Type;
var returnType = BindType(funcType.ReturnType);
var parameters = new List<BoundExpressionNode>(); var parameters = new List<BoundExpressionNode>();
@@ -320,7 +344,7 @@ public sealed class Binder
parameters.Add(BindExpression(parameter, expectedType)); parameters.Add(BindExpression(parameter, expectedType));
} }
return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters); return new BoundFuncCallNode(expression.Tokens, funcType.ReturnType, boundExpression, parameters);
} }
private BoundExpressionNode BindIdentifier(IdentifierNode expression) private BoundExpressionNode BindIdentifier(IdentifierNode expression)
@@ -336,8 +360,8 @@ public sealed class Binder
var localFunc = localFuncs[0]; var localFunc = localFuncs[0];
var type = new NubFuncType(BindType(localFunc.ReturnType), localFunc.Parameters.Select(p => p.Type).ToList()); var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList());
return new BoundLocalFuncIdentNode(expression.Tokens, type, @namespace, expression.Name); return new BoundLocalFuncIdentNode(expression.Tokens, BindType(type), @namespace, expression.Name);
} }
var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray(); var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray();
@@ -350,8 +374,8 @@ public sealed class Binder
var externFunc = externFuncs[0]; var externFunc = externFuncs[0];
var type = new NubFuncType(BindType(externFunc.ReturnType), externFunc.Parameters.Select(p => p.Type).ToList()); var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList());
return new BoundExternFuncIdentNode(expression.Tokens, type, @namespace, expression.Name); return new BoundExternFuncIdentNode(expression.Tokens, BindType(type), @namespace, expression.Name);
} }
if (!expression.Namespace.HasValue) if (!expression.Namespace.HasValue)
@@ -362,14 +386,14 @@ public sealed class Binder
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());
} }
private BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null) private BoundLiteralNode BindLiteral(LiteralNode expression, BoundNubType? expectedType = null)
{ {
var type = expectedType ?? expression.Kind switch var type = expectedType ?? expression.Kind switch
{ {
LiteralKind.Integer => NubPrimitiveType.I64, LiteralKind.Integer => BoundNubPrimitiveType.I64,
LiteralKind.Float => NubPrimitiveType.F64, LiteralKind.Float => BoundNubPrimitiveType.F64,
LiteralKind.String => new NubStringType(), LiteralKind.String => new BoundNubStringType(),
LiteralKind.Bool => NubPrimitiveType.Bool, LiteralKind.Bool => BoundNubPrimitiveType.Bool,
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
@@ -380,8 +404,7 @@ public sealed class Binder
{ {
var boundExpression = BindExpression(expression.Target); var boundExpression = BindExpression(expression.Target);
var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray(); var traitFuncImpls = _definitionTable.LookupTraitFuncImpl(UnbindType(boundExpression.Type), expression.Member).ToArray();
if (traitFuncImpls.Length > 0) if (traitFuncImpls.Length > 0)
{ {
if (traitFuncImpls.Length > 1) if (traitFuncImpls.Length > 1)
@@ -391,18 +414,18 @@ public sealed class Binder
var impl = traitFuncImpls[0]; var impl = traitFuncImpls[0];
var type = new NubFuncType(BindType(impl.ReturnType), impl.Parameters.Select(p => BindType(p.Type)).ToList()); var type = new BoundNubFuncType(BindType(impl.ReturnType), impl.Parameters.Select(p => BindType(p.Type)).ToList());
return new BoundTraitImplFuncAccessNode(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 BoundNubTraitType traitType)
{ {
var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray(); var traits = _definitionTable.LookupTrait(traitType.Namespace, traitType.Name).ToArray();
if (traits.Length > 0) if (traits.Length > 0)
{ {
if (traits.Length > 1) if (traits.Length > 1)
{ {
throw new BindException(Diagnostic.Error($"Trait {customType.Namespace}::{customType.Name} has multiple definitions").Build()); throw new BindException(Diagnostic.Error($"Trait {traitType.Namespace}::{traitType.Name} has multiple definitions").Build());
} }
var trait = traits[0]; var trait = traits[0];
@@ -417,22 +440,25 @@ public sealed class Binder
var traitFunc = traitFuncs[0]; var traitFunc = traitFuncs[0];
var type = new NubFuncType(BindType(traitFunc.ReturnType), traitFunc.Parameters.Select(p => BindType(p.Type)).ToList()); var type = new BoundNubFuncType(BindType(traitFunc.ReturnType), traitFunc.Parameters.Select(p => BindType(p.Type)).ToList());
return new BoundTraitFuncAccessNode(expression.Tokens, type, new NubTraitType(trait.Namespace, trait.Name), boundExpression, expression.Member); return new BoundTraitFuncAccessNode(expression.Tokens, type, traitType, boundExpression, expression.Member);
} }
} }
}
var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray(); if (boundExpression.Type is BoundNubStructType structType)
{
var structs = _definitionTable.LookupStruct(structType.Namespace, structType.Name).ToArray();
if (structs.Length > 0) if (structs.Length > 0)
{ {
if (structs.Length > 1) if (structs.Length > 1)
{ {
throw new BindException(Diagnostic.Error($"Struct {customType.Namespace}::{customType.Name} has multiple definitions").Build()); throw new BindException(Diagnostic.Error($"Struct {structType.Namespace}::{structType.Name} has multiple definitions").Build());
} }
var @struct = structs[0]; var @struct = structs[0];
var fields = _definitionTable.LookupStructField(@struct, customType.Name).ToArray(); var fields = _definitionTable.LookupStructField(@struct, expression.Member).ToArray();
if (fields.Length > 0) if (fields.Length > 0)
{ {
if (fields.Length > 1) if (fields.Length > 1)
@@ -442,12 +468,12 @@ public sealed class Binder
var field = fields[0]; var field = fields[0];
return new BoundStructFieldAccessNode(expression.Tokens, field.Type, new NubStructType(@struct.Namespace, @struct.Name), boundExpression, expression.Member); return new BoundStructFieldAccessNode(expression.Tokens, BindType(field.Type), structType, 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} does not have a member with the name {expression.Member}").Build());
} }
private BoundStructInitializerNode BindStructInitializer(StructInitializerNode expression) private BoundStructInitializerNode BindStructInitializer(StructInitializerNode expression)
@@ -487,23 +513,23 @@ public sealed class Binder
throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {field}").Build()); throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {field}").Build());
} }
initializers[field] = BindExpression(initializer, fields[0].Type); initializers[field] = BindExpression(initializer, BindType(fields[0].Type));
} }
return new BoundStructInitializerNode(expression.Tokens, structType, structType, initializers); return new BoundStructInitializerNode(expression.Tokens, BindType(structType), new BoundNubStructType(@struct.Namespace, @struct.Name), initializers);
} }
private BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression) private BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression)
{ {
var boundOperand = BindExpression(expression.Operand); var boundOperand = BindExpression(expression.Operand);
NubType? type = null; BoundNubType? type = null;
switch (expression.Operator) switch (expression.Operator)
{ {
case UnaryExpressionOperator.Negate: case UnaryExpressionOperator.Negate:
{ {
boundOperand = BindExpression(expression.Operand, NubPrimitiveType.I64); boundOperand = BindExpression(expression.Operand, BoundNubPrimitiveType.I64);
if (boundOperand.Type.IsNumber) if (boundOperand.Type.IsNumber)
{ {
@@ -514,9 +540,9 @@ public sealed class Binder
} }
case UnaryExpressionOperator.Invert: case UnaryExpressionOperator.Invert:
{ {
boundOperand = BindExpression(expression.Operand, NubPrimitiveType.Bool); boundOperand = BindExpression(expression.Operand, BoundNubPrimitiveType.Bool);
type = new NubPrimitiveType(PrimitiveTypeKind.Bool); type = new BoundNubPrimitiveType(PrimitiveTypeKind.Bool);
break; break;
} }
} }
@@ -529,46 +555,80 @@ 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) private BoundNubType BindType(NubType type)
{ {
if (type is NubCustomType customType) switch (type)
{ {
var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray(); case NubCustomType customType:
if (structs.Length > 1)
{ {
throw new BindException(Diagnostic.Error($"Struct {type} has multiple definitions").Build()); 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(); var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray();
if (traits.Length > 1) if (traits.Length > 1)
{ {
throw new BindException(Diagnostic.Error($"Trait {type} has multiple definitions").Build()); throw new BindException(Diagnostic.Error($"Trait {type} has multiple definitions").Build());
} }
if (structs.Length == 0 && traits.Length == 0) if (structs.Length == 0 && traits.Length == 0)
{ {
throw new BindException(Diagnostic.Error($"Failed to resolve type {type} to a struct or trait").Build()); throw new BindException(Diagnostic.Error($"Failed to resolve type {type} to a struct or trait").Build());
} }
if (structs.Length > 0 && traits.Length > 0) 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()); 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) if (structs.Length == 1)
{ {
return new NubStructType(customType.Namespace, customType.Name); return new BoundNubStructType(customType.Namespace, customType.Name);
} }
if (traits.Length == 1) if (traits.Length == 1)
{ {
return new NubTraitType(customType.Namespace, customType.Name); return new BoundNubTraitType(customType.Namespace, customType.Name);
} }
throw new UnreachableException(); throw new UnreachableException();
}
case NubArrayType arrayType:
return new BoundNubArrayType(BindType(arrayType.ElementType));
case NubCStringType:
return new BoundNubCStringType();
case NubStringType:
return new BoundNubStringType();
case NubFuncType funcType:
return new BoundNubFuncType(BindType(funcType.ReturnType), funcType.Parameters.Select(BindType).ToList());
case NubPointerType pointerType:
return new BoundNubPointerType(BindType(pointerType.BaseType));
case NubPrimitiveType primitiveType:
return new BoundNubPrimitiveType(primitiveType.Kind);
case NubVoidType:
return new BoundNubVoidType();
default:
throw new ArgumentOutOfRangeException(nameof(type));
} }
}
return type; private NubType UnbindType(BoundNubType type)
{
return type switch
{
BoundNubArrayType arrayType => new NubArrayType(UnbindType(arrayType.ElementType)),
BoundNubCStringType => new NubCStringType(),
BoundNubStringType => new NubStringType(),
BoundNubStructType structType => new NubCustomType(structType.Namespace, structType.Name),
BoundNubTraitType traitType => new NubCustomType(traitType.Namespace, traitType.Name),
BoundNubFuncType funcType => new NubFuncType(UnbindType(funcType.ReturnType), funcType.Parameters.Select(UnbindType).ToList()),
BoundNubPointerType pointerType => new NubPointerType(UnbindType(pointerType.BaseType)),
BoundNubPrimitiveType primitiveType => new NubPrimitiveType(primitiveType.Kind),
BoundNubVoidType => new NubVoidType(),
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
} }
} }

View File

@@ -37,16 +37,13 @@ public sealed class DefinitionTable
return structNode.Fields.Where(x => x.Name == field); return structNode.Fields.Where(x => x.Name == field);
} }
public IEnumerable<TraitImplNode> LookupTraitImpl(NubType itemType) public IEnumerable<TraitFuncImplNode> LookupTraitFuncImpl(NubType forType, string name)
{ {
return _topLevelNodes return _topLevelNodes
.OfType<TraitImplNode>() .OfType<TraitImplNode>()
.Where(x => x.TraitType == itemType); .Where(x => x.ForType == forType)
} .SelectMany(x => x.Functions)
.Where(x => x.Name == name);
public IEnumerable<TraitFuncImplNode> LookupTraitFuncImpl(TraitImplNode traitImpl, string name)
{
return traitImpl.Functions.Where(x => x.Name == name);
} }
public IEnumerable<TraitNode> LookupTrait(string @namespace, string name) public IEnumerable<TraitNode> LookupTrait(string @namespace, string name)
@@ -97,16 +94,20 @@ public sealed class BoundDefinitionTable
return structNode.Fields.First(x => x.Name == field); return structNode.Fields.First(x => x.Name == field);
} }
public BoundTraitImplNode LookupTraitImpl(NubType itemType) public IEnumerable<BoundTraitImplNode> LookupTraitImpls(BoundNubType itemType)
{ {
return _topLevelNodes return _topLevelNodes
.OfType<BoundTraitImplNode>() .OfType<BoundTraitImplNode>()
.First(x => x.TraitType == itemType); .Where(x => x.ForType == itemType);
} }
public BoundTraitFuncImplNode LookupTraitFuncImpl(BoundTraitImplNode traitImpl, string name) public BoundTraitFuncImplNode LookupTraitFuncImpl(BoundNubType forType, string name)
{ {
return traitImpl.Functions.First(x => x.Name == name); return _topLevelNodes
.OfType<BoundTraitImplNode>()
.Where(x => x.ForType == forType)
.SelectMany(x => x.Functions)
.First(x => x.Name == name);
} }
public BoundTraitNode LookupTrait(string @namespace, string name) public BoundTraitNode LookupTrait(string @namespace, string name)

View File

@@ -3,7 +3,8 @@ using Syntax.Tokenization;
namespace Syntax.Node; namespace Syntax.Node;
public record FuncParameter(string Name, NubType Type); public record FuncParameterNode(IEnumerable<Token> Tokens, string Name, NubType Type) : DefinitionNode(Tokens);
public record BoundFuncParameterNode(IEnumerable<Token> Tokens, string Name, BoundNubType Type) : DefinitionNode(Tokens);
public abstract record TopLevelNode(IEnumerable<Token> Tokens, string Namespace) : Node(Tokens); public abstract record TopLevelNode(IEnumerable<Token> Tokens, string Namespace) : Node(Tokens);
public abstract record BoundTopLevelNode(IEnumerable<Token> Tokens, string Namespace) : BoundNode(Tokens); public abstract record BoundTopLevelNode(IEnumerable<Token> Tokens, string Namespace) : BoundNode(Tokens);
@@ -11,26 +12,26 @@ public abstract record BoundTopLevelNode(IEnumerable<Token> Tokens, string Names
public abstract record DefinitionNode(IEnumerable<Token> Tokens) : Node(Tokens); public abstract record DefinitionNode(IEnumerable<Token> Tokens) : Node(Tokens);
public abstract record BoundDefinitionNode(IEnumerable<Token> Tokens) : BoundNode(Tokens); public abstract record BoundDefinitionNode(IEnumerable<Token> Tokens) : BoundNode(Tokens);
public record LocalFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<FuncParameter> Parameters, BlockNode Body, NubType ReturnType, bool Exported) : TopLevelNode(Tokens, Namespace); public record LocalFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<FuncParameterNode> Parameters, BlockNode Body, NubType ReturnType, bool Exported) : TopLevelNode(Tokens, Namespace);
public record BoundLocalFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<FuncParameter> Parameters, BoundBlock Body, NubType ReturnType, bool Exported) : BoundTopLevelNode(Tokens, Namespace); public record BoundLocalFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundFuncParameterNode> Parameters, BoundBlock Body, BoundNubType ReturnType, bool Exported) : BoundTopLevelNode(Tokens, Namespace);
public record ExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameter> Parameters, NubType ReturnType) : TopLevelNode(Tokens, Namespace); public record ExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameterNode> Parameters, NubType ReturnType) : TopLevelNode(Tokens, Namespace);
public record BoundExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameter> Parameters, NubType ReturnType) : BoundTopLevelNode(Tokens, Namespace); public record BoundExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<BoundFuncParameterNode> Parameters, BoundNubType ReturnType) : BoundTopLevelNode(Tokens, Namespace);
public record StructFieldNode(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<ExpressionNode> Value) : DefinitionNode(Tokens); public record StructFieldNode(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<ExpressionNode> Value) : DefinitionNode(Tokens);
public record StructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<StructFieldNode> Fields) : TopLevelNode(Tokens, Namespace); public record StructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<StructFieldNode> Fields) : TopLevelNode(Tokens, Namespace);
public record BoundStructFieldNode(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<BoundExpressionNode> Value) : BoundDefinitionNode(Tokens); public record BoundStructFieldNode(IEnumerable<Token> Tokens, int Index, string Name, BoundNubType Type, Optional<BoundExpressionNode> Value) : BoundDefinitionNode(Tokens);
public record BoundStructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundStructFieldNode> Fields) : BoundTopLevelNode(Tokens, Namespace); public record BoundStructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundStructFieldNode> Fields) : BoundTopLevelNode(Tokens, Namespace);
public record TraitFuncNode(IEnumerable<Token> Tokens, string Name, List<FuncParameter> Parameters, NubType ReturnType) : DefinitionNode(Tokens); public record TraitFuncNode(IEnumerable<Token> Tokens, string Name, List<FuncParameterNode> Parameters, NubType ReturnType) : DefinitionNode(Tokens);
public record TraitNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<TraitFuncNode> Functions) : TopLevelNode(Tokens, Namespace); public record TraitNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<TraitFuncNode> Functions) : TopLevelNode(Tokens, Namespace);
public record BoundTraitFuncNode(IEnumerable<Token> Tokens, string Name, List<FuncParameter> Parameters, NubType ReturnType) : BoundDefinitionNode(Tokens); public record BoundTraitFuncNode(IEnumerable<Token> Tokens, string Name, List<BoundFuncParameterNode> Parameters, BoundNubType ReturnType) : BoundDefinitionNode(Tokens);
public record BoundTraitNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundTraitFuncNode> Functions) : BoundTopLevelNode(Tokens, Namespace); public record BoundTraitNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundTraitFuncNode> Functions) : BoundTopLevelNode(Tokens, Namespace);
public record TraitFuncImplNode(IEnumerable<Token> Tokens, string Name, List<FuncParameter> Parameters, NubType ReturnType, BlockNode Body) : DefinitionNode(Tokens); public record TraitFuncImplNode(IEnumerable<Token> Tokens, string Name, List<FuncParameterNode> Parameters, NubType ReturnType, BlockNode Body) : DefinitionNode(Tokens);
public record TraitImplNode(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<TraitFuncImplNode> Functions) : TopLevelNode(Tokens, Namespace); public record TraitImplNode(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<TraitFuncImplNode> Functions) : TopLevelNode(Tokens, Namespace);
public record BoundTraitFuncImplNode(IEnumerable<Token> Tokens, string Name, List<FuncParameter> Parameters, NubType ReturnType, BoundBlock Body) : BoundDefinitionNode(Tokens); public record BoundTraitFuncImplNode(IEnumerable<Token> Tokens, string Name, List<BoundFuncParameterNode> Parameters, BoundNubType ReturnType, BoundBlock Body) : BoundDefinitionNode(Tokens);
public record BoundTraitImplNode(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<BoundTraitFuncImplNode> Functions) : BoundTopLevelNode(Tokens, Namespace); public record BoundTraitImplNode(IEnumerable<Token> Tokens, string Namespace, BoundNubType TraitType, BoundNubType ForType, List<BoundTraitFuncImplNode> Functions) : BoundTopLevelNode(Tokens, Namespace);

View File

@@ -24,44 +24,44 @@ public enum BinaryExpressionOperator
} }
public abstract record ExpressionNode(IEnumerable<Token> Tokens) : Node(Tokens); public abstract record ExpressionNode(IEnumerable<Token> Tokens) : Node(Tokens);
public abstract record BoundExpressionNode(IEnumerable<Token> Tokens, NubType Type) : BoundNode(Tokens); public abstract record BoundExpressionNode(IEnumerable<Token> Tokens, BoundNubType Type) : BoundNode(Tokens);
public record BinaryExpressionNode(IEnumerable<Token> Tokens, ExpressionNode Left, BinaryExpressionOperator Operator, ExpressionNode Right) : ExpressionNode(Tokens); public record BinaryExpressionNode(IEnumerable<Token> Tokens, ExpressionNode Left, BinaryExpressionOperator Operator, ExpressionNode Right) : ExpressionNode(Tokens);
public record BoundBinaryExpressionNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Left, BinaryExpressionOperator Operator, BoundExpressionNode Right) : BoundExpressionNode(Tokens, Type); public record BoundBinaryExpressionNode(IEnumerable<Token> Tokens, BoundNubType Type, BoundExpressionNode Left, BinaryExpressionOperator Operator, BoundExpressionNode Right) : BoundExpressionNode(Tokens, Type);
public record UnaryExpressionNode(IEnumerable<Token> Tokens, UnaryExpressionOperator Operator, ExpressionNode Operand) : ExpressionNode(Tokens); public record UnaryExpressionNode(IEnumerable<Token> Tokens, UnaryExpressionOperator Operator, ExpressionNode Operand) : ExpressionNode(Tokens);
public record BoundUnaryExpressionNode(IEnumerable<Token> Tokens, NubType Type, UnaryExpressionOperator Operator, BoundExpressionNode Operand) : BoundExpressionNode(Tokens, Type); public record BoundUnaryExpressionNode(IEnumerable<Token> Tokens, BoundNubType Type, UnaryExpressionOperator Operator, BoundExpressionNode Operand) : BoundExpressionNode(Tokens, Type);
public record FuncCallNode(IEnumerable<Token> Tokens, ExpressionNode Expression, List<ExpressionNode> Parameters) : ExpressionNode(Tokens); public record FuncCallNode(IEnumerable<Token> Tokens, ExpressionNode Expression, List<ExpressionNode> Parameters) : ExpressionNode(Tokens);
public record BoundFuncCallNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, List<BoundExpressionNode> Parameters) : BoundExpressionNode(Tokens, Type); public record BoundFuncCallNode(IEnumerable<Token> Tokens, BoundNubType 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 BoundVariableIdentNode(IEnumerable<Token> Tokens, NubType Type, string Name) : BoundExpressionNode(Tokens, Type); public record BoundVariableIdentNode(IEnumerable<Token> Tokens, BoundNubType Type, string Name) : BoundExpressionNode(Tokens, Type);
public record BoundLocalFuncIdentNode(IEnumerable<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type); public record BoundLocalFuncIdentNode(IEnumerable<Token> Tokens, BoundNubType 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 BoundExternFuncIdentNode(IEnumerable<Token> Tokens, BoundNubType 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, BoundNubType Type, BoundExpressionNode Capacity, BoundNubType ElementType) : BoundExpressionNode(Tokens, Type);
public record ArrayIndexAccessNode(IEnumerable<Token> Tokens, ExpressionNode Array, ExpressionNode Index) : ExpressionNode(Tokens); public record ArrayIndexAccessNode(IEnumerable<Token> Tokens, ExpressionNode Target, ExpressionNode Index) : ExpressionNode(Tokens);
public record BoundArrayIndexAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Array, BoundExpressionNode Index) : BoundExpressionNode(Tokens, Type); public record BoundArrayIndexAccessNode(IEnumerable<Token> Tokens, BoundNubType Type, BoundExpressionNode Target, BoundExpressionNode Index) : BoundExpressionNode(Tokens, Type);
public record AnonymousFuncNode(IEnumerable<Token> Tokens, List<FuncParameter> Parameters, BlockNode Body, NubType ReturnType) : ExpressionNode(Tokens); public record AnonymousFuncNode(IEnumerable<Token> Tokens, List<FuncParameterNode> Parameters, BlockNode Body, NubType ReturnType) : ExpressionNode(Tokens);
public record BoundAnonymousFuncNode(IEnumerable<Token> Tokens, NubType Type, List<FuncParameter> Parameters, BoundBlock Body, NubType ReturnType) : BoundExpressionNode(Tokens, Type); public record BoundAnonymousFuncNode(IEnumerable<Token> Tokens, BoundNubType Type, List<BoundFuncParameterNode> Parameters, BoundBlock Body, BoundNubType ReturnType) : BoundExpressionNode(Tokens, Type);
public record AddressOfNode(IEnumerable<Token> Tokens, ExpressionNode Expression) : ExpressionNode(Tokens); public record AddressOfNode(IEnumerable<Token> Tokens, ExpressionNode Expression) : ExpressionNode(Tokens);
public record BoundAddressOfNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type); public record BoundAddressOfNode(IEnumerable<Token> Tokens, BoundNubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type);
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, BoundNubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type);
public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Target, string Member) : ExpressionNode(Tokens); public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Target, string Member) : ExpressionNode(Tokens);
public record BoundStructFieldAccessNode(IEnumerable<Token> Tokens, NubType Type, NubStructType StructType, BoundExpressionNode Target, string Field) : BoundExpressionNode(Tokens, Type); public record BoundStructFieldAccessNode(IEnumerable<Token> Tokens, BoundNubType Type, BoundNubStructType 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 BoundTraitImplFuncAccessNode(IEnumerable<Token> Tokens, BoundNubType 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 BoundTraitFuncAccessNode(IEnumerable<Token> Tokens, BoundNubType Type, BoundNubTraitType 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, BoundNubType Type, BoundNubStructType StructType, Dictionary<string, BoundExpressionNode> Initializers) : BoundExpressionNode(Tokens, Type);
public record DereferenceNode(IEnumerable<Token> Tokens, ExpressionNode Expression) : ExpressionNode(Tokens); public record DereferenceNode(IEnumerable<Token> Tokens, ExpressionNode Expression) : ExpressionNode(Tokens);
public record BoundDereferenceNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type); public record BoundDereferenceNode(IEnumerable<Token> Tokens, BoundNubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type);

View File

@@ -20,7 +20,7 @@ public record IfNode(IEnumerable<Token> Tokens, ExpressionNode Condition, BlockN
public record BoundIfNode(IEnumerable<Token> Tokens, BoundExpressionNode Condition, BoundBlock Body, Optional<Variant<BoundIfNode, BoundBlock>> Else) : BoundStatementNode(Tokens); public record BoundIfNode(IEnumerable<Token> Tokens, BoundExpressionNode Condition, BoundBlock Body, Optional<Variant<BoundIfNode, BoundBlock>> Else) : BoundStatementNode(Tokens);
public record VariableDeclarationNode(IEnumerable<Token> Tokens, string Name, Optional<NubType> ExplicitType, Optional<ExpressionNode> Assignment) : StatementNode(Tokens); public record VariableDeclarationNode(IEnumerable<Token> Tokens, string Name, Optional<NubType> ExplicitType, Optional<ExpressionNode> Assignment) : StatementNode(Tokens);
public record BoundVariableDeclarationNode(IEnumerable<Token> Tokens, string Name, Optional<NubType> ExplicitType, Optional<BoundExpressionNode> Assignment, NubType Type) : BoundStatementNode(Tokens); public record BoundVariableDeclarationNode(IEnumerable<Token> Tokens, string Name, Optional<BoundExpressionNode> Assignment, BoundNubType Type) : BoundStatementNode(Tokens);
public record ContinueNode(IEnumerable<Token> Tokens) : StatementNode(Tokens); public record ContinueNode(IEnumerable<Token> Tokens) : StatementNode(Tokens);
public record BoundContinueNode(IEnumerable<Token> Tokens) : BoundStatementNode(Tokens); public record BoundContinueNode(IEnumerable<Token> Tokens) : BoundStatementNode(Tokens);

View File

@@ -0,0 +1,191 @@
using System.Diagnostics.CodeAnalysis;
namespace Syntax;
public abstract class BoundNubType : IEquatable<BoundNubType>
{
public bool Is8BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 };
public bool Is16BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 };
public bool Is32BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 };
public bool Is64BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 };
public bool IsSignedInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.I64 };
public bool IsUnsignedInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.U8 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.U64 };
public bool IsInteger => IsSignedInteger || IsUnsignedInteger;
public bool IsFloat32 => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F32 };
public bool IsFloat64 => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F64 };
public bool IsFloat => IsFloat32 || IsFloat64;
public bool IsNumber => IsFloat || IsInteger;
public bool IsVoid => this is BoundNubVoidType;
public bool IsString => this is BoundNubStringType;
public bool IsCString => this is BoundNubCStringType;
public bool IsBool => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.Bool };
public override bool Equals(object? obj) => obj is BoundNubType other && Equals(other);
public abstract bool Equals(BoundNubType? other);
public abstract override int GetHashCode();
public abstract override string ToString();
public static bool operator ==(BoundNubType? left, BoundNubType? right) => Equals(left, right);
public static bool operator !=(BoundNubType? left, BoundNubType? right) => !Equals(left, right);
}
public abstract class BoundNubComplexType : BoundNubType;
public abstract class BoundNubSimpleType : BoundNubType;
public class BoundNubCStringType : BoundNubComplexType
{
public override string ToString() => "cstring";
public override bool Equals(BoundNubType? other) => other is BoundNubCStringType;
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubCStringType));
}
public class BoundNubStringType : BoundNubComplexType
{
public override string ToString() => "string";
public override bool Equals(BoundNubType? other) => other is BoundNubStringType;
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubStringType));
}
public class BoundNubFuncType(BoundNubType returnType, List<BoundNubType> parameters) : BoundNubSimpleType
{
public BoundNubType ReturnType { get; } = returnType;
public List<BoundNubType> Parameters { get; } = parameters;
public override string ToString() => $"func({string.Join(", ", Parameters)}): {ReturnType}";
public override bool Equals(BoundNubType? other) => other is BoundNubFuncType func && ReturnType.Equals(func.ReturnType) && Parameters.SequenceEqual(func.Parameters);
public override int GetHashCode()
{
var hash = new HashCode();
hash.Add(typeof(BoundNubFuncType));
hash.Add(ReturnType);
foreach (var param in Parameters)
{
hash.Add(param);
}
return hash.ToHashCode();
}
}
public class BoundNubStructType(string @namespace, string name) : BoundNubComplexType
{
public string Namespace { get; } = @namespace;
public string Name { get; } = name;
public override string ToString() => $"{Namespace}::{Name}";
public override bool Equals(BoundNubType? other) => other is BoundNubStructType custom && Namespace == custom.Namespace && Name == custom.Name;
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubStructType), Namespace, Name);
}
public class BoundNubTraitType(string @namespace, string name) : BoundNubComplexType
{
public string Namespace { get; } = @namespace;
public string Name { get; } = name;
public override string ToString() => $"{Namespace}::{Name}";
public override bool Equals(BoundNubType? other) => other is BoundNubTraitType custom && Namespace == custom.Namespace && Name == custom.Name;
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubTraitType), Namespace, Name);
}
public class BoundNubPointerType(BoundNubType baseType) : BoundNubSimpleType
{
public BoundNubType BaseType { get; } = baseType;
public override string ToString() => "^" + BaseType;
public override bool Equals(BoundNubType? other) => other is BoundNubPointerType pointer && BaseType.Equals(pointer.BaseType);
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubPointerType), BaseType);
}
public class BoundNubArrayType(BoundNubType elementType) : BoundNubComplexType
{
public BoundNubType ElementType { get; } = elementType;
public override string ToString() => "[]" + ElementType;
public override bool Equals(BoundNubType? other) => other is BoundNubArrayType array && ElementType.Equals(array.ElementType);
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubArrayType), ElementType);
}
public class BoundNubVoidType : BoundNubSimpleType
{
public override string ToString() => "void";
public override bool Equals(BoundNubType? other) => other is BoundNubVoidType;
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubVoidType));
}
public class BoundNubPrimitiveType(PrimitiveTypeKind kind) : BoundNubSimpleType
{
public PrimitiveTypeKind Kind { get; } = kind;
public static BoundNubPrimitiveType I64 => new(PrimitiveTypeKind.I64);
public static BoundNubPrimitiveType I32 => new(PrimitiveTypeKind.I32);
public static BoundNubPrimitiveType I16 => new(PrimitiveTypeKind.I16);
public static BoundNubPrimitiveType I8 => new(PrimitiveTypeKind.I8);
public static BoundNubPrimitiveType U64 => new(PrimitiveTypeKind.U64);
public static BoundNubPrimitiveType U32 => new(PrimitiveTypeKind.U32);
public static BoundNubPrimitiveType U16 => new(PrimitiveTypeKind.U16);
public static BoundNubPrimitiveType U8 => new(PrimitiveTypeKind.U8);
public static BoundNubPrimitiveType F64 => new(PrimitiveTypeKind.F64);
public static BoundNubPrimitiveType F32 => new(PrimitiveTypeKind.F32);
public static BoundNubPrimitiveType Bool => new(PrimitiveTypeKind.Bool);
public static bool TryParse(string s, [NotNullWhen(true)] out PrimitiveTypeKind? kind)
{
kind = s switch
{
"i64" => PrimitiveTypeKind.I64,
"i32" => PrimitiveTypeKind.I32,
"i16" => PrimitiveTypeKind.I16,
"i8" => PrimitiveTypeKind.I8,
"u64" => PrimitiveTypeKind.U64,
"u32" => PrimitiveTypeKind.U32,
"u16" => PrimitiveTypeKind.U16,
"u8" => PrimitiveTypeKind.U8,
"f64" => PrimitiveTypeKind.F64,
"f32" => PrimitiveTypeKind.F32,
"bool" => PrimitiveTypeKind.Bool,
_ => null
};
return kind != null;
}
public override string ToString()
{
return Kind switch
{
PrimitiveTypeKind.I8 => "i8",
PrimitiveTypeKind.I16 => "i16",
PrimitiveTypeKind.I32 => "i32",
PrimitiveTypeKind.I64 => "i64",
PrimitiveTypeKind.U8 => "u8",
PrimitiveTypeKind.U16 => "u16",
PrimitiveTypeKind.U32 => "u32",
PrimitiveTypeKind.U64 => "u64",
PrimitiveTypeKind.F32 => "f32",
PrimitiveTypeKind.F64 => "f64",
PrimitiveTypeKind.Bool => "bool",
_ => throw new ArgumentOutOfRangeException(nameof(kind), Kind, null)
};
}
public override bool Equals(BoundNubType? other) => other is BoundNubPrimitiveType primitive && primitive.Kind == Kind;
public override int GetHashCode() => HashCode.Combine(typeof(BoundNubPrimitiveType), Kind.GetHashCode());
}

View File

@@ -86,18 +86,6 @@ 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;

View File

@@ -89,7 +89,7 @@ public sealed class Parser
private TopLevelNode ParseFunc(int startIndex, List<ModifierToken> modifiers) private TopLevelNode ParseFunc(int startIndex, List<ModifierToken> modifiers)
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();
List<FuncParameter> parameters = []; List<FuncParameterNode> parameters = [];
ExpectSymbol(Symbol.OpenParen); ExpectSymbol(Symbol.OpenParen);
@@ -184,7 +184,7 @@ public sealed class Parser
ExpectSymbol(Symbol.Func); ExpectSymbol(Symbol.Func);
var funcName = ExpectIdentifier().Value; var funcName = ExpectIdentifier().Value;
var parameters = new List<FuncParameter>(); var parameters = new List<FuncParameterNode>();
ExpectSymbol(Symbol.OpenParen); ExpectSymbol(Symbol.OpenParen);
while (!TryExpectSymbol(Symbol.CloseParen)) while (!TryExpectSymbol(Symbol.CloseParen))
@@ -223,9 +223,9 @@ public sealed class Parser
var funcStartIndex = _tokenIndex; var funcStartIndex = _tokenIndex;
ExpectSymbol(Symbol.Func); ExpectSymbol(Symbol.Func);
var functionName = ExpectIdentifier().Value; var functionName = ExpectIdentifier().Value;
var parameters = new List<FuncParameter> var parameters = new List<FuncParameterNode>
{ {
new("this", forType) new([], "this", forType)
}; };
ExpectSymbol(Symbol.OpenParen); ExpectSymbol(Symbol.OpenParen);
@@ -254,13 +254,14 @@ public sealed class Parser
return new TraitImplNode(GetTokensForNode(startIndex), _namespace, traitType, forType, functions); return new TraitImplNode(GetTokensForNode(startIndex), _namespace, traitType, forType, functions);
} }
private FuncParameter ParseFuncParameter() private FuncParameterNode ParseFuncParameter()
{ {
var startIndex = _tokenIndex;
var name = ExpectIdentifier(); var name = ExpectIdentifier();
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
var type = ParseType(); var type = ParseType();
return new FuncParameter(name.Value, type); return new FuncParameterNode(GetTokensForNode(startIndex), name.Value, type);
} }
private StatementNode ParseStatement() private StatementNode ParseStatement()
@@ -494,7 +495,7 @@ public sealed class Parser
{ {
case Symbol.Func: case Symbol.Func:
{ {
List<FuncParameter> parameters = []; List<FuncParameterNode> parameters = [];
ExpectSymbol(Symbol.OpenParen); ExpectSymbol(Symbol.OpenParen);
while (!TryExpectSymbol(Symbol.CloseParen)) while (!TryExpectSymbol(Symbol.CloseParen))
{ {