If you have stumbled upon this site, looking for cs502 content, or would like to create a blog for the CS502 class, please email me and I would gladly hand this site over to you.
October 16, 2006
Reminder: I have no idea what is on the exam. Like everyone else, I’m just speculating…
Possible Flow Analyses : Prof Jan Vitek‘s cs510 class has some interesting slides (see any similarities?) Particularly useful ones:
- Slide 53+ : The Overall Pattern
- Slide 63: A nice table of the analyses
- Slide 82+: Interprocedural Analyses (100-102 are caveats)
Possible compiler optimization/analysis that might be on the midterm:
Possible Language additions:
- Introduce “loop” primitive
- Create overloaded function (like + : ((int * int) -> int) | ((string * string) -> string))
- Adding OO constructs to the language (using records, maybe)
- Call-cc
As always, please post your speculations as well. Anyone interested in group cramming studying, say this evening 8:00p in LWSN common? (214) for oh for-8096
October 15, 2006
I went through the lecture slides and jotted down some notes on anything that I was still confused about. Please feel free to comment on, answer the questions in, or added on to this list of questions:
Lecture 3:
slide 17:
Problem: In class, Prof. Jagannathan challenged us to come up with a case where the BFH fails.
Solution (?): given the bool and color datatypes, supply the following patterns:
p1 = (x, red)
p2 = (false, blue)
p3 = (true, green)
The tree generated by the BFH will have 10 nodes.
The optimal tree has 8 nodes.
Is this due to the prescence of variables in the bool position?
Lecture 4:
slide 26: Could “fn f => (f(13), f(true))” work if we could promise that the f passed in will always be over type variables, not concrete types? Is this the kind of power that explicit type variable systems (which he refers to on slide 9) have?
slide 36:
Question posed: “What about lists?”
Answer (?): A box just a pointer, so we would just make a pointer to the list, similar to how we box other non-word-sized data structures
Lecture 7:
slide 10: Question posed: “How might we identify loops in Core-ML?”
Answer (?): Label any recursive call as effectively being a loop
Lecture 8:
slide 11: Shouldn’t the third line of the first example be:
“in if b then g(13, k) else g(15, k’)” ?
Lecture 10:
slide 3: Given that direction is a component of program analysis, how can flow-independent analysis exist?
~Bill Harris
October 12, 2006
Due: Oct 25, 2006
“While CPS’ed programs make control-flow explicit, the resulting output is inefficient, and still far removed from the format necessary to enable efficient code generation. For this project, you will simplify CPS programs. While there are many optimizations possible, we will concentrate on particularly important one:
Continuations that are not exported via a Non-Tail call, and which are instantiated
at most once via a Goto, can be inlined at the point of call.”
http://www.cs.purdue.edu/homes/suresh/502-Fall2006/project/cps-opt.tgz
October 9, 2006
October 9, 2006
These are just some straightforward tests. If anyone has others, please post. Sign up for an account: http://www.wordpress.com . It’s quick and spam-free!
(* The following are a list of my tests
* Each are one line (except a few at the bottom
* and DO NOT EXECUTE THE ENTIRE FILE at once.
*)
let fun f(x) = x in 13 end
let fun f(x) = x in f(13) end
(*make sure applying f not just returning 13*)
let fun f(x) = 7 in f(13) end
(*tail and nontail*)
let fun f(x) = let fun g(y) = x in g end in (f(13)) 7 end
(*binop*)
let val x = 4 + 2 in x end
let fun f(x) = 7 in f(13) + 5 end
let fun f(x) = 7 in 5 + f(13) end
let fun f(x) = let fun g(y) = x + y in g end in (f(13)) 7 end (*20*)
let fun f(x) = let fun g(y) = y + x in g end in (f(13)) 7 end (*20*)
(*anon funcs*)
val _ = (fn(x) => x) 13
let fun f(x) = (fn(y) => y + x) in (f(13)) 7 end
(*Unary funcs*)
val _ = ~(1 + 3)
(*tuple*)
let fun f(x) = 1 + x in (f(13), f(14), f(7), f(5)) end
(*Subscripts*)
val _ = #2 (5, 6, 7)
(*refs and order-of-eval-in-tuples/binops*)
val _ = ! (ref 0)
let val r = ref 0 val _ = (r := 1) val _ = (r := 2) in !r end
(* Should the following return 1 or 2? *)
let val r = ref 1
fun setTwo(x) =
let val _ = (r := 2)
in 0
end
in !r + setTwo()
end
(* Should the following return 1 or 2? *)
let val r = ref 1
fun setTwo(x) =
let val _ = (r := 2)
in 0
end
in setTwo() + !r
end
let val r = ref 1
fun two(x) = (r := 2)
fun five(x) = (r := 5)
in (!r, two(), !r, five(), !r)
end
(*ifthenelse*)
let fun fact(n) = if n < 1 then 1 else n * fact(n-1) in fact(4) end
(*Datatypes*)
let fun iotaHelper(x) =
(case x
of (0,l) => l
| (n,l) => iotaHelper(n-1,Cons(n,l)))
in iotaHelper(3,Nil)
end
(* Non-exhaustive Case tests: *)
let fun test(p) =
case p
of 0 => 0
in (test 0)
end
(* at this point you can try test-map.mml
* SUGGESTION: change the noisy flag to false (cps-interp.sml line 382)
* Otherwise, you'll be sitting around for hours ; )
*)
October 4, 2006
Anyone else done with Project 3? If not and you want to meet, give me a call: (214) 404-8096. Until then I’ll post some thoughts on the project.
Allthe work is in cps.sml’s cps function. Basically, you’re just connecting work you recursively did with the current computation (whether it’s a binop, apply, tuple, etc)
The cps function has 3 args: ce, ko, and kl. Now you may be wondering “Well when the heck do I use ko and kl??” That’s easy:
- ko : this will be
NONEwhen there is nothing left to do after computingce - kl : this is ALWAYS appended to, and NEVER removed from. You will have to append every continuation created to it
Suggested ordering for implementing the body of cps:
LetRec: Simplelet fun ...without applications.App: GetTailandNonTailworking. This should be the first time you’ll create a continuation. So you’ll need:Label, Id, RetVal, Ret. make sure you prepend the cont you created before returning!BinOp, UnOp: The tough part’s done (assuming you tested app thoroughly) so these should two should be a breeze. Notes: Take advantage ofbuildSimpleCont. You can’t test if you are evaluating binops correctly until you haveref‘s doneFnTuple: Here, I usedList.foldr3 times Notes: Take advantage ofbuildSimpleCont. You can’t test if you are evaluating tuples in the right order until you can create side-effectsIth, SetIth: These are needed for refs- Retest Binops and Tuples. Create a test and run it in SML/NJ and compare. Note: Assignments in MiniML don’t return unit.
IfConstructorError
Once you decide to try out test-map.mml I’d suggest unsetting the noisy flag (cps-interp.sml line 382). Otherwise you’ll be sitting around for hours waiting for the compiler to print.
Some tests to get started:
let fun f(x) = x in 13 end let fun f(x) = x in f(13) end (*make sure applying f not just returning 13*) let fun f(x) = 7 in f(13) end (*tail and nontail*) let fun f(x) = let fun g(y) = x in g end in (f(13)) 7 end
Happy coding!
September 27, 2006
Lecture Notes 1 (Data Types & Pattern Matching)
Posted by Philip Schatz under scribeLeave a Comment
Data Types
In MiniML: bool, int option, int list
datatype shape = Circle of real * real * real
Recursive Types
- Context-free Grammar
- Inductive (leaves are just ints)
Using Abstraction
Fold is your friend! fold takes a list, state (accumulator), and a folder.
internal function loop.
base case: empty list
induction step: apply folder to (head, state), and recursively call loop on the tail
map:
Generative Datatypes
Pattern Matching
like switches except not just on ints (or enums)
can be:
case s
of x => e1 (* any subject matches this pattern *)
| _ => e2 (* same as x but discarded *)
| 3 => e3 (* matches when s = 3 *)
| (p1, p2, pn) => e4 (* provided s is a tuple
* and the correct arity
* (guaranteed already by
* the type checker)
* pn can be a pattern
*)
| C y => e5 (* Matches Constructor AND
* y can be a tuple, constructor,
* record, etc.
*)
Quirks
case s of (1, 2) => e1 | (1, 3) => e2
A naive compiler would ask “Is the 1st element 1?” twice. In general, this is NP complete.
Infeasible/Silly
case s of x => e1 | 3 => e2
x will always match
fun diff(nil, y) = y(1) | diff(x, nil) = x(1)
Overlapping (nil, nil) so y(1) will never be executed.
Questions?
case s of Cons(x) => e (* 1-tuple = variable *) | Cons(y, nil) => e (* redundant *)
One cannot call functions ins a pattern, or match on the value of a ref. However, SML lists can be deconstructed using :: as in the following:
case s of [] => e (* empty list *) | hd :: tail => e (* non-empty list *)
Example
case s : (bool * intlist) of (true, _) => p1 | (false, nil) => p2 | (false, Cons(x,Nil)) => p3 | (false, Cons(y,z)) => p4
Is the order of matching important?
If the ordering is right to left, then the correct match will not happen until both arguments are matched (since _ is the wildcard)
Are p3, p4 redundant?
No, because p3 is more specific but overlapping. It matches specifically Nil while p4′s last argument matches anything and assigns the value to y
Is case s of x => e | 3 => e redundant?
Yes, because x will always match because of ordering and 3 will never
August 30, 2006
Here’s some random stuff I found useful after discussing with Phil on “how to start writing ML.”
1. use eval_be to handle binary operations and eval_ue for unary operations.
2. use conv() to handle A.Const_e and A.DataCon_e
3. patMatch() basically handle two cases: “Let val …” and “case … of …” both of these requires pattern matching (that’s why it is there).
4. Before you handling A.Let_e(A.Val_d(…)) in patMatch, it is a good idea to study how A.Case_e() works in patMatch. That should give you some hint on how to proceed.
5. Don’t worry about the A.Id_t(“pat”) or A.Id_t(“patType”) that you found in interp.sml. They are not used at all.
6. http://www.standardml.org/Basis/list-pair.html contains useful function to use when handling A.Tuple_p and A.Record_p in pat_compile. Specifically you need to walk down the tuple/records and perform matching one by one. ListPair is different from List where ListPair walk down two lists simultaneously (your root and p) whereas List do the same thing on one list.
7. Lastly, the assignment statement “x := 3″ returns a unit “()”.
August 29, 2006
I’m leaving the country Tuesday Aug 29 until Sept 21. JC has volunteered to add everyone who wishes to contribute to the projects posts and post scribe notes while I’m gone.
Best of luck!
August 28, 2006
For Sale!!! 1 MiniML interpreter for the LOW LOW price of just countless hours!! Seriously though, here are some (possibly) useful notes on how to tackle this beast (Make sure you start early)
Basically there are two parts, evaluate and pattern_compile. For evaluate, I’d suggest the following (in order):
- Const/Id
- Unop/Binop
- Fn/App
- Ref/Deref/Assign
- Tuple/Ith
- Datacon/If
- Let(Fun)
- Case/Let(Val)
- Record/Field
You won’t need to touch patterns until Case/Let(Val). And you’ll need DataCon to do If, and everything before to do Case/Let(Val).
August 26, 2006

A lot of time with SML, at least initially, will probably be spent fighting with the compiler. Specifically the cryptic compiler errors that are spit out. For those that are not fearful of IDE’s here’s a nifty plugin for eclipse that parses your SML and puts thosse infamous squigglys under the BAD parts of code. It works (hehe) and has been tested but I offer little support for the plugin. Attached is the zip file that you extract unto your eclipse/plugins dir.
The plugin creates a SML perspective and does all the nifty syntax highlighting for your sml (and sig) files. If you have smlnj installed, you can also optionally run the program from withing eclipse, or use MLton to typecheck every time you save (useful, but possibly time consuming). If there is interest, I’ll post how to do all of those.
Unlike the java editor however, it has no debugging/breakpoint support. After all, it’s only written by two people (but eclipse hackers are welcome to contribute!)
So, without further ado, here’s the link to the zip file:
http://www.cs.purdue.edu/homes/schatzp/cs502/ml-dev_2006-08-26.zip
And the user guide (a little older):
http://www.cse.iitd.ernet.in/~csu02132/mldev/userguide/
August 26, 2006
If anyone wants to check their project, pasting the code into smlnj is the best way, but if you’re on a linux machine you can run my compiled binary. It has a debug option that will print out the expression tree on every iteration of eval (type “:d” into the interpreter to toggle)
Changes to get interpreter to work on MLton:
- Run MLton versions of ml-lex and ml-yacc (smlnj uses Unsafe structure)
- Change some matches in typecheck.sml
- Add mlb, and main SML file that just runs the interpreter
The following tar.gz file has the MLton modifications and my compiled interpreter:
http://www.cs.purdue.edu/homes/schatzp/cs502/cs502-interp_mltonized_2006-08-26.zip
August 25, 2006
OK, I think I’m just about done with the project (anyone else? or have you not started yet?)
You can run the miniML code (for sanity sake) in SML/NJ simply by doing the following:
- type [
datatype 'a list = Nil | Cons of 'a * 'a list;] into SML/NJ - In a separate editor, open the test case and replace “\nval” with “\n;val” (so the values are printed to stdout) (but don’t save the file since miniML doesn’t like “;”)
- Paste the code into SML/NJ.
Time permitting, I may compile compiled my interpreter (it’s NOT A REFERENCE IMPL) using MLton (http://mlton.org) and post linux/windows binaries.
