/******************************************************************************* * Copyright (c) 2011 Andr� Arnold and others. * 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 *******************************************************************************/ package org.eclipse.xtend.backend.lib; import java.util.List; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.LocalVarContext; import org.eclipse.xtend.backend.functions.AbstractFunction; /** * @author Andr� Arnold - Initial contribution and API */ public abstract class AbstractClosure extends AbstractFunction { private final LocalVarContext _lvcAtDefinitionTime; private final FunctionDefContext _fdcAtDefinitionTime; private final List<String> _paramNames; public AbstractClosure (LocalVarContext lvcAtDefinitionTime, FunctionDefContext fdcAtDefinitionTime, List<String> paramNames, List<? extends BackendType> paramTypes) { super (null, paramTypes, null, 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; } public Object invoke (ExecutionContext ctx, Object[] params) { if (_fdcAtDefinitionTime == ctx.getFunctionDefContext()) return invokeWithExistingFdc (ctx, params); else { final FunctionDefContext oldFdc = ctx.getFunctionDefContext (); try { ctx.setFunctionDefContext (_fdcAtDefinitionTime); return invokeWithExistingFdc(ctx, params); } finally { ctx.setFunctionDefContext (oldFdc); } } } protected abstract Object apply (ExecutionContext ctx); private Object invokeWithExistingFdc (ExecutionContext ctx, Object... params) { // potential local variables that are hidden by parameters are not restored - but they will never be visible anyway final LocalVarContext lvc = _lvcAtDefinitionTime; for (int i=0; i<_paramNames.size(); i++) { lvc.getLocalVars().put(_paramNames.get(i), params[i]); } final LocalVarContext oldLvc = ctx.getLocalVarContext(); try { ctx.setLocalVarContext(lvc); return apply (ctx); } finally { ctx.setLocalVarContext(oldLvc); } } @Override public void setFunctionDefContext (FunctionDefContext fdc) { throw new UnsupportedOperationException (); } @Override public FunctionDefContext getFunctionDefContext () { return _fdcAtDefinitionTime; } @Override public BackendType getReturnType () { throw new UnsupportedOperationException (); } }