/* Copyright (c) 2008, 2009 Arno Haase, Andr� Arnold. 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 Andr� Arnold */ package org.eclipse.xtend.middleend.xtend; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.internal.xtend.expression.ast.Expression; import org.eclipse.internal.xtend.xtend.parser.ParseFacade; import org.eclipse.xtend.backend.BackendFacade; import org.eclipse.xtend.backend.common.ExecutionContext; 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.QualifiedName; import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.expression.ExecutionContextImpl; import org.eclipse.xtend.expression.Variable; import org.eclipse.xtend.middleend.LanguageContributor; 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.TypeToBackendType; import org.eclipse.xtend.middleend.xtend.internal.xtendlib.XtendGlobalVarOperations; import org.eclipse.xtend.middleend.xtend.internal.xtendlib.XtendLibContributor; import org.eclipse.xtend.middleend.xtend.plugin.OldCheckRegistryFactory; import org.eclipse.xtend.middleend.xtend.plugin.OldXtendRegistryFactory; import org.eclipse.xtend.typesystem.MetaModel; /** * * @author Arno Haase (http://www.haase-consulting.com) * @author Andr� Arnold */ public final class XtendBackendFacade { private final String _xtendFile; private final MiddleEnd _middleEnd; private final Collection<MetaModel> _mms; /** * This method invokes a "stand alone" expression that knows nothing about any functions defined in files. It is useful for * *very* simple use cases, and for testing purposes. <br> * * Both mms and localVars may be null. */ public static Object evaluateExpression (String expression, Collection<MetaModel> mms, Map<String, Object> localVars) { return evaluateExpression (expression, mms, localVars, null); } public static Object evaluateExpression (String expression, Collection<MetaModel> mms, Map<String, Object> localVars, Map<String, Object> globalVars) { return evaluateExpression (expression, null, null, mms, localVars, globalVars, null); } /** * This method invokes an expression that may call functions from an Xtend file.<br> * * The fileEncoding may be null, in which case the platform's default encoding is used. Both mms and localVars may be null. */ public static Object evaluateExpression (String expression, String initialXtendFileName, String fileEncoding, Collection<MetaModel> mms, Map<String, Object> localVars) { return evaluateExpression (expression, initialXtendFileName, fileEncoding, mms, localVars, null, null); } public static Object evaluateExpression (String expression, String initialXtendFileName, String fileEncoding, Collection<MetaModel> mms, Map<String, Object> localVars, Map<String, Object> globalVars, List<String> adviceResources) { return createForFile (initialXtendFileName, fileEncoding, mms).evaluateExpression (expression, localVars, globalVars, adviceResources); } public Object evaluateExpression (String expression, Map<String, Object> localVars) { return evaluateExpression (expression, localVars, null, null); } public Object evaluateExpression (String expression, Map<String, Object> localVars, Map<String, Object> globalVars, List<String> adviceResources) { if (localVars == null) localVars = new HashMap<String, Object> (); if (globalVars == null) globalVars = new HashMap<String, Object> (); if (adviceResources == null) adviceResources = new ArrayList<String> (); for (String a: adviceResources) _middleEnd.applyAdvice (a); final Expression oldAst = ParseFacade.expression (expression); ExecutionContextImpl ctx = new ExecutionContextImpl (); for (MetaModel mm: _mms) ctx.registerMetaModel (mm); for (String varName: localVars.keySet()) ctx = (ExecutionContextImpl) ctx.cloneWithVariable (new Variable (varName, ctx.getType (localVars.get (varName)))); final TypeToBackendType typeConverter = new TypeToBackendType (_middleEnd.getTypesystem(), ctx); final ExpressionBase newAst = new OldExpressionConverter (ctx, typeConverter, "<no file>").convert (oldAst); _middleEnd.getExecutionContext().setFunctionDefContext (createFdc ()); //TODO configure isLogStacktrace _middleEnd.getExecutionContext().getLocalVarContext().getLocalVars().putAll (localVars); _middleEnd.getExecutionContext().getContributionStateContext().storeState (XtendGlobalVarOperations.GLOBAL_VAR_VALUES_KEY, globalVars); return newAst.evaluate (_middleEnd.getExecutionContext()); } private FunctionDefContext createFdc () { if (_xtendFile != null) return _middleEnd.getFunctions (_xtendFile); final FunctionDefContextInternal result = _middleEnd.createEmptyFdc(); for (NamedFunction f: new XtendLibContributor (_middleEnd).getContributedFunctions()) result.register (f, false); return result; } /** * This function invokes a single Xtend function, returning the result. The fileEncoding may be null, in which case the platform's default file * encoding is used. */ public static Object invokeXtendFunction (String xtendFileName, String fileEncoding, Collection<MetaModel> mms, QualifiedName functionName, Object... parameters) { return createForFile (xtendFileName, fileEncoding, mms).invokeXtendFunction (functionName, parameters); } public Object invokeXtendFunction (QualifiedName functionName, Object... parameters) { 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)); } public static XtendBackendFacade createForFile (String xtendFileName, String fileEncoding, Collection<MetaModel> mms) { return new XtendBackendFacade (xtendFileName, fileEncoding, mms); } private Map<Class<?>, Object> getSpecificParameters (String fileEncoding, Collection<MetaModel> mms) { fileEncoding = OldHelper.normalizedFileEncoding (fileEncoding); final ExecutionContextImpl ctx = new ExecutionContextImpl (); ctx.getResourceManager().setFileEncoding (fileEncoding); for (MetaModel mm: mms) ctx.registerMetaModel (mm); final Map<Class<?>, Object> result = new HashMap<Class<?>, Object> (); result.put (OldXtendRegistryFactory.class, ctx); result.put (OldCheckRegistryFactory.class, ctx); return result; } private XtendBackendFacade (String xtendFileName, String fileEncoding, Collection<MetaModel> mms) { if (mms == null) mms = new ArrayList<MetaModel> (); _xtendFile = OldHelper.normalizeXtendResourceName (xtendFileName); _mms = mms; if (MiddleEndFactory.canCreateFromExtentions()) { _middleEnd = MiddleEndFactory.createFromExtensions (OldHelper.guessTypesystem (mms), getSpecificParameters (fileEncoding, mms)); } else { _middleEnd = MiddleEndFactory.create (OldHelper.guessTypesystem (mms), LanguageContributor.INSTANCE.getFreshMiddleEnds (getSpecificParameters (fileEncoding, mms))); } } public FunctionDefContext getFunctionDefContext () { return _middleEnd.getFunctions (_xtendFile); } }