Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Start translating the binder code.
  • Loading branch information
jnthn committed May 10, 2013
1 parent 111de52 commit 380909f
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 2 deletions.
168 changes: 167 additions & 1 deletion src/vm/jvm/runtime/org/perl6/rakudo/Binder.java
Expand Up @@ -45,12 +45,178 @@ public final class Binder {
private static final int SIG_ELEM_NATIVE_STR_VALUE = 8388608;
private static final int SIG_ELEM_NATIVE_VALUE = (SIG_ELEM_NATIVE_INT_VALUE | SIG_ELEM_NATIVE_NUM_VALUE | SIG_ELEM_NATIVE_STR_VALUE);

/* Hints for Parameter attributes. */
private static final int HINT_variable_name = 0;
private static final int HINT_named_names = 1;
private static final int HINT_type_captures = 2;
private static final int HINT_flags = 3;
private static final int HINT_nominal_type = 4;
private static final int HINT_post_constraints = 5;
private static final int HINT_coerce_type = 6;
private static final int HINT_coerce_method = 7;
private static final int HINT_sub_signature = 8;
private static final int HINT_default_value = 9;
private static final int HINT_container_descriptor = 10;
private static final int HINT_attr_package = 11;

/* Last error, per thread. */
public static HashMap<ThreadContext, String> lastErrors = new HashMap<ThreadContext, String>();

public static int bind(ThreadContext tc, CallFrame ctx, SixModelObject params,
private static String arityFail(ThreadContext tc, SixModelObject params,
int numParams, int numPosArgs, boolean tooMany) {
int arity = 0;
int count = 0;
String fail = tooMany ? "Too many" : "Not enough";

/* Work out how many we could have been passed. */
for (int i = 0; i < numParams; i++) {
SixModelObject param = params.at_pos_boxed(tc, i);
param.get_attribute_native(tc, Ops.Parameter, "$!flags", HINT_flags);
int flags = (int)tc.native_i;
SixModelObject namedNames = param.get_attribute_boxed(tc,
Ops.Parameter, "$!named_names", HINT_named_names);

if (namedNames != null)
continue;
if ((flags & SIG_ELEM_SLURPY_NAMED) != 0)
continue;
if ((flags & SIG_ELEM_SLURPY_POS) != 0) {
count = -1;
}
else if ((flags & SIG_ELEM_IS_OPTIONAL) != 0) {
count++;
}
else {
count++;
arity++;
}
}

/* Now generate decent error. */
if (arity == count)
return String.format(
"%s positional parameters passed; got %d but expected %d",
fail, numPosArgs, arity);
else if (count == -1)
return String.format(
"%s positional parameters passed; got %d but expected at least %d",
fail, numPosArgs, arity);
else
return String.format(
"%s positional parameters passed; got %d but expected between %d and %d",
fail, numPosArgs, arity, count);
}

/* 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 int bindOneParam(ThreadContext tc, CallFrame cf, SixModelObject param,
Object arg, byte flag, boolean noNomTypeCheck, boolean needError) {
System.err.println("bindOneParam NYI");
return BIND_RESULT_OK;
}

/* Takes a signature along with positional and named arguments and binds them
* into the provided callframe. Returns BIND_RESULT_OK if binding works out,
* BIND_RESULT_FAIL if there is a failure and BIND_RESULT_JUNCTION if the
* failure was because of a Junction being passed (meaning we need to auto-thread). */
public static int bind(ThreadContext tc, CallFrame cf, SixModelObject params,
CallSiteDescriptor csd, Object[] args,
boolean noNomTypeCheck, boolean needError) {
int bindFail = BIND_RESULT_OK;
int curPosArg = 0;

/* If we have a |$foo that's followed by slurpies, then we can suppress
* any future arity checks. */
boolean suppressArityFail = false;

/* Now we'll walk through the signature and go about binding things. */
int numPosArgs = csd.numPositionals;
long numParams = params.elems(tc);
for (long i = 0; i < numParams; i++) {
/* Get parameter, its flags and any named names. */
SixModelObject param = params.at_pos_boxed(tc, i);
param.get_attribute_native(tc, Ops.Parameter, "$!flags", HINT_flags);
int flags = (int)tc.native_i;
SixModelObject namedNames = param.get_attribute_boxed(tc,
Ops.Parameter, "$!named_names", HINT_named_names);

/* Is it looking for us to bind a capture here? */
if ((flags & SIG_ELEM_IS_CAPTURE) != 0) {
/* Capture the arguments from this point forwards into a Capture.
* Of course, if there's no variable name we can (cheaply) do pretty
* much nothing. */
param.get_attribute_native(tc, Ops.Parameter, "$!variable_name", HINT_variable_name);
if (tc.native_s == null) {
System.err.println("cap ok");
bindFail = BIND_RESULT_OK;
}
else {
throw new RuntimeException("Capture param binding NYI");
}
if (bindFail != 0) {
return bindFail;
}
else if (i + 1 == numParams) {
/* 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. */
return BIND_RESULT_OK;
}
else {
SixModelObject nextParam = params.at_pos_boxed(tc, i + 1);
nextParam.get_attribute_native(tc, Ops.Parameter, "$!flags", HINT_flags);
if (((int)tc.native_i & (SIG_ELEM_SLURPY_POS | SIG_ELEM_SLURPY_NAMED)) != 0)
suppressArityFail = true;
}
}

/* Could it be a named slurpy? */
else if ((flags & SIG_ELEM_SLURPY_NAMED) != 0) {
System.err.println("Slurpy named param NYI");
}

/* Otherwise, maybe it's a positional of some kind. */
else if (namedNames == null) {
/* Slurpy or LoL-slurpy? */
if ((flags & (SIG_ELEM_SLURPY_POS | SIG_ELEM_SLURPY_LOL)) != 0) {
System.err.println("Slurpy pos param NYI");
}

/* Otherwise, a positional. */
else {
/* Do we have a value?. */
if (curPosArg < numPosArgs) {
/* Easy - just bind that. */
bindFail = bindOneParam(tc, cf, param, args[curPosArg],
csd.argFlags[curPosArg], noNomTypeCheck, needError);
if (bindFail != 0)
return bindFail;
curPosArg++;
}
else {
/* No value. If it's optional, fetch a default and bind that;
* if not, we're screwed. Note that we never nominal type check
* an optional with no value passed. */
if ((flags & SIG_ELEM_IS_OPTIONAL) != 0) {
System.err.println("Optional parameters NYI");
}
else {
if (needError)
lastErrors.put(tc, arityFail(tc, params, (int)numParams, numPosArgs, false));
return BIND_RESULT_FAIL;
}
}
}
}

/* Else, it's a non-slurpy named. */
else {
System.err.println("Named arg binding NYI");
}
}


/* XXX TODO. */
System.err.println("p6bindsig NYI");
return BIND_RESULT_OK;
Expand Down
2 changes: 1 addition & 1 deletion src/vm/jvm/runtime/org/perl6/rakudo/Ops.java
Expand Up @@ -9,7 +9,7 @@
public final class Ops {
private static SixModelObject Code;
private static SixModelObject Signature;
private static SixModelObject Parameter;
public static SixModelObject Parameter;
private static SixModelObject False;
private static SixModelObject True;
private static boolean initialized = false;
Expand Down

0 comments on commit 380909f

Please sign in to comment.