Skip to content

Instantly share code, notes, and snippets.

@kmicinski
Created November 13, 2023 01:47
Show Gist options
  • Save kmicinski/2eaf2f52b59f796c841a239df5f017dd to your computer and use it in GitHub Desktop.
Save kmicinski/2eaf2f52b59f796c841a239df5f017dd to your computer and use it in GitHub Desktop.
#lang racket
(define (op? op)
(member op '(+ - * / cons car cdr = equal? length)))
(define (op->racket op)
(eval op (make-base-namespace))) ;; the *only* acceptable use of Racket's `eval` in this project
;; First attempt
(define (eval-a e env)
(match e
;; base literals
[(? number? n) n]
[(? boolean? b) #t]
[''() '()]
;; other operations
;; ...
;; closures
[`(lambda (,xs ...) ,e-body) `(closure ,e ,env)]
;; Primitives ("hard coded" application)
[`(,(? op? op) ,e-args ...)
(define vs (map (λ (e) (eval-a e env)) e-args))
(apply (op->racket op) vs)]
;; More general application
[`(,e-f ,e-args ...)
(match (eval-a e-f env)
[`(closure (lambda (,x) ,e-body) ,env+) (eval-a e-body (hash-set env+ x (eval-a (first e-args) env)))]
[`(closure (lambda (,x ,y) ,e-body) ,env+) (eval-a e-body (hash-set (hash-set env+ x (eval-a (first e-args) env))
y
(eval-a (second e-args) env)))])]))
(eval-a '((lambda (+) (+ 1 2)) (lambda (x y) x)) (hash)) ;; reutrns 3, should return 1
;; Note: this is not really a big deal for the vast number of testcases (maybe all?)
;; So if the top thing makes more sense to you--do that first
;; second attempt
(define (eval-b e env)
(match e
[(? number? n) n]
[(? boolean? b) #t]
[''() '()]
[(? symbol? x) (hash-ref env x)]
[`(lambda (,xs ...) ,e-b) `(closure ,e ,env)]
;; application
[`(,e-f ,e-args ...)
(match (eval-b e-f env)
[`(closure (lambda (,x) ,e-body) ,env+) (eval-b e-body (hash-set env+ x (eval-b (first e-args) env)))]
[`(closure (lambda (,x ,y) ,e-body) ,env+) (eval-b e-body (hash-set (hash-set env+ x (eval-b (first e-args) env))
y
(eval-b (second e-args) env)))]
['prim
(apply (op->racket e-f) (map (λ (e) (eval-b e env)) e-args))])]))
;; returns 1, as expected...
(eval-b '((lambda (+) (+ 1 2)) (lambda (x y) x)) (hash '+ 'prim '- 'prim '* 'prim 'cons 'prim 'car 'prim 'cdr 'prim))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment