First take at implementing predicate checks for OTREDyn.
Status in test suite CallinMethodBinding: 0/18/394 (E/F/T)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
index 632e599..e64613a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
@@ -46,6 +46,7 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialLiftExpression;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PotentialRoleReceiverExpression;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.OTDynCallinBindingsAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lifting;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
@@ -54,6 +55,7 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.AbstractStatementsGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
+import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.PredicateGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstClone;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
@@ -98,6 +100,8 @@
static final char[][] BEFORE_ARG_NAMES = new char[][]{IOTConstants.BASE, CALLIN_ID, BOUND_METHOD_ID, ARGUMENTS};
static final char[][] AFTER_ARG_NAMES = new char[][]{IOTConstants.BASE, CALLIN_ID, BOUND_METHOD_ID, ARGUMENTS, _OT_RESULT};
+ protected static final String OT_LOCAL = "_OT$local$"; //$NON-NLS-1$
+
private RoleModel _role;
private ClassScope _roleScope;
@@ -340,6 +344,9 @@
statements.add(gen.caseStatement(gen.intLiteral(baseMethodSpec.callinID)));
handledCallinIds[baseMethodSpec.callinID] = true;
}
+ PredicateGenerator predGen = new PredicateGenerator(
+ callinDecl.binding._declaringRoleClass,
+ callinDecl.isReplaceCallin());
MethodSpec baseSpec = callinDecl.baseMethodSpecs[0]; // TODO(SH): check base method multiplicity
@@ -355,35 +362,47 @@
boolean needLiftedRoleVar = !isStaticRoleMethod
&& roleType.isCompatibleWith(roleMethodBinding.declaringClass);
- int nStats = isReplace ? 1 : 2; // "return rm();" or "rm(); break;"
- if (needLiftedRoleVar)
- nStats++; // local role
- if (callinDecl.mappings != null)
- nStats += baseSpec.arguments.length; // one local per base arg
- if (mayUseResultArgument)
- nStats++; // local var "result"
- Statement[] blockStatements = new Statement[nStats];
- int statIdx = 0;
+ List<Statement> blockStatements = new ArrayList<Statement>();
+
+ // -------------- base predicate check -------
+ boolean hasBasePredicate = false;
+ for (MethodSpec baseMethodSpec : callinDecl.baseMethodSpecs) {
+ char[] resultName = null;
+ if ( callinDecl.callinModifier == TerminalTokens.TokenNameafter
+ && baseMethodSpec.resolvedType() != TypeBinding.VOID)
+ {
+ resultName = IOTConstants.RESULT;
+ }
+ // FIXME(SH): only call predidate for the current base method (from BoundMethodID?)
+ Statement predicateCheck = predGen.createBasePredicateCheck(
+ callinDecl, baseMethodSpec, resultName, gen);
+ if (predicateCheck != null) {
+ blockStatements.add(predicateCheck);
+ hasBasePredicate = true;
+ }
+ }
+
+
if (mayUseResultArgument)
// BaseReturnType result = (BaseReturnType)_OT$result;
- blockStatements[statIdx++] = gen.localVariable(RESULT, baseReturn,
+ blockStatements.add(gen.localVariable(RESULT, baseReturn,
gen.castExpression(gen.singleNameReference(_OT_RESULT),
gen.typeReference(baseReturn),
- CastExpression.RAW));
+ CastExpression.RAW)));
Expression receiver;
if (!isStaticRoleMethod) {
if (needLiftedRoleVar) {
// RoleType local$n = this._OT$liftToRoleType((BaseType)base);
char[] roleVar = (LOCAL_ROLE+statements.size()).toCharArray();
- blockStatements[statIdx++] = gen.localVariable(roleVar, roleType.sourceName(),
+ blockStatements.add(gen.localVariable(roleVar, roleType.sourceName(),
Lifting.liftCall(callMethod.scope,
gen.thisReference(),
gen.castExpression(gen.singleNameReference(IOTConstants.BASE), gen.typeReference(roleType.baseclass()), CastExpression.RAW),
callMethod.scope.getType(IOTConstants.ORG_OBJECTTEAMS_IBOUNDBASE, 3),
roleType,
false,
- gen));
+ gen)));
receiver = gen.singleNameReference(roleVar);
// private receiver needs to be casted to the class.
if (callinDecl.getRoleMethod().isPrivate())
@@ -396,9 +415,9 @@
receiver = gen.singleNameReference(callinDecl.getRoleMethod().declaringClass.sourceName());
}
- // unpack arguments to be used by parameter mappings:
+ // unpack arguments to be used by parameter mappings and base predicate:
// ArgTypeN argn = args[n]
- if (callinDecl.mappings != null) {
+ if (callinDecl.mappings != null || (hasBasePredicate && baseSpec.arguments != null)) {
TypeBinding[] baseParams = baseSpec.resolvedParameters();
for (int i=0; i<baseSpec.arguments.length; i++) {
Argument baseArg = baseSpec.arguments[i];
@@ -409,7 +428,8 @@
} else if (!baseParams[i].isTypeVariable()) {
init = gen.castExpression(rawArg, gen.typeReference(baseParams[i].erasure()), CastExpression.RAW);
}
- blockStatements[statIdx++] = gen.localVariable(baseArg.name, AstClone.copyTypeReference(baseArg.type), init);
+ // add to front so it is already available for the base predicate check:
+ blockStatements.add(i, gen.localVariable(baseArg.name, AstClone.copyTypeReference(baseArg.type), init));
}
}
@@ -424,33 +444,53 @@
callArgs[idx++] = gen.singleNameReference(argName);
for (int i=0; i<roleParams.length; i++) {
+ Expression arg;
+ TypeBinding roleParam = roleParams[i].erasure(); // type vars of callin-decl and role are not in scope :(
if (callinDecl.mappings == null) {
- Expression arg = gen.arrayReference(gen.singleNameReference(ARGUMENTS), i);
- if (roleParams[i].isBaseType()) {
- arg = gen.createUnboxing(arg, (BaseTypeBinding)roleParams[i]); // includes intermediate cast to boxed type
+ arg = gen.arrayReference(gen.singleNameReference(ARGUMENTS), i);
+ if (roleParam.isBaseType()) {
+ arg = gen.createUnboxing(arg, (BaseTypeBinding)roleParam); // includes intermediate cast to boxed type
} else {
// Object -> MyBaseClass
if (!baseSpec.resolvedParameters()[i].isTypeVariable())
arg = gen.castExpression(arg, gen.typeReference(baseSpec.resolvedParameters()[i].erasure()), CastExpression.DO_WRAP);
// lift?(MyBaseClass)
- arg = gen.potentialLift(gen.thisReference(), arg, roleParams[i], isReplace/*reversible*/);
+ arg = gen.potentialLift(gen.thisReference(), arg, roleParam, isReplace/*reversible*/);
}
- callArgs[i+idx] = arg;
} else {
- callArgs[i+idx] = getArgument(callinDecl, (MethodDeclaration) methodDecl, callinDecl.getRoleMethod().parameters,
- i+idx, baseSpec);
+ arg = new PotentialRoleReceiverExpression(
+ getArgument(callinDecl, (MethodDeclaration) methodDecl, callinDecl.getRoleMethod().parameters, i+idx, baseSpec),
+ ROLE_VAR_NAME,
+ gen.typeReference(roleType.getRealClass()));
}
+ char[] localName = (OT_LOCAL+i).toCharArray();
+ blockStatements.add(gen.localVariable(localName, roleParam, arg));
+ callArgs[i+idx] = gen.singleNameReference(localName);
+
}
+ // -- role side predicate:
+ Expression[] predicateArgs = maybeAddResultReference(callinDecl, callArgs, _OT_RESULT, gen);
+ Statement rolePredicateCheck = predGen.createPredicateCheck(
+ callinDecl,
+ callinDecl.scope.referenceType(),
+ receiver,
+ predicateArgs,
+ callArgs,
+ gen);
+ if (rolePredicateCheck != null)
+ // predicateCheck(_OT$role)
+ statements.add(rolePredicateCheck);
+
// -- assemble the method call:
MessageSend roleMethodCall = gen.messageSend(receiver, callinDecl.roleMethodSpec.selector, callArgs);
roleMethodCall.isPushedOutRoleMethodCall = true;
if (isReplace) {
- blockStatements[statIdx] = gen.returnStatement(roleMethodCall);
+ blockStatements.add(gen.returnStatement(roleMethodCall));
} else {
- blockStatements[statIdx++] = roleMethodCall;
- blockStatements[statIdx] = gen.breakStatement();
+ blockStatements.add(roleMethodCall);
+ blockStatements.add(gen.breakStatement());
}
- statements.add(gen.block(blockStatements));
+ statements.add(gen.block(blockStatements.toArray(new Statement[blockStatements.size()])));
}
boolean needSuperCall = false;
// callinIds handled by super call?
@@ -516,6 +556,28 @@
}
});
}
+ /**
+ * Assemble message send arguments plus perhaps a result reference to
+ * yield argument expressions for a predicate call.
+ * (From old CallinImplementor).
+ */
+ Expression[] maybeAddResultReference(CallinMappingDeclaration callinBindingDeclaration,
+ Expression[] messageSendArguments,
+ char[] resultName,
+ AstGenerator gen)
+ {
+ Expression[] predicateArgs = null;
+ if (callinBindingDeclaration.hasSignature) {
+ predicateArgs = messageSendArguments;
+ if (resultName != null) // has resultVar (after with non-void base return)
+ {
+ int l = messageSendArguments.length;
+ System.arraycopy(messageSendArguments, 0, predicateArgs = new Expression[l+1], 0, l);
+ predicateArgs[l] = gen.baseNameReference(resultName);
+ }
+ }
+ return predicateArgs;
+ }
private void generateCallNext(final List<CallinMappingDeclaration> callinDecls, final TeamModel aTeam) {
// public Object _OT$callNext(IBoundBase baze, Team[] teams, int idx, int[] callinIds, int boundMethodId, Object[] args, Object[] baseCallArgs)