Skip to content
This repository has been archived by the owner on Apr 9, 2023. It is now read-only.

Commit

Permalink
commented Trampoline. closes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
ksmonkey123 committed Oct 6, 2016
1 parent 890ff30 commit ee7198a
Showing 1 changed file with 152 additions and 7 deletions.
159 changes: 152 additions & 7 deletions src/main/java/ch/awae/utils/Trampoline.java
Expand Up @@ -21,38 +21,80 @@
* <p>
* This class provides all helper methods required for Trampoline
* implementations with functions with up to two arguments (helpers for more
* arguments may be added in the future). Use {@link Trampoline.Result
* arguments may be added in the future). Use {@link #Result
* Trampoline.Result&lt;T&gt;} (where {@code T} is the return type of the
* complete trampolined call structure) as the return type of any involved
* method. Normal methods invoked from inside a Trampoline must either be called
* as a subcall and the result packed into a {@link Trampoline.Result} instance
* using {@link Trampoline#result} or they can be wrapped into a
* {@link Trampoline.Result} using {@link Trampoline#bounceWrapped}.
* as a subcall and the result packed into a {@link #Result} instance using
* {@link #result} or they can be wrapped into a {@link #Result} using
* {@link #bounceWrapped}.
* </p>
*
* @author Andreas Wälchli (andreas.waelchli@me.com)
* @version 1.1
* @author Andreas Wälchli
* @since awaeUtils 0.0.1
*/
public final class Trampoline {


/**
* Helper class representing the result of a single trampoline step.
* <p>
* A Result may be the final return value or the bounce instruction to
* continue the trampoline. Result instances are implicitly created by
* calling any of the {@link #bounce} methods or the {@link #bounceWrapped}
* methods or the {@link #result} method.
* </p>
*
* @author Andreas Wälchli
* @since awaeUtils 0.0.1
* @param <T>
* the return type
* @deprecated this class will be rewritten. <b>DO NOT EXTEND!</b>
*/
@Deprecated
public static abstract class Result<T> {

private Result() {
}

/**
* indicates if this Result is a return value or not.
*
* @return {@code true} if the Result is a return value.
*/
boolean isReturn() {
return false;
}

/**
* returns the return value of this Result if it exists.
*
* @return the return value.
* @throws UnsupportedOperationException
* if this result does not represent a return value.
*/
T get() {
throw new UnsupportedOperationException();
}

/**
* performs the next trampoline step and returns the result of that
* step.
*
* @return the result of the performed step.
* @throws UnsupportedOperationException
* if the Result is a return value.
*/
abstract Result<T> call();

}

/**
* Wraps a value into a Result instance representing that value
*
* @param value
* the value to wrap into a Result
* @return the Result containing the {@code value}
*/
public static <T> Result<T> result(T value) {
return new Result<T>() {
@Override
Expand All @@ -72,6 +114,15 @@ public Result<T> call() {
};
}

/**
* Bounce to a {@link Supplier} for the next step.
*
* @param f
* the function
* @return a Result instance representing a Trampoline step. When executing
* that step the Function {@code f} will be called. The return value
* of that call determines the next trampoline action.
*/
public static <T> Result<T> bounce(Supplier<Result<T>> f) {
return new Result<T>() {

Expand All @@ -83,6 +134,18 @@ Result<T> call() {
};
}

/**
* Bounce to a {@link Function} for the next step.
*
* @param f
* the function
* @param param0
* the function parameter
* @return a Result instance representing a Trampoline step. When executing
* that step the function {@code f} will be called with the
* parameter {@code param0}. The return value of that call
* determines the next trampoline action.
*/
public static <T, A> Result<T> bounce(Function<A, Result<T>> f, A param0) {
return new Result<T>() {

Expand All @@ -93,6 +156,20 @@ Result<T> call() {
};
}

/**
* Bounce to a {@link BiFunction} for the next step.
*
* @param f
* the function
* @param param0
* the first function parameter
* @param param1
* the second function parameter
* @return a Result instance representing a Trampoline step. When executing
* that step the function {@code f} will be called with the
* parameters {@code param0} and {@code param1}. The return value of
* that call determines the next trampoline action.
*/
public static <T, A, B> Result<T> bounce(BiFunction<A, B, Result<T>> f, A param0, B param1) {
return new Result<T>() {
@Override
Expand All @@ -102,6 +179,22 @@ Result<T> call() {
};
}

/**
* Bounces to a generic {@link Supplier}.
* <p>
* This method is designed to provide a hook into an arbitrary external
* method. This does interrupt normal trampoline functionality until the
* supplier function returns. The return value of the supplier is then
* wrapped into a Result and returned.
* </p>
*
* @param f
* the function
* @return a Result instance representing a Trampoline step. When executing
* that step the Function {@code f} will be called. The return value
* of that call will be wrapped into a Result and returned to the
* trampoline.
*/
public static <T> Result<T> bounceWrapped(Supplier<T> f) {
return new Result<T>() {

Expand All @@ -113,6 +206,24 @@ Result<T> call() {
};
}

/**
* Bounces to a generic {@link Function}.
* <p>
* This method is designed to provide a hook into an arbitrary external
* method. This does interrupt normal trampoline functionality until the
* function returns. The return value of the function is then wrapped into a
* Result and returned.
* </p>
*
* @param f
* the function
* @param param0
* the function parameter
* @return a Result instance representing a Trampoline step. When executing
* that step the function {@code f} will be called with the
* parameter {@code param0}. The return value of that call will be
* wrapped into a Result and returned to the trampoline.
*/
public static <T, A> Result<T> bounceWrapped(Function<A, T> f, A param0) {
return new Result<T>() {

Expand All @@ -124,6 +235,27 @@ Result<T> call() {
};
}

/**
* Bounces to a generic {@link BiFunction}.
* <p>
* This method is designed to provide a hook into an arbitrary external
* method. This does interrupt normal trampoline functionality until the
* function returns. The return value of the function is then wrapped into a
* Result and returned.
* </p>
*
* @param f
* the function
* @param param0
* the first function parameter
* @param param1
* the second function parameter
* @return a Result instance representing a Trampoline step. When executing
* that step the function {@code f} will be called with the
* parameters {@code param0} and {@code param1}. The return value of
* that call will be wrapped into a Result and returned to the
* trampoline.
*/
public static <T, A, B> Result<T> bounceWrapped(BiFunction<A, B, T> f, A param0, B param1) {
return new Result<T>() {

Expand All @@ -135,6 +267,19 @@ Result<T> call() {
};
}

/**
* Starts a new trampoline with a given {@link #Result}.
*
* <p>
* Usually the passed {@code result} is generated with one of the
* {@link #bounce} methods. Using a {@link #bounceWrapped} method is
* recommended, since those methods break the normal trampoline execution.
* </p>
*
* @param result
* the Result to start the trampoline from
* @return the return value of the last trampoline step
*/
public static <T> T run(Result<T> result) {
Result<T> step = result;
while (!step.isReturn())
Expand Down

0 comments on commit ee7198a

Please sign in to comment.