remove b and F arg types + renames + set default args to none

setting default args to none rather than whatever default
value allows for easily checking whether the arg was set,
without losing anything (since e.g. calling get_integer on
a none value still returns a 0)

'b' and 'F' were kinda ugly and handled special niches, which
are no longer a thing now that we're defaulting to none
master
Daniel Kolesa 2021-04-29 01:24:05 +02:00
parent a9afa89af6
commit da7548664c
7 changed files with 114 additions and 231 deletions

View File

@ -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<integer_type>::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

View File

@ -535,48 +535,13 @@ lookup_id:
auto fmt = static_cast<command_impl &>(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<integer_type>::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<integer_type>::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(

View File

@ -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<command_impl *>(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<command_impl *>(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<command_impl *>(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<command_impl *>(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<command_impl *>(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<command_impl *>(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;

View File

@ -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<integer_type>::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;

View File

@ -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]);
});

View File

@ -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(

View File

@ -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";