#lang racket #| CSC324 Fall 2018: Exercise 4 |#
#|
* Before starting, please review the exercise guidelines at
http://www.cs.toronto.edu/~lczhang/324/assignments.html *
|#
;-------------------------------------------------------------------------------
(provide calculate eval-calc analyze-strictness)
;-------------------------------------------------------------------------------
; * Task 1: Eager Evaluation *
;-------------------------------------------------------------------------------
#|
(calculate expr)
expr: A datum representing an expression generated by the
grammar in the Exericse 4 handout
|#
(define (calculate expr)
(eval-calc expr (hash)))
#|
(eval-calc expr env)
expr: A datum representing an expression generated by the
grammar in the Exercise 4 handout
env: A hash table representing an environment.
The keys of the hash table are symbols representing identifiers.
You may assume that if an `expr` is an identifier, then it is present in `env`.
|#
(define (eval-calc expr env)
(void))
#;(module+ test
(require rackunit)
; You should write more tests to make sure that your
; interpreter uses lexical scoping
(test-equal? "Function definition"
(calculate '((lambda (a) (+ a 1)) 4))
5)
(test-equal? "Functions with multiple arguments"
(calculate '((lambda (a b) (+ b 1)) 4 14))
15))
;-------------------------------------------------------------------------------
; * Task 1: Strictness analysis *
;-------------------------------------------------------------------------------
#|
(analyze-strictness func-defs)
func-defs:
A datum representing a program as specified by the grammar on the handout.
(In this case, it's a list of function definitions.)
Returns a *strictness map*, which is a hash table mapping function names (as symbols)
to a list of indexes of the strict parameters of that function.
Each list should be in increasing order.
Remember, you may assume that the program has no syntactic or semantic errors
(so you don't even need to watch out for things like duplicate names).
Hash table reference: https://docs.racket-lang.org/reference/hashtables.html.
Implementation hints:
1. Same as Exercise 3, the main work can be done by processing the list of
function definitions in a call to foldl.
2. Working with list indexes is a bit more annoying in pure functional land.
Use the list function `indexes-where`, which is similar to `filter` except
it returns indexes rather than elements.
|#
(define (analyze-strictness func-defs)
(void))
#|
(strict-in? s-map id expr)
s-map: A strictness map
id: An identifier
expr: A quoted expression in the grammar specified by the assignment handout.
Returns whether id is strict in the given expression.
Uses the given strictness map to determine strictness in function calls.
NOTE: this function isn't being tested explicitly, so you may freely change it or
ignore it for this exercise.
Implementation hint:
Remember that `and` and `or` aren't function identifiers: you can't pass them to
HOFs like `map` or `apply`. But you can use functions like `andmap` and `ormap`
to achieve similar effects.
|#
(define (strict-in? s-map id expr)
(void))
(module+ test
(require rackunit)
(test-equal? "Identity function"
(analyze-strictness '((define (f x) x)))
(hash
'f (list 0)))
(test-equal? "One function, with if (1)"
(analyze-strictness '((define (f x) (if x 3 5))))
(hash
'f (list 0)))
(test-equal? "One function, with +"
(analyze-strictness '((define (f x y z) (+ x y))))
(hash
'f (list 0 1)))
)