48 lines
1.3 KiB
Racket
48 lines
1.3 KiB
Racket
#lang racket
|
|
|
|
(require racket/fixnum)
|
|
(require racket/dict)
|
|
(require racket/struct)
|
|
|
|
(provide Int Prim Var Let Program interp-RVar-class interp-RVar)
|
|
|
|
(struct Int (value) #:transparent)
|
|
(struct Var (name) #:transparent)
|
|
(struct Prim (op args) #:transparent)
|
|
(struct Let (var expr body) #:transparent)
|
|
|
|
(struct Program (info body) #:transparent)
|
|
|
|
(define interp-RVar-class
|
|
(class object%
|
|
(super-new)
|
|
|
|
(define/public ((interp-exp env) exp)
|
|
(match exp
|
|
[(Int n) n]
|
|
[(Var name) (eval-symbol env name)]
|
|
[(Prim 'read '()) (read-fixnum)]
|
|
[(Prim '- (list e)) (fx- 0 ((interp-exp env) e))]
|
|
[(Prim '+ `(,e1 ,e2)) (fx+ ((interp-exp env) e1) ((interp-exp env) e2))]
|
|
[(Let var rexp body)
|
|
(let ([value ((interp-exp env) rexp)])
|
|
((interp-exp (dict-set env var value)) body))]))
|
|
|
|
(define/public (interp-program program)
|
|
(match program
|
|
[(Program _ body) ((interp-exp (make-immutable-hash)) body)]))))
|
|
|
|
(define (read-fixnum)
|
|
(let ([r (read)])
|
|
(cond
|
|
[(fixnum? r) r]
|
|
[else (error "invalid fixnum in input: " r)])))
|
|
|
|
(define (eval-symbol env s)
|
|
(if (dict-has-key? env s)
|
|
(dict-ref env s)
|
|
(error "Symbol " s " not found")))
|
|
|
|
(define (interp-RVar program)
|
|
(send (new interp-RVar-class) interp-program program))
|