Summary
The ML flavor layout lexer terminates a string literal at the first raw newline, so a multi-line string literal that the Default flavor accepts fails to lex in .ospml. This is a cross-flavor parity gap: the same string content must be respelled with \n escapes in ML.
Reproduction
multiline.ospml:
ddl () =
"CREATE TABLE sales (
id INTEGER PRIMARY KEY,
product TEXT
);"
print "${ddl ()}"
$ osprey multiline.ospml --run
multiline.ospml:2:4: unterminated string literal
multiline.ospml:5:1: unexpected character ';'
multiline.ospml:5:2: unterminated string literal
multiline.ospml:3:2: inconsistent indentation does not match any enclosing block
...
The Default-flavor twin lexes and runs fine:
fn ddl() = "CREATE TABLE sales (
id INTEGER PRIMARY KEY,
product TEXT
);"
print(ddl())
Workaround
Spell the newlines as \n in one single-line string ("CREATE TABLE sales (\n id ...\n);"). Produces byte-identical output, but the two flavor sources read differently for the same literal — undercuts the "twin" story for any example with embedded multi-line text (e.g. SQL, JSON, templates).
Expected
The layout lexer should let a "..." (and presumably ${...} interpolation) span newlines: bracket depth already suppresses layout inside (...), and string scanning should likewise consume newlines until the closing quote rather than emitting a NEWLINE/unterminated string literal. Most layout languages (Haskell, F#) allow multi-line string literals.
Notes
- Frontend:
crates/osprey-syntax/src/ml/lexer.rs (string scanning vs. the offside-rule newline handling).
- Surfaced while authoring
examples/wasm/studio.ospml (the ML twin of the WASM SQLite demo), where the SQL schema/queries are naturally multi-line.
- ML frontend is in active development (spec 0024), so filing as feedback toward cross-flavor parity.
Environment
- Branch:
prototyping (ML-flavor frontend work)
Summary
The ML flavor layout lexer terminates a string literal at the first raw newline, so a multi-line string literal that the Default flavor accepts fails to lex in
.ospml. This is a cross-flavor parity gap: the same string content must be respelled with\nescapes in ML.Reproduction
multiline.ospml:The Default-flavor twin lexes and runs fine:
Workaround
Spell the newlines as
\nin one single-line string ("CREATE TABLE sales (\n id ...\n);"). Produces byte-identical output, but the two flavor sources read differently for the same literal — undercuts the "twin" story for any example with embedded multi-line text (e.g. SQL, JSON, templates).Expected
The layout lexer should let a
"..."(and presumably${...}interpolation) span newlines: bracket depth already suppresses layout inside(...), and string scanning should likewise consume newlines until the closing quote rather than emitting a NEWLINE/unterminated string literal. Most layout languages (Haskell, F#) allow multi-line string literals.Notes
crates/osprey-syntax/src/ml/lexer.rs(string scanning vs. the offside-rule newline handling).examples/wasm/studio.ospml(the ML twin of the WASM SQLite demo), where the SQL schema/queries are naturally multi-line.Environment
prototyping(ML-flavor frontend work)