Skip to content

Lua: quote member and constant names that are Lua keywords - #2

Merged
leshy merged 1 commit into
masterfrom
fix/lua-reserved-word-fields
Jul 30, 2026
Merged

Lua: quote member and constant names that are Lua keywords#2
leshy merged 1 commit into
masterfrom
fix/lua-reserved-word-fields

Conversation

@leshy

@leshy leshy commented Jul 30, 2026

Copy link
Copy Markdown
Member

The Lua backend emits every member and constant with dot notation, so a type with a field named after a Lua keyword produces a file that does not parse.

ROS's geographic_msgs/RouteSegment has fields named start and end. The generated RouteSegment.lua contained:

obj.end = nil                                     -- new()
table.insert(buf_table, self.end:_encode_one())   -- _encode_one()
obj.end = uuid_msgs_UniqueID._decode_one(data)    -- _decode_one()

luac -p rejects all three. Every other backend is fine — end is not reserved in Python, C++, Java, C#, TypeScript or Rust.

Needed by dimensionalOS/dimos-lcm#24, which adds geographic_msgs.

Fix

Emit t["end"] instead of t.end when the name is a Lua reserved word. One helper, lua_member_ref(), applied at every site that turns an LCM name into a Lua identifier:

  • member access in new(), _encode_one(), _decode_one(), and the array-element accessors
  • array length references — loop bounds (for i0 = 1, self["end"] do) and string.format widths / data:read() arguments, since a length field can itself be keyword-named
  • constants (Struct["end"] = 1)

Verification

Against the 190 types in dimos-lcm, generated with the patched and unpatched binary using an identical invocation:

  • geographic_msgs/RouteSegment.lua is the only file whose output differs — every other byte is identical, so this cannot regress existing consumers
  • all 190 files now pass luac -p (before: 189)
  • RouteSegment round-trips through encode/decode with the end field intact — a nested UniqueID in end decodes back to the value it was encoded with, alongside start and a variable-length props array

git clang-format reports no changes on the diff.

🤖 Generated with Claude Code

The Lua backend emitted every member and constant with dot notation, so
a type with a field named after a Lua keyword produced a file that does
not parse. ROS's geographic_msgs.RouteSegment has fields named "start"
and "end"; the generated RouteSegment.lua contained `obj.end = nil` and
was rejected by luac.

Emit `t["end"]` instead of `t.end` when the name is a reserved word.
This covers member access in _encode_one/_decode_one/new, the array
length references used in loop bounds and string.format widths, and
constants.

Output is unchanged for every name that is not a Lua keyword: of the 190
types in dimos-lcm, RouteSegment.lua is the only file whose generated
Lua differs, and it now round-trips through encode/decode with the "end"
field intact.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@leshy
leshy merged commit 553171c into master Jul 30, 2026
7 checks passed
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.

1 participant