casting
This commit is contained in:
@@ -478,6 +478,8 @@ public class Generator
|
|||||||
{
|
{
|
||||||
case BinaryExpressionNode binaryExpression:
|
case BinaryExpressionNode binaryExpression:
|
||||||
return GenerateBinaryExpression(binaryExpression);
|
return GenerateBinaryExpression(binaryExpression);
|
||||||
|
case CastNode cast:
|
||||||
|
return GenerateCast(cast);
|
||||||
case FuncCallExpressionNode funcCallExpression:
|
case FuncCallExpressionNode funcCallExpression:
|
||||||
return GenerateExpressionFuncCall(funcCallExpression);
|
return GenerateExpressionFuncCall(funcCallExpression);
|
||||||
case IdentifierNode identifier:
|
case IdentifierNode identifier:
|
||||||
@@ -493,44 +495,6 @@ public class Generator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateStructFieldAccessor(StructFieldAccessorNode structFieldAccessor)
|
|
||||||
{
|
|
||||||
var structType = structFieldAccessor.Struct.Type;
|
|
||||||
var structDefinition = _definitions
|
|
||||||
.OfType<StructDefinitionNode>()
|
|
||||||
.FirstOrDefault(s => s.Name == structType.Name);
|
|
||||||
|
|
||||||
if (structDefinition == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"Struct {structType.Name} is not defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldIndex == -1)
|
|
||||||
{
|
|
||||||
throw new Exception($"Field {structFieldAccessor.Field} is not defined in struct {structType.Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var offsetLabel = GenName("offset");
|
|
||||||
_builder.AppendLine($" %{offsetLabel} =l add {@struct}, {fieldIndex * QbeTypeSize(structFieldAccessor.Type)}");
|
|
||||||
|
|
||||||
var outputLabel = GenName("field");
|
|
||||||
_builder.AppendLine($" %{outputLabel} ={SQT(structFieldAccessor.Type)} load{SQT(structFieldAccessor.Type)} %{offsetLabel}");
|
|
||||||
|
|
||||||
return $"%{outputLabel}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateBinaryExpression(BinaryExpressionNode binaryExpression)
|
private string GenerateBinaryExpression(BinaryExpressionNode binaryExpression)
|
||||||
{
|
{
|
||||||
var left = GenerateExpression(binaryExpression.Left);
|
var left = GenerateExpression(binaryExpression.Left);
|
||||||
@@ -757,41 +721,12 @@ public class Generator
|
|||||||
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types left: {binaryExpression.Left.Type}, right: {binaryExpression.Right.Type} not supported");
|
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types left: {binaryExpression.Left.Type}, right: {binaryExpression.Right.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateIdentifier(IdentifierNode identifier)
|
private string GenerateCast(CastNode cast)
|
||||||
{
|
{
|
||||||
return _variables[identifier.Identifier].Identifier;
|
var input = GenerateExpression(cast.Expression);
|
||||||
}
|
var outputType = cast.TargetType;
|
||||||
|
var inputType = cast.Expression.Type;
|
||||||
|
|
||||||
private string GenerateLiteral(LiteralNode literal)
|
|
||||||
{
|
|
||||||
if (literal.LiteralType.Equals(NubPrimitiveType.String))
|
|
||||||
{
|
|
||||||
_strings.Add(literal.Literal);
|
|
||||||
return $"$str{_strings.Count}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (literal.LiteralType.Equals(NubPrimitiveType.I64))
|
|
||||||
{
|
|
||||||
return literal.Literal;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (literal.LiteralType.Equals(NubPrimitiveType.F64))
|
|
||||||
{
|
|
||||||
var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture);
|
|
||||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
|
||||||
return bits.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (literal.LiteralType.Equals(NubPrimitiveType.Bool))
|
|
||||||
{
|
|
||||||
return bool.Parse(literal.Literal) ? "1" : "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new NotSupportedException($"Literal {literal.LiteralType} is not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateTypeConversion(string input, NubType inputType, NubType outputType)
|
|
||||||
{
|
|
||||||
if (inputType.Equals(outputType) || outputType.Equals(NubPrimitiveType.Any))
|
if (inputType.Equals(outputType) || outputType.Equals(NubPrimitiveType.Any))
|
||||||
{
|
{
|
||||||
return input;
|
return input;
|
||||||
@@ -1107,6 +1042,39 @@ public class Generator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateIdentifier(IdentifierNode identifier)
|
||||||
|
{
|
||||||
|
return _variables[identifier.Identifier].Identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateLiteral(LiteralNode literal)
|
||||||
|
{
|
||||||
|
if (literal.LiteralType.Equals(NubPrimitiveType.String))
|
||||||
|
{
|
||||||
|
_strings.Add(literal.Literal);
|
||||||
|
return $"$str{_strings.Count}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (literal.LiteralType.Equals(NubPrimitiveType.I64))
|
||||||
|
{
|
||||||
|
return literal.Literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (literal.LiteralType.Equals(NubPrimitiveType.F64))
|
||||||
|
{
|
||||||
|
var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture);
|
||||||
|
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||||
|
return bits.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (literal.LiteralType.Equals(NubPrimitiveType.Bool))
|
||||||
|
{
|
||||||
|
return bool.Parse(literal.Literal) ? "1" : "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException($"Literal {literal.LiteralType} is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
private string GenerateStructInitializer(StructInitializerNode structInitializer)
|
private string GenerateStructInitializer(StructInitializerNode structInitializer)
|
||||||
{
|
{
|
||||||
var structDefinition = _definitions.OfType<StructDefinitionNode>()
|
var structDefinition = _definitions.OfType<StructDefinitionNode>()
|
||||||
@@ -1149,6 +1117,44 @@ public class Generator
|
|||||||
return $"%{structVar}";
|
return $"%{structVar}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateStructFieldAccessor(StructFieldAccessorNode structFieldAccessor)
|
||||||
|
{
|
||||||
|
var structType = structFieldAccessor.Struct.Type;
|
||||||
|
var structDefinition = _definitions
|
||||||
|
.OfType<StructDefinitionNode>()
|
||||||
|
.FirstOrDefault(s => s.Name == structType.Name);
|
||||||
|
|
||||||
|
if (structDefinition == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Struct {structType.Name} is not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldIndex == -1)
|
||||||
|
{
|
||||||
|
throw new Exception($"Field {structFieldAccessor.Field} is not defined in struct {structType.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var offsetLabel = GenName("offset");
|
||||||
|
_builder.AppendLine($" %{offsetLabel} =l add {@struct}, {fieldIndex * QbeTypeSize(structFieldAccessor.Type)}");
|
||||||
|
|
||||||
|
var outputLabel = GenName("field");
|
||||||
|
_builder.AppendLine($" %{outputLabel} ={SQT(structFieldAccessor.Type)} load{SQT(structFieldAccessor.Type)} %{offsetLabel}");
|
||||||
|
|
||||||
|
return $"%{outputLabel}";
|
||||||
|
}
|
||||||
|
|
||||||
private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall)
|
private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall)
|
||||||
{
|
{
|
||||||
var outputLabel = GenName();
|
var outputLabel = GenName();
|
||||||
|
|||||||
7
src/compiler/Nub.Lang/Frontend/Parsing/CastNode.cs
Normal file
7
src/compiler/Nub.Lang/Frontend/Parsing/CastNode.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class CastNode(NubType targetType, ExpressionNode expression) : ExpressionNode
|
||||||
|
{
|
||||||
|
public NubType TargetType { get; } = targetType;
|
||||||
|
public ExpressionNode Expression { get; } = expression;
|
||||||
|
}
|
||||||
@@ -304,53 +304,70 @@ public class Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ExpressionNode ParsePrimaryExpression()
|
private ExpressionNode ParsePrimaryExpression()
|
||||||
|
{
|
||||||
|
var token = ExpectToken();
|
||||||
|
switch (token)
|
||||||
{
|
{
|
||||||
var token = ExpectToken();
|
case LiteralToken literal:
|
||||||
switch (token)
|
|
||||||
{
|
{
|
||||||
case LiteralToken literal:
|
return new LiteralNode(literal.Value, literal.Type);
|
||||||
|
}
|
||||||
|
case IdentifierToken identifier:
|
||||||
|
{
|
||||||
|
return ParseExpressionIdentifier(identifier);
|
||||||
|
}
|
||||||
|
case SymbolToken symbolToken:
|
||||||
|
{
|
||||||
|
switch (symbolToken.Symbol)
|
||||||
{
|
{
|
||||||
return new LiteralNode(literal.Value, literal.Type);
|
case Symbol.OpenParen:
|
||||||
}
|
|
||||||
case IdentifierToken identifier:
|
|
||||||
{
|
|
||||||
return ParseExpressionIdentifier(identifier);
|
|
||||||
}
|
|
||||||
case SymbolToken symbolToken:
|
|
||||||
{
|
|
||||||
switch (symbolToken.Symbol)
|
|
||||||
{
|
{
|
||||||
case Symbol.OpenParen:
|
// This is ugly
|
||||||
|
var nextToken = Peek();
|
||||||
|
if (nextToken is { Value: IdentifierToken })
|
||||||
{
|
{
|
||||||
var expression = ParseExpression();
|
var startIndex = _index;
|
||||||
ExpectSymbol(Symbol.CloseParen);
|
var identifierToken = ExpectIdentifier();
|
||||||
return expression;
|
var type = NubType.Parse(identifierToken.Value);
|
||||||
}
|
|
||||||
case Symbol.New:
|
if (TryExpectSymbol(Symbol.CloseParen))
|
||||||
{
|
|
||||||
var type = ParseType();
|
|
||||||
Dictionary<string, ExpressionNode> initializers = [];
|
|
||||||
ExpectSymbol(Symbol.OpenBrace);
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseBrace))
|
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier().Value;
|
var expressionToCast = ParsePrimaryExpression();
|
||||||
ExpectSymbol(Symbol.Assign);
|
return new CastNode(type, expressionToCast);
|
||||||
var value = ParseExpression();
|
|
||||||
initializers.Add(name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StructInitializerNode(type, initializers);
|
_index = startIndex;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
|
var expression = ParseExpression();
|
||||||
|
ExpectSymbol(Symbol.CloseParen);
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
case Symbol.New:
|
||||||
|
{
|
||||||
|
var type = ParseType();
|
||||||
|
Dictionary<string, ExpressionNode> initializers = [];
|
||||||
|
ExpectSymbol(Symbol.OpenBrace);
|
||||||
|
while (!TryExpectSymbol(Symbol.CloseBrace))
|
||||||
{
|
{
|
||||||
throw new Exception($"Unknown symbol: {symbolToken.Symbol}");
|
var name = ExpectIdentifier().Value;
|
||||||
|
ExpectSymbol(Symbol.Assign);
|
||||||
|
var value = ParseExpression();
|
||||||
|
initializers.Add(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new StructInitializerNode(type, initializers);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new Exception($"Unknown symbol: {symbolToken.Symbol}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
throw new Exception($"Unexpected token type {token.GetType().Name}");
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
throw new Exception($"Unexpected token type {token.GetType().Name}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ExpressionNode ParseExpressionIdentifier(IdentifierToken identifier)
|
private ExpressionNode ParseExpressionIdentifier(IdentifierToken identifier)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -245,7 +245,6 @@ public class TypeChecker
|
|||||||
case LiteralNode literal:
|
case LiteralNode literal:
|
||||||
resultType = literal.LiteralType;
|
resultType = literal.LiteralType;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IdentifierNode identifier:
|
case IdentifierNode identifier:
|
||||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||||
{
|
{
|
||||||
@@ -253,23 +252,21 @@ public class TypeChecker
|
|||||||
}
|
}
|
||||||
resultType = varType;
|
resultType = varType;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BinaryExpressionNode binaryExpr:
|
case BinaryExpressionNode binaryExpr:
|
||||||
resultType = TypeCheckBinaryExpression(binaryExpr);
|
resultType = TypeCheckBinaryExpression(binaryExpr);
|
||||||
break;
|
break;
|
||||||
|
case CastNode cast:
|
||||||
|
resultType = TypeCheckCast(cast);
|
||||||
|
break;
|
||||||
case FuncCallExpressionNode funcCallExpr:
|
case FuncCallExpressionNode funcCallExpr:
|
||||||
resultType = TypeCheckFuncCall(funcCallExpr.FuncCall);
|
resultType = TypeCheckFuncCall(funcCallExpr.FuncCall);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StructInitializerNode structInit:
|
case StructInitializerNode structInit:
|
||||||
resultType = TypeCheckStructInitializer(structInit);
|
resultType = TypeCheckStructInitializer(structInit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StructFieldAccessorNode fieldAccess:
|
case StructFieldAccessorNode fieldAccess:
|
||||||
resultType = TypeCheckStructFieldAccess(fieldAccess);
|
resultType = TypeCheckStructFieldAccess(fieldAccess);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}");
|
throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}");
|
||||||
}
|
}
|
||||||
@@ -316,6 +313,13 @@ public class TypeChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NubType TypeCheckCast(CastNode cast)
|
||||||
|
{
|
||||||
|
TypeCheckExpression(cast.Expression);
|
||||||
|
// TODO: Check if castable
|
||||||
|
return cast.TargetType;
|
||||||
|
}
|
||||||
|
|
||||||
private NubType TypeCheckStructInitializer(StructInitializerNode structInit)
|
private NubType TypeCheckStructInitializer(StructInitializerNode structInit)
|
||||||
{
|
{
|
||||||
var structType = structInit.StructType;
|
var structType = structInit.StructType;
|
||||||
|
|||||||
Reference in New Issue
Block a user