Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend')
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEnd.java51
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/MiddleEndFactory.java49
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/Activator.java105
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/internal/MiddleEndImpl.java223
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/AbstractExecutionContextAware.java2
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java64
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tAroundAdvice.java31
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tCached.java27
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tNoFunction.java (renamed from plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tHidden.java)2
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/M2tPrivateFunction.java28
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/internal/JavaDefinedFunction.java (renamed from plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaDefinedFunction.java)68
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ImportedResource.java34
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEnd.java46
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/LanguageSpecificMiddleEndFactory.java48
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/plugins/ParsedResource.java46
15 files changed, 749 insertions, 75 deletions
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.<br>
+ *
+ * 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. <br>
+ *
+ * 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<LanguageSpecificMiddleEnd> 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.<br>
+ *
+ * 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<Class<?>, 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<LanguageSpecificMiddleEndFactory> _middleEndContributions = new ArrayList<LanguageSpecificMiddleEndFactory> ();
+ private boolean _isInitialized = false;
+
+
+ public List<LanguageSpecificMiddleEnd> getFreshMiddleEnds (Map<Class<?>, Object> specificParams) {
+ init ();
+
+ final List<LanguageSpecificMiddleEnd> result = new ArrayList<LanguageSpecificMiddleEnd>();
+
+ 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 <LanguageSpecificMiddleEndFactory> () {
+ 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.<br>
+ *
+ * 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<String, ParsedResource> _parsedResources = new HashMap<String, ParsedResource> ();
+ private final Map<String, FunctionDefContext> _fdcs = new HashMap<String, FunctionDefContext> ();
+
+ private final List<LanguageSpecificMiddleEnd> _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<LanguageSpecificMiddleEnd> languageHandlers) {
+ if (languageHandlers == null)
+ languageHandlers = new ArrayList<LanguageSpecificMiddleEnd> ();
+
+ // 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<String> reexported = new HashSet<String> ();
+ collectReexportedResources (reexported, new HashSet<String> (), 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<String> result, Set<String> 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. <br>
+ *
+ * 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/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<AroundAdvice> getContributedAdvice (String resourceName) {
- return new ArrayList<AroundAdvice> (); //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/M2tNoFunction.java
index 8d377c17..613a4e65 100644
--- 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/M2tNoFunction.java
@@ -23,5 +23,5 @@ import java.lang.annotation.Target;
*/
@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.METHOD)
-public @interface M2tHidden {
+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/JavaDefinedFunction.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/internal/JavaDefinedFunction.java
index 8c22e3f4..8a67eb23 100644
--- 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/internal/JavaDefinedFunction.java
@@ -8,7 +8,7 @@ http://www.eclipse.org/legal/epl-v10.html
Contributors:
Arno Haase - initial API and implementation
*/
-package org.eclipse.xtend.middleend.javaannotations;
+package org.eclipse.xtend.middleend.javaannotations.internal;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -20,11 +20,13 @@ 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.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;
/**
@@ -37,57 +39,19 @@ import org.eclipse.xtend.backend.util.ErrorHandler;
*
* @author Arno Haase (http://www.haase-consulting.com)
*/
-public final class JavaDefinedFunction implements Function {
+public final class JavaDefinedFunction extends AbstractFunction {
private final Method _mtd;
- private final List<BackendType> _parameterTypes;
- private final ExpressionBase _guard;
private final boolean _isStatic;
-
+
private final List<ParameterConverter> _parameterConverters = new ArrayList<ParameterConverter>();
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<JavaDefinedFunction> createForEntireClass (Class<?> cls, BackendTypesystem ts) {
- final List<JavaDefinedFunction> result = new ArrayList<JavaDefinedFunction>();
-
- 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 (mtd, guessParameterTypes (mtd, ts), guard);
}
@@ -95,9 +59,9 @@ public final class JavaDefinedFunction implements Function {
* This constructor provides full control
*/
public JavaDefinedFunction (Method mtd, List<BackendType> parameterTypes, ExpressionBase guard) {
+ super (guard, parameterTypes, mtd.getAnnotation (M2tCached.class) != null);
+
_mtd = mtd;
- _parameterTypes = parameterTypes;
- _guard = guard;
for (int i=0; i<mtd.getParameterTypes().length; i++) {
final ParameterConverter pc = JavaBuiltinConverterFactory.getParameterConverter (mtd.getParameterTypes()[i], i);
@@ -141,14 +105,6 @@ public final class JavaDefinedFunction implements Function {
return _mtd.getName();
}
- public boolean isCached () {
- return false;
- }
-
- public List<BackendType> getParameterTypes() {
- return _parameterTypes;
- }
-
public Object invoke (ExecutionContext ctx, Object[] params) {
for (ParameterConverter pc: _parameterConverters)
pc.convert(params);
@@ -175,14 +131,10 @@ public final class JavaDefinedFunction implements Function {
return null; // to make the compiler happy - this is never executed
}
}
-
- public ExpressionBase getGuard () {
- return _guard;
- }
@Override
public String toString () {
- return "JavaDefinedFunction '" + getName() + "' " + _parameterTypes;
+ 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.<br>
+ *
+ * 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. <br>
+ *
+ * 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.<br>
+ *
+ * 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<ImportedResource> _imports = new ArrayList<ImportedResource> ();
+ private final List<NamedFunction> _privateFunctions = new ArrayList<NamedFunction> ();
+ private final List<NamedFunction> _publicFunctions = new ArrayList<NamedFunction> ();
+ private final List<AroundAdvice> _advice = new ArrayList<AroundAdvice> ();
+
+ public List<ImportedResource> getImports () {
+ return _imports;
+ }
+
+ public List<NamedFunction> getPrivateFunctions () {
+ return _privateFunctions;
+ }
+
+ public List<NamedFunction> getPublicFunctions () {
+ return _publicFunctions;
+ }
+
+ public List<AroundAdvice> getAdvice () {
+ return _advice;
+ }
+}

Back to the top