Search in sources :

Example 6 with FunctionLibFunctionArg

use of lucee.transformer.library.function.FunctionLibFunctionArg in project Lucee by lucee.

the class VT method _writeOutFirstBIF.

static Type _writeOutFirstBIF(BytecodeContext bc, BIF bif, int mode, boolean last, Position line) throws TransformerException {
    double start = SystemUtil.millis();
    GeneratorAdapter adapter = bc.getAdapter();
    adapter.loadArg(0);
    // class
    ClassDefinition bifCD = bif.getClassDefinition();
    Class clazz = null;
    try {
        clazz = bifCD.getClazz();
    } catch (Exception e) {
        SystemOut.printDate(e);
    }
    Type rtnType = Types.toType(bif.getReturnType());
    if (rtnType == Types.VOID)
        rtnType = Types.STRING;
    // arguments
    Argument[] args = bif.getArguments();
    Type[] argTypes;
    // MUST setting this to false need to work !!!
    boolean core = bif.getFlf().isCore();
    if (bif.getArgType() == FunctionLibFunction.ARG_FIX && !bifCD.isBundle() && core) {
        if (isNamed(bif.getFlf().getName(), args)) {
            NamedArgument[] nargs = toNamedArguments(args);
            String[] names = new String[nargs.length];
            // get all names
            for (int i = 0; i < nargs.length; i++) {
                names[i] = getName(nargs[i].getName());
            }
            ArrayList<FunctionLibFunctionArg> list = bif.getFlf().getArg();
            Iterator<FunctionLibFunctionArg> it = list.iterator();
            argTypes = new Type[list.size() + 1];
            argTypes[0] = Types.PAGE_CONTEXT;
            FunctionLibFunctionArg flfa;
            int index = 0;
            VT vt;
            while (it.hasNext()) {
                flfa = it.next();
                vt = getMatchingValueAndType(bc.getFactory(), flfa, nargs, names, line);
                if (vt.index != -1)
                    names[vt.index] = null;
                argTypes[++index] = Types.toType(vt.type);
                if (vt.value == null)
                    ASMConstants.NULL(bc.getAdapter());
                else
                    vt.value.writeOut(bc, Types.isPrimitiveType(argTypes[index]) ? MODE_VALUE : MODE_REF);
            }
            for (int y = 0; y < names.length; y++) {
                if (names[y] != null) {
                    TransformerException bce = new TransformerException("argument [" + names[y] + "] is not allowed for function [" + bif.getFlf().getName() + "]", args[y].getStart());
                    UDFUtil.addFunctionDoc(bce, bif.getFlf());
                    throw bce;
                }
            }
        } else {
            argTypes = new Type[args.length + 1];
            argTypes[0] = Types.PAGE_CONTEXT;
            for (int y = 0; y < args.length; y++) {
                argTypes[y + 1] = Types.toType(args[y].getStringType());
                args[y].writeOutValue(bc, Types.isPrimitiveType(argTypes[y + 1]) ? MODE_VALUE : MODE_REF);
            }
            // if no method exists for the exact match of arguments, call the method with all arguments (when exists)
            if (methodExists(clazz, "call", argTypes, rtnType) == Boolean.FALSE) {
                ArrayList<FunctionLibFunctionArg> _args = bif.getFlf().getArg();
                Type[] tmp = new Type[_args.size() + 1];
                // fill the existing
                for (int i = 0; i < argTypes.length; i++) {
                    tmp[i] = argTypes[i];
                }
                // get the rest with default values
                FunctionLibFunctionArg flfa;
                VT def;
                for (int i = argTypes.length; i < tmp.length; i++) {
                    flfa = _args.get(i - 1);
                    tmp[i] = Types.toType(flfa.getTypeAsString());
                    def = getDefaultValue(bc.getFactory(), flfa);
                    if (def.value != null)
                        def.value.writeOut(bc, Types.isPrimitiveType(tmp[i]) ? MODE_VALUE : MODE_REF);
                    else
                        ASMConstants.NULL(bc.getAdapter());
                }
                argTypes = tmp;
            }
        }
    } else // Arg Type DYN or bundle based
    {
        // /////////////////////////////////////////////////////////////
        if (bif.getArgType() == FunctionLibFunction.ARG_FIX) {
            if (isNamed(bif.getFlf().getName(), args)) {
                NamedArgument[] nargs = toNamedArguments(args);
                String[] names = getNames(nargs);
                ArrayList<FunctionLibFunctionArg> list = bif.getFlf().getArg();
                Iterator<FunctionLibFunctionArg> it = list.iterator();
                LinkedList<Argument> tmpArgs = new LinkedList<Argument>();
                LinkedList<Boolean> nulls = new LinkedList<Boolean>();
                FunctionLibFunctionArg flfa;
                VT vt;
                while (it.hasNext()) {
                    flfa = it.next();
                    vt = getMatchingValueAndType(bc.getFactory(), flfa, nargs, names, line);
                    if (vt.index != -1)
                        names[vt.index] = null;
                    if (vt.value == null)
                        // has to by any otherwise a caster is set
                        tmpArgs.add(new Argument(bif.getFactory().createNull(), "any"));
                    else
                        tmpArgs.add(new Argument(vt.value, vt.type));
                    nulls.add(vt.value == null);
                }
                for (int y = 0; y < names.length; y++) {
                    if (names[y] != null) {
                        TransformerException bce = new TransformerException("argument [" + names[y] + "] is not allowed for function [" + bif.getFlf().getName() + "]", args[y].getStart());
                        UDFUtil.addFunctionDoc(bce, bif.getFlf());
                        throw bce;
                    }
                }
                // remove null at the end
                Boolean tmp;
                while ((tmp = nulls.pollLast()) != null) {
                    if (!tmp.booleanValue())
                        break;
                    tmpArgs.pollLast();
                }
                args = tmpArgs.toArray(new Argument[tmpArgs.size()]);
            }
        }
        // /////////////////////////////////////////////////////////////
        argTypes = new Type[2];
        argTypes[0] = Types.PAGE_CONTEXT;
        argTypes[1] = Types.OBJECT_ARRAY;
        ExpressionUtil.writeOutExpressionArray(bc, Types.OBJECT, args);
    }
    // core
    if (core && !bifCD.isBundle()) {
        adapter.invokeStatic(Type.getType(clazz), new Method("call", rtnType, argTypes));
    } else // external
    {
        // className
        if (bifCD.getClassName() != null)
            adapter.push(bifCD.getClassName());
        else
            ASMConstants.NULL(adapter);
        if (// bundle name
        bifCD.getName() != null)
            // bundle name
            adapter.push(bifCD.getName());
        else
            ASMConstants.NULL(adapter);
        if (// bundle version
        bifCD.getVersionAsString() != null)
            // bundle version
            adapter.push(bifCD.getVersionAsString());
        else
            ASMConstants.NULL(adapter);
        adapter.invokeStatic(Types.FUNCTION_HANDLER_POOL, INVOKE);
        rtnType = Types.OBJECT;
    }
    if (mode == MODE_REF || !last) {
        if (Types.isPrimitiveType(rtnType)) {
            adapter.invokeStatic(Types.CASTER, new Method("toRef", Types.toRefType(rtnType), new Type[] { rtnType }));
            rtnType = Types.toRefType(rtnType);
        }
    }
    return rtnType;
}
Also used : LitString(lucee.transformer.expression.literal.LitString) ExprString(lucee.transformer.expression.ExprString) ClassDefinition(lucee.runtime.db.ClassDefinition) FunctionLibFunctionArg(lucee.transformer.library.function.FunctionLibFunctionArg) TransformerException(lucee.transformer.TransformerException) Method(org.objectweb.asm.commons.Method) TransformerException(lucee.transformer.TransformerException) TemplateException(lucee.runtime.exp.TemplateException) LinkedList(java.util.LinkedList) Type(org.objectweb.asm.Type) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter)

Example 7 with FunctionLibFunctionArg

use of lucee.transformer.library.function.FunctionLibFunctionArg in project Lucee by lucee.

the class AbstrCFMLExprTransformer method getFunctionMember.

/**
 * Liest die Argumente eines Funktonsaufruf ein und prueft ob die Funktion
 * innerhalb der FLD (Function Library Descriptor) definiert ist.
 * Falls sie existiert wird die Funktion gegen diese geprueft und ein build-in-function CFXD Element generiert,
 * ansonsten ein normales funcion-call Element.
 * <br />
 * EBNF:<br />
 * <code>[impOp{"," impOp}];</code>
 * @param name Identifier der Funktion als Zeichenkette
 * @param checkLibrary Soll geprueft werden ob die Funktion innerhalb der Library existiert.
 * @return CFXD Element
 * @throws TemplateException
 */
private FunctionMember getFunctionMember(ExprData data, final ExprString name, boolean checkLibrary) throws TemplateException {
    // get Function Library
    checkLibrary = checkLibrary && data.flibs != null;
    FunctionLibFunction flf = null;
    if (checkLibrary) {
        if (!(name instanceof Literal))
            // should never happen!
            throw new TemplateException(data.srcCode, "syntax error");
        for (int i = 0; i < data.flibs.length; i++) {
            flf = data.flibs[i].getFunction(((Literal) name).getString());
            if (flf != null)
                break;
        }
        if (flf == null) {
            checkLibrary = false;
        }
    }
    FunctionMember fm = null;
    while (true) {
        int pos = data.srcCode.getPos();
        // Element Function
        if (checkLibrary) {
            BIF bif = new BIF(data.factory, data.settings, flf);
            // TODO data.ep.add(flf, bif, data.srcCode);
            bif.setArgType(flf.getArgType());
            try {
                bif.setClassDefinition(flf.getFunctionClassDefinition());
            } catch (Throwable t) {
                ExceptionUtil.rethrowIfNecessary(t);
                throw new PageRuntimeException(t);
            }
            bif.setReturnType(flf.getReturnTypeAsString());
            fm = bif;
            if (flf.getArgType() == FunctionLibFunction.ARG_DYNAMIC && flf.hasDefaultValues()) {
                ArrayList<FunctionLibFunctionArg> args = flf.getArg();
                Iterator<FunctionLibFunctionArg> it = args.iterator();
                FunctionLibFunctionArg arg;
                while (it.hasNext()) {
                    arg = it.next();
                    if (arg.getDefaultValue() != null)
                        bif.addArgument(new NamedArgument(data.factory.createLitString(arg.getName()), data.factory.createLitString(arg.getDefaultValue()), arg.getTypeAsString(), false));
                }
            }
        } else {
            fm = new UDF(name);
        }
        int count = getFunctionMemberAttrs(data, name, checkLibrary, fm, flf);
        if (checkLibrary) {
            // pre
            if (flf.hasTteClass()) {
                FunctionLibFunction tmp = flf.getEvaluator().pre((BIF) fm, flf);
                if (tmp != null && tmp != flf) {
                    flf = tmp;
                    data.srcCode.setPos(pos);
                    continue;
                }
            }
            // check max attributes
            {
                boolean isDynamic = flf.getArgType() == FunctionLibFunction.ARG_DYNAMIC;
                int max = flf.getArgMax();
                // Dynamic
                if (isDynamic) {
                    if (max != -1 && max < fm.getArguments().length)
                        throw new TemplateException(data.srcCode, "too many Attributes (" + max + ":" + fm.getArguments().length + ") in function [ " + ASMUtil.display(name) + " ]");
                } else // Fix
                {
                    if (flf.getArg().size() < fm.getArguments().length) {
                        TemplateException te = new TemplateException(data.srcCode, "too many Attributes (" + flf.getArg().size() + ":" + fm.getArguments().length + ") in function call [" + ASMUtil.display(name) + "]");
                        UDFUtil.addFunctionDoc(te, flf);
                        throw te;
                    }
                }
            }
            // check min attributes
            if (flf.getArgMin() > count) {
                TemplateException te = new TemplateException(data.srcCode, "too few attributes in function [" + ASMUtil.display(name) + "]");
                if (flf.getArgType() == FunctionLibFunction.ARG_FIX)
                    UDFUtil.addFunctionDoc(te, flf);
                throw te;
            }
            // evaluator
            if (flf.hasTteClass()) {
                flf.getEvaluator().execute((BIF) fm, flf);
            }
        }
        comments(data);
        if (checkLibrary)
            data.ep.add(flf, (BIF) fm, data.srcCode);
        break;
    }
    return fm;
}
Also used : TemplateException(lucee.runtime.exp.TemplateException) FunctionMember(lucee.transformer.bytecode.expression.var.FunctionMember) UDF(lucee.transformer.bytecode.expression.var.UDF) FunctionLibFunction(lucee.transformer.library.function.FunctionLibFunction) Literal(lucee.transformer.expression.literal.Literal) PageRuntimeException(lucee.runtime.exp.PageRuntimeException) NamedArgument(lucee.transformer.bytecode.expression.var.NamedArgument) BIF(lucee.transformer.bytecode.expression.var.BIF) FunctionLibFunctionArg(lucee.transformer.library.function.FunctionLibFunctionArg)

Example 8 with FunctionLibFunctionArg

use of lucee.transformer.library.function.FunctionLibFunctionArg in project Lucee by lucee.

the class CFMLExpressionInterpreter method functionArg.

/**
 * Liest die Argumente eines Funktonsaufruf ein und prueft ob die Funktion
 * innerhalb der FLD (Function Library Descriptor) definiert ist.
 * Falls sie existiert wird die Funktion gegen diese geprueft und ein build-in-function CFXD Element generiert,
 * ansonsten ein normales funcion-call Element.
 * <br />
 * EBNF:<br />
 * <code>[impOp{"," impOp}];</code>
 * @param name Identifier der Funktion als Zeichenkette
 * @param checkLibrary Soll geprueft werden ob die Funktion innerhalb der Library existiert.
 * @param flf FLD Function definition .
 * @return CFXD Element
 * @throws PageException
 */
private Ref[] functionArg(String name, boolean checkLibrary, FunctionLibFunction flf, char end) throws PageException {
    // get Function Library
    checkLibrary = checkLibrary && flf != null;
    // Function Attributes
    List<Ref> arr = new ArrayList<Ref>();
    List<FunctionLibFunctionArg> arrFuncLibAtt = null;
    int libLen = 0;
    if (checkLibrary) {
        arrFuncLibAtt = flf.getArg();
        libLen = arrFuncLibAtt.size();
    }
    int count = 0;
    Ref ref;
    do {
        cfml.next();
        cfml.removeSpace();
        // finish
        if (cfml.isCurrent(end))
            break;
        // too many Attributes
        boolean isDynamic = false;
        int max = -1;
        if (checkLibrary) {
            isDynamic = isDynamic(flf);
            max = flf.getArgMax();
            // Dynamic
            if (isDynamic) {
                if (max != -1 && max <= count)
                    throw new InterpreterException("too many Attributes in function [" + name + "]");
            } else // Fix
            {
                if (libLen <= count)
                    throw new InterpreterException("too many Attributes in function [" + name + "]");
            }
        }
        if (checkLibrary && !isDynamic) {
            // current attribues from library
            FunctionLibFunctionArg funcLibAtt = (FunctionLibFunctionArg) arrFuncLibAtt.get(count);
            short type = CFTypes.toShort(funcLibAtt.getTypeAsString(), false, CFTypes.TYPE_UNKNOW);
            if (type == CFTypes.TYPE_VARIABLE_STRING) {
                arr.add(functionArgDeclarationVarString());
            } else {
                ref = functionArgDeclaration();
                arr.add(new Casting(funcLibAtt.getTypeAsString(), type, ref));
            }
        } else {
            arr.add(functionArgDeclaration());
        }
        cfml.removeSpace();
        count++;
    } while (cfml.isCurrent(','));
    // end with ) ??
    if (!cfml.forwardIfCurrent(end)) {
        if (name.startsWith("_json"))
            throw new InterpreterException("Invalid Syntax Closing [" + end + "] not found");
        throw new InterpreterException("Invalid Syntax Closing [" + end + "] for function [" + name + "] not found");
    }
    // check min attributes
    if (checkLibrary && flf.getArgMin() > count)
        throw new InterpreterException("to less Attributes in function [" + name + "]");
    cfml.removeSpace();
    return (Ref[]) arr.toArray(new Ref[arr.size()]);
}
Also used : Casting(lucee.runtime.interpreter.ref.cast.Casting) Ref(lucee.runtime.interpreter.ref.Ref) ArrayList(java.util.ArrayList) FunctionLibFunctionArg(lucee.transformer.library.function.FunctionLibFunctionArg)

