diff --git a/src/vm/jvm/runtime/org/perl6/rakudo/Binder.java b/src/vm/jvm/runtime/org/perl6/rakudo/Binder.java index c59d7ff9ae0..c11f2310dcb 100644 --- a/src/vm/jvm/runtime/org/perl6/rakudo/Binder.java +++ b/src/vm/jvm/runtime/org/perl6/rakudo/Binder.java @@ -182,6 +182,14 @@ private static int juncOrFail(ThreadContext tc, Ops.GlobalExt gcx, SixModelObjec /* Binds a single argument into the lexpad, after doing any checks that are * needed. Also handles any type captures. If there is a sub signature, then * re-enters the binder. Returns one of the BIND_RESULT_* codes. */ + private static final CallSiteDescriptor ACCEPTS_o = new CallSiteDescriptor( + new byte[] { CallSiteDescriptor.ARG_OBJ, CallSiteDescriptor.ARG_OBJ }, null); + private static final CallSiteDescriptor ACCEPTS_i = new CallSiteDescriptor( + new byte[] { CallSiteDescriptor.ARG_OBJ, CallSiteDescriptor.ARG_INT }, null); + private static final CallSiteDescriptor ACCEPTS_n = new CallSiteDescriptor( + new byte[] { CallSiteDescriptor.ARG_OBJ, CallSiteDescriptor.ARG_NUM }, null); + private static final CallSiteDescriptor ACCEPTS_s = new CallSiteDescriptor( + new byte[] { CallSiteDescriptor.ARG_OBJ, CallSiteDescriptor.ARG_STR }, null); private static int bindOneParam(ThreadContext tc, Ops.GlobalExt gcx, CallFrame cf, SixModelObject param, Object origArg, byte origFlag, boolean noNomTypeCheck, String[] error) { /* Get parameter flags and variable name. */ @@ -436,7 +444,47 @@ else if ((paramFlags & SIG_ELEM_HASH_SIGIL) != 0) { if ((paramFlags & SIG_ELEM_INVOCANT) != 0) cf.oLex[sci.oTryGetLexicalIdx("self")] = decontValue; - /* TODO: post_constraints. */ + /* Handle any constraint types (note that they may refer to the parameter by + * name, so we need to have bound it already). */ + SixModelObject postConstraints = param.get_attribute_boxed(tc, gcx.Parameter, + "$!post_contraints", HINT_post_constraints); + if (postConstraints != null) { + long numConstraints = postConstraints.elems(tc); + for (long i = 0; i < numConstraints; i++) { + /* Check we meet the constraint. */ + SixModelObject consType = postConstraints.at_pos_boxed(tc, i); + SixModelObject acceptsMeth = org.perl6.nqp.runtime.Ops.findmethod(consType, "ACCEPTS", tc); + + /*if (STABLE(cons_type)->type_check(interp, cons_type, code_type)) + Parrot_sub_capture_lex(interp, + VTABLE_get_attr_keyed(interp, cons_type, code_type, DO_str));*/ + switch (flag) { + case CallSiteDescriptor.ARG_INT: + org.perl6.nqp.runtime.Ops.invokeDirect(tc, acceptsMeth, + ACCEPTS_i, new Object[] { consType, arg_i }); + break; + case CallSiteDescriptor.ARG_NUM: + org.perl6.nqp.runtime.Ops.invokeDirect(tc, acceptsMeth, + ACCEPTS_n, new Object[] { consType, arg_n }); + break; + case CallSiteDescriptor.ARG_STR: + org.perl6.nqp.runtime.Ops.invokeDirect(tc, acceptsMeth, + ACCEPTS_s, new Object[] { consType, arg_s }); + break; + default: + org.perl6.nqp.runtime.Ops.invokeDirect(tc, acceptsMeth, + ACCEPTS_o, new Object[] { consType, arg_o }); + break; + } + long result = org.perl6.nqp.runtime.Ops.istrue( + org.perl6.nqp.runtime.Ops.result_o(tc.curFrame), tc); + if (result == 0) { + if (error != null) + error[0] = "Constraint type check failed for parameter '" + varName + "'"; + return BIND_RESULT_FAIL; + } + } + } /* TODO: attributives. */ if ((paramFlags & SIG_ELEM_BIND_ATTRIBUTIVE) != 0) {