Permalink
Browse files

Almost complete with combinators

* Still need to handle subst substituting bound variables
    * changed <S>'s params to get around it
* Changed <COND> to a regular LambdaFunction
* Raised the Symbol case in Interpreter2
* Added a lot of tracing output
* Copied in Cons equals method and added append
  • Loading branch information...
Mark Watts
Mark Watts committed Nov 29, 2012
1 parent 6d390c7 commit 4a349d56e81d99e1418f47c0637c5e17adc6a94c
Showing with 268 additions and 151 deletions.
  1. +5 −2 crono/prelude.lisp
  2. +88 −45 crono/src/crono/Interpreter2.java
  3. +40 −3 crono/src/crono/type/CombinatorApplication.java
  4. +135 −101 crono/src/crono/type/Cons.java
View
@@ -37,7 +37,7 @@
(define <K> (\ (x y) x))
%General application combinator
-(define <S> (\ (f g x) (f x (g x))))
+(define <S> (\ (f g p) (f p (g p))))
%Function composition combinator
(define <B> (\ (f g x) (f (g x))))
@@ -56,5 +56,8 @@
(define <Y> (\ (f)
(\ (x) (f (x x))) (\ (x) (f (x x))) ))
+(define pred (\ (x) (- x 1)))
+(define my_cond (\ (p f g x) (if (p x) (f x) (g x))))
+(define fapp (\ (x y) ((<S> (<K> (<S> <I>)) <K>) x y)))
+(define pradd (\ (x z) (<Z> (<B> (my_cond ((=) 0) (<K> z)) (<B> (<S> (<B> (+) (<K> 1)) ) (<C> <B> pred))) x)))
-(define <COND> (\ (p f g x) (if (p x) (f x) (g x))))
@@ -16,6 +16,60 @@ public Interpreter2()
env_stack = new Stack<Environment>();
reset();
}
+ private CronoType coerceCombinator (CronoType val)
+ {
+ if (val == null)
+ {
+ throw new InterpreterException("attempting coerce on null");
+ }
+ System.out.println("coercing " + val + " to combinator");
+ CronoType result = null;
+ if (val instanceof Symbol && ((Symbol) val).isCombinator())
+ {
+ /* If the value is a combinator symbol,
+ * return true
+ */
+ result = val;
+ }
+ else if (val instanceof Cons)
+ {
+ /* If it's a cons and the head is a combinator
+ * reduce it and keep doing so until we
+ * reach a fixed point or the head isn't a combinator.
+ */
+ Cons c = (Cons) val;
+ CronoType head = c.car();
+ if (head instanceof Symbol)
+ {
+ Symbol maybe_comb = (Symbol) head;
+ if (maybe_comb.isCombinator())
+ {
+ System.out.println("Our head is a combinator symbol...");
+ CombinatorApplication ca = new CombinatorApplication(c);
+ CronoType r = ca.reduce(this);
+ System.out.println("c = " + c + " r = " + r );
+ /* Reduces to itself; fixed point */
+ if (r.equals(c))
+ {
+ result = r;
+ }
+ else if (r == null)
+ {
+ System.out.println("HERE at r == null");
+ }
+ else
+ {
+ /* If the result is still a combinator then we continue
+ * otherwise set result to null
+ */
+ result = coerceCombinator(r);
+ }
+ }
+ }
+ }
+ System.out.println("Result of coercion: " + result);
+ return result;
+ }
public CronoType visit (CronoType o)
{
@@ -25,6 +79,11 @@ public CronoType visit (CronoType o)
{
result = o;
}
+ else if (o instanceof Symbol)
+ {
+ Symbol s = (Symbol) o;
+ result = getEnv().get(s);
+ }
else if (o instanceof Cons)
{
/* Here we do two steps at once, both a translation
@@ -39,63 +98,47 @@ else if (o instanceof Cons)
*/
Cons c = (Cons) o;
CronoType head = c.car();
- if (head instanceof Symbol)
+ CronoType maybe_comb;
+ if ((maybe_comb = coerceCombinator(head)) != null)
{
- Symbol s = (Symbol) head;
- /* If the head position is occupied by a
- * "special" then we pass the whole cons to
- * a SpecialApplication.
- *
- * We don't evaluate the symbol, just look it
- * up, since we don't want to visit the head
- * twice
- */
- if (s.isCombinator())
+ c = new Cons(maybe_comb, c.cdr());
+ CombinatorApplication ca = new CombinatorApplication(c);
+ result = ca.reduce(this);
+ }
+ else
+ {
+ head = head.accept(this);
+ if (head instanceof Special)
{
- CombinatorApplication ca = new CombinatorApplication(c);
- result = ca.reduce(this);
+ SpecialForm sf = new SpecialForm(c);
+ /* If we wanted only to create an AST,
+ * we would stop here.
+ * However, we create the nodes and
+ * evaluate on the fly
+ */
+ result = sf.reduce(this);
}
- else
+ else if (head instanceof Function)
{
- CronoType t = getEnv().get(s);
- if (t instanceof Special)
- {
- SpecialForm sf = new SpecialForm(c);
- /* If we wanted only to create an AST,
- * we would stop here.
- * However, we create the nodes and
- * evaluate on the fly
- */
- result = sf.reduce(this);
- }
+ /*
+ * We assume function application by default
+ * Note that this assumption is relied on architecturally:
+ * Specials *are* Functions, Specials must always be checked
+ * before this case if they are to be matched...specifically
+ */
+ FunctionApplication fa = new FunctionApplication(c);
+ /* If we wanted only to create an AST,
+ * we would stop here.
+ */
+ result = fa.apply(this);
}
}
-
- if (result == null)
- {
- /*
- * We assume function application by default
- * Note that this assumption is relied on architecturally:
- * Specials *are* Functions, Specials must always be checked
- * before this case if they are to be matched...specifically
- */
- FunctionApplication fa = new FunctionApplication(c);
- /* If we wanted only to create an AST,
- * we would stop here.
- */
- result = fa.apply(this);
- }
}
else if (o instanceof Quote)
{
Quote q = (Quote) o;
result = q.node;
}
- else if (o instanceof Symbol)
- {
- Symbol s = (Symbol) o;
- result = getEnv().get(s);
- }
else
{
result = o;
@@ -27,6 +27,7 @@
*/
public CombinatorApplication (Cons c)
{
+ System.out.println("Reducing combinatory expression " + c);
function = c.car();
// Unchecked cdr assumed to be cons
args = ((Cons) c.cdr()).toList();
@@ -47,11 +48,12 @@ public CronoType reduce (Visitor v)
* This may be extended to a "callable"
* later
*/
- CronoType o = function.accept(v);
System.out.printf("Reducing combinatory expression...\n");
+ CronoType o = function.accept(v);
CronoType result = null;
if (o instanceof LambdaFunction)
{
+ System.out.println("Simple combinator...");
LambdaFunction f = (LambdaFunction) o;
/* The arguments are passed to the function
@@ -63,7 +65,12 @@ public CronoType reduce (Visitor v)
* arguments.
*/
- if (f.arity == args.size())
+ System.out.println(args);
+ if (args.size() == 0)
+ {
+ result = function;
+ }
+ else if (f.arity == args.size())
{
CronoType substituted_body = f.body[0];
int i = 0;
@@ -76,21 +83,51 @@ public CronoType reduce (Visitor v)
/* We have to keep evaluating this to reduce it to a value */
result = substituted_body.accept(v);
}
+ else if (f.arity < args.size())
+ {
+ /* we take as many as we need and leave the rest alone */
+ Cons usable_args = Cons.fromList(args.subList(0, f.arity));
+ Cons rest_of_args = Cons.fromList(args.subList(f.arity, args.size()));
+ /* We can use either the combinator or function application
+ /* We can use either the combinator or function application
+ * path for this
+ */
+ CronoType reduced = (new Cons(function, usable_args)).accept(v);
+ Cons new_expr = Nil.NIL;
+ if (reduced instanceof Cons)
+ {
+ new_expr = ((Cons) reduced).append(rest_of_args);
+ }
+ else
+ {
+ new_expr = new Cons(reduced, rest_of_args);
+ }
+ result = new_expr.accept(v);
+ }
else
{
+ System.out.println("Not enough arguments to combinator...");
result = new Cons(function, Cons.fromList(args));
}
}
+ else if (o instanceof Cons)
+ {
+ /* We have to append this to args */
+ System.out.println("Reducing parethesized combinator...");
+ Cons reduced = ((Cons) o).append(Cons.fromList(args));
+ result = reduced.accept(v);
+ }
else
{
throw new TypeException(this, Function.TYPEID, o);
}
+ System.out.println("Reduced expression: " + result);
return result;
}
public String toString ()
{
- return "(apply " + function.toString() + " " + args.toString() + ")";
+ return "(comb_apply " + function.toString() + " " + args.toString() + ")";
}
public TypeId typeId() {
return CombinatorApplication.TYPEID;
Oops, something went wrong.

0 comments on commit 4a349d5

Please sign in to comment.