Skip to content

Instantly share code, notes, and snippets.

@abersnaze
Created December 7, 2016 00:24
Show Gist options
  • Save abersnaze/bbfb57eee9345b23953aca2c94f6c6a3 to your computer and use it in GitHub Desktop.
Save abersnaze/bbfb57eee9345b23953aca2c94f6c6a3 to your computer and use it in GitHub Desktop.
Using Guice to as a stack language to compile a tree structure.
import java.util.List;
import java.util.Stack;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import com.google.inject.Binder;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.UniqueAnnotations;
public class Main {
public static interface Foo {
int get();
}
public static interface FooOp {
void apply(Stack<Foo> stack);
}
public static class OneFoo implements Foo {
@Override
public int get() {
return 1;
}
}
public static class TwoFoo implements Foo {
@Override
public int get() {
return 2;
}
}
public static class TimesTenFoo implements Foo {
private Foo a;
public TimesTenFoo(Foo a) {
this.a = a;
}
@Override
public int get() {
return a.get() * 10;
}
}
public static class AddFoo implements Foo {
private Foo a;
private Foo b;
public AddFoo(Foo a, Foo b) {
this.a = a;
this.b = b;
}
@Override
public int get() {
return a.get() + b.get();
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(Stage.PRODUCTION, new Module() {
@Override
public void configure(Binder binder) {
// 1 + 2 * 10
op(binder, OneFoo::new);
op(binder, TwoFoo::new);
op(binder, TimesTenFoo::new);
op(binder, AddFoo::new);
binder.bind(Foo.class).toProvider(EvalOperators.class);
}
});
Foo foo = injector.getInstance(Foo.class);
System.out.println(foo.get());
}
private static final class EvalOperators implements Provider<Foo> {
private Injector injector;
@Inject
public EvalOperators(Injector injector) {
this.injector = injector;
}
@Override
public Foo get() {
List<Binding<FooOp>> opBindings = injector.findBindingsByType(TypeLiteral.get(FooOp.class));
Stack<Foo> stack = new Stack<>();
for (Binding<FooOp> opBinding : opBindings) {
opBinding.getProvider().get().apply(stack);
}
return stack.pop();
}
}
public static void op(Binder binder, Supplier<Foo> foo0) {
binder.bind(FooOp.class).annotatedWith(UniqueAnnotations.create()).toInstance((stack) -> stack.push(foo0.get()));
}
public static void op(Binder binder, Function<Foo, Foo> foo1) {
binder.bind(FooOp.class).annotatedWith(UniqueAnnotations.create()).toInstance((stack) -> stack.push(foo1.apply(stack.pop())));
}
public static void op(Binder binder, BiFunction<Foo, Foo, Foo> foo2) {
binder.bind(FooOp.class).annotatedWith(UniqueAnnotations.create()).toInstance((stack) -> stack.push(foo2.apply(stack.pop(), stack.pop())));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment