...
This commit is contained in:
@@ -11,5 +11,5 @@ global func main(argc: i64, argv: i64) {
|
|||||||
text = &text
|
text = &text
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s\n", x.text^)
|
printf("%s\n", x.text)
|
||||||
}
|
}
|
||||||
@@ -508,26 +508,56 @@ public class Generator
|
|||||||
|
|
||||||
private string GenerateExpression(ExpressionNode expression)
|
private string GenerateExpression(ExpressionNode expression)
|
||||||
{
|
{
|
||||||
switch (expression)
|
return expression switch
|
||||||
{
|
{
|
||||||
case BinaryExpressionNode binaryExpression:
|
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||||
return GenerateBinaryExpression(binaryExpression);
|
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||||
case CastNode cast:
|
CastNode cast => GenerateCast(cast),
|
||||||
return GenerateCast(cast);
|
DereferenceNode dereference => GenerateDereference(dereference),
|
||||||
case FuncCallExpressionNode funcCallExpression:
|
FuncCallExpressionNode funcCallExpression => GenerateExpressionFuncCall(funcCallExpression),
|
||||||
return GenerateExpressionFuncCall(funcCallExpression);
|
IdentifierNode identifier => GenerateIdentifier(identifier),
|
||||||
case IdentifierNode identifier:
|
LiteralNode literal => GenerateLiteral(literal),
|
||||||
return GenerateIdentifier(identifier);
|
StructInitializerNode structInitializer => GenerateStructInitializer(structInitializer),
|
||||||
case LiteralNode literal:
|
UnaryExpressionNode unaryExpression => GenerateUnaryExpression(unaryExpression),
|
||||||
return GenerateLiteral(literal);
|
StructFieldAccessorNode structMemberAccessor => GenerateStructFieldAccessor(structMemberAccessor),
|
||||||
case StructInitializerNode structInitializer:
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
return GenerateStructInitializer(structInitializer);
|
};
|
||||||
case UnaryExpressionNode unaryExpression:
|
}
|
||||||
return GenerateUnaryExpression(unaryExpression);
|
|
||||||
case StructFieldAccessorNode structMemberAccessor:
|
private string GenerateDereference(DereferenceNode dereference)
|
||||||
return GenerateStructFieldAccessor(structMemberAccessor);
|
{
|
||||||
|
var result = GenerateExpression(dereference.Expression);
|
||||||
|
var outputLabel = GenName();
|
||||||
|
_builder.AppendLine($" %{outputLabel} ={SQT(dereference.Type)} load{SQT(dereference.Type)} {result}");
|
||||||
|
return $"%{outputLabel}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateAddressOf(AddressOfNode addressOf)
|
||||||
|
{
|
||||||
|
var result = GenerateExpression(addressOf.Expression);
|
||||||
|
var outputLabel = GenName();
|
||||||
|
switch (addressOf.Expression.Type)
|
||||||
|
{
|
||||||
|
case NubPointerType:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.String }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }:
|
||||||
|
_builder.AppendLine($" %{outputLabel} =l alloc8 8");
|
||||||
|
_builder.AppendLine($" storel {result}, %{outputLabel}");
|
||||||
|
return $"%{outputLabel}";
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.U16 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }:
|
||||||
|
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
||||||
|
_builder.AppendLine($" %{outputLabel} =l alloc8 4");
|
||||||
|
_builder.AppendLine($" storew {result}, %{outputLabel}");
|
||||||
|
return $"%{outputLabel}";
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(expression));
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1314,37 +1344,6 @@ public class Generator
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UnaryExpressionOperator.AddressOf:
|
|
||||||
{
|
|
||||||
switch (unaryExpression.Operand.Type)
|
|
||||||
{
|
|
||||||
case NubPointerType:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.String }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }:
|
|
||||||
_builder.AppendLine($" %{outputLabel} =l alloc8 8");
|
|
||||||
_builder.AppendLine($" storel {operand}, %{outputLabel}");
|
|
||||||
return $"%{outputLabel}";
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U16 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
|
||||||
_builder.AppendLine($" %{outputLabel} =l alloc8 4");
|
|
||||||
_builder.AppendLine($" storew {operand}, %{outputLabel}");
|
|
||||||
return $"%{outputLabel}";
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case UnaryExpressionOperator.Dereference:
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" %{outputLabel} ={SQT(unaryExpression.Type)} load{SQT(unaryExpression.Type)} {operand}");
|
|
||||||
return $"%{outputLabel}";
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|||||||
6
src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs
Normal file
6
src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class AddressOfNode(ExpressionNode expression) : ExpressionNode
|
||||||
|
{
|
||||||
|
public ExpressionNode Expression { get; } = expression;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class DereferenceNode(ExpressionNode expression) : ExpressionNode
|
||||||
|
{
|
||||||
|
public ExpressionNode Expression { get; } = expression;
|
||||||
|
}
|
||||||
@@ -362,7 +362,7 @@ public class Parser
|
|||||||
case Symbol.Ampersand:
|
case Symbol.Ampersand:
|
||||||
{
|
{
|
||||||
var expression = ParsePrimaryExpression();
|
var expression = ParsePrimaryExpression();
|
||||||
return new UnaryExpressionNode(UnaryExpressionOperator.AddressOf, expression);
|
return new AddressOfNode(expression);
|
||||||
}
|
}
|
||||||
case Symbol.Minus:
|
case Symbol.Minus:
|
||||||
{
|
{
|
||||||
@@ -408,10 +408,6 @@ public class Parser
|
|||||||
{
|
{
|
||||||
var field = ExpectIdentifier();
|
var field = ExpectIdentifier();
|
||||||
result = new StructFieldAccessorNode(result, field.Value);
|
result = new StructFieldAccessorNode(result, field.Value);
|
||||||
if (TryExpectSymbol(Symbol.Caret))
|
|
||||||
{
|
|
||||||
result = new UnaryExpressionNode(UnaryExpressionOperator.Dereference, result);
|
|
||||||
}
|
|
||||||
} while (TryExpectSymbol(Symbol.Period));
|
} while (TryExpectSymbol(Symbol.Period));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -434,11 +430,6 @@ public class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Caret))
|
|
||||||
{
|
|
||||||
return new UnaryExpressionNode(UnaryExpressionOperator.Dereference, new IdentifierNode(identifier.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IdentifierNode(identifier.Value);
|
return new IdentifierNode(identifier.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ public class UnaryExpressionNode(UnaryExpressionOperator @operator, ExpressionNo
|
|||||||
|
|
||||||
public enum UnaryExpressionOperator
|
public enum UnaryExpressionOperator
|
||||||
{
|
{
|
||||||
AddressOf,
|
|
||||||
Dereference,
|
|
||||||
Negate,
|
Negate,
|
||||||
Invert
|
Invert
|
||||||
}
|
}
|
||||||
@@ -130,6 +130,17 @@ public class TypeChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NubType TypeCheckDereference(DereferenceNode dereference)
|
||||||
|
{
|
||||||
|
TypeCheckExpression(dereference.Expression);
|
||||||
|
if (dereference.Expression.Type is not NubPointerType nubPointerType)
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException($"Cannot dereference a non-pointer type {dereference.Expression.Type}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return nubPointerType.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
private NubType TypeCheckFuncCall(FuncCall funcCall)
|
private NubType TypeCheckFuncCall(FuncCall funcCall)
|
||||||
{
|
{
|
||||||
var localFuncDef = _definitions.OfType<LocalFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name);
|
var localFuncDef = _definitions.OfType<LocalFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name);
|
||||||
@@ -239,47 +250,46 @@ public class TypeChecker
|
|||||||
|
|
||||||
private NubType TypeCheckExpression(ExpressionNode expression)
|
private NubType TypeCheckExpression(ExpressionNode expression)
|
||||||
{
|
{
|
||||||
NubType resultType;
|
var resultType = expression switch
|
||||||
|
|
||||||
switch (expression)
|
|
||||||
{
|
{
|
||||||
case LiteralNode literal:
|
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
||||||
resultType = literal.LiteralType;
|
LiteralNode literal => literal.LiteralType,
|
||||||
break;
|
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
||||||
case IdentifierNode identifier:
|
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
CastNode cast => TypeCheckCast(cast),
|
||||||
{
|
DereferenceNode dereference => TypeCheckDereference(dereference),
|
||||||
throw new TypeCheckingException($"Variable '{identifier.Identifier}' is not defined");
|
FuncCallExpressionNode funcCallExpr => TypeCheckFuncCall(funcCallExpr.FuncCall),
|
||||||
}
|
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
||||||
|
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
||||||
resultType = varType;
|
StructFieldAccessorNode fieldAccess => TypeCheckStructFieldAccess(fieldAccess),
|
||||||
break;
|
_ => throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}")
|
||||||
case BinaryExpressionNode binaryExpr:
|
};
|
||||||
resultType = TypeCheckBinaryExpression(binaryExpr);
|
|
||||||
break;
|
|
||||||
case CastNode cast:
|
|
||||||
resultType = TypeCheckCast(cast);
|
|
||||||
break;
|
|
||||||
case FuncCallExpressionNode funcCallExpr:
|
|
||||||
resultType = TypeCheckFuncCall(funcCallExpr.FuncCall);
|
|
||||||
break;
|
|
||||||
case StructInitializerNode structInit:
|
|
||||||
resultType = TypeCheckStructInitializer(structInit);
|
|
||||||
break;
|
|
||||||
case UnaryExpressionNode unaryExpression:
|
|
||||||
resultType = TypeCheckUnaryExpression(unaryExpression);
|
|
||||||
break;
|
|
||||||
case StructFieldAccessorNode fieldAccess:
|
|
||||||
resultType = TypeCheckStructFieldAccess(fieldAccess);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
expression.Type = resultType;
|
expression.Type = resultType;
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NubType TypeCheckIdentifier(IdentifierNode identifier)
|
||||||
|
{
|
||||||
|
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException($"Variable '{identifier.Identifier}' is not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
return varType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NubType TypeCheckAddressOf(AddressOfNode addressOf)
|
||||||
|
{
|
||||||
|
TypeCheckExpression(addressOf.Expression);
|
||||||
|
if (addressOf.Expression is not (IdentifierNode or StructFieldAccessorNode))
|
||||||
|
{
|
||||||
|
throw new TypeCheckingException($"Cannot take the address of {addressOf.Expression.Type}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NubPointerType(addressOf.Expression.Type);
|
||||||
|
}
|
||||||
|
|
||||||
private NubType TypeCheckBinaryExpression(BinaryExpressionNode binaryExpr)
|
private NubType TypeCheckBinaryExpression(BinaryExpressionNode binaryExpr)
|
||||||
{
|
{
|
||||||
var leftType = TypeCheckExpression(binaryExpr.Left);
|
var leftType = TypeCheckExpression(binaryExpr.Left);
|
||||||
@@ -382,24 +392,6 @@ public class TypeChecker
|
|||||||
|
|
||||||
switch (unaryExpression.Operator)
|
switch (unaryExpression.Operator)
|
||||||
{
|
{
|
||||||
case UnaryExpressionOperator.AddressOf:
|
|
||||||
{
|
|
||||||
if (unaryExpression.Operand is not (IdentifierNode or StructFieldAccessorNode))
|
|
||||||
{
|
|
||||||
throw new TypeCheckingException($"Cannot take the address of {unaryExpression.Operand.GetType().Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NubPointerType(operandType);
|
|
||||||
}
|
|
||||||
case UnaryExpressionOperator.Dereference:
|
|
||||||
{
|
|
||||||
if (operandType is not NubPointerType nubPointerType)
|
|
||||||
{
|
|
||||||
throw new TypeCheckingException($"Cannot dereference a non-pointer type {operandType}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return nubPointerType.BaseType;
|
|
||||||
}
|
|
||||||
case UnaryExpressionOperator.Negate:
|
case UnaryExpressionOperator.Negate:
|
||||||
{
|
{
|
||||||
if (operandType.Equals(NubPrimitiveType.I8) ||
|
if (operandType.Equals(NubPrimitiveType.I8) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user