Skip to content

Instantly share code, notes, and snippets.

@BurntPizza
Last active August 29, 2015 14:07
Show Gist options
  • Save BurntPizza/94ccfecb9851ac193bc8 to your computer and use it in GitHub Desktop.
Save BurntPizza/94ccfecb9851ac193bc8 to your computer and use it in GitHub Desktop.
Just what the name says...
package stupid;
import java.util.*;
import java.util.function.Consumer;
/**
* A very broken FORTH-like embedded Java DSL
*/
@SuppressWarnings("unchecked")
public enum StupidDSL implements Consumer<ArrayDeque<Object>> {
drop(s -> s.pop()),
dup(s -> s.push(s.peek())),
print(s -> {
((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
System.out.println(s.pop());
}),
apply(s -> {
Object o = s.pop();
if (o instanceof List)
((List<Consumer<ArrayDeque<Object>>>) o).forEach(a -> a.accept(s));
else if (o instanceof Consumer) {
((Consumer<ArrayDeque<Object>>) o).accept(s);
}
}),
swap(s -> {
Object o2 = s.pop(), o1 = s.pop();
s.push(o2);
s.push(o1);
}),
compose(s -> {
List<Consumer<ArrayDeque<Object>>> q2 = (List<Consumer<ArrayDeque<Object>>>) s.pop();
List<Consumer<ArrayDeque<Object>>> q1 = (List<Consumer<ArrayDeque<Object>>>) s.pop();
q1.addAll(q2);
s.push(q1);
}),
join(s -> {
quote((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
swap.accept(s);
quote((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
swap.accept(s);
compose.accept(s);
}),
plus(s -> {
((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
Object o2 = s.pop();
((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
Object o1 = s.pop();
if (o1 instanceof String)
lit((String) o1 + o2).accept(s);
else if (o2 instanceof String)
lit(o1 + (String) o2).accept(s);
else if (o1 instanceof Integer && o2 instanceof Integer)
lit((Integer) o1 + (Integer) o2).accept(s);
}),
def(s -> {
((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
String name = (String) s.pop();
List<Consumer<ArrayDeque<Object>>> quotation = (List<Consumer<ArrayDeque<Object>>>) s.pop();
Wordbank.put(name, a -> a.push(quotation));
}),
call(s -> {
((Consumer<ArrayDeque<Object>>) s.pop()).accept(s);
String name = (String) s.pop();
Wordbank.get(name).accept(s);
apply.accept(s);
});
/*
* Simple hello world demonstrating some of the words
*/
public static void main(String[] args) {
List<Consumer<ArrayDeque<Object>>> prog = Arrays.asList(
quote(lit("Hello World!\n"), lit(21), dup, plus, plus, print), lit("hello"), def,
lit("hello"), dup, call, call,
quote(lit(4)), quote(lit(5), plus, print), compose, apply
);
run(prog);
}
public static void run(List<Consumer<ArrayDeque<Object>>> program) {
ArrayDeque<Object> stack = new ArrayDeque<>();
program.iterator().forEachRemaining(s -> s.accept(stack));
}
@SafeVarargs
public static Consumer<ArrayDeque<Object>> quote(Consumer<ArrayDeque<Object>>... a) {
List<Consumer<ArrayDeque<Object>>> quotation = new ArrayList<>();
for (Consumer<ArrayDeque<Object>> c : a)
quotation.add(c);
return s -> s.push(quotation);
}
public static Consumer<ArrayDeque<Object>> lit(Object a) {
return z -> z.push((Consumer<ArrayDeque<Object>>) s -> s.push(a));
}
private static class Wordbank {
private static final Map<String, Consumer<ArrayDeque<Object>>> instance = new HashMap<>();
static void put(String name, Consumer<ArrayDeque<Object>> word) {
instance.put(name, word);
}
static Consumer<ArrayDeque<Object>> get(Object name) {
return instance.get(name);
}
}
static {
for (StupidDSL word : StupidDSL.values())
Wordbank.put(word.name(), word);
}
private final Consumer<ArrayDeque<Object>> c;
private StupidDSL(Consumer<ArrayDeque<Object>> c) {
this.c = c;
}
@Override
public void accept(ArrayDeque<Object> t) {
c.accept(t);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment