Array type works with args
This commit is contained in:
@@ -1,23 +1,10 @@
|
|||||||
import c
|
import c
|
||||||
|
|
||||||
struct Test {
|
global func main(args: []string) {
|
||||||
name: ^string
|
i = 0
|
||||||
}
|
printf("%d\n", args.count)
|
||||||
|
while i < args.count {
|
||||||
struct Test2 {
|
printf("%s\n", args[i])
|
||||||
parent: ^Test
|
i = i + 1
|
||||||
}
|
|
||||||
|
|
||||||
global func main(argc: i64, argv: i64) {
|
|
||||||
name = "Oliver"
|
|
||||||
|
|
||||||
parent = new Test {
|
|
||||||
name = &name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test = new Test2 {
|
|
||||||
parent = &parent
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", <string>(test.parent^.name^))
|
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,7 @@ public class Generator
|
|||||||
}
|
}
|
||||||
case NubStructType:
|
case NubStructType:
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
|
case NubArrayType:
|
||||||
{
|
{
|
||||||
return "l";
|
return "l";
|
||||||
}
|
}
|
||||||
@@ -120,6 +121,7 @@ public class Generator
|
|||||||
return ":" + nubCustomType.Name;
|
return ":" + nubCustomType.Name;
|
||||||
}
|
}
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
|
case NubArrayType:
|
||||||
{
|
{
|
||||||
return "l";
|
return "l";
|
||||||
}
|
}
|
||||||
@@ -169,6 +171,7 @@ public class Generator
|
|||||||
return ":" + nubCustomType.Name;
|
return ":" + nubCustomType.Name;
|
||||||
}
|
}
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
|
case NubArrayType:
|
||||||
{
|
{
|
||||||
return "l";
|
return "l";
|
||||||
}
|
}
|
||||||
@@ -221,6 +224,7 @@ public class Generator
|
|||||||
return definition.Fields.Sum(f => QbeTypeSize(f.Type));
|
return definition.Fields.Sum(f => QbeTypeSize(f.Type));
|
||||||
}
|
}
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
|
case NubArrayType:
|
||||||
{
|
{
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
@@ -474,15 +478,23 @@ public class Generator
|
|||||||
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
|
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(variableAssignment.Value);
|
var result = GenerateExpression(variableAssignment.Value);
|
||||||
var pointerLabel = GenName();
|
|
||||||
_builder.AppendLine($" %{pointerLabel} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}");
|
|
||||||
_builder.AppendLine($" storel {result}, %{pointerLabel}");
|
|
||||||
|
|
||||||
_variables[variableAssignment.Name] = new Variable
|
if (_variables.TryGetValue(variableAssignment.Name, out var existingVariable))
|
||||||
{
|
{
|
||||||
Pointer = $"%{pointerLabel}",
|
_builder.AppendLine($" storel {result}, {existingVariable.Pointer}");
|
||||||
Type = variableAssignment.Value.Type
|
}
|
||||||
};
|
else
|
||||||
|
{
|
||||||
|
var pointerLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{pointerLabel} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}");
|
||||||
|
_builder.AppendLine($" storel {result}, %{pointerLabel}");
|
||||||
|
|
||||||
|
_variables[variableAssignment.Name] = new Variable
|
||||||
|
{
|
||||||
|
Pointer = $"%{pointerLabel}",
|
||||||
|
Type = variableAssignment.Value.Type
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateWhile(WhileNode whileStatement)
|
private void GenerateWhile(WhileNode whileStatement)
|
||||||
@@ -511,6 +523,7 @@ public class Generator
|
|||||||
return expression switch
|
return expression switch
|
||||||
{
|
{
|
||||||
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||||
|
ArrayIndexNode arrayIndex => GenerateArrayIndex(arrayIndex),
|
||||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||||
CastNode cast => GenerateCast(cast),
|
CastNode cast => GenerateCast(cast),
|
||||||
DereferenceNode dereference => GenerateDereference(dereference),
|
DereferenceNode dereference => GenerateDereference(dereference),
|
||||||
@@ -519,11 +532,29 @@ public class Generator
|
|||||||
LiteralNode literal => GenerateLiteral(literal),
|
LiteralNode literal => GenerateLiteral(literal),
|
||||||
StructInitializerNode structInitializer => GenerateStructInitializer(structInitializer),
|
StructInitializerNode structInitializer => GenerateStructInitializer(structInitializer),
|
||||||
UnaryExpressionNode unaryExpression => GenerateUnaryExpression(unaryExpression),
|
UnaryExpressionNode unaryExpression => GenerateUnaryExpression(unaryExpression),
|
||||||
StructFieldAccessorNode structMemberAccessor => GenerateStructFieldAccessor(structMemberAccessor),
|
MemberAccessNode memberAccess => GenerateMemberAccess(memberAccess),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateArrayIndex(ArrayIndexNode arrayIndex)
|
||||||
|
{
|
||||||
|
var array = GenerateExpression(arrayIndex.Expression);
|
||||||
|
var index = GenerateExpression(arrayIndex.Index);
|
||||||
|
|
||||||
|
var arrayBaseType = ((NubArrayType)arrayIndex.Expression.Type).BaseType;
|
||||||
|
|
||||||
|
var firstItem = GenName();
|
||||||
|
_builder.AppendLine($" %{firstItem} =l add {array}, 8");
|
||||||
|
var adjustedIndex = GenName();
|
||||||
|
_builder.AppendLine($" %{adjustedIndex} =l mul {index}, {QbeTypeSize(arrayBaseType)}");
|
||||||
|
var indexLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{indexLabel} ={SQT(arrayIndex.Type)} add %{firstItem}, %{adjustedIndex}");
|
||||||
|
var outputLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{outputLabel} =l load{SQT(arrayBaseType)} %{indexLabel}");
|
||||||
|
return $"%{outputLabel}";
|
||||||
|
}
|
||||||
|
|
||||||
private string GenerateDereference(DereferenceNode dereference)
|
private string GenerateDereference(DereferenceNode dereference)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(dereference.Expression);
|
var result = GenerateExpression(dereference.Expression);
|
||||||
@@ -1354,42 +1385,60 @@ public class Generator
|
|||||||
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 string GenerateStructFieldAccessor(StructFieldAccessorNode structFieldAccessor)
|
private string GenerateMemberAccess(MemberAccessNode memberAccess)
|
||||||
{
|
{
|
||||||
var structType = structFieldAccessor.Struct.Type;
|
var expression = GenerateExpression(memberAccess.Expression);
|
||||||
var structDefinition = _definitions
|
|
||||||
.OfType<StructDefinitionNode>()
|
|
||||||
.FirstOrDefault(s => s.Name == structType.Name);
|
|
||||||
|
|
||||||
if (structDefinition == null)
|
switch (memberAccess.Expression.Type)
|
||||||
{
|
{
|
||||||
throw new Exception($"Struct {structType.Name} is not defined");
|
case NubArrayType:
|
||||||
}
|
|
||||||
|
|
||||||
var @struct = GenerateExpression(structFieldAccessor.Struct);
|
|
||||||
|
|
||||||
var fieldIndex = -1;
|
|
||||||
for (var i = 0; i < structDefinition.Fields.Count; i++)
|
|
||||||
{
|
|
||||||
if (structDefinition.Fields[i].Name == structFieldAccessor.Field)
|
|
||||||
{
|
{
|
||||||
fieldIndex = i;
|
if (memberAccess.Member == "count")
|
||||||
|
{
|
||||||
|
var outputLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{outputLabel} =l loadl {expression}");
|
||||||
|
return $"%{outputLabel}";
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NubStructType structType:
|
||||||
|
{
|
||||||
|
var structDefinition = _definitions
|
||||||
|
.OfType<StructDefinitionNode>()
|
||||||
|
.FirstOrDefault(s => s.Name == structType.Name);
|
||||||
|
|
||||||
|
if (structDefinition == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Struct {structType.Name} is not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldIndex = -1;
|
||||||
|
for (var i = 0; i < structDefinition.Fields.Count; i++)
|
||||||
|
{
|
||||||
|
if (structDefinition.Fields[i].Name == memberAccess.Member)
|
||||||
|
{
|
||||||
|
fieldIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldIndex == -1)
|
||||||
|
{
|
||||||
|
throw new Exception($"Field {memberAccess.Member} is not defined in struct {structType.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var offsetLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{offsetLabel} =l add {expression}, {fieldIndex * QbeTypeSize(memberAccess.Type)}");
|
||||||
|
|
||||||
|
var outputLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{outputLabel} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetLabel}");
|
||||||
|
|
||||||
|
return $"%{outputLabel}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldIndex == -1)
|
throw new ArgumentOutOfRangeException(nameof(memberAccess.Expression.Type));
|
||||||
{
|
|
||||||
throw new Exception($"Field {structFieldAccessor.Field} is not defined in struct {structType.Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var offsetLabel = GenName();
|
|
||||||
_builder.AppendLine($" %{offsetLabel} =l add {@struct}, {fieldIndex * QbeTypeSize(structFieldAccessor.Type)}");
|
|
||||||
|
|
||||||
var outputLabel = GenName();
|
|
||||||
_builder.AppendLine($" %{outputLabel} ={SQT(structFieldAccessor.Type)} load{SQT(structFieldAccessor.Type)} %{offsetLabel}");
|
|
||||||
|
|
||||||
return $"%{outputLabel}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall)
|
private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall)
|
||||||
|
|||||||
7
src/compiler/Nub.Lang/Frontend/Parsing/ArrayIndexNode.cs
Normal file
7
src/compiler/Nub.Lang/Frontend/Parsing/ArrayIndexNode.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class ArrayIndexNode(ExpressionNode expression, ExpressionNode index) : ExpressionNode
|
||||||
|
{
|
||||||
|
public ExpressionNode Expression { get; } = expression;
|
||||||
|
public ExpressionNode Index { get; } = index;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class MemberAccessNode(ExpressionNode expression, string member) : ExpressionNode
|
||||||
|
{
|
||||||
|
public ExpressionNode Expression { get; } = expression;
|
||||||
|
public string Member { get; } = member;
|
||||||
|
}
|
||||||
@@ -427,17 +427,17 @@ public class Parser
|
|||||||
if (TryExpectSymbol(Symbol.Period))
|
if (TryExpectSymbol(Symbol.Period))
|
||||||
{
|
{
|
||||||
var structMember = ExpectIdentifier().Value;
|
var structMember = ExpectIdentifier().Value;
|
||||||
expr = new StructFieldAccessorNode(expr, structMember);
|
expr = new MemberAccessNode(expr, structMember);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (TryExpectSymbol(Symbol.OpenBracket))
|
if (TryExpectSymbol(Symbol.OpenBracket))
|
||||||
// {
|
{
|
||||||
// var index = ParseExpression();
|
var index = ParseExpression();
|
||||||
// ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
// expr = new ArrayIndexNode(expr, index);
|
expr = new ArrayIndexNode(expr, index);
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -459,10 +459,25 @@ public class Parser
|
|||||||
|
|
||||||
private NubType ParseType()
|
private NubType ParseType()
|
||||||
{
|
{
|
||||||
var pointer = TryExpectSymbol(Symbol.Caret);
|
if (TryExpectIdentifier(out var name))
|
||||||
var name = ExpectIdentifier().Value;
|
{
|
||||||
var type = NubType.Parse(name);
|
return NubType.Parse(name);
|
||||||
return pointer ? new NubPointerType(type) : type;
|
}
|
||||||
|
|
||||||
|
if (TryExpectSymbol(Symbol.Caret))
|
||||||
|
{
|
||||||
|
var baseType = ParseType();
|
||||||
|
return new NubPointerType(baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryExpectSymbol(Symbol.OpenBracket))
|
||||||
|
{
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
var baseType = ParseType();
|
||||||
|
return new NubArrayType(baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Unexpected token {Peek()} when parsing type");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Token ExpectToken()
|
private Token ExpectToken()
|
||||||
@@ -517,6 +532,19 @@ public class Parser
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryExpectIdentifier([NotNullWhen(true)] out string? identifier)
|
||||||
|
{
|
||||||
|
if (Peek() is { HasValue: true, Value: IdentifierToken identifierToken })
|
||||||
|
{
|
||||||
|
identifier = identifierToken.Value;
|
||||||
|
Next();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
identifier = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private IdentifierToken ExpectIdentifier()
|
private IdentifierToken ExpectIdentifier()
|
||||||
{
|
{
|
||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace Nub.Lang.Frontend.Parsing;
|
|
||||||
|
|
||||||
public class StructFieldAccessorNode(ExpressionNode @struct, string field) : ExpressionNode
|
|
||||||
{
|
|
||||||
public ExpressionNode Struct { get; } = @struct;
|
|
||||||
public string Field { get; } = field;
|
|
||||||
}
|
|
||||||
@@ -253,6 +253,7 @@ public class TypeChecker
|
|||||||
var resultType = expression switch
|
var resultType = expression switch
|
||||||
{
|
{
|
||||||
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
||||||
|
ArrayIndexNode arrayIndex => TypeCheckArrayIndex(arrayIndex),
|
||||||
LiteralNode literal => literal.LiteralType,
|
LiteralNode literal => literal.LiteralType,
|
||||||
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
||||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||||
@@ -261,7 +262,7 @@ public class TypeChecker
|
|||||||
FuncCallExpressionNode funcCallExpr => TypeCheckFuncCall(funcCallExpr.FuncCall),
|
FuncCallExpressionNode funcCallExpr => TypeCheckFuncCall(funcCallExpr.FuncCall),
|
||||||
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
||||||
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
||||||
StructFieldAccessorNode fieldAccess => TypeCheckStructFieldAccess(fieldAccess),
|
MemberAccessNode memberAccess => TypeCheckMemberAccess(memberAccess),
|
||||||
_ => throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}")
|
_ => throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}")
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -269,6 +270,23 @@ public class TypeChecker
|
|||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NubType TypeCheckArrayIndex(ArrayIndexNode arrayIndex)
|
||||||
|
{
|
||||||
|
var expressionType = TypeCheckExpression(arrayIndex.Expression);
|
||||||
|
if (expressionType is not NubArrayType arrayType)
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException($"Annot access index of non-array type {expressionType}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var indexType = TypeCheckExpression(arrayIndex.Index);
|
||||||
|
if (!IsInteger(indexType))
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException("Array index type must be an integer");
|
||||||
|
}
|
||||||
|
|
||||||
|
return arrayType.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
private NubType TypeCheckIdentifier(IdentifierNode identifier)
|
private NubType TypeCheckIdentifier(IdentifierNode identifier)
|
||||||
{
|
{
|
||||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||||
@@ -282,7 +300,7 @@ public class TypeChecker
|
|||||||
private NubType TypeCheckAddressOf(AddressOfNode addressOf)
|
private NubType TypeCheckAddressOf(AddressOfNode addressOf)
|
||||||
{
|
{
|
||||||
TypeCheckExpression(addressOf.Expression);
|
TypeCheckExpression(addressOf.Expression);
|
||||||
if (addressOf.Expression is not (IdentifierNode or StructFieldAccessorNode))
|
if (addressOf.Expression is not (IdentifierNode or MemberAccessNode))
|
||||||
{
|
{
|
||||||
throw new TypeCheckingException($"Cannot take the address of {addressOf.Expression.Type}");
|
throw new TypeCheckingException($"Cannot take the address of {addressOf.Expression.Type}");
|
||||||
}
|
}
|
||||||
@@ -422,27 +440,39 @@ public class TypeChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubType TypeCheckStructFieldAccess(StructFieldAccessorNode fieldAccess)
|
private NubType TypeCheckMemberAccess(MemberAccessNode memberAccess)
|
||||||
{
|
{
|
||||||
var structType = TypeCheckExpression(fieldAccess.Struct);
|
var expressionType = TypeCheckExpression(memberAccess.Expression);
|
||||||
if (structType is not NubStructType customType)
|
switch (expressionType)
|
||||||
{
|
{
|
||||||
throw new TypeCheckingException($"Cannot access field '{fieldAccess.Field}' on non-struct type '{structType}'");
|
case NubArrayType:
|
||||||
|
{
|
||||||
|
if (memberAccess.Member == "count")
|
||||||
|
{
|
||||||
|
return NubPrimitiveType.I64;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NubStructType structType:
|
||||||
|
{
|
||||||
|
var definition = _definitions.OfType<StructDefinitionNode>().FirstOrDefault(s => s.Name == structType.Name);
|
||||||
|
if (definition == null)
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException($"Struct type '{structType.Name}' is not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = definition.Fields.FirstOrDefault(f => f.Name == memberAccess.Member);
|
||||||
|
if (field == null)
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException($"Field '{memberAccess.Member}' does not exist in struct '{structType.Name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return field.Type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = _definitions.OfType<StructDefinitionNode>().FirstOrDefault(s => s.Name == customType.Name);
|
throw new TypeCheckingException($"Cannot access member '{memberAccess.Member}' on type '{expressionType}'");
|
||||||
if (definition == null)
|
|
||||||
{
|
|
||||||
throw new TypeCheckingException($"Struct type '{customType.Name}' is not defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
var field = definition.Fields.FirstOrDefault(f => f.Name == fieldAccess.Field);
|
|
||||||
if (field == null)
|
|
||||||
{
|
|
||||||
throw new TypeCheckingException($"Field '{fieldAccess.Field}' does not exist in struct '{customType.Name}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return field.Type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AreTypesCompatible(NubType sourceType, NubType targetType)
|
private static bool AreTypesCompatible(NubType sourceType, NubType targetType)
|
||||||
@@ -474,4 +504,27 @@ public class TypeChecker
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsInteger(NubType type)
|
||||||
|
{
|
||||||
|
if (type is not NubPrimitiveType primitiveType)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (primitiveType.Kind)
|
||||||
|
{
|
||||||
|
case PrimitiveTypeKind.I8:
|
||||||
|
case PrimitiveTypeKind.I16:
|
||||||
|
case PrimitiveTypeKind.I32:
|
||||||
|
case PrimitiveTypeKind.I64:
|
||||||
|
case PrimitiveTypeKind.U8:
|
||||||
|
case PrimitiveTypeKind.U16:
|
||||||
|
case PrimitiveTypeKind.U32:
|
||||||
|
case PrimitiveTypeKind.U64:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,29 @@ public class NubPointerType(NubType baseType) : NubType("^" + baseType)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode() => BaseType.GetHashCode() * 31;
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(base.GetHashCode(), BaseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NubArrayType(NubType baseType) : NubType("[]" + baseType)
|
||||||
|
{
|
||||||
|
public NubType BaseType { get; } = baseType;
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj is NubArrayType other)
|
||||||
|
{
|
||||||
|
return BaseType.Equals(other.BaseType);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(base.GetHashCode(), BaseType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType(KindToString(kind))
|
public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType(KindToString(kind))
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ extern main
|
|||||||
|
|
||||||
section .text
|
section .text
|
||||||
_start:
|
_start:
|
||||||
; Extract argc and argv from the stack
|
; The args already match our array structure, so we pass the result directly
|
||||||
mov rdi, [rsp] ; rdi = argc
|
mov rdi, rsp
|
||||||
lea rsi, [rsp + 8] ; rsi = argv (pointer to array of strings)
|
|
||||||
|
|
||||||
; Call main(argc, argv)
|
|
||||||
call main ; main returns int in rax
|
call main ; main returns int in rax
|
||||||
|
|
||||||
; Exit with main's return value
|
; Exit with main's return value
|
||||||
@@ -34,3 +32,4 @@ nub_strcmp:
|
|||||||
.equal:
|
.equal:
|
||||||
mov rax, 1
|
mov rax, 1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
Reference in New Issue
Block a user