diff options
18 files changed, 611 insertions, 9 deletions
diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdviceContextImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdviceContextImpl.java new file mode 100644 index 00000000..a5e0de21 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdviceContextImpl.java @@ -0,0 +1,91 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.xtend.backend.common.AdviceContext; +import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.util.DoubleKeyCache; +import org.eclipse.xtend.backend.util.ObjectWrapper; +import org.eclipse.xtend.backend.util.Triplet; + + +/** + * This class represents all currently registered advice. It is + * designed to efficiently handle dynamically registered advice, + * e.g. for the scope of an invocation.<br> + * + * In order to allow aggressive caching, it is immutable and creates + * a copy when additional advice is registered. This design decision + * assumes that registering new advice is very infrequent compared to the + * invocation of functions. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class AdviceContextImpl implements AdviceContext { + private final List<AroundAdvice> _advice = new ArrayList<AroundAdvice> (); + + private final DoubleKeyCache <String, Function, AdvisedFunction> _advisedFunctionCache = new DoubleKeyCache<String, Function, AdvisedFunction> () { + @Override + protected AdvisedFunction create (String functionName, Function f) { + final List<AroundAdvice> applicableAdvice = new ArrayList<AroundAdvice> (); + + for (AroundAdvice advice: _advice) + if (advice.getPointcut().matches (functionName, f)) + applicableAdvice.add (advice); + + return new AdvisedFunction (functionName, f, applicableAdvice); + } + }; + + private final Map<Triplet <Function, AroundAdvice, List<?>>, ObjectWrapper> _resultCache; + + + public AdviceContextImpl () { + this (new HashMap<Triplet<Function,AroundAdvice,List<?>>, ObjectWrapper> ()); + } + + private AdviceContextImpl (Map<Triplet <Function, AroundAdvice, List<?>>, ObjectWrapper> resultCache) { + _resultCache = resultCache; + } + + public AdviceContextImpl copyWithAdvice (AroundAdvice advice) { + // the result cache survives the addition (and going out-of-scope!) of advice. This + // is possible because newly applied advice is applied "around" advice applied earlier. + final AdviceContextImpl result = new AdviceContextImpl (_resultCache); + + result._advice.addAll (_advice); + result._advice.add (advice); + + return result; + } + + //TODO test this (including the order in which advice is applied)!!! + + /** + * returns the advice to be applied to this function, starting with the innermost + * advice, i.e. the advice that is to be directly applied to the result of the + * advised function. + */ + public AdvisedFunction getAdvice (String functionName, Function f) { + return _advisedFunctionCache.get (functionName, f); + } + + public Map<Triplet<Function, AroundAdvice, List<?>>, ObjectWrapper> getResultCache () { + return _resultCache; + } +} + + diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdviceParamType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdviceParamType.java new file mode 100644 index 00000000..ec195d2a --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdviceParamType.java @@ -0,0 +1,37 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import org.eclipse.xtend.backend.common.BackendType; + + +/** + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class AdviceParamType { + private final BackendType _type; + private final boolean _includingSubtypes; + + public AdviceParamType (BackendType type, boolean includingSubtypes) { + _type = type; + _includingSubtypes = includingSubtypes; + } + + //TODO testen! + + public boolean matches (BackendType type) { + if (_includingSubtypes) + return _type.isAssignableFrom (type); + else + return _type.equals (type); + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdvisedFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdvisedFunction.java new file mode 100644 index 00000000..ddab16fb --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AdvisedFunction.java @@ -0,0 +1,103 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.util.ObjectWrapper; +import org.eclipse.xtend.backend.util.Triplet; + + +/** + * This class represents a function with all applicable Advice.<br> + * + * It could formally be treated as a function, but it is a conscious design decision + * not to do that. The rationale behind that decision is that advice is bound to a + * name or context (via its PointCut) whereas a function is not. In other words, if + * a function is passed around in a program, the applicable advice can vary - and + * for that reason, advice is only applied "just in time", based on the then current + * name and context. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class AdvisedFunction { + private final Function _function; + private final List<AroundAdvice> _advice; + private final int _firstCacheableIndex; + + private final ThisJoinPointStaticPart _thisJoinPointStaticPart; + + + public AdvisedFunction (String functionName, Function function, List<AroundAdvice> advice) { + _function = function; + _advice = advice; + + _thisJoinPointStaticPart = new ThisJoinPointStaticPart (functionName, _function); + + if (function.isCached()) { + int firstCacheableIndex = advice.size(); + while (firstCacheableIndex > 0 && advice.get (firstCacheableIndex - 1).isCacheable()) + firstCacheableIndex--; + + _firstCacheableIndex = firstCacheableIndex; + } + else + _firstCacheableIndex = advice.size(); + } + + public Object evaluate (ExecutionContext ctx, Object[] params) { + // the evaluation of the advice is performed in three stages: + // 1. all advice that is "outside" the outermost non-cacheable advice + // is always actually evaluated + // 2. advice that is cacheable but not yet cached is evaluated and cached + // (iff the function is cached) + // 3. once cached advice is encountered, the evaluation is short-circuited + // and the result from the cache is returned + + return proceedInternal (ctx, 0, params); + } + + private Object proceedInternal (final ExecutionContext ctx, final int indNextAdvice, final Object[] params) { + if (indNextAdvice >= _advice.size()) + return ctx.getFunctionInvoker().invoke (ctx, _function, Arrays.asList (params)); + + if (indNextAdvice >= _firstCacheableIndex) { + final ObjectWrapper ow = ctx.getAdviceContext().getResultCache().get (new Triplet<Function, AroundAdvice, List<?>> (_function, _advice.get (indNextAdvice), Arrays.asList(params))); + if (ow != null) + return ow._content; + } + + final ThisJoinPoint thisJoinPoint = new ThisJoinPoint (ctx.getStacktrace(), params) { + @Override + public Object proceed (Object[] localParams) { + return proceedInternal (ctx, indNextAdvice+1, localParams); + } + }; + + final AroundAdvice advice = _advice.get (indNextAdvice); + final Object result = advice.evaluate (ctx, thisJoinPoint, _thisJoinPointStaticPart); + + if (indNextAdvice >= _firstCacheableIndex) { + final Triplet<Function, AroundAdvice, List<?>> key = new Triplet<Function, AroundAdvice, List<?>> (_function, _advice.get (indNextAdvice), Arrays.asList(params)); + ctx.getAdviceContext().getResultCache().put (key, new ObjectWrapper (result)); + } + + return result; + } +} + + + + + diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AroundAdvice.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AroundAdvice.java new file mode 100644 index 00000000..29c9c59d --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/AroundAdvice.java @@ -0,0 +1,70 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.ExpressionBase; +import org.eclipse.xtend.backend.common.SyntaxConstants; + + +/** + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class AroundAdvice { + private final ExpressionBase _body; + private final Pointcut _pointcut; + + private final boolean _isCacheable; + + /** + * + * @param body contains the body of this advice + * @param pointcut contains the pointcut that guards this advice + * @param isCacheable This flag marks the advice as "cacheable". This means that the result of its execution + * will be cached iff all advice wrapped by it, and the originally wrapped function, + * are cacheable or cached, respectively. + */ + public AroundAdvice (ExpressionBase body, Pointcut pointcut, boolean isCacheable) { + _body = body; + _pointcut = pointcut; + _isCacheable = isCacheable; + } + + /** + * actually evaluates the advice, regardless of caching - that is context sensitive and must + * be taken care of by callers + */ + public Object evaluate (ExecutionContext ctx, ThisJoinPoint thisJoinPoint, ThisJoinPointStaticPart thisJoinPointStaticPart) { + ctx.getLocalVarContext().getLocalVars().put (SyntaxConstants.THIS_JOINPOINT, thisJoinPoint); + ctx.getLocalVarContext().getLocalVars().put (SyntaxConstants.THIS_JOINPOINT_STATICPART, thisJoinPointStaticPart); + + try { + return _body.evaluate (ctx); + } + finally { + ctx.getLocalVarContext ().getLocalVars ().remove (SyntaxConstants.THIS_JOINPOINT); + ctx.getLocalVarContext ().getLocalVars ().remove (SyntaxConstants.THIS_JOINPOINT_STATICPART); + } + } + + public Pointcut getPointcut () { + return _pointcut; + } + + /** + * This flag determines whether the advice is cacheable. It is intentionally + * kept separate from the "cached" flag of the implementing function because + * of the different semantics. + */ + public boolean isCacheable () { + return _isCacheable; + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ExecutionPointcut.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ExecutionPointcut.java new file mode 100644 index 00000000..13575905 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ExecutionPointcut.java @@ -0,0 +1,118 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import java.util.List; +import java.util.regex.Pattern; + +import org.eclipse.xtend.backend.common.BackendType; +import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.util.Pair; + + +/** + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class ExecutionPointcut implements Pointcut { + private final String _functionNamePattern; + private final boolean _hasCompleteName; + private final Pattern _namePattern; + + private final List<Pair<String, AdviceParamType>> _paramTypes; + + private final boolean _hasVarArgs; + private final AdviceParamType _varArgsType; + + /** + * + * @param functionNamePattern is the pattern for the function name that is matched by this pointcut. '*' can + * be used as a wildcard. + * + * @param paramTypes this is the - optionally empty - list of parameters for which an explicit type is given. + * + * @param hasVarArgs this flag determines if there is a variable number of arguments after the explicitly given + * param types. One of the two extreme cases is that all parameters are explicitly given, then this + * flag is false. The other extreme case is that the pointcut regardless of + * + * @param varArgsType + */ + public ExecutionPointcut (String functionNamePattern, List<Pair<String, AdviceParamType>> paramTypes, boolean hasVarArgs, AdviceParamType varArgsType) { + _functionNamePattern = functionNamePattern; + if (_functionNamePattern.contains ("*")) { + _hasCompleteName = false; + _namePattern = Pattern.compile (functionNamePattern.replace ("*", ".*")); + } + else { + _hasCompleteName = true; + _namePattern = null; + } + + _paramTypes = paramTypes; + _hasVarArgs = hasVarArgs; + _varArgsType = varArgsType; + } + + //TODO testen!!! + + public boolean matches (String name, Function function) { + if (! matchesName (name)) + return false; + + if (! matchesParamTypes (function.getParameterTypes())) + return false; + + return true; + } + + private boolean matchesParamTypes (List<? extends BackendType> paramTypes) { + // check the number of parameters + if (_hasVarArgs) { + if (paramTypes.size() < _paramTypes.size()) + return false; + } + else { + if (paramTypes.size() != _paramTypes.size()) + return false; + } + + // check the explicitly given parameter types + for (int i=0; i<_paramTypes.size(); i++) + if (! _paramTypes.get (i).getSecond().matches (paramTypes.get (i))) + return false; + + // check the var args type against the remaining parameter types + for (int i=_paramTypes.size(); i<paramTypes.size(); i++) + if (! _varArgsType.matches (paramTypes.get(i))) + return false; + + return true; + } + + private boolean matchesName (String functionName) { + if (_hasCompleteName) + return functionName.equals (_functionNamePattern); + + return _namePattern.matcher (functionName).matches(); + } +} + + + + + + + + + + + + diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/Pointcut.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/Pointcut.java new file mode 100644 index 00000000..4a1af326 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/Pointcut.java @@ -0,0 +1,26 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import org.eclipse.xtend.backend.common.Function; + + +/** + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public interface Pointcut { + + /** + * checks if this pointcut matches a given function + */ + public boolean matches (String name, Function f); +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ThisJoinPoint.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ThisJoinPoint.java new file mode 100644 index 00000000..1d36a311 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ThisJoinPoint.java @@ -0,0 +1,45 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import java.util.List; + +import org.eclipse.xtend.backend.common.StacktraceEntry; + + +/** + * This class exposes all dynamic data available for a matched join point. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public abstract class ThisJoinPoint { + private final List<StacktraceEntry> _stackTrace; + private final Object[] _params; + + public ThisJoinPoint (List<StacktraceEntry> stackTrace, Object[] params) { + _stackTrace = stackTrace; + _params = params; + } + + public List<StacktraceEntry> getStackTrace () { + return _stackTrace; + } + + public Object[] getParameters () { + return _params; + } + + public Object proceed () { + return proceed (_params); + } + + public abstract Object proceed (Object[] params); +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ThisJoinPointStaticPart.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ThisJoinPointStaticPart.java new file mode 100644 index 00000000..a61f6366 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/aop/ThisJoinPointStaticPart.java @@ -0,0 +1,42 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.aop; + +import org.eclipse.xtend.backend.common.Function; + + +/** + * This class exposes all static information about the matched join point. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class ThisJoinPointStaticPart { + private final String _functionName; + private final Function _function; + + public ThisJoinPointStaticPart (String functionName, Function function) { + _functionName = functionName; + _function = function; + } + + public String getFunctionName () { + return _functionName; + } + + public Function getFunction () { + return _function; + } + + @Override + public String toString () { + return _functionName + ": " + _function; + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/AdviceContext.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/AdviceContext.java new file mode 100644 index 00000000..2a3c2844 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/AdviceContext.java @@ -0,0 +1,24 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation + */ +package org.eclipse.xtend.backend.common; + +import org.eclipse.xtend.backend.aop.AdvisedFunction; +import org.eclipse.xtend.backend.aop.AroundAdvice; + + +/** + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public interface AdviceContext { + AdviceContext copyWithAdvice (AroundAdvice advice); + AdvisedFunction getAdvice (String functionName, Function f); +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/ExecutionContext.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/ExecutionContext.java index c21df69e..26bd22d7 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/ExecutionContext.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/ExecutionContext.java @@ -12,6 +12,8 @@ package org.eclipse.xtend.backend.common; import java.util.List; +import org.eclipse.xtend.backend.aop.AdviceContextImpl; + /** * @@ -28,6 +30,9 @@ public interface ExecutionContext { FunctionInvoker getFunctionInvoker (); CreationCache getCreationCache (); + AdviceContextImpl getAdviceContext (); + void setAdviceContext (AdviceContextImpl ctx); + void logNullDeRef (SourcePos pos); boolean isLogStacktrace (); diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/util/SyntaxConstants.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/SyntaxConstants.java index fb3818f8..56640a82 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/util/SyntaxConstants.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/SyntaxConstants.java @@ -8,7 +8,7 @@ http://www.eclipse.org/legal/epl-v10.html Contributors: Arno Haase - initial API and implementation */ -package org.eclipse.xtend.backend.util; +package org.eclipse.xtend.backend.common; /** @@ -18,4 +18,7 @@ package org.eclipse.xtend.backend.util; public interface SyntaxConstants { String NS_DELIM = "::"; String THIS = "this"; + + String THIS_JOINPOINT = "thisJoinPoint"; + String THIS_JOINPOINT_STATICPART = "thisJoinPointStaticPart"; } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java index 295bc54b..3716a49d 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java @@ -107,11 +107,12 @@ public final class FunctionDefContextImpl implements FunctionDefContextInternal Function f = null; try { - f = new PolymorphicResolver(functionName).evaluateGuards(ctx, candidates); + f = new PolymorphicResolver (functionName).evaluateGuards (ctx, candidates); } catch (Exception exc) { ErrorHandler.handle ("could not resolve function '" + functionName + "' for parameter types " + StringHelper.getTypesAsString (params) + " - candidates were " + candidates, exc); } + return ctx.getFunctionInvoker().invoke (ctx, f, params); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/ExecutionContextImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/ExecutionContextImpl.java index c27ba972..3658d0c3 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/ExecutionContextImpl.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/ExecutionContextImpl.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.LogFactory; +import org.eclipse.xtend.backend.aop.AdviceContextImpl; import org.eclipse.xtend.backend.common.BackendTypesystem; import org.eclipse.xtend.backend.common.Constants; import org.eclipse.xtend.backend.common.ContributionStateContext; @@ -39,6 +40,8 @@ public final class ExecutionContextImpl implements ExecutionContext { private final boolean _logStacktrace; private final List<StacktraceEntry> _stacktrace = new ArrayList<StacktraceEntry> (); + private AdviceContextImpl _adviceContext = new AdviceContextImpl (); + private final ContributionStateContext _contributionStateContext = new ContributionStateContext (); public ExecutionContextImpl (FunctionDefContext initialFunctionDefContext, BackendTypesystem typesystem, boolean logStacktrace) { @@ -94,4 +97,12 @@ public final class ExecutionContextImpl implements ExecutionContext { public boolean isLogStacktrace () { return _logStacktrace; } + + public AdviceContextImpl getAdviceContext () { + return _adviceContext; + } + + public void setAdviceContext (AdviceContextImpl ctx) { + _adviceContext = ctx; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/FunctionInvokerImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/FunctionInvokerImpl.java index 4b9b5547..4a934c1b 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/FunctionInvokerImpl.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/internal/FunctionInvokerImpl.java @@ -38,7 +38,7 @@ public final class FunctionInvokerImpl implements FunctionInvoker { private ExecutionContext _ctx; - public Object invoke(ExecutionContext ctx, Function f, List<?> params) { + public Object invoke (ExecutionContext ctx, Function f, List<?> params) { if (f.isCached()) { _ctx = ctx; return _cache.get(f, params); diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/util/ObjectWrapper.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/util/ObjectWrapper.java new file mode 100644 index 00000000..92ab9d5a --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/util/ObjectWrapper.java @@ -0,0 +1,26 @@ +/* +Copyright (c) 2008 Arno Haase. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://www.eclipse.org/legal/epl-v10.html + +Contributors: + Arno Haase - initial API and implementation +*/ +package org.eclipse.xtend.backend.util; + + +/** + * This class was introduced to allow the distinction between a cached "null" value + * and no stored value without necessitating two lookups. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class ObjectWrapper { + public ObjectWrapper (Object content) { + _content = content; + } + + public Object _content; +} diff --git a/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldDefinitionConverter.java b/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldDefinitionConverter.java index 06f6dbf4..a2ead0ba 100644 --- a/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldDefinitionConverter.java +++ b/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldDefinitionConverter.java @@ -41,6 +41,7 @@ import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.common.SourcePos; +import org.eclipse.xtend.backend.common.SyntaxConstants; import org.eclipse.xtend.backend.expr.ConcatExpression; import org.eclipse.xtend.backend.expr.HidingLocalVarDefExpression; import org.eclipse.xtend.backend.expr.IfExpression; @@ -55,7 +56,6 @@ import org.eclipse.xtend.backend.functions.SourceDefinedFunction; import org.eclipse.xtend.backend.syslib.FileIoOperations; import org.eclipse.xtend.backend.syslib.SysLibNames; import org.eclipse.xtend.backend.types.builtin.ObjectType; -import org.eclipse.xtend.backend.util.SyntaxConstants; import org.eclipse.xtend.expression.AnalysationIssue; import org.eclipse.xtend.expression.ExecutionContext; import org.eclipse.xtend.expression.Variable; diff --git a/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExpressionConverter.java b/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExpressionConverter.java index f9e3db60..d4b4e1d6 100644 --- a/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExpressionConverter.java +++ b/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExpressionConverter.java @@ -152,7 +152,7 @@ final class OldExpressionConverter { if (hasMatchingOperationCall (functionName, paramTypes.toArray (new Type[0]))) return new InvocationOnObjectExpression (functionName, params, false, sourcePos); else { - final ExpressionBase thisExpression = new LocalVarEvalExpression (org.eclipse.xtend.backend.util.SyntaxConstants.THIS, sourcePos); + final ExpressionBase thisExpression = new LocalVarEvalExpression (org.eclipse.xtend.backend.common.SyntaxConstants.THIS, sourcePos); final Type thisType = (Type) _ctx.getVariable (ExecutionContext.IMPLICIT_VARIABLE).getValue(); return createInvocationOnTargetExpression (functionName, thisExpression, thisType, params, paramTypes, true, sourcePos); } @@ -251,7 +251,7 @@ final class OldExpressionConverter { if (! hasThis()) throw new IllegalStateException ("typeSelect with neither a target nor an implicit 'this'"); - final ExpressionBase thisExpr = new LocalVarEvalExpression (org.eclipse.xtend.backend.util.SyntaxConstants.THIS, sourcePos); + final ExpressionBase thisExpr = new LocalVarEvalExpression (org.eclipse.xtend.backend.common.SyntaxConstants.THIS, sourcePos); return new InvocationOnObjectExpression (SysLibNames.TYPE_SELECT, Arrays.asList (thisExpr, typeExpr), true, sourcePos); } else @@ -324,7 +324,7 @@ final class OldExpressionConverter { // 4. check for "this" if (hasThis()) { - final ExpressionBase thisExpr = new LocalVarEvalExpression (org.eclipse.xtend.backend.util.SyntaxConstants.THIS, sourcePos); + final ExpressionBase thisExpr = new LocalVarEvalExpression (org.eclipse.xtend.backend.common.SyntaxConstants.THIS, sourcePos); return createPropertyExpression (thisExpr, (Type) _ctx.getVisibleVariables().get (ExecutionContext.IMPLICIT_VARIABLE).getValue(), expr.getName().getValue(), sourcePos); } @@ -372,7 +372,7 @@ final class OldExpressionConverter { if (! hasThis()) throw new IllegalStateException (functionName + " with neither a target nor an implicit 'this'"); - final ExpressionBase thisExpr = new LocalVarEvalExpression (org.eclipse.xtend.backend.util.SyntaxConstants.THIS, sourcePos); + final ExpressionBase thisExpr = new LocalVarEvalExpression (org.eclipse.xtend.backend.common.SyntaxConstants.THIS, sourcePos); return new InvocationOnObjectExpression (functionName, Arrays.asList (thisExpr, closureExpr), true, sourcePos); } else diff --git a/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExtensionConverter.java b/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExtensionConverter.java index 25799409..d9466bd1 100644 --- a/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExtensionConverter.java +++ b/plugins/org.eclipse.xtend.middleend.old/src/org/eclipse/xtend/middleend/old/OldExtensionConverter.java @@ -25,12 +25,12 @@ import org.eclipse.xtend.backend.common.ExpressionBase; import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.NamedFunction; +import org.eclipse.xtend.backend.common.SyntaxConstants; import org.eclipse.xtend.backend.expr.CreateCachedExpression; import org.eclipse.xtend.backend.expr.LocalVarEvalExpression; import org.eclipse.xtend.backend.expr.NewLocalVarDefExpression; import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.backend.functions.SourceDefinedFunction; -import org.eclipse.xtend.backend.util.SyntaxConstants; import org.eclipse.xtend.expression.AnalysationIssue; import org.eclipse.xtend.expression.ExecutionContext; import org.eclipse.xtend.expression.Variable; |