diff --git a/source/cell.c b/source/cell.c index 8a9e3c5f..bcba91dc 100644 --- a/source/cell.c +++ b/source/cell.c @@ -399,33 +399,15 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - JSRuntime *rt = JS_NewRuntime(); - if (!rt) { - printf("Failed to create JS runtime\n"); - free(allocated_script); - return 1; - } - JSContext *ctx = JS_NewContext(rt); - if (!ctx) { - printf("Failed to create JS context\n"); - JS_FreeRuntime(rt); - free(allocated_script); - return 1; - } - - char *json = JS_AST(ctx, script, strlen(script), filename); + char *json = JS_AST(script, strlen(script), filename); if (json) { int has_errors = print_json_errors(json); printf("%s\n", json); free(json); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return has_errors ? 1 : 0; } else { printf("Failed to parse AST\n"); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } @@ -460,33 +442,15 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - JSRuntime *rt = JS_NewRuntime(); - if (!rt) { - printf("Failed to create JS runtime\n"); - free(allocated_script); - return 1; - } - JSContext *ctx = JS_NewContext(rt); - if (!ctx) { - printf("Failed to create JS context\n"); - JS_FreeRuntime(rt); - free(allocated_script); - return 1; - } - - char *json = JS_Tokenize(ctx, script, strlen(script), filename); + char *json = JS_Tokenize(script, strlen(script), filename); if (json) { int has_errors = print_json_errors(json); printf("%s\n", json); free(json); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return has_errors ? 1 : 0; } else { printf("Failed to tokenize\n"); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } @@ -521,51 +485,31 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - JSRuntime *rt = JS_NewRuntime(); - if (!rt) { - printf("Failed to create JS runtime\n"); - free(allocated_script); - return 1; - } - JSContext *ctx = JS_NewContext(rt); - if (!ctx) { - printf("Failed to create JS context\n"); - JS_FreeRuntime(rt); - free(allocated_script); - return 1; - } - - char *ast_json = JS_AST(ctx, script, strlen(script), filename); + char *ast_json = JS_AST(script, strlen(script), filename); if (!ast_json) { printf("Failed to parse AST\n"); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } if (print_json_errors(ast_json)) { free(ast_json); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } - char *mcode_json = JS_Mcode(ctx, ast_json); + char *mcode_json = JS_Mcode(ast_json); free(ast_json); if (!mcode_json) { printf("Failed to generate MCODE\n"); - JS_FreeContext(ctx); JS_FreeRuntime(rt); free(allocated_script); + free(allocated_script); return 1; } printf("%s\n", mcode_json); free(mcode_json); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 0; } @@ -592,40 +536,35 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - JSRuntime *rt = JS_NewRuntime(); - if (!rt) { printf("Failed to create JS runtime\n"); free(allocated_script); return 1; } - /* Use a parser context (small heap) for AST + MCODE generation */ - JSContext *parse_ctx = JS_NewContext(rt); - if (!parse_ctx) { printf("Failed to create JS context\n"); JS_FreeRuntime(rt); free(allocated_script); return 1; } - - char *ast_json = JS_AST(parse_ctx, script, strlen(script), filename); + char *ast_json = JS_AST(script, strlen(script), filename); if (!ast_json) { printf("Failed to parse AST\n"); - JS_FreeContext(parse_ctx); JS_FreeRuntime(rt); free(allocated_script); + free(allocated_script); return 1; } if (print_json_errors(ast_json)) { - free(ast_json); JS_FreeContext(parse_ctx); JS_FreeRuntime(rt); free(allocated_script); + free(ast_json); free(allocated_script); return 1; } - char *mcode_json = JS_Mcode(parse_ctx, ast_json); + char *mcode_json = JS_Mcode(ast_json); free(ast_json); - JS_FreeContext(parse_ctx); if (!mcode_json) { printf("Failed to generate MCODE\n"); - JS_FreeRuntime(rt); free(allocated_script); + free(allocated_script); return 1; } if (print_json_errors(mcode_json)) { - free(mcode_json); JS_FreeRuntime(rt); free(allocated_script); + free(mcode_json); free(allocated_script); return 1; } /* Use a larger heap context for execution */ + JSRuntime *rt = JS_NewRuntime(); + if (!rt) { printf("Failed to create JS runtime\n"); free(mcode_json); free(allocated_script); return 1; } JSContext *ctx = JS_NewContextWithHeapSize(rt, 64 * 1024); if (!ctx) { printf("Failed to create execution context\n"); free(mcode_json); JS_FreeRuntime(rt); free(allocated_script); return 1; } @@ -676,37 +615,32 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - JSRuntime *rt = JS_NewRuntime(); - if (!rt) { - printf("Failed to create JS runtime\n"); - free(allocated_script); - return 1; - } - JSContext *ctx = JS_NewContext(rt); - if (!ctx) { - printf("Failed to create JS context\n"); - JS_FreeRuntime(rt); - free(allocated_script); - return 1; - } - - char *ast_json = JS_AST(ctx, script, strlen(script), filename); + char *ast_json = JS_AST(script, strlen(script), filename); if (!ast_json) { printf("Failed to parse AST\n"); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } if (print_json_errors(ast_json)) { free(ast_json); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } + JSRuntime *rt = JS_NewRuntime(); + if (!rt) { + printf("Failed to create JS runtime\n"); + free(ast_json); free(allocated_script); + return 1; + } + JSContext *ctx = JS_NewContext(rt); + if (!ctx) { + printf("Failed to create JS context\n"); + free(ast_json); JS_FreeRuntime(rt); free(allocated_script); + return 1; + } + JS_DumpMach(ctx, ast_json, JS_NULL); free(ast_json); @@ -745,37 +679,32 @@ int cell_init(int argc, char **argv) script = (char *)script_or_file; } - JSRuntime *rt = JS_NewRuntime(); - if (!rt) { - printf("Failed to create JS runtime\n"); - free(allocated_script); - return 1; - } - JSContext *ctx = JS_NewContext(rt); - if (!ctx) { - printf("Failed to create JS context\n"); - JS_FreeRuntime(rt); - free(allocated_script); - return 1; - } - - char *ast_json = JS_AST(ctx, script, strlen(script), filename); + char *ast_json = JS_AST(script, strlen(script), filename); if (!ast_json) { printf("Failed to parse AST\n"); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } if (print_json_errors(ast_json)) { free(ast_json); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); free(allocated_script); return 1; } + JSRuntime *rt = JS_NewRuntime(); + if (!rt) { + printf("Failed to create JS runtime\n"); + free(ast_json); free(allocated_script); + return 1; + } + JSContext *ctx = JS_NewContext(rt); + if (!ctx) { + printf("Failed to create JS context\n"); + free(ast_json); JS_FreeRuntime(rt); free(allocated_script); + return 1; + } + JSValue result = JS_RunMach(ctx, ast_json, JS_NULL); free(ast_json); diff --git a/source/quickjs.c b/source/quickjs.c index a9832f19..bc9818ec 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -27857,7 +27857,6 @@ JSValue js_math_cycles_use (JSContext *ctx) { ============================================================ */ typedef struct ASTParseState { - JSContext *ctx; const char *filename; const uint8_t *buf_start; const uint8_t *buf_ptr; @@ -27870,23 +27869,42 @@ typedef struct ASTParseState { int has_error; union { struct { - JSValue str; + const char *str; + size_t len; } str; struct { - JSValue val; + double val; } num; struct { - JSValue str; + const char *str; + size_t len; BOOL has_escape; BOOL is_reserved; } ident; struct { - JSValue body; - JSValue flags; + const char *body; + size_t body_len; + const char *flags; + size_t flags_len; } regexp; } token_u; } ASTParseState; +/* Add a length-delimited string to a cJSON object (source pointers aren't null-terminated) */ +static void cjson_add_strn (cJSON *obj, const char *key, const char *str, size_t len) { + char *tmp = sys_malloc (len + 1); + memcpy (tmp, str, len); + tmp[len] = '\0'; + cJSON_AddStringToObject (obj, key, tmp); + sys_free (tmp); +} + +/* Compare a length-delimited token string against a null-terminated literal */ +static inline BOOL tok_eq (const char *str, size_t len, const char *lit) { + size_t ll = strlen (lit); + return len == ll && memcmp (str, lit, ll) == 0; +} + static cJSON *ast_parse_expr (ASTParseState *s); static cJSON *ast_parse_assign_expr (ASTParseState *s); static cJSON *ast_parse_statement (ASTParseState *s); @@ -28046,7 +28064,8 @@ redo: } p++; s->token_val = TOK_TEMPLATE; - s->token_u.str.str = JS_NewStringLen (s->ctx, (const char *)(start + 1), p - start - 2); + s->token_u.str.str = (const char *)(start + 1); + s->token_u.str.len = p - start - 2; } break; case '\'': case '\"': { @@ -28065,7 +28084,8 @@ redo: p++; /* Store the string content without quotes */ s->token_val = TOK_STRING; - s->token_u.str.str = JS_NewStringLen (s->ctx, (const char *)(start + 1), p - start - 2); + s->token_u.str.str = (const char *)(start + 1); + s->token_u.str.len = p - start - 2; } break; case '\r': if (p[1] == '\n') p++; @@ -28137,7 +28157,8 @@ redo: } } size_t len = p - start; - s->token_u.ident.str = JS_NewStringLen (s->ctx, (const char *)start, len); + s->token_u.ident.str = (const char *)start; + s->token_u.ident.len = len; s->token_u.ident.has_escape = ident_has_escape; s->token_u.ident.is_reserved = FALSE; s->token_val = TOK_IDENT; @@ -28222,7 +28243,7 @@ redo: numstr[p - start] = '\0'; double val = strtod (numstr, NULL); sys_free (numstr); - s->token_u.num.val = JS_NewFloat64 (s->ctx, val); + s->token_u.num.val = val; } break; case '*': if (p[1] == '=') { p += 2; s->token_val = TOK_MUL_ASSIGN; } @@ -28357,11 +28378,13 @@ static int tokenize_next (ASTParseState *s) { if (p >= s->buf_end) { ast_error (s, start, "unterminated template literal"); s->token_val = TOK_ERROR; - s->token_u.str.str = JS_NewStringLen (s->ctx, (const char *)(start + 1), p - start - 1); + s->token_u.str.str = (const char *)(start + 1); + s->token_u.str.len = p - start - 1; } else { p++; s->token_val = TOK_TEMPLATE; - s->token_u.str.str = JS_NewStringLen (s->ctx, (const char *)(start + 1), p - start - 2); + s->token_u.str.str = (const char *)(start + 1); + s->token_u.str.len = p - start - 2; } } break; case '\'': @@ -28376,11 +28399,13 @@ static int tokenize_next (ASTParseState *s) { if (p >= s->buf_end) { ast_error (s, start, "unterminated string literal"); s->token_val = TOK_ERROR; - s->token_u.str.str = JS_NewStringLen (s->ctx, (const char *)(start + 1), p - start - 1); + s->token_u.str.str = (const char *)(start + 1); + s->token_u.str.len = p - start - 1; } else { p++; s->token_val = TOK_STRING; - s->token_u.str.str = JS_NewStringLen (s->ctx, (const char *)(start + 1), p - start - 2); + s->token_u.str.str = (const char *)(start + 1); + s->token_u.str.len = p - start - 2; } } break; case '\r': @@ -28460,7 +28485,8 @@ static int tokenize_next (ASTParseState *s) { } } size_t len = p - start; - s->token_u.ident.str = JS_NewStringLen (s->ctx, (const char *)start, len); + s->token_u.ident.str = (const char *)start; + s->token_u.ident.len = len; s->token_u.ident.has_escape = ident_has_escape; s->token_u.ident.is_reserved = FALSE; s->token_val = TOK_IDENT; @@ -28544,7 +28570,7 @@ static int tokenize_next (ASTParseState *s) { numstr[p - start] = '\0'; double val = strtod (numstr, NULL); sys_free (numstr); - s->token_u.num.val = JS_NewFloat64 (s->ctx, val); + s->token_u.num.val = val; } break; case '*': if (p[1] == '=') { p += 2; s->token_val = TOK_MUL_ASSIGN; } @@ -28639,10 +28665,7 @@ static cJSON *ast_parse_primary (ASTParseState *s) { switch (s->token_val) { case TOK_NUMBER: { node = ast_node (s, "number", start); - double d = JS_VALUE_GET_FLOAT64 (s->token_u.num.val); - if (JS_VALUE_GET_TAG (s->token_u.num.val) == JS_TAG_INT) { - d = JS_VALUE_GET_INT (s->token_u.num.val); - } + double d = s->token_u.num.val; /* Store original text representation */ size_t len = s->buf_ptr - start; char *text = sys_malloc (len + 1); @@ -28657,9 +28680,7 @@ static cJSON *ast_parse_primary (ASTParseState *s) { case TOK_STRING: { node = ast_node (s, "text", start); - const char *str = JS_ToCString (s->ctx, s->token_u.str.str); - cJSON_AddStringToObject (node, "value", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "value", s->token_u.str.str, s->token_u.str.len); ast_node_end (s, node, s->buf_ptr); ast_next_token (s); } break; @@ -28681,9 +28702,7 @@ static cJSON *ast_parse_primary (ASTParseState *s) { if (!has_expr) { /* Simple template — unchanged behavior */ node = ast_node (s, "text", start); - const char *str = JS_ToCString (s->ctx, s->token_u.str.str); - cJSON_AddStringToObject (node, "value", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "value", s->token_u.str.str, s->token_u.str.len); ast_node_end (s, node, s->buf_ptr); ast_next_token (s); } else { @@ -28747,9 +28766,7 @@ static cJSON *ast_parse_primary (ASTParseState *s) { node = ast_parse_arrow_function (s); } else { node = ast_node (s, "name", start); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (node, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "name", s->token_u.ident.str, s->token_u.ident.len); ast_node_end (s, node, s->buf_ptr); ast_next_token (s); } @@ -28845,9 +28862,7 @@ static cJSON *ast_parse_primary (ASTParseState *s) { while (s->token_val != ')' && s->token_val != TOK_EOF) { if (s->token_val == TOK_IDENT) { cJSON *param = ast_node (s, "name", s->token_ptr); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (param, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (param, "name", s->token_u.ident.str, s->token_u.ident.len); ast_node_end (s, param, s->buf_ptr); ast_next_token (s); if (s->token_val == '=' || s->token_val == '|') { @@ -28994,9 +29009,7 @@ static cJSON *ast_parse_postfix (ASTParseState *s) { cJSON *new_node = ast_node (s, ".", start); cJSON_AddItemToObject (new_node, "left", node); if (s->token_val == TOK_IDENT) { - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (new_node, "right", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (new_node, "right", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); } else { ast_error (s, s->token_ptr, "expected property name after '.'"); @@ -29079,9 +29092,7 @@ static cJSON *ast_parse_postfix (ASTParseState *s) { /* Optional property access: o?.a */ cJSON *new_node = ast_node (s, "?.", start); cJSON_AddItemToObject (new_node, "left", node); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (new_node, "right", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (new_node, "right", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); ast_node_end (s, new_node, s->buf_ptr); node = new_node; @@ -29363,9 +29374,7 @@ static cJSON *ast_parse_function_inner (ASTParseState *s, BOOL is_expr) { /* Optional function name */ if (s->token_val == TOK_IDENT) { - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (node, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "name", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); } @@ -29377,18 +29386,22 @@ static cJSON *ast_parse_function_inner (ASTParseState *s, BOOL is_expr) { if (s->token_val == TOK_IDENT) { const uint8_t *param_ptr = s->token_ptr; cJSON *param = ast_node (s, "name", param_ptr); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (param, "name", str ? str : ""); + cjson_add_strn (param, "name", s->token_u.ident.str, s->token_u.ident.len); /* Check for duplicate parameter name */ - cJSON *prev; - cJSON_ArrayForEach (prev, params) { - const char *prev_name = cJSON_GetStringValue (cJSON_GetObjectItem (prev, "name")); - if (prev_name && str && strcmp (prev_name, str) == 0) { - ast_error (s, param_ptr, "duplicate parameter name '%s'", str); - break; + { + char *tmp_name = sys_malloc (s->token_u.ident.len + 1); + memcpy (tmp_name, s->token_u.ident.str, s->token_u.ident.len); + tmp_name[s->token_u.ident.len] = '\0'; + cJSON *prev; + cJSON_ArrayForEach (prev, params) { + const char *prev_name = cJSON_GetStringValue (cJSON_GetObjectItem (prev, "name")); + if (prev_name && strcmp (prev_name, tmp_name) == 0) { + ast_error (s, param_ptr, "duplicate parameter name '%s'", tmp_name); + break; + } } + sys_free (tmp_name); } - JS_FreeCString (s->ctx, str); ast_node_end (s, param, s->buf_ptr); ast_next_token (s); if (s->token_val == '=' || s->token_val == '|') { @@ -29448,9 +29461,7 @@ static cJSON *ast_parse_arrow_function (ASTParseState *s) { if (s->token_val == TOK_IDENT) { /* Single parameter without parens: x => ... */ cJSON *param = ast_node (s, "name", s->token_ptr); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (param, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (param, "name", s->token_u.ident.str, s->token_u.ident.len); ast_node_end (s, param, s->buf_ptr); cJSON_AddItemToArray (params, param); ast_next_token (s); @@ -29461,18 +29472,22 @@ static cJSON *ast_parse_arrow_function (ASTParseState *s) { if (s->token_val == TOK_IDENT) { const uint8_t *param_ptr = s->token_ptr; cJSON *param = ast_node (s, "name", param_ptr); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (param, "name", str ? str : ""); + cjson_add_strn (param, "name", s->token_u.ident.str, s->token_u.ident.len); /* Check for duplicate parameter name */ - cJSON *prev; - cJSON_ArrayForEach (prev, params) { - const char *prev_name = cJSON_GetStringValue (cJSON_GetObjectItem (prev, "name")); - if (prev_name && str && strcmp (prev_name, str) == 0) { - ast_error (s, param_ptr, "duplicate parameter name '%s'", str); - break; + { + char *tmp_name = sys_malloc (s->token_u.ident.len + 1); + memcpy (tmp_name, s->token_u.ident.str, s->token_u.ident.len); + tmp_name[s->token_u.ident.len] = '\0'; + cJSON *prev; + cJSON_ArrayForEach (prev, params) { + const char *prev_name = cJSON_GetStringValue (cJSON_GetObjectItem (prev, "name")); + if (prev_name && strcmp (prev_name, tmp_name) == 0) { + ast_error (s, param_ptr, "duplicate parameter name '%s'", tmp_name); + break; + } } + sys_free (tmp_name); } - JS_FreeCString (s->ctx, str); ast_node_end (s, param, s->buf_ptr); ast_next_token (s); @@ -29587,8 +29602,11 @@ static cJSON *ast_parse_statement (ASTParseState *s) { const uint8_t *var_ptr = s->token_ptr; node = ast_node (s, kind_name, start); cJSON *left = ast_node (s, "name", s->token_ptr); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (left, "name", str ? str : ""); + cjson_add_strn (left, "name", s->token_u.ident.str, s->token_u.ident.len); + /* Save name for potential error message */ + char *var_name = sys_malloc (s->token_u.ident.len + 1); + memcpy (var_name, s->token_u.ident.str, s->token_u.ident.len); + var_name[s->token_u.ident.len] = '\0'; ast_node_end (s, left, s->buf_ptr); cJSON_AddItemToObject (node, "left", left); ast_next_token (s); @@ -29602,9 +29620,9 @@ static cJSON *ast_parse_statement (ASTParseState *s) { cJSON_AddBoolToObject (node, "pop", 1); } else if (is_def) { /* def (constant) requires initializer */ - ast_error (s, var_ptr, "missing initializer for constant '%s'", str); + ast_error (s, var_ptr, "missing initializer for constant '%s'", var_name); } - JS_FreeCString (s->ctx, str); + sys_free (var_name); ast_node_end (s, node, s->buf_ptr); cJSON_AddItemToArray (decls, node); decl_count++; @@ -29772,9 +29790,7 @@ static cJSON *ast_parse_statement (ASTParseState *s) { node = ast_node (s, "break", start); ast_next_token (s); if (s->token_val == TOK_IDENT && !s->got_lf) { - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (node, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "name", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); } ast_expect_semi (s); @@ -29785,9 +29801,7 @@ static cJSON *ast_parse_statement (ASTParseState *s) { node = ast_node (s, "continue", start); ast_next_token (s); if (s->token_val == TOK_IDENT && !s->got_lf) { - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (node, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "name", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); } ast_expect_semi (s); @@ -29816,9 +29830,7 @@ static cJSON *ast_parse_statement (ASTParseState *s) { if (s->token_val == '(') { ast_next_token (s); if (s->token_val == TOK_IDENT) { - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (catch_node, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (catch_node, "name", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); } if (s->token_val == ')') ast_next_token (s); @@ -29864,9 +29876,7 @@ static cJSON *ast_parse_statement (ASTParseState *s) { if (p < s->buf_end && *p == ':') { /* Labeled statement */ node = ast_node (s, "label", start); - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (node, "name", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (node, "name", s->token_u.ident.str, s->token_u.ident.len); ast_next_token (s); /* skip identifier */ ast_next_token (s); /* skip colon */ cJSON *stmt = ast_parse_statement (s); @@ -30540,11 +30550,10 @@ static void ast_semantic_check (cJSON *ast, cJSON **errors_out, *intrinsics_out = intr_arr; } -char *JS_AST (JSContext *ctx, const char *source, size_t len, const char *filename) { +char *JS_AST (const char *source, size_t len, const char *filename) { ASTParseState s; memset (&s, 0, sizeof (s)); - s.ctx = ctx; s.filename = filename; s.buf_start = (const uint8_t *)source; s.buf_ptr = (const uint8_t *)source; @@ -30628,22 +30637,15 @@ static cJSON *build_token_object (ASTParseState *s) { cJSON_AddStringToObject (tok, "value", text); sys_free (text); /* Store parsed number */ - double d = JS_VALUE_GET_FLOAT64 (s->token_u.num.val); - if (JS_VALUE_GET_TAG (s->token_u.num.val) == JS_TAG_INT) { - d = JS_VALUE_GET_INT (s->token_u.num.val); - } + double d = s->token_u.num.val; cJSON_AddNumberToObject (tok, "number", d); } break; case TOK_STRING: case TOK_TEMPLATE: { - const char *str = JS_ToCString (s->ctx, s->token_u.str.str); - cJSON_AddStringToObject (tok, "value", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (tok, "value", s->token_u.str.str, s->token_u.str.len); } break; case TOK_IDENT: { - const char *str = JS_ToCString (s->ctx, s->token_u.ident.str); - cJSON_AddStringToObject (tok, "value", str ? str : ""); - JS_FreeCString (s->ctx, str); + cjson_add_strn (tok, "value", s->token_u.ident.str, s->token_u.ident.len); } break; case TOK_ERROR: { /* Store the raw source text as value */ @@ -30673,11 +30675,10 @@ static cJSON *build_token_object (ASTParseState *s) { return tok; } -char *JS_Tokenize (JSContext *ctx, const char *source, size_t len, const char *filename) { +char *JS_Tokenize (const char *source, size_t len, const char *filename) { ASTParseState s; memset (&s, 0, sizeof (s)); - s.ctx = ctx; s.filename = filename; s.buf_start = (const uint8_t *)source; s.buf_ptr = (const uint8_t *)source; @@ -30731,21 +30732,39 @@ typedef struct MachVarInfo { } MachVarInfo; /* ---- Compile-time constant pool entry ---- */ -/* Stores raw data during compilation; converted to JSValues when building JSCodeRegister */ -typedef enum { MACH_CP_IMM, MACH_CP_STR } MachCPType; +/* Stores raw data during compilation; converted to JSValues when loading into context */ +typedef enum { MACH_CP_INT, MACH_CP_FLOAT, MACH_CP_STR } MachCPType; typedef struct { MachCPType type; union { - JSValue val; /* immediate value (int, float) - no GC alloc */ + int32_t ival; /* integer constant */ + double fval; /* float constant */ char *str; /* owned C string */ }; } MachCPoolEntry; +/* ---- Compiled output (context-free) ---- */ +typedef struct MachCode { + uint16_t arity; + uint16_t nr_close_slots; + uint16_t nr_slots; + uint16_t entry_point; + + uint32_t cpool_count; + MachCPoolEntry *cpool; + + uint32_t instr_count; + MachInstr32 *instructions; + + uint32_t func_count; + struct MachCode **functions; + + char *name; /* owned C string, or NULL */ +} MachCode; + /* ---- Compiler state ---- */ typedef struct MachCompState { - JSContext *ctx; - /* Instruction buffer (growable) */ MachInstr32 *code; int code_count; @@ -30757,7 +30776,7 @@ typedef struct MachCompState { int cpool_capacity; /* Nested functions */ - JSCodeRegister **functions; + MachCode **functions; int func_count; int func_capacity; @@ -30820,26 +30839,33 @@ static void mach_free_reg_to(MachCompState *cs, int saved) { cs->freereg = saved; } -/* Add a constant to the pool, return its index */ -static int mach_cpool_add(MachCompState *cs, JSValue val) { - /* Check for duplicates (immediate values only) */ +/* Add an integer constant to the pool, return its index */ +static int mach_cpool_add_int(MachCompState *cs, int32_t val) { for (int i = 0; i < cs->cpool_count; i++) { MachCPoolEntry *e = &cs->cpool[i]; - if (e->type != MACH_CP_IMM) continue; - if (JS_IsInt(val) && JS_IsInt(e->val)) { - if (JS_VALUE_GET_INT(val) == JS_VALUE_GET_INT(e->val)) - return i; - } else if (e->val == val) { - return i; - } + if (e->type == MACH_CP_INT && e->ival == val) return i; } - if (cs->cpool_count >= cs->cpool_capacity) { int new_cap = cs->cpool_capacity ? cs->cpool_capacity * 2 : 16; cs->cpool = sys_realloc(cs->cpool, new_cap * sizeof(MachCPoolEntry)); cs->cpool_capacity = new_cap; } - cs->cpool[cs->cpool_count] = (MachCPoolEntry){ .type = MACH_CP_IMM, .val = val }; + cs->cpool[cs->cpool_count] = (MachCPoolEntry){ .type = MACH_CP_INT, .ival = val }; + return cs->cpool_count++; +} + +/* Add a float constant to the pool, return its index */ +static int mach_cpool_add_float(MachCompState *cs, double val) { + for (int i = 0; i < cs->cpool_count; i++) { + MachCPoolEntry *e = &cs->cpool[i]; + if (e->type == MACH_CP_FLOAT && e->fval == val) return i; + } + if (cs->cpool_count >= cs->cpool_capacity) { + int new_cap = cs->cpool_capacity ? cs->cpool_capacity * 2 : 16; + cs->cpool = sys_realloc(cs->cpool, new_cap * sizeof(MachCPoolEntry)); + cs->cpool_capacity = new_cap; + } + cs->cpool[cs->cpool_count] = (MachCPoolEntry){ .type = MACH_CP_FLOAT, .fval = val }; return cs->cpool_count++; } @@ -30869,14 +30895,18 @@ static JSValue *mach_materialize_cpool(JSContext *ctx, MachCPoolEntry *entries, if (count == 0) { sys_free(entries); return NULL; } JSValue *cpool = js_malloc_rt(count * sizeof(JSValue)); for (int i = 0; i < count; i++) { - if (entries[i].type == MACH_CP_STR) { + switch (entries[i].type) { + case MACH_CP_INT: + cpool[i] = JS_NewInt32(ctx, entries[i].ival); + break; + case MACH_CP_FLOAT: + cpool[i] = JS_NewFloat64(ctx, entries[i].fval); + break; + case MACH_CP_STR: cpool[i] = js_key_new(ctx, entries[i].str); - sys_free(entries[i].str); - } else { - cpool[i] = entries[i].val; + break; } } - sys_free(entries); return cpool; } @@ -30904,10 +30934,10 @@ static int mach_find_var(MachCompState *cs, const char *name) { } /* Add a nested function, return its index */ -static int mach_add_function(MachCompState *cs, JSCodeRegister *fn) { +static int mach_add_function(MachCompState *cs, MachCode *fn) { if (cs->func_count >= cs->func_capacity) { int new_cap = cs->func_capacity ? cs->func_capacity * 2 : 4; - cs->functions = sys_realloc(cs->functions, new_cap * sizeof(JSCodeRegister*)); + cs->functions = sys_realloc(cs->functions, new_cap * sizeof(MachCode*)); cs->func_capacity = new_cap; } cs->functions[cs->func_count] = fn; @@ -30976,12 +31006,11 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) { mach_emit(cs, MACH_AsBx(MACH_LOADI, dest, (int16_t)ival)); } else { /* Large number: use constant pool */ - JSValue val; + int ki; if (dval == (double)(int32_t)dval) - val = JS_NewInt32(cs->ctx, (int32_t)dval); + ki = mach_cpool_add_int(cs, (int32_t)dval); else - val = JS_NewFloat64(cs->ctx, dval); - int ki = mach_cpool_add(cs, val); + ki = mach_cpool_add_float(cs, dval); mach_emit(cs, MACH_ABx(MACH_LOADK, dest, ki)); } } else { @@ -31417,7 +31446,6 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) { if (dest < 0) dest = mach_reserve_reg(cs); /* Compile nested function */ MachCompState child = {0}; - child.ctx = cs->ctx; child.parent = cs; child.scopes = cs->scopes; child.freereg = 1; /* slot 0 = this */ @@ -31460,10 +31488,11 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) { /* Implicit return null */ mach_emit(&child, MACH_ABC(MACH_RETNIL, 0, 0, 0)); - /* Build JSCodeRegister for the child function */ + /* Build MachCode for the child function */ cJSON *fn_scope = mach_find_scope_record(cs->scopes, child.function_nr); cJSON *fn_ncs = fn_scope ? cJSON_GetObjectItem(fn_scope, "nr_close_slots") : NULL; - JSCodeRegister *fn_code = js_mallocz_rt(sizeof(JSCodeRegister)); + MachCode *fn_code = sys_malloc(sizeof(MachCode)); + memset(fn_code, 0, sizeof(MachCode)); fn_code->arity = nparams; fn_code->nr_slots = child.maxreg; fn_code->nr_close_slots = fn_ncs ? (int)cJSON_GetNumberValue(fn_ncs) : 0; @@ -31471,15 +31500,17 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) { fn_code->instr_count = child.code_count; fn_code->instructions = child.code; fn_code->cpool_count = child.cpool_count; - fn_code->cpool = mach_materialize_cpool(cs->ctx, child.cpool, child.cpool_count); + fn_code->cpool = child.cpool; fn_code->func_count = child.func_count; fn_code->functions = child.functions; cJSON *fname = cJSON_GetObjectItem(node, "name"); if (fname && cJSON_IsString(fname)) { - fn_code->name = js_key_new(cs->ctx, cJSON_GetStringValue(fname)); + const char *ns = cJSON_GetStringValue(fname); + fn_code->name = sys_malloc(strlen(ns) + 1); + strcpy(fn_code->name, ns); } else { - fn_code->name = JS_NULL; + fn_code->name = NULL; } /* Free child var table (not code/cpool, those are owned by fn_code now) */ @@ -31752,7 +31783,7 @@ static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) { /* ---- Top-level compiler ---- */ -static JSCodeRegister *mach_compile_program(MachCompState *cs, cJSON *ast, JSValue env) { +static MachCode *mach_compile_program(MachCompState *cs, cJSON *ast) { cJSON *stmts = cJSON_GetObjectItem(ast, "statements"); if (!stmts || !cJSON_IsArray(stmts)) return NULL; @@ -31776,8 +31807,9 @@ static JSCodeRegister *mach_compile_program(MachCompState *cs, cJSON *ast, JSVal cJSON *prog_scope = mach_find_scope_record(cs->scopes, 0); cJSON *ncs_node = prog_scope ? cJSON_GetObjectItem(prog_scope, "nr_close_slots") : NULL; - /* Build JSCodeRegister */ - JSCodeRegister *code = js_mallocz_rt(sizeof(JSCodeRegister)); + /* Build MachCode */ + MachCode *code = sys_malloc(sizeof(MachCode)); + memset(code, 0, sizeof(MachCode)); code->arity = 0; code->nr_slots = cs->maxreg; code->nr_close_slots = ncs_node ? (int)cJSON_GetNumberValue(ncs_node) : 0; @@ -31785,30 +31817,26 @@ static JSCodeRegister *mach_compile_program(MachCompState *cs, cJSON *ast, JSVal code->instr_count = cs->code_count; code->instructions = cs->code; code->cpool_count = cs->cpool_count; - code->cpool = mach_materialize_cpool(cs->ctx, cs->cpool, cs->cpool_count); + code->cpool = cs->cpool; code->func_count = cs->func_count; code->functions = cs->functions; - code->name = JS_NULL; + code->name = NULL; return code; } -/* Public API: compile AST JSON to JSCodeRegister */ -JSCodeRegister *JS_CompileMach(JSContext *ctx, const char *ast_json, JSValue env) { +/* Public API: compile AST JSON to MachCode (context-free) */ +MachCode *JS_CompileMach(const char *ast_json) { cJSON *ast = cJSON_Parse(ast_json); if (!ast) return NULL; MachCompState cs = {0}; - cs.ctx = ctx; cs.freereg = 1; /* slot 0 = this */ cs.maxreg = 1; - JSCodeRegister *code = mach_compile_program(&cs, ast, env); + MachCode *code = mach_compile_program(&cs, ast); - /* Link: resolve GETNAME to GETINTRINSIC/GETENV */ - if (code) mach_link_code(ctx, code, env); - - /* Free var table (code/cpool/functions are owned by JSCodeRegister now) */ + /* Free var table (code/cpool/functions are owned by MachCode now) */ for (int i = 0; i < cs.var_count; i++) sys_free(cs.vars[i].name); sys_free(cs.vars); @@ -31817,6 +31845,55 @@ JSCodeRegister *JS_CompileMach(JSContext *ctx, const char *ast_json, JSValue env return code; } +/* Free a MachCode tree (compiled but not yet loaded) */ +void JS_FreeMachCode(MachCode *mc) { + if (!mc) return; + sys_free(mc->instructions); + for (uint32_t i = 0; i < mc->cpool_count; i++) { + if (mc->cpool[i].type == MACH_CP_STR) + sys_free(mc->cpool[i].str); + } + sys_free(mc->cpool); + for (uint32_t i = 0; i < mc->func_count; i++) + JS_FreeMachCode(mc->functions[i]); + sys_free(mc->functions); + sys_free(mc->name); + sys_free(mc); +} + +/* Load a MachCode into a JSCodeRegister (materializes JSValues, needs ctx) */ +JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env) { + JSCodeRegister *code = js_mallocz_rt(sizeof(JSCodeRegister)); + code->arity = mc->arity; + code->nr_close_slots = mc->nr_close_slots; + code->nr_slots = mc->nr_slots; + code->entry_point = mc->entry_point; + code->instr_count = mc->instr_count; + code->instructions = mc->instructions; /* transfer ownership */ + + /* Materialize cpool: raw -> JSValue */ + code->cpool_count = mc->cpool_count; + code->cpool = mach_materialize_cpool(ctx, mc->cpool, mc->cpool_count); + + /* Recursively load nested functions */ + code->func_count = mc->func_count; + if (mc->func_count > 0) { + code->functions = js_malloc_rt(mc->func_count * sizeof(JSCodeRegister *)); + for (uint32_t i = 0; i < mc->func_count; i++) + code->functions[i] = JS_LoadMachCode(ctx, mc->functions[i], env); + } else { + code->functions = NULL; + } + + /* Intern function name */ + code->name = mc->name ? js_key_new(ctx, mc->name) : JS_NULL; + + /* Link: resolve GETNAME to GETENV/GETINTRINSIC */ + mach_link_code(ctx, code, env); + + return code; +} + /* Free a JSCodeRegister and all nested functions */ static void js_free_code_register(JSCodeRegister *code) { if (!code) return; @@ -32457,7 +32534,6 @@ done: ============================================================ */ typedef struct MachGenState { - JSContext *ctx; cJSON *instructions; cJSON *data; cJSON *functions; @@ -33570,7 +33646,6 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) { static cJSON *mach_gen_function (MachGenState *parent, cJSON *func_node) { MachGenState s = {0}; - s.ctx = parent->ctx; s.instructions = cJSON_CreateArray (); s.data = parent->data; s.functions = parent->functions; @@ -33734,12 +33809,11 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) { return result; } -char *JS_Mcode (JSContext *ctx, const char *ast_json) { +char *JS_Mcode (const char *ast_json) { cJSON *ast = cJSON_Parse (ast_json); if (!ast) return NULL; MachGenState s = {0}; - s.ctx = ctx; s.instructions = cJSON_CreateArray (); s.errors = NULL; s.has_error = 0; @@ -34929,12 +35003,13 @@ static void dump_register_code(JSContext *ctx, JSCodeRegister *code, int indent) /* Dump MACH bytecode to stdout for debugging. Takes AST JSON. */ void JS_DumpMach(JSContext *ctx, const char *ast_json, JSValue env) { - JSCodeRegister *code = JS_CompileMach(ctx, ast_json, env); - if (!code) { + MachCode *mc = JS_CompileMach(ast_json); + if (!mc) { printf("=== MACH Bytecode ===\nFailed to compile\n=== End MACH Bytecode ===\n"); return; } + JSCodeRegister *code = JS_LoadMachCode(ctx, mc, env); printf("=== MACH Bytecode ===\n"); dump_register_code(ctx, code, 0); printf("=== End MACH Bytecode ===\n"); @@ -34942,11 +35017,12 @@ void JS_DumpMach(JSContext *ctx, const char *ast_json, JSValue env) { /* Compile and execute MACH bytecode. Takes AST JSON. */ JSValue JS_RunMach(JSContext *ctx, const char *ast_json, JSValue env) { - JSCodeRegister *code = JS_CompileMach(ctx, ast_json, env); - if (!code) { + MachCode *mc = JS_CompileMach(ast_json); + if (!mc) { return JS_ThrowSyntaxError(ctx, "failed to compile AST to MACH bytecode"); } + JSCodeRegister *code = JS_LoadMachCode(ctx, mc, env); JSValue result = JS_CallRegisterVM(ctx, code, ctx->global_obj, 0, NULL, env, JS_NULL); return result; } diff --git a/source/quickjs.h b/source/quickjs.h index d03aa1f1..b9ce74c3 100644 --- a/source/quickjs.h +++ b/source/quickjs.h @@ -1219,29 +1219,42 @@ CellModule *cell_module_from_bytecode (JSContext *ctx, JSFunctionBytecode *main_ CellModule *JS_CompileModule (JSContext *ctx, const char *input, size_t input_len, const char *filename); /* Parse source code and return AST as JSON string. - Returns malloc'd JSON string (caller must free), or NULL on error. */ -char *JS_AST (JSContext *ctx, const char *source, size_t len, const char *filename); + Returns malloc'd JSON string (caller must free), or NULL on error. + No JSContext needed — pure string transformation. */ +char *JS_AST (const char *source, size_t len, const char *filename); /* Tokenize source code and return token array as JSON string. - Returns malloc'd JSON string (caller must free), or NULL on error. */ -char *JS_Tokenize (JSContext *ctx, const char *source, size_t len, const char *filename); + Returns malloc'd JSON string (caller must free), or NULL on error. + No JSContext needed — pure string transformation. */ +char *JS_Tokenize (const char *source, size_t len, const char *filename); -/* Compile AST JSON directly to register bytecode. - Returns JSCodeRegister* (caller should not free — managed by context), or NULL on error. */ -struct JSCodeRegister *JS_CompileMach(JSContext *ctx, const char *ast_json, JSValue env); +/* Compiled bytecode (context-free, serializable) */ +typedef struct MachCode MachCode; + +/* Compile AST JSON to context-free MachCode. + Returns MachCode* (caller must free with JS_FreeMachCode), or NULL on error. */ +MachCode *JS_CompileMach(const char *ast_json); + +/* Free a compiled MachCode tree. */ +void JS_FreeMachCode(MachCode *mc); + +/* Load compiled MachCode into a JSContext, materializing JSValues. + Returns JSCodeRegister* linked and ready for execution. */ +struct JSCodeRegister *JS_LoadMachCode(JSContext *ctx, MachCode *mc, JSValue env); /* Dump MACH bytecode to stdout for debugging. Takes AST JSON. - Internally generates MCODE and links to binary bytecode. */ + Internally compiles, loads, and dumps binary bytecode. */ void JS_DumpMach (JSContext *ctx, const char *ast_json, JSValue env); /* Compile and execute MACH bytecode. Takes AST JSON. - Internally generates MCODE and links to binary bytecode. + Internally compiles, loads, and executes. Returns result of execution, or JS_EXCEPTION on error. */ JSValue JS_RunMach (JSContext *ctx, const char *ast_json, JSValue env); /* Compile AST JSON to MCODE JSON (string-based IR). - Returns malloc'd JSON string, or NULL on error. Caller must free. */ -char *JS_Mcode (JSContext *ctx, const char *ast_json); + Returns malloc'd JSON string, or NULL on error. Caller must free. + No JSContext needed — pure string transformation. */ +char *JS_Mcode (const char *ast_json); /* Parse and execute MCODE JSON directly via the MCODE interpreter. Returns result of execution, or JS_EXCEPTION on error. */ diff --git a/source/suite.c b/source/suite.c index 250971f6..f2e3ffb0 100644 --- a/source/suite.c +++ b/source/suite.c @@ -2190,7 +2190,7 @@ TEST(cell_module_string_constant) { TEST(tokenize_unterminated_string) { const char *src = "var x = \"hello"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "unterminated string"); free(json); @@ -2199,7 +2199,7 @@ TEST(tokenize_unterminated_string) { TEST(tokenize_unterminated_template) { const char *src = "var x = `hello"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "unterminated template"); free(json); @@ -2208,7 +2208,7 @@ TEST(tokenize_unterminated_template) { TEST(tokenize_unterminated_block_comment) { const char *src = "var x /* comment"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "unterminated block comment"); free(json); @@ -2217,7 +2217,7 @@ TEST(tokenize_unterminated_block_comment) { TEST(tokenize_malformed_hex) { const char *src = "var x = 0x"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "malformed hex"); free(json); @@ -2226,7 +2226,7 @@ TEST(tokenize_malformed_hex) { TEST(tokenize_malformed_binary) { const char *src = "var x = 0b"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "malformed binary"); free(json); @@ -2235,7 +2235,7 @@ TEST(tokenize_malformed_binary) { TEST(tokenize_malformed_exponent) { const char *src = "var x = 1e+"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "no digits after exponent"); free(json); @@ -2244,7 +2244,7 @@ TEST(tokenize_malformed_exponent) { TEST(tokenize_valid_no_errors) { const char *src = "var x = 42"; - char *json = JS_Tokenize(ctx, src, strlen(src), ""); + char *json = JS_Tokenize(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_Tokenize returned NULL"); ASSERT_NO_ERRORS(json); free(json); @@ -2257,7 +2257,7 @@ TEST(tokenize_valid_no_errors) { TEST(ast_missing_identifier_after_var) { const char *src = "var = 1"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "expected identifier"); free(json); @@ -2266,7 +2266,7 @@ TEST(ast_missing_identifier_after_var) { TEST(ast_missing_initializer_def) { const char *src = "def x"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "missing initializer"); free(json); @@ -2275,7 +2275,7 @@ TEST(ast_missing_initializer_def) { TEST(ast_recovery_continues_after_error) { const char *src = "var = 1; var y = 2"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_HAS_ERRORS(json, 1); /* Check that 'y' statement is present in the AST */ @@ -2286,7 +2286,7 @@ TEST(ast_recovery_continues_after_error) { TEST(ast_valid_no_errors) { const char *src = "var x = 1; var y = 2"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_NO_ERRORS(json); free(json); @@ -2299,7 +2299,7 @@ TEST(ast_valid_no_errors) { TEST(ast_sem_assign_to_const) { const char *src = "def x = 5; x = 3"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "cannot assign to constant"); free(json); @@ -2308,7 +2308,7 @@ TEST(ast_sem_assign_to_const) { TEST(ast_sem_assign_to_arg) { const char *src = "function(x) { x = 5; }"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "cannot assign to constant"); free(json); @@ -2317,7 +2317,7 @@ TEST(ast_sem_assign_to_arg) { TEST(ast_sem_redeclare_const) { const char *src = "def x = 1; def x = 2"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "cannot redeclare constant"); free(json); @@ -2326,7 +2326,7 @@ TEST(ast_sem_redeclare_const) { TEST(ast_sem_break_outside_loop) { const char *src = "break"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "outside of loop"); free(json); @@ -2335,7 +2335,7 @@ TEST(ast_sem_break_outside_loop) { TEST(ast_sem_continue_outside_loop) { const char *src = "continue"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "outside of loop"); free(json); @@ -2344,7 +2344,7 @@ TEST(ast_sem_continue_outside_loop) { TEST(ast_sem_break_inside_loop_ok) { const char *src = "while (true) { break; }"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_NO_ERRORS(json); free(json); @@ -2353,7 +2353,7 @@ TEST(ast_sem_break_inside_loop_ok) { TEST(ast_sem_increment_const) { const char *src = "def x = 1; x++"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_ERROR_MSG_CONTAINS(json, "cannot assign to constant"); free(json); @@ -2362,7 +2362,7 @@ TEST(ast_sem_increment_const) { TEST(ast_sem_shadow_var_ok) { const char *src = "var array = []; array"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_NO_ERRORS(json); free(json); @@ -2371,7 +2371,7 @@ TEST(ast_sem_shadow_var_ok) { TEST(ast_sem_var_assign_ok) { const char *src = "var x = 1; x = x + 1"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_NO_ERRORS(json); free(json); @@ -2380,7 +2380,7 @@ TEST(ast_sem_var_assign_ok) { TEST(ast_sem_nested_function_scope) { const char *src = "var x = 1; function f(x) { return x + 1; }"; - char *json = JS_AST(ctx, src, strlen(src), ""); + char *json = JS_AST(src, strlen(src), ""); ASSERT_MSG(json != NULL, "JS_AST returned NULL"); ASSERT_NO_ERRORS(json); free(json); @@ -2393,21 +2393,23 @@ TEST(ast_sem_nested_function_scope) { TEST(mach_compile_basic) { const char *src = "var x = 1; x = x + 1"; - char *ast_json = JS_AST(ctx, src, strlen(src), ""); + char *ast_json = JS_AST(src, strlen(src), ""); ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL"); - struct JSCodeRegister *code = JS_CompileMach(ctx, ast_json, JS_NULL); + MachCode *mc = JS_CompileMach(ast_json); free(ast_json); - ASSERT_MSG(code != NULL, "JS_CompileMach returned NULL"); + ASSERT_MSG(mc != NULL, "JS_CompileMach returned NULL"); + JS_FreeMachCode(mc); return 1; } TEST(mach_compile_function) { const char *src = "function f(x) { return x + 1 }"; - char *ast_json = JS_AST(ctx, src, strlen(src), ""); + char *ast_json = JS_AST(src, strlen(src), ""); ASSERT_MSG(ast_json != NULL, "JS_AST returned NULL"); - struct JSCodeRegister *code = JS_CompileMach(ctx, ast_json, JS_NULL); + MachCode *mc = JS_CompileMach(ast_json); free(ast_json); - ASSERT_MSG(code != NULL, "JS_CompileMach returned NULL"); + ASSERT_MSG(mc != NULL, "JS_CompileMach returned NULL"); + JS_FreeMachCode(mc); return 1; }