Skip to content

support {{ }} brace escaping in string literals#198

Merged
kacy merged 1 commit into
mainfrom
feat/brace-escaping
May 23, 2026
Merged

support {{ }} brace escaping in string literals#198
kacy merged 1 commit into
mainfrom
feat/brace-escaping

Conversation

@kacy
Copy link
Copy Markdown
Owner

@kacy kacy commented May 23, 2026

summary

literal braces in string literals previously required chr(123)/chr(125),
because a { always opened interpolation. this adds the universal doubling
convention: {{ emits a literal { and }} emits a literal }, while a
single {expr} still interpolates as before.

print("plain {{literal}} braces")   # -> plain {literal} braces
print("hello {name}")               # -> hello world
print("json-ish {{\"k\": 1}}")      # -> json-ish {"k": 1}

two coordinated changes:

  • the lexer skips {{ pairs when scanning a string literal to decide whether
    it interpolates (and inside trailing segments of an interpolated string)
  • the ir consumer collapses {{/}} to single braces in the string table —
    the same decode pass that already handles \n, \t, \\, etc.

a single { still means interpolation, so existing code is unaffected
(a lone literal { never worked before anyway).

the regenerated self-host/ir_driver is included so the change takes effect
on the native build path, matching how prior frontend changes are committed.

what was tested

  • new regression tests/cases/test_brace_escaping.pith covering plain {{}},
    interpolation, mixed literal+interp, lone }}, json-ish, and empty {}
  • full Cranelift regression suite (91 passed, 0 failed)
  • self-hosted examples (83) and self-hosted regressions — all passing
  • bootstrap fixed-point verification

design notes

}} needs no lexer change: a single } is already literal everywhere outside
an interpolation expression, so doubled close braces survive into the string
table and are collapsed there alongside {{.

literal braces previously required chr(123)/chr(125) because { always
opened interpolation. adopt the universal doubling convention: {{ -> {
and }} -> }, while a single {expr} still interpolates.

the lexer now skips {{ pairs when deciding whether a string interpolates,
and the ir consumer collapses {{/}} to single braces in the string table
(the same choke point that decodes \n, \t, etc).
@kacy kacy merged commit 6869e50 into main May 23, 2026
2 checks passed
@kacy kacy deleted the feat/brace-escaping branch May 23, 2026 14:54
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