From e90f8a9dcd53e3449a220699792b569f96208182 Mon Sep 17 00:00:00 2001 From: ahaase Date: Mon, 10 Mar 2008 23:58:51 +0000 Subject: refactored middleend infrastructure to improve reuse between languages --- .../org.eclipse.xtend.backend/META-INF/MANIFEST.MF | 12 +- .../org/eclipose/xtend/middleend/MiddleEnd.java | 139 ------------- .../eclipose/xtend/middleend/MiddleEndFactory.java | 48 ----- .../xtend/middleend/internal/Activator.java | 105 ---------- .../plugins/LanguageSpecificMiddleEnd.java | 58 ------ .../plugins/LanguageSpecificMiddleEndFactory.java | 48 ----- .../eclipse/xtend/backend/aop/AroundAdvice.java | 9 +- .../org/eclipse/xtend/backend/common/Function.java | 4 +- .../xtend/backend/expr/CurriedFunction.java | 9 + .../backend/expr/HidingLocalVarDefExpression.java | 3 + .../expr/InvocationOnWhateverExpression.java | 3 + .../backend/expr/PropertyOnWhateverExpression.java | 3 + .../xtend/backend/functions/AbstractFunction.java | 50 +++++ .../backend/functions/SourceDefinedFunction.java | 48 +---- .../xtend/backend/functions/internal/Closure.java | 35 ++-- .../functions/internal/FunctionDefContextImpl.java | 1 - .../backend/internal/FunctionInvokerImpl.java | 20 +- .../xtend/backend/syslib/CollectionOperations.java | 6 +- .../xtend/backend/syslib/StringOperations.java | 4 +- .../eclipse/xtend/backend/types/AbstractType.java | 17 ++ .../xtend/backend/types/builtin/FunctionType.java | 9 + .../xtend/backend/types/builtin/TypeType.java | 9 + .../backend/types/emf/internal/EClassType.java | 9 + .../backend/types/java/internal/JavaOperation.java | 22 +- .../src/org/eclipse/xtend/middleend/MiddleEnd.java | 51 +++++ .../eclipse/xtend/middleend/MiddleEndFactory.java | 49 +++++ .../xtend/middleend/internal/Activator.java | 105 ++++++++++ .../xtend/middleend/internal/MiddleEndImpl.java | 223 +++++++++++++++++++++ .../AbstractExecutionContextAware.java | 2 + .../javaannotations/JavaDefinedFunction.java | 200 ------------------ .../JavaFunctionClassContributor.java | 64 ++++-- .../middleend/javaannotations/M2tAroundAdvice.java | 31 +++ .../xtend/middleend/javaannotations/M2tCached.java | 27 +++ .../xtend/middleend/javaannotations/M2tHidden.java | 27 --- .../middleend/javaannotations/M2tNoFunction.java | 27 +++ .../javaannotations/M2tPrivateFunction.java | 28 +++ .../internal/JavaDefinedFunction.java | 152 ++++++++++++++ .../xtend/middleend/plugins/ImportedResource.java | 34 ++++ .../plugins/LanguageSpecificMiddleEnd.java | 46 +++++ .../plugins/LanguageSpecificMiddleEndFactory.java | 48 +++++ .../xtend/middleend/plugins/ParsedResource.java | 46 +++++ .../xtend/middleend/xpand/OldXpandRegistry.java | 118 ++++------- .../xtend/middleend/xpand/XpandBackendFacade.java | 9 +- .../xpand/internal/OldDefinitionConverter.java | 23 +-- .../xpand/internal/OldXpandRegistryFactory.java | 4 +- .../xtend/middleend/xtend/OldXtendRegistry.java | 171 +++------------- .../xtend/middleend/xtend/XtendBackendFacade.java | 18 +- .../xtend/internal/OldExpressionConverter.java | 5 +- .../xtend/middleend/xtend/internal/OldHelper.java | 4 +- .../xtend/internal/xtend/CheckConverter.java | 5 +- .../internal/xtend/JavaExtensionFunction.java | 22 +- .../internal/xtend/OldExtensionConverter.java | 31 +-- .../internal/xtendlib/XtendLibContributor.java | 2 +- .../xtend/plugin/OldXtendRegistryFactory.java | 4 +- .../src/org/eclipse/xtend/backend/aop/AopTest.java | 55 ++--- .../backend/expr/InitClosureExpressionTest.java | 16 +- .../xtend/backend/functions/FunctionTest.java | 15 +- .../backend/testhelpers/BackendTestHelper.java | 11 +- .../backend/testhelpers/NamedFunctionFactory.java | 36 ++-- .../xtend/middleend/old/first/FirstAttempt.java | 2 + 60 files changed, 1248 insertions(+), 1134 deletions(-) delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEnd.java delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEndFactory.java delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/internal/Activator.java delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/AbstractFunction.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEnd.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEndFactory.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/Activator.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/MiddleEndImpl.java delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaDefinedFunction.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tAroundAdvice.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tCached.java delete mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tHidden.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tNoFunction.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tPrivateFunction.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/internal/JavaDefinedFunction.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ImportedResource.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java create mode 100644 plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ParsedResource.java diff --git a/plugins/org.eclipse.xtend.backend/META-INF/MANIFEST.MF b/plugins/org.eclipse.xtend.backend/META-INF/MANIFEST.MF index fd67501f..0bf9d571 100644 --- a/plugins/org.eclipse.xtend.backend/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.xtend.backend/META-INF/MANIFEST.MF @@ -3,10 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Backend Plug-in (Incubation) Bundle-SymbolicName: org.eclipse.xtend.backend;singleton:=true Bundle-Version: 0.7.0 -Export-Package: org.eclipose.xtend.middleend, - org.eclipose.xtend.middleend.internal;x-internal:=true, - org.eclipose.xtend.middleend.plugins, - org.eclipse.xtend.backend;uses:="org.eclipse.xtend.backend.common", +Export-Package: org.eclipse.xtend.backend;uses:="org.eclipse.xtend.backend.common", org.eclipse.xtend.backend.aop, org.eclipse.xtend.backend.aop.internal;x-internal:=true, org.eclipse.xtend.backend.common, @@ -22,11 +19,14 @@ Export-Package: org.eclipose.xtend.middleend, org.eclipse.xtend.backend.types.emf.internal;x-internal:=true, org.eclipse.xtend.backend.types.java.internal;x-internal:=true, org.eclipse.xtend.backend.util, - org.eclipse.xtend.middleend.javaannotations + org.eclipse.xtend.middleend, + org.eclipse.xtend.middleend.internal;x-internal:=true, + org.eclipse.xtend.middleend.javaannotations, + org.eclipse.xtend.middleend.plugins Require-Bundle: org.apache.commons.logging, org.eclipse.emf.ecore, org.eclipse.osgi, org.eclipse.equinox.registry, org.eclipse.emf.mwe.core Eclipse-LazyStart: true -Bundle-Activator: org.eclipose.xtend.middleend.internal.Activator +Bundle-Activator: org.eclipse.xtend.middleend.internal.Activator diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEnd.java b/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEnd.java deleted file mode 100644 index 176c2d08..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEnd.java +++ /dev/null @@ -1,139 +0,0 @@ -/* -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.eclipose.xtend.middleend; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; -import org.eclipse.xtend.backend.BackendFacade; -import org.eclipse.xtend.backend.aop.AroundAdvice; -import org.eclipse.xtend.backend.common.BackendTypesystem; -import org.eclipse.xtend.backend.common.ExecutionContext; -import org.eclipse.xtend.backend.common.FunctionDefContext; -import org.eclipse.xtend.backend.common.NamedFunction; -import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; -import org.eclipse.xtend.backend.functions.internal.FunctionDefContextImpl; -import org.eclipse.xtend.backend.syslib.SyslibContributor; -import org.eclipse.xtend.middleend.javaannotations.JavaFunctionClassContributor; - - -/** - * This class is the generic entry point for parsing and executing code. Different - * languages can contribute their specific middle ends using extension points.
- * - * MiddleEnd instances are stateful in that they preserve caching of the contributed - * middle ends. They also preserve a single ExecutionContext instance throughout their - * life span, but they expose it to allows using code to selectively manipulate and / or - * re-initialize it between invocations. - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -public final class MiddleEnd { - private static final Log _log = LogFactory.getLog (MiddleEnd.class); - - private final List _languageHandlers; - private final ExecutionContext _ctx; - private final BackendTypesystem _ts; - - /** - * this flag marks the temporary state while the syslib is added to a newly created fdc. During - * this phase, newly created fdcs are returned *without* registering the syslib to avoid endless - * recursion. - */ - private boolean _isInitializingSyslib = false; - - /** - * The map with "specific params" is used to initialize the contributed middle ends. - * The key must be the class implementing the LanguageSpecificMiddleEnd interface - * and contributed via the extension point. - */ - public MiddleEnd (BackendTypesystem ts, List languageHandlers) { - if (languageHandlers == null) - languageHandlers = new ArrayList (); - - // this is a "built-in" handler that is, among other things, necessary for the syslib - languageHandlers.add (new JavaFunctionClassContributor ()); - - _ts = ts; - _languageHandlers = languageHandlers; - - for (LanguageSpecificMiddleEnd handler: languageHandlers) - handler.setMiddleEnd (this); - - // it is important that the middle end is properly initialized before an fdc is created because - // syslib registration relies on an initialized middle end. - _ctx = BackendFacade.createExecutionContext (createEmptyFdc(), ts, false); - } - - private LanguageSpecificMiddleEnd findHandler (String resourceName) { - for (LanguageSpecificMiddleEnd candidate: _languageHandlers) { - if (candidate.canHandle (resourceName)) { - _log.debug ("middle end " + candidate.getName() + " handles resource " + resourceName); - return candidate; - } - } - - _log.warn ("no middle end for resource " + resourceName); - throw new IllegalArgumentException ("no middle end for resource " + resourceName); - } - - /** - * tells this middle end instance to apply the advice in a given resource to all - * subsequent invocations. - */ - public void applyAdvice (String resourceName) { - for (AroundAdvice advice: findHandler(resourceName).getContributedAdvice(resourceName)) - _ctx.setAdviceContext (_ctx.getAdviceContext().copyWithAdvice (advice)); - } - - public FunctionDefContext getFunctions (String resourceName) { - return findHandler (resourceName).getContributedFunctions (resourceName); - } - - - /** - * This method exposes the execution context to using code with the explicit purpose of allowing others to - * inspect and manipulate / re-initialize it partially or in toto.
- * - * But beware: This data structure is used directly by the runtime, and modifications can significantly - * influence behavior at runtime! - */ - public ExecutionContext getExecutionContext () { - return _ctx; - } - - public BackendTypesystem getTypesystem () { - return _ts; - } - - public FunctionDefContextInternal createEmptyFdc () { - final FunctionDefContextInternal result = new FunctionDefContextImpl (); - - if (_isInitializingSyslib) - return result; - - _isInitializingSyslib = true; - - try { - for (String resourceName: SyslibContributor.getSysLibResources()) - for (NamedFunction f: getFunctions(resourceName).getPublicFunctions()) - result.register (f, true); - - return result; - } - finally { - _isInitializingSyslib = false; - } - } -} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEndFactory.java b/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEndFactory.java deleted file mode 100644 index b2679eff..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/MiddleEndFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* -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.eclipose.xtend.middleend; - -import java.util.List; -import java.util.Map; - -import org.eclipose.xtend.middleend.internal.Activator; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; -import org.eclipse.xtend.backend.common.BackendTypesystem; - - -/** - * This class encapsulates the OSGi / Eclipse extension registry specific behavior and - * initialization code. It serves as an optional wrapper / convenience initialization - * code for the actual MiddleEnd class. - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -public final class MiddleEndFactory { - /** - * This method creates a MiddleEnd instance based on an explicitly provided list of handlers. It works without - * OSGi. - */ - public static MiddleEnd create (BackendTypesystem ts, List languageHandlers) { - return new MiddleEnd (ts, languageHandlers); - } - - /** - * This method creates a middle end based on the handlers registered with the extension point. It relies - * on OSGi and makes use of the Eclipse extension registry.
- * - * The map with "specific params" is used to initialize the contributed middle ends. - * The key must be the class implementing the LanguageSpecificMiddleEnd interface - * and contributed via the extension point. - */ - public static MiddleEnd create (BackendTypesystem ts, Map, Object> specificParams) { - return new MiddleEnd (ts, Activator.getInstance().getFreshMiddleEnds (specificParams)); - } -} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/internal/Activator.java b/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/internal/Activator.java deleted file mode 100644 index bad81b2f..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/internal/Activator.java +++ /dev/null @@ -1,105 +0,0 @@ -/* -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.eclipose.xtend.middleend.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEndFactory; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.RegistryFactory; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - - -/** - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -public class Activator implements BundleActivator { - private static final Log _log = LogFactory.getLog (Activator.class); - - private static Activator _instance = null; - - public static Activator getInstance () { - return _instance; - } - - private final List _middleEndContributions = new ArrayList (); - private boolean _isInitialized = false; - - - public List getFreshMiddleEnds (Map, Object> specificParams) { - init (); - - final List result = new ArrayList(); - - for (LanguageSpecificMiddleEndFactory factory: _middleEndContributions) { - try { - result.add (factory.create (specificParams.get (factory.getClass()))); - } - catch (IllegalArgumentException exc) { - // this is the official way for an implementation to withdraw from the pool for this call - _log.debug ("middle end implementation " + factory.getName() + " says it is not available: " + exc.getMessage()); - } - } - - return result; - } - - public void start (BundleContext context) throws Exception { - //TODO Bernd: implement error handling and logging to be both robust and independent of Eclipse - - _isInitialized = false; - _instance = this; - } - - private void init () { - if (_isInitialized) - return; - - _isInitialized = true; - _middleEndContributions.clear (); - - try { - final IConfigurationElement[] confEl = RegistryFactory.getRegistry().getConfigurationElementsFor ("org.eclipse.xtend.backend.MiddleEnd"); - - for (IConfigurationElement curEl: confEl) { - final Object o = curEl.createExecutableExtension ("class"); - _middleEndContributions.add ((LanguageSpecificMiddleEndFactory) o); - } - } - catch (Exception exc) { - exc.printStackTrace (); - } - - Collections.sort (_middleEndContributions, new Comparator () { - public int compare (LanguageSpecificMiddleEndFactory o1, LanguageSpecificMiddleEndFactory o2) { - return o1.getPriority() - o2.getPriority(); - } - }); - - _log.info ("Activating Eclipse Modeling Middle End - the following middle ends are registered:"); - for (LanguageSpecificMiddleEndFactory factory: _middleEndContributions) - _log.info (" " + factory.getName()); - } - - public void stop (BundleContext context) throws Exception { - _instance = null; - _middleEndContributions.clear(); - } -} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java b/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java deleted file mode 100644 index 351cd174..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java +++ /dev/null @@ -1,58 +0,0 @@ -/* -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.eclipose.xtend.middleend.plugins; - -import java.util.List; - -import org.eclipose.xtend.middleend.MiddleEnd; -import org.eclipse.xtend.backend.aop.AroundAdvice; -import org.eclipse.xtend.backend.common.FunctionDefContext; - - -/** - * This interface is the common abstraction through which all handlers for different - * languages can contribute their middle ends. - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -public interface LanguageSpecificMiddleEnd { - /** - * This method is used to break the circular dependency between MiddleEnd and the - * language specific handlers. It is called by the MiddleEnd on creation. - */ - void setMiddleEnd (MiddleEnd middleEnd); - - String getName (); - - /** - * gives the middle end a way to declare if it can and wants to handle a given - * source file / resource. If and only if it returns true, it will be asked for - * the functions and advice provided in this resource. - */ - boolean canHandle (String resourceName); - - /** - * This method asks the middle end to parse a resource for which it declared - * that it is the appropriate handler, and return the functions contained therein.
- * - * Implementations are encouraged to perform aggressive caching. The calling code - * takes care of re-initializing the middle end implementations as it deems fit by - * creating new instances of the contributed middle end implementation classes. - */ - FunctionDefContext getContributedFunctions (String resourceName); - - /** - * This method is the same as getContributedFunctions, except that it returns advice - * rather than functions. Since the semantics of advice depends on the order in which - * it is applied, this method returns a list rather than an arbitrary collection. - */ - List getContributedAdvice (String resourceName); -} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java b/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java deleted file mode 100644 index feb69150..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipose/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/* -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.eclipose.xtend.middleend.plugins; - - -/** - * This interface is the common abstraction through which all handlers for different - * languages can contribute their middle ends. Every language should contribute its - * MiddleEnd implementation factory through the extension point. - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -public interface LanguageSpecificMiddleEndFactory { - /** - * a clear text name describing the language / middle end - */ - String getName (); - - /** - * the priority is a possible way to determine the order in which the middle ends - * are asked if they can handle a given resource. Typically, only one middle end - * implementation should declare that it can handle a given resource (i.e. source - * file), and in this case a priority of 0 should be returned.
- * - * In the rare case where it is needed, highest priority is asked first. - */ - int getPriority (); - - /** - * This method creates the actual implementation of the middle end. The specificData parameter is - * passed through from the MiddleEnd constructor.
- * - * It is permitted for implementations to throw an IllegalArgumentException, - * which is the official way for an implementation to say that it views the - * passed data as insufficient to perform, and therefore needs to be removed - * from the list of registered middle ends. This is done on a per-call basis - * and avoids the necessity to always initialize all middle end implementations. - */ - LanguageSpecificMiddleEnd create (Object specificData); -} 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 index dff82bb0..5fee28bb 100644 --- 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 @@ -23,7 +23,7 @@ import org.eclipse.xtend.backend.common.SyntaxConstants; public final class AroundAdvice { private final ExpressionBase _body; private final Pointcut _pointcut; - private final FunctionDefContext _fdc; + private FunctionDefContext _fdc; private final boolean _isCacheable; @@ -35,11 +35,10 @@ public final class AroundAdvice { * 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, FunctionDefContext fdc) { + public AroundAdvice (ExpressionBase body, Pointcut pointcut, boolean isCacheable) { _body = body; _pointcut = pointcut; _isCacheable = isCacheable; - _fdc = fdc; } /** @@ -65,6 +64,10 @@ public final class AroundAdvice { } } + public void setFunctionDefContext (FunctionDefContext fdc) { + _fdc = fdc; + } + public Pointcut getPointcut () { return _pointcut; } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/Function.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/Function.java index 676cd8a1..60be6f59 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/Function.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/Function.java @@ -14,7 +14,6 @@ import java.util.List; /** - * * @author Arno Haase (http://www.haase-consulting.com) */ public interface Function { @@ -28,4 +27,7 @@ public interface Function { /** returns the expression that guards this function - or null, if there is no guard.*/ ExpressionBase getGuard(); + + FunctionDefContext getFunctionDefContext (); + void setFunctionDefContext (FunctionDefContext fdc); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/CurriedFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/CurriedFunction.java index cd1ec273..967fda8c 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/CurriedFunction.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/CurriedFunction.java @@ -17,6 +17,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.ExpressionBase; import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.common.FunctionDefContext; /** @@ -71,4 +72,12 @@ final class CurriedFunction implements Function { public boolean isCached () { return false; } + + public FunctionDefContext getFunctionDefContext () { + return _inner.getFunctionDefContext(); + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/HidingLocalVarDefExpression.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/HidingLocalVarDefExpression.java index 964bf7c2..1e6d96c6 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/HidingLocalVarDefExpression.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/HidingLocalVarDefExpression.java @@ -16,6 +16,9 @@ import org.eclipse.xtend.backend.common.SourcePos; import org.eclipse.xtend.backend.common.StacktraceEntry; +//TODO refactor: middle ends only use this, and a subsequent step differentiates / optimizes to NewLocalVarExpression + + /** * * @author Arno Haase (http://www.haase-consulting.com) diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/InvocationOnWhateverExpression.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/InvocationOnWhateverExpression.java index 406d99e5..817b807e 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/InvocationOnWhateverExpression.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/InvocationOnWhateverExpression.java @@ -20,6 +20,9 @@ import org.eclipse.xtend.backend.common.SourcePos; import org.eclipse.xtend.backend.syslib.CollectionOperations; +//TODO refactor: middle ends only use this, and a subsequent step differentiates / optimizes to the other two + + /** * This expression invokes a function on the first argument, deciding at runtime whether to do the "collection magic" of * invoking the function on every member of the collection that is the first argument and returning the collection of diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/PropertyOnWhateverExpression.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/PropertyOnWhateverExpression.java index 5163e28c..b4f55fe0 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/PropertyOnWhateverExpression.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/PropertyOnWhateverExpression.java @@ -20,6 +20,9 @@ import org.eclipse.xtend.backend.syslib.CollectionOperations; import org.eclipse.xtend.backend.types.builtin.CollectionType; +//TODO refactor: middle ends only use this, and a subsequent step differentiates / optimizes to the other two + + /** * This class deals with the case where the middle end can not decide statically whether * a property is to be resolved on a single object or on a collection diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/AbstractFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/AbstractFunction.java new file mode 100644 index 00000000..f90b212d --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/AbstractFunction.java @@ -0,0 +1,50 @@ +package org.eclipse.xtend.backend.functions; + +import java.util.List; + +import org.eclipse.xtend.backend.common.BackendType; +import org.eclipse.xtend.backend.common.ExpressionBase; +import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.common.FunctionDefContext; + + +/** + * This convenience implementation provides default implementations for many of the + * Function methods. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public abstract class AbstractFunction implements Function { + private final ExpressionBase _guard; + private final List _parameterTypes; + private final boolean _cached; + + private FunctionDefContext _fdc; + + + public AbstractFunction (ExpressionBase guard, List parameterTypes, boolean cached) { + _guard = guard; + _parameterTypes = parameterTypes; + _cached = cached; + } + + public ExpressionBase getGuard () { + return _guard; + } + + public List getParameterTypes () { + return _parameterTypes; + } + + public boolean isCached () { + return _cached; + } + + public FunctionDefContext getFunctionDefContext () { + return _fdc; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + _fdc = fdc; + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/SourceDefinedFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/SourceDefinedFunction.java index ace0b564..5634018f 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/SourceDefinedFunction.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/SourceDefinedFunction.java @@ -15,8 +15,6 @@ import java.util.List; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; 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.LocalVarContext; import org.eclipse.xtend.backend.common.StacktraceEntry; @@ -25,53 +23,19 @@ import org.eclipse.xtend.backend.common.StacktraceEntry; * * @author Arno Haase (http://www.haase-consulting.com) */ -public final class SourceDefinedFunction implements Function { +public final class SourceDefinedFunction extends AbstractFunction { private final String _name; private final List _paramNames; - private final List _paramTypes; - private final FunctionDefContext _defContext; private final ExpressionBase _def; - private final boolean _cached; - private final ExpressionBase _guard; - public SourceDefinedFunction (String name, List paramNames, List paramTypes, FunctionDefContext defContext, ExpressionBase def, boolean cached, ExpressionBase guard) { + public SourceDefinedFunction (String name, List paramNames, List paramTypes, ExpressionBase def, boolean cached, ExpressionBase guard) { + super (guard, paramTypes, cached); _name = name; _paramNames = paramNames; - _paramTypes = paramTypes; - _defContext = defContext; _def = def; - _cached = cached; - _guard = guard; } - public boolean isCached () { - return _cached; - } - - public List getParameterTypes() { - return _paramTypes; - } - - public FunctionDefContext getFunctionDefContext () { - return _defContext; - } - public Object invoke (ExecutionContext ctx, Object[] params) { - if (_defContext == ctx.getFunctionDefContext()) - return invokeWithExistingFdc (ctx, params); - else { - final FunctionDefContext oldFdc = ctx.getFunctionDefContext (); - try { - ctx.setFunctionDefContext (_defContext); - return invokeWithExistingFdc(ctx, params); - } - finally { - ctx.setFunctionDefContext (oldFdc); - } - } - } - - private Object invokeWithExistingFdc (ExecutionContext ctx, Object[] params) { final LocalVarContext lvc = new LocalVarContext (); for (int i=0; i<_paramNames.size(); i++) { lvc.getLocalVars().put(_paramNames.get(i), params[i]); @@ -94,13 +58,9 @@ public final class SourceDefinedFunction implements Function { } } - public ExpressionBase getGuard() { - return _guard; - } - @Override public String toString () { - return "SourceDefinedFunction '" + _name + "' " + _paramTypes; + return "SourceDefinedFunction '" + _name + "' " + getParameterTypes(); } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/Closure.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/Closure.java index 82a56a04..8b47c956 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/Closure.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/Closure.java @@ -15,47 +15,34 @@ import java.util.List; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; 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.LocalVarContext; +import org.eclipse.xtend.backend.functions.AbstractFunction; /** * * @author Arno Haase (http://www.haase-consulting.com) */ -public final class Closure implements Function { +public final class Closure extends AbstractFunction { private final LocalVarContext _lvcAtDefinitionTime; private final FunctionDefContext _fdcAtDefinitionTime; private final List _paramNames; - private final List _paramTypes; private final ExpressionBase _def; public Closure (LocalVarContext lvcAtDefinitionTime, FunctionDefContext fdcAtDefinitionTime, List paramNames, List paramTypes, ExpressionBase def) { + super (null, paramTypes, false); + //freeze local variables at definition time so they will be available in a different context at evaluation time _lvcAtDefinitionTime = new LocalVarContext(); _lvcAtDefinitionTime.getLocalVars().putAll (lvcAtDefinitionTime.getLocalVars()); _fdcAtDefinitionTime = fdcAtDefinitionTime; _paramNames = paramNames; - _paramTypes = paramTypes; _def = def; } - - public String getName () { - return ""; - } - - public boolean isCached () { - return false; - } - - public List getParameterTypes() { - return _paramTypes; - } - public Object invoke (ExecutionContext ctx, Object[] params) { if (_fdcAtDefinitionTime == ctx.getFunctionDefContext()) return invokeWithExistingFdc (ctx, params); @@ -87,8 +74,14 @@ public final class Closure implements Function { ctx.setLocalVarContext(oldLvc); } } - - public ExpressionBase getGuard() { - return null; - } + + @Override + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } + + @Override + public FunctionDefContext getFunctionDefContext () { + return _fdcAtDefinitionTime; + } } 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 ea01bcb5..e159dffc 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 @@ -114,7 +114,6 @@ public final class FunctionDefContextImpl implements FunctionDefContextInternal } return ctx.getAdviceContext().getAdvice (functionName, f).evaluate(ctx, params); -// return ctx.getFunctionInvoker().invoke (ctx, f, params); } /** 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 4a934c1b..37dde12d 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 @@ -15,6 +15,7 @@ import java.util.List; import org.eclipse.xtend.backend.common.EfficientLazyString; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.FunctionInvoker; import org.eclipse.xtend.backend.util.DoubleKeyCache; @@ -27,7 +28,7 @@ public final class FunctionInvokerImpl implements FunctionInvoker { private final DoubleKeyCache , Object> _cache = new DoubleKeyCache, Object> () { @Override protected Object create (Function f, List params) { - final Object result = f.invoke (_ctx, params.toArray()); + final Object result = invoke (f, _ctx, params); if (result instanceof EfficientLazyString) ((EfficientLazyString) result).makeImmutable(); @@ -37,14 +38,27 @@ public final class FunctionInvokerImpl implements FunctionInvoker { }; private ExecutionContext _ctx; + + private Object invoke (Function f, ExecutionContext ctx, List params) { + //TODO optimize for the case when the fdc is == the existing fdc + + final FunctionDefContext oldFdc = ctx.getFunctionDefContext(); + ctx.setFunctionDefContext (f.getFunctionDefContext()); + try { + return f.invoke(ctx, params.toArray()); + } + finally { + ctx.setFunctionDefContext (oldFdc); + } + } public Object invoke (ExecutionContext ctx, Function f, List params) { if (f.isCached()) { _ctx = ctx; - return _cache.get(f, params); + return _cache.get (f, params); } else { - return f.invoke(ctx, params.toArray()); + return invoke (f, ctx, params); } } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/CollectionOperations.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/CollectionOperations.java index 9f3ca6af..a9d32fa8 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/CollectionOperations.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/CollectionOperations.java @@ -24,7 +24,7 @@ import org.eclipse.xtend.backend.common.EfficientLazyString; import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.Helpers; import org.eclipse.xtend.middleend.javaannotations.AbstractExecutionContextAware; -import org.eclipse.xtend.middleend.javaannotations.M2tHidden; +import org.eclipse.xtend.middleend.javaannotations.M2tNoFunction; /** @@ -350,7 +350,7 @@ public final class CollectionOperations extends AbstractExecutionContextAware { // helpers /////////////////////////////////// - @M2tHidden + @M2tNoFunction public static void addFlattened (Collection coll, Object newEl) { if (newEl instanceof Collection) coll.addAll ((Collection) newEl); @@ -358,7 +358,7 @@ public final class CollectionOperations extends AbstractExecutionContextAware { coll.add (newEl); } - @M2tHidden + @M2tNoFunction public static Collection createMatchingCollection (Collection coll) { if (coll instanceof List) return new ArrayList(); diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/StringOperations.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/StringOperations.java index fba728e5..bdc5e1ed 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/StringOperations.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/syslib/StringOperations.java @@ -17,7 +17,7 @@ import org.eclipse.xtend.backend.common.EfficientLazyString; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.Helpers; import org.eclipse.xtend.middleend.javaannotations.AbstractExecutionContextAware; -import org.eclipse.xtend.middleend.javaannotations.M2tHidden; +import org.eclipse.xtend.middleend.javaannotations.M2tNoFunction; /** @@ -220,7 +220,7 @@ public final class StringOperations extends AbstractExecutionContextAware { * This method is however not itself intended to be published as an extension. It is a helper function, intended to * be used by other extensions. */ - @M2tHidden + @M2tNoFunction public static CharSequence overridableToString (ExecutionContext ctx, Object o) { return Helpers.overridableToString (ctx, o); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java index c8e5016c..b32e3cae 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java @@ -23,6 +23,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; 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.Property; import org.eclipse.xtend.backend.common.StaticProperty; @@ -175,6 +176,14 @@ public abstract class AbstractType implements BackendType { public boolean isCached () { return false; } + + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } } private class GetterOperation implements Function { @@ -201,6 +210,14 @@ public abstract class AbstractType implements BackendType { public boolean isCached () { return false; } + + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java index acb4c4a1..97789385 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java @@ -17,6 +17,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; 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.types.AbstractType; @@ -46,6 +47,14 @@ public final class FunctionType extends AbstractType { public ExpressionBase getGuard() { return null; } + + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } }); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java index 8a64e5f3..1eb2f0b3 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java @@ -18,6 +18,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; 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.types.AbstractProperty; import org.eclipse.xtend.backend.types.AbstractType; import org.eclipse.xtend.backend.util.ReflectionHelper; @@ -71,6 +72,14 @@ public final class TypeType extends AbstractType { public boolean isCached () { return false; } + + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } }); } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java index 605134c8..f64266a5 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java @@ -26,6 +26,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; 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.types.AbstractProperty; import org.eclipse.xtend.backend.types.AbstractType; import org.eclipse.xtend.backend.types.emf.EmfTypesystem; @@ -121,6 +122,14 @@ public final class EClassType extends AbstractType { return false; } + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } + }); } catch (Exception e) { ErrorHandler.handle (e); diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaOperation.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaOperation.java index 158fe7c1..88fba43b 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaOperation.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaOperation.java @@ -20,7 +20,7 @@ import org.apache.commons.logging.LogFactory; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.ExpressionBase; -import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.functions.AbstractFunction; import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverter; import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverterFactory; import org.eclipse.xtend.backend.functions.java.internal.ParameterConverter; @@ -36,20 +36,18 @@ import org.eclipse.xtend.backend.util.StringHelper; * * @author Arno Haase (http://www.haase-consulting.com) */ -public final class JavaOperation implements Function { +public final class JavaOperation extends AbstractFunction { private final Log _log = LogFactory.getLog(getClass()); private final Method _mtd; - private final List _parameterTypes; - private final ExpressionBase _guard; private final List _parameterConverters = new ArrayList(); private final JavaBuiltinConverter _returnValueConverter; public JavaOperation (Method mtd, List parameterTypes, ExpressionBase guard) { + super (guard, parameterTypes, false); + _mtd = mtd; - _parameterTypes = parameterTypes; - _guard = guard; for (int i=0; i getParameterTypes() { - return _parameterTypes; - } - public Object invoke (ExecutionContext ctx, Object[] params) { for (ParameterConverter pc: _parameterConverters) pc.convert(params); @@ -95,10 +85,6 @@ public final class JavaOperation implements Function { return null; // just for the compiler - this is never executed } } - - public ExpressionBase getGuard () { - return _guard; - } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEnd.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEnd.java new file mode 100644 index 00000000..989ed496 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEnd.java @@ -0,0 +1,51 @@ +/* +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.middleend; + +import org.eclipse.xtend.backend.common.BackendTypesystem; +import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.FunctionDefContext; +import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; + + +/** + * This interface is the generic entry point for parsing and executing code. Different + * languages can contribute their specific middle ends using extension points.
+ * + * MiddleEnd instances are stateful in that they preserve caching of the contributed + * middle ends. They also preserve a single ExecutionContext instance throughout their + * life span, but they expose it to allows using code to selectively manipulate and / or + * re-initialize it between invocations. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public interface MiddleEnd { + /** + * tells this middle end instance to apply the advice in a given resource to all + * subsequent invocations. + */ + void applyAdvice (String resourceName); + + FunctionDefContext getFunctions (String resourceName); + + /** + * This method exposes the execution context to using code with the explicit purpose of allowing others to + * inspect and manipulate / re-initialize it partially or in toto.
+ * + * But beware: This data structure is used directly by the runtime, and modifications can significantly + * influence behavior at runtime! + */ + ExecutionContext getExecutionContext (); + + BackendTypesystem getTypesystem (); + + FunctionDefContextInternal createEmptyFdc (); +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEndFactory.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEndFactory.java new file mode 100644 index 00000000..6321bb2a --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEndFactory.java @@ -0,0 +1,49 @@ +/* +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.middleend; + +import java.util.List; +import java.util.Map; + +import org.eclipse.xtend.backend.common.BackendTypesystem; +import org.eclipse.xtend.middleend.internal.Activator; +import org.eclipse.xtend.middleend.internal.MiddleEndImpl; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; + + +/** + * This class encapsulates the OSGi / Eclipse extension registry specific behavior and + * initialization code. It serves as an optional wrapper / convenience initialization + * code for the actual MiddleEnd class. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class MiddleEndFactory { + /** + * This method creates a MiddleEnd instance based on an explicitly provided list of handlers. It works without + * OSGi. + */ + public static MiddleEnd create (BackendTypesystem ts, List languageHandlers) { + return new MiddleEndImpl (ts, languageHandlers); + } + + /** + * This method creates a middle end based on the handlers registered with the extension point. It relies + * on OSGi and makes use of the Eclipse extension registry.
+ * + * The map with "specific params" is used to initialize the contributed middle ends. + * The key must be the class implementing the LanguageSpecificMiddleEnd interface + * and contributed via the extension point. + */ + public static MiddleEnd createFromExtensions (BackendTypesystem ts, Map, Object> specificParams) { + return new MiddleEndImpl (ts, Activator.getInstance().getFreshMiddleEnds (specificParams)); + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/Activator.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/Activator.java new file mode 100644 index 00000000..ada8778e --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/Activator.java @@ -0,0 +1,105 @@ +/* +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.middleend.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.RegistryFactory; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEndFactory; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + + +/** + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public class Activator implements BundleActivator { + private static final Log _log = LogFactory.getLog (Activator.class); + + private static Activator _instance = null; + + public static Activator getInstance () { + return _instance; + } + + private final List _middleEndContributions = new ArrayList (); + private boolean _isInitialized = false; + + + public List getFreshMiddleEnds (Map, Object> specificParams) { + init (); + + final List result = new ArrayList(); + + for (LanguageSpecificMiddleEndFactory factory: _middleEndContributions) { + try { + result.add (factory.create (specificParams.get (factory.getClass()))); + } + catch (IllegalArgumentException exc) { + // this is the official way for an implementation to withdraw from the pool for this call + _log.debug ("middle end implementation " + factory.getName() + " says it is not available: " + exc.getMessage()); + } + } + + return result; + } + + public void start (BundleContext context) throws Exception { + //TODO Bernd: implement error handling and logging to be both robust and independent of Eclipse + + _isInitialized = false; + _instance = this; + } + + private void init () { + if (_isInitialized) + return; + + _isInitialized = true; + _middleEndContributions.clear (); + + try { + final IConfigurationElement[] confEl = RegistryFactory.getRegistry().getConfigurationElementsFor ("org.eclipse.xtend.backend.MiddleEnd"); + + for (IConfigurationElement curEl: confEl) { + final Object o = curEl.createExecutableExtension ("class"); + _middleEndContributions.add ((LanguageSpecificMiddleEndFactory) o); + } + } + catch (Exception exc) { + exc.printStackTrace (); + } + + Collections.sort (_middleEndContributions, new Comparator () { + public int compare (LanguageSpecificMiddleEndFactory o1, LanguageSpecificMiddleEndFactory o2) { + return o1.getPriority() - o2.getPriority(); + } + }); + + _log.info ("Activating Eclipse Modeling Middle End - the following middle ends are registered:"); + for (LanguageSpecificMiddleEndFactory factory: _middleEndContributions) + _log.info (" " + factory.getName()); + } + + public void stop (BundleContext context) throws Exception { + _instance = null; + _middleEndContributions.clear(); + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/MiddleEndImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/MiddleEndImpl.java new file mode 100644 index 00000000..bdfe7d8d --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/MiddleEndImpl.java @@ -0,0 +1,223 @@ +/* +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.middleend.internal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.xtend.backend.BackendFacade; +import org.eclipse.xtend.backend.aop.AroundAdvice; +import org.eclipse.xtend.backend.common.BackendTypesystem; +import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.FunctionDefContext; +import org.eclipse.xtend.backend.common.NamedFunction; +import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; +import org.eclipse.xtend.backend.functions.internal.FunctionDefContextImpl; +import org.eclipse.xtend.backend.syslib.SyslibContributor; +import org.eclipse.xtend.middleend.MiddleEnd; +import org.eclipse.xtend.middleend.javaannotations.JavaFunctionClassContributor; +import org.eclipse.xtend.middleend.plugins.ImportedResource; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.ParsedResource; + + +/** + * This class is the generic entry point for parsing and executing code. Different + * languages can contribute their specific middle ends using extension points.
+ * + * MiddleEnd instances are stateful in that they preserve caching of the contributed + * middle ends. They also preserve a single ExecutionContext instance throughout their + * life span, but they expose it to allows using code to selectively manipulate and / or + * re-initialize it between invocations. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class MiddleEndImpl implements MiddleEnd { + private static final Log _log = LogFactory.getLog (MiddleEndImpl.class); + + private final Map _parsedResources = new HashMap (); + private final Map _fdcs = new HashMap (); + + private final List _languageHandlers; + private final ExecutionContext _ctx; + private final BackendTypesystem _ts; + + /** + * this flag marks the temporary state while the syslib is added to a newly created fdc. During + * this phase, newly created fdcs are returned *without* registering the syslib to avoid endless + * recursion. + */ + private boolean _isInitializingSyslib = false; + + /** + * The map with "specific params" is used to initialize the contributed middle ends. + * The key must be the class implementing the LanguageSpecificMiddleEnd interface + * and contributed via the extension point. + */ + public MiddleEndImpl (BackendTypesystem ts, List languageHandlers) { + if (languageHandlers == null) + languageHandlers = new ArrayList (); + + // this is a "built-in" handler that is, among other things, necessary for the syslib + languageHandlers.add (new JavaFunctionClassContributor ()); + + _ts = ts; + _languageHandlers = languageHandlers; + + for (LanguageSpecificMiddleEnd handler: languageHandlers) + handler.setMiddleEnd (this); + + // it is important that the middle end is properly initialized before an fdc is created because + // syslib registration relies on an initialized middle end. + _ctx = BackendFacade.createExecutionContext (createEmptyFdc(), ts, false); + } + + private LanguageSpecificMiddleEnd findHandler (String resourceName) { + for (LanguageSpecificMiddleEnd candidate: _languageHandlers) { + if (candidate.canHandle (resourceName)) { + _log.debug ("middle end " + candidate.getName() + " handles resource " + resourceName); + return candidate; + } + } + + _log.warn ("no middle end for resource " + resourceName); + throw new IllegalArgumentException ("no middle end for resource " + resourceName); + } + + private ParsedResource parseResource (String resourceName) { + if (_parsedResources.containsKey (resourceName)) + return _parsedResources.get (resourceName); + + final ParsedResource result = findHandler (resourceName).parseResource (resourceName); + _parsedResources.put (resourceName, result); + + final FunctionDefContext fdc = getFdc (resourceName); + for (NamedFunction f: result.getPrivateFunctions()) + f.getFunction().setFunctionDefContext (fdc); + for (NamedFunction f: result.getPublicFunctions()) + f.getFunction().setFunctionDefContext (fdc); + for (AroundAdvice advice: result.getAdvice()) + advice.setFunctionDefContext (fdc); + + return result; + } + + private FunctionDefContext getFdc (String resourceName) { + if (_fdcs.containsKey (resourceName)) + return _fdcs.get (resourceName); + + final FunctionDefContextInternal result = createEmptyFdc(); + _fdcs.put (resourceName, result); + + System.out.println ("*****" + resourceName); + final Set reexported = new HashSet (); + collectReexportedResources (reexported, new HashSet (), resourceName); + System.out.println ("/////" + resourceName); + + for (String importedReexp: reexported) + for (NamedFunction f: parseResource (importedReexp).getPublicFunctions()) + result.register (f, true); + + for (ImportedResource ir: parseResource (resourceName).getImports()) { + if (ir.isReexported()) + continue; + + for (NamedFunction f: parseResource (ir.getResourceName ()).getPublicFunctions ()) + result.register (f, false); + } + + for (NamedFunction f: parseResource (resourceName).getPrivateFunctions()) + result.register(f, false); + for (NamedFunction f: parseResource (resourceName).getPublicFunctions()) + result.register(f, true); + + _log.debug ("fdc for " + resourceName + ": "); + _log.debug (" reexported: " + reexported); + _log.debug (" public functions: " + result.getPublicFunctions()); + + return result; + } + + /** + * tells this middle end instance to apply the advice in a given resource to all + * subsequent invocations. + */ + public void applyAdvice (String resourceName) { + for (AroundAdvice advice: parseResource (resourceName).getAdvice()) + _ctx.setAdviceContext (_ctx.getAdviceContext().copyWithAdvice (advice)); + } + + public FunctionDefContext getFunctions (String resourceName) { + return getFdc (resourceName); + } + + private void collectReexportedResources (Set result, Set visited, String curResource) { + if (visited.contains (curResource)) + return; + visited.add (curResource); + + for (ImportedResource candidate: parseResource (curResource).getImports()) { + final String candidateName = candidate.getResourceName(); + + if (! candidate.isReexported()) + continue; + + if (visited.contains (candidateName)) + continue; + + result.add (candidateName); + collectReexportedResources (result, visited, candidateName); + } + } + + + /** + * This method exposes the execution context to using code with the explicit purpose of allowing others to + * inspect and manipulate / re-initialize it partially or in toto.
+ * + * But beware: This data structure is used directly by the runtime, and modifications can significantly + * influence behavior at runtime! + */ + public ExecutionContext getExecutionContext () { + return _ctx; + } + + public BackendTypesystem getTypesystem () { + return _ts; + } + + //TODO make this private? + public FunctionDefContextInternal createEmptyFdc () { + final FunctionDefContextInternal result = new FunctionDefContextImpl (); + + if (_isInitializingSyslib) + return result; + + _isInitializingSyslib = true; + + try { + for (String resourceName: SyslibContributor.getSysLibResources()) + for (NamedFunction f: getFunctions(resourceName).getPublicFunctions()) + result.register (f, true); + + return result; + } + finally { + _isInitializingSyslib = false; + } + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/AbstractExecutionContextAware.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/AbstractExecutionContextAware.java index 8ff34c55..872c24a4 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/AbstractExecutionContextAware.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/AbstractExecutionContextAware.java @@ -25,6 +25,8 @@ public abstract class AbstractExecutionContextAware implements ExecutionContextA _ctx = ctx; } + //TODO add "invoke" method - and rename this to AbstractJavaDefinedFunctions, with implementations for the import methods as well + protected ExecutionContext getExecutionContext () { return _ctx; } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaDefinedFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaDefinedFunction.java deleted file mode 100644 index 8c22e3f4..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaDefinedFunction.java +++ /dev/null @@ -1,200 +0,0 @@ -/* -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.middleend.javaannotations; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.xtend.backend.common.BackendType; -import org.eclipse.xtend.backend.common.BackendTypesystem; -import org.eclipse.xtend.backend.common.ExecutionContext; -import org.eclipse.xtend.backend.common.ExpressionBase; -import org.eclipse.xtend.backend.common.Function; -import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverter; -import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverterFactory; -import org.eclipse.xtend.backend.functions.java.internal.ParameterConverter; -import org.eclipse.xtend.backend.util.ErrorHandler; - - -/** - * This class represents a "helper" function that is defined in a Java class but for which the defining - * object is not an explicit parameter. It is used for "JAVA extension" style functions.
- * - * If it represents a non-static method, a single instance of the underlying class is shared by all methods - * of the class, and across all compilation units etc. from which they are referenced. This single instance - * is scoped with the ExecutionContext used. - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -public final class JavaDefinedFunction implements Function { - private final Method _mtd; - private final List _parameterTypes; - private final ExpressionBase _guard; - private final boolean _isStatic; - - private final List _parameterConverters = new ArrayList(); - private final JavaBuiltinConverter _returnValueConverter; - - - //TODO move this factory to JavaFunctionClassContributor - //TODO separate internal API - /** - * This is a convenience factory method that creates functions for all public methods for an entire class. - */ - public static List createForEntireClass (Class cls, BackendTypesystem ts) { - final List result = new ArrayList(); - - for (Method mtd: cls.getDeclaredMethods()) { - // register only public methods - if (! isPublic (mtd)) - continue; - - // do not register infrastructure methods inherited from ExecutionContextAware - if (ExecutionContextAware.class.isAssignableFrom (cls)) { - try { - ExecutionContextAware.class.getMethod (mtd.getName(), mtd.getParameterTypes()); - continue; - } - catch (NoSuchMethodException e) { - } - } - - if (mtd.getAnnotation (M2tHidden.class) != null) - continue; - - result.add (new JavaDefinedFunction (mtd, null, ts)); - } - return result; - } - - private static boolean isPublic (Method mtd) { - return (mtd.getModifiers() & Modifier.PUBLIC) != 0; - } - - - /** - * shortcut constructor that attempts to derive the parameter types from the method's signature - */ - public JavaDefinedFunction (Method mtd, ExpressionBase guard, BackendTypesystem ts) { - this (mtd, guessParameterTypes(mtd, ts), guard); - } - - - /** - * This constructor provides full control - */ - public JavaDefinedFunction (Method mtd, List parameterTypes, ExpressionBase guard) { - _mtd = mtd; - _parameterTypes = parameterTypes; - _guard = guard; - - for (int i=0; i guessParameterTypes (Method mtd, BackendTypesystem ts) { - final List result = new ArrayList(); - - for (Class cls: mtd.getParameterTypes()) - result.add (ts.findType (cls)); - - return result; - } - - public String getName () { - return _mtd.getName(); - } - - public boolean isCached () { - return false; - } - - public List getParameterTypes() { - return _parameterTypes; - } - - public Object invoke (ExecutionContext ctx, Object[] params) { - for (ParameterConverter pc: _parameterConverters) - pc.convert(params); - - Object o = getInstance (ctx); - if (o instanceof ExecutionContextAware) { - ((ExecutionContextAware) o).setExecutionContext (ctx); - } - - try { - final Object resultRaw = _mtd.invoke (o, params); - return _returnValueConverter.javaToBackend (resultRaw); - - } catch (Exception e) { - final List paramTypes = new ArrayList (); - for (Object p: params) { - if (p == null) - paramTypes.add (Void.TYPE.getName()); - else - paramTypes.add (p.getClass().getName()); - } - - ErrorHandler.handle ("could not invoke method " + _mtd + " with parameters " + Arrays.asList(params) + " of types " + paramTypes, e); - return null; // to make the compiler happy - this is never executed - } - } - - public ExpressionBase getGuard () { - return _guard; - } - - @Override - public String toString () { - return "JavaDefinedFunction '" + getName() + "' " + _parameterTypes; - } -} - - - - - - - - - - - - - diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java index 5e1aaa44..8c24dd56 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java @@ -10,17 +10,16 @@ Contributors: */ package org.eclipse.xtend.middleend.javaannotations; -import java.util.ArrayList; -import java.util.List; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; -import org.eclipose.xtend.middleend.MiddleEnd; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; import org.eclipse.emf.mwe.core.resources.ResourceLoader; import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory; -import org.eclipse.xtend.backend.aop.AroundAdvice; -import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.NamedFunction; -import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; +import org.eclipse.xtend.middleend.MiddleEnd; +import org.eclipse.xtend.middleend.javaannotations.internal.JavaDefinedFunction; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.ParsedResource; /** @@ -55,21 +54,54 @@ public final class JavaFunctionClassContributor implements LanguageSpecificMiddl } } - public List getContributedAdvice (String resourceName) { - return new ArrayList (); //TODO add support for advice - } - - public FunctionDefContext getContributedFunctions (String resourceName) { - final FunctionDefContextInternal result = _middleEnd.createEmptyFdc(); + public ParsedResource parseResource (String resourceName) { + final ParsedResource result = new ParsedResource (); - //TODO add support for imported resources + //TODO imports + //TODO advice + //TODO guards + + final Class cls = getCls (resourceName); - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (getCls (resourceName), _middleEnd.getTypesystem())) - result.register (new NamedFunction (f.getName(), f), true); //TODO add support for non-public functions + for (Method mtd: cls.getDeclaredMethods()) { + // register only public methods + if (! isPublic (mtd)) + continue; + + if(isInfrastructureMethod (mtd, cls)) + continue; + + if (mtd.getAnnotation (M2tNoFunction.class) != null) + continue; + + final boolean isPublicFunction = (mtd.getAnnotation (M2tPrivateFunction.class) == null); + final NamedFunction f = new NamedFunction (mtd.getName(), new JavaDefinedFunction (mtd, null, _middleEnd.getTypesystem())); + + if (isPublicFunction) + result.getPublicFunctions().add (f); + else + result.getPrivateFunctions().add (f); + } return result; } + private boolean isPublic (Method mtd) { + return (mtd.getModifiers() & Modifier.PUBLIC) != 0; + } + + private boolean isInfrastructureMethod (Method mtd, Class cls) { + if (ExecutionContextAware.class.isAssignableFrom (cls)) { + try { + ExecutionContextAware.class.getMethod (mtd.getName(), mtd.getParameterTypes()); + return true; + } + catch (NoSuchMethodException e) { + } + } + return false; + } + public String getName () { return MIDDLE_END_NAME; } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tAroundAdvice.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tAroundAdvice.java new file mode 100644 index 00000000..2fce92ab --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tAroundAdvice.java @@ -0,0 +1,31 @@ +/* +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.middleend.javaannotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Methods marked with this annotation are treated as "around" advice + * rather than functions. They must take exactly two parameters of the + * types ThisJoinPointStaticPart and ThisJoinPoint, respectively. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +@Retention (RetentionPolicy.RUNTIME) +@Target (ElementType.METHOD) +public @interface M2tAroundAdvice { + //TODO add name matching pattern + //TODO add type parameters for the function params, including support for wildcard arguments +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tCached.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tCached.java new file mode 100644 index 00000000..17ff70a8 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tCached.java @@ -0,0 +1,27 @@ +/* +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.middleend.javaannotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Methods marked with this annotation will be cached + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +@Retention (RetentionPolicy.RUNTIME) +@Target (ElementType.METHOD) +public @interface M2tCached { +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tHidden.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tHidden.java deleted file mode 100644 index 8d377c17..00000000 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tHidden.java +++ /dev/null @@ -1,27 +0,0 @@ -/* -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.middleend.javaannotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -/** - * Methods marked with this annotation will not be registered as extensions if their class is registered - * - * @author Arno Haase (http://www.haase-consulting.com) - */ -@Retention (RetentionPolicy.RUNTIME) -@Target (ElementType.METHOD) -public @interface M2tHidden { -} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tNoFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tNoFunction.java new file mode 100644 index 00000000..613a4e65 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tNoFunction.java @@ -0,0 +1,27 @@ +/* +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.middleend.javaannotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Methods marked with this annotation will not be registered as extensions if their class is registered + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +@Retention (RetentionPolicy.RUNTIME) +@Target (ElementType.METHOD) +public @interface M2tNoFunction { +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tPrivateFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tPrivateFunction.java new file mode 100644 index 00000000..e906db5c --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tPrivateFunction.java @@ -0,0 +1,28 @@ +/* +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.middleend.javaannotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Methods marked with this annotation will be registered as private extensions, i.e. they will be visible for + * invocations from within the class but not from other resources + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +@Retention (RetentionPolicy.RUNTIME) +@Target (ElementType.METHOD) +public @interface M2tPrivateFunction { +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/internal/JavaDefinedFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/internal/JavaDefinedFunction.java new file mode 100644 index 00000000..8a67eb23 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/internal/JavaDefinedFunction.java @@ -0,0 +1,152 @@ +/* +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.middleend.javaannotations.internal; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.xtend.backend.common.BackendType; +import org.eclipse.xtend.backend.common.BackendTypesystem; +import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.ExpressionBase; +import org.eclipse.xtend.backend.functions.AbstractFunction; +import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverter; +import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverterFactory; +import org.eclipse.xtend.backend.functions.java.internal.ParameterConverter; +import org.eclipse.xtend.backend.util.ErrorHandler; +import org.eclipse.xtend.middleend.javaannotations.ExecutionContextAware; +import org.eclipse.xtend.middleend.javaannotations.M2tCached; + + +/** + * This class represents a "helper" function that is defined in a Java class but for which the defining + * object is not an explicit parameter. It is used for "JAVA extension" style functions.
+ * + * If it represents a non-static method, a single instance of the underlying class is shared by all methods + * of the class, and across all compilation units etc. from which they are referenced. This single instance + * is scoped with the ExecutionContext used. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class JavaDefinedFunction extends AbstractFunction { + private final Method _mtd; + private final boolean _isStatic; + + private final List _parameterConverters = new ArrayList(); + private final JavaBuiltinConverter _returnValueConverter; + + + /** + * shortcut constructor that attempts to derive the parameter types from the method's signature + */ + public JavaDefinedFunction (Method mtd, ExpressionBase guard, BackendTypesystem ts) { + this (mtd, guessParameterTypes (mtd, ts), guard); + } + + + /** + * This constructor provides full control + */ + public JavaDefinedFunction (Method mtd, List parameterTypes, ExpressionBase guard) { + super (guard, parameterTypes, mtd.getAnnotation (M2tCached.class) != null); + + _mtd = mtd; + + for (int i=0; i guessParameterTypes (Method mtd, BackendTypesystem ts) { + final List result = new ArrayList(); + + for (Class cls: mtd.getParameterTypes()) + result.add (ts.findType (cls)); + + return result; + } + + public String getName () { + return _mtd.getName(); + } + + public Object invoke (ExecutionContext ctx, Object[] params) { + for (ParameterConverter pc: _parameterConverters) + pc.convert(params); + + Object o = getInstance (ctx); + if (o instanceof ExecutionContextAware) { + ((ExecutionContextAware) o).setExecutionContext (ctx); + } + + try { + final Object resultRaw = _mtd.invoke (o, params); + return _returnValueConverter.javaToBackend (resultRaw); + + } catch (Exception e) { + final List paramTypes = new ArrayList (); + for (Object p: params) { + if (p == null) + paramTypes.add (Void.TYPE.getName()); + else + paramTypes.add (p.getClass().getName()); + } + + ErrorHandler.handle ("could not invoke method " + _mtd + " with parameters " + Arrays.asList(params) + " of types " + paramTypes, e); + return null; // to make the compiler happy - this is never executed + } + } + + @Override + public String toString () { + return "JavaDefinedFunction '" + getName() + "' " + getParameterTypes(); + } +} + + + + + + + + + + + + + diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ImportedResource.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ImportedResource.java new file mode 100644 index 00000000..bc7968b0 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ImportedResource.java @@ -0,0 +1,34 @@ +/* +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.middleend.plugins; + + +/** + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class ImportedResource { + private final String _resourceName; + private final boolean _isReexported; + + public ImportedResource (String resourceName, boolean isReexported) { + _resourceName = resourceName; + _isReexported = isReexported; + } + + public String getResourceName () { + return _resourceName; + } + + public boolean isReexported () { + return _isReexported; + } +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java new file mode 100644 index 00000000..5216b5c5 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java @@ -0,0 +1,46 @@ +/* +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.middleend.plugins; + +import org.eclipse.xtend.middleend.MiddleEnd; + + +/** + * This interface is the common abstraction through which all handlers for different + * languages can contribute their middle ends. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public interface LanguageSpecificMiddleEnd { + /** + * This method is used to break the circular dependency between MiddleEnd and the + * language specific handlers. It is called by the MiddleEnd on creation. + */ + void setMiddleEnd (MiddleEnd middleEnd); + + String getName (); + + /** + * gives the middle end a way to declare if it can and wants to handle a given + * source file / resource. If and only if it returns true, it will be asked for + * the functions and advice provided in this resource. + */ + boolean canHandle (String resourceName); + + /** + * This method asks the middle end to parse a resource for which it declared + * that it is the appropriate handler, and return the functions contained therein.
+ * + * Implementations are not required to perform any caching because the MiddleEnd + * implementation takes care of that. + */ + ParsedResource parseResource (String resourceName); +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java new file mode 100644 index 00000000..c5143859 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java @@ -0,0 +1,48 @@ +/* +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.middleend.plugins; + + +/** + * This interface is the common abstraction through which all handlers for different + * languages can contribute their middle ends. Every language should contribute its + * MiddleEnd implementation factory through the extension point. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public interface LanguageSpecificMiddleEndFactory { + /** + * a clear text name describing the language / middle end + */ + String getName (); + + /** + * the priority is a possible way to determine the order in which the middle ends + * are asked if they can handle a given resource. Typically, only one middle end + * implementation should declare that it can handle a given resource (i.e. source + * file), and in this case a priority of 0 should be returned.
+ * + * In the rare case where it is needed, highest priority is asked first. + */ + int getPriority (); + + /** + * This method creates the actual implementation of the middle end. The specificData parameter is + * passed through from the MiddleEnd constructor.
+ * + * It is permitted for implementations to throw an IllegalArgumentException, + * which is the official way for an implementation to say that it views the + * passed data as insufficient to perform, and therefore needs to be removed + * from the list of registered middle ends. This is done on a per-call basis + * and avoids the necessity to always initialize all middle end implementations. + */ + LanguageSpecificMiddleEnd create (Object specificData); +} diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ParsedResource.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ParsedResource.java new file mode 100644 index 00000000..29ece5f5 --- /dev/null +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ParsedResource.java @@ -0,0 +1,46 @@ +/* +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.middleend.plugins; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.xtend.backend.aop.AroundAdvice; +import org.eclipse.xtend.backend.common.NamedFunction; + + +/** + * This class represents all information about a resource that is relevant for the backend. + * + * @author Arno Haase (http://www.haase-consulting.com) + */ +public final class ParsedResource { + private final List _imports = new ArrayList (); + private final List _privateFunctions = new ArrayList (); + private final List _publicFunctions = new ArrayList (); + private final List _advice = new ArrayList (); + + public List getImports () { + return _imports; + } + + public List getPrivateFunctions () { + return _privateFunctions; + } + + public List getPublicFunctions () { + return _publicFunctions; + } + + public List getAdvice () { + return _advice; + } +} diff --git a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/OldXpandRegistry.java b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/OldXpandRegistry.java index 3d746be4..6726fd33 100644 --- a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/OldXpandRegistry.java +++ b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/OldXpandRegistry.java @@ -10,27 +10,21 @@ Contributors: */ package org.eclipse.xtend.middleend.xpand; -import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; -import org.eclipose.xtend.middleend.MiddleEnd; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; import org.eclipse.internal.xpand2.ast.Advice; import org.eclipse.internal.xpand2.ast.Template; import org.eclipse.internal.xpand2.model.XpandAdvice; import org.eclipse.internal.xpand2.model.XpandDefinition; import org.eclipse.xpand2.XpandExecutionContext; import org.eclipse.xpand2.XpandUtil; -import org.eclipse.xtend.backend.aop.AroundAdvice; import org.eclipse.xtend.backend.common.BackendTypesystem; -import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.NamedFunction; -import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; -import org.eclipse.xtend.backend.util.Cache; +import org.eclipse.xtend.middleend.MiddleEnd; +import org.eclipse.xtend.middleend.plugins.ImportedResource; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.ParsedResource; import org.eclipse.xtend.middleend.xpand.internal.OldDefinitionConverter; import org.eclipse.xtend.middleend.xpand.plugin.XpandDefinitionName; import org.eclipse.xtend.middleend.xtend.internal.OldHelper; @@ -48,24 +42,6 @@ public final class OldXpandRegistry implements LanguageSpecificMiddleEnd { private BackendTypesystem _ts; private MiddleEnd _middleEnd; - private final Cache _functionDefContexts = new Cache () { - @Override - protected FunctionDefContextInternal create (String compilationUnit) { - return _middleEnd.createEmptyFdc(); - } - }; - - /** - * all functions actually defined in a given compilation unit - */ - private final Map> _functionsByResource = new HashMap >(); - - private final Map> _adviceByResource = new HashMap > (); - - private FunctionDefContextInternal getFunctionDefContext (String xtendName) { - return _functionDefContexts.get (OldHelper.normalizeXtendResourceName (xtendName)); - } - public OldXpandRegistry (Object specificData) { if (specificData == null) @@ -79,15 +55,27 @@ public final class OldXpandRegistry implements LanguageSpecificMiddleEnd { _ts = middleEnd.getTypesystem(); } - - /** - * parses and converts an Xpand file and all other files it depends on. - */ - public void registerXpandFile (String xpandFile) { + public boolean canHandle (String xpandFile) { xpandFile = OldHelper.normalizeXpandResourceName (xpandFile); - if (_functionsByResource.containsKey (xpandFile)) - return; + final String xpandResourceName = OldHelper.xpandFileAsOldResourceName (xpandFile); + try { + final Template file = (Template) _ctx.getResourceManager().loadResource (xpandResourceName, XpandUtil.TEMPLATE_EXTENSION); + return file != null; + } + catch (Exception exc) { + return false; + } + } + + public String getName () { + return "Xpand"; + } + + public ParsedResource parseResource (String xpandFile) { + final ParsedResource result = new ParsedResource (); + + xpandFile = OldHelper.normalizeXpandResourceName (xpandFile); final String xpandResourceName = OldHelper.xpandFileAsOldResourceName (xpandFile); final Template file = (Template) _ctx.getResourceManager().loadResource (xpandResourceName, XpandUtil.TEMPLATE_EXTENSION); @@ -99,76 +87,48 @@ public final class OldXpandRegistry implements LanguageSpecificMiddleEnd { final TypeToBackendType typeConverter = new TypeToBackendType (_ts, ctx); final OldDefinitionConverter definitionFactory = new OldDefinitionConverter (ctx, typeConverter); - final List defined = new ArrayList(); - final FunctionDefContextInternal fdc = getFunctionDefContext (xpandFile); - // register the XtendLib. Do this first so the extension can override functions for (NamedFunction f: new XtendLibContributor (_middleEnd).getContributedFunctions()) - fdc.register (f, false); + result.getPrivateFunctions().add (f); final Set referenced = new HashSet (); for (XpandDefinition ext: file.getDefinitions ()) - defined.add (definitionFactory.create (ext, fdc, referenced)); + result.getPublicFunctions().add (definitionFactory.createUnregistered (ext, referenced)); - _functionsByResource.put (xpandFile, defined); - - final List newAdvice = new ArrayList(); - for (XpandAdvice a: file.getAdvices()) - newAdvice.add (definitionFactory.create ((Advice) a, referenced, fdc)); - _adviceByResource.put(xpandResourceName, newAdvice); + for (XpandAdvice a: file.getAdvices()) + result.getAdvice().add (definitionFactory.create ((Advice) a, referenced)); // make sure all imported resources are registered as well for (String imported: file.getImportedExtensions()) - for (NamedFunction f: _middleEnd.getFunctions (imported).getPublicFunctions()) - fdc.register (f, false); + result.getImports().add (new ImportedResource (imported, false)); // collect all referenced template files... final Set xpandFileNames = new HashSet (); for (XpandDefinitionName n: referenced) xpandFileNames.add (n.getCanonicalTemplateFileName()); - // ... and register all template definitions from these files. It is necessary to have them all registered to enable - // polymorphism - static type analysis does not find all potential matches. - for (String xpandFileName: xpandFileNames) - for (NamedFunction f: _middleEnd.getFunctions (xpandFileName).getPublicFunctions()) - fdc.register (f, false); + for (String importedXpand: xpandFileNames) + result.getImports().add (new ImportedResource (importedXpand, false)); + return result; } +} + + + + + + + - public FunctionDefContext getContributedFunctions (String xpandFile) { - registerXpandFile (xpandFile); - return getFunctionDefContext (xpandFile); - } - public boolean canHandle (String xpandFile) { - xpandFile = OldHelper.normalizeXpandResourceName (xpandFile); - - if (_functionsByResource.containsKey (xpandFile)) - return true; - final String xpandResourceName = OldHelper.xpandFileAsOldResourceName (xpandFile); - try { - final Template file = (Template) _ctx.getResourceManager().loadResource (xpandResourceName, XpandUtil.TEMPLATE_EXTENSION); - return file != null; - } - catch (Exception exc) { - return false; - } - } - public List getContributedAdvice (String resourceName) { - registerXpandFile (resourceName); - return _adviceByResource.get (OldHelper.normalizeXpandResourceName (resourceName)); - } - public String getName () { - return "Xpand"; - } -} diff --git a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/XpandBackendFacade.java b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/XpandBackendFacade.java index e0c7462a..a39aa5e7 100644 --- a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/XpandBackendFacade.java +++ b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/XpandBackendFacade.java @@ -12,8 +12,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.eclipose.xtend.middleend.MiddleEnd; -import org.eclipose.xtend.middleend.MiddleEndFactory; import org.eclipse.internal.xpand2.ast.Definition; import org.eclipse.internal.xpand2.ast.Statement; import org.eclipse.internal.xpand2.ast.Template; @@ -38,6 +36,8 @@ import org.eclipse.xtend.backend.syslib.InMemoryPostprocessor; import org.eclipse.xtend.backend.syslib.SysLibNames; import org.eclipse.xtend.backend.syslib.UriBasedPostprocessor; import org.eclipse.xtend.expression.Variable; +import org.eclipse.xtend.middleend.MiddleEnd; +import org.eclipse.xtend.middleend.MiddleEndFactory; import org.eclipse.xtend.middleend.xpand.internal.OldDefinitionConverter; import org.eclipse.xtend.middleend.xpand.internal.OldXpandRegistryFactory; import org.eclipse.xtend.middleend.xpand.plugin.XpandDefinitionName; @@ -271,7 +271,7 @@ public final class XpandBackendFacade { outlets = new ArrayList (); _xpandFile = OldHelper.normalizeXpandResourceName (xpandFilename); - _middleEnd = MiddleEndFactory.create (OldHelper.guessTypesystem (mms), createSpecificParameters (fileEncoding, mms, outlets)); + _middleEnd = MiddleEndFactory.createFromExtensions (OldHelper.guessTypesystem (mms), createSpecificParameters (fileEncoding, mms, outlets)); _fileEncoding = fileEncoding; _mms = mms; @@ -283,9 +283,6 @@ public final class XpandBackendFacade { } public FunctionDefContext getFunctionDefContext () { - if (_xpandFile == null) - return _middleEnd.createEmptyFdc(); - return _middleEnd.getFunctions (_xpandFile); } } diff --git a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldDefinitionConverter.java b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldDefinitionConverter.java index 1710e403..23500de3 100644 --- a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldDefinitionConverter.java +++ b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldDefinitionConverter.java @@ -40,7 +40,6 @@ import org.eclipse.xtend.backend.aop.AroundAdvice; import org.eclipse.xtend.backend.common.BackendType; 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.SourcePos; import org.eclipse.xtend.backend.common.SyntaxConstants; @@ -53,7 +52,6 @@ import org.eclipse.xtend.backend.expr.LiteralExpression; import org.eclipse.xtend.backend.expr.LocalVarEvalExpression; import org.eclipse.xtend.backend.expr.NewLocalVarDefExpression; import org.eclipse.xtend.backend.expr.SequenceExpression; -import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.backend.functions.SourceDefinedFunction; import org.eclipse.xtend.backend.syslib.FileIoOperations; import org.eclipse.xtend.backend.syslib.SysLibNames; @@ -92,7 +90,7 @@ public final class OldDefinitionConverter { } - public AroundAdvice create (Advice a, Set referencedDefinitions, FunctionDefContext fdc) { + public AroundAdvice create (Advice a, Set referencedDefinitions) { final XpandExecutionContext oldCtx = _ctx; try { @@ -106,33 +104,24 @@ public final class OldDefinitionConverter { _ctx = (XpandExecutionContext) _ctx.cloneWithVariable (new Variable (localVarNames.get(i), localVarTypes.get(i))); final ExpressionBase body = convertStatementSequence (a.getBody(), a, referencedDefinitions); - return exprConv.convertAdvice (body, a.getName(), Arrays.asList (a.getParams()), a.isWildcardParams(), fdc); + return exprConv.convertAdvice (body, a.getName(), Arrays.asList (a.getParams()), a.isWildcardParams()); } finally { _ctx = oldCtx; } } - /** - * converts an extension to a function, taking care of mutual registration with its fdc - */ - public NamedFunction create (XpandDefinition def, FunctionDefContextInternal fdc, Set referencedDefinitions) { - final NamedFunction result = createUnregistered (def, fdc, referencedDefinitions); - fdc.register (result, true); - return result; - } - - private NamedFunction createUnregistered (XpandDefinition def, FunctionDefContextInternal fdc, Set referencedDefinitions) { + public NamedFunction createUnregistered (XpandDefinition def, Set referencedDefinitions) { if (def instanceof Definition) { final String canonicalName = new XpandDefinitionName (def).getCanonicalDefinitionName(); - return new NamedFunction (canonicalName, createNormalDefinition ((Definition) def, fdc, referencedDefinitions)); + return new NamedFunction (canonicalName, createNormalDefinition ((Definition) def, referencedDefinitions)); } throw new IllegalArgumentException ("unsupported definition type " + def.getClass().getName()); } - private Function createNormalDefinition (Definition def, FunctionDefContext fdc, Set referencedDefinitions) { + private Function createNormalDefinition (Definition def, Set referencedDefinitions) { final XpandExecutionContext oldCtx = _ctx; try { @@ -151,7 +140,7 @@ public final class OldDefinitionConverter { paramTypes.add (_typeConverter.convertToBackendType (pt)); } - return new SourceDefinedFunction (def.getName(), paramNames, paramTypes, fdc, convertStatementSequence (def.getBody(), def, referencedDefinitions), false, null); + return new SourceDefinedFunction (def.getName(), paramNames, paramTypes, convertStatementSequence (def.getBody(), def, referencedDefinitions), false, null); } finally { _ctx = oldCtx; diff --git a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldXpandRegistryFactory.java b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldXpandRegistryFactory.java index d3fe2367..a8fb04f4 100644 --- a/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldXpandRegistryFactory.java +++ b/plugins/org.eclipse.xtend.middleend.xpand/src/org/eclipse/xtend/middleend/xpand/internal/OldXpandRegistryFactory.java @@ -10,8 +10,8 @@ Contributors: */ package org.eclipse.xtend.middleend.xpand.internal; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEndFactory; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEndFactory; import org.eclipse.xtend.middleend.xpand.OldXpandRegistry; diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/OldXtendRegistry.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/OldXtendRegistry.java index cc4e0f75..ae2dab77 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/OldXtendRegistry.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/OldXtendRegistry.java @@ -10,28 +10,18 @@ Contributors: */ package org.eclipse.xtend.middleend.xtend; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.eclipose.xtend.middleend.MiddleEnd; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; import org.eclipse.internal.xtend.xtend.XtendFile; import org.eclipse.internal.xtend.xtend.ast.Around; import org.eclipse.internal.xtend.xtend.ast.Extension; import org.eclipse.internal.xtend.xtend.ast.ExtensionFile; import org.eclipse.internal.xtend.xtend.ast.ImportStatement; -import org.eclipse.xtend.backend.aop.AroundAdvice; import org.eclipse.xtend.backend.common.BackendTypesystem; -import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.NamedFunction; -import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; -import org.eclipse.xtend.backend.util.Cache; import org.eclipse.xtend.expression.ExecutionContext; +import org.eclipse.xtend.middleend.MiddleEnd; +import org.eclipse.xtend.middleend.plugins.ImportedResource; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.ParsedResource; import org.eclipse.xtend.middleend.xtend.internal.OldHelper; import org.eclipse.xtend.middleend.xtend.internal.TypeToBackendType; import org.eclipse.xtend.middleend.xtend.internal.xtend.CheckConverter; @@ -52,32 +42,6 @@ public final class OldXtendRegistry implements LanguageSpecificMiddleEnd { private BackendTypesystem _ts; - private final Cache _functionDefContexts = new Cache () { - @Override - protected FunctionDefContextInternal create (String compilationUnit) { - return _middleEnd.createEmptyFdc(); - } - }; - - - /** - * all functions actually defined in a given compilation unit - */ - private final Map> _definedFunctionsByResource = new HashMap >(); - - /** - * all functions exported by a compilation unit, i.e. those functions visible to others that import it - */ - private final Map> _exportedFunctionsByResource = new HashMap >(); - - /** - * all locally defined functions that are exported by a compilation unit. This is an artifact to cleanly handle - * reexports. - */ - private final Map> _locallyExportedFunctionsByResource = new HashMap >(); - - private final Map> _advice = new HashMap> (); - /** * the specificData field contains an ExecutionContext initialized with the MetaModels and the file encoding @@ -95,19 +59,26 @@ public final class OldXtendRegistry implements LanguageSpecificMiddleEnd { } - private FunctionDefContextInternal getFunctionDefContext (String xtendName) { - return _functionDefContexts.get (OldHelper.normalizeXtendResourceName (xtendName)); + public boolean canHandle (String resourceName) { + resourceName = OldHelper.normalizeXtendResourceName (resourceName); + + try { + final ExtensionFile extensionFile = (ExtensionFile) _ctx.getResourceManager().loadResource (resourceName, XtendFile.FILE_EXTENSION); + return extensionFile != null; + } + catch (Exception exc) { + return false; + } + } + + public String getName () { + return "Xtend"; } - - /** - * parses and converts an Xtend file and all other files it depends on. - */ - public void registerExtensionFile (String xtendFile) { - xtendFile = OldHelper.normalizeXtendResourceName (xtendFile); + public ParsedResource parseResource (String xtendFile) { + final ParsedResource result = new ParsedResource (); - if (_definedFunctionsByResource.containsKey (xtendFile)) - return; + xtendFile = OldHelper.normalizeXtendResourceName (xtendFile); final ExtensionFile extensionFile = (ExtensionFile) _ctx.getResourceManager().loadResource (xtendFile, XtendFile.FILE_EXTENSION); if (extensionFile == null) @@ -121,104 +92,26 @@ public final class OldXtendRegistry implements LanguageSpecificMiddleEnd { for (Extension ext: extensionFile.getExtensions()) ext.init (ctx); - final List defined = new ArrayList(); - final List exported = new ArrayList(); - - final FunctionDefContextInternal fdc = getFunctionDefContext (xtendFile); - // register the XtendLib. Do this first so the extension can override functions - for (NamedFunction f: new XtendLibContributor (_middleEnd).getContributedFunctions()) - fdc.register (f, false); + result.getPrivateFunctions().addAll (new XtendLibContributor (_middleEnd).getContributedFunctions()); - fdc.register (new CheckConverter (ctx, typeConverter).createCheckFunction(_ts, fdc, extensionFile), false); + result.getPrivateFunctions().add (new CheckConverter (ctx, typeConverter).createCheckFunction(_ts, extensionFile)); for (Extension ext: extensionFile.getExtensions()) { - final NamedFunction f = extensionFactory.create (ext, fdc); - - defined.add(f); - - if (!ext.isPrivate()) - exported.add (f); + final NamedFunction f = extensionFactory.createUnregistered (ext); + if (ext.isPrivate()) + result.getPrivateFunctions().add (f); + else + result.getPublicFunctions().add (f); } - _definedFunctionsByResource.put (xtendFile, defined); - _exportedFunctionsByResource.put (xtendFile, exported); - _locallyExportedFunctionsByResource.put (xtendFile, new ArrayList (exported)); - - // make sure all imported resources are registered as well - for (String imported: extensionFile.getImportedExtensions()) - registerExtensionFile (imported); - - // make all imported extensions visible for the scope of this compilation unit - for (String importedResource: extensionFile.getImportedExtensions()) { - for (NamedFunction f: _locallyExportedFunctionsByResource.get (OldHelper.normalizeXtendResourceName (importedResource))) - fdc.register (f, false); - } + for (ImportStatement imp: extensionFile.getExtImports()) + result.getImports().add (new ImportedResource (OldHelper.normalizeXtendResourceName (imp.getImportedId().getValue()), imp.isExported())); - final Set visitedForReexport = new HashSet(); - visitedForReexport.add (xtendFile); - final List reexported = new ArrayList(); - getReexported (xtendFile, reexported, visitedForReexport, new HashSet()); - - for (NamedFunction f: reexported) { - exported.add (f); - fdc.register (f, true); - } - - final List advice = new ArrayList (); - _advice.put (xtendFile, advice); for (Around a: extensionFile.getArounds()) - advice.add (extensionFactory.create (a, fdc)); - } - - private void getReexported (String xtendFile, Collection result, Set harvestedCompilationUnits, Set processedCompilationUnits) { - xtendFile = OldHelper.normalizeXtendResourceName (xtendFile); - - if (processedCompilationUnits.contains (xtendFile)) - return; - processedCompilationUnits.add (xtendFile); - - if (! harvestedCompilationUnits.contains (xtendFile)) { - for (NamedFunction f: _locallyExportedFunctionsByResource.get(xtendFile)) - result.add (f); - - harvestedCompilationUnits.add (xtendFile); - } - - final ExtensionFile file = (ExtensionFile) _ctx.getResourceManager().loadResource (xtendFile, XtendFile.FILE_EXTENSION); - for (ImportStatement imp: file.getExtImports()) { - if (imp.isExported()) - getReexported (imp.getImportedId().getValue(), result, harvestedCompilationUnits, processedCompilationUnits); - } - } - - public boolean canHandle (String resourceName) { - resourceName = OldHelper.normalizeXtendResourceName (resourceName); - - if (_definedFunctionsByResource.containsKey (resourceName)) - return true; + result.getAdvice().add(extensionFactory.create (a)); - try { - final ExtensionFile extensionFile = (ExtensionFile) _ctx.getResourceManager().loadResource (resourceName, XtendFile.FILE_EXTENSION); - return extensionFile != null; - } - catch (Exception exc) { - return false; - } - } - - public FunctionDefContext getContributedFunctions (String xtendFile) { - registerExtensionFile (xtendFile); - return getFunctionDefContext(xtendFile); - } - - public List getContributedAdvice (String resourceName) { - registerExtensionFile (resourceName); - return _advice.get (OldHelper.normalizeXtendResourceName (resourceName)); - } - - public String getName () { - return "Xtend"; + return result; } } diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/XtendBackendFacade.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/XtendBackendFacade.java index 4982e9e7..06f0440b 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/XtendBackendFacade.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/XtendBackendFacade.java @@ -17,8 +17,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipose.xtend.middleend.MiddleEnd; -import org.eclipose.xtend.middleend.MiddleEndFactory; import org.eclipse.internal.xtend.expression.ast.Expression; import org.eclipse.internal.xtend.xtend.parser.ParseFacade; import org.eclipse.xtend.backend.BackendFacade; @@ -29,6 +27,8 @@ import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.expression.ExecutionContextImpl; import org.eclipse.xtend.expression.Variable; +import org.eclipse.xtend.middleend.MiddleEnd; +import org.eclipse.xtend.middleend.MiddleEndFactory; import org.eclipse.xtend.middleend.xtend.internal.OldExpressionConverter; import org.eclipse.xtend.middleend.xtend.internal.OldHelper; import org.eclipse.xtend.middleend.xtend.internal.TypeToBackendType; @@ -100,8 +100,7 @@ public final class XtendBackendFacade { final TypeToBackendType typeConverter = new TypeToBackendType (_middleEnd.getTypesystem(), ctx); final ExpressionBase newAst = new OldExpressionConverter (ctx, typeConverter, "").convert (oldAst); - final FunctionDefContext fdc = createFdc (); - _middleEnd.getExecutionContext().setFunctionDefContext (fdc); + _middleEnd.getExecutionContext().setFunctionDefContext (createFdc ()); //TODO configure isLogStacktrace _middleEnd.getExecutionContext().getLocalVarContext().getLocalVars().putAll (localVars); _middleEnd.getExecutionContext().getContributionStateContext().storeState (XtendGlobalVarOperations.GLOBAL_VAR_VALUES_KEY, globalVars); @@ -112,7 +111,7 @@ public final class XtendBackendFacade { private FunctionDefContext createFdc () { if (_xtendFile != null) - return getFunctionDefContext(); + return _middleEnd.getFunctions (_xtendFile); final FunctionDefContextInternal result = _middleEnd.createEmptyFdc(); @@ -131,7 +130,7 @@ public final class XtendBackendFacade { } public Object invokeXtendFunction (String functionName, Object... parameters) { - final FunctionDefContext fdc = getFunctionDefContext(); + final FunctionDefContext fdc = _middleEnd.getFunctions (_xtendFile); final ExecutionContext ctx = BackendFacade.createExecutionContext (fdc, _middleEnd.getTypesystem(), true); //TODO configure isLogStacktrace return fdc.invoke (ctx, functionName, Arrays.asList (parameters)); } @@ -161,13 +160,10 @@ public final class XtendBackendFacade { _xtendFile = OldHelper.normalizeXtendResourceName (xtendFileName); _mms = mms; - _middleEnd = MiddleEndFactory.create (OldHelper.guessTypesystem (mms), getSpecificParameters (fileEncoding, mms)); + _middleEnd = MiddleEndFactory.createFromExtensions (OldHelper.guessTypesystem (mms), getSpecificParameters (fileEncoding, mms)); } - - public FunctionDefContext getFunctionDefContext () { - if (_xtendFile == null) - return _middleEnd.createEmptyFdc(); + public FunctionDefContext getFunctionDefContext () { return _middleEnd.getFunctions (_xtendFile); } } diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldExpressionConverter.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldExpressionConverter.java index c05ec790..43e4d708 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldExpressionConverter.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldExpressionConverter.java @@ -46,7 +46,6 @@ import org.eclipse.xtend.backend.aop.ExecutionPointcut; import org.eclipse.xtend.backend.aop.Pointcut; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExpressionBase; -import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.SourcePos; import org.eclipse.xtend.backend.common.SyntaxConstants; import org.eclipse.xtend.backend.expr.AndExpression; @@ -106,14 +105,14 @@ public final class OldExpressionConverter { private static final AdviceParamType _wildCardParamType = new AdviceParamType (ObjectType.INSTANCE, true); - public AroundAdvice convertAdvice (ExpressionBase body, String namePattern, List params, boolean hasVarArgs, FunctionDefContext fdc) { + public AroundAdvice convertAdvice (ExpressionBase body, String namePattern, List params, boolean hasVarArgs) { final List > paramTypes = new ArrayList > (); for (DeclaredParameter dp: params) paramTypes.add (new Pair (dp.getName().getValue(), new AdviceParamType (_typeConverter.convertToBackendType (dp.getType()), true))); final Pointcut pointcut = new ExecutionPointcut (namePattern, paramTypes, hasVarArgs, _wildCardParamType); - return new AroundAdvice (body, pointcut, false, fdc); + return new AroundAdvice (body, pointcut, false); } public ExpressionBase convert (Expression expr) { diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldHelper.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldHelper.java index 4cac5b77..85ec9c88 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldHelper.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/OldHelper.java @@ -69,8 +69,8 @@ public final class OldHelper { if (xpandName == null) return null; - if (! xpandName.endsWith("." + XpandUtil.TEMPLATE_EXTENSION)) - xpandName += "." + XpandUtil.TEMPLATE_EXTENSION; + if (xpandName.endsWith("." + XpandUtil.TEMPLATE_EXTENSION)) + xpandName = xpandName.substring (0, xpandName.length() - XpandUtil.TEMPLATE_EXTENSION.length() - 1); xpandName = xpandName.replace (SyntaxConstants.NS_DELIM, "/"); if (xpandName.startsWith ("/")) diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/CheckConverter.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/CheckConverter.java index ef36b5d6..097eb42f 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/CheckConverter.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/CheckConverter.java @@ -20,7 +20,6 @@ import org.eclipse.internal.xtend.xtend.ast.ExtensionFile; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.BackendTypesystem; import org.eclipse.xtend.backend.common.ExpressionBase; -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; @@ -64,7 +63,7 @@ public final class CheckConverter { } - public NamedFunction createCheckFunction (BackendTypesystem ts, FunctionDefContext fdc, ExtensionFile extensionFile) { + public NamedFunction createCheckFunction (BackendTypesystem ts, ExtensionFile extensionFile) { final OldExpressionConverter exprConv = new OldExpressionConverter (_emptyExecutionContext.cloneWithResource (extensionFile), _typeConverter, OldHelper.normalizeXtendResourceName (extensionFile.getFullyQualifiedName())); final List paramNames = Arrays.asList (ISSUES_PARAM_NAME, ALL_OBJECTS_PARAM_NAME); final List paramTypes = Arrays.asList (ts.findType (Issues.class), CollectionType.INSTANCE); @@ -75,7 +74,7 @@ public final class CheckConverter { final ExpressionBase body = new SequenceExpression (allChecks, exprConv.getSourcePos (extensionFile)); - return new NamedFunction (ALL_CHECKS_FUNCTION_NAME, new SourceDefinedFunction (ALL_CHECKS_FUNCTION_NAME, paramNames, paramTypes, fdc, body, false, null)); + return new NamedFunction (ALL_CHECKS_FUNCTION_NAME, new SourceDefinedFunction (ALL_CHECKS_FUNCTION_NAME, paramNames, paramTypes, body, false, null)); } diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/JavaExtensionFunction.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/JavaExtensionFunction.java index c87980b6..6601f76f 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/JavaExtensionFunction.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/JavaExtensionFunction.java @@ -15,8 +15,7 @@ import java.util.List; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; -import org.eclipse.xtend.backend.common.ExpressionBase; -import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.functions.AbstractFunction; import org.eclipse.xtend.backend.util.ErrorHandler; @@ -24,29 +23,18 @@ import org.eclipse.xtend.backend.util.ErrorHandler; * * @author Arno Haase (http://www.haase-consulting.com) */ -final class JavaExtensionFunction implements Function { +final class JavaExtensionFunction extends AbstractFunction { private final Method _mtd; - private final boolean _cached; - private final List _paramTypes; public JavaExtensionFunction (Method mtd, boolean cached, List paramTypes) { + super (null, paramTypes, cached); _mtd = mtd; - _cached = cached; - _paramTypes = paramTypes; } - public ExpressionBase getGuard () { - return null; - } - public String getName () { return _mtd.getName(); } - public List getParameterTypes () { - return _paramTypes; - } - public Object invoke (ExecutionContext ctx, Object[] params) { try { return _mtd.invoke (null, params); @@ -55,8 +43,4 @@ final class JavaExtensionFunction implements Function { return null; // to make the compiler happy - this is never executed } } - - public boolean isCached () { - return _cached; - } } diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/OldExtensionConverter.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/OldExtensionConverter.java index e48cc97b..0b770456 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/OldExtensionConverter.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtend/OldExtensionConverter.java @@ -25,13 +25,11 @@ import org.eclipse.xtend.backend.aop.AroundAdvice; import org.eclipse.xtend.backend.common.BackendType; 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.expression.AnalysationIssue; import org.eclipse.xtend.expression.ExecutionContext; @@ -56,30 +54,21 @@ public final class OldExtensionConverter { _typeConverter = typeConverter; } - public AroundAdvice create (Around around, FunctionDefContext fdc) { + public AroundAdvice create (Around around) { final OldExpressionConverter exprConv = new OldExpressionConverter (_ctx, _typeConverter, ""); final ExpressionBase body = convertExpression (around.getExpression(), exprConv.getAdviceLocalVarNames(), exprConv.getAdviceLocalVarTypes(_ctx), ""); - return exprConv.convertAdvice (body, around.getPointCut().getValue(), around.getParams(), around.isWildparams(), fdc); + return exprConv.convertAdvice (body, around.getPointCut().getValue(), around.getParams(), around.isWildparams()); } - /** - * converts an extension to a function, taking care of mutual registration with its fdc - */ - public NamedFunction create (Extension extension, FunctionDefContextInternal fdc) { - final NamedFunction result = new NamedFunction (extension.getName(), createUnregistered (extension, fdc)); - fdc.register (result, !extension.isPrivate()); - return result; - } - - private Function createUnregistered (Extension extension, FunctionDefContextInternal fdc) { + public NamedFunction createUnregistered (Extension extension) { if (extension instanceof JavaExtensionStatement) - return createJavaExtension ((JavaExtensionStatement) extension); + return new NamedFunction (extension.getName(), createJavaExtension ((JavaExtensionStatement) extension)); if (extension instanceof ExpressionExtensionStatement) - return createExpressionExtension ((ExpressionExtensionStatement) extension, fdc); + return new NamedFunction (extension.getName(), createExpressionExtension ((ExpressionExtensionStatement) extension)); if (extension instanceof CreateExtensionStatement) - return createCreateExtension ((CreateExtensionStatement) extension, fdc); + return new NamedFunction (extension.getName(), createCreateExtension ((CreateExtensionStatement) extension)); throw new IllegalArgumentException ("unsupported extension type " + extension.getClass().getName()); } @@ -104,12 +93,12 @@ public final class OldExtensionConverter { return exprConverter.convert (expr); } - private Function createExpressionExtension (ExpressionExtensionStatement extension, FunctionDefContext fdc) { + private Function createExpressionExtension (ExpressionExtensionStatement extension) { return new SourceDefinedFunction (extension.getName(), extension.getParameterNames(), getParameterTypes (extension), // - fdc, convertExpression (extension.getExpression(), extension.getParameterNames(), extension.getParameterTypes(), extension.getName ()), extension.isCached(), null); + convertExpression (extension.getExpression(), extension.getParameterNames(), extension.getParameterTypes(), extension.getName ()), extension.isCached(), null); } - private Function createCreateExtension (CreateExtensionStatement extension, FunctionDefContext fdc) { + private Function createCreateExtension (CreateExtensionStatement extension) { final Type createdType = _ctx.getTypeForName (extension.getReturnTypeIdentifier().getValue()); final List paramExprs = new ArrayList (); for (String varName: extension.getParameterNames()) @@ -119,7 +108,7 @@ public final class OldExtensionConverter { final ExpressionBase createExpr = new CreateCachedExpression (_typeConverter.convertToBackendType(createdType), paramExprs, OldExpressionConverter.getSourcePos (extension, extension.getName())); final ExpressionBase createWrapper = new NewLocalVarDefExpression (SyntaxConstants.THIS, createExpr, body, OldExpressionConverter.getSourcePos (extension, extension.getName ())); - return new SourceDefinedFunction (extension.getName(), extension.getParameterNames(), getParameterTypes(extension), fdc, createWrapper, true, null); + return new SourceDefinedFunction (extension.getName(), extension.getParameterNames(), getParameterTypes(extension), createWrapper, true, null); } private Function createJavaExtension (JavaExtensionStatement extension) { diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtendlib/XtendLibContributor.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtendlib/XtendLibContributor.java index 48652c00..a4dcf03c 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtendlib/XtendLibContributor.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/internal/xtendlib/XtendLibContributor.java @@ -14,9 +14,9 @@ import static org.eclipse.xtend.middleend.javaannotations.JavaFunctionClassContr import java.util.Collection; -import org.eclipose.xtend.middleend.MiddleEnd; import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.functions.DuplicateAwareNamedFunctionCollection; +import org.eclipse.xtend.middleend.MiddleEnd; /** diff --git a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/plugin/OldXtendRegistryFactory.java b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/plugin/OldXtendRegistryFactory.java index 99387efd..d7c3d456 100644 --- a/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/plugin/OldXtendRegistryFactory.java +++ b/plugins/org.eclipse.xtend.middleend.xtend/src/org/eclipse/xtend/middleend/xtend/plugin/OldXtendRegistryFactory.java @@ -10,8 +10,8 @@ Contributors: */ package org.eclipse.xtend.middleend.xtend.plugin; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEnd; -import org.eclipose.xtend.middleend.plugins.LanguageSpecificMiddleEndFactory; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd; +import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEndFactory; import org.eclipse.xtend.middleend.xtend.OldXtendRegistry; diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/aop/AopTest.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/aop/AopTest.java index 82e34040..6fc2773a 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/aop/AopTest.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/aop/AopTest.java @@ -10,6 +10,7 @@ Contributors: */ package org.eclipse.xtend.backend.aop; +import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyExecutionContext; import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.*; import static org.junit.Assert.assertEquals; @@ -23,17 +24,17 @@ import org.eclipse.xtend.backend.common.AdviceContext; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.ExpressionBase; -import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.expr.ConcatExpression; import org.eclipse.xtend.backend.expr.InvocationOnObjectExpression; import org.eclipse.xtend.backend.expr.LiteralExpression; +import org.eclipse.xtend.backend.functions.AbstractFunction; import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.backend.testhelpers.CounterFunction; +import org.eclipse.xtend.backend.types.CompositeTypesystem; import org.eclipse.xtend.backend.types.builtin.CollectionType; import org.eclipse.xtend.backend.types.builtin.ObjectType; import org.eclipse.xtend.backend.util.Pair; -import org.eclipse.xtend.middleend.javaannotations.JavaDefinedFunction; import org.junit.Test; @@ -46,12 +47,9 @@ public class AopTest { public void testUncached () { final ExecutionContext ctx = createEmptyExecutionContext(); - final FunctionDefContextInternal fdc = createEmptyFdc (ctx.getTypesystem()); + final FunctionDefContextInternal fdc = createFdc (ctx.getTypesystem(), CounterFunction.class); ctx.setFunctionDefContext (fdc); - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (CounterFunction.class, ctx.getTypesystem())) - fdc.register (new NamedFunction (f.getName(), f), true); - @SuppressWarnings("unchecked") final Pointcut pointCut = new ExecutionPointcut ("*", Collections.EMPTY_LIST, true, new AdviceParamType (ObjectType.INSTANCE, true)); registerAdvice (ctx, "pre-1", "post-1", true, pointCut, true); @@ -77,7 +75,10 @@ public class AopTest { } private void registerAdvice (ExecutionContext ctx, String prefix, String postfix, boolean proceed, Pointcut pointCut, boolean cached) { - ctx.setAdviceContext (ctx.getAdviceContext().copyWithAdvice (new AroundAdvice (ConcatAdviceFactory.createConcatExpression (prefix, postfix, proceed), pointCut, cached, createEmptyFdc (ctx.getTypesystem())))); + final AroundAdvice newAdvice = new AroundAdvice (ConcatAdviceFactory.createConcatExpression (prefix, postfix, proceed), pointCut, cached); + newAdvice.setFunctionDefContext (createEmptyFdc (new CompositeTypesystem ())); + + ctx.setAdviceContext (ctx.getAdviceContext().copyWithAdvice (newAdvice)); } @SuppressWarnings("unchecked") @@ -85,12 +86,9 @@ public class AopTest { public void testVarArgsParamTypeMatching () { final ExecutionContext ctx = createEmptyExecutionContext(); - final FunctionDefContextInternal fdc = createEmptyFdc (ctx.getTypesystem()); + final FunctionDefContextInternal fdc = createFdc (ctx.getTypesystem(), AopTestFunctions.class); ctx.setFunctionDefContext (fdc); - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (AopTestFunctions.class, ctx.getTypesystem())) - fdc.register (new NamedFunction (f.getName(), f), true); - final Pointcut pointCutObject = new ExecutionPointcut ("f", Collections.EMPTY_LIST, true, new AdviceParamType (ObjectType.INSTANCE, false)); final Pointcut pointCutObjectPlus = new ExecutionPointcut ("f", Collections.EMPTY_LIST, true, new AdviceParamType (ObjectType.INSTANCE, true)); final Pointcut pointCutCollection = new ExecutionPointcut ("f", Collections.EMPTY_LIST, true, new AdviceParamType (CollectionType.INSTANCE, false)); @@ -112,12 +110,9 @@ public class AopTest { public void testExplicitParamTypeMatching () { final ExecutionContext ctx = createEmptyExecutionContext(); - final FunctionDefContextInternal fdc = createEmptyFdc (ctx.getTypesystem()); + final FunctionDefContextInternal fdc = createFdc (ctx.getTypesystem(), AopTestFunctions.class); ctx.setFunctionDefContext (fdc); - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (AopTestFunctions.class, ctx.getTypesystem())) - fdc.register (new NamedFunction (f.getName(), f), true); - final Pointcut pointCutObject = new ExecutionPointcut ("f", Arrays.asList (new Pair ("o", new AdviceParamType (ObjectType.INSTANCE, false))), false, null); final Pointcut pointCutObjectPlus = new ExecutionPointcut ("f", Arrays.asList (new Pair ("o", new AdviceParamType (ObjectType.INSTANCE, true))), false, null); final Pointcut pointCutCollection = new ExecutionPointcut ("f", Arrays.asList (new Pair ("o", new AdviceParamType (CollectionType.INSTANCE, false))), false, null); @@ -139,12 +134,9 @@ public class AopTest { public void testNameMatching () { final ExecutionContext ctx = createEmptyExecutionContext(); - final FunctionDefContextInternal fdc = createEmptyFdc (ctx.getTypesystem()); + final FunctionDefContextInternal fdc = createFdc (ctx.getTypesystem(), AopTestFunctions.class); ctx.setFunctionDefContext (fdc); - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (AopTestFunctions.class, ctx.getTypesystem())) - fdc.register (new NamedFunction (f.getName(), f), true); - final Pointcut pointCutFirstPre = new ExecutionPointcut ("first*", Collections.EMPTY_LIST, true, new AdviceParamType (ObjectType.INSTANCE, true)); final Pointcut pointCutFirstPost = new ExecutionPointcut ("*tFunction", Collections.EMPTY_LIST, true, new AdviceParamType (ObjectType.INSTANCE, true)); final Pointcut pointCutFirstIn = new ExecutionPointcut ("*tF*", Collections.EMPTY_LIST, true, new AdviceParamType (ObjectType.INSTANCE, true)); @@ -180,29 +172,13 @@ public class AopTest { final ExecutionContext ctx = createEmptyExecutionContext(); - final FunctionDefContextInternal fdc = createEmptyFdc (ctx.getTypesystem()); + final FunctionDefContextInternal fdc = createFdc (ctx.getTypesystem(), CounterFunction.class); ctx.setFunctionDefContext (fdc); - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (CounterFunction.class, ctx.getTypesystem())) - fdc.register (new NamedFunction (f.getName(), f), true); - - fdc.register (new NamedFunction ("f", new Function () { - - public ExpressionBase getGuard () { - return null; - } - - public List getParameterTypes () { - return new ArrayList (); - } - + fdc.register (new NamedFunction ("f", new AbstractFunction (null, new ArrayList (), true) { public Object invoke (ExecutionContext localCtx, Object[] params) { return _counter++; } - - public boolean isCached () { - return true; - } }), true); final Pointcut pointCut = new ExecutionPointcut ("f", Collections.EMPTY_LIST, false, null); @@ -225,7 +201,10 @@ public class AopTest { toBeConcatenated.add (new LiteralExpression (" ", null)); toBeConcatenated.add (ConcatAdviceFactory.createProceedExpression()); - ctx.setAdviceContext (ctx.getAdviceContext().copyWithAdvice (new AroundAdvice (new ConcatExpression (toBeConcatenated, null), pointCut, cacheable, ctx.getFunctionDefContext()))); + final AroundAdvice advice = new AroundAdvice (new ConcatExpression (toBeConcatenated, null), pointCut, cacheable); + advice.setFunctionDefContext (ctx.getFunctionDefContext()); + + ctx.setAdviceContext (ctx.getAdviceContext().copyWithAdvice (advice)); } } diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/expr/InitClosureExpressionTest.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/expr/InitClosureExpressionTest.java index bf435cfd..2691efc5 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/expr/InitClosureExpressionTest.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/expr/InitClosureExpressionTest.java @@ -24,6 +24,7 @@ import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.ExpressionBase; import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.NamedFunction; +import org.eclipse.xtend.backend.functions.AbstractFunction; import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.backend.types.CompositeTypesystem; import org.eclipse.xtend.backend.types.builtin.StringType; @@ -77,23 +78,10 @@ public class InitClosureExpressionTest { final BackendTypesystem ts = new CompositeTypesystem (); final FunctionDefContextInternal fdc = createEmptyFdc (ts); - fdc.register (new NamedFunction ("myFunction", new Function () { - - public ExpressionBase getGuard () { - return null; - } - - public List getParameterTypes () { - return new ArrayList(); - } - + fdc.register (new NamedFunction ("myFunction", new AbstractFunction (null, new ArrayList (), false) { public Object invoke (ExecutionContext ctx, Object[] params) { return "myResult"; } - - public boolean isCached () { - return false; - } }), true); final ExecutionContext initCtx = BackendFacade.createExecutionContext (fdc, ts, true); diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/functions/FunctionTest.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/functions/FunctionTest.java index 5d6ab75c..e60bd87e 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/functions/FunctionTest.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/functions/FunctionTest.java @@ -10,17 +10,17 @@ Contributors: */ package org.eclipse.xtend.backend.functions; -import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.*; +import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyExecutionContext; +import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyFdc; +import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createFdc; import static org.junit.Assert.assertEquals; import java.util.ArrayList; import org.eclipse.xtend.backend.common.EfficientLazyString; import org.eclipse.xtend.backend.common.ExecutionContext; -import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.testhelpers.CounterFunction; import org.eclipse.xtend.backend.testhelpers.NamedFunctionFactory; -import org.eclipse.xtend.middleend.javaannotations.JavaDefinedFunction; import org.junit.Test; @@ -32,18 +32,15 @@ public class FunctionTest { @Test public void testCachedAndSingleInstance () { final ExecutionContext ctx = createEmptyExecutionContext (); - final FunctionDefContextInternal fdc = createEmptyFdc (ctx.getTypesystem()); + final FunctionDefContextInternal fdc = createFdc (ctx.getTypesystem(), CounterFunction.class); ctx.setFunctionDefContext (fdc); - - for (JavaDefinedFunction f: JavaDefinedFunction.createForEntireClass (CounterFunction.class, ctx.getTypesystem())) - fdc.register (new NamedFunction (f.getName(), f), true); - fdc.register (new NamedFunctionFactory ("myCached", true) { + fdc.register (new NamedFunctionFactory ("myCached", true, fdc) { public Object invoke (ExecutionContext innerCtx, Object[] params) { return innerCtx.getFunctionDefContext().invoke (innerCtx, "nextCounterValue", new ArrayList ()); } }.create(), true); - fdc.register (new NamedFunctionFactory ("myUncached", false) { + fdc.register (new NamedFunctionFactory ("myUncached", false, fdc) { public Object invoke (ExecutionContext innerCtx, Object[] params) { return innerCtx.getFunctionDefContext().invoke (innerCtx, "nextCounterValue", new ArrayList ()); } diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BackendTestHelper.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BackendTestHelper.java index 08581da8..a56f0195 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BackendTestHelper.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BackendTestHelper.java @@ -10,7 +10,6 @@ Contributors: */ package org.eclipse.xtend.backend.testhelpers; -import org.eclipose.xtend.middleend.MiddleEnd; import org.eclipse.xtend.backend.BackendFacade; import org.eclipse.xtend.backend.common.BackendTypesystem; import org.eclipse.xtend.backend.common.ExecutionContext; @@ -19,6 +18,8 @@ import org.eclipse.xtend.backend.common.SourcePos; import org.eclipse.xtend.backend.expr.LiteralExpression; import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.backend.types.CompositeTypesystem; +import org.eclipse.xtend.middleend.MiddleEndFactory; +import org.eclipse.xtend.middleend.javaannotations.JavaFunctionClassContributor; /** @@ -34,11 +35,15 @@ public class BackendTestHelper { */ public static ExecutionContext createEmptyExecutionContext () { final BackendTypesystem ts = new CompositeTypesystem (); - return BackendFacade.createExecutionContext (new MiddleEnd (ts, null).createEmptyFdc(), ts, true); + return BackendFacade.createExecutionContext (createEmptyFdc (ts), ts, true); } public static FunctionDefContextInternal createEmptyFdc (BackendTypesystem ts) { - return new MiddleEnd (ts, null).createEmptyFdc(); + return (FunctionDefContextInternal) MiddleEndFactory.create (ts, null).getFunctions ("java/lang/Object"); + } + + public static FunctionDefContextInternal createFdc (BackendTypesystem ts, Class contributingClass) { + return (FunctionDefContextInternal) MiddleEndFactory.create (ts, null).getFunctions (JavaFunctionClassContributor.classAsResource (contributingClass)); } public static ExpressionBase createLiteral (Object literal) { diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/NamedFunctionFactory.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/NamedFunctionFactory.java index d94c4467..2344f159 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/NamedFunctionFactory.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/NamedFunctionFactory.java @@ -10,47 +10,39 @@ Contributors: */ package org.eclipse.xtend.backend.testhelpers; +import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyFdc; + import java.util.Arrays; -import java.util.List; import org.eclipse.xtend.backend.common.BackendType; -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.functions.AbstractFunction; +import org.eclipse.xtend.backend.types.CompositeTypesystem; /** * * @author Arno Haase (http://www.haase-consulting.com) */ -public abstract class NamedFunctionFactory implements Function { +public abstract class NamedFunctionFactory extends AbstractFunction { private final String _name; - private final List _parameterTypes; - private final boolean _cached; public NamedFunctionFactory (String name, BackendType... paramTypes) { this (name, false, paramTypes); } - public NamedFunction create () { - return new NamedFunction (_name, this); - } - public NamedFunctionFactory (String name, boolean cached, BackendType... paramTypes) { - _name = name; - _cached = cached; - _parameterTypes = Arrays.asList (paramTypes); + this (name, cached, createEmptyFdc (new CompositeTypesystem ()), paramTypes); } - public ExpressionBase getGuard () { - return null; - } - - public List getParameterTypes () { - return _parameterTypes; + public NamedFunctionFactory (String name, boolean cached, FunctionDefContext fdc, BackendType... paramTypes) { + super (null, Arrays.asList (paramTypes), cached); + _name = name; + setFunctionDefContext (fdc); } - - public boolean isCached () { - return _cached; + + public NamedFunction create () { + return new NamedFunction (_name, this); } } diff --git a/tests/org.eclipse.xtend.middleend.old.test/src/org/eclipse/xtend/middleend/old/first/FirstAttempt.java b/tests/org.eclipse.xtend.middleend.old.test/src/org/eclipse/xtend/middleend/old/first/FirstAttempt.java index 53696fea..0b13bff1 100644 --- a/tests/org.eclipse.xtend.middleend.old.test/src/org/eclipse/xtend/middleend/old/first/FirstAttempt.java +++ b/tests/org.eclipse.xtend.middleend.old.test/src/org/eclipse/xtend/middleend/old/first/FirstAttempt.java @@ -57,6 +57,8 @@ public class FirstAttempt { } { + System.out.println ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + final XtendBackendFacade bc = XtendBackendFacade.createForFile ("org::eclipse::xtend::middleend::old::first::first", "iso-8859-1", mms); final ExecutionContext ctx = BackendFacade.createExecutionContext (bc.getFunctionDefContext(), ts, true); -- cgit v1.2.3