package org.openquark.cal.internal.runtime.lecc.functions;
import java.util.NoSuchElementException;
import org.openquark.cal.internal.runtime.lecc.RTCons;
import org.openquark.cal.internal.runtime.lecc.RTExecutionContext;
import org.openquark.cal.internal.runtime.lecc.RTRecordValue;
import org.openquark.cal.internal.runtime.lecc.RTValue;
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;
RTRecordValue tuple;
TupleParam(RTValue tuple) {
current = 0;
this.tuple = (RTRecordValue) tuple;
}
RTValue getNext(RTExecutionContext $ec) throws CALExecutorException {
return tuple.getNthValue(current++);
}
}
/**
* This class is used for extracting parameter values from a list
* @author mbyne
*/
private static class ListParam extends RecordParamHelper {
private RTValue calListValue;
ListParam(RTValue list) {
calListValue = list;
}
RTValue getNext(RTExecutionContext $ec) throws CALExecutorException {
RTValue listItem; // this is the item used to generate the record
// value
calListValue = calListValue.evaluate($ec);
switch (calListValue.getOrdinalValue()) {
case 0: {
// Prelude.Nil
throw new NoSuchElementException();
}
case 1: {
// Prelude.Cons
RTCons listCons = (RTCons) calListValue;
listItem = listCons.getFieldByIndex(1, 0, null);
calListValue = listCons.getFieldByIndex(1, 1, null);
listItem.evaluate($ec);
break;
}
default: {
throw new IndexOutOfBoundsException();
}
}
return listItem;
}
}
abstract RTValue getNext(RTExecutionContext $ec) throws CALExecutorException;
static RecordParamHelper create(RTValue v, RTExecutionContext $ec) throws CALExecutorException {
v = v.evaluate($ec);
if (v instanceof RTRecordValue) {
return new TupleParam(v);
} else {
return new ListParam(v);
}
}
}