+++ /dev/null
-
-#define DEFSTRUCT(T) typedef struct T T; struct T
-
-DEFSTRUCT(ParamInit) {
- SV *name;
- OP *init;
-};
-
-#define DEFVECTOR(T, B) DEFSTRUCT(T) { \
- B (*data); \
- size_t used, size; \
-}
-
-DEFVECTOR(ParamInitVec, ParamInit);
-DEFVECTOR(ParamVec, SV *);
-
-DEFSTRUCT(ParamSpec) {
- SV *invocant;
- ParamVec positional_required;
- ParamInitVec positional_optional;
- ParamVec named_required;
- ParamInitVec named_optional;
- SV *slurpy;
-};
-
-#define DEFVECTOR_CLEAR(T, N, F) static void N(T *p) { \
- while (p->used) { \
- p->used--; \
- F(p->data[p->used]); \
- } \
- Safefree(p->data); \
- p->data =NULL; \
- p->size = 0; \
-} static void N(T *)
-
-static void pi_clear(ParamInit pi) {
- if (pi.name) {
- SvREFCNT_dec(pi.name);
- }
- if (pi.init) {
- op_free(pi.init);
- }
-}
-
-DEFVECTOR_CLEAR(ParamVec, pv_clear, SvREFCNT_dec);
-DEFVECTOR_CLEAR(ParamInitVec, piv_clear, pi_clear);
-
-static void ps_free(ParamSpec *ps) {
- if (ps->invocant) {
- SvREFCNT_dec(ps->invocant);
- ps->invocant = NULL;
- }
- pv_clear(&ps->positional_required);
- piv_clear(&ps->positional_optional);
- pv_clear(&ps->named_required);
- piv_clear(&ps->named_optional);
- if (ps->slurpy) {
- SvREFCNT_dec(ps->slurpy);
- ps->slurpy = NULL;
- }
- Safefree(ps);
-}
-
-static int args_min(const ParamSpec *ps) {
- int n = 0;
- if (ps->invocant) {
- n++;
- }
- n += ps->positional_required.used;
- n += ps->named_required.used * 2;
- return n;
-}
-
-static int args_max(const ParamSpec *ps) {
- int n = 0;
- if (ps->invocant) {
- n++;
- }
- n += ps->positional_required.used;
- n += ps->positional_optional.used;
- if (ps->named_required.used || ps->named_optional.used || ps->slurpy) {
- n = -1;
- }
- return n;
-}
-
-static size_t count_positional_params(const ParamSpec *ps) {
- return ps->positional_required.used + ps->positional_optional.used;
-}
-
-static size_t count_named_params(const ParamSpec *ps) {
- return ps->named_required.used + ps->named_optional.used;
-}
-
-static void gen(ParamSpec *ps) {
- int amin = args_min(ps);
- if (amin > 0) {
- printf("croak 'not enough' if @_ < %d;\n", amin);
- }
- int amax = args_max(ps);
- if (amax >= 0) {
- printf("croak 'too many' if @_ > %d;\n", amax);
- }
- size_t named_params = count_named_params(ps);
- if (named_params || (ps->slurpy && SvPV_nolen(ps->slurpy)[0] == '%')) {
- size_t t = named_params + !!ps->invocant;
- printf("croak 'odd' if (@_ - %zu) > 0 && (@_ - %zu) % 2;\n", t, t);
- }
- if (ps->invocant) {
- printf("%s = shift @_;\n", SvPV_nolen(ps->invocant));
- }
- // XXX (...) = @_;
- size_t positional_params = count_positional_params(ps);
- for (size_t i = 0; i < ps->positional_optional.used; i++) {
- printf("%*sif (@_ < %zu) {\n", (int)i * 2, "", positional_params - i);
- }
- for (size_t i = 0; i < ps->positional_optional.used; i++) {
- ParamInit *pi = &ps->positional_optional.data[i];
- printf("%*s %s = %p;\n", (int)(ps->positional_optional.used - i - 1) * 2, "", SvPV_nolen(pi->name), pi->init);
- printf("%*s}\n", (int)(ps->positional_optional.used - i - 1) * 2, "");
- }
- if (named_params) {
- printf("if (@_ > %zu) {\n", positional_params);
- printf(" my $_b = '';\n");
- printf(" my $_i = %zu;\n", positional_params);
- printf(" while ($_i < @_) {\n");
- printf(" my $_k = $_[$_i];\n");
- size_t req = ps->named_required.used;
- for (size_t i = 0; i < named_params; i++) {
- printf(" ");
- if (i) {
- printf("els");
- }
- SV *param = i >= req ? ps->named_optional.data[i - req] : ps->named_required.data[i];
- printf("if ($_k eq '%s') {\n", SvPV_nolen(param) + 1);
- printf(" %s = $_[$_i + 1];\n", SvPV_nolen(param));
- printf(" vec($_b, %zu, 1) = 1;\n", i);
- printf(" }\n");
- }
- printf(" else {\n");
- if (ps->slurpy) {
- const char *slurpy = SvPV_nolen(ps->slurpy);
- if (slurpy[0] == '%') {
- printf(" $%s{$_k} = $_[$_i + 1];\n", slurpy + 1);
- } else {
- printf(" push %s, $_k, $_[$_i + 1];\n", slurpy);
- }
- } else {
- printf(" croak 'no such param ' . $_k;\n");
- }
- printf(" }\n");
- printf(" $_i += 2;\n");
- printf(" }\n");
- if (ps->named_required.used) {
- printf(" if (($_b & pack('b*', '1' x %zu)) ne pack('b*', '1' x %zu)) {\n", ps->named_required.used, ps->named_required.used);
- printf(" croak 'missing required named args';\n"); // XXX
- printf(" }\n");
- }
- for (size_t i = 0; i < ps->named_optional.used; i++) {
- printf(" %s = %p unless vec $_k, %zu, 1;\n", SvPV_nolen(ps->named_optional[i].name), ps->named_optional[i].init, ps->named_required.used + i);
- }
- printf("}\n");
- }
-}