diff --git a/CMakeLists.txt b/CMakeLists.txt index 1441509..2d110ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(fun VERSION 0.41.2 LANGUAGES C) +project(fun VERSION 0.41.3 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/scripts/check_op_includes.py b/scripts/check_op_includes.py index 1a8c4da..8b58889 100755 --- a/scripts/check_op_includes.py +++ b/scripts/check_op_includes.py @@ -45,6 +45,11 @@ def parse_opcodes_from_bytecode(text: str) -> set[str]: def parse_includes_from_vm(text: str) -> set[str]: pairs = [(m.group(1) or "", m.group(2)) for m in INCLUDE_RE.finditer(text)] + # Manually check for opcodes handled directly in switch/case instead of via includes + switch_ops = set() + if "case OP_CPP_ADD:" in text: + switch_ops.add("CPP_ADD") + # Drop support includes that are not opcode handlers support_includes = {"thread_common", "stubs", "handles"} pairs = [(d, n) for (d, n) in pairs if n not in support_includes] @@ -56,9 +61,9 @@ def parse_includes_from_vm(text: str) -> set[str]: "load_const": "LOAD_CONST", "load_local": "LOAD_LOCAL", "store_local": "STORE_LOCAL", "load_global": "LOAD_GLOBAL", "store_global": "STORE_GLOBAL", "pop": "POP", "dup": "DUP", "swap": "SWAP", - "call": "CALL", "return": "RETURN", "print": "PRINT", + "call": "CALL", "return": "RETURN", "print": "PRINT", "echo": "ECHO", "jump": "JUMP", "jump_if_false": "JUMP_IF_FALSE", - "line": "LINE", + "line": "LINE", "exit": "EXIT", # arithmetic/logic "add": "ADD", "sub": "SUB", "mul": "MUL", "div": "DIV", "mod": "MOD", "lt": "LT", "lte": "LTE", "gt": "GT", "gte": "GTE", @@ -68,32 +73,49 @@ def parse_includes_from_vm(text: str) -> set[str]: "index_get": "INDEX_GET", "index_set": "INDEX_SET", "push": "PUSH", "apop": "APOP", "set": "SET", "insert": "INSERT", "remove": "REMOVE", "slice": "SLICE", "clear": "CLEAR", "contains": "CONTAINS", "index_of": "INDEX_OF", + "arr_push": "PUSH", "arr_pop": "APOP", "arr_set": "SET", "arr_insert": "INSERT", "arr_remove": "REMOVE", # conversions and type/meta "to_number": "TO_NUMBER", "to_string": "TO_STRING", "cast": "CAST", "typeof": "TYPEOF", "uclamp": "UCLAMP", "sclamp": "SCLAMP", # strings and iteration helpers "split": "SPLIT", "join": "JOIN", "substr": "SUBSTR", "find": "FIND", "enumerate": "ENUMERATE", "zip": "ZIP", + "regex_match": "REGEX_MATCH", "regex_replace": "REGEX_REPLACE", "regex_search": "REGEX_SEARCH", # maps and I/O "make_map": "MAKE_MAP", "keys": "KEYS", "values": "VALUES", "has_key": "HAS_KEY", - "read_file": "READ_FILE", "write_file": "WRITE_FILE", + "read_file": "READ_FILE", "write_file": "WRITE_FILE", "input_line": "INPUT_LINE", # os/env - "env": "ENV", "sleep_ms": "SLEEP_MS", + "env": "ENV", "sleep_ms": "SLEEP_MS", "env_all": "ENV_ALL", "fun_version": "FUN_VERSION", + "proc_run": "PROC_RUN", "proc_system": "PROC_SYSTEM", "random_number": "RANDOM_NUMBER", + "clock_mono_ms": "CLOCK_MONO_MS", "time_now_ms": "TIME_NOW_MS", "date_format": "DATE_FORMAT", # math / RNG "min": "MIN", "max": "MAX", "clamp": "CLAMP", "abs": "ABS", "pow": "POW", "random_seed": "RANDOM_SEED", "random_int": "RANDOM_INT", + "floor": "FLOOR", "ceil": "CEIL", "trunc": "TRUNC", "round": "ROUND", + "sin": "SIN", "cos": "COS", "tan": "TAN", "exp": "EXP", "log": "LOG", "log10": "LOG10", "sqrt": "SQRT", + "gcd": "GCD", "lcm": "LCM", "isqrt": "ISQRT", "sign": "SIGN", "fmin": "FMIN", "fmax": "FMAX", # bitwise and shifts/rotates "band": "BAND", "bor": "BOR", "bxor": "BXOR", "bnot": "BNOT", "shl": "SHL", "shr": "SHR", "rol": "ROTL", "ror": "ROTR", # threads "thread_spawn": "THREAD_SPAWN", "thread_join": "THREAD_JOIN", + # exceptions + "throw": "THROW", "try_pop": "TRY_POP", "try_push": "TRY_PUSH", } def map_token(d: str, n: str) -> str: # Directory-specific namespaces if d == "curl": return f"CURL_{n.upper()}" + if d == "openssl": + return f"OPENSSL_{n.upper()}" + if d == "rust": + return f"RUST_{n.upper()}" + if d == "cpp": + if n == "add": + return "CPP_ADD" + return f"CPP_{n.upper()}" if d == "ini": if n in {"load", "free", "get_string", "get_int", "get_double", "get_bool", "set", "unset", "save"}: return f"INI_{n.upper()}" @@ -106,20 +128,12 @@ def parse_includes_from_vm(text: str) -> set[str]: if d == "sqlite": if n in {"open", "close", "exec", "query"}: return f"SQLITE_{n.upper()}" - if d == "libsql": - if n in {"open", "close", "exec", "query"}: - return f"LIBSQL_{n.upper()}" if d == "pcsc": if n in {"establish", "release", "list_readers", "connect", "disconnect", "transmit"}: return f"PCSC_{n.upper()}" if d == "pcre2": if n in {"test", "match", "findall"}: return f"PCRE2_{n.upper()}" - if d == "tk": - # wm_title already uses underscore - return f"TK_{n.upper()}" - if d == "notcurses": - return f"NC_{n.upper()}" if d == "os": # special cases in OS if n == "list_dir": @@ -134,6 +148,7 @@ def parse_includes_from_vm(text: str) -> set[str]: return base_overrides.get(n, n.upper()) tokens = set(map(lambda p: map_token(p[0], p[1]), pairs)) + tokens.update(switch_ops) return tokens def main() -> int: diff --git a/src/bytecode.c b/src/bytecode.c index dfbd7b5..f5fcbf5 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -309,20 +309,6 @@ static const char *opcode_name(OpCode op) { return "XML_NAME"; case OP_XML_TEXT: return "XML_TEXT"; - case OP_TK_EVAL: - return "TK_EVAL"; - case OP_TK_RESULT: - return "TK_RESULT"; - case OP_TK_LOOP: - return "TK_LOOP"; - case OP_TK_WM_TITLE: - return "TK_WM_TITLE"; - case OP_TK_LABEL: - return "TK_LABEL"; - case OP_TK_BUTTON: - return "TK_BUTTON"; - case OP_TK_PACK: - return "TK_PACK"; case OP_FLOOR: return "FLOOR"; case OP_CEIL: diff --git a/src/bytecode.h b/src/bytecode.h index 0171a22..22d1bb4 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -221,9 +221,6 @@ typedef enum { // OS additions OP_OS_LIST_DIR, // pops path string; pushes array of strings - // Tk additions - OP_TK_BIND, // pops command, event, id; binds event to command - // Serial communication (termios) OP_SERIAL_OPEN, // pops baud_rate (int), path (string); returns fd (int) or 0 OP_SERIAL_CONFIG, // pops flow_control, stop_bits, parity, data_bits, fd; returns 1/0 @@ -231,15 +228,6 @@ typedef enum { OP_SERIAL_RECV, // pops maxlen (int), fd; returns data (string) OP_SERIAL_CLOSE, // pops fd; returns 1/0 - // Tk (Tcl/Tk) optional minimal API - OP_TK_EVAL, // pops script string; pushes int rc (0 = OK) - OP_TK_RESULT, // pushes string: last Tcl result - OP_TK_LOOP, // enters Tk event loop; pushes Nil when done - OP_TK_WM_TITLE, // pops title string; sets window title; pushes rc - OP_TK_LABEL, // pops text, id; creates/updates label .id; pushes rc - OP_TK_BUTTON, // pops text, id; creates/updates button .id; pushes rc - OP_TK_PACK, // pops id; packs .id; pushes rc - // exceptions (minimal) OP_TRY_PUSH, // operand = handler ip; push handler onto try-stack OP_TRY_POP, // pop current handler @@ -279,21 +267,6 @@ typedef enum { // C++ demo opcode(s) OP_CPP_ADD, // pops b, a; pushes (a + b) - - /* Notcurses TUI (optional) */ - OP_NC_INIT, // initializes Notcurses; returns 1 on success, 0 on failure - OP_NC_SHUTDOWN, // shuts down Notcurses; returns 0 - OP_NC_CLEAR, // clears screen/plane; returns 0 - OP_NC_DRAW_TEXT, // pops text, x, y; draws; returns 0 - OP_NC_GETCH, // pops timeout_ms; returns codepoint or -1 on timeout/error - OP_NC_GET_SIZE, // pushes [rows:int, cols:int] or -1 when unavailable - OP_NC_SET_STYLE, // pops style:int, bg_rgb:int, fg_rgb:int; returns 0/-1 - OP_NC_DRAW_CHAR, // pops ch:int, x:int, y:int; returns 0/-1 - OP_NC_DRAW_HLINE,// pops len:int, x:int, y:int, ch:int; returns 0/-1 - OP_NC_DRAW_VLINE,// pops len:int, x:int, y:int, ch:int; returns 0/-1 - OP_NC_BOX, // pops x:int, y:int, w:int, h:int, style:int; returns 0/-1 - OP_NC_FILL, // pops x:int, y:int, w:int, h:int, ch:int; returns 0/-1 - OP_NC_RENDER // forces a render; returns 0/-1 } OpCode; typedef struct { diff --git a/src/parser.c b/src/parser.c index 2bedf2c..6a9a44d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1461,165 +1461,6 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos) free(name); return 1; } - /* Tk (GUI) builtins (no raw Tcl exposed) */ - if (strcmp(name, "tk_loop") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "tk_loop expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_LOOP, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_title") == 0) { - (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_title expects (title:string)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after tk_title arg"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_WM_TITLE, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_label") == 0) { - (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_label expects (id:string, text:string)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ',')) { - parser_fail(*pos, "tk_label expects 2 args"); - free(name); - return 0; - } - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_label expects (id:string, text:string)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after tk_label args"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_LABEL, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_button") == 0) { - (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_button expects (id:string, text:string)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ',')) { - parser_fail(*pos, "tk_button expects 2 args"); - free(name); - return 0; - } - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_button expects (id:string, text:string)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after tk_button args"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_BUTTON, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_pack") == 0) { - (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_pack expects (id:string)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after tk_pack arg"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_PACK, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_bind") == 0) { - (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_bind expects (id, event, cmd)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ',')) { - parser_fail(*pos, "tk_bind expects 3 args"); - free(name); - return 0; - } - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_bind expects 3 args"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ',')) { - parser_fail(*pos, "tk_bind expects 3 args"); - free(name); - return 0; - } - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_bind expects 3 args"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after tk_bind args"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_BIND, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_eval") == 0) { - (*pos)++; /* '(' */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "tk_eval expects (script)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after tk_eval arg"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_EVAL, 0); - free(name); - return 1; - } - if (strcmp(name, "tk_result") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "tk_result expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_TK_RESULT, 0); - free(name); - return 1; - } if (strcmp(name, "json_from_file") == 0) { (*pos)++; /* '(' */ if (!emit_expression(bc, src, len, pos)) { @@ -2340,206 +2181,7 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos) free(name); return 1; } - /* Notcurses builtins (optional) */ - if (strcmp(name, "nc_init") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "nc_init expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_INIT, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_shutdown") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "nc_shutdown expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_SHUTDOWN, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_clear") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "nc_clear expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_CLEAR, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_draw_text") == 0) { - (*pos)++; /* '(' */ - /* (y, x, text) -> push y, x, text, then opcode will pop text,x,y */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "nc_draw_text expects (y, x, text)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ',')) { - parser_fail(*pos, "nc_draw_text expects (y, x, text)"); - free(name); - return 0; - } - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "nc_draw_text expects (y, x, text)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ',')) { - parser_fail(*pos, "nc_draw_text expects (y, x, text)"); - free(name); - return 0; - } - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "nc_draw_text expects (y, x, text)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after nc_draw_text args"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_DRAW_TEXT, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_getch") == 0) { - (*pos)++; /* '(' */ - /* (timeout_ms) */ - if (!emit_expression(bc, src, len, pos)) { - parser_fail(*pos, "nc_getch expects (timeout_ms)"); - free(name); - return 0; - } - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "Expected ')' after nc_getch arg"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_GETCH, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_get_size") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "nc_get_size expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_GET_SIZE, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_set_style") == 0) { - (*pos)++; /* '(' */ - /* (style, bg_rgb, fg_rgb) */ - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_set_style expects (style, bg_rgb, fg_rgb)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_set_style expects (style, bg_rgb, fg_rgb)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_set_style expects (style, bg_rgb, fg_rgb)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_set_style expects (style, bg_rgb, fg_rgb)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_set_style expects (style, bg_rgb, fg_rgb)"); free(name); return 0; } - if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after nc_set_style args"); free(name); return 0; } - bytecode_add_instruction(bc, OP_NC_SET_STYLE, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_draw_char") == 0) { - (*pos)++; /* '(' */ - /* (y, x, ch) */ - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_char expects (y, x, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_char expects (y, x, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_char expects (y, x, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_char expects (y, x, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_char expects (y, x, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after nc_draw_char args"); free(name); return 0; } - bytecode_add_instruction(bc, OP_NC_DRAW_CHAR, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_draw_hline") == 0) { - (*pos)++; /* '(' */ - /* (y, x, len, ch) */ - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_hline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after nc_draw_hline args"); free(name); return 0; } - bytecode_add_instruction(bc, OP_NC_DRAW_HLINE, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_draw_vline") == 0) { - (*pos)++; /* '(' */ - /* (y, x, len, ch) */ - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_draw_vline expects (y, x, len, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after nc_draw_vline args"); free(name); return 0; } - bytecode_add_instruction(bc, OP_NC_DRAW_VLINE, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_box") == 0) { - (*pos)++; /* '(' */ - /* (x, y, w, h, style) -- wrapper may reorder */ - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_box expects (x, y, w, h, style)"); free(name); return 0; } - if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after nc_box args"); free(name); return 0; } - bytecode_add_instruction(bc, OP_NC_BOX, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_fill") == 0) { - (*pos)++; /* '(' */ - /* (x, y, w, h, ch) */ - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ',')) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "nc_fill expects (x, y, w, h, ch)"); free(name); return 0; } - if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after nc_fill args"); free(name); return 0; } - bytecode_add_instruction(bc, OP_NC_FILL, 0); - free(name); - return 1; - } - if (strcmp(name, "nc_render") == 0) { - (*pos)++; /* '(' */ - if (!consume_char(src, len, pos, ')')) { - parser_fail(*pos, "nc_render expects ()"); - free(name); - return 0; - } - bytecode_add_instruction(bc, OP_NC_RENDER, 0); - free(name); - return 1; - } + /* PCSC builtins (optional) */ if (strcmp(name, "pcsc_release") == 0) { (*pos)++; /* '(' */ if (!emit_expression(bc, src, len, pos)) { diff --git a/src/vm.h b/src/vm.h index ec652b1..c1427ea 100644 --- a/src/vm.h +++ b/src/vm.h @@ -66,19 +66,13 @@ static const char *opcode_names[] = { "FD_SET_NONBLOCK", "FD_POLL_READ", "FD_POLL_WRITE", "EXIT", "OS_LIST_DIR", - "TK_BIND", "SERIAL_OPEN", "SERIAL_CONFIG", "SERIAL_SEND", "SERIAL_RECV", "SERIAL_CLOSE", - "TK_EVAL", "TK_RESULT", "TK_LOOP", "TK_WM_TITLE", "TK_LABEL", "TK_BUTTON", "TK_PACK", "TRY_PUSH", "TRY_POP", "THROW", "FMIN", "FMAX", /* Rust FFI demo */ "RUST_HELLO", "RUST_HELLO_ARGS", "RUST_HELLO_ARGS_RETURN", "RUST_GET_SP", "RUST_SET_EXIT", /* C++ demo */ - "CPP_ADD", - /* Notcurses TUI (optional) */ - "NC_INIT", "NC_SHUTDOWN", "NC_CLEAR", "NC_DRAW_TEXT", "NC_GETCH", - "NC_GET_SIZE", "NC_SET_STYLE", "NC_DRAW_CHAR", "NC_DRAW_HLINE", "NC_DRAW_VLINE", - "NC_BOX", "NC_FILL", "NC_RENDER"}; + "CPP_ADD"}; typedef struct { Bytecode *fn; @@ -162,7 +156,7 @@ void vm_debug_request_finish(VM *vm); void vm_debug_request_continue(VM *vm); static inline int opcode_is_valid(int op) { - return op >= OP_NOP && op <= OP_NC_RENDER; // all current opcodes (including optional NC_*) + return op >= OP_NOP && op <= OP_CPP_ADD; // all current opcodes } /* --- Minimal C ABI helpers for FFI (Rust opcode experiments) --- */