Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating point constant expression #189

Merged
merged 11 commits into from
Aug 17, 2022
1 change: 1 addition & 0 deletions Cesium.CodeGen.Tests/CodeGenMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public void VarArgMainDoesNotCompile2() => DoesNotCompile<WipException>(
[Fact] public Task Parameter1Get() => DoTest("int foo(int x){ return x + 1; }");
[Fact] public Task Parameter5Get() => DoTest("int foo(int a, int b, int c, int d, int e){ return e + 1; }");
[Fact] public Task CharConstTest() => DoTest("int main() { char x = '\\t'; return 42; }");
[Fact] public Task DoubleConstTest() => DoTest("int main() { double x = 1.5; return 42; }");

[Fact] public Task MultiDeclaration() => DoTest("int main() { int x = 0, y = 2 + 2; }");

Expand Down
1 change: 1 addition & 0 deletions Cesium.CodeGen.Tests/CodeGenTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Cesium.CodeGen.Tests;

[UseInvariantCulture]
public abstract class CodeGenTestBase : VerifyTestBase
{
protected static AssemblyDefinition GenerateAssembly(TargetRuntimeDescriptor? runtime, params string[] sources)
Expand Down
35 changes: 35 additions & 0 deletions Cesium.CodeGen.Tests/UseInvariantCultureAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
using Xunit.Sdk;


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class UseInvariantCultureAttribute : BeforeAfterTestAttribute
{
CultureInfo originalCulture = null!;
CultureInfo originalUICulture = null!;

public override void Before(MethodInfo methodUnderTest)
{
originalCulture = Thread.CurrentThread.CurrentCulture;
originalUICulture = Thread.CurrentThread.CurrentUICulture;

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

CultureInfo.CurrentCulture.ClearCachedData();
CultureInfo.CurrentUICulture.ClearCachedData();
}

public override void After(MethodInfo methodUnderTest)
{
Thread.CurrentThread.CurrentCulture = originalCulture;
Thread.CurrentThread.CurrentUICulture = originalUICulture;

CultureInfo.CurrentCulture.ClearCachedData();
CultureInfo.CurrentUICulture.ClearCachedData();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
System.Int32 <Module>::main()
Locals:
System.Double V_0
IL_0000: ldc.r8 1.5
IL_0009: stloc.0
IL_000a: ldc.i4.s 42
IL_000c: ret
1 change: 1 addition & 0 deletions Cesium.CodeGen/Ir/Expressions/ConstantExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ private static IConstant GetConstant(Ast.ConstantExpression expression)
CTokenType.IntLiteral => new IntegerConstant(constant.Text),
CTokenType.CharLiteral => new CharConstant(constant.Text),
CTokenType.StringLiteral => new StringConstant(constant),
CTokenType.FloatLiteral => new FloatingPointConstant(constant.Text),
_ => throw new WipException(228, $"Constant of kind {constant.Kind} is not supported.")
};
}
Expand Down
28 changes: 28 additions & 0 deletions Cesium.CodeGen/Ir/Expressions/Constants/FloatingPointConstant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Globalization;
using Cesium.CodeGen.Contexts;
using Cesium.CodeGen.Ir.Types;
using Cesium.Core;
using Mono.Cecil.Cil;

namespace Cesium.CodeGen.Ir.Expressions.Constants;

internal class FloatingPointConstant : IConstant
{
private readonly double _value;

public FloatingPointConstant(string value)
{
if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out _value))
throw new CompilationException($"Cannot parse a double literal: {value}.");
}

public void EmitTo(IDeclarationScope scope)
{
// TODO[#248]: This should support `float` as well.
scope.Method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldc_R8, _value));
}

public IType GetConstantType(IDeclarationScope scope) => scope.CTypeSystem.Double;

public override string ToString() => $"double: {_value}";
}
2 changes: 2 additions & 0 deletions Cesium.CodeGen/Ir/Types/CTypeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ internal class CTypeSystem
public IType Char { get; } = new PrimitiveType(PrimitiveTypeKind.Char);
public IType Int { get; } = new PrimitiveType(PrimitiveTypeKind.Int);
public IType CharPtr { get; } = new PrimitiveType(PrimitiveTypeKind.Char).MakePointerType();
public IType Float { get; } = new PrimitiveType(PrimitiveTypeKind.Float);
public IType Double { get; } = new PrimitiveType(PrimitiveTypeKind.Double);
}