Skip to content

Implement interpolated string function calls#2261

Draft
rofrankel wants to merge 6 commits intoluau-lang:masterfrom
rofrankel:interp-string-function-calls
Draft

Implement interpolated string function calls#2261
rofrankel wants to merge 6 commits intoluau-lang:masterfrom
rofrankel:interp-string-function-calls

Conversation

@rofrankel
Copy link

@rofrankel rofrankel commented Feb 24, 2026

Summary

  • Implement the interpolated string function calls RFC, gated behind the LuauInterpStringFunctionCalls feature flag
  • Desugar parentheses-free interpolated string calls (e.g. f hello {x} ) into 2-argument function calls: f("hello {x}", {x})
  • If the interpolated string has no expressions, desugar to a single string argument (same as f "hello")
  • Add two new core library functions: string.interpparse (extracts expression names from a template) and string.interp (renders a template with values, supporting both sequential and associative tables)

Changes

  • Parser (Ast/include/Luau/Parser.h, Ast/src/Parser.cpp): Add parseInterpStringCall which constructs the template string and values table. Template uses doubled braces ({{/}}) to escape literal braces from \{ in source.
  • Library functions (VM/src/lstrlib.cpp): Implement string.interpparse(template) -> {string} and string.interp(template, values) -> string
  • Type definitions (Analysis/src/BuiltinDefinitions.cpp): Add type signatures for both new functions
  • Parser tests (tests/Parser.test.cpp): 7 test cases covering simple, expressions, method calls, multiple expressions, complex expressions, flag-off behavior, and chaining
  • Compiler tests (tests/Compiler.test.cpp): 3 test cases verifying bytecode output
  • Conformance test (tests/conformance/stringinterpcall.luau): End-to-end runtime tests for call desugaring, string.interpparse, string.interp, escaped braces, side effects, and the currying/integration patterns from the RFC
  • Autocomplete test (tests/Autocomplete.test.cpp): Updated string completion count for new library functions

Test plan

  • All 10 new unit tests pass (7 parser + 3 compiler)
  • New conformance test passes end-to-end
  • Full unit test suite passes (413/414, only pre-existing RecursionParseFunctionArguments crash)
  • Full conformance test suite passes (236/236)
  • Full CLI test suite passes (66/66)

Desugar parentheses-free interpolated string calls into 3-argument function calls: (template, values, offsets). Gated behind the LuauInterpStringFunctionCalls feature flag.

Co-authored-by: Cursor <cursoragent@cursor.com>
@rofrankel rofrankel marked this pull request as draft February 24, 2026 19:37
Simplify call desugaring from 3 args (template, values, offsets) to 2 args (template, values) per updated RFC. Add string.interpparse and string.interp core library functions for extracting expression names and rendering templates at runtime. Template strings use doubled braces ({{ / }}) to escape literal braces from \{ in source.

Made-with: Cursor
Replace character-by-character luaL_addchar with luaL_addlstring for runs of literal text between expression boundaries.

Made-with: Cursor
The logInfo example now returns a key-value table mapping expression names to values, and demonstrates the same function working with both paren-free (sequential values) and parenthesized (associative values) calling conventions.

Made-with: Cursor
Since Luau interns strings, repeated interpparse calls with the same template (e.g. from a hot logging path) return the same frozen table in O(1) via registry-based cache lookup. Cache miss falls through to normal parsing.

Made-with: Cursor
When the compiler encounters a desugared interpolated string call, it records the template's constant index and expression name strings as trailing metadata in the bytecode. The VM loader reads this metadata after loading all protos and populates the interpparse registry cache with frozen tables, eliminating the first-call parsing cost for string.interpparse on compile-time-known templates.

Made-with: Cursor
@Bottersnike
Copy link

Bottersnike commented Feb 27, 2026

Aaaand I accidentally posted that on the language PR not the RFC PR. Sorry!

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.

2 participants