PS7: Open to Interpretation
- Due: Tuesday, April 26
- Notes:
- This problem set is now complete. It has four problems worth 100 points.
- It has been designed in such a way that you can expect 10 points to require approximately 1 hour. Please let me know if this expectation is wrong on particular problems!
- Please keep track of the time estimates for each problem/subproblem.
- Submission:
- In the yourFullName CS251 Spring 2016 Folder, create a Google Doc named yourFullName CS251 PS7.
- For each problem and subproblem, please indicate at the beginning of each writeup approximately how long that problem took you to solve and write up.
- You will create the following code files in this pset:
- Problem 1:
yourAccountName-BindexToPostFix.sml
- Problem 2 :
Simprex.sml
andSimprexEnvInterp.sml
- Problems 3 and 4:
Valex.sml
- Problem 1:
- Include all answers, including copies of relevant code from your
.sml
files in your PS7 Google Doc. - Drop copies of your
.sml
files in your~/cs251/drop/ps07
drop folder oncs.wellesley.edu
.
1. Bindex To PostFix (25 points)
Background
In lecture, we studied the following intexToPostFix
function that automatically translates Intex programs to equivalent PostFix programs:
fun intexToPostFix (Intex.Intex(numargs, exp)) =
PostFix.PostFix(numargs, expToCmds exp 0)
(* 0 is a depth argument that statically tracks
how many values are on stack above the arguments *)
and expToCmds (Intex.Int i) depth = [PostFix.Int i]
| expToCmds (Intex.Arg index) depth = [PostFix.Int (index + depth), PostFix.Nget]
(* specified argument is on stack at index + depth *)
| expToCmds (Intex.BinApp(binop,exp1,exp2)) depth =
(expToCmds exp1 depth) (* 1st operand is at same depth as whole binapp *)
@ (expToCmds exp2 (depth + 1)) (* for 2nd operand, add 1 to depth
to account for 1st operand *)
@ [PostFix.Arithop (binopToArithop binop)]
and binopToArithop Intex.Add = PostFix.Add
| binopToArithop Intex.Sub = PostFix.Sub
| binopToArithop Intex.Mul = PostFix.Mul
| binopToArithop Intex.Div = PostFix.Div
| binopToArithop Intex.Rem = PostFix.Rem
For example, given the Intex program intexP2
expressed as an Intex.pgm
datatype instance
val intexP2 = Intex(4, BinApp(Mul,
BinApp(Sub, Arg 1, Arg 2),
BinApp(Div, Arg 3, Arg 4)))
the intexToPostFix
translation is as follows:
- intexToPostFix(intexP2);
val it =
PostFix
(4,
[Int 1,Nget,Int 3,Nget,Arithop Sub,Int 4,Nget,Int 6,Nget,Arithop Div,
Arithop Mul]) : PostFix.pgm
With the helper function translateString
shown below, the input and output of translation can be expressed as strings in s-expression format:
fun translateString intexPgmString =
PostFix.pgmToString (intexToPostFix (Intex.stringToPgm intexPgmString))
- IntexToPostFix.translateString("(intex 4 (* (- ($ 1) ($ 2)) (/ ($ 3) ($ 4))))");
val it = "(postfix 4 1 nget 3 nget sub 4 nget 6 nget div mul)" : string
There are two key aspects to the translation from Intex to PostFix:
-
The
expToCmds
function translates every Intex expression to a sequence of PostFix commands that, when executed, will push the integer value of that expression onto the stack. In the case of translating a binary application expression, these sequence is composed by appending the sequences for the two operands followed by the appropriate arithmetic operator command. -
The trickiest part of
expToCommands
is knowing how many integers are on the stack above the program arguments, so that references to Intex arguments by index can be appropriately translated. This is handled by adepth
argument toexpToCommands
that keeps track of this number. Note that the first operand of a binary application has the same depth as the whole binary application expression, but the second operand has a depth one greater than the first to account for the integer value of the first operand pushed onto the stack.
Your Task
In this problem, you will implement a similar translator from Bindex programs to PostFix programs.
Begin by performing the following steps:
-
I assume you already have a directory named
/home/wx/cs251-download
. If not, please create it as follows via this command in a Linux shell:mkdir /home/wx/cs251-download
-
Copy the entire contents of the
cs251-download
directory oncs.wellesleley.edu
to your localcs251-download
directory using the following command. This may overwrite some of your existing files in this directory, but that’s OK. (If you think it’s not OK, then save versions of files you care about elsewhere first!) Of course, as usual, here and elsewhere you should replace usernamegdome
by your own account name:scp -r gdome@cs.wellesley.edu:/home/cs251/download/* /home/wx/cs251-download
-
Immediately make a copy of the
bindex-to-postfix/BindexToPostFixSkeleton.sml
program that begins with your username and omitsSkeleton
. (Again, replacegdome
by your username):cd /home/wx/cs251-download/bindex-to-postfix cp BindexToPostFixSkeleton.sml gdome-BindexToPostFix.sml
-
If you don’t already have one, create a
*sml*
SML interpreter buffer within Emacs. -
In the
*sml*
buffer, execute the following SML command to change the default directory:- Posix.FileSys.chdir "/home/wx/cs251-download/bindex-to-postfix";
-
Finally, take your
gdome-BindexToPostFix.sml
for a spin. This will print out lots of information, which is omitted below.- use "gdome-BindexToPostFix.sml"; ... lots of information omitted ...
The file gdome-BindexToPostFix.sml
contains a skeleton of the Bindex to PostFix translator in which all Bindex expressions translate to a command sequence consisting of the single integer command 42
:
fun makeArgEnv args = Env.make args (Utils.range 1 ((length args) + 1))
(* returned env associates each arg name with its 1-based index *)
fun envPushAll env = Env.map (fn index => index + 1) env
(* add one to the index for each name in env *)
fun envPush name env = Env.bind name 1 (envPushAll env)
fun bindexToPostFix (Bindex.Bindex(args, body)) =
PostFix.PostFix(length args, expToCmds body (makeArgEnv args))
(* In expToCmds, env statically tracks the depth of each named variable
value on the stack *)
and expToCmds (Bindex.Int i) env = [PostFix.Int 42] (* replace this stub *)
| expToCmds (Bindex.Var name) env = [PostFix.Int 42] (* replace this stub *)
| expToCmds (Bindex.BinApp(binop, rand1, rand2)) env = [PostFix.Int 42] (* replace this stub *)
| expToCmds (Bindex.Bind(name, defn, body)) env = [PostFix.Int 42] (* replace this stub *)
and binopToArithop Bindex.Add = PostFix.Add
| binopToArithop Bindex.Sub = PostFix.Sub
| binopToArithop Bindex.Mul = PostFix.Mul
| binopToArithop Bindex.Div = PostFix.Div
| binopToArithop Bindex.Rem = PostFix.Rem
When loaded, the gdome-BindexToPostFix.sml
file performs numerous tests of the translator. Initially, all of these fail. Your task is to redefine the clauses of expToCmds
so that all the test cases succeed.
Notes:
-
The
expToCmds
function in the Bindex to PostFix translator uses an environment to track the depth of each variable name in the program. Recall that an environment (defined by theEnv
structure inutils/Env.sml
) maps names to values. In this case, it maps names in a Bindex program to the current stack depth of the value associated with that name. Carefully study the helper functionsmakeArgEnv
,envPushAll
, andenvPush
to understand what they do; all are helpful in the contex of this problem. -
As in the Intex to PostFix translator, in the Bindex to PostFix translator, each Bindex expression should translate to a sequence of PostFix commands that, when executed, pushes exactly one value — the integer value of that expression — onto the stack.
-
For simplicity, you may assume there are no unbound variables in the Bindex program you are translating. With this assumption, you may use the
Option.valOf
function to extract the valuev
from aSOME(v)
value. -
The
BindexToPostFix
structure contains atestTranslator
function that takes the name of a file containing a Bindex program and a list of argument lists and (1) displays the Bindex program as an s-expression string, (2) displays the PostFix program resulting from the translation as an s-expression string and (3) tests the behavior of both programs on each of the argument lists in the list of argument lists. If the behaviors match, it prints an approprate message; if they don’t match, it reports an an error with the two different result values. For instance, in the initial skelton, the behavioral tests fail on the program in../bindex/avg.bdx
:Testing Bindex program file ../bindex/avg.bdx Bindex program input to translation: (bindex (a b) (/ (+ a b) 2)) PostFix program output of translation: (postfix 2 42) Testing args [3,7]: *** ERROR IN TRANSLATION *** Bindex result: 5 PostFix result: 42 Testing args [15,5]: *** ERROR IN TRANSLATION *** Bindex result: 10 PostFix result: 42
However, when the translator is working, the following will be displayed:
Testing Bindex program file ../bindex/avg.bdx Bindex program input to translation: (bindex (a b) (/ (+ a b) 2)) PostFix program output of translation: (postfix 2 1 nget 3 nget add 2 div) Testing args [3,7]: both programs return 5 Testing args [15,5]: both programs return 10
-
You have succeeded when all of the test cases succeed when you load the
.sml
file.
2. Simprex (30 points)
Background
Rae Q. Cerf of Toy-Languages-я-Us likes the sigma
construct from lecture, but she wants something more general. In addition to expressing sums, she would also like to express numeric functions like factorial and exponentiation that are easily definable via simple recursion. The functions that Rae wants to define all have the following form:
f(n) = z, if n ≤ 0
f(n) = c(n, f(n-1)), if n > 0
Here, z
is an integer that defines the value of f
for any non-positive integer value and and c
is a binary combining function that combines n
and the value of f(n−1)
for any positive n
. Expanding the definition yields:
f(n) = c(n, c(n-1, c(n−2, ... c(2, c(1, z)))))
For example, to define the factorial function, Rae uses:
z_fact = 1
c_fact(n, a) = n*a
To define the exponentation function bn, Rae uses:
z_expt = 1
c_expt(n, a) = b*a
In this case, c_expt
ignores its first argument, but the fact that c_expt
is called n
times is important.
As another example, Rae defines the sum of the squares of the integers between 1 and n using
z_sos = 0
c_sos(n, a) = (n*n) + a
Rae designs an extension to Bindex named Simprex that adds a new simprec
construct for expressing her simple recursions:
(simprec E_zero (Id_num Id_ans E_combine ) E_arg)
This simprec
expression evaluates E_arg
to the integer value n_arg
and E_zero
to the integer value n_zero
. If n_arg
≤ 0, it returns n_zero
. Otherwise, it returns the value
c(n_arg, c(n_arg−1, c(n_arg−2, ... c(2, c(1, nzero)))))
where c
is the binary combining function specified by (Id_num Id_ans E_combine)
. This denotes a two-argument function whose two formal parameters are named Id_num
and Id_ans
and whose body is E_combine
. The Id_num
parameter ranges over the numbers from n_arg
down to 1, while the Id_ans
parameter ranges over the answers built up by c
starting at n_zero
. The scope of Id_num
and Id_ans
includes only E_combine
; it does not include E_zero
or E_arg
.
Rae’s simprec
expression is closely related to the notion of primitive recursive functions defined in the theory of computation.
Here are some sample Simprex programs:
;; Program that calculuates the factorial of n
(simprex (n) (simprec 1 (x a (* x a)) n))
;; Exponentiation program raising base b to power p
(simprex (b p) (simprec 1 (n ans (* b ans)) p))
;; Program summing the squares of the numbers from 1 to x
(simprex (x) (simprec 0 (y z (+ (* y y) z)) x))
Your Tasks
After completing her design, Rae is called away to work on another langudage design problem. Toy-Languages-я-Us is impressed with your CS251 background, and has hired you to implement the Simprex language, starting with a version of the Sigmex implementation. (Sigmex is the name of the language that results from extending Bindex with the sigma construct from lecture.) Your first week on the job, you are asked to complete the following tasks that Rae has specified in a memo she has written about finishing her project.
-
(9 points) Rae’s memo contains the following Simprex test programs. Give the results of running each of the programs on the argument 3. Show your work so that you may get partial credit if your answer is incorrect.
;; program 1 (1 point) (simprex (a) (simprec 0 (b c (+ 2 c)) a)) ;; program 2 (2 points) (simprex (x) (simprec 0 (n sum (+ n (* x sum))) 4)) ;; program 3 (2 points) (simprex (y) (simprec 0 (a b (+ b (sigma c 1 a (* a c)))) y)) ;; program 4 (4 points) (simprex (n) (simprec (simprec (* n (- n 3)) (q r r) (* n n)) (c d (+ d (simprec 0 (x sum (+ sum (- (* 2 x) 1))) c))) (simprec -5 (a b (+ 1 b)) (* n n))))
-
(21 points)
Rae has created a skeleton implementation of Simprex by modifying the files for the Sigmex (= Bindex +
sigma
) implementation to contain stubs for thesimprec
construct. Her modified files, which are namedSimprexSkeleton.sml
andSimprexEnvInterpSkeleton.sml
can be downloaded via these steps:-
Perform this step again even if you already did it in Problem 1 (As a rule, you will perform this step when beginning any problem going forward.) Copy the entire contents of the
cs251-download
directory oncs.wellesleley.edu
to your localcs251-download
directory using the following command. Of course, as usual, here and elsewhere you should replace usernamegdome
by your own account name:scp -r gdome@cs.wellesley.edu:/home/cs251/download/* /home/wx/cs251-download
-
Immediately make copies of the
ps7/SimprexSkeleton.sml
andps7/SimprexEnvInterpSkeleton.sml
files namedSimprex.sml
andSimprexEnvInterp.sml
(i.e., without theSkeleton
suffix). Do not prepend your username to the front of these files.cd /home/wx/cs251-download/ps7 cp SimprexSkeleton.sml Simprex.sml cp SimprexEnvInterpSkeleton.sml SimprexEnvInterp.sml
-
In the
*sml*
buffer, execute the following SML command to change the default directory:- Posix.FileSys.chdir "/home/wx/cs251-download/ps7";
Finish Rae’s implementation of the Simprex language by completing the following four tasks, which Rae has listed in her memo:
-
(3 points) Extend the definition of
sexpToExp
inSimprex.sml
to correctly parsesimprec
expressions. -
(3 points) Extend the definition of
expToSexp
inSimprex.sml
to correctly unparsesimprec
expressions. -
(5 points) Extend the definition of
freeVarsExp
inSimprex.sml
to correctly determine the free variables of asimprec
expression. -
(10 points) Extend the definition of
eval
inSimprexEnvInterp.sml
to correctly evaluatesimprec
expressions using the environment model.
Notes:
-
This problem is similar the the Sigmex (= Bindex +
sigma
) language extension we implemented in lecture. You may wish to study the solution filesbindex/SigmexSolns.sml
andbindex/SigmexEnvInterp.sml
as part of doing this problem. -
In
Simprec.sml
, theexp
type is defined to be:and exp = Int of int (* integer literal with value *) | Var of var (* variable reference *) | BinApp of binop * exp * exp (* binary operator application with rator, rands *) | Bind of var * exp * exp (* bind name to value of defn in body *) | Sigma of var * exp * exp * exp (* E_lo, E_hi, E_body *) | Simprec of exp * var * var * exp * exp (* zeroExp * numVar * ansVar * combExp * argExp *)
The s-expression notation
(simprec E_zero (I_num I_ans E_combine) E_arg)
is represented in SML asSimprec (<exp for E-zero>, <string for I_num>, <string for I_ans>, <exp for E_combine>, <exp for E_arg>)
For example, the expression
(simprec 1 (x a (* x a)) n)
is represented in SML asSimprec(Int 1, "x", "a", BinApp(Mul, Var "x", Var "a"), Var "n")
-
Any attempt to
use "Simprec.sml"
oruse "SimprecEnvInterp.sml"
will fail with aSyntaxError
until you extendsexpToExp
andexpToExp
to handlesimprec
expressions. -
You can test your modifications of
sexpToExp
,expToExp
, andfreeVarsExp
viause "Simprex.sml"
. This will display the results of various test cases forfreeVarsExp
before displaying theSimprex
structure. It will also testsexpToExp
andexpToSexp
. -
You can test your modifications of
eval
viause "SimprexEnvInterp.sml"
. This will display the results of various test cases foreval
before displaying theSimprexEnvInterp
structure.
-
3. Extending Valex with New Primitive Operators (15 points)
The Valex language implementation is designed to make it easy to add new primitive operators to the language. In this problem, you are asked to extend Valex with some new primitive operators, like we did in lecture.
To begin this problem, follow these steps:
-
Perform this step again even if you already did it above. Copy the entire contents of the
cs251-download
directory oncs.wellesleley.edu
to your localcs251-download
directory using the following command. Of course, as usual, here and elsewhere you should replace usernamegdome
by your own account name:scp -r gdome@cs.wellesley.edu:/home/cs251/download/* /home/wx/cs251-download
-
Immediately make a copy of the
ps7/ValexPS7.sml
namedValex.sml
(i.e., without thePS7
suffix). Do not prepend your username to the front of this files.cd /home/wx/cs251-download/ps7 cp ValexPS7.sml Valex.sml
-
In the
*sml*
buffer, execute the following SML command to change the default directory:- Posix.FileSys.chdir "/home/wx/cs251-download/ps7";
Add each of the following four primitive operators to Valex.sml
:
-
(1 point)
(abs n)
: Returns the absolute value of the integer n. E.g.valex> (abs -17) 17 valex> (abs 42) 42
-
(3 points)
(sqrt n)
: If n is a non-negative integer, returns the integer square root n. The integer square root of a non-negative integer is the largest integer i such that i2 ≤ n. Signals an error if n is negative. E.g.valex> (sqrt 25) 5 valex> (sqrt 35) 5 valex> (sqrt 36) 6 valex> (sqrt 37) 6
Hint: The
Real
andMath
structures contain helpful functions for this problem. -
(4 points)
(between lo hi)
: Assume lo and hi are integers. If lo ≤ hi, returns a list of integers from lo to hi, inclusive. Otherwise, returns the empty list. For example:valex> (between 1 20) (list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) valex> (between 3 7) (list 3 4 5 6 7) valex> (between 7 3) #e
-
(7 points)
(rot n xs)
Assume n is an integer and xs is a list. If xs is empty, returns the empty list. If n is a nonnegative integer, returns a list that results from moving the first n elements of the list to the end of the list. If n is greater than the length L of the list, uses (n mod L) instead. If n is a negative integer, raises an error. For example:valex> (rot 2 (explode "abcdefg")) (list 'c' 'd' 'e' 'f' 'g' 'a' 'b') valex> (rot 6 (explode "abcdefg")) (list 'g' 'a' 'b' 'c' 'd' 'e' 'f') valex> (rot 0 (explode "abcdefg")) (list 'a' 'b' 'c' 'd' 'e' 'f' 'g') valex> (rot 17 (explode "abcdefg")) (list 'd' 'e' 'f' 'g' 'a' 'b' 'c') (* same as rot 3 *) valex> (rot 17 (list)) #e valex> (rot -3 (explode "abcdefg")) Eval Error: negative rotation ~3 in rot
NOTES:
-
All four primitives above can be added to Valex by adding new
Primop
entries to theprimops
list inps7/Valex.ml
. Study the other primitives to see how this is done. -
Be careful to change the Valex implementation in the
ps7
directory, not the one in thevalex
directory. -
You should only change
Valex.sml
and notValexEnvInterp.sml
-
If you wish to test your implementation after editing
Valex.sml
, you must first execute the following in SML when connected to the directory/home/wx/cs251-download/ps7
:use "ValexEnvInterp.sml"; (* *not* Valex.sml! *)
-
Test your new primitives interactively in a Vales read-eval-print loop (REPL) launched by invoking
ValexEnvInterp.repl()
.
4. Desugaring classify
(30 points)
The classify
construct
You are a summer programming intern at Sweetshop Coding, Inc. Your supervisor, Dexter Rose, has been studying the syntactic sugar for Valex and is very impressed by the cond construct. He decides that it would be neat to extend Valex with a related classify
construct that classifies an integer relative to a collection of ranges. For instance, using his construct, Dexter can write the following grade classification program:
; Classify Program 1
(valex (grade)
(classify grade
((90 100) 'A')
((80 89) 'B')
((70 79) 'C')
((60 69) 'D')
(otherwise 'F')))
This program takes an integer grade value and returns a character indicating which range the grade falls in.
In general, the classify
construct has the following form:
(classify E_disc
((Elo_1 Ehi_1) Ebody_1)
...
((Elo_n Ehi_n) Ebody_n)
(otherwise E_default))
The evaluation of classify should proceed as follows.
First the discriminant expression E_disc
should be evaluated to the value V_disc
, which is expected to be an integer. Then V_disc
should be matched against each of the clauses ((Elo_i Ehi_i) Ebody_i)
from top to bottom until one matches. The value matches a clause if it lies in the range between Vlo_i
and Vhi_i
, inclusive, where Vlo_i
is the integer value of Elo_i
, and Vhi_i
is the integer value of Ehi_i
. When the first matching clause is found, the value of the associated expression Ebody_i
is returned. If none of the clauses matches V_disc
, the value of the default expression E_default
is returned.
Here are a few more examples of the classify
construct:
; Classify program 2
(valex (a b c d)
(classify (* c d)
((a (- (/ (+ a b) 2) 1)) (* a c))
(((+ (/ (+ a b) 2) 1) b) (* b d))
(otherwise (- d c))))
Program 2 emphasizes that any of the subexpressions of classify may be arbitrary expressions that require evaluation. In particular, the upper and lower bound expressions need not be integer literals. For instance, here are some examples of the resulting value returned by Program 2 for some sample inputs:
a | b | c | d | result |
---|---|---|---|---|
10 | 20 | 3 | 4 | 30 |
10 | 20 | 3 | 6 | 120 |
10 | 20 | 3 | 5 | 2 |
; Classify program 3
(valex (a)
(classify a
((0 9) a)
(((/ 20 a) 20) (+ a 1))
(otherwise (/ 100 (- a 5)))))
Program 3 emphasizes that (1) ranges may overlap (in which case the first matching range is chosen) and (2) expressions in clauses after the matching one are not evaluated. For instance, here are here are some examples of the resulting value returned by Program 3 for some sample inputs:
a | result |
---|---|
0 | 0 |
5 | 5 |
10 | 11 |
20 | 21 |
25 | 5 |
30 | 4 |
Your Tasks
Dexter has asked you to implement the classify construct in Valex as syntactic sugar. You will do this in three phases.
-
(9 points) In your PS7 Google Doc, write down how you would like each of the three example programs above to be desugared into equivalent Valex programs that do not have
classify
. Your programs may include other sugar constructs, such as&&
. -
(9 points) In your PS7 Google Doc, write down incremental desugaring rules that desugar
classify
into other Valex constructs. These rules should be expressed as rewrite rules on s-expressions. For example, here are the desugaring rules for Valex’s sugared constructs exceptquote
:(&& E_rand1 E_rand2) ↝ (if E_rand1 E_rand2 #f) (|| E_rand1 E_rand2) ↝ (if E_rand1 #t E_rand2) (cond (else E_default)) ↝ E_default (cond (E_test E_then) ...) ↝ (if E_test E_then (cond ...)) (list) ↝ #e (list E_head ...) ↝ (prep E_head (list ...)) (bindseq () E_body) ↝ E_body (bindseq ((Id E_defn) ...) E_body) ↝ (bind Id E_defn (bindseq (...) E_body)) (bindpar ((Id_1 E_defn_1) ... (Id_n E_defn_n)) E_body) ↝ (bind Id_list (* fresh variable name *) (list E_defn_1 ... E_defn_n) (* eval defns in parallel *) (bindseq ((Id_1 (nth 1 Id_list)) ... (Id_n (nth n Id_list))) E_body))
Note that
...
means zero or more occurrences of the preceding kind of syntactic entity.NOTES:
-
Your desugaring rules may rewrite an s-expression into an s-expression that includes other sugar constructs, such as
&&
. -
Your desugaring rules should be written in such a way that
E_disc
is evaulated only once. To guarantee this, you will need to name the value ofE_disc
with a “fresh” variable (one that does not appear elsewhere in the program). -
You should treat differently the cases where
E_disc
is an identifier and when it is not an identifier. -
Your rules should be designed to give the same output for the three sample programs as in part a.
-
-
(12 points) In this part, you will implement and test your desugaring rules from the previous part. You will modify the very same
ps7/Valex.sml
file you created in Problem 3 in this part. You should make your changes to thedesugarRules
function inps7/Valex.sml
.NOTES:
-
Be careful to change the Valex implementation in the
ps7
directory, not the one in thevalex
directory. -
Use
Utils.fresh
to create a fresh variable. -
If you wish to test your implementation editing
Valex.sml
, you must first execute the following in SML when connected to the directory/home/wx/cs251-download/ps7
:use "ValexEnvInterp.sml"; (* *not* Valex.sml! *)
-
In the
ps7
directory, the filesclassify1.vlx
,classify2.vlx
, andclassify3.vlx
contain the three exampleclassify
programs from above. The filesort3.vlx
contains a test file that not usingclassify
that returns a sorted list of its 3 arguments. -
Your implementation should give the same output for the three sample programs as in part a. For seeing the output of the desugaring of your
classify
construct for examples, use one of the following approaches:-
To desugar a file, use
Valex.desugarFile
to print the result of desugaring the program in the file. For example, supposedsort3.vlx
contains this program:(valex (a b c) (cond ((&& (<= a b) (<= b c)) (list a b c)) ((&& (<= a c) (<= c b)) (list a c b)) ((&& (<= b a) (<= a c)) (list b a c)) ((&& (<= b c) (<= c a)) (list c b a)) ((&& (<= c a) (<= a b)) (list c a b)) (else (list c b a))))
Then here is the result of using
Valex.desugarFile
on this program:- Valex.desugarFile "sort3.vlx"; (valex (a b c) (if (if (<= a b) (<= b c) #f) (prep a (prep b (prep c #e))) (if (if (<= a c) (<= c b) #f) (prep a (prep c (prep b #e))) (if (if (<= b a) (<= a c) #f) (prep b (prep a (prep c #e))) (if (if (<= b c) (<= c a) #f) (prep c (prep b (prep a #e))) (if (if (<= c a) (<= a b) #f) (prep c (prep a (prep b #e))) (prep c (prep b (prep a #e))) ) ) ) ) ) ) val it = () : unit
-
To desugar an expression, one approach is to invoke the
Valex.desugarString
function on a string representing the expression you want to desugar. For example:- Valex.desugarString "(&& (|| a b) (|| c d))" (if (if a #t b) (if c #t d) #f) - : unit = () - Valex.desugarString "(list 1 2 3)" (prep 1 (prep 2 (prep 3 #e))) - : unit = ()
-
To desugar an expression, another approach is to use
ValexEnvInterp.repl()
to launch a read-eval-print loop and use the#desugar
directive to desugar an expression. For example:- ValexEnvInterp.repl(); valex> (#desugar (&& (|| a b) (|| c d))) (if (if a #t b) (if c #t d) #f) valex> (#desugar (list 1 2 3)) (prep 1 (prep 2 (prep 3 #e)))
-
-
There are several ways to test the evaluation of your desugared classify construct:
-
To run a program, one approach is to invoke
ValexEnvInterp.runFile
on the filename and a list of integer arguments. For example:- ValexEnvInterp.runFile "sort3.vlx" [23, 42, 17]; val it = List [Int 17,Int 23,Int 42] : Valex.value
-
To run a program, another approach is to use
ValexEnvInterp.repl()
to launch a read-eval-print loop and use the#run
directive to run a fileon arguments. For example:- ValexEnvInterp.repl(); valex> (#run sort3.vlx 23 42 17) (list 17 23 42)
-
To evaluate an expression, use
ValexEnvInterp.repl()
to launch a read-eval-print loop and enter the expression. To evaluate an expression with free variables, use the#args
directive to bind the variables. For example:- ValexEnvInterp.repl(); valex> (#args (a 2) (b 3)) valex> (bindpar ((a (+ a b)) (b (* a b))) (list a b)) (list 5 6) valex> (bindseq ((a (+ a b)) (b (* a b))) (list a b)) (list 5 15)
-
-