schleifen

A toy interpreter for LOOP programs

git clone https://git.8pit.net/schleifen.git

 1(require-extension srfi-1)
 2
 3(define (set-variable env variable)
 4  (let ((pair (assoc (car variable) env)))
 5    (if pair
 6        (begin
 7          (set-cdr! pair (cdr variable))
 8          env)
 9        (cons variable env))))
10
11(define (ntimes n fn arg)
12  (if (> n 0)
13      (ntimes (- n 1) fn (fn arg))
14      arg))
15
16(define (variable-name lvalue)
17  (assert (eq? (car lvalue) 'var))
18  (cdr lvalue))
19
20(define (variable-value env variable)
21  (assert (eq? (car variable) 'var))
22  (let ((value (assoc (cdr variable) env)))
23    (if value (cdr value) 0)))
24
25(define (eval-literal literal)
26  (assert (eq? (car literal) 'lit))
27  (cdr literal))
28
29(define (eval-operation op)
30  (assert (eq? (car op) 'op))
31  (let ((o (cdr op)))
32    (cond ((eq? o 'plus) +)
33          ((eq? o 'minus) -)
34          (else (error "invalid operation")))))
35
36(define (eval-expression env expr)
37  (assert (eq? (car expr) 'expr))
38  (let ((v1 (eval-rvalue env (second expr)))
39        (op (eval-operation (third expr)))
40        (v2 (eval-rvalue env (fourth expr))))
41    (op v1 v2)))
42
43(define (eval-rvalue env rvalue)
44  (let ((kind (car rvalue)))
45    (cond ((eq? kind 'lit)
46           (eval-literal rvalue))
47          ((eq? kind 'var)
48           (variable-value env rvalue))
49          ((eq? kind 'expr)
50           (eval-expression env rvalue))
51          (else (display kind) (newline) (error "invalid rvalue")))))
52
53(define (eval-assign env lvalue rvalue)
54  (set-variable env (cons (variable-name lvalue)
55                          (eval-rvalue env rvalue))))
56
57(define (eval-loop env cond body)
58  (let ((amount (eval-rvalue env cond)))
59    (ntimes amount (lambda (env)
60                     (eval-loop-prog env body)) env)))
61
62(define (eval-command comp env)
63  (let ((kind (car comp)) (args (cdr comp)))
64    (cond ((eq? kind 'loop)
65           (eval-loop env (first args) (second args)))
66          ((eq? kind 'assign)
67           (eval-assign env (first args) (second args)))
68          (else (error "invalid command")))))
69
70(define (eval-loop-prog env prog)
71  (fold eval-command env prog))