@Override public void invoke(ExecutionContext context, Object[] args) throws ResolvedControlThrowable { try { Dispatch.call(context, x); } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, Arrays.copyOf(args, args.length)); } resume(context, args); }
private void nonStringReplace( ExecutionContext context, String str, StringPattern pat, int idx, int count, int num, StringBuilder bld, Object repl, String fullMatch, List<Object> captures) throws ResolvedControlThrowable { assert (!captures.isEmpty()); Object cap = captures.get(0); try { if (repl instanceof Table) { Dispatch.index(context, (Table) repl, cap); } else if (repl instanceof LuaFunction) { Dispatch.call(context, (LuaFunction) repl, (Object[]) captures.toArray()); } else { throw new IllegalStateException("Illegal replacement: " + repl); } } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, new State(str, pat, count, num, repl, bld, fullMatch, idx)); } resumeReplace(context, bld, fullMatch); }
private static Object tryEmulateOperation(UnOp.Op op, Object arg) { if (arg == null) { return null; } switch (op) { case UNM: { Number n = Conversions.arithmeticValueOf(arg); return n != null ? Dispatch.unm(n) : null; } case BNOT: { Long l = Conversions.integerValueOf(arg); return l != null ? LuaMathOperators.bnot(l) : null; } case NOT: return arg.equals(Boolean.FALSE); case LEN: if (arg instanceof String) return Dispatch.len((String) arg); else if (arg instanceof ByteString) return Long.valueOf(((ByteString) arg).length()); else return null; default: throw new IllegalArgumentException("Illegal operation: " + op); } }
/** * Returns {@code true} iff {@code a} <i>op</i> {@code b}, where <i>op</i> is * "{@code <=}" (lesser than or equal to) if {@code sign > 0}, or "{@code >=}" (greater * than or equal to) if {@code sign < 0}. * * <p>When {@code sign} is zero or <i>NaN</i>, returns {@code false}.</p> * * @param a the first operand, must not be {@code null} * @param b the second operand, must not be {@code null} * @param sign the sign, must not be {@code null} * * @return {@code true} iff {@code a} is below {@code b} depending on the sign * of {@code sign} * * @throws NullPointerException if {@code a}, {@code b} or {@code sign} is {@code null} */ @SuppressWarnings("unused") public static boolean signed_le(Number a, Number b, Number sign) { return !eq(ZERO, sign) && (lt(ZERO, sign) ? le(a, b) : le(b, a)); }
private static Object tryEmulateArithmeticOperation(BinOp.Op op, Object l, Object r) { Number nl = Conversions.arithmeticValueOf(l); Number nr = Conversions.arithmeticValueOf(r); if (nl == null || nr == null) { return null; } try { switch (op) { case ADD: return Dispatch.add(nl, nr); case SUB: return Dispatch.sub(nl, nr); case MUL: return Dispatch.mul(nl, nr); case DIV: return Dispatch.div(nl, nr); case MOD: return Dispatch.mod(nl, nr); case IDIV: return Dispatch.idiv(nl, nr); case POW: return Dispatch.pow(nl, nr); default: throw new IllegalArgumentException("Illegal operation: " + op); } } catch (ArithmeticException ex) { return null; } }
/** * Evaluates the Lua expression {@code table[key]} (in non-assignment context) including * the handling of metamethods, and stores the result to the return buffer associated with * {@code context}. * <b>This method throws an {@link UnresolvedControlThrowable}</b>: non-local control * changes are expected to be resolved by the caller of this method. * * <p>This method differs from {@link #index(ExecutionContext, Object, Object)} * in that the {@code table} argument is required to be a non-{@code null} reference * to a {@link Table}.</p> * * @param context execution context, must not be {@code null} * @param table the table, must not be {@code null} * @param key the key, may be any value * * @throws UnresolvedControlThrowable if the evaluation called a metamethod and the metamethod * initiates a non-local control change * * @throws NullPointerException if {@code context} or {@code table} is {@code null} */ @SuppressWarnings("unused") public static void index(ExecutionContext context, Table table, Object key) throws UnresolvedControlThrowable { // TODO: don't just delegate to the generic case index(context, (Object) Objects.requireNonNull(table), key); }
/** * Executes the Lua statement {@code table[key] = value}, including the handling of * metamethods, and stores the result to the return buffer associated with {@code context}. * <b>This method throws an {@link UnresolvedControlThrowable}</b>: non-local control * changes are expected to be resolved by the caller of this method. * * <p>This method differs from {@link #setindex(ExecutionContext, Object, Object, Object)} * in that the {@code table} argument is required to be a non-{@code null} reference * to a {@link Table}.</p> * * @param context execution context, must not be {@code null} * @param table the target, must not be {@code null} * @param key the key, may be any value * @param value the value, may be any value * * @throws UnresolvedControlThrowable if the evaluation called a metamethod and the metamethod * initiates a non-local control change * @throws NullPointerException if {@code context} or {@code table} is {@code null} */ @SuppressWarnings("unused") public static void setindex(ExecutionContext context, Table table, Object key, Object value) throws UnresolvedControlThrowable { // TODO: don't just delegate to the generic case setindex(context, (Object) Objects.requireNonNull(table), key, value); }
private void fetchLen(ExecutionContext context, int state, ArgumentIterator args, Table t) throws ResolvedControlThrowable { long len = 0; try { switch (state) { case STATE_OFFSET_LEN: state = STATE_OFFSET_LEN + 1; Dispatch.len(context, t); case STATE_OFFSET_LEN + 1: len = getLength(context.getReturnBuffer()); break; default: throw new IllegalStateException("Illegal state: " + state); } } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, new SuspendedState(state, -1, args, t, null, 1, -1, -1, null, null, null)); } prepareLoop(context, args, t, len); }
private static void _call_comparison_mt(ExecutionContext context, boolean cmpTo, Object handler, Object a, Object b) throws UnresolvedControlThrowable { try { call(context, handler, a, b); } catch (UnresolvedControlThrowable ct) { // suspended in the metamethod call throw ct.resolve(cmpResultResumable(cmpTo), null).unresolve(); } // not suspended: set the result, possibly flipping it ReturnBuffer result = context.getReturnBuffer(); result.setTo(cmpTo == Conversions.booleanValueOf(result.get0())); }
evaluateTailCalls(context); setindex(context, handler, key, value);
evaluateTailCalls(context); index(context, handler, key);
static void mt_invoke(ExecutionContext context, Object target, Object[] args) throws ResolvedControlThrowable { LuaFunction fn = callTarget(context, target); if (fn == target) { fn.invoke(context, args); } else { Object[] mtArgs = new Object[args.length + 1]; mtArgs[0] = target; System.arraycopy(args, 0, mtArgs, 1, args.length); fn.invoke(context, mtArgs); } }
@Override public void invoke(ExecutionContext context, Object arg1, Object arg2, Object arg3) throws ResolvedControlThrowable { try { // b + c Dispatch.add(context, arg2, arg3); } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, arg1); } resume(context, arg1); }
private void run(ExecutionContext context, Object[] args, int idx, Object best) throws ResolvedControlThrowable { for ( ; idx < args.length; idx++) { Object o = args[idx]; try { if (isMax) { Dispatch.lt(context, best, o); } else { Dispatch.lt(context, o, best); } } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, new State(args, idx, best)); } if (Conversions.booleanValueOf(context.getReturnBuffer().get0())) { best = o; } } // we're done context.getReturnBuffer().setTo(best); }
private static void eq(ExecutionContext context, boolean polarity, Object a, Object b) throws UnresolvedControlThrowable { boolean rawEqual = Ordering.isRawEqual(a, b); if (!rawEqual && ((a instanceof Table && b instanceof Table) || (a instanceof Userdata && b instanceof Userdata))) { Object handler = Metatables.binaryHandlerFor(context, Metatables.MT_EQ, a, b); if (handler != null) { _call_comparison_mt(context, polarity, handler, a, b); return; } // else keep the result as false } context.getReturnBuffer().setTo(rawEqual == polarity); }