Phase 5: anchor the editor vocabulary to the compiler
check-vocabulary.py now extracts the keywords selfhost/parse*.ludic actually dispatches on and requires the header's declaration/clause keywords to be a subset (LUDIC_KW_RESERVED exempts documented-but-unimplemented scene/layer/on/ start, itself checked so an implemented reserved word must be promoted). Closes the highlighted-but-unparsed loop against the real compiler; verified it catches an injected bogus keyword. Reconciled the drift it exposed across ludic_syntax.h, JetBrains, TextMate, and emacs: dropped scene/layer/on/start (->RESERVED), the never-implemented needs/uses/requires/ensures/invariant/effects clauses, and the retired edge/export/pure prefixes; added enum/main. @annotations highlight generically. Tooling-only (no seed change): test.sh 14/14, check-vocabulary + test-tools 28/0. Phases 1-5 complete. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f87964c5f7
commit
9585405dc0
8 changed files with 426 additions and 64 deletions
|
|
@ -11,12 +11,11 @@
|
|||
;;; Code:
|
||||
|
||||
(defconst ludic--declaration-keywords
|
||||
'("game" "module" "import" "component" "struct" "archetype" "enum" "ui" "scene" "layer"
|
||||
"const" "var" "fn" "extern" "system" "start" "on"))
|
||||
'("game" "module" "import" "component" "struct" "archetype" "enum" "ui"
|
||||
"const" "var" "fn" "extern" "system" "main"))
|
||||
|
||||
(defconst ludic--clause-keywords
|
||||
'("phase" "query" "reads" "writes" "needs" "uses"
|
||||
"requires" "ensures" "invariant" "effects"))
|
||||
'("phase" "query" "reads" "writes"))
|
||||
|
||||
(defconst ludic--statement-keywords
|
||||
'("let" "return" "if" "else" "when" "while" "for" "in" "spawn" "despawn"
|
||||
|
|
|
|||
|
|
@ -41,12 +41,11 @@ object LudicTokens {
|
|||
*/
|
||||
object LudicVocabulary {
|
||||
val DECL = setOf(
|
||||
"game", "module", "import", "component", "struct", "archetype", "enum", "ui", "scene", "layer",
|
||||
"const", "var", "fn", "extern", "system", "start", "on"
|
||||
"game", "module", "import", "component", "struct", "archetype", "enum", "ui",
|
||||
"const", "var", "fn", "extern", "system", "main"
|
||||
)
|
||||
val CLAUSE = setOf(
|
||||
"phase", "query", "reads", "writes", "needs", "uses",
|
||||
"requires", "ensures", "invariant", "effects"
|
||||
"phase", "query", "reads", "writes"
|
||||
)
|
||||
val STMT = setOf(
|
||||
"let", "return", "if", "else", "when", "while", "for", "in", "spawn", "despawn",
|
||||
|
|
|
|||
|
|
@ -75,35 +75,25 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(scene)\\s+([A-Za-z_][A-Za-z0-9_]*)(\\s+start)?",
|
||||
"captures": {
|
||||
"1": { "name": "storage.type.scene.ludic" },
|
||||
"2": { "name": "entity.name.type.scene.ludic" },
|
||||
"3": { "name": "keyword.other.start.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(layer|ui)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"match": "\\b(ui)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
"1": { "name": "storage.type.ludic" },
|
||||
"2": { "name": "entity.name.type.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(edge\\s+)?(system)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"match": "\\b(system)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
"1": { "name": "storage.modifier.edge.ludic" },
|
||||
"2": { "name": "storage.type.system.ludic" },
|
||||
"3": { "name": "entity.name.function.system.ludic" }
|
||||
"1": { "name": "storage.type.system.ludic" },
|
||||
"2": { "name": "entity.name.function.system.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(export\\s+|pure\\s+)?(extern\\s+)?(fn)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"match": "\\b(extern\\s+)?(fn)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
"1": { "name": "storage.modifier.ludic" },
|
||||
"2": { "name": "storage.modifier.extern.ludic" },
|
||||
"3": { "name": "storage.type.function.ludic" },
|
||||
"4": { "name": "entity.name.function.ludic" }
|
||||
"1": { "name": "storage.modifier.extern.ludic" },
|
||||
"2": { "name": "storage.type.function.ludic" },
|
||||
"3": { "name": "entity.name.function.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -173,9 +163,9 @@
|
|||
"patterns": [
|
||||
{ "name": "keyword.control.ludic", "match": "\\b(if|else|when|while|for|in|match|machine|become|enter|return|spawn|despawn|where|break|continue|new)\\b" },
|
||||
{ "name": "keyword.operator.logical.ludic", "match": "\\b(and|or|not)\\b" },
|
||||
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|reads|writes|needs|uses|requires|ensures|invariant|effects|on)\\b" },
|
||||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern|start)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(game|module|component|struct|archetype|enum|ui|scene|layer|const|var|let|fn|system|state)\\b" },
|
||||
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|reads|writes)\\b" },
|
||||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(game|module|component|struct|archetype|enum|ui|const|var|let|fn|system|main|state)\\b" },
|
||||
{ "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|void)\\b" },
|
||||
{ "name": "constant.language.boolean.ludic", "match": "\\b(true|false)\\b" },
|
||||
{ "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" }
|
||||
|
|
|
|||
|
|
@ -75,35 +75,25 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(scene)\\s+([A-Za-z_][A-Za-z0-9_]*)(\\s+start)?",
|
||||
"captures": {
|
||||
"1": { "name": "storage.type.scene.ludic" },
|
||||
"2": { "name": "entity.name.type.scene.ludic" },
|
||||
"3": { "name": "keyword.other.start.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(layer|ui)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"match": "\\b(ui)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
"1": { "name": "storage.type.ludic" },
|
||||
"2": { "name": "entity.name.type.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(edge\\s+)?(system)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"match": "\\b(system)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
"1": { "name": "storage.modifier.edge.ludic" },
|
||||
"2": { "name": "storage.type.system.ludic" },
|
||||
"3": { "name": "entity.name.function.system.ludic" }
|
||||
"1": { "name": "storage.type.system.ludic" },
|
||||
"2": { "name": "entity.name.function.system.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "\\b(export\\s+|pure\\s+)?(extern\\s+)?(fn)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"match": "\\b(extern\\s+)?(fn)\\s+([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
"1": { "name": "storage.modifier.ludic" },
|
||||
"2": { "name": "storage.modifier.extern.ludic" },
|
||||
"3": { "name": "storage.type.function.ludic" },
|
||||
"4": { "name": "entity.name.function.ludic" }
|
||||
"1": { "name": "storage.modifier.extern.ludic" },
|
||||
"2": { "name": "storage.type.function.ludic" },
|
||||
"3": { "name": "entity.name.function.ludic" }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -173,9 +163,9 @@
|
|||
"patterns": [
|
||||
{ "name": "keyword.control.ludic", "match": "\\b(if|else|when|while|for|in|match|machine|become|enter|return|spawn|despawn|where|break|continue|new)\\b" },
|
||||
{ "name": "keyword.operator.logical.ludic", "match": "\\b(and|or|not)\\b" },
|
||||
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|reads|writes|needs|uses|requires|ensures|invariant|effects|on)\\b" },
|
||||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern|start)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(game|module|component|struct|archetype|enum|ui|scene|layer|const|var|let|fn|system|state)\\b" },
|
||||
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|reads|writes)\\b" },
|
||||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(game|module|component|struct|archetype|enum|ui|const|var|let|fn|system|main|state)\\b" },
|
||||
{ "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|void)\\b" },
|
||||
{ "name": "constant.language.boolean.ludic", "match": "\\b(true|false)\\b" },
|
||||
{ "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue