diff --git a/include/cubescript/cubescript/state.hh b/include/cubescript/cubescript/state.hh index 0e4944b..1cb5416 100644 --- a/include/cubescript/cubescript/state.hh +++ b/include/cubescript/cubescript/state.hh @@ -316,13 +316,13 @@ struct LIBCUBESCRIPT_EXPORT state { * check the type explicitly for whether it was actually provided. * * Commands also support variadics. Variadic commands have their type - * list suffixed with `V`. + * list suffixed with `...`. * - * If `V` is used alone, the inputs are any arbitrary values. However, + * If `...` is used alone, the inputs are any arbitrary values. However, * they can also be used with repetition. Repetition works for example - * like `if2V`. The `2` is the number of types to repeat; it must be at + * like `if2...`. The `2` is the number of types to repeat; it must be at * most the number of simple types preceeding it. It must be followed by - * `V`. This specific example means that the variadic arguments are a + * `...`. This specific example means that the variadic arguments are a * sequence of integer, float, integer, float, integer, float and so on. * * The resulting command stores the number of arguments it takes. The diff --git a/src/cs_parser.cc b/src/cs_parser.cc index 16abdfb..bf1afc6 100644 --- a/src/cs_parser.cc +++ b/src/cs_parser.cc @@ -543,7 +543,7 @@ lookup_id: gs.gen_val_integer(-1); ++numargs; break; - case 'V': + case '.': comtype = BC_INST_COM_V; break; case '1': @@ -991,7 +991,8 @@ bool parser_state::parse_call_command( gs.gen_val_integer(numargs - fakeargs); ++numargs; break; - case 'V': /* varargs */ + case '.': /* varargs */ + it += 2; /* third will be skipped by the loop */ comtype = BC_INST_COM_V; if (more) { for (;;) { @@ -1271,7 +1272,8 @@ static bool parse_assign_var( ps.gs.gen_val_integer(nargs); ++nargs; break; - case 'V': + case '.': + it += 2; /* third will be skipped by the loop */ comtype = BC_INST_COM_V; if (more && !got) { more = ps.parse_arg(VAL_ANY); diff --git a/src/cs_state.cc b/src/cs_state.cc index ec43337..306cd2f 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -199,7 +199,7 @@ state::state(alloc_func func, void *data) { }); static_cast(p)->p_type = ID_NOT; - p = &new_command("&&", "c1V", [](auto &cs, auto args, auto &res) { + p = &new_command("&&", "c1...", [](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("||", "c1V", [](auto &cs, auto args, auto &res) { + p = &new_command("||", "c1...", [](auto &cs, auto args, auto &res) { if (args.empty()) { res.set_integer(0); } else { @@ -616,12 +616,12 @@ LIBCUBESCRIPT_EXPORT command &state::new_command( *this, "not enough arguments to repeat" }; } - if ((args.end() - fmt) != 2) { + if ((args.end() - fmt) != 4) { throw error{ *this, "malformed argument list" }; } - if (fmt[1] != 'V') { + if (fmt[1] != '.') { throw error{ *this, "repetition without variadic arguments" }; @@ -629,12 +629,16 @@ LIBCUBESCRIPT_EXPORT command &state::new_command( nargs -= nrep; break; } - case 'V': - if ((fmt + 1) != args.end()) { + case '.': + if ( + ((fmt + 3) != args.end()) || + std::memcmp(&fmt[0], "...", 3) + ) { throw error{ *this, "unterminated variadic argument list" }; } + fmt += 2; break; default: throw error{ diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 356c7e8..435a6e4 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -112,7 +112,7 @@ void exec_command( i += 1; args[i].set_integer(integer_type(lookup ? -1 : i - fakeargs)); break; - case 'V': + case '.': i = std::max(i + 1, numargs); static_cast(id)->call( ts, span_type{args, std::size_t(i)}, res diff --git a/src/lib_base.cc b/src/lib_base.cc index 1b67924..5a4739c 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -106,7 +106,7 @@ LIBCUBESCRIPT_EXPORT void std_init_base(state &gcs) { } }); - new_cmd_quiet(gcs, "cond", "bb2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "cond", "bb2...", [](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", "iab2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "case", "iab2...", [](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", "fab2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "casef", "fab2...", [](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", "sab2V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "cases", "sab2...", [](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 ( diff --git a/src/lib_list.cc b/src/lib_list.cc index 9e8ac2a..ce67d77 100644 --- a/src/lib_list.cc +++ b/src/lib_list.cc @@ -147,7 +147,7 @@ LIBCUBESCRIPT_EXPORT void std_init_list(state &gcs) { ); }); - new_cmd_quiet(gcs, "at", "si1V", [](auto &cs, auto args, auto &res) { + new_cmd_quiet(gcs, "at", "si1...", [](auto &cs, auto args, auto &res) { if (args.empty()) { return; } diff --git a/src/lib_math.cc b/src/lib_math.cc index fb5a6a0..6639833 100644 --- a/src/lib_math.cc +++ b/src/lib_math.cc @@ -116,28 +116,28 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { res.set_float(std::exp(args[0].get_float())); }); - new_cmd_quiet(cs, "min", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "min", "i1...", [](auto &, auto args, auto &res) { integer_type v = (!args.empty() ? args[0].get_integer() : 0); for (size_t i = 1; i < args.size(); ++i) { v = std::min(v, args[i].get_integer()); } res.set_integer(v); }); - new_cmd_quiet(cs, "max", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "max", "i1...", [](auto &, auto args, auto &res) { integer_type v = (!args.empty() ? args[0].get_integer() : 0); for (size_t i = 1; i < args.size(); ++i) { v = std::max(v, args[i].get_integer()); } res.set_integer(v); }); - new_cmd_quiet(cs, "minf", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "minf", "f1...", [](auto &, auto args, auto &res) { float_type v = (!args.empty() ? args[0].get_float() : 0); for (size_t i = 1; i < args.size(); ++i) { v = std::min(v, args[i].get_float()); } res.set_float(v); }); - new_cmd_quiet(cs, "maxf", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "maxf", "f1...", [](auto &, auto args, auto &res) { float_type v = (!args.empty() ? args[0].get_float() : 0); for (size_t i = 1; i < args.size(); ++i) { v = std::max(v, args[i].get_float()); @@ -171,43 +171,43 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { res.set_float(r); }); - new_cmd_quiet(cs, "+", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "+", "i1...", [](auto &, auto args, auto &res) { math_op(args, res, 0, std::plus(), math_noop()); }); - new_cmd_quiet(cs, "*", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "*", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 1, std::multiplies(), math_noop() ); }); - new_cmd_quiet(cs, "-", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "-", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::minus(), std::negate() ); }); - new_cmd_quiet(cs, "^", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "^", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::bit_xor(), [](integer_type val) { return ~val; } ); }); - new_cmd_quiet(cs, "~", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "~", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::bit_xor(), [](integer_type val) { return ~val; } ); }); - new_cmd_quiet(cs, "&", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "&", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::bit_and(), math_noop() ); }); - new_cmd_quiet(cs, "|", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "|", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::bit_or(), math_noop() ); }); /* special combined cases */ - new_cmd_quiet(cs, "^~", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "^~", "i1...", [](auto &, auto args, auto &res) { integer_type val; if (args.size() >= 2) { val = args[0].get_integer() ^ ~args[1].get_integer(); @@ -219,7 +219,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { } res.set_integer(val); }); - new_cmd_quiet(cs, "&~", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "&~", "i1...", [](auto &, auto args, auto &res) { integer_type val; if (args.size() >= 2) { val = args[0].get_integer() & ~args[1].get_integer(); @@ -231,7 +231,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { } res.set_integer(val); }); - new_cmd_quiet(cs, "|~", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "|~", "i1...", [](auto &, auto args, auto &res) { integer_type val; if (args.size() >= 2) { val = args[0].get_integer() | ~args[1].get_integer(); @@ -244,7 +244,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { res.set_integer(val); }); - new_cmd_quiet(cs, "<<", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "<<", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](integer_type val1, integer_type val2) { return (val2 < integer_type(sizeof(integer_type) * CHAR_BIT)) @@ -253,7 +253,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { }, math_noop() ); }); - new_cmd_quiet(cs, ">>", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, ">>", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](integer_type val1, integer_type val2) { return val1 >> std::clamp( @@ -263,23 +263,23 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { ); }); - new_cmd_quiet(cs, "+f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "+f", "f1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::plus(), math_noop() ); }); - new_cmd_quiet(cs, "*f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "*f", "f1...", [](auto &, auto args, auto &res) { math_op( args, res, 1, std::multiplies(), math_noop() ); }); - new_cmd_quiet(cs, "-f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "-f", "f1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, std::minus(), std::negate() ); }); - new_cmd_quiet(cs, "div", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "div", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](integer_type val1, integer_type val2) { if (val2) { @@ -289,7 +289,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { }, math_noop() ); }); - new_cmd_quiet(cs, "mod", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "mod", "i1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](integer_type val1, integer_type val2) { if (val2) { @@ -299,7 +299,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { }, math_noop() ); }); - new_cmd_quiet(cs, "divf", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "divf", "f1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](float_type val1, float_type val2) { if (val2) { @@ -309,7 +309,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { }, math_noop() ); }); - new_cmd_quiet(cs, "modf", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "modf", "f1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](float_type val1, float_type val2) { if (val2) { @@ -320,7 +320,7 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { ); }); - new_cmd_quiet(cs, "pow", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "pow", "f1...", [](auto &, auto args, auto &res) { math_op( args, res, 0, [](float_type val1, float_type val2) { return float_type(pow(val1, val2)); @@ -328,41 +328,41 @@ LIBCUBESCRIPT_EXPORT void std_init_math(state &cs) { ); }); - new_cmd_quiet(cs, "=", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "=", "i1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::equal_to()); }); - new_cmd_quiet(cs, "!=", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "!=", "i1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::not_equal_to()); }); - new_cmd_quiet(cs, "<", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "<", "i1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::less()); }); - new_cmd_quiet(cs, ">", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, ">", "i1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::greater()); }); - new_cmd_quiet(cs, "<=", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "<=", "i1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::less_equal()); }); - new_cmd_quiet(cs, ">=", "i1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, ">=", "i1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::greater_equal()); }); - new_cmd_quiet(cs, "=f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "=f", "f1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::equal_to()); }); - new_cmd_quiet(cs, "!=f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "!=f", "f1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::not_equal_to()); }); - new_cmd_quiet(cs, "(args, res, std::less()); }); - new_cmd_quiet(cs, ">f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, ">f", "f1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::greater()); }); - new_cmd_quiet(cs, "<=f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, "<=f", "f1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::less_equal()); }); - new_cmd_quiet(cs, ">=f", "f1V", [](auto &, auto args, auto &res) { + new_cmd_quiet(cs, ">=f", "f1...", [](auto &, auto args, auto &res) { cmp_op(args, res, std::greater_equal()); }); } diff --git a/src/lib_str.cc b/src/lib_str.cc index 4e1beaf..ec438bb 100644 --- a/src/lib_str.cc +++ b/src/lib_str.cc @@ -91,15 +91,15 @@ LIBCUBESCRIPT_EXPORT void std_init_string(state &cs) { res.set_string(s.str(), ccs); }); - new_cmd_quiet(cs, "concat", "V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "concat", "...", [](auto &ccs, auto args, auto &res) { res.set_string(concat_values(ccs, args, " ")); }); - new_cmd_quiet(cs, "concatword", "V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "concatword", "...", [](auto &ccs, auto args, auto &res) { res.set_string(concat_values(ccs, args)); }); - new_cmd_quiet(cs, "format", "V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "format", "...", [](auto &ccs, auto args, auto &res) { if (args.empty()) { return; } @@ -166,25 +166,25 @@ LIBCUBESCRIPT_EXPORT void std_init_string(state &cs) { }, ccs); }); - new_cmd_quiet(cs, "strcmp", "s1V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "strcmp", "s1...", [](auto &ccs, auto args, auto &res) { str_cmp_by(ccs, args, res, std::equal_to()); }); - new_cmd_quiet(cs, "=s", "s1V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "=s", "s1...", [](auto &ccs, auto args, auto &res) { str_cmp_by(ccs, args, res, std::equal_to()); }); - new_cmd_quiet(cs, "!=s", "s1V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "!=s", "s1...", [](auto &ccs, auto args, auto &res) { str_cmp_by(ccs, args, res, std::not_equal_to()); }); - new_cmd_quiet(cs, "()); }); - new_cmd_quiet(cs, ">s", "s1V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, ">s", "s1...", [](auto &ccs, auto args, auto &res) { str_cmp_by(ccs, args, res, std::greater()); }); - new_cmd_quiet(cs, "<=s", "s1V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, "<=s", "s1...", [](auto &ccs, auto args, auto &res) { str_cmp_by(ccs, args, res, std::less_equal()); }); - new_cmd_quiet(cs, ">=s", "s1V", [](auto &ccs, auto args, auto &res) { + new_cmd_quiet(cs, ">=s", "s1...", [](auto &ccs, auto args, auto &res) { str_cmp_by(ccs, args, res, std::greater_equal()); }); diff --git a/tests/runner.cc b/tests/runner.cc index 8b5e260..4661de6 100644 --- a/tests/runner.cc +++ b/tests/runner.cc @@ -50,7 +50,7 @@ int main(int argc, char **argv) { cs::state gcs; cs::std_init_all(gcs); - gcs.new_command("echo", "V", [](auto &s, auto args, auto &) { + gcs.new_command("echo", "...", [](auto &s, auto args, auto &) { std::printf("%s\n", cs::concat_values(s, args, " ").data()); }); diff --git a/tools/repl.cc b/tools/repl.cc index f68823a..1333b28 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -75,20 +75,18 @@ inline std::string_view get_arg_type(char arg) { } inline void fill_cmd_args(std::string &writer, std::string_view args) { - char variadic = '\0'; + bool variadic = false; int nrep = 0; - if (!args.empty() && ((args.back() == 'V') || (args.back() == 'C'))) { - variadic = args.back(); - args.remove_suffix(1); + if ((args.size() >= 3) && (args.substr(args.size() - 3) == "...")) { + variadic = true; + args.remove_suffix(3); if (!args.empty() && isdigit(args.back())) { nrep = args.back() - '0'; args.remove_suffix(1); } } if (args.empty()) { - if (variadic == 'C') { - writer += "concat(...)"; - } else if (variadic == 'V') { + if (variadic) { writer += "..."; } return; @@ -107,9 +105,6 @@ inline void fill_cmd_args(std::string &writer, std::string_view args) { if (norep > 0) { writer += ", "; } - if (variadic == 'C') { - writer += "concat("; - } if (!args.empty()) { if (args.size() > 1) { writer += '{'; @@ -125,9 +120,6 @@ inline void fill_cmd_args(std::string &writer, std::string_view args) { } } writer += "..."; - if (variadic == 'C') { - writer += ")"; - } } } @@ -371,7 +363,7 @@ int main(int argc, char **argv) { } }); - gcs.new_command("echo", "V", [](auto &css, auto args, auto &) { + gcs.new_command("echo", "...", [](auto &css, auto args, auto &) { std::printf("%s\n", cs::concat_values(css, args, " ").data()); });