All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.qlexpress4.runtime.QLambdaInner Maven / Gradle / Ivy

package com.alibaba.qlexpress4.runtime;

import com.alibaba.qlexpress4.QLOptions;
import com.alibaba.qlexpress4.exception.QLErrorCodes;
import com.alibaba.qlexpress4.exception.UserDefineException;
import com.alibaba.qlexpress4.runtime.data.AssignableDataValue;
import com.alibaba.qlexpress4.runtime.data.convert.ObjTypeConvertor;
import com.alibaba.qlexpress4.runtime.instruction.QLInstruction;
import com.alibaba.qlexpress4.runtime.scope.QvmBlockScope;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author: DQinYuan
 */
public class QLambdaInner implements QLambda {

    private final QLambdaDefinitionInner lambdaDefinition;

    private final QContext qContext;

    private final QLOptions qlOptions;

    private final boolean newEnv;

    public QLambdaInner(QLambdaDefinitionInner lambdaDefinition, QContext qContext, QLOptions qlOptions,
                        boolean newEnv) {
        this.lambdaDefinition = lambdaDefinition;
        this.qContext = qContext;
        this.qlOptions = qlOptions;
        this.newEnv = newEnv;
    }

    public QResult call(Object... params) throws Throwable {
        QContext newRuntime = newEnv? inheritScope(params): qContext;

        QLInstruction[] instructions = lambdaDefinition.getInstructions();
        for (int i = 0; i < instructions.length; i++) {
            QResult qResult = instructions[i].execute(newRuntime, qlOptions);
            switch (qResult.getResultType()) {
                case JUMP:
                    i += (int) qResult.getResult().get();
                    continue;
                case RETURN:
                case BREAK:
                case CONTINUE:
                    return qResult;
            }
        }

        return QResult.NEXT_INSTRUCTION;
    }

    private QContext inheritScope(Object[] params) throws UserDefineException {
        Map initSymbolTable = new HashMap<>(params.length);
        List paramsDefinition = lambdaDefinition.getParamsType();
        for (int i = 0; i < params.length; i++) {
            QLambdaDefinitionInner.Param paramDefinition = paramsDefinition.get(i);
            Object originParamI = params[i];
            Class targetCls = paramDefinition.getClazz();
            ObjTypeConvertor.QConverted qlConvertResult = ObjTypeConvertor.cast(originParamI, targetCls);
            if (!qlConvertResult.isConvertible()) {
                throw new UserDefineException(UserDefineException.ExceptionType.INVALID_ARGUMENT,
                        MessageFormat.format(
                                "invalid argument at index {0} (start from 0), required type {1}, but {2} provided",
                                i, targetCls.getName(),
                                originParamI == null? "null": originParamI.getClass().getName())
                );
            }
            initSymbolTable.put(paramDefinition.getName(),
                    new AssignableDataValue(paramDefinition.getName(), qlConvertResult.getConverted(), targetCls));
        }
        // null for rest params
        for (int i = params.length; i < paramsDefinition.size(); i++) {
            QLambdaDefinitionInner.Param paramDefinition = paramsDefinition.get(i);
            initSymbolTable.put(paramDefinition.getName(),
                    new AssignableDataValue(paramDefinition.getName(), null, paramDefinition.getClazz()));
        }
        QvmBlockScope newScope = new QvmBlockScope(qContext, initSymbolTable, lambdaDefinition.getMaxStackSize(),
                ExceptionTable.EMPTY);
        return new DelegateQContext(qContext, newScope);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy