private static Type lub(List<AbstractFunction> candidates) { Set<FunctionType> alternatives = new HashSet<FunctionType>(); Iterator<AbstractFunction> iter = candidates.iterator(); if (!iter.hasNext()) { return TF.voidType(); } FunctionType first = iter.next().getFunctionType(); Type returnType = first.getReturnType(); alternatives.add(first); AbstractFunction l = null; while (iter.hasNext()) { l = iter.next(); if (l.getFunctionType().getReturnType() == returnType) { alternatives.add(l.getFunctionType()); } else { return TF.valueType(); } } return RascalTypeFactory.getInstance().overloadedFunctionType(alternatives); }
public class RelationalFunctionsOnList { protected static final TypeFactory typeFactory = TypeFactory.getInstance(); protected static final Type voidType = typeFactory.voidType(); public static int arity(IList rel) { return rel.getElementType().getArity(); } public static IList carrier(IList rel1) { Type newType = rel1.getType().carrier(); IListWriter w = List.createListWriter(newType.getElementType()); HashSet<IValue> cache = new HashSet<>(); for (IValue v : rel1) { ITuple t = (ITuple) v; for (IValue e : t) { if (!cache.contains(e)) { cache.add(e); w.append(e); } } } return w.done(); } public static IList domain(IList rel1) { Type lrelType = rel1.getType(); IListWriter w = List.createListWriter(lrelType.getFieldType(0)); HashSet<IValue> cache = new HashSet<>(); for (IValue elem : rel1) { ITuple tuple = (ITuple) elem; IValue e = tuple.get(0); if (!cache.contains(e)) { cache.add(e); w.append(e); } } return w.done(); } public static IList range(IList rel1) { Type lrelType = rel1.getType(); int last = lrelType.getArity() - 1; IListWriter w = List.createListWriter(lrelType.getFieldType(last)); HashSet<IValue> cache = new HashSet<>(); for (IValue elem : rel1) { ITuple tuple = (ITuple) elem; IValue e = tuple.get(last); if (!cache.contains(e)) { cache.add(e); w.append(e); } } return w.done(); } public static IList compose(IList rel1, IList rel2) { Type otherTupleType = rel2.getType().getFieldTypes(); if (rel1.getElementType() == voidType) return rel1; if (otherTupleType == voidType) return rel2; if (rel1.getElementType().getArity() != 2 || otherTupleType.getArity() != 2) throw new IllegalOperationException("compose", rel1.getElementType(), otherTupleType); // Relaxed type constraint: if (!rel1.getElementType().getFieldType(1).comparable(otherTupleType.getFieldType(0))) throw new IllegalOperationException("compose", rel1.getElementType(), otherTupleType); Type[] newTupleFieldTypes = new Type[] {rel1.getElementType().getFieldType(0), otherTupleType.getFieldType(1)}; Type tupleType = typeFactory.tupleType(newTupleFieldTypes); IListWriter w = new ListWriter(tupleType); for (IValue v1 : rel1) { ITuple tuple1 = (ITuple) v1; for (IValue t2 : rel2) { ITuple tuple2 = (ITuple) t2; if (tuple1.get(1).isEqual(tuple2.get(0))) { w.append(Tuple.newTuple(tuple1.get(0), tuple2.get(1))); } } } return w.done(); } public static IList closure(IList rel1) { Type resultType = rel1.getType().closure(); // will throw exception if not binary and reflexive IList tmp = rel1; int prevCount = 0; ShareableValuesHashSet addedTuples = new ShareableValuesHashSet(); while (prevCount != tmp.length()) { prevCount = tmp.length(); IList tcomp = compose(tmp, tmp); IListWriter w = List.createListWriter(resultType.getElementType()); for (IValue t1 : tcomp) { if (!tmp.contains(t1)) { if (!addedTuples.contains(t1)) { addedTuples.add(t1); w.append(t1); } } } tmp = tmp.concat(w.done()); addedTuples.clear(); } return tmp; } public static IList closureStar(IList rel1) { Type resultType = rel1.getType().closure(); // an exception will have been thrown if the type is not acceptable IListWriter reflex = List.createListWriter(resultType.getElementType()); for (IValue e : carrier(rel1)) { reflex.insert(Tuple.newTuple(new IValue[] {e, e})); } return closure(rel1).concat(reflex.done()); } public static IList project(IList rel1, int... fields) { IListWriter w = ValueFactory.getInstance().listWriter(); for (IValue v : rel1) { w.append(((ITuple) v).select(fields)); } return w.done(); } public static IList projectByFieldNames(IList rel1, String... fields) { int[] indexes = new int[fields.length]; int i = 0; if (rel1.getType().getFieldTypes().hasFieldNames()) { for (String field : fields) { indexes[i++] = rel1.getType().getFieldTypes().getFieldIndex(field); } return project(rel1, indexes); } throw new IllegalOperationException("select with field names", rel1.getType()); } }