package com.acme.symbolic; import java.util.function.Function; import static church.lang.operators.Streams.$$encode; @SuppressWarnings("unchecked") public abstract class Primitive { public interface Visitor<S> { default S get(Primitive receiver) { S result = receiver.accept(this); return result == null ? defaultImplementation(receiver) : result; } default S getOrDefault(Primitive receiver, S defaultValue) { S result = receiver.accept(this); return result == null ? defaultValue : result; } default S integer(int i) { return null; } default S proc(Function<Primitive, Primitive> fn) { return null; } default S defaultImplementation(Primitive e) { throw new UnsupportedOperationException(); } } public abstract <S> S accept(Visitor<S> visitor); public static Primitive integer(int i) { return new Primitive() { public <S> S accept(Visitor<S> visitor) { return visitor.integer(i); } }; } public static Primitive proc(Function<Primitive, Primitive> fn) { return new Primitive() { public <S> S accept(Visitor<S> visitor) { return visitor.proc(fn); } }; } public static <T> $$encode<T, Primitive> $encode($$encode<T, Integer> $L0, $$encode<T, String> $L1) { return (stream, $0) -> new Visitor<T>() { public T integer(int i) { return $L0.$encode(stream, i); } public T proc(Function<Primitive, Primitive> fn) { return $L1.$encode(stream, "<function>"); } } .get($0); } }