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)
- (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)]
- [_ false]))
- ;; wartości zwracane przez interpreter
- (struct val-symbol (s))
- (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 `(
- (+ ,+)
- (* ,*)
- (- ,-)
- (/ ,/)
- (> ,>)
- (>= ,>=)
- (< ,<)
- (<= ,<=)
- (= ,=)
- (% ,modulo)
- (!= ,(lambda (x y) (not (= x y))))
- (&& ,(lambda (x y) (and x y)))
- (|| ,(lambda (x y) (or x y)))
- (eq? ,(lambda (x y) (eq? (val-symbol-s x)
- (val-symbol-s y))))
- )))
- ;; definicja instrukcji w języku WHILE
- (struct skip () #:transparent) ; skip
- (struct comp (s1 s2) #:transparent) ; s1; s2
- (struct assign (x e) #:transparent) ; x := e
- (struct while (b s) #:transparent) ; while (b) s
- (struct if-stm (b t e) #:transparent) ; if (b) t else e
- (struct var-block (x e s) #:transparent) ; var x := e in s
- (define (stm? e)
- (match e
- [(skip) true]
- [(comp s1 s2) (and (stm? s1) (stm? s2))]
- [(assign x e) (and (symbol? x) (expr? e))]
- [(while b s) (and (expr? b) (stm? s))]
- [(if-stm b t e) (and (expr? b) (stm? t) (stm? e))]
- [_ false]))
- ;; aktualizacja środowiska dla danej zmiennej (koniecznie już
- ;; istniejącej w środowisku!)
- (define (update x v xs)
- (cond
- [(null? xs)
- (error x "unknown identifier :(")]
- [(eq? (caar xs) x)
- (cons (list (caar xs) v) (cdr xs))]
- [else
- (cons (car xs) (update x v (cdr xs)))]))
- ;; interfejs do obsługi środowisk
- (define (env-empty) `(() ()))
- (define env-lookup (lambda (x env) (lookup x (car env))))
- (define (env-add x v env) (let ((nowe (cons (list x v) (car env))))
- (cons nowe (cons nowe (cdr env)))))
- (define env-update (lambda (x v env) (let ([nowe (update x v (car env))])
- (cons nowe (cons nowe (cdr env))))))
- (define env-discard (lambda (env) (let ([nowe (cdr (car env))])
- (cons nowe (cons nowe (cdr env))))))
- (define (env-from-assoc-list xs) (list xs xs))
- ;; ewaluacja wyrażeń ze środowiskiem
- (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))
- (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)]))
- ;; interpretacja programów w języku WHILE, gdzie środowisko m to stan
- ;; pamięci. Interpreter to procedura, która dostaje program i początkowy
- ;; stan pamięci, a której wynikiem jest końcowy stan pamięci. Pamięć to
- ;; aktualne środowisko zawierające wartości zmiennych
- (define (interp p m)
- (match p
- [(skip) m]
- [(comp s1 s2) (interp s2 (interp s1 m))]
- [(assign x e)
- (env-update x (eval e m) m)]
- [(while b s)
- (if (eval b m)
- (interp p (interp s m))
- m)]
- [(var-block x e s)
- (env-discard
- (interp s (env-add x (eval e m) m)))]
- [(if-stm b t e) (if (eval b m)
- (interp t m)
- (interp e m))]))
- (define fact-in-WHILE
- (var-block 'x (const 0) ; var x := 0 in
- (comp (assign 'x (const 1)) ; x := 1
- (comp (while (op '> (variable 'i) (const 0)) ; while (i > 0)
- (comp (assign 'x (op '* (variable 'x) (variable 'i))) ; x := x * i
- (assign 'i (op '- (variable 'i) (const 1))))) ; i := i - 1
- (assign 'i (variable 'x)))))) ; i := x
- (define (factorial n)
- (env-lookup 'i (interp fact-in-WHILE
- (env-from-assoc-list `((i ,n))))))
- (define (debug prog env)
- (let ((wart (interp prog env)))
- (reverse (cdr wart))))
- (debug fact-in-WHILE (env-from-assoc-list `((i ,5))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement