diff --git a/include/cubescript/cubescript/state.hh b/include/cubescript/cubescript/state.hh index 682d70c..cd3c310 100644 --- a/include/cubescript/cubescript/state.hh +++ b/include/cubescript/cubescript/state.hh @@ -295,17 +295,26 @@ struct LIBCUBESCRIPT_EXPORT state { * simple types are recognized: * * * `s` - a string - * * `i` - an integer, default value 0 - * * `b` - an integer, default value `limits::min` - * * `f` - a float, default value 0 - * * `F` - a float, default value is the preceeding value - * * `t` - any (passed as is) - * * `e` - bytecode - * * `E` - condition (see below) + * * `i` - an integer + * * `f` - a float + * * `a` - any (passed as is) + * * `b` - bytecode/block + * * `c` - condition (see below) * * `r` - ident * * `N` - number of real arguments passed up until now * * `$` - self ident (the command, except for special hooks) * + * For condition types, the type of the value is generally kept as is, + * except for non-empty strings, which are compiled as bytecode. Therefore, + * to check condition types, you first try to get their bytecode; if it is + * valid, you run it and use its result, otherwise use the value as is, + * and then evaluate it as a boolean. + * + * When an argument is not provided by the caller, it is assigned to none + * type. Using the appropriate getters on the value structure will get + * you fallback defaults (e.g. 0 for integer and so on) but you can still + * check the type explicitly for whether it was actually provided. + * * Commands also support variadics. Variadic commands have their type * list suffixed with `V` or `C`. A `V` variadic is a traditional variadic * function, while `C` will concatenate all inputs into a single big diff --git a/src/cs_parser.cc b/src/cs_parser.cc index c759e94..7871fb2 100644 --- a/src/cs_parser.cc +++ b/src/cs_parser.cc @@ -535,48 +535,13 @@ lookup_id: auto fmt = static_cast(id).get_args(); for (char c: fmt) { switch (c) { - case 's': - gs.gen_val_string(std::string_view{}); - numargs++; - break; - case 'i': - gs.gen_val_integer(); - numargs++; - break; - case 'b': - gs.gen_val_integer( - std::numeric_limits::min() - ); - numargs++; - break; - case 'f': - gs.gen_val_float(); - numargs++; - break; - case 'F': - gs.gen_dup(VAL_FLOAT); - numargs++; - break; - case 'E': - case 't': - gs.gen_val_null(); - numargs++; - break; - case 'e': - gs.gen_block(); - numargs++; - break; - case 'r': - gs.gen_val_ident(); - numargs++; - break; case '$': gs.gen_val_ident(id); - numargs++; + ++numargs; break; case 'N': gs.gen_val_integer(-1); - numargs++; + ++numargs; break; case 'C': comtype = BC_INST_COM_C; @@ -589,6 +554,10 @@ lookup_id: case '3': case '4': break; + default: + gs.gen_val_null(); + ++numargs; + break; } } gs.gen_command_call(id, comtype, ltype, numargs); @@ -946,77 +915,44 @@ static bool parse_cmd_arg(parser_state &ps, char s, bool more, bool rep) { if (more) { more = ps.parse_arg(VAL_STRING); } - if (!more && !rep) { - ps.gs.gen_val_string(); - } - return more; + break; case 'i': /* integer */ if (more) { more = ps.parse_arg(VAL_INT); } - if (!more && !rep) { - ps.gs.gen_val_integer(); - } - return more; - case 'b': /* integer, INT_MIN default */ - if (more) { - more = ps.parse_arg(VAL_INT); - } - if (!more && !rep) { - ps.gs.gen_val_integer(std::numeric_limits::min()); - } - return more; + break; case 'f': /* float */ if (more) { more = ps.parse_arg(VAL_FLOAT); } - if (!more && !rep) { - ps.gs.gen_val_float(); - } - return more; - case 'F': /* float, prev-argument default */ - if (more) { - more = ps.parse_arg(VAL_FLOAT); - } - if (!more && !rep) { - ps.gs.gen_dup(VAL_FLOAT); - } - return more; - case 't': /* any arg */ + break; + case 'a': /* any arg */ if (more) { more = ps.parse_arg(VAL_ANY); } - if (!more && !rep) { - ps.gs.gen_val_null(); - } - return more; - case 'E': /* condition */ + break; + case 'c': /* condition */ if (more) { more = ps.parse_arg(VAL_COND); } - if (!more && !rep) { - ps.gs.gen_val_null(); - } - return more; - case 'e': /* code */ + break; + case 'b': /* bytecode */ if (more) { more = ps.parse_arg(VAL_CODE); } - if (!more && !rep) { - ps.gs.gen_block(); - } - return more; + break; case 'r': /* ident */ if (more) { more = ps.parse_arg(VAL_IDENT); } - if (!more && !rep) { - ps.gs.gen_val_ident(); - } - return more; + break; default: return more; } + if (!more && !rep) { + ps.gs.gen_val_null(); + } + return more; } bool parser_state::parse_call_command( diff --git a/src/cs_state.cc b/src/cs_state.cc index 523b3a2..2d8b4dc 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -172,34 +172,34 @@ state::state(alloc_func func, void *data) { /* builtins */ - p = &new_command("do", "e", [](auto &cs, auto args, auto &res) { + p = &new_command("do", "b", [](auto &cs, auto args, auto &res) { res = cs.run(args[0].get_code()); }); static_cast(p)->p_type = ID_DO; - p = &new_command("doargs", "e", [](auto &cs, auto args, auto &res) { + p = &new_command("doargs", "b", [](auto &cs, auto args, auto &res) { call_with_args(*cs.p_tstate, [&cs, &res, &args]() { res = cs.run(args[0].get_code()); }); }); static_cast(p)->p_type = ID_DOARGS; - p = &new_command("if", "tee", [](auto &cs, auto args, auto &res) { + p = &new_command("if", "abb", [](auto &cs, auto args, auto &res) { res = cs.run((args[0].get_bool() ? args[1] : args[2]).get_code()); }); static_cast(p)->p_type = ID_IF; - p = &new_command("result", "t", [](auto &, auto args, auto &res) { + p = &new_command("result", "a", [](auto &, auto args, auto &res) { res = std::move(args[0]); }); static_cast(p)->p_type = ID_RESULT; - p = &new_command("!", "t", [](auto &, auto args, auto &res) { + p = &new_command("!", "a", [](auto &, auto args, auto &res) { res.set_integer(!args[0].get_bool()); }); static_cast(p)->p_type = ID_NOT; - p = &new_command("&&", "E1V", [](auto &cs, auto args, auto &res) { + p = &new_command("&&", "c1V", [](auto &cs, auto args, auto &res) { if (args.empty()) { res.set_integer(1); } else { @@ -218,7 +218,7 @@ state::state(alloc_func func, void *data) { }); static_cast(p)->p_type = ID_AND; - p = &new_command("||", "E1V", [](auto &cs, auto args, auto &res) { + p = &new_command("||", "c1V", [](auto &cs, auto args, auto &res) { if (args.empty()) { res.set_integer(0); } else { @@ -596,14 +596,12 @@ LIBCUBESCRIPT_EXPORT command &state::new_command( for (auto fmt = args.begin(); fmt != args.end(); ++fmt) { switch (*fmt) { case 'i': - case 'b': case 'f': - case 'F': - case 't': - case 'E': + case 'a': + case 'c': case 'N': case 's': - case 'e': + case 'b': case 'r': case '$': ++nargs; diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 913bcd4..2e38034 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -51,112 +51,56 @@ void exec_command( int i = -1, fakeargs = 0, numargs = int(nargs); bool rep = false; auto fmt = id->get_args(); + auto set_fake = [&i, &fakeargs, &rep, args, numargs]() { + if (++i >= numargs) { + if (rep) { + return false; + } + args[i].set_none(); + ++fakeargs; + return false; + } + return true; + }; for (auto it = fmt.begin(); it != fmt.end(); ++it) { switch (*it) { case 'i': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_integer(0); - fakeargs++; - } else { - args[i].force_integer(); - } - break; - case 'b': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_integer( - std::numeric_limits::min() - ); - fakeargs++; - } else { + if (set_fake()) { args[i].force_integer(); } break; case 'f': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_float(0.0f); - fakeargs++; - } else { - args[i].force_float(); - } - break; - case 'F': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_float(args[i - 1].get_float()); - fakeargs++; - } else { + if (set_fake()) { args[i].force_float(); } break; case 's': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_string("", *ts.pstate); - fakeargs++; - } else { + if (set_fake()) { args[i].force_string(*ts.pstate); } break; - case 'T': - case 't': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_none(); - fakeargs++; - } + case 'a': + set_fake(); break; - case 'E': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_none(); - fakeargs++; - } else if (args[i].get_type() == value_type::STRING) { - auto str = args[i].get_string(*ts.pstate); - if (str.empty()) { - args[i].set_integer(0); - } else { - args[i].force_code(*ts.pstate); + case 'c': + if (set_fake()) { + if (args[i].get_type() == value_type::STRING) { + auto str = args[i].get_string(*ts.pstate); + if (str.empty()) { + args[i].set_integer(0); + } else { + args[i].force_code(*ts.pstate); + } } } break; - case 'e': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_code(bcode_p::make_ref( - bcode_get_empty(ts.istate->empty, VAL_NULL) - )); - fakeargs++; - } else { + case 'b': + if (set_fake()) { args[i].force_code(*ts.pstate); } break; case 'r': - if (++i >= numargs) { - if (rep) { - break; - } - args[i].set_ident(*ts.istate->id_dummy); - fakeargs++; - } else { + if (set_fake()) { args[i].force_ident(*ts.pstate); } break; diff --git a/src/lib_base.cc b/src/lib_base.cc index d36b0aa..1b67924 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -68,7 +68,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { throw error{cs, args[0].get_string(cs)}; }); - new_cmd_quiet(gcs, "pcall", "err", [](auto &cs, auto args, auto &ret) { + new_cmd_quiet(gcs, "pcall", "brr", [](auto &cs, auto args, auto &ret) { auto &cret = args[1].get_ident(cs); auto &css = args[2].get_ident(cs); if (!cret.is_alias()) { @@ -98,7 +98,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { ts.get_astack(ssa).set_alias(ssa, ts, tback); }); - new_cmd_quiet(gcs, "?", "ttt", [](auto &, auto args, auto &res) { + new_cmd_quiet(gcs, "?", "aaa", [](auto &, auto args, auto &res) { if (args[0].get_bool()) { res = std::move(args[1]); } else { @@ -106,7 +106,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "cond", "ee2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "cond", "bb2V", [](auto &cs, auto args, auto &res) { for (size_t i = 0; i < args.size(); i += 2) { if ((i + 1) < args.size()) { if (cs.run(args[i].get_code()).get_bool()) { @@ -120,7 +120,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "case", "ite2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "case", "iab2V", [](auto &cs, auto args, auto &res) { integer_type val = args[0].get_integer(); for (size_t i = 1; (i + 1) < args.size(); i += 2) { if ( @@ -133,7 +133,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "casef", "fte2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "casef", "fab2V", [](auto &cs, auto args, auto &res) { float_type val = args[0].get_float(); for (size_t i = 1; (i + 1) < args.size(); i += 2) { if ( @@ -146,7 +146,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "cases", "ste2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "cases", "sab2V", [](auto &cs, auto args, auto &res) { string_ref val = args[0].get_string(cs); for (size_t i = 1; (i + 1) < args.size(); i += 2) { if ( @@ -159,7 +159,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "pushif", "rte", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "pushif", "rab", [](auto &cs, auto args, auto &res) { alias_local st{cs, args[0]}; if (st.get_alias().is_arg()) { throw error{cs, "cannot push an argument"}; @@ -170,28 +170,28 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "loop", "rie", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loop", "rab", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), 0, args[1].get_integer(), 1, bcode_ref{}, args[2].get_code() ); }); - new_cmd_quiet(gcs, "loop+", "riie", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loop+", "riib", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), args[1].get_integer(), args[2].get_integer(), 1, bcode_ref{}, args[3].get_code() ); }); - new_cmd_quiet(gcs, "loop*", "riie", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loop*", "riib", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), 0, args[1].get_integer(), args[2].get_integer(), bcode_ref{}, args[3].get_code() ); }); - new_cmd_quiet(gcs, "loop+*", "riiie", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loop+*", "riiib", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), args[1].get_integer(), args[3].get_integer(), args[2].get_integer(), @@ -199,28 +199,28 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { ); }); - new_cmd_quiet(gcs, "loopwhile", "riee", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loopwhile", "ribb", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), 0, args[1].get_integer(), 1, args[2].get_code(), args[3].get_code() ); }); - new_cmd_quiet(gcs, "loopwhile+", "riiee", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loopwhile+", "riibb", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), args[1].get_integer(), args[2].get_integer(), 1, args[3].get_code(), args[4].get_code() ); }); - new_cmd_quiet(gcs, "loopwhile*", "riiee", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "loopwhile*", "riibb", [](auto &cs, auto args, auto &) { do_loop( cs, args[0].get_ident(cs), 0, args[2].get_integer(), args[1].get_integer(), args[3].get_code(), args[4].get_code() ); }); - new_cmd_quiet(gcs, "loopwhile+*", "riiiee", []( + new_cmd_quiet(gcs, "loopwhile+*", "riiibb", []( auto &cs, auto args, auto & ) { do_loop( @@ -230,7 +230,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { ); }); - new_cmd_quiet(gcs, "while", "ee", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "while", "bb", [](auto &cs, auto args, auto &) { auto cond = args[0].get_code(); auto body = args[1].get_code(); while (cs.run(cond).get_bool()) { @@ -245,7 +245,7 @@ end: return; }); - new_cmd_quiet(gcs, "loopconcat", "rie", []( + new_cmd_quiet(gcs, "loopconcat", "rib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -254,7 +254,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcat+", "riie", []( + new_cmd_quiet(gcs, "loopconcat+", "riib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -263,7 +263,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcat*", "riie", []( + new_cmd_quiet(gcs, "loopconcat*", "riib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -272,7 +272,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcat+*", "riiie", []( + new_cmd_quiet(gcs, "loopconcat+*", "riiib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -282,7 +282,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcatword", "rie", []( + new_cmd_quiet(gcs, "loopconcatword", "rib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -291,7 +291,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcatword+", "riie", []( + new_cmd_quiet(gcs, "loopconcatword+", "riib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -300,7 +300,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcatword*", "riie", []( + new_cmd_quiet(gcs, "loopconcatword*", "riib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -309,7 +309,7 @@ end: ); }); - new_cmd_quiet(gcs, "loopconcatword+*", "riiie", []( + new_cmd_quiet(gcs, "loopconcatword+*", "riiib", []( auto &cs, auto args, auto &res ) { do_loop_conc( @@ -319,7 +319,7 @@ end: ); }); - new_cmd_quiet(gcs, "push", "rte", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "push", "rab", [](auto &cs, auto args, auto &res) { alias_local st{cs, args[0]}; if (st.get_alias().is_arg()) { throw error{cs, "cannot push an argument"}; @@ -332,7 +332,7 @@ end: cs.reset_value(args[0].get_string(cs)); }); - new_cmd_quiet(gcs, "alias", "st", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "alias", "sa", [](auto &cs, auto args, auto &) { cs.assign_value(args[0].get_string(cs), args[1]); }); diff --git a/src/lib_list.cc b/src/lib_list.cc index 398870c..64ea906 100644 --- a/src/lib_list.cc +++ b/src/lib_list.cc @@ -204,7 +204,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { res.set_string(make_str_view(list, qend), cs); }); - new_cmd_quiet(gcs, "listfind", "rse", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "listfind", "rsb", [](auto &cs, auto args, auto &res) { alias_local st{cs, args[0]}; any_value idv{}; auto body = args[2].get_code(); @@ -221,7 +221,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { res.set_integer(-1); }); - new_cmd_quiet(gcs, "listassoc", "rse", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "listassoc", "rsb", [](auto &cs, auto args, auto &res) { alias_local st{cs, args[0]}; any_value idv{}; auto body = args[2].get_code(); @@ -286,7 +286,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { ); }); - new_cmd_quiet(gcs, "looplist", "rse", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "looplist", "rsb", [](auto &cs, auto args, auto &) { alias_local st{cs, args[0]}; any_value idv{}; auto body = args[2].get_code(); @@ -303,7 +303,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { } }); - new_cmd_quiet(gcs, "looplist2", "rrse", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "looplist2", "rrsb", [](auto &cs, auto args, auto &) { alias_local st1{cs, args[0]}; alias_local st2{cs, args[1]}; any_value idv{}; @@ -327,7 +327,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { } }); - new_cmd_quiet(gcs, "looplist3", "rrrse", [](auto &cs, auto args, auto &) { + new_cmd_quiet(gcs, "looplist3", "rrrsb", [](auto &cs, auto args, auto &) { alias_local st1{cs, args[0]}; alias_local st2{cs, args[1]}; alias_local st3{cs, args[2]}; @@ -358,7 +358,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { } }); - new_cmd_quiet(gcs, "looplistconcat", "rse", []( + new_cmd_quiet(gcs, "looplistconcat", "rsb", []( auto &cs, auto args, auto &res ) { loop_list_conc( @@ -367,7 +367,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { ); }); - new_cmd_quiet(gcs, "looplistconcatword", "rse", []( + new_cmd_quiet(gcs, "looplistconcatword", "rsb", []( auto &cs, auto args, auto &res ) { loop_list_conc( @@ -376,7 +376,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { ); }); - new_cmd_quiet(gcs, "listfilter", "rse", []( + new_cmd_quiet(gcs, "listfilter", "rsb", []( auto &cs, auto args, auto &res ) { alias_local st{cs, args[0]}; @@ -397,7 +397,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { res.set_string(r.str(), cs); }); - new_cmd_quiet(gcs, "listcount", "rse", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "listcount", "rsb", [](auto &cs, auto args, auto &res) { alias_local st{cs, args[0]}; any_value idv{}; auto body = args[2].get_code(); @@ -608,7 +608,7 @@ static void list_sort( } static void init_lib_list_sort(state &gcs) { - new_cmd_quiet(gcs, "sortlist", "srree", []( + new_cmd_quiet(gcs, "sortlist", "srrbb", []( auto &cs, auto args, auto &res ) { list_sort( @@ -616,7 +616,7 @@ static void init_lib_list_sort(state &gcs) { args[2].get_ident(cs), args[3].get_code(), args[4].get_code() ); }); - new_cmd_quiet(gcs, "uniquelist", "srre", []( + new_cmd_quiet(gcs, "uniquelist", "srrb", []( auto &cs, auto args, auto &res ) { list_sort( diff --git a/tools/repl.cc b/tools/repl.cc index 42ea5de..e53bd1a 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -54,21 +54,17 @@ inline std::string_view get_arg_type(char arg) { switch (arg) { case 'i': return "int"; - case 'b': - return "int_min"; case 'f': return "float"; - case 'F': - return "float_prev"; - case 't': + case 'a': return "any"; - case 'E': + case 'c': return "cond"; case 'N': return "numargs"; case 's': return "str"; - case 'e': + case 'b': return "block"; case 'r': return "ident";