Phase 7d: string interpolation text {expr} text
The readable way to build strings, as you noted `{a} {b}` beats `a + " " + b`.
A backtick string embeds any expression in `{…}` and desugars to the Phase-7c
`+` chain, wrapping each hole in `str(...)`:
`hello {name}, n={count + 1}`
== "hello " + name + ", n=" + str(count + 1)
- Lexer: a backtick captures its content raw as TK_INTERP.
- Parser: parse_interp splits literal runs from `{…}` holes (brace-depth aware,
`{{`/`}}` escape to literal braces), re-lexes each hole as a full expression
(save/restore toks/pi like an import), and folds it all into E_BIN(+) nodes —
so no new AST or runtime beyond the existing concat.
- str(x): a string passes through; int/bool/fixed convert via a small emitted
@fn_int_str prelude (digits from the end of a buffer, '-' for negatives),
emitted once into any program that uses it.
examples/strings.ludic gains interpolation cases (now prints 1..7); the smoke
covers it. Grammar + ludic_syntax.h tokenize backtick strings (holes highlighted
as embedded code). LANGUAGE.md documents it as the preferred form.
Reseeded (22530 lines); C-free fixpoint holds; goldens identical; 18/18; vocab +
doc-fences clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
a997e34b2d
commit
ad63f09d53
13 changed files with 4748 additions and 3962 deletions
|
|
@ -126,6 +126,12 @@ fn emit_call(e: Node) -> Val {
|
|||
if (name == "quit") { emit(" store i32 0, ptr @L_running\n"); return val("0", "void") }
|
||||
if (name == "len") { return emit_len(e) }
|
||||
if (name == "push") { return emit_push(e) }
|
||||
if (name == "str") { # str(x): int/bool/fixed -> text, a string passes through
|
||||
let a = emit_expr(e.kids[0])
|
||||
if (llty(a.ty) == "ptr") { return a }
|
||||
g_uses_intstr = true
|
||||
return val(emit_bind(("call ptr @fn_int_str(i32 " + (a.code + ")"))), "str")
|
||||
}
|
||||
if (name == "fx") { let a = emit_expr(e.kids[0]); return val(emit_bind(("shl i32 " + (a.code + ", 16"))), "fixed") }
|
||||
if (name == "flr") { let a = emit_expr(e.kids[0]); return val(emit_bind(("ashr i32 " + (a.code + ", 16"))), "int") }
|
||||
if is_intrinsic(name) { return emit_intrinsic(name, e) }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue