|
|
|
@@ -8547,10 +8547,8 @@ enum {
|
|
|
|
TOK_FOR,
|
|
|
|
TOK_FOR,
|
|
|
|
TOK_BREAK,
|
|
|
|
TOK_BREAK,
|
|
|
|
TOK_CONTINUE,
|
|
|
|
TOK_CONTINUE,
|
|
|
|
TOK_THROW,
|
|
|
|
TOK_DISRUPT,
|
|
|
|
TOK_TRY,
|
|
|
|
TOK_DISRUPTION,
|
|
|
|
TOK_CATCH,
|
|
|
|
|
|
|
|
TOK_FINALLY,
|
|
|
|
|
|
|
|
TOK_FUNCTION,
|
|
|
|
TOK_FUNCTION,
|
|
|
|
TOK_DEBUGGER,
|
|
|
|
TOK_DEBUGGER,
|
|
|
|
TOK_WITH,
|
|
|
|
TOK_WITH,
|
|
|
|
@@ -8653,10 +8651,8 @@ static const char *ast_token_kind_str(int token_val) {
|
|
|
|
case TOK_FOR: return "for";
|
|
|
|
case TOK_FOR: return "for";
|
|
|
|
case TOK_BREAK: return "break";
|
|
|
|
case TOK_BREAK: return "break";
|
|
|
|
case TOK_CONTINUE: return "continue";
|
|
|
|
case TOK_CONTINUE: return "continue";
|
|
|
|
case TOK_THROW: return "throw";
|
|
|
|
case TOK_DISRUPT: return "disrupt";
|
|
|
|
case TOK_TRY: return "try";
|
|
|
|
case TOK_DISRUPTION: return "disruption";
|
|
|
|
case TOK_CATCH: return "catch";
|
|
|
|
|
|
|
|
case TOK_FINALLY: return "finally";
|
|
|
|
|
|
|
|
case TOK_FUNCTION: return "function";
|
|
|
|
case TOK_FUNCTION: return "function";
|
|
|
|
case TOK_DEBUGGER: return "debugger";
|
|
|
|
case TOK_DEBUGGER: return "debugger";
|
|
|
|
case TOK_WITH: return "with";
|
|
|
|
case TOK_WITH: return "with";
|
|
|
|
@@ -9808,10 +9804,8 @@ static const JSKeywordEntry js_keywords[] = {
|
|
|
|
{ "for", TOK_FOR, FALSE },
|
|
|
|
{ "for", TOK_FOR, FALSE },
|
|
|
|
{ "break", TOK_BREAK, FALSE },
|
|
|
|
{ "break", TOK_BREAK, FALSE },
|
|
|
|
{ "continue", TOK_CONTINUE, FALSE },
|
|
|
|
{ "continue", TOK_CONTINUE, FALSE },
|
|
|
|
{ "throw", TOK_THROW, FALSE },
|
|
|
|
{ "disrupt", TOK_DISRUPT, FALSE },
|
|
|
|
{ "try", TOK_TRY, FALSE },
|
|
|
|
{ "disruption", TOK_DISRUPTION, FALSE },
|
|
|
|
{ "catch", TOK_CATCH, FALSE },
|
|
|
|
|
|
|
|
{ "finally", TOK_FINALLY, FALSE },
|
|
|
|
|
|
|
|
{ "function", TOK_FUNCTION, FALSE },
|
|
|
|
{ "function", TOK_FUNCTION, FALSE },
|
|
|
|
{ "debugger", TOK_DEBUGGER, FALSE },
|
|
|
|
{ "debugger", TOK_DEBUGGER, FALSE },
|
|
|
|
{ "with", TOK_WITH, FALSE },
|
|
|
|
{ "with", TOK_WITH, FALSE },
|
|
|
|
@@ -12058,7 +12052,7 @@ static __exception int js_define_var (JSParseState *s, JSValue name, int tok) {
|
|
|
|
case TOK_VAR:
|
|
|
|
case TOK_VAR:
|
|
|
|
var_def_type = JS_VAR_DEF_LET;
|
|
|
|
var_def_type = JS_VAR_DEF_LET;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case TOK_CATCH:
|
|
|
|
case TOK_DISRUPTION:
|
|
|
|
var_def_type = JS_VAR_DEF_CATCH;
|
|
|
|
var_def_type = JS_VAR_DEF_CATCH;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
@@ -13378,16 +13372,9 @@ static __exception int js_parse_statement_or_decl (JSParseState *s,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (js_parse_expect_semi (s)) goto fail;
|
|
|
|
if (js_parse_expect_semi (s)) goto fail;
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
case TOK_THROW: {
|
|
|
|
case TOK_DISRUPT: {
|
|
|
|
const uint8_t *op_token_ptr;
|
|
|
|
|
|
|
|
op_token_ptr = s->token.ptr;
|
|
|
|
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
if (s->got_lf) {
|
|
|
|
emit_op (s, OP_null);
|
|
|
|
js_parse_error (s, "line terminator not allowed after throw");
|
|
|
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (js_parse_expr (s)) goto fail;
|
|
|
|
|
|
|
|
emit_source_pos (s, op_token_ptr);
|
|
|
|
|
|
|
|
emit_op (s, OP_throw);
|
|
|
|
emit_op (s, OP_throw);
|
|
|
|
if (js_parse_expect_semi (s)) goto fail;
|
|
|
|
if (js_parse_expect_semi (s)) goto fail;
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
@@ -13604,126 +13591,6 @@ static __exception int js_parse_statement_or_decl (JSParseState *s,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (js_parse_expect_semi (s)) goto fail;
|
|
|
|
if (js_parse_expect_semi (s)) goto fail;
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
case TOK_TRY: {
|
|
|
|
|
|
|
|
int label_catch, label_catch2, label_finally, label_end;
|
|
|
|
|
|
|
|
JSValue name;
|
|
|
|
|
|
|
|
BlockEnv block_env;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
|
|
|
|
label_catch = new_label (s);
|
|
|
|
|
|
|
|
label_catch2 = new_label (s);
|
|
|
|
|
|
|
|
label_finally = new_label (s);
|
|
|
|
|
|
|
|
label_end = new_label (s);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emit_goto (s, OP_catch, label_catch);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
push_break_entry (s->cur_func, &block_env, JS_NULL, -1, -1, 1);
|
|
|
|
|
|
|
|
block_env.label_finally = label_finally;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (js_parse_block (s)) goto fail;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pop_break_entry (s->cur_func);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (js_is_live_code (s)) {
|
|
|
|
|
|
|
|
/* drop the catch offset */
|
|
|
|
|
|
|
|
emit_op (s, OP_drop);
|
|
|
|
|
|
|
|
/* must push dummy value to keep same stack size */
|
|
|
|
|
|
|
|
emit_op (s, OP_null);
|
|
|
|
|
|
|
|
emit_goto (s, OP_gosub, label_finally);
|
|
|
|
|
|
|
|
emit_op (s, OP_drop);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emit_goto (s, OP_goto, label_end);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->token.val == TOK_CATCH) {
|
|
|
|
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
push_scope (s); /* catch variable */
|
|
|
|
|
|
|
|
emit_label (s, label_catch);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->token.val == '{') {
|
|
|
|
|
|
|
|
/* support optional-catch-binding feature */
|
|
|
|
|
|
|
|
emit_op (s, OP_drop); /* pop the exception object */
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (js_parse_expect (s, '(')) goto fail;
|
|
|
|
|
|
|
|
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
|
|
|
|
|
|
|
|
if (s->token.val == '[' || s->token.val == '{') {
|
|
|
|
|
|
|
|
/* catch variables behave like var (block scoped) */
|
|
|
|
|
|
|
|
if (js_parse_destructuring_element (s, TOK_VAR, 0, TRUE, TRUE, FALSE)
|
|
|
|
|
|
|
|
< 0)
|
|
|
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
js_parse_error (s, "identifier expected");
|
|
|
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
name = s->token.u.ident.str;
|
|
|
|
|
|
|
|
if (next_token (s) || js_define_var (s, name, TOK_CATCH) < 0) {
|
|
|
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store the exception value in the catch variable */
|
|
|
|
|
|
|
|
emit_op (s, OP_scope_put_var);
|
|
|
|
|
|
|
|
emit_key (s, name);
|
|
|
|
|
|
|
|
emit_u16 (s, s->cur_func->scope_level);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (js_parse_expect (s, ')')) goto fail;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: should keep the address to nop it out if there is no finally
|
|
|
|
|
|
|
|
* block */
|
|
|
|
|
|
|
|
emit_goto (s, OP_catch, label_catch2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
push_scope (s); /* catch block */
|
|
|
|
|
|
|
|
push_break_entry (s->cur_func, &block_env, JS_NULL, -1, -1, 1);
|
|
|
|
|
|
|
|
block_env.label_finally = label_finally;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (js_parse_block (s)) goto fail;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pop_break_entry (s->cur_func);
|
|
|
|
|
|
|
|
pop_scope (s); /* catch block */
|
|
|
|
|
|
|
|
pop_scope (s); /* catch variable */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (js_is_live_code (s)) {
|
|
|
|
|
|
|
|
/* drop the catch2 offset */
|
|
|
|
|
|
|
|
emit_op (s, OP_drop);
|
|
|
|
|
|
|
|
/* XXX: should keep the address to nop it out if there is no finally
|
|
|
|
|
|
|
|
* block */
|
|
|
|
|
|
|
|
/* must push dummy value to keep same stack size */
|
|
|
|
|
|
|
|
emit_op (s, OP_null);
|
|
|
|
|
|
|
|
emit_goto (s, OP_gosub, label_finally);
|
|
|
|
|
|
|
|
emit_op (s, OP_drop);
|
|
|
|
|
|
|
|
emit_goto (s, OP_goto, label_end);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* catch exceptions thrown in the catch block to execute the
|
|
|
|
|
|
|
|
* finally clause and rethrow the exception */
|
|
|
|
|
|
|
|
emit_label (s, label_catch2);
|
|
|
|
|
|
|
|
/* catch value is at TOS, no need to push undefined */
|
|
|
|
|
|
|
|
emit_goto (s, OP_gosub, label_finally);
|
|
|
|
|
|
|
|
emit_op (s, OP_throw);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (s->token.val == TOK_FINALLY) {
|
|
|
|
|
|
|
|
/* finally without catch : execute the finally clause
|
|
|
|
|
|
|
|
* and rethrow the exception */
|
|
|
|
|
|
|
|
emit_label (s, label_catch);
|
|
|
|
|
|
|
|
/* catch value is at TOS, no need to push undefined */
|
|
|
|
|
|
|
|
emit_goto (s, OP_gosub, label_finally);
|
|
|
|
|
|
|
|
emit_op (s, OP_throw);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
js_parse_error (s, "expecting catch or finally");
|
|
|
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_label (s, label_finally);
|
|
|
|
|
|
|
|
if (s->token.val == TOK_FINALLY) {
|
|
|
|
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
|
|
|
|
/* on the stack: ret_value gosub_ret_value */
|
|
|
|
|
|
|
|
push_break_entry (s->cur_func, &block_env, JS_NULL, -1, -1, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (js_parse_block (s)) goto fail;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pop_break_entry (s->cur_func);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_op (s, OP_ret);
|
|
|
|
|
|
|
|
emit_label (s, label_end);
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case ';':
|
|
|
|
case ';':
|
|
|
|
/* empty statement */
|
|
|
|
/* empty statement */
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
if (next_token (s)) goto fail;
|
|
|
|
@@ -16579,8 +16446,7 @@ static __exception int js_parse_directives (JSParseState *s) {
|
|
|
|
case TOK_DO:
|
|
|
|
case TOK_DO:
|
|
|
|
case TOK_WHILE:
|
|
|
|
case TOK_WHILE:
|
|
|
|
case TOK_FOR:
|
|
|
|
case TOK_FOR:
|
|
|
|
case TOK_THROW:
|
|
|
|
case TOK_DISRUPT:
|
|
|
|
case TOK_TRY:
|
|
|
|
|
|
|
|
case TOK_FUNCTION:
|
|
|
|
case TOK_FUNCTION:
|
|
|
|
case TOK_DEBUGGER:
|
|
|
|
case TOK_DEBUGGER:
|
|
|
|
case TOK_DEF:
|
|
|
|
case TOK_DEF:
|
|
|
|
@@ -27867,6 +27733,7 @@ typedef struct ASTParseState {
|
|
|
|
int function_nr;
|
|
|
|
int function_nr;
|
|
|
|
cJSON *errors; /* array of error objects */
|
|
|
|
cJSON *errors; /* array of error objects */
|
|
|
|
int has_error;
|
|
|
|
int has_error;
|
|
|
|
|
|
|
|
int in_disruption;
|
|
|
|
union {
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
struct {
|
|
|
|
const char *str;
|
|
|
|
const char *str;
|
|
|
|
@@ -28171,7 +28038,6 @@ redo:
|
|
|
|
else if (len == 3 && !memcmp (start, "var", 3)) s->token_val = TOK_VAR;
|
|
|
|
else if (len == 3 && !memcmp (start, "var", 3)) s->token_val = TOK_VAR;
|
|
|
|
else if (len == 3 && !memcmp (start, "def", 3)) s->token_val = TOK_DEF;
|
|
|
|
else if (len == 3 && !memcmp (start, "def", 3)) s->token_val = TOK_DEF;
|
|
|
|
else if (len == 3 && !memcmp (start, "for", 3)) s->token_val = TOK_FOR;
|
|
|
|
else if (len == 3 && !memcmp (start, "for", 3)) s->token_val = TOK_FOR;
|
|
|
|
else if (len == 3 && !memcmp (start, "try", 3)) s->token_val = TOK_TRY;
|
|
|
|
|
|
|
|
else if (len == 4 && !memcmp (start, "else", 4)) s->token_val = TOK_ELSE;
|
|
|
|
else if (len == 4 && !memcmp (start, "else", 4)) s->token_val = TOK_ELSE;
|
|
|
|
else if (len == 4 && !memcmp (start, "this", 4)) s->token_val = TOK_THIS;
|
|
|
|
else if (len == 4 && !memcmp (start, "this", 4)) s->token_val = TOK_THIS;
|
|
|
|
else if (len == 4 && !memcmp (start, "null", 4)) s->token_val = TOK_NULL;
|
|
|
|
else if (len == 4 && !memcmp (start, "null", 4)) s->token_val = TOK_NULL;
|
|
|
|
@@ -28179,13 +28045,12 @@ redo:
|
|
|
|
else if (len == 5 && !memcmp (start, "false", 5)) s->token_val = TOK_FALSE;
|
|
|
|
else if (len == 5 && !memcmp (start, "false", 5)) s->token_val = TOK_FALSE;
|
|
|
|
else if (len == 5 && !memcmp (start, "while", 5)) s->token_val = TOK_WHILE;
|
|
|
|
else if (len == 5 && !memcmp (start, "while", 5)) s->token_val = TOK_WHILE;
|
|
|
|
else if (len == 5 && !memcmp (start, "break", 5)) s->token_val = TOK_BREAK;
|
|
|
|
else if (len == 5 && !memcmp (start, "break", 5)) s->token_val = TOK_BREAK;
|
|
|
|
else if (len == 5 && !memcmp (start, "throw", 5)) s->token_val = TOK_THROW;
|
|
|
|
|
|
|
|
else if (len == 5 && !memcmp (start, "catch", 5)) s->token_val = TOK_CATCH;
|
|
|
|
|
|
|
|
else if (len == 6 && !memcmp (start, "return", 6)) s->token_val = TOK_RETURN;
|
|
|
|
else if (len == 6 && !memcmp (start, "return", 6)) s->token_val = TOK_RETURN;
|
|
|
|
else if (len == 6 && !memcmp (start, "delete", 6)) s->token_val = TOK_DELETE;
|
|
|
|
else if (len == 6 && !memcmp (start, "delete", 6)) s->token_val = TOK_DELETE;
|
|
|
|
else if (len == 7 && !memcmp (start, "finally", 7)) s->token_val = TOK_FINALLY;
|
|
|
|
else if (len == 7 && !memcmp (start, "disrupt", 7)) s->token_val = TOK_DISRUPT;
|
|
|
|
else if (len == 8 && !memcmp (start, "function", 8)) s->token_val = TOK_FUNCTION;
|
|
|
|
else if (len == 8 && !memcmp (start, "function", 8)) s->token_val = TOK_FUNCTION;
|
|
|
|
else if (len == 8 && !memcmp (start, "continue", 8)) s->token_val = TOK_CONTINUE;
|
|
|
|
else if (len == 8 && !memcmp (start, "continue", 8)) s->token_val = TOK_CONTINUE;
|
|
|
|
|
|
|
|
else if (len == 10 && !memcmp (start, "disruption", 10)) s->token_val = TOK_DISRUPTION;
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
case '.':
|
|
|
|
case '.':
|
|
|
|
if (p[1] >= '0' && p[1] <= '9') {
|
|
|
|
if (p[1] >= '0' && p[1] <= '9') {
|
|
|
|
@@ -28499,7 +28364,6 @@ static int tokenize_next (ASTParseState *s) {
|
|
|
|
else if (len == 3 && !memcmp (start, "var", 3)) s->token_val = TOK_VAR;
|
|
|
|
else if (len == 3 && !memcmp (start, "var", 3)) s->token_val = TOK_VAR;
|
|
|
|
else if (len == 3 && !memcmp (start, "def", 3)) s->token_val = TOK_DEF;
|
|
|
|
else if (len == 3 && !memcmp (start, "def", 3)) s->token_val = TOK_DEF;
|
|
|
|
else if (len == 3 && !memcmp (start, "for", 3)) s->token_val = TOK_FOR;
|
|
|
|
else if (len == 3 && !memcmp (start, "for", 3)) s->token_val = TOK_FOR;
|
|
|
|
else if (len == 3 && !memcmp (start, "try", 3)) s->token_val = TOK_TRY;
|
|
|
|
|
|
|
|
else if (len == 4 && !memcmp (start, "else", 4)) s->token_val = TOK_ELSE;
|
|
|
|
else if (len == 4 && !memcmp (start, "else", 4)) s->token_val = TOK_ELSE;
|
|
|
|
else if (len == 4 && !memcmp (start, "this", 4)) s->token_val = TOK_THIS;
|
|
|
|
else if (len == 4 && !memcmp (start, "this", 4)) s->token_val = TOK_THIS;
|
|
|
|
else if (len == 4 && !memcmp (start, "null", 4)) s->token_val = TOK_NULL;
|
|
|
|
else if (len == 4 && !memcmp (start, "null", 4)) s->token_val = TOK_NULL;
|
|
|
|
@@ -28507,13 +28371,12 @@ static int tokenize_next (ASTParseState *s) {
|
|
|
|
else if (len == 5 && !memcmp (start, "false", 5)) s->token_val = TOK_FALSE;
|
|
|
|
else if (len == 5 && !memcmp (start, "false", 5)) s->token_val = TOK_FALSE;
|
|
|
|
else if (len == 5 && !memcmp (start, "while", 5)) s->token_val = TOK_WHILE;
|
|
|
|
else if (len == 5 && !memcmp (start, "while", 5)) s->token_val = TOK_WHILE;
|
|
|
|
else if (len == 5 && !memcmp (start, "break", 5)) s->token_val = TOK_BREAK;
|
|
|
|
else if (len == 5 && !memcmp (start, "break", 5)) s->token_val = TOK_BREAK;
|
|
|
|
else if (len == 5 && !memcmp (start, "throw", 5)) s->token_val = TOK_THROW;
|
|
|
|
|
|
|
|
else if (len == 5 && !memcmp (start, "catch", 5)) s->token_val = TOK_CATCH;
|
|
|
|
|
|
|
|
else if (len == 6 && !memcmp (start, "return", 6)) s->token_val = TOK_RETURN;
|
|
|
|
else if (len == 6 && !memcmp (start, "return", 6)) s->token_val = TOK_RETURN;
|
|
|
|
else if (len == 6 && !memcmp (start, "delete", 6)) s->token_val = TOK_DELETE;
|
|
|
|
else if (len == 6 && !memcmp (start, "delete", 6)) s->token_val = TOK_DELETE;
|
|
|
|
else if (len == 7 && !memcmp (start, "finally", 7)) s->token_val = TOK_FINALLY;
|
|
|
|
else if (len == 7 && !memcmp (start, "disrupt", 7)) s->token_val = TOK_DISRUPT;
|
|
|
|
else if (len == 8 && !memcmp (start, "function", 8)) s->token_val = TOK_FUNCTION;
|
|
|
|
else if (len == 8 && !memcmp (start, "function", 8)) s->token_val = TOK_FUNCTION;
|
|
|
|
else if (len == 8 && !memcmp (start, "continue", 8)) s->token_val = TOK_CONTINUE;
|
|
|
|
else if (len == 8 && !memcmp (start, "continue", 8)) s->token_val = TOK_CONTINUE;
|
|
|
|
|
|
|
|
else if (len == 10 && !memcmp (start, "disruption", 10)) s->token_val = TOK_DISRUPTION;
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
case '.':
|
|
|
|
case '.':
|
|
|
|
if (p[1] >= '0' && p[1] <= '9') {
|
|
|
|
if (p[1] >= '0' && p[1] <= '9') {
|
|
|
|
@@ -29370,6 +29233,10 @@ static cJSON *ast_parse_function_inner (ASTParseState *s, BOOL is_expr) {
|
|
|
|
const uint8_t *start = s->token_ptr;
|
|
|
|
const uint8_t *start = s->token_ptr;
|
|
|
|
cJSON *node = ast_node (s, "function", start);
|
|
|
|
cJSON *node = ast_node (s, "function", start);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->in_disruption) {
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "cannot define function inside disruption clause");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ast_next_token (s); /* skip 'function' */
|
|
|
|
ast_next_token (s); /* skip 'function' */
|
|
|
|
|
|
|
|
|
|
|
|
/* Optional function name */
|
|
|
|
/* Optional function name */
|
|
|
|
@@ -29444,6 +29311,26 @@ static cJSON *ast_parse_function_inner (ASTParseState *s, BOOL is_expr) {
|
|
|
|
ast_error (s, s->token_ptr, "expected '{' for function body");
|
|
|
|
ast_error (s, s->token_ptr, "expected '{' for function body");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Optional disruption clause */
|
|
|
|
|
|
|
|
if (s->token_val == TOK_DISRUPTION) {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
if (s->token_val == '{') {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
int old_in_disruption = s->in_disruption;
|
|
|
|
|
|
|
|
s->in_disruption = 1;
|
|
|
|
|
|
|
|
cJSON *disruption_stmts = ast_parse_block_statements (s);
|
|
|
|
|
|
|
|
s->in_disruption = old_in_disruption;
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (node, "disruption", disruption_stmts);
|
|
|
|
|
|
|
|
if (s->token_val == '}') {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
} else if (s->token_val == TOK_EOF) {
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "unterminated disruption clause, expected '}'");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "expected '{' after disruption");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cJSON_AddNumberToObject (node, "function_nr", s->function_nr++);
|
|
|
|
cJSON_AddNumberToObject (node, "function_nr", s->function_nr++);
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
return node;
|
|
|
|
return node;
|
|
|
|
@@ -29455,6 +29342,10 @@ static cJSON *ast_parse_arrow_function (ASTParseState *s) {
|
|
|
|
cJSON *node = ast_node (s, "function", start);
|
|
|
|
cJSON *node = ast_node (s, "function", start);
|
|
|
|
cJSON_AddBoolToObject (node, "arrow", 1);
|
|
|
|
cJSON_AddBoolToObject (node, "arrow", 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->in_disruption) {
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "cannot define function inside disruption clause");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Parameters */
|
|
|
|
/* Parameters */
|
|
|
|
cJSON *params = cJSON_AddArrayToObject (node, "list");
|
|
|
|
cJSON *params = cJSON_AddArrayToObject (node, "list");
|
|
|
|
|
|
|
|
|
|
|
|
@@ -29558,7 +29449,7 @@ static void ast_sync_to_statement (ASTParseState *s) {
|
|
|
|
case '}':
|
|
|
|
case '}':
|
|
|
|
return; /* don't consume - let caller handle */
|
|
|
|
return; /* don't consume - let caller handle */
|
|
|
|
case TOK_VAR: case TOK_DEF: case TOK_IF: case TOK_WHILE:
|
|
|
|
case TOK_VAR: case TOK_DEF: case TOK_IF: case TOK_WHILE:
|
|
|
|
case TOK_FOR: case TOK_RETURN: case TOK_THROW: case TOK_TRY:
|
|
|
|
case TOK_FOR: case TOK_RETURN: case TOK_DISRUPT:
|
|
|
|
case TOK_FUNCTION: case TOK_BREAK:
|
|
|
|
case TOK_FUNCTION: case TOK_BREAK:
|
|
|
|
case TOK_CONTINUE: case TOK_DO:
|
|
|
|
case TOK_CONTINUE: case TOK_DO:
|
|
|
|
return; /* statement-starting keyword found */
|
|
|
|
return; /* statement-starting keyword found */
|
|
|
|
@@ -29774,14 +29665,9 @@ static cJSON *ast_parse_statement (ASTParseState *s) {
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
|
|
case TOK_THROW: {
|
|
|
|
case TOK_DISRUPT: {
|
|
|
|
node = ast_node (s, "throw", start);
|
|
|
|
node = ast_node (s, "disrupt", start);
|
|
|
|
ast_next_token (s);
|
|
|
|
ast_next_token (s);
|
|
|
|
if (s->got_lf) {
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "line terminator not allowed after throw");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON *expr = ast_parse_expr (s);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (node, "expression", expr);
|
|
|
|
|
|
|
|
ast_expect_semi (s);
|
|
|
|
ast_expect_semi (s);
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
@@ -29808,57 +29694,6 @@ static cJSON *ast_parse_statement (ASTParseState *s) {
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
|
|
case TOK_TRY: {
|
|
|
|
|
|
|
|
node = ast_node (s, "try", start);
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->token_val == '{') {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
cJSON *stmts = ast_parse_block_statements (s);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (node, "statements", stmts);
|
|
|
|
|
|
|
|
if (s->token_val == '}') ast_next_token (s);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "expected '{' for try block");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->token_val != TOK_CATCH && s->token_val != TOK_FINALLY)
|
|
|
|
|
|
|
|
ast_error (s, s->token_ptr, "expected 'catch' or 'finally' after try block");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->token_val == TOK_CATCH) {
|
|
|
|
|
|
|
|
cJSON *catch_node = ast_node (s, "catch", s->token_ptr);
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
if (s->token_val == '(') {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
if (s->token_val == TOK_IDENT) {
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->token_val == '{') {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
cJSON *catch_stmts = ast_parse_block_statements (s);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (catch_node, "statements", catch_stmts);
|
|
|
|
|
|
|
|
if (s->token_val == '}') ast_next_token (s);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_node_end (s, catch_node, s->buf_ptr);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (node, "catch", catch_node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s->token_val == TOK_FINALLY) {
|
|
|
|
|
|
|
|
cJSON *finally_node = ast_node (s, "finally", s->token_ptr);
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
if (s->token_val == '{') {
|
|
|
|
|
|
|
|
ast_next_token (s);
|
|
|
|
|
|
|
|
cJSON *finally_stmts = ast_parse_block_statements (s);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (finally_node, "statements", finally_stmts);
|
|
|
|
|
|
|
|
if (s->token_val == '}') ast_next_token (s);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_node_end (s, finally_node, s->buf_ptr);
|
|
|
|
|
|
|
|
cJSON_AddItemToObject (node, "finally", finally_node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_node_end (s, node, s->buf_ptr);
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TOK_FUNCTION: {
|
|
|
|
case TOK_FUNCTION: {
|
|
|
|
node = ast_parse_function_inner (s, FALSE);
|
|
|
|
node = ast_parse_function_inner (s, FALSE);
|
|
|
|
@@ -30244,6 +30079,14 @@ static void ast_sem_check_expr (ASTSemState *st, ASTSemScope *scope, cJSON *expr
|
|
|
|
ast_sem_check_stmt (st, &fn_scope, stmt);
|
|
|
|
ast_sem_check_stmt (st, &fn_scope, stmt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check disruption clause */
|
|
|
|
|
|
|
|
cJSON *disruption = cJSON_GetObjectItem (expr, "disruption");
|
|
|
|
|
|
|
|
if (disruption) {
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (stmt, disruption) {
|
|
|
|
|
|
|
|
ast_sem_check_stmt (st, &fn_scope, stmt);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Build scope record and attach to scopes array */
|
|
|
|
/* Build scope record and attach to scopes array */
|
|
|
|
int nr_slots, nr_close;
|
|
|
|
int nr_slots, nr_close;
|
|
|
|
cJSON *rec = ast_sem_build_scope_record (&fn_scope, &nr_slots, &nr_close);
|
|
|
|
cJSON *rec = ast_sem_build_scope_record (&fn_scope, &nr_slots, &nr_close);
|
|
|
|
@@ -30399,12 +30242,15 @@ static void ast_sem_check_stmt (ASTSemState *st, ASTSemScope *scope, cJSON *stmt
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "return") == 0 || strcmp (kind, "throw") == 0 ||
|
|
|
|
if (strcmp (kind, "return") == 0 || strcmp (kind, "go") == 0) {
|
|
|
|
strcmp (kind, "go") == 0) {
|
|
|
|
|
|
|
|
ast_sem_check_expr (st, scope, cJSON_GetObjectItem (stmt, "expression"));
|
|
|
|
ast_sem_check_expr (st, scope, cJSON_GetObjectItem (stmt, "expression"));
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "disrupt") == 0) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "break") == 0) {
|
|
|
|
if (strcmp (kind, "break") == 0) {
|
|
|
|
if (!ast_sem_in_loop (scope)) {
|
|
|
|
if (!ast_sem_in_loop (scope)) {
|
|
|
|
ast_sem_error (st, stmt, "'break' used outside of loop");
|
|
|
|
ast_sem_error (st, stmt, "'break' used outside of loop");
|
|
|
|
@@ -30419,31 +30265,6 @@ static void ast_sem_check_stmt (ASTSemState *st, ASTSemScope *scope, cJSON *stmt
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "try") == 0) {
|
|
|
|
|
|
|
|
cJSON *s2;
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (s2, cJSON_GetObjectItem (stmt, "statements")) {
|
|
|
|
|
|
|
|
ast_sem_check_stmt (st, scope, s2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON *catch_node = cJSON_GetObjectItem (stmt, "catch");
|
|
|
|
|
|
|
|
if (catch_node) {
|
|
|
|
|
|
|
|
ASTSemScope catch_scope = {0};
|
|
|
|
|
|
|
|
catch_scope.parent = scope;
|
|
|
|
|
|
|
|
catch_scope.function_nr = scope->function_nr;
|
|
|
|
|
|
|
|
const char *catch_name = cJSON_GetStringValue (cJSON_GetObjectItem (catch_node, "name"));
|
|
|
|
|
|
|
|
if (catch_name) ast_sem_add_var (&catch_scope, catch_name, 0, "var", scope->function_nr);
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (s2, cJSON_GetObjectItem (catch_node, "statements")) {
|
|
|
|
|
|
|
|
ast_sem_check_stmt (st, &catch_scope, s2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON *finally_node = cJSON_GetObjectItem (stmt, "finally");
|
|
|
|
|
|
|
|
if (finally_node) {
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (s2, cJSON_GetObjectItem (finally_node, "statements")) {
|
|
|
|
|
|
|
|
ast_sem_check_stmt (st, scope, s2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "block") == 0) {
|
|
|
|
if (strcmp (kind, "block") == 0) {
|
|
|
|
ASTSemScope block_scope = {0};
|
|
|
|
ASTSemScope block_scope = {0};
|
|
|
|
block_scope.parent = scope;
|
|
|
|
block_scope.parent = scope;
|
|
|
|
@@ -30489,6 +30310,14 @@ static void ast_sem_check_stmt (ASTSemState *st, ASTSemScope *scope, cJSON *stmt
|
|
|
|
ast_sem_check_stmt (st, &fn_scope, s2);
|
|
|
|
ast_sem_check_stmt (st, &fn_scope, s2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check disruption clause */
|
|
|
|
|
|
|
|
cJSON *disruption = cJSON_GetObjectItem (stmt, "disruption");
|
|
|
|
|
|
|
|
if (disruption) {
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (s2, disruption) {
|
|
|
|
|
|
|
|
ast_sem_check_stmt (st, &fn_scope, s2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Build scope record and attach to scopes array */
|
|
|
|
/* Build scope record and attach to scopes array */
|
|
|
|
int nr_slots, nr_close;
|
|
|
|
int nr_slots, nr_close;
|
|
|
|
cJSON *rec = ast_sem_build_scope_record (&fn_scope, &nr_slots, &nr_close);
|
|
|
|
cJSON *rec = ast_sem_build_scope_record (&fn_scope, &nr_slots, &nr_close);
|
|
|
|
@@ -31743,13 +31572,9 @@ static void mach_compile_stmt(MachCompState *cs, cJSON *stmt) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Throw statement */
|
|
|
|
/* Disrupt statement */
|
|
|
|
if (strcmp(kind, "throw") == 0) {
|
|
|
|
if (strcmp(kind, "disrupt") == 0) {
|
|
|
|
cJSON *expr = cJSON_GetObjectItem(stmt, "expression");
|
|
|
|
mach_emit(cs, MACH_ABC(MACH_THROW, 0, 0, 0));
|
|
|
|
int save = cs->freereg;
|
|
|
|
|
|
|
|
int r = mach_compile_expr(cs, expr, -1);
|
|
|
|
|
|
|
|
mach_emit(cs, MACH_ABC(MACH_THROW, r, 0, 0));
|
|
|
|
|
|
|
|
mach_free_reg_to(cs, save);
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -33559,10 +33384,8 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "throw") == 0) {
|
|
|
|
if (strcmp (kind, "disrupt") == 0) {
|
|
|
|
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
|
|
|
mach_gen_emit_0 (s, "disrupt");
|
|
|
|
int slot = mach_gen_expr (s, expr, -1);
|
|
|
|
|
|
|
|
mach_gen_emit_1 (s, "throw", slot);
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -33623,44 +33446,6 @@ static void mach_gen_statement (MachGenState *s, cJSON *stmt) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "try") == 0) {
|
|
|
|
|
|
|
|
cJSON *try_stmts = cJSON_GetObjectItem (stmt, "statements");
|
|
|
|
|
|
|
|
cJSON *catch_node = cJSON_GetObjectItem (stmt, "catch");
|
|
|
|
|
|
|
|
cJSON *finally_node = cJSON_GetObjectItem (stmt, "finally");
|
|
|
|
|
|
|
|
char *catch_label = catch_node ? mach_gen_label (s, "catch") : NULL;
|
|
|
|
|
|
|
|
char *finally_label = finally_node ? mach_gen_label (s, "finally") : NULL;
|
|
|
|
|
|
|
|
char *end_label = mach_gen_label (s, "try_end");
|
|
|
|
|
|
|
|
cJSON *instr = cJSON_CreateArray ();
|
|
|
|
|
|
|
|
cJSON_AddItemToArray (instr, cJSON_CreateString ("try_begin"));
|
|
|
|
|
|
|
|
cJSON_AddItemToArray (instr, cJSON_CreateString (catch_label ? catch_label : end_label));
|
|
|
|
|
|
|
|
cJSON_AddItemToArray (instr, cJSON_CreateString (finally_label ? finally_label : end_label));
|
|
|
|
|
|
|
|
cJSON_AddItemToArray (s->instructions, instr);
|
|
|
|
|
|
|
|
cJSON *child;
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (child, try_stmts) { mach_gen_statement (s, child); }
|
|
|
|
|
|
|
|
mach_gen_emit_0 (s, "try_end");
|
|
|
|
|
|
|
|
if (catch_node) mach_gen_emit_jump (s, finally_label ? finally_label : end_label);
|
|
|
|
|
|
|
|
if (catch_node) {
|
|
|
|
|
|
|
|
mach_gen_emit_label (s, catch_label);
|
|
|
|
|
|
|
|
int err_slot = mach_gen_alloc_slot (s);
|
|
|
|
|
|
|
|
mach_gen_emit_1 (s, "catch_begin", err_slot);
|
|
|
|
|
|
|
|
cJSON *catch_stmts = cJSON_GetObjectItem (catch_node, "statements");
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (child, catch_stmts) { mach_gen_statement (s, child); }
|
|
|
|
|
|
|
|
mach_gen_emit_0 (s, "catch_end");
|
|
|
|
|
|
|
|
sys_free (catch_label);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (finally_node) {
|
|
|
|
|
|
|
|
mach_gen_emit_label (s, finally_label);
|
|
|
|
|
|
|
|
mach_gen_emit_0 (s, "finally_begin");
|
|
|
|
|
|
|
|
cJSON *finally_stmts = cJSON_GetObjectItem (finally_node, "statements");
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (child, finally_stmts) { mach_gen_statement (s, child); }
|
|
|
|
|
|
|
|
mach_gen_emit_0 (s, "finally_end");
|
|
|
|
|
|
|
|
sys_free (finally_label);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
mach_gen_emit_label (s, end_label);
|
|
|
|
|
|
|
|
sys_free (end_label);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (kind, "function") == 0) {
|
|
|
|
if (strcmp (kind, "function") == 0) {
|
|
|
|
cJSON *name_obj = cJSON_GetObjectItem (stmt, "name");
|
|
|
|
cJSON *name_obj = cJSON_GetObjectItem (stmt, "name");
|
|
|
|
if (name_obj && cJSON_IsString (name_obj)) {
|
|
|
|
if (name_obj && cJSON_IsString (name_obj)) {
|
|
|
|
@@ -33787,6 +33572,12 @@ static cJSON *mach_gen_function (MachGenState *parent, cJSON *func_node) {
|
|
|
|
|
|
|
|
|
|
|
|
mach_gen_emit_0 (&s, "return_undef");
|
|
|
|
mach_gen_emit_0 (&s, "return_undef");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Compile disruption clause if present */
|
|
|
|
|
|
|
|
cJSON *disruption = cJSON_GetObjectItem (func_node, "disruption");
|
|
|
|
|
|
|
|
if (disruption && cJSON_IsArray (disruption)) {
|
|
|
|
|
|
|
|
cJSON_ArrayForEach (stmt, disruption) { mach_gen_statement (&s, stmt); }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cJSON *fn_scope = mach_find_scope_record (s.scopes, s.function_nr);
|
|
|
|
cJSON *fn_scope = mach_find_scope_record (s.scopes, s.function_nr);
|
|
|
|
cJSON *fn_ncs = fn_scope ? cJSON_GetObjectItem (fn_scope, "nr_close_slots") : NULL;
|
|
|
|
cJSON *fn_ncs = fn_scope ? cJSON_GetObjectItem (fn_scope, "nr_close_slots") : NULL;
|
|
|
|
cJSON_AddNumberToObject (result, "nr_close_slots", fn_ncs ? (int)cJSON_GetNumberValue (fn_ncs) : 0);
|
|
|
|
cJSON_AddNumberToObject (result, "nr_close_slots", fn_ncs ? (int)cJSON_GetNumberValue (fn_ncs) : 0);
|
|
|
|
@@ -33874,7 +33665,7 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) {
|
|
|
|
if (strcmp (kind, "call") == 0) {
|
|
|
|
if (strcmp (kind, "call") == 0) {
|
|
|
|
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
|
|
|
cJSON *expr = cJSON_GetObjectItem (stmt, "expression");
|
|
|
|
last_expr_slot = mach_gen_expr (s, expr, -1);
|
|
|
|
last_expr_slot = mach_gen_expr (s, expr, -1);
|
|
|
|
} else if (strcmp (kind, "return") == 0 || strcmp (kind, "throw") == 0 ||
|
|
|
|
} else if (strcmp (kind, "return") == 0 || strcmp (kind, "disrupt") == 0 ||
|
|
|
|
strcmp (kind, "break") == 0 || strcmp (kind, "continue") == 0) {
|
|
|
|
strcmp (kind, "break") == 0 || strcmp (kind, "continue") == 0) {
|
|
|
|
mach_gen_statement (s, stmt);
|
|
|
|
mach_gen_statement (s, stmt);
|
|
|
|
last_expr_slot = -1;
|
|
|
|
last_expr_slot = -1;
|
|
|
|
@@ -33882,7 +33673,7 @@ static cJSON *mach_gen_program (MachGenState *s, cJSON *ast) {
|
|
|
|
strcmp (kind, "function") == 0 || strcmp (kind, "block") == 0 ||
|
|
|
|
strcmp (kind, "function") == 0 || strcmp (kind, "block") == 0 ||
|
|
|
|
strcmp (kind, "if") == 0 || strcmp (kind, "while") == 0 ||
|
|
|
|
strcmp (kind, "if") == 0 || strcmp (kind, "while") == 0 ||
|
|
|
|
strcmp (kind, "do") == 0 || strcmp (kind, "for") == 0 ||
|
|
|
|
strcmp (kind, "do") == 0 || strcmp (kind, "for") == 0 ||
|
|
|
|
strcmp (kind, "switch") == 0 || strcmp (kind, "try") == 0) {
|
|
|
|
strcmp (kind, "switch") == 0) {
|
|
|
|
mach_gen_statement (s, stmt);
|
|
|
|
mach_gen_statement (s, stmt);
|
|
|
|
last_expr_slot = -1;
|
|
|
|
last_expr_slot = -1;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@@ -34795,15 +34586,11 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- Exceptions ---- */
|
|
|
|
/* ---- Disruption ---- */
|
|
|
|
else if (strcmp(op, "throw") == 0) {
|
|
|
|
else if (strcmp(op, "disrupt") == 0) {
|
|
|
|
result = JS_Throw(ctx, frame->slots[(int)a1->valuedouble]);
|
|
|
|
result = JS_Throw(ctx, JS_NULL);
|
|
|
|
goto done;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(op, "try_begin") == 0 || strcmp(op, "try_end") == 0 ||
|
|
|
|
|
|
|
|
strcmp(op, "catch_begin") == 0 || strcmp(op, "catch_end") == 0) {
|
|
|
|
|
|
|
|
/* TODO: exception handling */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- Unknown opcode ---- */
|
|
|
|
/* ---- Unknown opcode ---- */
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
|