diff --git a/Fasto/CodeGen.fs b/Fasto/CodeGen.fs index 64bd779..1a2553e 100644 --- a/Fasto/CodeGen.fs +++ b/Fasto/CodeGen.fs @@ -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 *) diff --git a/Fasto/Interpreter.fs b/Fasto/Interpreter.fs index 0b20fd5..9d50726 100644 --- a/Fasto/Interpreter.fs +++ b/Fasto/Interpreter.fs @@ -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) diff --git a/Fasto/Lexer.fsl b/Fasto/Lexer.fsl index f9373ad..5d92bbc 100644 --- a/Fasto/Lexer.fsl +++ b/Fasto/Lexer.fsl @@ -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 diff --git a/Fasto/Parser.fsp b/Fasto/Parser.fsp index 9cbe67e..f098305 100644 --- a/Fasto/Parser.fsp +++ b/Fasto/Parser.fsp @@ -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 NUM %token CHARLIT %token ID STRINGLIT @@ -68,7 +51,7 @@ let parse_error_rich = %type Exp %type Exps %type FunArg -// TODO: Task 1(b): add any new nonterminals here + %type 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 } diff --git a/Fasto/TypeChecker.fs b/Fasto/TypeChecker.fs index 01f669e..d71900a 100644 --- a/Fasto/TypeChecker.fs +++ b/Fasto/TypeChecker.fs @@ -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