/*
Copyright (c) 2008 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.backend.expr;
import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.SOURCE_POS;
import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyExecutionContext;
import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyFdc;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.xtend.backend.BackendFacade;
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.common.NamedFunction;
import org.eclipse.xtend.backend.common.QualifiedName;
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.ObjectType;
import org.eclipse.xtend.backend.types.builtin.StringType;
import org.junit.Test;
/**
*
* @author Arno Haase (http://www.haase-consulting.com)
* @author Andr� Arnold
*/
public class InitClosureExpressionTest {
/**
* test that the newly initialized closure actually has the correct number and type of parameters, and correctly binds the values to the right
* local variables in its body.
*/
@Test public void testParameterBinding () {
final List<String> paramNames = Arrays.asList("a");
final List<StringType> paramTypes = Arrays.asList(StringType.INSTANCE);
final LocalVarEvalExpression body = new LocalVarEvalExpression ("a", SOURCE_POS);
final Function closure = (Function) new InitClosureExpression (paramNames, paramTypes, body, SOURCE_POS).evaluate (createEmptyExecutionContext());
assertEquals (1, closure.getParameterTypes().size());
assertEquals (StringType.INSTANCE, closure.getParameterTypes().get(0));
assertEquals ("xyz", closure.invoke(createEmptyExecutionContext(), new Object[] {"xyz"}));
assertEquals ("abc", closure.invoke(createEmptyExecutionContext(), new Object[] {"abc"}));
}
/**
* test that local variables that were in scope during the initialization of a closure are visible during its execution, even if that is in an
* entirely different scope.
*/
@Test public void testLocalVariableBinding () {
final ExecutionContext initContext = createEmptyExecutionContext();
initContext.getLocalVarContext().getLocalVars().put ("a", "aValue");
final LocalVarEvalExpression body = new LocalVarEvalExpression ("a", SOURCE_POS);
final Function closure = (Function) new InitClosureExpression (new ArrayList<String>(), new ArrayList<BackendType>(), body, SOURCE_POS).evaluate (initContext);
assertEquals ("aValue", closure.invoke (createEmptyExecutionContext(), new Object[] {}));
}
/**
* test that functions visible during the initialization of a closure are callable in a different context where they are no longer in scope.
*/
@Test public void testFdcPropagation () {
final BackendTypesystem ts = new CompositeTypesystem ();
final FunctionDefContextInternal fdc = createEmptyFdc (ts);
fdc.register (new NamedFunction (new QualifiedName ("myFunction"), new AbstractFunction (null, new ArrayList<BackendType> (), ObjectType.INSTANCE, false) {
public Object invoke (ExecutionContext ctx, Object[] params) {
return "myResult";
}
}), true);
final ExecutionContext initCtx = BackendFacade.createExecutionContext (fdc, ts, true);
final ExpressionBase body = new InvocationOnObjectExpression (new QualifiedName ("myFunction"), new ArrayList<ExpressionBase> (), false, SOURCE_POS);
final Function closure = (Function) new InitClosureExpression (new ArrayList<String>(), new ArrayList<BackendType>(), body, SOURCE_POS).evaluate (initCtx);
assertEquals ("myResult", closure.invoke(createEmptyExecutionContext(), new Object[]{}));
}
}