Homework Assignment # 6
Due Monday March 7, 2011 by 9:00 pm. Use turnin to submit your homework (i.e., turnin -submit stober cs345_hw6 Python.g Lambda.java Call.java Extra.txt)
As shown in class "let" can be made redundant.
In the textbook, the author says the following:
Now that we have functions and function invocation as two distinct
primitives, we can combine them to recover the behavior of "with" [i.e., "let"] as a
special case. Every time we encounter an expression of the form
- {with {var named} body}
- we can replace it with
- {{fun {var} body} named}
Example:
- In DrRacket:
- > (calc (parse '{with {x {+ 5 5}} {with {y {- x 3}} {+ y y}}}) )
- 14
- In jython:
- >>> (lambda x : (lambda y : y + y) (x - 3) ) (5 + 5)
- 14
I propose the following syntax for "let " in jython
- (let x : 10 : x - 3)() // in this case, let x be 10 and then substitute 10 for x in "x - 3"
which should translate into the following:
- (lambda x : x - 3)(10)
This homework is to modify the jython grammar to accept the "let" statement above (i.e., (let var: expr: test)() ) and then translate it into the appropriate jython lambda application.
Here's how you might go about this:
- Modify lambdef in Python.g to have a LET rule after the LAMBDA rule. The LET rule should recognize the above syntax. Note: this syntax should be of the form "LET varargslist COLON expr[expr_contextType.Load] COLON test[expr_contextType.Load] ".
- Modify PartialPython.g and Base.g in a manner similar to what exists in them for lambdef already. (Don't turnin PartialPython.g or Base.g).
- Once you have this working, study the AST so you can see what's going on internally.
This can be done by invoking /dist/bin/jython ast/astview.py yourTestFile.py
- Add a new constructor to Lambda.java that expects the let "expr" along with the other arguments that Lambda already accepts.
- Call the new constructor with "etype = new Lambda($LET, a, actions.castExpr($test.tree), actions.castExpr($expr.tree)); " in the new Let rule.
- Store the let "expr" in a new member variable (maybe named let_expr) in Lambda.
- Modify the appropriate Call.java constructor such that if "func" is an instanceOf Lambda and "args.size() == 0" and "let_expr != null", then add the let "expr" that was passed to Lambda (let_expr) to Call's "args' list.
This may be tricky because you probably won't be able to see "func's" Lambda members or methods becuase Java thinks of it as an expr. One way to get around this is to make a new Lambda l and set l = (Lambda) func. Then, using l, you should be able to see and get what you need.
Then you should get the following when you try this out:
$ dist/bin/jython
Jython 2.5.2rc4 (trunk, Feb 27 2011, 21:35:17)
[Java HotSpot(TM) Client VM (Sun Microsystems Inc.)] on java1.6.0_23
Type "help", "copyright", "credits" or "license" for more information.
>>> (let x: 11: x*2)()
22
>>>
------------------------------------------------------
Possible extra credit worth 7 points that you can add to quiz and/or homework score(s):
[5 Points] Implement Let as (let list_of_vars: list_of_exprs: test)(). If you include Extra.txt, the TAs will assume you did the extra credit.
[2 Points] Use this to show if this implementation of Let is statically or dynamically scoped. Put your answer in Extra.txt.