Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2013-01-05 21:46:40 +0000
committerStephan Herrmann2013-01-22 20:48:26 +0000
commitf347a7c86e66fcbac9468e9bf4d7028a33df1d93 (patch)
tree76eb6088b195e9323cbfabeeb3103585c120709c
parent7fbb8f7a2dd267ce2e988aed25ff156cf30c1430 (diff)
downloadorg.eclipse.objectteams-f347a7c86e66fcbac9468e9bf4d7028a33df1d93.tar.gz
org.eclipse.objectteams-f347a7c86e66fcbac9468e9bf4d7028a33df1d93.tar.xz
org.eclipse.objectteams-f347a7c86e66fcbac9468e9bf4d7028a33df1d93.zip
Bug 397192 - Prepare OTDT for new (dynamic) weaver:
Improvements for array-translations: - distinguish who's responsible for lift/lowering: team or current role? - lift/lower calls are manually resolved, avoid unintended role wrapping - now some lowering exprs need their teamExpr to be resolved in a deferred way. AllTests: 2184/2/135
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java56
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java41
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java12
7 files changed, 142 insertions, 18 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java
index fd0ac5be5..677ddb03b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLifting.java
@@ -40,7 +40,7 @@ public class ArrayLifting extends ArrayTranslations {
TypeBinding requiredType)
{
this._teamExpr = teamExpr;
- return (MessageSend)translateArray(scope, expression, providedType, requiredType, /*isLifting*/true);
+ return (MessageSend)translateArray(scope, expression, providedType, requiredType, /*isLifting*/true, /*deferredResolve*/false);
}
/* implement hook. */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java
index 09edc8aac..6af5828a5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayLowering.java
@@ -44,15 +44,17 @@ public class ArrayLowering extends ArrayTranslations {
BlockScope scope,
Expression expression,
TypeBinding providedType,
- TypeBinding requiredType)
+ TypeBinding requiredType,
+ boolean deferredResolve)
{
// TODO (SH): check if we need to use the team anchor of a RoleTypeBinding
// as receiver for the translation call.
ReferenceBinding teamBinding = ((ReferenceBinding)providedType.leafComponentType()).enclosingType();
if (this._teamExpr == null)
this._teamExpr = new AstGenerator(expression).qualifiedThisReference(teamBinding);
- this._teamExpr.resolveType(scope);
- return translateArray(scope, expression, providedType, requiredType, /*isLifting*/false);
+ if (!deferredResolve)
+ this._teamExpr.resolveType(scope);
+ return translateArray(scope, expression, providedType, requiredType, /*isLifting*/false, deferredResolve);
}
/* implement hook. */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java
index 60fde271b..5d4966ae4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/ArrayTranslations.java
@@ -36,6 +36,7 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstConverter;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator.IRunInScope;
/**
* This class handles the common part of array lifting and lowering.
@@ -86,20 +87,34 @@ public abstract class ArrayTranslations {
* @param providedType given type of expression
* @param requiredType this should be produced by translation
* @param isLifting is a lifting translation required (else == lowering)
+ * @param deferredResolve if true we set up a special message send for custom resolving
* @return a message send to the appropriate translation method.
*/
- Expression translateArray(BlockScope scope, Expression expression, TypeBinding providedType, TypeBinding requiredType, boolean isLifting) {
+ Expression translateArray(BlockScope scope, Expression expression,
+ TypeBinding providedType, TypeBinding requiredType,
+ boolean isLifting, boolean deferredResolve)
+ {
this._scope = scope;
this._expression = expression;
MethodBinding methodBinding = ensureTransformMethod(
scope, this._teamExpr, providedType, requiredType, isLifting);
+ // if expression is resolved but teamExpression is unresolved schedule special resolving:
+ IRunInScope hook = new IRunInScope() { public void run(BlockScope blockScope) { /*nop*/ } };
+ if (deferredResolve && expression.resolvedType != null && this._teamExpr.resolvedType == null) {
+ hook = new IRunInScope() { public void run(BlockScope blockScope) {
+ // resolving this expression was deferred:
+ ArrayTranslations.this._teamExpr.resolve(blockScope);
+ }};
+ }
+
AstGenerator gen = new AstGenerator(expression.sourceStart, expression.sourceEnd);
- MessageSend send = gen.messageSend(
+ MessageSend send = gen.messageSendWithResolveHook(
this._teamExpr,
methodBinding.selector,
- new Expression[] {expression});
+ new Expression[] {expression},
+ hook);
// manual resolving since expression is already resolved:
send.binding = methodBinding;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java
index d332642fa..dcf614610 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lifting/Lowering.java
@@ -74,12 +74,23 @@ public class Lowering implements IOTConstants {
* @return translation expression
*/
public Expression lowerExpression(
- BlockScope scope,
+ final BlockScope scope,
final Expression expression,
+ TypeBinding unloweredType,
+ TypeBinding requiredType,
+ final Expression teamExpression,
+ boolean needNullCheck)
+ {
+ return lowerExpression(scope, expression, unloweredType, requiredType, teamExpression, needNullCheck, false);
+ }
+ public Expression lowerExpression(
+ final BlockScope scope,
+ final Expression expression,
TypeBinding unloweredType,
TypeBinding requiredType,
- Expression teamExpression,
- boolean needNullCheck)
+ final Expression teamExpression,
+ boolean needNullCheck,
+ boolean deferredResolve)
{
// Note, this method is responsible for 'resolving' all AST nodes it generates!
@@ -116,7 +127,8 @@ public class Lowering implements IOTConstants {
scope,
unloweredExpression,
unloweredType,
- requiredType);
+ requiredType,
+ deferredResolve);
}
else
{
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 711ba5b3f..6de35d5c8 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
@@ -38,8 +38,10 @@ import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -109,7 +111,7 @@ public class CallinImplementorDyn extends MethodMappingImplementor {
static final char[] ARGUMENTS = "arguments".toCharArray(); //$NON-NLS-1$
static final char[] _OT_RESULT = "_OT$result".toCharArray(); //$NON-NLS-1$
static final char[] RESULT = "result".toCharArray(); //$NON-NLS-1$
- static final String LOCAL_ROLE = "local$"; //$NON-NLS-1$
+ static final String LOCAL_ROLE = "local$role$"; //$NON-NLS-1$
// for call next:
private static final char[] BASE_CALL_ARGS = "baseCallArguments".toCharArray(); //$NON-NLS-1$
@@ -596,10 +598,15 @@ public class CallinImplementorDyn extends MethodMappingImplementor {
Statement[] messageSendStatements;
if (isReplace) {
Expression result = roleMethodCall;
- if (baseSpec.returnNeedsTranslation) {// FIXME(SH): per base method!
+ if (baseSpec.returnNeedsTranslation) {
// lowering:
TypeBinding[]/*role,base*/ returnTypes = getReturnTypes(callinDecl, 0);
- result = new Lowering().lowerExpression(methodDecl.scope, result, returnTypes[0], returnTypes[1], gen.thisReference(), true);
+ // who is responsible for lowering: the team or the current role?
+ Expression lowerReceiver = (isRoleOfCurrentRole(roleType, returnTypes[0]))
+ ? gen.singleNameReference(roleVar)
+ : gen.thisReference();
+ result = new Lowering().lowerExpression(methodDecl.scope, result, returnTypes[0], returnTypes[1],
+ lowerReceiver, true/*needNullCheck*/, true/*delayedResolve*/);
}
// possibly convert using result mapping
callinDecl.checkResultMapping();
@@ -862,8 +869,13 @@ public class CallinImplementorDyn extends MethodMappingImplementor {
if (mapping.baseMethodSpecs[0].returnNeedsTranslation) { // FIXME(SH): per basemethod!
// lifting:
TypeBinding[]/*role,base*/ returnTypes = getReturnTypes(mapping, 0);
+ // who is responsible for lifting: the team or the current role?
+ Expression liftReceiver = (isRoleOfCurrentRole(mapping.scope.enclosingReceiverType(), returnTypes[0]))
+ ? Lifting.liftCall(mapping.scope, gen.thisReference(), gen.singleNameReference(IOTConstants.BASE), returnTypes[1], returnTypes[0], false)
+ // TODO: might want to extend the signature of callNext to pass the current role to avoid this lifting?
+ : gen.thisReference();
result = Lifting.liftCall(mapping.scope,
- gen.thisReference(),
+ liftReceiver,
gen.castExpression(result,
gen.typeReference(returnTypes[1]),
CastExpression.RAW),
@@ -974,4 +986,40 @@ public class CallinImplementorDyn extends MethodMappingImplementor {
}
return false;
}
+
+ /**
+ * the expression local$role$n.roleMethod(..) should not wrap its
+ * return type anchored to the generated team anchor _OT$role,
+ * because the method should actually be seen as being within
+ * the scope of this role already, although, physically it is part of
+ * the team.
+ *
+ * @param scope use the scope to determine if we are actually within
+ * a callin wrapper.
+ * @param receiver if this is _OT$role this is the role method call.
+ * @return true if the return type should not be wrapped further.
+ */
+ public static boolean avoidWrapRoleType(BlockScope scope, Expression receiver) {
+ MethodScope methodScope = scope.methodScope();
+ if (methodScope != null) { // CLOVER: never false in jacks suite
+ AbstractMethodDeclaration refMethod = methodScope.referenceMethod();
+ if ( refMethod != null
+ && refMethod.isMappingWrapper._callin())
+ {
+ if ( receiver instanceof SingleNameReference
+ && CharOperation.prefixEquals(LOCAL_ROLE.toCharArray(), ((SingleNameReference)receiver).token))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean isRoleOfCurrentRole(ReferenceBinding currentRole, TypeBinding type) {
+ TypeBinding leafType = type.leafComponentType();
+ if (leafType.isRole()) {
+ return currentRole.erasure().isCompatibleWith(leafType.enclosingType().erasure());
+ }
+ return false;
+ }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
index 75dc7ee04..16f5a7c9f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
@@ -743,6 +743,47 @@ public class AstGenerator extends AstFactory {
return messageSend;
}
+ // function type for the next method:
+ public static interface IRunInScope { void run(BlockScope scope); }
+
+ /**
+ * Create a message send that has a custom resolve method (see inside for details).
+ */
+ public MessageSend messageSendWithResolveHook(Expression receiver, char[] selector, Expression[] parameters, final IRunInScope hook) {
+ MessageSend messageSend = new MessageSend() {
+ @Override
+ public TypeBinding resolveType(BlockScope scope) {
+ // arguments always need resolving:
+ if (this.arguments != null) {
+ int length = this.arguments.length;
+ for (int i = 0; i < length; i++){
+ Expression argument = this.arguments[i];
+ if (argument.resolvedType == null)
+ argument.resolveType(scope);
+ }
+ }
+ // skip the receiver unless its again a hooked message send:
+ if (this.receiver.getClass() == this.getClass())
+ this.receiver.resolveType(scope);
+
+ // the main payload:
+ hook.run(scope);
+
+ this.actualReceiverType = this.binding.declaringClass;
+ return this.resolvedType;
+ }
+ };
+ messageSend.sourceStart = this.sourceStart;
+ messageSend.sourceEnd = this.sourceEnd;
+ messageSend.statementEnd = this.sourceEnd;
+ messageSend.nameSourcePosition = this.pos;
+ messageSend.receiver = receiver;
+ messageSend.selector = selector;
+ messageSend.arguments = parameters;
+ messageSend.constant = Constant.NotAConstant;
+ return messageSend;
+ }
+
public MessageSend messageSend(Expression receiver, char[] selector, Expression[] parameters, final TypeBinding resolvedReturn) {
MessageSend messageSend = new MessageSend() {
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
index 675fc59d1..d59c1991f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/RoleTypeCreator.java
@@ -389,9 +389,15 @@ public class RoleTypeCreator implements TagBits {
else
returnType = roleReturn;
}
- if (CallinImplementor.avoidWrapRoleType(scope, send.receiver))
- // don't use synthetic _OT$role as additional anchor
- return returnType;
+ if (CallinImplementorDyn.DYNAMIC_WEAVING) {
+ if (CallinImplementorDyn.avoidWrapRoleType(scope, send.receiver))
+ // don't use synthetic local$role$n as additional anchor
+ return returnType;
+ } else {
+ if (CallinImplementor.avoidWrapRoleType(scope, send.receiver))
+ // don't use synthetic _OT$role as additional anchor
+ return returnType;
+ }
}
} else {
if (send.arguments != null && send.arguments.length > 0)

Back to the top