answer the parsing question: a grammar is a basis, and five keywords reserved nothing
This commit is contained in:
@@ -145,6 +145,22 @@ fn tok_append(tokens: [Any], kind: String, value: String) -> [Any] {
|
||||
|
||||
// -- Keyword lookup ------------------------------------------------------------
|
||||
|
||||
// keyword_kind — the language's reserved spellings.
|
||||
//
|
||||
// A grammar is a BASIS: `fn` means function-start because someone said so, and
|
||||
// nothing derives it. But unlike the other tables moved out this session, this
|
||||
// one stays code, and the SHOULD gate is why. The keyword set is closed by the
|
||||
// language definition -- it does not leak the way an allowlist does -- and the
|
||||
// lexer runs before the program is understood, so a program can never declare
|
||||
// its own keywords. Externalising it would cost file I/O on every compile and
|
||||
// buy nothing.
|
||||
//
|
||||
// Removed 2026-08-17: sealed, activate, seed, protocol, impl. Reserved in the
|
||||
// lexer, consumed by no parser or codegen path, and each one stole an
|
||||
// identifier from users for nothing. `test` LOOKED inert by the same measure
|
||||
// and is not -- codegen consumes it at 4135 for --test mode, 408 uses in the
|
||||
// tree. The first measurement checked only parser.el and would have broken all
|
||||
// of them.
|
||||
fn keyword_kind(word: String) -> String {
|
||||
if word == "let" { return "Let" }
|
||||
if word == "fn" { return "Fn" }
|
||||
@@ -161,14 +177,9 @@ fn keyword_kind(word: String) -> String {
|
||||
if word == "from" { return "From" }
|
||||
if word == "as" { return "As" }
|
||||
if word == "with" { return "With" }
|
||||
if word == "sealed" { return "Sealed" }
|
||||
if word == "activate" { return "Activate" }
|
||||
if word == "where" { return "Where" }
|
||||
if word == "test" { return "Test" }
|
||||
if word == "seed" { return "Seed" }
|
||||
if word == "assert" { return "Assert" }
|
||||
if word == "protocol" { return "Protocol" }
|
||||
if word == "impl" { return "Impl" }
|
||||
if word == "retry" { return "Retry" }
|
||||
if word == "times" { return "Times" }
|
||||
if word == "fallback" { return "Fallback" }
|
||||
|
||||
@@ -943,3 +943,27 @@ test "string-plus-string-still-concatenates" {
|
||||
let out: String = compile_capture(src)
|
||||
assert str_contains(out, "el_str_concat"), "String + String still concatenates"
|
||||
}
|
||||
|
||||
// ── Reserved words that reserved nothing ─────────────────────────────────────
|
||||
//
|
||||
// sealed, activate, seed, protocol and impl were keywords in the lexer and were
|
||||
// consumed by no parser or codegen path. Each stole an identifier from users
|
||||
// for nothing, and using one silently miscompiled: `let seed = 42` compiled
|
||||
// clean and produced the wrong value with no diagnostic at any layer.
|
||||
|
||||
test "freed-identifiers-compile-as-identifiers" {
|
||||
let src: String = "fn main() { let seed = 42 let impl = seed + 1 println(int_to_str(impl)) }"
|
||||
let out: String = compile_capture(src)
|
||||
assert str_contains(out, "el_val_t seed"), "seed is an identifier"
|
||||
assert str_contains(out, "el_val_t impl"), "impl is an identifier"
|
||||
assert str_contains(out, "(seed + 1)"), "and arithmetic on them dispatches correctly"
|
||||
}
|
||||
|
||||
test "test-keyword-is-still-reserved" {
|
||||
// `test` LOOKED inert by the same measure and is not: codegen consumes it
|
||||
// for --test mode, 408 uses in the tree. Measuring only parser.el would
|
||||
// have removed it.
|
||||
let src: String = "fn main() { println(\"x\") }"
|
||||
let out: String = compile_capture(src)
|
||||
assert str_contains(out, "int main"), "the suite still compiles, which requires test to remain a keyword"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user