package com.sap.runlet.interpreter.expressions;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import behavioral.actions.Iterator;
import behavioral.actions.Statement;
import com.sap.runlet.abstractinterpreter.Interpreter;
import com.sap.runlet.abstractinterpreter.objects.EmptyObject;
import com.sap.runlet.abstractinterpreter.objects.RunletObject;
import com.sap.runlet.interpreter.RunletInterpreter;
import com.sap.runlet.interpreter.RunletStackFrame;
import data.classes.Association;
import data.classes.AssociationEnd;
import data.classes.ClassTypeDefinition;
import data.classes.NativeImpl;
import data.classes.SapClass;
import data.classes.SignatureImplementation;
import data.classes.TypeDefinition;
import dataaccess.expressions.Expression;
import dataaccess.expressions.collectionexpressions.Iterate;
public class IterateInterpreter implements Interpreter<Iterate, SapClass, TypeDefinition, ClassTypeDefinition, Association, AssociationEnd, Statement, Expression, SignatureImplementation, RunletStackFrame, NativeImpl, RunletInterpreter> {
private Iterate iterate;
public IterateInterpreter(Iterate iterate) {
this.iterate = iterate;
}
@Override
public RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> evaluate(RunletInterpreter interpreter)
throws SecurityException, IllegalArgumentException, NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException {
RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> source = interpreter.evaluate(iterate.getSource());
RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> acc = null;
if (iterate.getAccumulator() != null && iterate.getAccumulator().getInitExpression() != null) {
acc = interpreter.evaluate(iterate.getAccumulator().getInitExpression());
} else {
// no accumulator or no init expression provided;
// use EmptyObject as accumulator value
acc = new EmptyObject<AssociationEnd, SapClass, TypeDefinition, ClassTypeDefinition>(
iterate.getIteratorExpression().getType(), interpreter.getModelAdapter());
}
behavioral.actions.Iterator[] iterators = new behavioral.actions.Iterator[iterate.getIterators().size()];
int i = 0;
for (behavioral.actions.Iterator iterator : iterate.getIterators()) {
iterators[i++] = iterator;
}
Map<behavioral.actions.Iterator, RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> iteratorValues =
new HashMap<Iterator, RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>>();
return iterate(interpreter, iterators, 0, source, acc, iteratorValues);
}
private RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> iterate(RunletInterpreter interpreter,
behavioral.actions.Iterator[] iterators, int iteratorIndex,
RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> source,
RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> acc,
Map<behavioral.actions.Iterator, RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition>> iteratorValues)
throws SecurityException, IllegalArgumentException, NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException {
behavioral.actions.Iterator iter = iterators[iteratorIndex];
for (RunletObject<AssociationEnd, TypeDefinition, ClassTypeDefinition> sourceElement : source.flatten()) {
iteratorValues.put(iter, sourceElement);
if (iteratorIndex < iterators.length - 1) {
acc = iterate(interpreter, iterators, iteratorIndex + 1, source, acc, iteratorValues);
} else {
// innermost iterator; perform one "step"
RunletStackFrame stackFrame =
new RunletStackFrame(interpreter.getCallstack().peek());
stackFrame.enterValue(iterate.getAccumulator(), acc);
for (behavioral.actions.Iterator iterator : iteratorValues.keySet()) {
stackFrame.enterValue(iterator, iteratorValues.get(iterator));
}
interpreter.push(stackFrame);
acc = interpreter.evaluate(iterate.getIteratorExpression());
interpreter.pop();
}
}
return acc;
}
}