(call *ast.CallExpr, name string, args []sem.Expr, argTypes []super.Type, inType super.Type)
| 759 | } |
| 760 | |
| 761 | func (t *translator) semCallByName(call *ast.CallExpr, name string, args []sem.Expr, argTypes []super.Type, inType super.Type) (sem.Expr, super.Type) { |
| 762 | if subquery, typ := t.maybeSubqueryCall(call, name, inType); subquery != nil { |
| 763 | return subquery, typ |
| 764 | } |
| 765 | // Check if the name resolves to a symbol in scope. |
| 766 | if entry := t.scope.lookupEntry(name); entry != nil { |
| 767 | switch ref := entry.ref.(type) { |
| 768 | case funcParamValue: |
| 769 | t.error(call, fmt.Errorf("function called via parameter %q is bound to a non-function", name)) |
| 770 | return badExpr, t.checker.unknown |
| 771 | case *funcParamLambda: |
| 772 | // Called name is a parameter inside of a function. We only end up here |
| 773 | // when actual values have been bound to the parameter (i.e., we're compiling |
| 774 | // a lambda-variant function each time it is called to create each variant), |
| 775 | // so we call the resolver here to create a new instance of the function being |
| 776 | // called. In the case of recursion, all the lambdas that are further passed |
| 777 | // as args are known (in terms of their decl IDs), so the resolver can |
| 778 | // look this up in the variants of the decl and stop the recursion even if the body |
| 779 | // of the called entity is not completed yet. We won't know the type but we |
| 780 | // can't know the type without function type signatures so when we integrate |
| 781 | // type checking here, we will use unknown for this corner case. |
| 782 | if isBuiltin(ref.id) { |
| 783 | // Check argument count here for builtin functions. |
| 784 | if _, err := function.New(super.NewContext(), ref.id, len(args)); err != nil { |
| 785 | t.error(call, fmt.Errorf("function %q called via parameter %q: %w", ref.id, ref.param, err)) |
| 786 | return badExpr, t.checker.unknown |
| 787 | } |
| 788 | return sem.NewCall(call, ref.id, args), t.checker.unknown //XXX type check call |
| 789 | } |
| 790 | return t.resolver.mustResolveCall(call, ref.id, args, argTypes) |
| 791 | case *opDecl: |
| 792 | t.error(call, fmt.Errorf("cannot call user operator %q in an expression (consider subquery syntax)", name)) |
| 793 | return badExpr, t.checker.unknown |
| 794 | case *sem.FuncRef: |
| 795 | // FuncRefs are put in the symbol table when passing stuff to user ops, e.g., |
| 796 | // a lambda as a parameter, a &func, or a builtin like &upper. |
| 797 | return t.resolver.mustResolveCall(ref, ref.ID, args, argTypes) |
| 798 | case *funcDecl: |
| 799 | return t.resolver.mustResolveCall(call, ref.id, args, argTypes) |
| 800 | case *constDecl, *queryDecl: |
| 801 | t.error(call, fmt.Errorf("%q is not a function", name)) |
| 802 | return badExpr, t.checker.unknown |
| 803 | case thunk: |
| 804 | // We're calling a function that is a user-operator parameter. |
| 805 | // It must be bound to a function. |
| 806 | f, _ := t.resolveThunk(ref, inType) |
| 807 | funcRef, ok := f.(*sem.FuncRef) |
| 808 | if !ok { |
| 809 | t.error(call, fmt.Errorf("function called via parameter %q is not a function", name)) |
| 810 | return badExpr, t.checker.unknown |
| 811 | } |
| 812 | return t.resolver.mustResolveCall(call, funcRef.ID, args, argTypes) |
| 813 | |
| 814 | } |
| 815 | if _, ok := entry.ref.(sem.Expr); ok { |
| 816 | t.error(call, fmt.Errorf("%q is not a function", name)) |
| 817 | return badExpr, t.checker.unknown |
| 818 | } |
no test coverage detected