From 87b3ec06a27f7a80347cafdb9a8dd9d9a8335b7c Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 Oct 2025 00:08:13 +0800 Subject: [PATCH] :art: support return statement outside function block --- src/nasal_parse.cpp | 42 ++++++++++++++++++++++++++++++++++-------- src/nasal_parse.h | 1 + src/nasal_vm.h | 5 +++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/nasal_parse.cpp b/src/nasal_parse.cpp index cf8820c..4a9bb80 100644 --- a/src/nasal_parse.cpp +++ b/src/nasal_parse.cpp @@ -94,7 +94,36 @@ void parse::match(tok type, const char* info) { } bool parse::lookahead(tok type) { - return toks[ptr].type==type; + return toks[ptr].type == type; +} + +bool parse::lookahead_expression() { + switch (toks[ptr].type) { + case tok::tk_nil: + case tok::tk_num: + case tok::tk_str: + case tok::tk_id: + case tok::tk_true: + case tok::tk_false: + case tok::tk_func: + case tok::tk_lbracket: + case tok::tk_lbrace: + case tok::tk_sub: + case tok::tk_floater: + case tok::tk_not: + case tok::tk_var: + case tok::tk_lcurve: + case tok::tk_for: + case tok::tk_forindex: + case tok::tk_foreach: + case tok::tk_while: + case tok::tk_if: + case tok::tk_cont: + case tok::tk_brk: + case tok::tk_ret: return true; + default: return false; + } + return false; } bool parse::is_call(tok type) { @@ -378,14 +407,11 @@ expr* parse::lcurve_expr() { } expr* parse::expression() { - tok type=toks[ptr].type; - if ((type==tok::tk_brk || type==tok::tk_cont) && !in_loop_depth) { + tok type = toks[ptr].type; + if ((type == tok::tk_brk || type == tok::tk_cont) && !in_loop_depth) { die(thisspan, "must use break/continue in loops"); } - if (type==tok::tk_ret && !in_func_depth) { - die(thisspan, "must use return in functions"); - } - switch(type) { + switch (type) { case tok::tk_use: return use_stmt_gen(); case tok::tk_nil: case tok::tk_num: @@ -439,7 +465,7 @@ code_block* parse::expression_block() { } } match(tok::tk_rbrace, "expected \"}\" when generating expressions"); - } else { + } else if (lookahead_expression()) { node->add_expression(expression()); if (lookahead(tok::tk_semi)) { match(tok::tk_semi); diff --git a/src/nasal_parse.h b/src/nasal_parse.h index f589d63..2baa441 100644 --- a/src/nasal_parse.h +++ b/src/nasal_parse.h @@ -87,6 +87,7 @@ private: void next(); void match(tok, const char* info = nullptr); bool lookahead(tok); + bool lookahead_expression(); bool is_call(tok); bool check_comma(const tok*); bool check_tuple(); diff --git a/src/nasal_vm.h b/src/nasal_vm.h index c8f3fde..17da570 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -1181,6 +1181,11 @@ inline void vm::o_mcallh() { } inline void vm::o_ret() { + // return statement outside any other functions + // directly exit the program + if (ctx.funcr.is_nil()) { + std::exit(0); + } /* +-------------+ * | return value| <- top[0] * +-------------+