diff --git a/src/binder/bind.c b/src/binder/bind.c index 608043a3678..931461ce474 100644 --- a/src/binder/bind.c +++ b/src/binder/bind.c @@ -323,16 +323,21 @@ Rakudo_binding_bind_one_param(PARROT_INTERP, PMC *lexpad, llsig_element *sig_inf /* If it has a sub-signature, bind that. */ if (!PMC_IS_NULL(sig_info->sub_signature)) { - /* Turn value into a capture. */ + /* Turn value into a capture, unless we already have one. */ PMC *capture = PMCNULL; - PMC *meth = VTABLE_find_method(interp, value, string_from_literal(interp, "Capture")); INTVAL result; - if (PMC_IS_NULL(meth)) { - if (error) - *error = Parrot_sprintf_c(interp, "Could not turn argument into capture"); - return BIND_RESULT_FAIL; + if (sig_info->flags & SIG_ELEM_IS_CAPTURE) { + capture = value; + } + else { + PMC *meth = VTABLE_find_method(interp, value, string_from_literal(interp, "Capture")); + if (PMC_IS_NULL(meth)) { + if (error) + *error = Parrot_sprintf_c(interp, "Could not turn argument into capture"); + return BIND_RESULT_FAIL; + } + Parrot_ext_call(interp, meth, "Pi->P", value, &capture); } - Parrot_ext_call(interp, meth, "Pi->P", value, &capture); /* Recurse into signature binder. */ result = Rakudo_binding_bind_signature(interp, lexpad, sig_info->sub_signature, @@ -525,6 +530,14 @@ Rakudo_binding_bind_signature(PARROT_INTERP, PMC *lexpad, PMC *signature, mem_sys_free(pos_from_named); return bind_fail; } + else if (i + 1 == num_elements) { + /* Since a capture acts as "the ultimate slurpy" in a sense, if + * this is the last parameter in the signature we can return + * success right off the bat. */ + if (pos_from_named) + mem_sys_free(pos_from_named); + return BIND_RESULT_OK; + } } /* Is it a positional sourced from a named? */ diff --git a/src/builtins/Capture.pir b/src/builtins/Capture.pir index 98601bab7d5..edbae3591b2 100644 --- a/src/builtins/Capture.pir +++ b/src/builtins/Capture.pir @@ -134,7 +134,39 @@ to. :-) Hands back a Capture containing the snapshot. .param pmc capture .param int pos_position .param pmc nameds_unbound - die "Capture snapshots in signatures not yet implemented." + + .local int num_positionals + .local pmc positionals, nameds + num_positionals = elements capture + positionals = root_new ['parrot';'ResizablePMCArray'] + nameds = root_new ['parrot';'Hash'] + + # Copy positionals. + pos_loop: + if pos_position >= num_positionals goto pos_loop_end + $P0 = capture[pos_position] + push positionals, $P0 + inc pos_position + goto pos_loop + pos_loop_end: + + # Copy still unbound named parameters. + if null nameds_unbound goto named_loop_end + $P0 = iter nameds_unbound + named_loop: + unless $P0 goto named_loop_end + $S0 = shift $P0 + $P1 = capture[$S0] + nameds[$S0] = $P1 + goto named_loop + named_loop_end: + + # Finally, create capture. + $P0 = get_hll_global 'Capture' + $P0 = $P0.'CREATE'('P6opaque') + setattribute $P0, '$!pos', positionals + setattribute $P0, '$!named', nameds + .return ($P0) .end =back