Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #lang racket
- ;; definicja wyrażeń
- (struct variable (x) #:transparent)
- (struct const (val) #:transparent)
- (struct op (symb l r) #:transparent)
- (struct let-expr (x e1 e2) #:transparent)
- (struct if-expr (b t e) #:transparent)
- (struct cons-expr (l r) #:transparent)
- (struct car-expr (p) #:transparent)
- (struct cdr-expr (p) #:transparent)
- (struct pair?-expr (p) #:transparent)
- (struct null-expr () #:transparent)
- (struct null?-expr (e) #:transparent)
- (struct symbol-expr (v) #:transparent)
- (struct symbol?-expr (e) #:transparent)
- (struct lambda-expr (xs b) #:transparent)
- (struct app-expr (f es) #:transparent)
- (struct apply-expr (f e) #:transparent)
- (struct closure (x b e))
- (define (expr? e)
- (match e
- [(variable s) (symbol? s)]
- [(const n) (or (number? n)
- (boolean? n))]
- [(op s l r) (and (member s '(+ *))
- (expr? l)
- (expr? r))]
- [(let-expr x e1 e2) (and (symbol? x)
- (expr? e1)
- (expr? e2))]
- [(if-expr b t e) (andmap expr? (list b t e))]
- [(cons-expr l r) (andmap expr? (list l r))]
- [(car-expr p) (expr? p)]
- [(cdr-expr p) (expr? p)]
- [(pair?-expr p) (expr? p)]
- [(null-expr) true]
- [(null?-expr p) (expr? p)]
- [(symbol-expr v) (symbol? v)]
- [(symbol?-expr p) (expr? p)]
- [(lambda-expr xs b) (and (list? xs)
- (andmap symbol? xs)
- (expr? b)
- (not (check-duplicates xs)))]
- [(app-expr f es) (and (expr? f)
- (list? es)
- (andmap expr? es))]
- [(apply-expr f e) (and (expr? f)
- (expr? e))]
- [_ false]))
- ;; wartości zwracane przez interpreter
- (struct val-symbol (s) #:transparent)
- (define (my-value? v)
- (or (number? v)
- (boolean? v)
- (and (pair? v)
- (my-value? (car v))
- (my-value? (cdr v)))
- ; null-a reprezentujemy symbolem (a nie racketowym
- ; nullem) bez wyraźnej przyczyny
- (and (symbol? v) (eq? v 'null))
- (and ((val-symbol? v) (symbol? (val-symbol-s v))))))
- ;; wyszukiwanie wartości dla klucza na liście asocjacyjnej
- ;; dwuelementowych list
- (define (lookup x xs)
- (cond
- [(null? xs)
- (error x "unknown identifier :(")]
- [(eq? (caar xs) x) (cadar xs)]
- [else (lookup x (cdr xs))]))
- ;; kilka operatorów do wykorzystania w interpreterze
- (define (op-to-proc x)
- (lookup x `(
- (+ ,+)
- (* ,*)
- (- ,-)
- (/ ,/)
- (> ,>)
- (>= ,>=)
- (< ,<)
- (<= ,<=)
- (= ,=)
- (eq? ,(lambda (x y) (eq? (val-symbol-s x)
- (val-symbol-s y))))
- )))
- ;; interfejs do obsługi środowisk
- (define (env-empty) null)
- (define env-lookup lookup)
- (define (env-add x v env)
- (cond [(or (and (null? x) (not (null? v))) (and (null? v) (not (null? x))))
- (error "różne liczby argumentów :(")]
- [(symbol? x) (cons (list x v) env)]
- [(and (null? x) (null? v)) env]
- [else (let ([cdv (if (pair? v) (cdr v) null)]
- [cdx (if (pair? x) (cdr x) null)]
- [cav (if (pair? v) (car v) v)]
- [cax (if (pair? x) (car x) x)])
- (env-add cdx cdv (cons (list cax cav) env)))]))
- (define (env? e)
- (and (list? e)
- (andmap (lambda (xs) (and (list? e)
- (= (length e) 2)
- (symbol? (first e)))))))
- ;; interpretacja wyrażeń
- (define (eval e env)
- (match e
- [(const n) n]
- [(op s l r)
- ((op-to-proc s) (eval l env)
- (eval r env))]
- [(let-expr x e1 e2)
- (let ((v1 (eval e1 env)))
- (eval e2 (env-add x v1 env)))]
- [(variable x) (env-lookup x env)]
- [(if-expr b t e) (if (eval b env)
- (eval t env)
- (eval e env))]
- [(cons-expr l r)
- (let ((vl (eval l env)) ;; dodawanie zmiennych do env
- (vr (eval r env)))
- (cons vl vr))]
- [(car-expr p) (car (eval p env))]
- [(cdr-expr p) (cdr (eval p env))]
- [(pair?-expr p) (pair? (eval p env))]
- [(null-expr) 'null]
- [(null?-expr e) (eq? (eval e env) 'null)]
- [(symbol-expr v) (val-symbol v)]
- [(lambda-expr xs b) (closure xs b env)]
- [(app-expr f e) (let ((vf (eval f env))
- (ve e))
- (match vf
- [(closure x b c-env)
- (eval b (env-add x ve c-env))]
- [_ (error "application: not a function :(")]))]
- [(apply-expr f e) (let ([vf (eval f env)]
- [ve (eval e env)])
- (match vf
- [(closure x b c-env)
- (eval b (env-add x ve c-env))]))]))
- (define (run e)
- (eval e (env-empty)))
- (define gg
- (let-expr 'foo
- (lambda-expr '(x y z)
- (op '+ (variable 'x) (op '+ (variable 'y) (variable 'z))))
- (apply-expr (variable 'foo) (cons-expr (const 1) (cons-expr (const 2) (const 3))))))
- (my-value? (run gg))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement