blob: 4bbd19432455a0e8b80daf3247fafd3d59ea08b2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 Cloudsmith Inc. 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
*
* Contributors:
* Cloudsmith Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ql;
/**
* A function that executes some code
*/
public final class LambdaExpression extends Unary {
private final Expression[] currying;
private final Variable[] variables;
public LambdaExpression(Expression body, Expression[] currying, Variable[] variables) {
super(body);
int idx = currying.length;
if (idx > 0) {
if (idx != variables.length)
throw new IllegalArgumentException("Number of currying expressions and variables differ"); //$NON-NLS-1$
int anyCount = 0;
while (--idx >= 0)
if (currying[idx] instanceof EachVariable)
++anyCount;
if (anyCount != 1)
throw new IllegalArgumentException("Exaclty one _ must be present among the currying expressions"); //$NON-NLS-1$
} else if (variables.length != 1)
throw new IllegalArgumentException("Exaclty one variable required unless currying is used"); //$NON-NLS-1$
this.currying = currying;
this.variables = variables;
}
public LambdaExpression(Expression body, Variable variable) {
this(body, Expression.emptyArray, new Variable[] {variable});
}
public boolean accept(Visitor visitor) {
if (super.accept(visitor)) {
for (int idx = 0; idx < currying.length; ++idx)
if (!currying[idx].accept(visitor))
return false;
for (int idx = 0; idx < variables.length; ++idx)
if (!variables[idx].accept(visitor))
return false;
}
return true;
}
public void toString(StringBuffer bld) {
int top = currying.length;
if (top > 0) {
Array.elementsToString(bld, currying);
bld.append(", {"); //$NON-NLS-1$
}
Array.elementsToString(bld, variables);
bld.append(" | "); //$NON-NLS-1$
appendOperand(bld, operand, ExpressionParser.PRIORITY_COMMA);
if (top > 0)
bld.append('}');
}
int countReferenceToEverything() {
if (super.countReferenceToEverything() > 0)
return 2;
for (int idx = 0; idx < currying.length; ++idx)
if (currying[idx].countReferenceToEverything() > 0)
return 2;
for (int idx = 0; idx < variables.length; ++idx)
if (variables[idx].countReferenceToEverything() > 0)
return 2;
return 0;
}
EachVariable getItemVariable() {
int idx = currying.length;
if (idx == 0)
// No currying. Then we know that we have exactly one variable
return (EachVariable) variables[0];
while (--idx >= 0) {
Expression expr = currying[idx];
if (expr instanceof EachVariable)
return (EachVariable) variables[idx];
}
return null;
}
String getOperator() {
return "|"; //$NON-NLS-1$
}
int getPriority() {
return ExpressionParser.PRIORITY_LAMBDA;
}
VariableScope prolog(ExpressionContext context, VariableScope scope) {
if (currying.length == 0)
scope = new SingleVariableScope(scope, variables[0]);
else {
VariableScope lambdaScope = new MultiVariableScope(scope, variables);
for (int idx = 0; idx < currying.length; ++idx) {
Expression curry = currying[idx];
if (!(curry instanceof EachVariable))
variables[idx].setValue(lambdaScope, curry.evaluate(context, scope));
}
scope = lambdaScope;
}
return scope;
}
}