Example 9 with FunctionLibFunctionArg

use of lucee.transformer.library.function.FunctionLibFunctionArg in project Lucee by lucee.

the class GetFunctionData method cfmlBasedFunction.

private static Struct cfmlBasedFunction(PageContext pc, FunctionLibFunction function) throws PageException {
    Struct sct = new StructImpl();
    ArrayList<FunctionLibFunctionArg> args = function.getArg();
    String filename = Caster.toString(args.get(0).getDefaultValue());
    Key name = KeyImpl.toKey(args.get(1).getDefaultValue());
    boolean isWeb = Caster.toBooleanValue(args.get(2).getDefaultValue());
    UDF udf = CFFunction.loadUDF(pc, filename, name, isWeb);
    sct.set(KeyConstants._name, function.getName());
    sct.set(ARGUMENT_TYPE, "fixed");
    sct.set(KeyConstants._description, StringUtil.emptyIfNull(udf.getHint()));
    sct.set(RETURN_TYPE, StringUtil.emptyIfNull(udf.getReturnTypeAsString()));
    sct.set(KeyConstants._type, "cfml");
    sct.set(SOURCE, udf.getSource());
    sct.set(KeyConstants._status, "implemeted");
    FunctionArgument[] fas = udf.getFunctionArguments();
    Array _args = new ArrayImpl();
    sct.set(KeyConstants._arguments, _args);
    int min = 0, max = 0;
    for (int i = 0; i < fas.length; i++) {
        FunctionArgument fa = fas[i];
        Struct meta = fa.getMetaData();
        Struct _arg = new StructImpl();
        if (fa.isRequired())
            min++;
        max++;
        _arg.set(KeyConstants._required, fa.isRequired() ? Boolean.TRUE : Boolean.FALSE);
        _arg.set(KeyConstants._type, StringUtil.emptyIfNull(fa.getTypeAsString()));
        _arg.set(KeyConstants._name, StringUtil.emptyIfNull(fa.getName()));
        _arg.set(KeyConstants._description, StringUtil.emptyIfNull(fa.getHint()));
        String status;
        if (meta == null)
            status = "implemeted";
        else
            status = TagLibFactory.toStatus(TagLibFactory.toStatus(Caster.toString(meta.get(KeyConstants._status, "implemeted"))));
        _arg.set(KeyConstants._status, status);
        _args.append(_arg);
    }
    sct.set(ARG_MIN, Caster.toDouble(min));
    sct.set(ARG_MAX, Caster.toDouble(max));
    return sct;
}
Also used : ArrayImpl(lucee.runtime.type.ArrayImpl) Struct(lucee.runtime.type.Struct) Array(lucee.runtime.type.Array) StructImpl(lucee.runtime.type.StructImpl) UDF(lucee.runtime.type.UDF) FunctionArgument(lucee.runtime.type.FunctionArgument) FunctionLibFunctionArg(lucee.transformer.library.function.FunctionLibFunctionArg) Key(lucee.runtime.type.Collection.Key)

