✨
This commit is contained in:
@ -258,13 +258,6 @@ let rec compileExp (e : TypedExp)
|
||||
let code2 = compileExp e2 vtable t2
|
||||
code1 @ code2 @ [Mips.SUB (place,t1,t2)]
|
||||
|
||||
(* TODO project task 1:
|
||||
Look in `AbSyn.fs` for the expression constructors `Times`, ...
|
||||
`Times` is very similar to `Plus`/`Minus`.
|
||||
For `Divide`, you may ignore division by zero for a quick first
|
||||
version, but remember to come back and clean it up later.
|
||||
`Not` and `Negate` are simpler; you can use `Mips.XORI` for `Not`
|
||||
*)
|
||||
| Times (e1, e2, pos) ->
|
||||
let t1 = newReg "times_L"
|
||||
let t2 = newReg "times_R"
|
||||
@ -397,13 +390,6 @@ let rec compileExp (e : TypedExp)
|
||||
let code2 = compileExp e2 vtable t2
|
||||
code1 @ code2 @ [Mips.SLT (place,t1,t2)]
|
||||
|
||||
(* TODO project task 1:
|
||||
Look in `AbSyn.fs` for the expression constructors of `And` and `Or`.
|
||||
The implementation of `And` and `Or` is more complicated than `Plus`
|
||||
because you need to ensure the short-circuit semantics, e.g.,
|
||||
in `e1 || e2` if the execution of `e1` will evaluate to `true` then
|
||||
the code of `e2` must not be executed. Similarly for `And` (&&).
|
||||
*)
|
||||
| And (e1, e2, pos) ->
|
||||
let R0 = Mips.RS "0"
|
||||
let label = newLab "false"
|
||||
@ -589,31 +575,6 @@ let rec compileExp (e : TypedExp)
|
||||
; Mips.LABEL loop_end
|
||||
]
|
||||
|
||||
(* TODO project task 2:
|
||||
`replicate (n, a)`
|
||||
`filter (f, arr)`
|
||||
`scan (f, ne, arr)`
|
||||
Look in `AbSyn.fs` for the shape of expression constructors
|
||||
`Replicate`, `Filter`, `Scan`.
|
||||
General Hint: write down on a piece of paper the C-like pseudocode
|
||||
for implementing them, then translate that to Mips pseudocode.
|
||||
To allocate heap space for an array you may use `dynalloc` defined
|
||||
above. For example, if `sz_reg` is a register containing an integer `n`,
|
||||
and `ret_type` is the element-type of the to-be-allocated array, then
|
||||
`dynalloc (sz_reg, arr_reg, ret_type)` will alocate enough space for
|
||||
an n-element array of element-type `ret_type` (including the first
|
||||
word that holds the length, and the necessary allignment padding), and
|
||||
will place in register `arr_reg` the start address of the new array.
|
||||
Since you need to allocate space for the result arrays of `Replicate`,
|
||||
`Map` and `Scan`, then `arr_reg` should probably be `place` ...
|
||||
|
||||
`replicate(n,a)`: You should allocate a new (result) array, and execute a
|
||||
loop of count `n`, in which you store the value hold into the register
|
||||
corresponding to `a` into each memory location corresponding to an
|
||||
element of the result array.
|
||||
If `n` is less than `0` then remember to terminate the program with
|
||||
an error -- see implementation of `iota`.
|
||||
*)
|
||||
| Replicate (n_exp, a_exp, a_type, (line, _)) ->
|
||||
let a_size = getElemSize a_type
|
||||
|
||||
@ -668,21 +629,6 @@ let rec compileExp (e : TypedExp)
|
||||
@ loop_replicate
|
||||
@ loop_footer
|
||||
|
||||
(* TODO project task 2: see also the comment to replicate.
|
||||
(a) `filter(f, arr)`: has some similarity with the implementation of map.
|
||||
(b) Use `applyFunArg` to call `f(a)` in a loop, for every element `a` of `arr`.
|
||||
(c) If `f(a)` succeeds (result in the `true` value) then (and only then):
|
||||
- set the next element of the result array to `a`, and
|
||||
- increment a counter (initialized before the loop)
|
||||
(d) It is useful to maintain two array iterators: one for the input array `arr`
|
||||
and one for the result array. (The latter increases slower because
|
||||
some of the elements of the input array are skipped because they fail
|
||||
under the predicate).
|
||||
(e) The last step (after the loop writing the elments of the result array)
|
||||
is to update the logical size of the result array to the value of the
|
||||
counter computed in step (c). You do this of course with a
|
||||
`Mips.SW(counter_reg, place, 0)` instruction.
|
||||
*)
|
||||
| Filter (farg, arr_exp, a_type, pos) ->
|
||||
let size_reg = newReg "size_reg" (* size of input/output array *)
|
||||
let arr_reg = newReg "arr_reg" (* address of array *)
|
||||
@ -737,13 +683,6 @@ let rec compileExp (e : TypedExp)
|
||||
@ loop_map
|
||||
@ loop_footer
|
||||
|
||||
(* TODO project task 2: see also the comment to replicate.
|
||||
`scan(f, ne, arr)`: you can inspire yourself from the implementation of
|
||||
`reduce`, but in the case of `scan` you will need to also maintain
|
||||
an iterator through the result array, and write the accumulator in
|
||||
the current location of the result iterator at every iteration of
|
||||
the loop.
|
||||
*)
|
||||
| Scan (farg, e_exp, arr_exp, a_type, pos) ->
|
||||
let size_reg = newReg "size_reg" (* size of input/output array *)
|
||||
let arr_reg = newReg "arr_reg" (* address of array *)
|
||||
|
@ -134,16 +134,6 @@ let rec evalExp (e : UntypedExp, vtab : VarTable, ftab : FunTable) : Value =
|
||||
| (IntVal n1, IntVal n2) -> IntVal (n1-n2)
|
||||
| (IntVal _, _) -> reportWrongType "right operand of -" Int res2 (expPos e2)
|
||||
| (_, _) -> reportWrongType "left operand of -" Int res1 (expPos e1)
|
||||
(* TODO: project task 1:
|
||||
Look in `AbSyn.fs` for the arguments of the `Times`
|
||||
(`Divide`,...) expression constructors.
|
||||
Implementation similar to the cases of Plus/Minus.
|
||||
Try to pattern match the code above.
|
||||
For `Divide`, remember to check for attempts to divide by zero.
|
||||
For `And`/`Or`: make sure to implement the short-circuit semantics,
|
||||
e.g., `And (e1, e2, pos)` should not evaluate `e2` if `e1` already
|
||||
evaluates to false.
|
||||
*)
|
||||
| Times(e1, e2, pos) ->
|
||||
let res1 = evalExp(e1, vtab, ftab)
|
||||
let res2 = evalExp(e2, vtab, ftab)
|
||||
@ -276,15 +266,6 @@ let rec evalExp (e : UntypedExp, vtab : VarTable, ftab : FunTable) : Value =
|
||||
| ArrayVal (lst,tp1) ->
|
||||
List.fold (fun acc x -> evalFunArg (farg, vtab, ftab, pos, [acc;x])) nel lst
|
||||
| otherwise -> reportNonArray "3rd argument of \"reduce\"" arr pos
|
||||
(* TODO project task 2: `replicate(n, a)`
|
||||
Look in `AbSyn.fs` for the arguments of the `Replicate`
|
||||
(`Map`,`Scan`) expression constructors.
|
||||
- evaluate `n` then evaluate `a`,
|
||||
- check that `n` evaluates to an integer value >= 0
|
||||
- If so then create an array containing `n` replicas of
|
||||
the value of `a`; otherwise raise an error (containing
|
||||
a meaningful message).
|
||||
*)
|
||||
| Replicate (narg, aarg, _, pos) ->
|
||||
let n = evalExp(narg, vtab, ftab)
|
||||
let a = evalExp(aarg, vtab, ftab)
|
||||
@ -294,14 +275,6 @@ let rec evalExp (e : UntypedExp, vtab : VarTable, ftab : FunTable) : Value =
|
||||
ArrayVal (a_array, valueType a)
|
||||
| _ -> reportWrongType "argument of \"Replicate\"" Int n pos
|
||||
|
||||
(* TODO project task 2: `filter(p, arr)`
|
||||
pattern match the implementation of map:
|
||||
- check that the function `p` result type (use `rtpFunArg`) is bool;
|
||||
- evaluate `arr` and check that the (value) result corresponds to an array;
|
||||
- use F# `List.filter` to keep only the elements `a` of `arr` which succeed
|
||||
under predicate `p`, i.e., `p(a) = true`;
|
||||
- create an `ArrayVal` from the (list) result of the previous step.
|
||||
*)
|
||||
| Filter (farg, arrayarg, _, pos) ->
|
||||
let arr = evalExp(arrayarg, vtab, ftab)
|
||||
match arr with
|
||||
@ -315,11 +288,6 @@ let rec evalExp (e : UntypedExp, vtab : VarTable, ftab : FunTable) : Value =
|
||||
ArrayVal (new_array, a_type)
|
||||
| _ -> reportWrongType "argument of \"Filter\"" Int arr pos
|
||||
|
||||
|
||||
(* TODO project task 2: `scan(f, ne, arr)`
|
||||
Implementation similar to reduce, except that it produces an array
|
||||
of the same type and length to the input array `arr`.
|
||||
*)
|
||||
| Scan (farg, ne, arrayexp, _, pos) ->
|
||||
let arr = evalExp(arrayexp, vtab, ftab)
|
||||
let init_e = evalExp(ne, vtab, ftab)
|
||||
|
@ -1,20 +1,3 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// TODO: project task 1
|
||||
// implement lexer tokens for the new operators:
|
||||
// multiplication (*), division (/), numerical negation (~),
|
||||
// logical negation (not), logical and (&&), logical or (||),
|
||||
// boolean literals (true, false), semicolon (;)
|
||||
//
|
||||
//
|
||||
// TODO: project task 2
|
||||
// implement lexer tokens (keywords) for replicate, filter, scan
|
||||
//
|
||||
//
|
||||
// TODO: project task 4
|
||||
// implement the lexer tokens (keywords) for array comprehension
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
{
|
||||
module Lexer
|
||||
|
||||
|
@ -19,23 +19,6 @@ let parse_error_rich =
|
||||
|
||||
%}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// TODO: Add new (lexer) token definitions:
|
||||
//
|
||||
// TODO: project task 1 :
|
||||
// - multiplication (*), division (/), numerical negation (~),
|
||||
// logical negation (not), logical and (&&), logical or (||),
|
||||
// boolean literals (true, false)
|
||||
// - add the required precedence and associativity rules for
|
||||
// *, /, ~, not, &&, ||
|
||||
// - generalize the syntax of let-expressions to allow
|
||||
// multiple variable declarations
|
||||
//
|
||||
// TODO: project task 2: replicate, filter, scan
|
||||
//
|
||||
// TODO: project task 4: array comprehension
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
%token <int * Position> NUM
|
||||
%token <char * Position> CHARLIT
|
||||
%token <string * Position> ID STRINGLIT
|
||||
@ -68,7 +51,7 @@ let parse_error_rich =
|
||||
%type <AbSyn.UntypedExp> Exp
|
||||
%type <AbSyn.UntypedExp list> Exps
|
||||
%type <AbSyn.UntypedFunArg> FunArg
|
||||
// TODO: Task 1(b): add any new nonterminals here
|
||||
|
||||
%type <AbSyn.UntypedExp> MultiLet
|
||||
|
||||
%%
|
||||
@ -106,11 +89,6 @@ BinOp : PLUS { (Lambda
|
||||
$1) ,$1))}
|
||||
;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// TODO: project tasks 1,2,4:
|
||||
// add grammer rules for the new expressions
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
Exp : NUM { Constant (IntVal (fst $1), snd $1) }
|
||||
| CHARLIT { Constant (CharVal (fst $1), snd $1) }
|
||||
| ID { Var $1 }
|
||||
|
@ -125,10 +125,6 @@ and checkExp (ftab : FunTable)
|
||||
let (e1_dec, e2_dec) = checkBinOp ftab vtab (pos, Int, e1, e2)
|
||||
(Int, Minus (e1_dec, e2_dec, pos))
|
||||
|
||||
(* TODO project task 1:
|
||||
Implement by pattern matching Plus/Minus above.
|
||||
See `AbSyn.fs` for the expression constructors of `Times`, ...
|
||||
*)
|
||||
| Times (e1, e2, pos) ->
|
||||
let (e1_dec, e2_dec) = checkBinOp ftab vtab (pos, Int, e1, e2)
|
||||
(Int, Times (e1_dec, e2_dec, pos))
|
||||
@ -294,16 +290,6 @@ and checkExp (ftab : FunTable)
|
||||
f_argres_type e_type pos
|
||||
(f_argres_type, Reduce (f', e_dec, arr_dec, elem_type, pos))
|
||||
|
||||
(* TODO project task 2:
|
||||
See `AbSyn.fs` for the expression constructors of
|
||||
`Replicate`, `Filter`, `Scan`.
|
||||
|
||||
Hints for `replicate(n, a)`:
|
||||
- recursively type check `n` and `a`
|
||||
- check that `n` has integer type
|
||||
- assuming `a` is of type `t` the result type
|
||||
of replicate is `[t]`
|
||||
*)
|
||||
| Replicate (n_exp, a_exp, _, pos) ->
|
||||
let (n_t, n_dec) = checkExp ftab vtab n_exp
|
||||
let (a_t, a_dec) = checkExp ftab vtab a_exp
|
||||
@ -311,15 +297,6 @@ and checkExp (ftab : FunTable)
|
||||
(Array a_t, Replicate (n_dec, a_dec, a_t, pos))
|
||||
else raise (MyError("parameter n not Int", pos))
|
||||
|
||||
(* TODO project task 2: Hint for `filter(f, arr)`
|
||||
Look into the type-checking lecture slides for the type rule of `map`
|
||||
and think of what needs to be changed for filter (?)
|
||||
Use `checkFunArg` to get the signature of the function argument `f`.
|
||||
Check that:
|
||||
- `f` has type `ta -> Bool`
|
||||
- `arr` should be of type `[ta]`
|
||||
- the result of filter should have type `[tb]`
|
||||
*)
|
||||
| Filter (f, arr_exp, _, pos) ->
|
||||
let (arr_type, arr_exp_dec) = checkExp ftab vtab arr_exp
|
||||
let elem_type =
|
||||
@ -338,12 +315,6 @@ and checkExp (ftab : FunTable)
|
||||
|
||||
(Array f_arg_type, Filter (f', arr_exp_dec, elem_type, pos))
|
||||
|
||||
(* TODO project task 2: `scan(f, ne, arr)`
|
||||
Hint: Implementation is very similar to `reduce(f, ne, arr)`.
|
||||
(The difference between `scan` and `reduce` is that
|
||||
scan's return type is the same as the type of `arr`,
|
||||
while reduce's return type is that of an element of `arr`).
|
||||
*)
|
||||
| Scan (f, e_exp, arr_exp, _, pos) ->
|
||||
let (e_type , e_dec ) = checkExp ftab vtab e_exp
|
||||
let (arr_type, arr_dec) = checkExp ftab vtab arr_exp
|
||||
|
Reference in New Issue
Block a user