-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy patheval.rkt
More file actions
84 lines (67 loc) · 2.81 KB
/
eval.rkt
File metadata and controls
84 lines (67 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#lang racket
(require "ast.rkt")
;; ===================================================
;; ===================================================
;; STACK MACHINE EVALUATION
;; ===================================================
;; ===================================================
;; type Expression = Word*
;; An expression is a list of operators, commonly called
;; 'words' in Forth and related languages.
;; type MachineState = (Stack Value, Expression)
;; A machine consists of:
;; 1. a stack of values, which will end up as the result
;; of evaluation
;; 2. an expression to evaluate
(struct machine (stack expr) #:transparent)
;; eval-barley :: Expression -> Stack | Error
;; Runs the expression e on an initial (empty)
;; stack. The machine terminates when the
;; expression is 'empty' (expressions are just
;; a list of operators). If no transition rule
;; can be applied and the expression part is not
;; empty, then the machine is 'stuck'.
(define (eval-wort e)
;; step-eval :: MachineState -> Stack | Error
(define (step-eval state)
(if (empty? (machine-expr state))
(machine-stack state)
(step-eval (step state))))
;; step :: MachineState -> MachineState | Error
(define (step state)
(match state
;; Pushing values
[(machine s (list c e ...))
#:when (or (number? c)
(boolean? c)
(ast-block? c))
(machine (cons c s) e)]
;; Value binding
[(machine (list v s ...) (list (ast-bind name body) e ...))
(machine s (append (subst name (list v) body) e))]
;; Let binding
[(machine s (list (ast-let name arg body) e ...))
(machine s (append (subst name arg body) e))]
;; Primitives
[(machine (list n1 n2 s ...) (list (ast-prim "add") e ...))
(machine (list* (+ n1 n2) s) e)]
[(machine (list (ast-block exp) s ...) (list (ast-prim "call") e ...))
(machine s (append exp e))]
[(machine (list (ast-block exp) s ...) (list (ast-prim "fix") e ...))
(machine (list* (ast-block (list (ast-block exp) (ast-prim "fix"))) s)
(append exp e))]
[(machine (list #t v1 v2 s ...) (list (ast-prim "if") e ...))
(machine (list* v1 s) e)]
[(machine (list #f v1 v2 s ...) (list (ast-prim "if") e ...))
(machine (list* v2 s) e)]
[(machine (list n1 n2 s ...) (list (ast-prim "eq") e ...))
#:when (and (number? n1) (number? n2))
(machine (list* (eq? n1 n2) s) e)]
[(machine (list n1 n2 s ...) (list (ast-prim "less") e ...))
#:when (and (number? n1) (number? n2))
(machine (list* (< n2 n1) s) e)]
;; Stuck (should never occur if inference passes!)
[_
(error "looks like we're stuck!")]))
(step-eval (machine (list) e)))
(provide eval-wort)