Add float to int builtin
This commit is contained in:
@@ -645,7 +645,8 @@ public class QBEGenerator
|
||||
StructFuncCallNode expr => EmitStructFuncCall(expr),
|
||||
StructInitializerNode expr => EmitStructInitializer(expr),
|
||||
UnaryExpressionNode expr => EmitUnaryExpression(expr),
|
||||
SizeCompilerMacroNode expr => $"{SizeOf(expr.TargetType)}",
|
||||
SizeBuiltinNode expr => $"{SizeOf(expr.TargetType)}",
|
||||
FloatToIntBuiltinNode expr => EmitFloatToIntBuiltin(expr),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rValue))
|
||||
};
|
||||
}
|
||||
@@ -1106,6 +1107,31 @@ public class QBEGenerator
|
||||
return result;
|
||||
}
|
||||
|
||||
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToInt)
|
||||
{
|
||||
var value = EmitExpression(floatToInt.Value);
|
||||
|
||||
var method = floatToInt.TargetType.Signed switch
|
||||
{
|
||||
true => floatToInt.ValueType.Width switch
|
||||
{
|
||||
32 => "stosi",
|
||||
64 => "dtosi",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
false => floatToInt.ValueType.Width switch
|
||||
{
|
||||
32 => "stoui",
|
||||
64 => "dtoui",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
}
|
||||
};
|
||||
|
||||
var result = TmpName();
|
||||
_writer.Indented($"{result} {QBEAssign(floatToInt.TargetType)} {method} {value}");
|
||||
return result;
|
||||
}
|
||||
|
||||
private string EmitFuncCall(FuncCallNode funcCall)
|
||||
{
|
||||
var funcPointer = EmitExpression(funcCall.Expression);
|
||||
|
||||
@@ -461,7 +461,7 @@ public sealed class Parser
|
||||
Symbol.OpenBracket => ParseArrayInitializer(startIndex),
|
||||
Symbol.OpenBrace => new StructInitializerSyntax(GetTokens(startIndex), null, ParseStructInitializerBody()),
|
||||
Symbol.Struct => ParseStructInitializer(startIndex),
|
||||
Symbol.At => ParseCompilerMacro(startIndex),
|
||||
Symbol.At => ParseBuiltinFunction(startIndex),
|
||||
_ => throw new ParseException(Diagnostic
|
||||
.Error($"Unexpected symbol '{symbolToken.Symbol}' in expression")
|
||||
.WithHelp("Expected '(', '-', '!', '[' or '{'")
|
||||
@@ -478,7 +478,7 @@ public sealed class Parser
|
||||
return ParsePostfixOperators(expr);
|
||||
}
|
||||
|
||||
private ExpressionSyntax ParseCompilerMacro(int startIndex)
|
||||
private ExpressionSyntax ParseBuiltinFunction(int startIndex)
|
||||
{
|
||||
var name = ExpectIdentifier();
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
@@ -489,7 +489,7 @@ public sealed class Parser
|
||||
{
|
||||
var type = ParseType();
|
||||
ExpectSymbol(Symbol.CloseParen);
|
||||
return new SizeCompilerMacroSyntax(GetTokens(startIndex), type);
|
||||
return new SizeBuiltinSyntax(GetTokens(startIndex), type);
|
||||
}
|
||||
case "interpret":
|
||||
{
|
||||
@@ -497,11 +497,19 @@ public sealed class Parser
|
||||
ExpectSymbol(Symbol.Comma);
|
||||
var expression = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseParen);
|
||||
return new InterpretCompilerMacroSyntax(GetTokens(startIndex), type, expression);
|
||||
return new InterpretBuiltinSyntax(GetTokens(startIndex), type, expression);
|
||||
}
|
||||
case "floatToInt":
|
||||
{
|
||||
var type = ParseType();
|
||||
ExpectSymbol(Symbol.Comma);
|
||||
var expression = ParseExpression();
|
||||
ExpectSymbol(Symbol.CloseParen);
|
||||
return new FloatToIntBuiltinSyntax(GetTokens(startIndex), type, expression);
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ParseException(Diagnostic.Error("Unknown compiler macro").At(name).Build());
|
||||
throw new ParseException(Diagnostic.Error($"Unknown builtin {name.Value}").At(name).Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ public record StructInitializerSyntax(List<Token> Tokens, TypeSyntax? StructType
|
||||
|
||||
public record DereferenceSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
||||
|
||||
public record SizeCompilerMacroSyntax(List<Token> Tokens, TypeSyntax Type) : ExpressionSyntax(Tokens);
|
||||
public record SizeBuiltinSyntax(List<Token> Tokens, TypeSyntax Type) : ExpressionSyntax(Tokens);
|
||||
|
||||
public record InterpretCompilerMacroSyntax(List<Token> Tokens, TypeSyntax Type, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
||||
public record InterpretBuiltinSyntax(List<Token> Tokens, TypeSyntax Type, ExpressionSyntax Target) : ExpressionSyntax(Tokens);
|
||||
|
||||
public record FloatToIntBuiltinSyntax(List<Token> Tokens, TypeSyntax Type, ExpressionSyntax Value) : ExpressionSyntax(Tokens);
|
||||
@@ -78,4 +78,6 @@ public record ConvertIntNode(NubType Type, ExpressionNode Value, NubIntType Valu
|
||||
|
||||
public record ConvertFloatNode(NubType Type, ExpressionNode Value, NubFloatType ValueType, NubFloatType TargetType) : RValueExpressionNode(Type);
|
||||
|
||||
public record SizeCompilerMacroNode(NubType Type, NubType TargetType) : RValueExpressionNode(Type);
|
||||
public record SizeBuiltinNode(NubType Type, NubType TargetType) : RValueExpressionNode(Type);
|
||||
|
||||
public record FloatToIntBuiltinNode(NubType Type, ExpressionNode Value, NubFloatType ValueType, NubIntType TargetType) : RValueExpressionNode(Type);
|
||||
@@ -305,8 +305,9 @@ public sealed class TypeChecker
|
||||
LiteralSyntax expression => CheckLiteral(expression, expectedType),
|
||||
StructFieldAccessSyntax expression => CheckStructFieldAccess(expression),
|
||||
StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType),
|
||||
InterpretCompilerMacroSyntax expression => CheckExpression(expression.Target) with { Type = ResolveType(expression.Type) },
|
||||
SizeCompilerMacroSyntax expression => new SizeCompilerMacroNode(new NubIntType(false, 64), ResolveType(expression.Type)),
|
||||
InterpretBuiltinSyntax expression => CheckExpression(expression.Target) with { Type = ResolveType(expression.Type) },
|
||||
SizeBuiltinSyntax expression => new SizeBuiltinNode(new NubIntType(false, 64), ResolveType(expression.Type)),
|
||||
FloatToIntBuiltinSyntax expression => CheckFloatToInt(expression),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||
};
|
||||
|
||||
@@ -334,6 +335,29 @@ public sealed class TypeChecker
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build());
|
||||
}
|
||||
|
||||
private FloatToIntBuiltinNode CheckFloatToInt(FloatToIntBuiltinSyntax expression)
|
||||
{
|
||||
var value = CheckExpression(expression.Value);
|
||||
if (value.Type is not NubFloatType sourceFloatType)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error("Source type of float to int conversion must be an float")
|
||||
.At(expression.Value)
|
||||
.Build());
|
||||
}
|
||||
|
||||
var targetType = ResolveType(expression.Type);
|
||||
if (targetType is not NubIntType targetIntType)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error("Target type of float to int conversion must be an integer")
|
||||
.At(expression.Type)
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new FloatToIntBuiltinNode(targetIntType, value, sourceFloatType, targetIntType);
|
||||
}
|
||||
|
||||
private AddressOfNode CheckAddressOf(AddressOfSyntax expression)
|
||||
{
|
||||
var target = CheckExpression(expression.Target);
|
||||
@@ -652,10 +676,25 @@ public sealed class TypeChecker
|
||||
{
|
||||
case LiteralKind.Integer:
|
||||
{
|
||||
var type = expectedType as NubIntType ?? new NubIntType(true, 64);
|
||||
return type.Signed
|
||||
? new IntLiteralNode(type, long.Parse(expression.Value))
|
||||
: new UIntLiteralNode(type, ulong.Parse(expression.Value));
|
||||
if (expectedType is NubIntType intType)
|
||||
{
|
||||
return intType.Signed
|
||||
? new IntLiteralNode(intType, long.Parse(expression.Value))
|
||||
: new UIntLiteralNode(intType, ulong.Parse(expression.Value));
|
||||
}
|
||||
|
||||
if (expectedType is NubFloatType floatType)
|
||||
{
|
||||
return floatType.Width switch
|
||||
{
|
||||
32 => new Float32LiteralNode(floatType, float.Parse(expression.Value)),
|
||||
64 => new Float64LiteralNode(floatType, double.Parse(expression.Value)),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
var type = new NubIntType(true, 64);
|
||||
return new IntLiteralNode(type, long.Parse(expression.Value));
|
||||
}
|
||||
case LiteralKind.Float:
|
||||
{
|
||||
|
||||
@@ -6,11 +6,30 @@ module "main"
|
||||
extern "main" func main(args: []cstring): i64
|
||||
{
|
||||
raylib::InitWindow(1600, 900, "Hi from nub-lang")
|
||||
raylib::SetTargetFPS(240)
|
||||
|
||||
let x: i32 = 0
|
||||
let y: i32 = 0
|
||||
|
||||
let width: i32 = 100
|
||||
let height: i32 = 100
|
||||
|
||||
let direction: raylib::Vector2 = { x = 1 y = 1 }
|
||||
|
||||
let bgColor: raylib::Color = { r = 0 g = 0 b = 0 a = 255 }
|
||||
let color: raylib::Color = { r = 255 g = 255 b = 255 a = 255 }
|
||||
|
||||
while !raylib::WindowShouldClose()
|
||||
{
|
||||
raylib::BeginDrawing()
|
||||
{
|
||||
raylib::ClearBackground(bgColor);
|
||||
raylib::DrawRectangle(x, y, width, height, color)
|
||||
}
|
||||
raylib::EndDrawing()
|
||||
|
||||
x = x + @floatToInt(i32, direction.x)
|
||||
y = y + @floatToInt(i32, direction.y)
|
||||
}
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user