SMiLe and Tetris
-
**Due:** 11:00pm Tuesday, April 21 - Checkpoint: 11:00pm Tuesday, April 21: submit one of the two parts
- Due: 11:00pm Tuesday, April 28: full assignment due
- Files:
- fork wellesleycs251 / cs251-tetris, share with fturbak
- Programming answers in
smile.sml,tetris_assignment.rb - Time estimates in
time.txt
- Submission: commit and push your completed work to your Bitbucket fork.
- Relevant reading:
- SML and Ruby References
- Especially SML notes on evaluation rules for pattern-matching, etc.
- Tools:
- Collaboration:
- All problems fall under the group collaboration policy. You may work with one or zero partners to produce one solution for this assignment. You may discuss ideas with other groups but your group’s writing and code must be due to your group members only.
- Advice:
- Smiling and playing Tetris are both fun. Playing too much Tetris can
make the assignment take longer than necessary; smiling too much cannot! :)
- Smiling and playing Tetris are both fun. Playing too much Tetris can
1. SMiLe Interpreter [50 points]
In class, we have been building an interpreter for our (currently) dynamically-typed subset of ML (alternately called SMiLe and SortaML). In this assignment, you will answer some questions about the cases we have completed and you will complete the interpreter by finish the last cases of the eval function: Fun bindings and the Case expression, i.e., pattern-matching.
-
Understanding Environments and Closures (Again)
Add English descriptions at each
(* Describe *)comment insmile.smlto document precisely what the steps of theFnandApplycases do and how they interact with each other. -
FunBindingsWe implemented
Valbindings inLetexpressions together in class. You will add support forFunbindings.A
Fun(f,x,e)binding has three pieces: a string giving the name for the function (f), a string giving the name for the parameter (x), and anexprfor the body (e). Evaluating aFunbinding as part of aLetexpression should produce an environment that extends the current environment with an association offand a closure for the SMiLe function defined. The closure must support recursion, meaning that the environment it saves must have a mapping fromfto the closure itself. It is legal for the SMiLe expressionVar fto appear insidee, and this must work when an application of the closure is evaluated. (Hint, this is where therefin the type held byClosureVbecomes important.) See the factorial programs included insmile.smlfor examples.Make sure to document and test your code.
-
CaseExpressionsImplement
Caseexpressions for SMiLe following the semantics ofcaseexpressions in ML. ACaseexpression carries an expression,e, to evaluate and match against apattern list. Thepatterndatatype is given insmile.sml. Altogether, the whole section ofevalthat handle the SMiLeCaseexpression takes about 30 lines of ML code in our sample solution, as a ball-park figure. To accomplish pattern-matching for SMiLe, we added three ML helper functions, and suggest you do similarly:-
matchis a recursive function that checks to see if the evaluated expression’s value matches a single pattern. If the pattern and value match,matchreturnsSOMEof a list of(string * value)pairs representing all the bindings that the pattern introduces. If it does not match,matchreturnsNONE. The implementation uses ML pattern-matching to match simultaneously on a givenpatternconstructor andvalueconstructor.Given a
valuevandpatternp, eitherp
matchesvor not. If it does, the match produces a list
ofstring * valuepairs; order in the list does not matter. Assume that one pattern binds each possible variable at most once. In other words, no pattern will includeVarP "x"more than once. Make sure to respect this assumption in your test code … or implement a check if you prefer.The rules for matching should be unsurprising:
Wildcardmatches everything and produces the empty list of bindings.VarP smatches any valuevand produces the one-element list holding(s,v).UnitPmatches onlyUnitVand produces the empty list of bindings.BoolP falsematches onlyBoolV falseand produces the empty list of bindings (and similarly for other booleans).IntP 17matches onlyIntV 17and produces the empty list of bindings (and similarly for other integers).StringP "smile"matches onlyStringV "smile"and produces the empty list of bindings (and similarly for other strings).TupleP psmatches a value of the formTupleV vsifpsandvshave the same length and for alli, the ith element ofpsmatches the ith element ofvs. The list of bindings produced is all the lists from the nested pattern matches appended together.TagP(s1,p)matchesTagV(s2,v)ifs1ands2are the same string (you can compare them with=) andpmatchesv. The list of bindings produced is the list from the nested pattern match. We call the stringss1ands2the constructor name.- Nothing else matches.
tuplematchis a recursive helper function used when matching tuple patterns recursively inmatch.evalcaseis a recursive function that iterates through the list of(pattern * expr)cases given in theCaseexpression, applyingmatchto eachpattern. For the first pattern that matches,evalcasethen evaluates the associated resultexprfrom the list, using the current environment extended with all the bindings introduced by the pattern. If no pattern matches, raiseNoMatch.
In addition to implementing the matching code, write SMiLe programs to test it.
-
-
Optional Extension (0 points)
As an optional extension, change
Val,FunandFnto support arbitrary binding-introducing patterns instead of just a parameter name. This will involve changing the type of arguments to these constructors fromsymtopatternand using the same pattern-matching code you built forCasein every function application. -
Optional Challenge (0 points)
As an optional challenge problem, implement basic type-checking for SMiLe:
- Define an ML datatype,
typ, describing types of SMiLe expressions. Many of its constructors will mirror the constructors of thevaluedatatype. Start without type variables – add those later if you get a simpler type-checker working. Also start without support for type-checking patterns or constructors. If you succeed in type-checking these simpler programs, consider adding explicitDataTypebindings to the SMiLe language, and accompanying support intypfor datatypes. - Define an ML function,
typecheck : expr -> typ -> bool, that takes a SMiLe expression and a SMiLe type and checks whether that expression has that type. Follow the type-checking rules we have established for ML. (Again, start without type variables, patterns, or constructors.) Remember, your job here is only to check the given type, not to infer it. (Naturally, to test yourtypecheckimplementation, you will have to manually infer types to pass totypecheck.)
- Define an ML datatype,
2. Tetris [50 points]
This assignment is adopted from CSE 341 at the University of Washington.
See intructions for installing or using ruby and irb, an interpreter and a REPL for the Ruby language. There is minor configuration to do on tempest (cs.wellesley.edu – one line to a configuration file). There are also instructions for installing on your own machine. [Windows instructions may currently include a broken link.]
Please see the PDF tetris instructions, also distributed with the starter code.