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

com.alibaba.qlexpress4.runtime.instruction.SliceInstruction Maven / Gradle / Ivy

package com.alibaba.qlexpress4.runtime.instruction;

import com.alibaba.qlexpress4.QLOptions;
import com.alibaba.qlexpress4.exception.ErrorReporter;
import com.alibaba.qlexpress4.exception.QLErrorCodes;
import com.alibaba.qlexpress4.runtime.QContext;
import com.alibaba.qlexpress4.runtime.QResult;
import com.alibaba.qlexpress4.runtime.Value;
import com.alibaba.qlexpress4.runtime.data.DataValue;
import com.alibaba.qlexpress4.runtime.util.ValueUtils;
import com.alibaba.qlexpress4.utils.PrintlnUtils;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Operation: slice array or list, like a[2:4], a[4:-1], a[:4], a[5:], a[:]
 * Input: 0-2
 * Output: 1
 * 

* Author: DQinYuan */ public class SliceInstruction extends QLInstruction { public enum Mode { LEFT, RIGHT, BOTH, COPY } private final Mode mode; public SliceInstruction(ErrorReporter errorReporter, Mode mode) { super(errorReporter); this.mode = mode; } @Override public QResult execute(QContext qContext, QLOptions qlOptions) { int startInt = 0; int endInt = 0; Object indexAble = null; if (mode == Mode.BOTH) { Object end = qContext.pop().get(); Object start = qContext.pop().get(); indexAble = qContext.pop().get(); startInt = ValueUtils.assertType(start, Number.class, QLErrorCodes.INVALID_INDEX.name(), QLErrorCodes.INVALID_INDEX.getErrorMsg(), errorReporter).intValue(); endInt = ValueUtils.assertType(end, Number.class, QLErrorCodes.INVALID_INDEX.name(), QLErrorCodes.INVALID_INDEX.getErrorMsg(), errorReporter).intValue(); } else if (mode == Mode.LEFT) { Object end = qContext.pop().get(); indexAble = qContext.pop().get(); endInt = ValueUtils.assertType(end, Number.class, QLErrorCodes.INVALID_INDEX.name(), QLErrorCodes.INVALID_INDEX.getErrorMsg(), errorReporter).intValue(); } else if (mode == Mode.RIGHT) { Object start = qContext.pop().get(); indexAble = qContext.pop().get(); startInt = ValueUtils.assertType(start, Number.class, QLErrorCodes.INVALID_INDEX.name(), QLErrorCodes.INVALID_INDEX.getErrorMsg(), errorReporter).intValue(); endInt = indexAbleLen(indexAble); } else if (mode == Mode.COPY) { indexAble = qContext.pop().get(); endInt = indexAbleLen(indexAble); } if (indexAble instanceof List) { List result = listSlice((List) indexAble, startInt, endInt); qContext.push(new DataValue(result)); return QResult.NEXT_INSTRUCTION; } else if (indexAble != null && indexAble.getClass().isArray()) { Object result = arraySlice(indexAble, startInt, endInt); qContext.push(new DataValue(result)); return QResult.NEXT_INSTRUCTION; } else if (indexAble == null && qlOptions.isAvoidNullPointer()) { qContext.push(Value.NULL_VALUE); return QResult.NEXT_INSTRUCTION; } else { throw errorReporter.reportFormat(QLErrorCodes.NONINDEXABLE_OBJECT.name(), QLErrorCodes.NONINDEXABLE_OBJECT.getErrorMsg(), indexAble == null? "null": indexAble.getClass().getName()); } } private int indexAbleLen(Object indexAble) { if (indexAble instanceof List) { return ((List) indexAble).size(); } else if (indexAble != null && indexAble.getClass().isArray()) { return Array.getLength(indexAble); } else { throw errorReporter.reportFormat(QLErrorCodes.NONINDEXABLE_OBJECT.name(), QLErrorCodes.NONINDEXABLE_OBJECT.getErrorMsg(), indexAble == null? "null": indexAble.getClass().getName()); } } private List listSlice(List listObj, int originStart, int originEnd) { int start = Math.max(ValueUtils.javaIndex(listObj.size(), originStart), 0); int end = Math.min(ValueUtils.javaIndex(listObj.size(), originEnd), listObj.size()); if (start >= end) { return new ArrayList<>(0); } return listObj.subList(start, end); } private Object arraySlice(Object arrObj, int originStart, int originEnd) { int arrLen = Array.getLength(arrObj); int start = Math.max(ValueUtils.javaIndex(arrLen, originStart), 0); int end = Math.min(ValueUtils.javaIndex(arrLen, originEnd), arrLen); if (start >= end) { return Array.newInstance(arrObj.getClass().getComponentType(), 0); } Object newArr = Array.newInstance(arrObj.getClass().getComponentType(), end - start); for (int i = start; i < end; i++) { Array.set(newArr, i - start, Array.get(arrObj, i)); } return newArr; } @Override public int stackInput() { if (mode == Mode.BOTH) { return 2; } else if (mode == Mode.COPY) { return 0; } else { return 1; } } @Override public int stackOutput() { return 1; } @Override public void println(int index, int depth, Consumer debug) { PrintlnUtils.printlnByCurDepth(depth, index + ": Slice", debug); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy