public FunDef getDef(Exp[] args, String funName, Syntax syntax) { // Compute signature first. It makes debugging easier. final String signature = syntax.getSignature(funName, Category.Unknown, ExpBase.getTypes(args)); // Resolve function by its upper-case name first. If there is only one // function with that name, stop immediately. If there is more than // function, use some custom method, which generally involves looking // at the type of one of its arguments. List<Resolver> resolvers = funTable.getResolvers(funName, syntax); assert resolvers != null; final List<Resolver.Conversion> conversionList = new ArrayList<Resolver.Conversion>(); int minConversionCost = Integer.MAX_VALUE; List<FunDef> matchDefs = new ArrayList<FunDef>(); List<Resolver.Conversion> matchConversionList = null; for (Resolver resolver : resolvers) { conversionList.clear(); FunDef def = resolver.resolve(args, this, conversionList); if (def != null) { int conversionCost = sumConversionCost(conversionList); if (conversionCost < minConversionCost) { minConversionCost = conversionCost; matchDefs.clear(); matchDefs.add(def); matchConversionList = new ArrayList<Resolver.Conversion>(conversionList); } else if (conversionCost == minConversionCost) { matchDefs.add(def); } else { // ignore this match -- it required more coercions than // other overloadings we've seen } } } switch (matchDefs.size()) { case 0: throw MondrianResource.instance().NoFunctionMatchesSignature.ex(signature); case 1: break; default: final StringBuilder buf = new StringBuilder(); for (FunDef matchDef : matchDefs) { if (buf.length() > 0) { buf.append(", "); } buf.append(matchDef.getSignature()); } throw MondrianResource.instance() .MoreThanOneFunctionMatchesSignature .ex(signature, buf.toString()); } final FunDef matchDef = matchDefs.get(0); for (Resolver.Conversion conversion : matchConversionList) { conversion.checkValid(); conversion.apply(this, Arrays.asList(args)); } return matchDef; }
private boolean requiresExpression(int n) { if (n < 1) { return false; } final Object parent = stack.get(n - 1); if (parent instanceof Formula) { return ((Formula) parent).isMember(); } else if (parent instanceof ResolvedFunCall) { final ResolvedFunCall funCall = (ResolvedFunCall) parent; if (funCall.getFunDef().getSyntax() == Syntax.Parentheses) { return requiresExpression(n - 1); } else { int k = whichArg(funCall, (Exp) stack.get(n)); if (k < 0) { // Arguments of call have mutated since call was placed // on stack. Presumably the call has already been // resolved correctly, so the answer we give here is // irrelevant. return false; } final FunDef funDef = funCall.getFunDef(); final int[] parameterTypes = funDef.getParameterCategories(); return parameterTypes[k] != Category.Set; } } else if (parent instanceof UnresolvedFunCall) { final UnresolvedFunCall funCall = (UnresolvedFunCall) parent; if (funCall.getSyntax() == Syntax.Parentheses || funCall.getFunName().equals("*")) { return requiresExpression(n - 1); } else { int k = whichArg(funCall, (Exp) stack.get(n)); if (k < 0) { // Arguments of call have mutated since call was placed // on stack. Presumably the call has already been // resolved correctly, so the answer we give here is // irrelevant. return false; } return requiresExpression(funCall, k); } } else { return false; } }