diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 5e4067b..1987079 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -1587,6 +1587,12 @@ compilecomv: } } break; + case CsIdBreak: + gs.code.push(CsCodeBreak | CsCodeFlagFalse); + break; + case CsIdContinue: + gs.code.push(CsCodeBreak | CsCodeFlagTrue); + break; case CsIdResult: if (more) { more = compilearg(gs, CsValAny, prevargs); diff --git a/src/cs_vm.cc b/src/cs_vm.cc index fe95a93..4e5b7e2 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -734,6 +734,20 @@ static ostd::Uint32 *runcode(CsState &cs, ostd::Uint32 *code, CsValue &result) { } continue; } + case CsCodeBreak | CsCodeFlagFalse: + if (cs.is_in_loop()) { + throw CsBreakException(); + } else { + throw CsErrorException(cs, "no loop to break"); + } + break; + case CsCodeBreak | CsCodeFlagTrue: + if (cs.is_in_loop()) { + throw CsContinueException(); + } else { + throw CsErrorException(cs, "no loop to continue"); + } + break; case CsCodeMacro: { ostd::Uint32 len = op >> 8; diff --git a/src/cs_vm.hh b/src/cs_vm.hh index cf66205..0d2e733 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -21,7 +21,8 @@ static constexpr int DbgaliasIdx = MaxArguments + 2; enum { CsIdUnknown = -1, CsIdIvar, CsIdFvar, CsIdSvar, CsIdCommand, CsIdAlias, - CsIdLocal, CsIdDo, CsIdDoArgs, CsIdIf, CsIdResult, CsIdNot, CsIdAnd, CsIdOr + CsIdLocal, CsIdDo, CsIdDoArgs, CsIdIf, CsIdBreak, CsIdContinue, CsIdResult, + CsIdNot, CsIdAnd, CsIdOr }; struct CsIdentLink { @@ -76,6 +77,7 @@ enum { CsCodeLocal, CsCodeDo, CsCodeDoArgs, CsCodeJump, CsCodeJumpB, CsCodeJumpResult, + CsCodeBreak, CsCodeOpMask = 0x3F, CsCodeRet = 6, diff --git a/src/cubescript.cc b/src/cubescript.cc index 429a717..11390e0 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -332,6 +332,22 @@ CsState::CsState(CsAllocCb func, void *data): new_command("local", nullptr, nullptr)->p_type = CsIdLocal; + new_command("break", "", [](auto &cs, auto, auto &) { + if (cs.is_in_loop()) { + throw CsBreakException(); + } else { + throw CsErrorException(cs, "no loop to break"); + } + })->p_type = CsIdBreak; + + new_command("continue", "", [](auto &cs, auto, auto &) { + if (cs.is_in_loop()) { + throw CsContinueException(); + } else { + throw CsErrorException(cs, "no loop to continue"); + } + })->p_type = CsIdContinue; + cs_init_lib_base(*this); } @@ -1113,22 +1129,6 @@ void cs_init_lib_base(CsState &gcs) { } }); - gcs.new_command("break", "", [](auto &cs, auto, auto &) { - if (cs.is_in_loop()) { - throw CsBreakException(); - } else { - throw CsErrorException(cs, "no loop to break"); - } - }); - - gcs.new_command("continue", "", [](auto &cs, auto, auto &) { - if (cs.is_in_loop()) { - throw CsContinueException(); - } else { - throw CsErrorException(cs, "no loop to continue"); - } - }); - gcs.new_command("?", "tTT", [](auto &, auto args, auto &res) { if (args[0].get_bool()) { res = ostd::move(args[1]);