Example 10 with FunctionLibFunctionArg

use of lucee.transformer.library.function.FunctionLibFunctionArg in project Lucee by lucee.

the class MemberUtil method callWithNamedValues.

public static Object callWithNamedValues(PageContext pc, Object coll, Collection.Key methodName, Struct args, short type, String strType) throws PageException {
    Map<Key, FunctionLibFunction> members = getMembers(pc, type);
    FunctionLibFunction member = members.get(methodName);
    if (member != null) {
        List<FunctionLibFunctionArg> _args = member.getArg();
        FunctionLibFunctionArg arg;
        if (args.size() < _args.size()) {
            Object val;
            ArrayList<Ref> refs = new ArrayList<Ref>();
            arg = _args.get(0);
            refs.add(new Casting(arg.getTypeAsString(), arg.getType(), new LFunctionValue(new LString(arg.getName()), coll)));
            for (int y = 1; y < _args.size(); y++) {
                arg = _args.get(y);
                // match by name
                val = args.get(arg.getName(), null);
                // match by alias
                if (val == null) {
                    String alias = arg.getAlias();
                    if (!StringUtil.isEmpty(alias, true)) {
                        String[] aliases = lucee.runtime.type.util.ListUtil.trimItems(lucee.runtime.type.util.ListUtil.listToStringArray(alias, ','));
                        for (int x = 0; x < aliases.length; x++) {
                            val = args.get(aliases[x], null);
                            if (val != null)
                                break;
                        }
                    }
                }
                if (val == null) {
                    if (arg.getRequired()) {
                        String[] names = member.getMemberNames();
                        String n = ArrayUtil.isEmpty(names) ? "" : names[0];
                        throw new ExpressionException("missing required argument [" + arg.getName() + "] for member function call [" + n + "]");
                    }
                } else {
                    refs.add(new Casting(arg.getTypeAsString(), arg.getType(), new LFunctionValue(new LString(arg.getName()), val)));
                // refs.add(new LFunctionValue(new LString(arg.getName()),new Casting(pc,arg.getTypeAsString(),arg.getType(),val)));
                }
            }
            return new BIFCall(coll, member, refs.toArray(new Ref[refs.size()])).getValue(pc);
        }
    }
    throw new ExpressionException("No matching function member [" + methodName + "] for call with named arguments found, available function members are [" + lucee.runtime.type.util.ListUtil.sort(CollectionUtil.getKeyList(members.keySet().iterator(), ","), "textnocase", "asc", ",") + "]");
}
Also used : ArrayList(java.util.ArrayList) LString(lucee.runtime.interpreter.ref.literal.LString) LString(lucee.runtime.interpreter.ref.literal.LString) ExpressionException(lucee.runtime.exp.ExpressionException) Casting(lucee.runtime.interpreter.ref.cast.Casting) Ref(lucee.runtime.interpreter.ref.Ref) FunctionLibFunction(lucee.transformer.library.function.FunctionLibFunction) LFunctionValue(lucee.runtime.interpreter.ref.literal.LFunctionValue) BIFCall(lucee.runtime.interpreter.ref.func.BIFCall) Key(lucee.runtime.type.Collection.Key) FunctionLibFunctionArg(lucee.transformer.library.function.FunctionLibFunctionArg)

