package org.openquark.cal.internal.machine.g.functions;
import java.util.NoSuchElementException;
import org.openquark.cal.internal.machine.g.Executor;
import org.openquark.cal.internal.machine.g.NConstr2;
import org.openquark.cal.internal.machine.g.NRecordValue;
import org.openquark.cal.internal.machine.g.Node;
import org.openquark.cal.runtime.CALExecutorException;
/**
* This class is used by the BuildList and BuildRecord primitive functions
* to extract values from lists and records.
*
* @author mbyne
*/
public abstract class RecordParamHelper {
private static class TupleParam extends RecordParamHelper {
int current;
NRecordValue tuple;
TupleParam(Node tuple) {
current = 0;
this.tuple = (NRecordValue) tuple;
}
Node getNext(Executor $ec) throws CALExecutorException {
return tuple.fieldValues().get(current++);
}
}
/**
* This class is used for extracting parameter values from a list
* @author mbyne
*/
private static class ListParam extends RecordParamHelper {
private Node calListValue;
ListParam(Node list) {
calListValue = list;
}
Node getNext(Executor $ec) throws CALExecutorException {
Node listItem; // this is the item used to generate the record
// value
calListValue = $ec.internalEvaluate(calListValue);
switch (calListValue.getOrdinalValue()) {
case 0: {
// Prelude.Nil
throw new NoSuchElementException();
}
case 1: {
// Prelude.Cons
NConstr2 listCons = (NConstr2) calListValue;
listItem = $ec.internalEvaluate(listCons.getN0());
calListValue = listCons.getN1();
break;
}
default: {
throw new IndexOutOfBoundsException();
}
}
return listItem;
}
}
abstract Node getNext(Executor $ec) throws CALExecutorException;
static RecordParamHelper create(Node v, Executor $ec) throws CALExecutorException {
v = $ec.internalEvaluate(v);
if (v instanceof NRecordValue) {
return new TupleParam(v);
} else {
return new ListParam(v);
}
}
}