This commit is contained in:
NikolajDanger
2022-06-09 12:41:00 +02:00
parent 5ff8dd409a
commit 7c20bc1c2c
5 changed files with 1 additions and 162 deletions

View File

@ -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 *)

View File

@ -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)

View File

@ -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

View File

@ -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 }

View File

@ -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