Aggregations

FunctionLibFunctionArg (lucee.transformer.library.function.FunctionLibFunctionArg)15 ArrayList (java.util.ArrayList)6 Casting (lucee.runtime.interpreter.ref.cast.Casting)6 Ref (lucee.runtime.interpreter.ref.Ref)5 FunctionLibFunction (lucee.transformer.library.function.FunctionLibFunction)5 ExpressionException (lucee.runtime.exp.ExpressionException)4 BIFCall (lucee.runtime.interpreter.ref.func.BIFCall)4 LString (lucee.runtime.interpreter.ref.literal.LString)4 TemplateException (lucee.runtime.exp.TemplateException)3 LFunctionValue (lucee.runtime.interpreter.ref.literal.LFunctionValue)3 Key (lucee.runtime.type.Collection.Key)3 Array (lucee.runtime.type.Array)2 ArrayImpl (lucee.runtime.type.ArrayImpl)2 Struct (lucee.runtime.type.Struct)2 StructImpl (lucee.runtime.type.StructImpl)2 ExprString (lucee.transformer.expression.ExprString)2 LitString (lucee.transformer.expression.literal.LitString)2 LinkedList (java.util.LinkedList)1 Entry (java.util.Map.Entry)1 ClassDefinition (lucee.runtime.db.ClassDefinition)1