Phase 7b: null literal + x == null (retire ptr_null/ptr_is_null)
`null` is now a real pointer literal and null-tests are comparisons, instead of `ptr_null()` and `ptr_is_null(x)`: ptr_null() -> null ptr_is_null(x) -> (x == null) not ptr_is_null(x) -> (x != null) Mechanics: a new E_NULL primary (`null`, like true/false) lowers to the `null` pointer; emit_bin's comparison path now picks `ptr` vs `i32` from operand type (via llty), so `==`/`!=` work on any pointer/record/slice. The two intrinsics are deleted. Two reseeds: (A) add the literal + ptr comparison keeping the intrinsics; (B) migrate all 182 call sites (compiler + runtime, via a balanced-paren script that skips string-literal args and rewrites `not ptr_is_null` to `!= null`) and delete the intrinsics. Node/Val/Buf/Tok field defaults now read `ptr = null`. Vocabulary drops the two from LUDIC_INTRINSICS; `null` joins true/false as a language constant (grammar + ludic_syntax.h). LANGUAGE.md notes the literal. Reseeded (21664 lines); C-free fixpoint holds; goldens identical; 17/17; vocab + doc-fences clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ddb1af3008
commit
70ab79a4e9
34 changed files with 5064 additions and 5124 deletions
|
|
@ -68,8 +68,8 @@ object LudicVocabulary {
|
|||
// compiler intrinsics: the floor the Ludic-written runtime stands on
|
||||
"mem_alloc", "mem_realloc", "mem_free", "mem_copy", "mem_set", "peek8", "poke8", "peek32",
|
||||
"os_argc", "os_arg", "file_stderr",
|
||||
"poke32", "peekp", "pokep", "peekf", "pokef", "ptr_add", "ptr_null",
|
||||
"ptr_is_null", "as_fixed", "as_int", "file_open", "file_read", "file_write",
|
||||
"poke32", "peekp", "pokep", "peekf", "pokef", "ptr_add",
|
||||
"as_fixed", "as_int", "file_open", "file_read", "file_write",
|
||||
"file_seek", "file_tell", "file_close", "read_byte", "write_byte", "print_str",
|
||||
"str_len", "os_exit", "os_time",
|
||||
"is_windowed", "game_title", "win_open", "win_poll", "win_present",
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@
|
|||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|fn|handler|entry|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.boolean.ludic", "match": "\\b(true|false|null)\\b" },
|
||||
{ "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" }
|
||||
]
|
||||
},
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
{
|
||||
"comment": "compiler intrinsics — these lower straight to libc or the OS",
|
||||
"name": "support.function.intrinsic.ludic",
|
||||
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek8|poke8|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|ptr_null|ptr_is_null|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|print_str|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
|
||||
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek8|poke8|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|print_str|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@
|
|||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|fn|handler|entry|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.boolean.ludic", "match": "\\b(true|false|null)\\b" },
|
||||
{ "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" }
|
||||
]
|
||||
},
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
{
|
||||
"comment": "compiler intrinsics — these lower straight to libc or the OS",
|
||||
"name": "support.function.intrinsic.ludic",
|
||||
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek8|poke8|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|ptr_null|ptr_is_null|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|print_str|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
|
||||
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek8|poke8|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|print_str|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -161,8 +161,6 @@ static const LBuiltin LUDIC_INTRINSICS[] = {
|
|||
{"peekf","peekf(p: ptr, off: int) -> fixed","Read a fixed-point word."},
|
||||
{"pokef","pokef(p: ptr, off: int, v: fixed)","Write a fixed-point word."},
|
||||
{"ptr_add","ptr_add(p: ptr, off: int) -> ptr","Offset a pointer by bytes."},
|
||||
{"ptr_null","ptr_null() -> ptr","The null pointer."},
|
||||
{"ptr_is_null","ptr_is_null(p: ptr) -> bool","Null test."},
|
||||
{"as_fixed","as_fixed(i: int) -> fixed","Reinterpret an int as fixed (no conversion)."},
|
||||
{"as_int","as_int(f: fixed) -> int","Reinterpret a fixed as int (no conversion)."},
|
||||
{"file_open","file_open(path: str, mode: str) -> ptr","fopen."},
|
||||
|
|
@ -259,7 +257,7 @@ static void lud_lex(LLex* L, const char* src){
|
|||
int len = i - s; char w[128];
|
||||
if (len < (int)sizeof(w)){ memcpy(w, src + s, len); w[len] = 0; } else { w[0] = 0; }
|
||||
int k = LT_ID;
|
||||
if (!strcmp(w, "true") || !strcmp(w, "false")) k = LT_BOOL;
|
||||
if (!strcmp(w, "true") || !strcmp(w, "false") || !strcmp(w, "null")) k = LT_BOOL;
|
||||
else if (lud_in(LUDIC_TYPES, w)) k = LT_TYPE;
|
||||
else if (lud_in(LUDIC_PHASES, w)) k = LT_PHASE;
|
||||
else if (lud_is_keyword(w)) k = LT_KW;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue