Skip to content

Instantly share code, notes, and snippets.

@kmicinski
Created February 23, 2023 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmicinski/7c9bbe55363107ededa028ba917ba10b to your computer and use it in GitHub Desktop.
Save kmicinski/7c9bbe55363107ededa028ba917ba10b to your computer and use it in GitHub Desktop.
#lang racket
;; Interpreters, Feb 23
(define (arith-expr? e)
(match e
[(? number? n) #t]
[`(,(? number? n0) + ,(? number? n1)) #t]
[`(,(? number? n0) - ,(? number? n1)) #t]
[`(,(? number? n0) * ,(? number? n1)) #t]
[`(,(? number? n0) / ,(? number? n1)) #t]
[_ #f]))
(define value? number?)
(define/contract (eval-arith-expr e)
(-> arith-expr? value?)
(match e
[(? number?) e]
[`(,n0 + ,n1) (+ n0 n1)]
[`(,n0 - ,n1) (- n0 n1)]
[`(,n0 * ,n1) (* n0 n1)]
[`(,(? integer? n0) / ,(? integer? n1)) (let ([remainder (modulo n0 n1)])
(/ (- n0 remainder) n1))]))
(define (bop? op)
(match op ['+ #t] ['* #t] ['- #t] ['/ #t] [_ #f]))
(define (naexpr? e)
(match e
[(? number? n) #t]
[(? symbol? x) #t]
[`(let ([,(? symbol? x) ,(? naexpr? e)]) ,(? naexpr? e-body)) #t]
[`(,(? naexpr? n0) ,(? bop? op) ,(? naexpr? n1)) #t]
[`(if0 ,(? naexpr? guard) ,(? naexpr? true-expr) ,(? naexpr? false-expr)) #t]
[_ #f]))
(define (environment? env)
(and (hash? env)
(andmap (λ (key) (symbol? key)) (hash-keys env))
(andmap (λ (value) (value? value)) (hash-values env))))
(define/contract (eval-naexpr e env)
(-> naexpr? environment? value?)
;(displayln "At entrypoint:")
;(pretty-print e)
(match e
[(? number?) e]
[(? symbol? x) (hash-ref env x)]
[`(let ([,x ,e]) ,e-body)
;; first evaluate e to some value using the current environment env
;; then, build a new environment (using hash-set) to update env
;; with a binding for x that binds it to the newly-evaluated value
;; then execute the body
(let ([v (eval-naexpr e env)])
(eval-naexpr e-body (hash-set env x v)))]
[`(,e0 + ,e1) (+ (eval-naexpr e0 env) (eval-naexpr e1 env))]
[`(,e0 - ,e1) (- (eval-naexpr e0 env) (eval-naexpr e1 env))]
[`(,e0 * ,e1) (* (eval-naexpr e0 env) (eval-naexpr e1 env))]
[`(,e0 / ,e1) (let ([remainder (modulo (eval-naexpr e0 env) (eval-naexpr e1 env))])
(/ (- (eval-naexpr e0 env) remainder) (eval-naexpr e1 env)))]
[`(if0 ,e-guard ,e-true ,e-false)
(if (equal? (eval-naexpr e-guard env) 0)
(eval-naexpr e-true env)
(eval-naexpr e-false env))]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment