Skip to content

[patch] Keep string, float and long literals through a YAML round trip - #108

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/yaml-literal-roundtrip-83
Sep 28, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/yaml-literal-roundtrip-83

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #83

What changed

String literals. YamlSerializer let the emitter choose whether to quote a string. It already quoted true and 123, but it wrote null, Null and ~ bare, so they came back as ''. The serializer is now built with WithQuotingNecessaryStrings(), which quotes any string the reader would take for a non-string scalar.

Float and long literals. The issue offered two options: support these end to end, or remove Literal.SingleValue and Literal.BigNumberValue. Removing them would break the public API, so this PR supports them.

  • YamlSerializer has a case for LiteralExpression<float> and LiteralExpression<long>. Before, both were written as {}.
  • YamlDeserializer reads Literal<Single> and Literal<Int64>. A float is parsed as a float directly, which avoids rounding twice. It also accepts the .inf, -.inf and .nan spellings: the non-finite parsing moved out of TryParseDouble into a shared TryParseNonFinite.
  • In LanguageGeneratorBase:
    • TryGenerateCommonNode writes both types. A new FormatSingle formats a float as a float, so 0.1f stays 0.1 instead of widening to 0.10000000149011612. It adds .0 to a whole number the same way FormatDouble does.
    • CanGenerateStandardNodes and LeadingSign know both types, so -(-5000000000) is not written as --.
  • CSharpGenerator adds the f and L suffixes.
  • GoGenerator treats both as compile-time values and infers float32 and int64 for them.

Not changed: the graph editor (Coder.Graph/AstFields, AstSchema) still has no editable field for float or long literals. That is a separate UI change. This PR is about data loss on save and load.

Tests

New file: Coder.Test/Serialization/LiteralRoundTripTests.cs.

  • String round trip for null, Null, ~, true, False, 123, -4.5, 1e3, .inf, .nan, the empty string and plain text.
  • Float round trip for finite, whole-number, MaxValue and non-finite values.
  • Long round trip, including MaxValue and MinValue, and as a variable initialiser.
  • All seven generators write float and long literals. C# writes the suffixes, a whole-number float keeps .0, and a negated negative long doesn't fuse its signs.

With the Coder/ changes reverted, 19 of the 28 new cases fail. The 9 that pass are strings the emitter already quoted. With the fix, the full suite passes (962/962) and dotnet build Coder.sln reports no errors.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YLYtHwwqdY3Tk9vpkwT6Sw


Generated by Claude Code

A string literal whose text YAML reads as another scalar (null, ~) was
written bare and came back as ''. The serializer now quotes any string
the reader would take for a non-string.

Float and long literals had no serializer case, so they were written as
{} and read back as nothing, and every generator threw for them. They
now round-trip through the serializer and deserializer, and the shared
generator path, C# (f/L suffixes) and Go's type inference know them.

Fixes #83

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YLYtHwwqdY3Tk9vpkwT6Sw
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit ddd80c4 into main Sep 28, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the fix/yaml-literal-roundtrip-83 branch September 28, 2026 01:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

YAML round-trip loses literal data: string "null" becomes '', float/long literals serialize to {} and deserialize to null

2 participants