CS 291 Assignment #9

Due Monday, May 4th (by 11:59pm)
Not accepted after May 6th

The Assignment

For your final assignment, you'll build an SECD machine in Prolog. The SECD was one of the earliest constructs for evaluating lambda-calculus expressions, so we can actually try using it to evaluate some of the lambda terms we discussed in the first half of the semester. Before starting this assignment, make sure you read the description of the SECD Machine. (It will help if you've looked at the sample evaluations linked to from that document, and understand the basic workings of the SECD.) As with the graph coloring project, I'm breaking the SECD down into smaller pieces for you. The problems below will guide you through the steps of creating an SECD implementation.
  1. Define the relation lookup(Var,Env,Val), which is true if Var is bound to Val in the list of bindings Env. Val should be the first binding for Var found in Env.
    ?- lookup(n, [], Val).
    Val = n.
    
    ?- lookup(n, [b(m,5),b(n,10)], Val).
    Val = 10 ;
    false.
    
    ?- lookup(n, [b(n,5),b(n,10)], Val).
    Val = 5 ;
    false.
    
    ?- lookup(n, [b(m,10)], Val).
    Val = n.
    
  2. Implement the seven transformation rules in the format shown below. Actually, you'll only need to implement five of the rules: I'm doing the first one for you, and you can skip rule #5 until you get the rest working. Here's the first transformation rule:
    % Rule 1: There's a constant at the top of the control stack.  Pop it
    % off of C and push it onto S.
    %
    transform(secd(S, E, [C|Cs], D),
    	  secd([C|S], E, Cs, D)) :- integer(C).
    
  3. Define a predicate reduce(State,Val) that is true if State is an SECD machine state, and Val is the entry at the top of the S stack once State has been simplified to a final machine state according to the transformation rules you implemented above. (The sample inputs below represent a final SECD state, evaluation of a variable, and evaluation of the expression (head (cons 5 (cons 6 0))).)
    ?- reduce(secd([7],[],[],[]), Val).
    Val = 7.
    
    ?- reduce(secd([],[b(n,5),b(n,10)],[n],[]),Val).
    Val = 5 ;
    false.
    
    ?- reduce(secd([], 
    |              [],
    |              [app(lam(l,app(l,lam(x,lam(y,x)))),
    |                   app(app(lam(h,lam(t,lam(s,app(app(s,h),t)))),5),
    |                       app(app(lam(h,lam(t,lam(s,app(app(s,h),t)))),6),0)))],
    |              []), Val).
    Val = 5 ;
    false.
    
  4. Define a predicate eval(Expr,Result) that is true if the lambda expression Expr evaluates to Result. It should be implemented in terms of your reduce predicate.
    ?- eval(5,X).
    X = 5 ;
    false.
    
    ?- eval(app(lam(x,lam(y,x)), 5), X).
    X = cl(y, x, [b(x, 5)]) ;
    false.
    
    ?- eval(app(lam(l,app(l,lam(x,lam(y,x)))),
    |           app(app(lam(h,lam(t,lam(s,app(app(s,h),t)))),5),
    |               app(app(lam(h,lam(t,lam(s,app(app(s,h),t)))),6),0))), 
    |               Result).
    Result = 5 ;
    false.
    
  5. Add the built-in functions inc, dec, and iszero to your SECD implementation. As you implement rule #5, you should keep the details of each of the built-in functions separate from the transformation rule. (That is, don't write three different versions of rule 5 — one for each built-in function — just write one new transformation rule.) The iszero built-in should take an integer as input, but return the appropriate lambda-calculus representation of true (λx.λy.x) and false (λx.λy.y). (Note that in the iszero examples below, these lambda expressions have been evaluated into closures before being returned.)
    ?- eval(app(inc,3), R).
    R = 4 ;
    false.
    
    ?- eval(app(dec,7), R).
    R = 6 ;
    false.
    
    ?- eval(app(dec,app(dec,7)), R).
    R = 5 ;
    false.
    
    ?- eval(app(iszero,0), R).
    R = cl(x, lam(y, x), []) ;
    false.
    
    ?- eval(app(iszero,5), R).
    R = cl(x, lam(y, y), []) ;
    false.
    
    ?- IF=lam(p,lam(t,lam(f,app(app(p,t),f)))),
    |    eval(app(app(app(IF,app(iszero,2)), 1), 0), R).
    IF = lam(p, lam(t, lam(f, app(app(p, t), f))))
    R = 0 ;
    false.
    

Extending the Assignment

If you finish the basic SECD machine and are hankerin' for more of a challenge, consider one of the following extensions:

Submitting:

Submit your file as an attachment to me at brichards@ups.edu.


Brad Richards, 2009