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
16
LANGUAGE.md
16
LANGUAGE.md
|
|
@ -584,7 +584,21 @@ are **`& | ^ << >> ~`** (`>>` is a logical/unsigned shift).
|
|||
**Strings are values.** `a + b` concatenates two strings, and `a == b` / `a != b`
|
||||
compare them **by content** (not by pointer). `"go" + dir == "goleft"` works as
|
||||
written. (Under the hood these call a small emitted string runtime; a `==`/`!=`
|
||||
against `null` is still a pointer test.) `expr with { field: … }`
|
||||
against `null` is still a pointer test.)
|
||||
|
||||
**Interpolation is the readable way to build them.** A backtick string
|
||||
`` `text {expr} text` `` embeds any expression in `{…}` — numbers, bools and
|
||||
`fixed` values become text automatically, strings pass through — and desugars to
|
||||
the `+` chain above:
|
||||
|
||||
```ludic
|
||||
# doc-check: skip — illustrative interpolation
|
||||
let msg = `hello {name}, you have {count + 1} messages`
|
||||
# == "hello " + name + ", you have " + str(count + 1) + " messages"
|
||||
```
|
||||
|
||||
`str(x)` is the same conversion on its own. Write a literal brace as `{{` / `}}`.
|
||||
`expr with { field: … }`
|
||||
is not implemented; records appear only in `spawn`. Char literals (`'w'`) are
|
||||
`int` code points; colors are hex ints (`0xff8800`). `null` is the null-pointer
|
||||
literal; test any pointer/record/slice with `x == null` / `x != null` (an unset
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue