What's wrong
LanguageGeneratorBase writes a LiteralExpression<double> as doubleLit.Value.ToString(CultureInfo.InvariantCulture) (Coder/Languages/LanguageGeneratorBase.cs:~132-134). As a result, 2.0 is written as 2. The C# generator overrides this and adds a d suffix. The C, C++, Go, Rust, Python and JavaScript generators use the base behaviour.
Failure scenarios
Input: VariableDeclaration("x", "double", Binary(Literal.DecimalValue(1.0), Divide, Literal.DecimalValue(2.0)))
- C / C++: emits
double x = (1 / 2);. This is integer division, so x is 0, not 0.5.
- Go: emits
var x float64 = (1 / 2). This is constant integer division, so x is 0.
- Rust: emits
let mut x: f64 = (1 / 2);, which rustc rejects with E0308 (mismatched types).
- Inferred locals:
2.0 becomes k := 2, auto k = 2; or let mut k = 2;, which types the variable as an integer. A later k = k * 0.5 then fails to compile in Go.
Non-finite values have their own problems:
double.PositiveInfinity is emitted as the bare text Infinity in every target (Infinityd in C#).
- After a YAML round trip it gets worse. The serializer writes
.inf, and YamlDeserializer (~line 1264) cannot parse that, so the declaration silently loses its initializer and becomes double inf;.
Suggested fix
- Format with
"R" (round-trip) and append .0 when the text contains none of ., E or e.
- Spell infinity and NaN for each language:
INFINITY/NAN (C/C++), f64::INFINITY (Rust), math.Inf(1) (Go), float('inf') (Python), Infinity (JS), double.PositiveInfinity (C#).
- Accept
.inf, -.inf and .nan in the YAML deserializer.
- Add per-language tests that
1.0 / 2.0 emits a floating-point expression.
What's wrong
LanguageGeneratorBasewrites aLiteralExpression<double>asdoubleLit.Value.ToString(CultureInfo.InvariantCulture)(Coder/Languages/LanguageGeneratorBase.cs:~132-134). As a result,2.0is written as2. The C# generator overrides this and adds adsuffix. The C, C++, Go, Rust, Python and JavaScript generators use the base behaviour.Failure scenarios
Input:
VariableDeclaration("x", "double", Binary(Literal.DecimalValue(1.0), Divide, Literal.DecimalValue(2.0)))double x = (1 / 2);. This is integer division, so x is 0, not 0.5.var x float64 = (1 / 2). This is constant integer division, so x is 0.let mut x: f64 = (1 / 2);, which rustc rejects with E0308 (mismatched types).2.0becomesk := 2,auto k = 2;orlet mut k = 2;, which types the variable as an integer. A laterk = k * 0.5then fails to compile in Go.Non-finite values have their own problems:
double.PositiveInfinityis emitted as the bare textInfinityin every target (Infinitydin C#)..inf, andYamlDeserializer(~line 1264) cannot parse that, so the declaration silently loses its initializer and becomesdouble inf;.Suggested fix
"R"(round-trip) and append.0when the text contains none of.,Eore.INFINITY/NAN(C/C++),f64::INFINITY(Rust),math.Inf(1)(Go),float('inf')(Python),Infinity(JS),double.PositiveInfinity(C#)..inf,-.infand.nanin the YAML deserializer.1.0 / 2.0emits a floating-point expression.