@Override public Type getKeywordArgumentTypes(Environment scope) { ArrayList<String> labels = new ArrayList<>(); ArrayList<Type> types = new ArrayList<>(); // TODO: I am not sure this is what we want. Double names will end up twice in the tuple type... for (AbstractFunction c : primaryCandidates) { Type args = c.getKeywordArgumentTypes(scope); if (args != null && args.hasFieldNames()) { for (String label : args.getFieldNames()) { labels.add(label); types.add(args.getFieldType(label)); } } } for (AbstractFunction c : defaultCandidates) { Type args = c.getKeywordArgumentTypes(scope); if (args != null && args.hasFieldNames()) { for (String label : args.getFieldNames()) { labels.add(label); types.add(args.getFieldType(label)); } } } return TF.tupleType( types.toArray(new Type[types.size()]), labels.toArray(new String[labels.size()])); }
public Element compute(Element parameter) { for (AbstractFunction fn : fns) { if (Element.pfalse.equals(fn.compute(parameter))) return Element.pfalse; } return Element.ptrue; }
public List<AbstractFunction> getTests() { List<AbstractFunction> result = new LinkedList<AbstractFunction>(); for (AbstractFunction f : getFunctions()) { if (f.isTest()) { result.add(f); } } return result; }
@Override public String toString() { StringBuilder b = new StringBuilder(); for (AbstractFunction l : primaryCandidates) { b.append(l.toString()); b.append(' '); } for (AbstractFunction l : defaultCandidates) { b.append(l.toString()); b.append(' '); } return b.toString(); }
@Override public OverloadedFunction cloneInto(Environment env) { List<AbstractFunction> newCandidates = new ArrayList<>(); for (AbstractFunction f : primaryCandidates) { newCandidates.add((AbstractFunction) f.cloneInto(env)); } List<AbstractFunction> newDefaultCandidates = new ArrayList<>(); for (AbstractFunction f : defaultCandidates) { newDefaultCandidates.add((AbstractFunction) f.cloneInto(env)); } OverloadedFunction of = new OverloadedFunction(name, getType(), newCandidates, newDefaultCandidates, isStatic, ctx); of.setPublic(isPublic()); return of; }
public OverloadedFunction(AbstractFunction function) { super(function.getType(), null, function.getEval()); this.name = function.getName(); this.primaryCandidates = new ArrayList<AbstractFunction>(1); this.defaultCandidates = new ArrayList<AbstractFunction>(1); if (function.isDefault()) { defaultCandidates.add(function); } else { primaryCandidates.add(function); } this.isStatic = function.isStatic(); }
public OverloadedFunction add(AbstractFunction candidate) { List<AbstractFunction> joined = new ArrayList<AbstractFunction>(primaryCandidates.size() + 1); joined.addAll(primaryCandidates); List<AbstractFunction> defJoined = new ArrayList<AbstractFunction>(defaultCandidates.size() + 1); defJoined.addAll(defaultCandidates); if (candidate.isDefault() && !defJoined.contains(candidate)) { defJoined.add(candidate); } else if (!candidate.isDefault() && !joined.contains(candidate)) { joined.add(candidate); } return new OverloadedFunction( "(" + name + "+" + candidate.getName() + ")", lub(joined).lub(lub(defJoined)), joined, defJoined, ctx); }
private static Result<IValue> callWith( List<AbstractFunction> candidates, Type[] argTypes, IValue[] argValues, Map<String, IValue> keyArgValues, boolean mustSucceed) { AbstractFunction failed = null; Failure failure = null; for (AbstractFunction candidate : candidates) { if ((candidate.hasVarArgs() && argValues.length >= candidate.getArity() - 1) || candidate.getArity() == argValues.length || candidate.hasKeywordArguments()) { try { return candidate.call(argTypes, argValues, keyArgValues); } catch (MatchFailed m) { // could happen if pattern dispatched } catch (Failure e) { failed = candidate; failure = e; // could happen if function body throws fail } } } if (failed != null && mustSucceed) { throw new UnguardedFail(failed.ast, failure); } return null; }
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); }
/** * This function groups occurrences of pattern dispatched functions as one "PatternFunction" that * has a hash table to look up based on outermost function symbol. A group is a bunch of functions * that have an ADT as a first parameter type and a call or tree pattern with a fixed name as the * first parameter pattern, or it is a singleton other case. The addAll function retains the order * of the functions from the candidates list, in order to preserve shadowing rules! */ private void addAll( List<AbstractFunction> container, List<AbstractFunction> candidates, boolean nonDefault) { @SuppressWarnings("unchecked") Map<String, List<AbstractFunction>>[] constructors = new Map[10]; @SuppressWarnings("unchecked") Map<IConstructor, List<AbstractFunction>>[] productions = new Map[10]; List<AbstractFunction> other = new LinkedList<AbstractFunction>(); for (AbstractFunction func : candidates) { if (nonDefault && func.isDefault()) { continue; } if (!nonDefault && !func.isDefault()) { continue; } String label = null; IConstructor prod = null; if (func.isPatternDispatched()) { // this one is already hashed, but we might find more to add to that map in the next round Map<String, List<AbstractFunction>> funcMap = ((AbstractPatternDispatchedFunction) func).getMap(); int pos = func.getIndexedArgumentPosition(); for (String key : funcMap.keySet()) { addFuncsToMap(pos, constructors, funcMap.get(key), key); } } else if (func.isConcretePatternDispatched()) { // this one is already hashed, but we might find more to add to that map in the next round Map<IConstructor, List<AbstractFunction>> funcMap = ((ConcretePatternDispatchedFunction) func).getMap(); int pos = func.getIndexedArgumentPosition(); for (IConstructor key : funcMap.keySet()) { addProdsToMap(pos, productions, funcMap.get(key), key); } } else { // a new function definition, that may be hashable int pos = func.getIndexedArgumentPosition(); label = func.getIndexedLabel(); prod = func.getIndexedProduction(); if (label != null) { // we found another one to hash addFuncToMap(pos, constructors, func, label); } else if (prod != null) { addProdToMap(pos, productions, func, prod); } else { other.add(func); } } } for (int i = 0; i < constructors.length; i++) { if (constructors[i] != null && !constructors[i].isEmpty()) { container.add( new AbstractPatternDispatchedFunction( ctx.getEvaluator(), i, name, type, constructors[i])); } } for (int i = 0; i < productions.length; i++) { if (productions[i] != null && !productions[i].isEmpty()) { container.add( new ConcretePatternDispatchedFunction( ctx.getEvaluator(), i, name, type, productions[i])); } } container.addAll(other); }
public static void addOrReplaceFunction(AbstractFunction fun) { // We shouldn't get there unless that function don't exist removeFunction(fun.name(), fun.argTypes()); declare(fun); }
@Override protected void initAttrs(Element element) throws ParseException { super.initAttrs(element); this.inputField = super.getAttr(Constants.ATTR_INPUT); }