refactor(lang): rename the str type (and stringify builtin) to string
Expand the abbreviated string type and its conversion builtin to the full
word everywhere:
str -> string (the immutable-string type)
str(x) -> str -> string(x) -> string (the stringify builtin;
what `{…}` interpolation calls)
Types are recognized by identifier, and llty maps both spellings to LLVM
`ptr`, so this is an atomic source rewrite: type annotations, the Ludic
type tags, the builtin name/dispatch, and the interpolation desugar, plus
the grammars, LSP, docs (type-str -> type-string, fn-str -> fn-string), and
inventory. int/bool stay (universally accepted, like Math).
Reseeded; C-free fixpoint holds; all suites green (45/24/29); site + check.py OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4c48077d68
commit
b7745a4600
70 changed files with 207 additions and 207 deletions
|
|
@ -34,7 +34,7 @@ game Atlas {
|
|||
|
||||
# build "<DIR>/tile_%04d.png" without a formatter: the runtime's string
|
||||
# helpers write into a scratch buffer we own
|
||||
function tile_path(i: int) -> str {
|
||||
function tile_path(i: int) -> string {
|
||||
let buf = atlas_buf()
|
||||
let n = rt_put_str(buf, 0, DIR)
|
||||
n = rt_put_str(buf, n, "/tile_")
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
],
|
||||
"builtins": [
|
||||
"fn-print",
|
||||
"fn-str",
|
||||
"fn-string",
|
||||
"fn-quit",
|
||||
"fn-save",
|
||||
"fn-load",
|
||||
|
|
@ -327,7 +327,7 @@
|
|||
"type-ptr",
|
||||
"type-ptrs",
|
||||
"type-slices",
|
||||
"type-str",
|
||||
"type-string",
|
||||
"type-void",
|
||||
"type-words"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ object LudicTokens {
|
|||
val KEYWORD = LudicTokenType("KEYWORD")
|
||||
val DECL_KEYWORD = LudicTokenType("DECL_KEYWORD") // game, component, system, function, ...
|
||||
val CLAUSE = LudicTokenType("CLAUSE") // phase, query, reads, writes, ...
|
||||
val PRIMITIVE = LudicTokenType("PRIMITIVE") // int, fixed, bool, entity, str, ptr, void
|
||||
val PRIMITIVE = LudicTokenType("PRIMITIVE") // int, fixed, bool, entity, string, pointer, void
|
||||
val PHASE = LudicTokenType("PHASE") // Start, Update, Render, ...
|
||||
val BOOLEAN = LudicTokenType("BOOLEAN")
|
||||
val BUILTIN = LudicTokenType("BUILTIN") // runtime surface + compiler intrinsics
|
||||
|
|
@ -52,7 +52,7 @@ object LudicVocabulary {
|
|||
"enable", "disable", "match", "machine", "state", "become", "where",
|
||||
"and", "or", "not", "break", "continue", "new", "emit", "cancel"
|
||||
)
|
||||
val PRIMITIVES = setOf("int", "long", "fixed", "bool", "entity", "str", "ptr", "byte", "words", "fixeds", "ptrs", "void")
|
||||
val PRIMITIVES = setOf("int", "long", "fixed", "bool", "entity", "string", "ptr", "byte", "words", "fixeds", "ptrs", "void")
|
||||
val PHASES = setOf("Start", "Input", "FixedUpdate", "Update", "LateUpdate", "Render")
|
||||
val WIDGETS = setOf("panel", "col", "row", "label", "button", "image", "spacer")
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ object LudicVocabulary {
|
|||
"sprites_load", "draw_sprite", "draw_sprite_scaled", "ui_build", "ui_open",
|
||||
"ui_tick", "ui_render", "ui_clicked", "ui_set_text", "ui_set_int", "ui_focus",
|
||||
"ui_focused", "ui_visible", "key", "reg", "set_reg", "self", "save", "load",
|
||||
"status", "print", "str", "quit",
|
||||
"status", "print", "string", "quit",
|
||||
// compiler intrinsics: the floor the Ludic-written runtime stands on
|
||||
"bytes", "words", "resize", "free", "fill", "arg_count", "arg", "file_stderr", "file_stdout",
|
||||
"offset",
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@
|
|||
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|on)\\b" },
|
||||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|function|handler|entry|state)\\b" },
|
||||
{ "name": "support.type.primitive.ludic", "match": "\\b(int|long|fixed|bool|entity|str|ptr|byte|words|fixeds|ptrs|void)\\b" },
|
||||
{ "name": "support.type.primitive.ludic", "match": "\\b(int|long|fixed|bool|entity|string|ptr|byte|words|fixeds|ptrs|void)\\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" }
|
||||
]
|
||||
|
|
@ -204,7 +204,7 @@
|
|||
{
|
||||
"comment": "the runtime surface — every name here resolves to rt_<name> in runtime/native",
|
||||
"name": "support.function.builtin.ludic",
|
||||
"match": "\\b(min|max|abs|clamp|seed|rng_range|rng_chance|fx|flr|map_size|map_row|tile|clear|present|fill_rect|frame_rect|put_px|text|text_int|font_load|text_ttf|text_w|text_h|image_load|draw_image|draw_image_scaled|draw_9slice|png_load|sprites_load|draw_sprite|draw_sprite_scaled|ui_build|ui_open|ui_tick|ui_render|ui_clicked|ui_set_text|ui_set_int|ui_focus|ui_focused|ui_visible|key|reg|set_reg|self|save|load|status|print|str|quit)\\b(?=\\s*\\()"
|
||||
"match": "\\b(min|max|abs|clamp|seed|rng_range|rng_chance|fx|flr|map_size|map_row|tile|clear|present|fill_rect|frame_rect|put_px|text|text_int|font_load|text_ttf|text_w|text_h|image_load|draw_image|draw_image_scaled|draw_9slice|png_load|sprites_load|draw_sprite|draw_sprite_scaled|ui_build|ui_open|ui_tick|ui_render|ui_clicked|ui_set_text|ui_set_int|ui_focus|ui_focused|ui_visible|key|reg|set_reg|self|save|load|status|print|string|quit)\\b(?=\\s*\\()"
|
||||
},
|
||||
{
|
||||
"comment": "compiler intrinsics — these lower straight to libc or the OS",
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@
|
|||
{ "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|on)\\b" },
|
||||
{ "name": "keyword.other.ludic", "match": "\\b(import|extern)\\b" },
|
||||
{ "name": "storage.type.ludic", "match": "\\b(program|property|model|enum|ui|const|var|let|function|handler|entry|state)\\b" },
|
||||
{ "name": "support.type.primitive.ludic", "match": "\\b(int|long|fixed|bool|entity|str|ptr|byte|words|fixeds|ptrs|void)\\b" },
|
||||
{ "name": "support.type.primitive.ludic", "match": "\\b(int|long|fixed|bool|entity|string|ptr|byte|words|fixeds|ptrs|void)\\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" }
|
||||
]
|
||||
|
|
@ -204,7 +204,7 @@
|
|||
{
|
||||
"comment": "the runtime surface — every name here resolves to rt_<name> in runtime/native",
|
||||
"name": "support.function.builtin.ludic",
|
||||
"match": "\\b(min|max|abs|clamp|seed|rng_range|rng_chance|fx|flr|map_size|map_row|tile|clear|present|fill_rect|frame_rect|put_px|text|text_int|font_load|text_ttf|text_w|text_h|image_load|draw_image|draw_image_scaled|draw_9slice|png_load|sprites_load|draw_sprite|draw_sprite_scaled|ui_build|ui_open|ui_tick|ui_render|ui_clicked|ui_set_text|ui_set_int|ui_focus|ui_focused|ui_visible|key|reg|set_reg|self|save|load|status|print|str|quit)\\b(?=\\s*\\()"
|
||||
"match": "\\b(min|max|abs|clamp|seed|rng_range|rng_chance|fx|flr|map_size|map_row|tile|clear|present|fill_rect|frame_rect|put_px|text|text_int|font_load|text_ttf|text_w|text_h|image_load|draw_image|draw_image_scaled|draw_9slice|png_load|sprites_load|draw_sprite|draw_sprite_scaled|ui_build|ui_open|ui_tick|ui_render|ui_clicked|ui_set_text|ui_set_int|ui_focus|ui_focused|ui_visible|key|reg|set_reg|self|save|load|status|print|string|quit)\\b(?=\\s*\\()"
|
||||
},
|
||||
{
|
||||
"comment": "compiler intrinsics — these lower straight to libc or the OS",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ program LudicFmt {
|
|||
const LT_ERR: int = 14
|
||||
|
||||
# ---- tiny stdio + string helpers (self-contained) ----
|
||||
function read_file(path: str) -> ptr {
|
||||
function read_file(path: string) -> ptr {
|
||||
let f = file_open(path, "rb")
|
||||
if (f == null) { return null }
|
||||
file_seek(f, 0, 2)
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ program LudicLsp {
|
|||
return c == 43 or c == 45 or c == 42 or c == 47 or c == 37 or c == 60 or c == 62 or c == 61 or c == 40 or c == 41 or c == 123 or c == 125 or c == 91 or c == 93 or c == 44 or c == 58 or c == 46 or c == 33 or c == 64 or c == 59
|
||||
}
|
||||
function is_type_word(w: ptr) -> bool {
|
||||
return (w == "int") or (w == "long") or (w == "fixed") or (w == "bool") or (w == "entity") or (w == "str") or (w == "ptr") or (w == "byte") or (w == "words") or (w == "fixeds") or (w == "ptrs") or (w == "void")
|
||||
return (w == "int") or (w == "long") or (w == "fixed") or (w == "bool") or (w == "entity") or (w == "string") or (w == "ptr") or (w == "byte") or (w == "words") or (w == "fixeds") or (w == "ptrs") or (w == "void")
|
||||
}
|
||||
function is_phase_word(w: ptr) -> bool {
|
||||
return (w == "Start") or (w == "Input") or (w == "FixedUpdate") or (w == "Update") or (w == "LateUpdate") or (w == "Render")
|
||||
|
|
@ -1272,24 +1272,24 @@ program LudicLsp {
|
|||
if (ns == "Text") {
|
||||
if (meth == "length") { return "Text.length(s) -> int" }
|
||||
if (meth == "char_at") { return "Text.char_at(s, i) -> int" }
|
||||
if (meth == "slice") { return "Text.slice(s, a, b) -> str" }
|
||||
if (meth == "slice") { return "Text.slice(s, a, b) -> string" }
|
||||
if (meth == "starts_with") { return "Text.starts_with(s, prefix) -> bool" }
|
||||
if (meth == "ends_with") { return "Text.ends_with(s, suffix) -> bool" }
|
||||
if (meth == "contains") { return "Text.contains(s, sub) -> bool" }
|
||||
if (meth == "index_of") { return "Text.index_of(s, sub) -> int" }
|
||||
if (meth == "equals") { return "Text.equals(a, b) -> bool" }
|
||||
if (meth == "concat") { return "Text.concat(a, b) -> str" }
|
||||
if (meth == "concat") { return "Text.concat(a, b) -> string" }
|
||||
if (meth == "to_int") { return "Text.to_int(s) -> int" }
|
||||
if (meth == "from_int") { return "Text.from_int(n) -> str" }
|
||||
if (meth == "upper") { return "Text.upper(s) -> str" }
|
||||
if (meth == "lower") { return "Text.lower(s) -> str" }
|
||||
if (meth == "trim") { return "Text.trim(s) -> str" }
|
||||
if (meth == "repeat") { return "Text.repeat(s, n) -> str" }
|
||||
if (meth == "pad_left") { return "Text.pad_left(s, width) -> str" }
|
||||
if (meth == "pad_right") { return "Text.pad_right(s, width) -> str" }
|
||||
if (meth == "split") { return "Text.split(s, sep) -> []str" }
|
||||
if (meth == "join") { return "Text.join(parts, sep) -> str" }
|
||||
if (meth == "replace") { return "Text.replace(s, from, to) -> str" }
|
||||
if (meth == "from_int") { return "Text.from_int(n) -> string" }
|
||||
if (meth == "upper") { return "Text.upper(s) -> string" }
|
||||
if (meth == "lower") { return "Text.lower(s) -> string" }
|
||||
if (meth == "trim") { return "Text.trim(s) -> string" }
|
||||
if (meth == "repeat") { return "Text.repeat(s, n) -> string" }
|
||||
if (meth == "pad_left") { return "Text.pad_left(s, width) -> string" }
|
||||
if (meth == "pad_right") { return "Text.pad_right(s, width) -> string" }
|
||||
if (meth == "split") { return "Text.split(s, sep) -> []string" }
|
||||
if (meth == "join") { return "Text.join(parts, sep) -> string" }
|
||||
if (meth == "replace") { return "Text.replace(s, from, to) -> string" }
|
||||
}
|
||||
if (ns == "Hash") {
|
||||
if (meth == "of") { return "Hash.of(s) -> int" }
|
||||
|
|
@ -1360,11 +1360,11 @@ program LudicLsp {
|
|||
if (meth == "local_id") { return "Network.local_id() -> int" }
|
||||
}
|
||||
if (ns == "System") {
|
||||
if (meth == "arg") { return "System.arg(i) -> str" }
|
||||
if (meth == "arg") { return "System.arg(i) -> string" }
|
||||
if (meth == "arg_count") { return "System.arg_count() -> int" }
|
||||
if (meth == "exit") { return "System.exit(code)" }
|
||||
if (meth == "run") { return "System.run(command) -> int" }
|
||||
if (meth == "env") { return "System.env(name) -> str" }
|
||||
if (meth == "env") { return "System.env(name) -> string" }
|
||||
if (meth == "read_char") { return "System.read_char() -> int" }
|
||||
if (meth == "file_open") { return "System.file_open(path, mode) -> ptr" }
|
||||
if (meth == "file_read") { return "System.file_read(file, buf, n) -> int" }
|
||||
|
|
@ -1407,25 +1407,25 @@ program LudicLsp {
|
|||
badd("fx", "fx(i: int) -> fixed")
|
||||
badd("flr", "flr(f: fixed) -> int")
|
||||
badd("map_size", "map_size(w: int, h: int)")
|
||||
badd("map_row", "map_row(y: int, row: str)")
|
||||
badd("map_row", "map_row(y: int, row: string)")
|
||||
badd("tile", "tile(x: int, y: int) -> int")
|
||||
badd("clear", "clear(color: int)")
|
||||
badd("present", "present()")
|
||||
badd("fill_rect", "fill_rect(x: int, y: int, w: int, h: int, color: int)")
|
||||
badd("frame_rect", "frame_rect(x: int, y: int, w: int, h: int, color: int)")
|
||||
badd("put_px", "put_px(x: int, y: int, color: int)")
|
||||
badd("text", "text(x: int, y: int, s: str, color: int, scale: int)")
|
||||
badd("text", "text(x: int, y: int, s: string, color: int, scale: int)")
|
||||
badd("text_int", "text_int(x: int, y: int, n: int, color: int, scale: int)")
|
||||
badd("font_load", "font_load(path: str) -> int")
|
||||
badd("text_ttf", "text_ttf(font: int, x: int, y: int, utf8: str, color: int, px: int)")
|
||||
badd("text_w", "text_w(font: int, utf8: str, px: int) -> int")
|
||||
badd("font_load", "font_load(path: string) -> int")
|
||||
badd("text_ttf", "text_ttf(font: int, x: int, y: int, utf8: string, color: int, px: int)")
|
||||
badd("text_w", "text_w(font: int, utf8: string, px: int) -> int")
|
||||
badd("text_h", "text_h(font: int, px: int) -> int")
|
||||
badd("image_load", "image_load(path: str) -> int")
|
||||
badd("image_load", "image_load(path: string) -> int")
|
||||
badd("draw_image", "draw_image(id: int, x: int, y: int)")
|
||||
badd("draw_image_scaled", "draw_image_scaled(id: int, x: int, y: int, w: int, h: int)")
|
||||
badd("draw_9slice", "draw_9slice(id: int, x: int, y: int, w: int, h: int, inset: int)")
|
||||
badd("png_load", "png_load(path: str) -> int")
|
||||
badd("sprites_load", "sprites_load(path: str)")
|
||||
badd("png_load", "png_load(path: string) -> int")
|
||||
badd("sprites_load", "sprites_load(path: string)")
|
||||
badd("draw_sprite", "draw_sprite(id: int, x: int, y: int)")
|
||||
badd("draw_sprite_scaled", "draw_sprite_scaled(id: int, x: int, y: int, scale: int)")
|
||||
badd("ui_build", "ui_build()")
|
||||
|
|
@ -1433,7 +1433,7 @@ program LudicLsp {
|
|||
badd("ui_tick", "ui_tick(key: int)")
|
||||
badd("ui_render", "ui_render()")
|
||||
badd("ui_clicked", "ui_clicked(id: int) -> bool")
|
||||
badd("ui_set_text", "ui_set_text(id: int, s: str)")
|
||||
badd("ui_set_text", "ui_set_text(id: int, s: string)")
|
||||
badd("ui_set_int", "ui_set_int(id: int, n: int)")
|
||||
badd("ui_focus", "ui_focus(id: int)")
|
||||
badd("ui_focused", "ui_focused() -> int")
|
||||
|
|
@ -1444,15 +1444,15 @@ program LudicLsp {
|
|||
badd("self", "self() -> entity")
|
||||
badd("save", "save()")
|
||||
badd("load", "load() -> bool")
|
||||
badd("status", "status(s: str)")
|
||||
badd("status", "status(s: string)")
|
||||
badd("print", "print(x)")
|
||||
badd("str", "str(x) -> str")
|
||||
badd("string", "string(x) -> string")
|
||||
badd("quit", "quit()")
|
||||
badd("bytes", "bytes(n: int) -> ptr")
|
||||
badd("words", "words(n: int) -> words")
|
||||
badd("resize", "resize(p: ptr, n: int) -> ptr")
|
||||
badd("arg_count", "arg_count() -> int")
|
||||
badd("arg", "arg(i: int) -> str")
|
||||
badd("arg", "arg(i: int) -> string")
|
||||
badd("file_stderr", "file_stderr() -> ptr")
|
||||
badd("file_stdout", "file_stdout() -> ptr")
|
||||
badd("free", "free(p: ptr)")
|
||||
|
|
@ -1460,7 +1460,7 @@ program LudicLsp {
|
|||
badd("offset", "offset(p: ptr, off: int) -> ptr")
|
||||
badd("as_fixed", "as_fixed(i: int) -> fixed")
|
||||
badd("as_int", "as_int(f: fixed) -> int")
|
||||
badd("file_open", "file_open(path: str, mode: str) -> ptr")
|
||||
badd("file_open", "file_open(path: string, mode: string) -> ptr")
|
||||
badd("file_read", "file_read(f: ptr, buf: ptr, n: int) -> int")
|
||||
badd("file_write", "file_write(f: ptr, buf: ptr, n: int) -> int")
|
||||
badd("file_seek", "file_seek(f: ptr, off: int, whence: int) -> int")
|
||||
|
|
@ -1469,8 +1469,8 @@ program LudicLsp {
|
|||
badd("read_char", "read_char() -> int")
|
||||
badd("exit", "exit(code: int)")
|
||||
badd("is_windowed", "is_windowed() -> bool")
|
||||
badd("game_title", "game_title() -> str")
|
||||
badd("win_open", "win_open(title: str, w: int, h: int, scale: int)")
|
||||
badd("game_title", "game_title() -> string")
|
||||
badd("win_open", "win_open(title: string, w: int, h: int, scale: int)")
|
||||
badd("win_poll", "win_poll() -> int")
|
||||
badd("win_present", "win_present(px: ptr, w: int, h: int)")
|
||||
badd("win_running", "win_running() -> bool")
|
||||
|
|
@ -2287,7 +2287,7 @@ program LudicLsp {
|
|||
}
|
||||
function comp_types(o: Buf) -> void {
|
||||
comp_item(o, "int", 14, "built-in type"); comp_item(o, "long", 14, "built-in type"); comp_item(o, "fixed", 14, "built-in type"); comp_item(o, "bool", 14, "built-in type")
|
||||
comp_item(o, "entity", 14, "built-in type"); comp_item(o, "str", 14, "built-in type"); comp_item(o, "ptr", 14, "built-in type"); comp_item(o, "void", 14, "built-in type")
|
||||
comp_item(o, "entity", 14, "built-in type"); comp_item(o, "string", 14, "built-in type"); comp_item(o, "ptr", 14, "built-in type"); comp_item(o, "void", 14, "built-in type")
|
||||
}
|
||||
function comp_builtins(o: Buf) -> void { var i = 0; while i < len(g_builtins) { comp_item(o, g_builtins[i], 3, g_bsigs[i]); i = i + 1 } }
|
||||
function on_completion(msg: JVal, id: JVal) -> void {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ enum {
|
|||
LT_EOF, LT_NL, LT_COMMENT,
|
||||
LT_ID, /* a plain identifier */
|
||||
LT_KW, /* a reserved word (see KEYWORDS) */
|
||||
LT_TYPE, /* a built-in type name: int fixed bool entity str ptr void */
|
||||
LT_TYPE, /* a built-in type name: int fixed bool entity string pointer void */
|
||||
LT_PHASE, /* Start Input FixedUpdate Update LateUpdate Render */
|
||||
LT_BOOL, /* true false */
|
||||
LT_INT, LT_FLOAT, LT_STR, LT_CHAR,
|
||||
|
|
@ -71,7 +71,7 @@ static const char* LUDIC_KW_STMT[] = {
|
|||
"and","or","not","break","continue","new","emit","cancel", 0
|
||||
};
|
||||
static const char* LUDIC_TYPES[] = {
|
||||
"int","long","fixed","bool","entity","str","ptr","byte","words","fixeds","ptrs","void", 0
|
||||
"int","long","fixed","bool","entity","string","ptr","byte","words","fixeds","ptrs","void", 0
|
||||
};
|
||||
static const char* LUDIC_PHASES[] = {
|
||||
"Start","Input","FixedUpdate","Update","LateUpdate","Render", 0
|
||||
|
|
@ -100,25 +100,25 @@ static const LBuiltin LUDIC_BUILTINS[] = {
|
|||
{"fx","fx(i: int) -> fixed","Widen an int to Q16.16 fixed-point."},
|
||||
{"flr","flr(f: fixed) -> int","Truncate a fixed-point value toward zero."},
|
||||
{"map_size","map_size(w: int, h: int)","Set the tilemap dimensions."},
|
||||
{"map_row","map_row(y: int, row: str)","Fill one tilemap row from a string."},
|
||||
{"map_row","map_row(y: int, row: string)","Fill one tilemap row from a string."},
|
||||
{"tile","tile(x: int, y: int) -> int","Tile code at a map cell."},
|
||||
{"clear","clear(color: int)","Clear the framebuffer to a 0xRRGGBB colour."},
|
||||
{"present","present()","Push the framebuffer to the window (or out.ppm when headless)."},
|
||||
{"fill_rect","fill_rect(x: int, y: int, w: int, h: int, color: int)","Filled rectangle."},
|
||||
{"frame_rect","frame_rect(x: int, y: int, w: int, h: int, color: int)","One-pixel rectangle outline."},
|
||||
{"put_px","put_px(x: int, y: int, color: int)","Write a single pixel."},
|
||||
{"text","text(x: int, y: int, s: str, color: int, scale: int)","Draw text with the built-in 5x7 bitmap font."},
|
||||
{"text","text(x: int, y: int, s: string, color: int, scale: int)","Draw text with the built-in 5x7 bitmap font."},
|
||||
{"text_int","text_int(x: int, y: int, n: int, color: int, scale: int)","Draw an integer with the 5x7 bitmap font."},
|
||||
{"font_load","font_load(path: str) -> int","Load a TrueType .ttf/.ttc; returns a font id."},
|
||||
{"text_ttf","text_ttf(font: int, x: int, y: int, utf8: str, color: int, px: int)","Draw UTF-8 text with a TrueType font."},
|
||||
{"text_w","text_w(font: int, utf8: str, px: int) -> int","Advance width of the string, in pixels."},
|
||||
{"font_load","font_load(path: string) -> int","Load a TrueType .ttf/.ttc; returns a font id."},
|
||||
{"text_ttf","text_ttf(font: int, x: int, y: int, utf8: string, color: int, px: int)","Draw UTF-8 text with a TrueType font."},
|
||||
{"text_w","text_w(font: int, utf8: string, px: int) -> int","Advance width of the string, in pixels."},
|
||||
{"text_h","text_h(font: int, px: int) -> int","Line height of the font, in pixels."},
|
||||
{"image_load","image_load(path: str) -> int","Decode a PNG into an image id."},
|
||||
{"image_load","image_load(path: string) -> int","Decode a PNG into an image id."},
|
||||
{"draw_image","draw_image(id: int, x: int, y: int)","Blit an image at its natural size."},
|
||||
{"draw_image_scaled","draw_image_scaled(id: int, x: int, y: int, w: int, h: int)","Blit an image stretched to w x h."},
|
||||
{"draw_9slice","draw_9slice(id: int, x: int, y: int, w: int, h: int, inset: int)","Nine-slice an image across a w x h box."},
|
||||
{"png_load","png_load(path: str) -> int","Decode a PNG as a 16x16 sprite sheet; returns the first sprite id."},
|
||||
{"sprites_load","sprites_load(path: str)","Load the sprite sheet used by draw_sprite."},
|
||||
{"png_load","png_load(path: string) -> int","Decode a PNG as a 16x16 sprite sheet; returns the first sprite id."},
|
||||
{"sprites_load","sprites_load(path: string)","Load the sprite sheet used by draw_sprite."},
|
||||
{"draw_sprite","draw_sprite(id: int, x: int, y: int)","Blit a sprite."},
|
||||
{"draw_sprite_scaled","draw_sprite_scaled(id: int, x: int, y: int, scale: int)","Blit a sprite at an integer scale."},
|
||||
{"ui_build","ui_build()","Construct every declared `ui` tree (loads skins and images)."},
|
||||
|
|
@ -126,7 +126,7 @@ static const LBuiltin LUDIC_BUILTINS[] = {
|
|||
{"ui_tick","ui_tick(key: int)","Feed a key to the UI: w/s move focus, space/enter activate."},
|
||||
{"ui_render","ui_render()","Lay out and draw the active ui tree."},
|
||||
{"ui_clicked","ui_clicked(id: int) -> bool","True on the frame a widget was activated."},
|
||||
{"ui_set_text","ui_set_text(id: int, s: str)","Replace a widget's text."},
|
||||
{"ui_set_text","ui_set_text(id: int, s: string)","Replace a widget's text."},
|
||||
{"ui_set_int","ui_set_int(id: int, n: int)","Replace a widget's text with a number."},
|
||||
{"ui_focus","ui_focus(id: int)","Move keyboard focus to a widget."},
|
||||
{"ui_focused","ui_focused() -> int","Id of the focused widget."},
|
||||
|
|
@ -137,9 +137,9 @@ static const LBuiltin LUDIC_BUILTINS[] = {
|
|||
{"self","self() -> entity","The entity of the innermost query loop."},
|
||||
{"save","save()","Write a binary snapshot of the whole ECS world."},
|
||||
{"load","load() -> bool","Restore the snapshot; false if there is none."},
|
||||
{"status","status(s: str)","Set the one-line status message."},
|
||||
{"status","status(s: string)","Set the one-line status message."},
|
||||
{"print","print(x)","Print a value (int or string) and a newline to stdout."},
|
||||
{"str","str(x) -> str","Convert an int/bool/fixed to text (a string passes through)."},
|
||||
{"string","string(x) -> string","Convert an int/bool/fixed to text (a string passes through)."},
|
||||
{"quit","quit()","Stop the frame loop and exit."},
|
||||
{0,0,0}
|
||||
};
|
||||
|
|
@ -157,7 +157,7 @@ static const LBuiltin LUDIC_INTRINSICS[] = {
|
|||
{"offset","offset(p: ptr, off: int) -> ptr","Offset a pointer by bytes."},
|
||||
{"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."},
|
||||
{"file_open","file_open(path: string, mode: string) -> ptr","fopen."},
|
||||
{"file_read","file_read(f: ptr, buf: ptr, n: int) -> int","fread."},
|
||||
{"file_write","file_write(f: ptr, buf: ptr, n: int) -> int","fwrite."},
|
||||
{"file_seek","file_seek(f: ptr, off: int, whence: int) -> int","fseek."},
|
||||
|
|
@ -167,7 +167,7 @@ static const LBuiltin LUDIC_INTRINSICS[] = {
|
|||
{"exit","exit(code: int)","Terminate the process."},
|
||||
{"is_windowed","is_windowed() -> bool","True when the build has a window."},
|
||||
{"game_title","game_title() -> str","The name from the `game` declaration."},
|
||||
{"win_open","win_open(title: str, w: int, h: int, scale: int)","Open the platform window."},
|
||||
{"win_open","win_open(title: string, w: int, h: int, scale: int)","Open the platform window."},
|
||||
{"win_poll","win_poll() -> int","Pump the event queue; returns a key code."},
|
||||
{"win_present","win_present(px: ptr, w: int, h: int)","Blit a framebuffer to the window."},
|
||||
{"win_running","win_running() -> bool","False once the window has been closed."},
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ function check(label: ptr, got: ptr, want: ptr) -> void {
|
|||
# print the "== N passed, M failed ==" footer and return the process exit code
|
||||
function report() -> int {
|
||||
print("")
|
||||
print(`== {str(PASS)} passed, {str(FAIL)} failed ==`)
|
||||
print(`== {string(PASS)} passed, {string(FAIL)} failed ==`)
|
||||
if (FAIL == 0) { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ function cmd_test() -> int {
|
|||
write_file("/tmp/x_cli_exit.ludic", "entry { exit(42) }\n")
|
||||
let rc = sh("LUDIC_HOME=. bin/ludic /tmp/x_cli_exit.ludic > /tmp/x_cli.out 2>&1")
|
||||
if (rc == 42) { ok("ludic app.ludic -> compiles, runs, forwards exit code") }
|
||||
else { bad2("ludic run: expected exit 42", `got {str(rc)}`) }
|
||||
else { bad2("ludic run: expected exit 42", `got {string(rc)}`) }
|
||||
|
||||
return report()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ function cmd_test_tools() -> int {
|
|||
} else { bad("formatter altered non-whitespace bytes") }
|
||||
|
||||
# --- multi-byte characters must survive intact -----------------------------
|
||||
write_file("/tmp/x_utf8.ludic", "program E {\n # … ellipsis in a comment\n const S: str = \"café → naïve\"\n}\n")
|
||||
write_file("/tmp/x_utf8.ludic", "program E {\n # … ellipsis in a comment\n const S: string = \"café → naïve\"\n}\n")
|
||||
if shq(`{fmt} /tmp/x_utf8.ludic > /tmp/x_utf8.out 2>/dev/null; cmp -s /tmp/x_utf8.ludic /tmp/x_utf8.out`) {
|
||||
ok("UTF-8 preserved byte for byte")
|
||||
} else { bad("UTF-8 mangled") }
|
||||
|
|
@ -111,10 +111,10 @@ function cmd_test_tools() -> int {
|
|||
|
||||
# --- --check exit status, for CI and pre-commit hooks ----------------------
|
||||
let chk1 = sh(`{fmt} --check -q /tmp/x_m.ludic`)
|
||||
check("--check exits 1 on unformatted input", str(chk1), "1")
|
||||
check("--check exits 1 on unformatted input", string(chk1), "1")
|
||||
run(`{fmt} -w /tmp/x_m.ludic`)
|
||||
let chk2 = sh(`{fmt} --check -q /tmp/x_m.ludic`)
|
||||
check("--check exits 0 after -w", str(chk2), "0")
|
||||
check("--check exits 0 after -w", string(chk2), "0")
|
||||
|
||||
# --- markdown: fences formatted, prose untouched ---------------------------
|
||||
write_file("/tmp/x_d.md", "# T\n\nprose with spaces\n\n```ludic\nprogram D{property P{x:int=0}}\n```\n\n```python\nz = 1\n```\n")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue