Created
December 7, 2016 00:24
-
-
Save abersnaze/bbfb57eee9345b23953aca2c94f6c6a3 to your computer and use it in GitHub Desktop.
Using Guice to as a stack language to compile a tree structure.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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