Commit 2f8e380f authored by Matt's avatar Matt

Doc updates

Also closes #11, but I'm not sure how I feel about it
parent db800e76
......@@ -4,10 +4,16 @@
; Based on Q0 from:
; Ian Barland, 2008.Nov.27, updates through 2015.Nov.09
(provide (all-defined-out))
(provide string->expr eval expr->string
; exported for testing:
make-paren-expr make-bin-expr make-parity-expr
make-ifzero-expr make-let-expr
make-func-expr make-func-apply-expr
char-alphanumeric? string-alphanumeric? check-pop! id?)
(require "scanner.rkt")
;;; Helpers
;;; Helpers =====================================================
; char-alphanumeric? : char -> boolean
(define (char-alphanumeric? c)
......@@ -38,8 +44,19 @@
#t ; if we made it to here w/out error, everything is peachy
(apply check-pop! context scnr (first more) (rest more))))
;;;; Expression types ===========================================
;;;; Expression types
#| An Expr is one of:
- a number
- an identifier
- (make-paren-expr [Expr])
- (make-bin-expr [Expr] [Bin-op] [Expr])
- (make-parity-expr [Expr] [Expr] [Expr])
- (make-ifzero-expr [Expr] [Expr] [Expr])
- (make-let-expr [Id] [Expr] [Expr])
- (make-func-expr [Id] [Expr])
- (make-func-apply-expr [Expr] [Expr])
|#
;; ID
; id? : any -> boolean
......@@ -83,9 +100,9 @@
; (make-func-apply-expr [Expr] [Expr])
(define-struct func-apply-expr (func arg) #:transparent)
;;;; "Big Three" expression functions
;;;; Functions on type Expr =====================================
;;; string->expr
;;; string->expr ------------------------------------------------
; parse! : scanner -> expr
; Return (our internal, parse-tree representation of) the first
......@@ -222,7 +239,7 @@
(define (string->expr str)
(parse! (create-scanner str)))
;;; eval
;;; eval --------------------------------------------------------
; eval : expr[, environment] -> val
; Evaluate the given expr, using the given environment.
......@@ -245,8 +262,10 @@
[else (error 'eval "unknown internal format?!: ~v" exp)]))
; lookup : env, id -> value
; If we find a function, then change the function's closure to contain
; itself before returning it.
; Find the value associated with an identifier in an environment.
; If the value is a function, before returning it update it's
; closure to contain a reference from the identifier we found it
; under to itself (enables recursion).
(define (lookup env id)
(maybe-bind-closure
(hash-ref env id (λ () (error 'eval "Unbound Id ~v" id)))
......@@ -254,15 +273,17 @@
; maybe-bind-closure : expr, id -> expr
; If expr is a function, returns a new function with the same body,
; but includes itself in its closure using the given id
; but extends the closure to contain a reference from the given
; id to the function itself.
(define (maybe-bind-closure e id)
(if (func-expr? e)
(bind-closure e id)
e))
; bind-closure : func-expr, id -> func-expr
; Returns a new func-expr with the same body and parameter as the original,
; but with an updated closure containing the function under the given Id
; Returns a new func-expr with the same body and parameter as
; the original, but with a closure which maps from the given Id
; to the function itself.
(define (bind-closure f id)
(make-func-expr (func-expr-id f)
(func-expr-body f)
......@@ -302,8 +323,8 @@
(eval (let-expr-val lexpr) env))))
; eval-func-expr : func-expr, environment -> value
; Evaluating a function expression should return that function expression
; with the closure set to the given environment
; Evaluating a function expression should return that function
; expression with its closure set to the given environment
(define (eval-func-expr fexpr env)
(make-func-expr (func-expr-id fexpr)
(func-expr-body fexpr)
......@@ -320,7 +341,7 @@
(eval (func-apply-expr-arg faexpr) env)))))
; func-or-err : func-apply-expr -> func-expr
; Evaluates the function portion of a function application.
; Evaluates the first expr of a function application.
; The result should be a function; raise an error if not
(define (func-or-err faexpr env)
(let {[f (eval (func-apply-expr-func faexpr) env)]
......@@ -332,80 +353,61 @@
(expr->string faexpr)
(expr->string f)))))
;;; expr->string
;;; expr->string ------------------------------------------------
; expr->string : expr -> string (a.k.a. toString)
; Return a human-readable version of our internal representation of Exprs.
; expr->string : expr -> string
; Return a human-readable version of our internal representation
(define (expr->string e)
(cond [(number? e) (format "~v" e)]
[(paren-expr? e) (string-append "[["
(expr->string (paren-expr-body e))
"]]")]
[(bin-expr? e) (string-append "("
(expr->string (bin-expr-left e))
" "
(bin-expr-op e)
" "
(expr->string (bin-expr-right e))
")")]
[(parity-expr? e) (string-append "parity "
(expr->string (parity-expr-test e))
" even: "
(expr->string (parity-expr-even-br e))
" odd: "
(expr->string (parity-expr-odd-br e))
";"
)]
[(ifzero-expr? e) (string-append "if "
(expr->string (ifzero-expr-test e))
" is zero then "
(expr->string (ifzero-expr-zero-br e))
" else "
(expr->string (ifzero-expr-else-br e))
"@")]
[(let-expr? e) (string-append "say "
(let-expr-id e)
" be "
(expr->string (let-expr-val e))
" in "
(expr->string (let-expr-body e))
" matey")]
[(func-expr? e) (string-append "("
(func-expr-id e)
") -> {"
(expr->string (func-expr-body e))
"}")]
[(func-apply-expr? e) (string-append "<"
(expr->string (func-apply-expr-func e))
" @ "
(expr->string (func-apply-expr-arg e))
">")]
[(paren-expr? e)
(string-append "[["
(expr->string (paren-expr-body e))
"]]")]
[(bin-expr? e)
(string-append "("
(expr->string (bin-expr-left e))
" "
(bin-expr-op e)
" "
(expr->string (bin-expr-right e))
")")]
[(parity-expr? e)
(string-append "parity "
(expr->string (parity-expr-test e))
" even: "
(expr->string (parity-expr-even-br e))
" odd: "
(expr->string (parity-expr-odd-br e))
";")]
[(ifzero-expr? e)
(string-append "if "
(expr->string (ifzero-expr-test e))
" is zero then "
(expr->string (ifzero-expr-zero-br e))
" else "
(expr->string (ifzero-expr-else-br e))
"@")]
[(let-expr? e)
(string-append "say "
(let-expr-id e)
" be "
(expr->string (let-expr-val e))
" in "
(expr->string (let-expr-body e))
" matey")]
[(func-expr? e)
(string-append "("
(func-expr-id e)
") -> {"
(expr->string (func-expr-body e))
"}")]
[(func-apply-expr? e)
(string-append "<"
(expr->string (func-apply-expr-func e))
" @ "
(expr->string (func-apply-expr-arg e))
">")]
[(id? e) e]
[else (error 'expr->string "unknown internal format?!: ~v" e)]))
;;;;;;;;;;; language Qn ;;;;;;;;;;;;;;
#| The grammar thus far:
Expr ::= Num | Id | ParenExpr | BinExpr | ParityExpr |
IfZeroExpr | LetExpr | FuncExpr | FuncApplyExpr
ParenExpr ::= [[ Expr ]]
BinExpr ::= (Expr BinOp Expr)
ParityExpr ::= parity Expr even: Expr odd: Expr;
IfZeroExpr ::= if Expr is zero then Expr else Expr@
LetExpr ::= say Id be Expr in Expr matey
FuncExpr ::= (Id) -> {Expr}
FuncApplyExpr ::= <Expr @ Expr>
BinOp ::= add | sub | mul | mod
Accoringly, an Expr is one of:
- a number
- an identifier
- (make-paren-expr [Expr])
- (make-bin-expr [Expr] [Bin-op] [Expr])
- (make-parity-expr [Expr] [Expr] [Expr])
- (make-ifzero-expr [Expr] [Expr] [Expr])
- (make-let-expr [Id] [Expr] [Expr])
- (make-func-expr [Id] [Expr])
- (make-func-apply-expr [Expr] [Expr])
|#
......@@ -69,3 +69,7 @@ BinOp ::= add | sub | mul | mod
Change evaluation to use deferred substitution; no syntax changes.
## Q6
Static scope; no syntax changes.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment