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

org.classdump.luna.standalone.Aux Maven / Gradle / Ivy

/*
 * Copyright 2016 Miroslav Janíček
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.classdump.luna.standalone;

import org.classdump.luna.impl.NonsuspendableFunctionException;
import org.classdump.luna.runtime.AbstractFunction0;
import org.classdump.luna.runtime.AbstractFunction2;
import org.classdump.luna.runtime.AbstractFunction3;
import org.classdump.luna.runtime.AbstractFunctionAnyArg;
import org.classdump.luna.runtime.Dispatch;
import org.classdump.luna.runtime.ExecutionContext;
import org.classdump.luna.runtime.LuaFunction;
import org.classdump.luna.runtime.ResolvedControlThrowable;
import org.classdump.luna.runtime.UnresolvedControlThrowable;

import java.util.Arrays;
import java.util.Objects;

/**
 * Basic utility functions.
 */
public final class Aux {

	private Aux() {
		// not to be instantiated
	}

	/**
	 * Returns a vararg function that calls the result of the Lua expression {@code x()}
	 * with the remaining supplied arguments.
	 *
	 * 

In Lua terms, the returned function is equivalent to:

*
	 *   function (...)
	 *     return x()(...)
	 *   end
	 * 
*

where {@code x} is the argument supplied to this method.

* * @param x the argument to evaluate as a function, may be {@code null} * @return a vararg function that calls the result of {@code x()} with the remaining * arguments */ public static LuaFunction lift(Object x) { return new Lift(x); } /** * Returns a vararg function that returns the results of the call {@code x(y1,...,yn, ...)}, * where {@code yi} is the {@code i-th} value in {@code ys}. In other words, the function * inserts {@code ys} to the argument list before the vararg arguments, and calls {@code f} * with the resulting arguments. * *

For illustration, consider the case in which {@code ys} consists of two values * {@code y1} and {@code y2}. Then the function returned by this method this is equivalent * to:

*
	 *   function (...)
	 *     return x(y1, y2, ...)
	 *   end
	 * 
* *

For empty {@code ys}, the resulting function is equivalent to:

*
	 *   function (...)
	 *     return x(...)
	 *   end
	 * 
* * @param x the call target, may be {@code null} * @param ys the arguments to insert to the argument list, must not be {@code null} * @return a vararg function that inserts {@code ys} to the argument list and calls {@code x} * * @throws NullPointerException if {@code ys} is {@code null} */ public static LuaFunction bind(Object x, Object... ys) { return new Bind(x, Arrays.copyOf(ys, ys.length)); } /** * Returns a 0-ary function that returns the results of the call {@code x(y1,...,yn)}, * where {@code yi} is the {@code i}-th value in {@code ys}. * *

For example, if {@code ys} consists of two values {@code y1} and {@code y2}, * the returned function is equivalent to:

*
	 *   function ()
	 *     return x(y1, y2)
	 *   end
	 * 
* * @param x the call target, may be {@code null} * @param ys the arguments to call {@code x} with, must not be {@code null} * @return a 0-ary function that returns the results of {@code x(ys)} * * @throws NullPointerException if {@code ys} is {@code null} */ public static LuaFunction call(Object x, Object... ys) { return new Call(bind(x, ys)); } /** * Returns a function of two arguments {@code t} and {@code k} that returns the result * of the Lua expression {@code t[k]}. * *

In other words, the returned function is equivalent to:

*
	 *   function (t, k)
	 *     return t[k]
	 *   end
	 * 
* * @return a function of two arguments that performs a table lookup */ public static LuaFunction index() { return Index.INSTANCE; } /** * Returns a 0-ary function that returns the result of the Lua expression {@code t[k]}, * including metamethod processing. * *

In other words, the returned function is equivalent to:

*
	 *   function ()
	 *     return t[k]
	 *   end
	 * 
*

where {@code t} and {@code k} are the arguments supplied to this method.

* * @param t the object to index, may be {@code null} * @param k the key to look up in {@code t}, may be {@code null} * @return a function that returns the result of {@code t[k]} */ public static LuaFunction index(Object t, Object k) { return call(index(), t, k); } /** * Returns a function of three arguments {@code t}, {@code k} and {@code v} that * executes the Lua statement {@code t[k] = v}. * *

In Lua terms, the returned function is equivalent to:

*
	 *   function (t, k, v)
	 *     t[k] = v
	 *   end
	 * 
* * @return a ternary function that performs table assignment */ public static LuaFunction setIndex() { return SetIndex.INSTANCE; } /** * Returns a 0-ary function that executes the Lua statement {@code t[k] = v}. * *

In Lua terms, the returned function is equivalent to:

*
	 *   function ()
	 *     t[k] = v
	 *   end
	 * 
*

where {@code t}, {@code k} and {@code v} are the arguments to this method.

* * @param t the object to assign to, may be {@code null} * @param k the key to assign, may be {@code null} * @param v the value to assign, may be {@code null} * @return a 0-ary function that performs table assignment */ public static LuaFunction setIndex(Object t, Object k, Object v) { return call(setIndex(), t, k, v); } /** * Returns a new vararg function that looks up {@code name} in {@code env}, * and calls the result of the lookup with the supplied arguments. Neither operation is * raw, i.e., it both the lookup and call may involve metamethod processing. * *

In Lua terms, the returned function is equivalent to:

*
	 *   function (...)
	 *     return env[name](...)
	 *   end
	 * 
*

where {@code env} and {@code name} are the arguments supplied to this method.

* * @param env the environment to look up {@code name} in, may be {@code null} * @param name the name to look up in {@code env}, may be {@code null} * @return a vararg function that looks up its first argument in {@code env} and calls it * with the remaining arguments */ public static LuaFunction callGlobal(Object env, Object name) { return lift(index(env, name)); } static class Lift extends AbstractFunctionAnyArg { private final Object x; public Lift(Object x) { this.x = x; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Lift that = (Lift) o; return Objects.equals(x, that.x); } @Override public int hashCode() { return Objects.hash(getClass(), x); } @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); } @Override public void resume(ExecutionContext context, Object suspendedState) throws ResolvedControlThrowable { Object target = context.getReturnBuffer().get0(); context.getReturnBuffer().setToCallWithContentsOf(target, (Object[]) suspendedState); } } static class Bind extends AbstractFunctionAnyArg { private final Object fn; private final Object[] curriedArgs; public Bind(Object fn, Object[] args) { this.fn = fn; // may be null this.curriedArgs = Objects.requireNonNull(args); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Bind that = (Bind) o; return Objects.equals(fn, that.fn) && Arrays.equals(curriedArgs, that.curriedArgs); } @Override public int hashCode() { int result = getClass().hashCode(); result = 31 * result + (fn != null ? fn.hashCode() : 0); result = 31 * result + Arrays.hashCode(curriedArgs); return result; } @Override public void invoke(ExecutionContext context, Object[] args) throws ResolvedControlThrowable { Object[] callArgs = new Object[curriedArgs.length + args.length]; System.arraycopy(curriedArgs, 0, callArgs, 0, curriedArgs.length); System.arraycopy(args, 0, callArgs, curriedArgs.length, args.length); context.getReturnBuffer().setToCallWithContentsOf(fn, callArgs); } @Override public void resume(ExecutionContext context, Object suspendedState) throws ResolvedControlThrowable { throw new NonsuspendableFunctionException(getClass()); } } static class Call extends AbstractFunction0 { private final Object x; public Call(Object x) { this.x = x; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Call that = (Call) o; return Objects.equals(x, that.x); } @Override public int hashCode() { return Objects.hash(getClass(), x); } @Override public void invoke(ExecutionContext context) throws ResolvedControlThrowable { context.getReturnBuffer().setToCall(x); } @Override public void resume(ExecutionContext context, Object suspendedState) throws ResolvedControlThrowable { throw new NonsuspendableFunctionException(this.getClass()); } } static class Index extends AbstractFunction2 { static final Index INSTANCE = new Index(); @Override public void invoke(ExecutionContext context, Object t, Object k) throws ResolvedControlThrowable { try { Dispatch.index(context, t, k); } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, null); } resume(context, null); } @Override public void resume(ExecutionContext context, Object suspendedState) throws ResolvedControlThrowable { Object result = context.getReturnBuffer().get0(); context.getReturnBuffer().setTo(result); } } static class SetIndex extends AbstractFunction3 { static final SetIndex INSTANCE = new SetIndex(); @Override public void invoke(ExecutionContext context, Object t, Object k, Object v) throws ResolvedControlThrowable { try { Dispatch.setindex(context, t, k, v); } catch (UnresolvedControlThrowable ct) { throw ct.resolve(this, null); } resume(context, null); } @Override public void resume(ExecutionContext context, Object suspendedState) throws ResolvedControlThrowable { context.getReturnBuffer().setTo(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy