~subsetpark/ec

ref: 44351a16f5df24d3489ee0f6084204e43d034d78 ec/src/eval.janet -rw-r--r-- 1.8 KiB
44351a16 — Zach Smith Update README 9 months ago
                                                                                
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
(use fugue)
(use /src/calc)

(def define (:new Adverb
                  :arity 2
                  :type :define
                  :fun-ref (fn define [stack]
                             (let [sym (pop stack)
                                   q (pop stack)]
                               (match sym
                                 {:value sym-value :quoted? true} (put-in stack [:env sym-value] q))))))


(defn lookup
  ```
  Look up a symbol in a stack 's environment. The symbol might refer
  to an atomic element or to an unevaluated quotation.
  ```
  [stack sym-value]
  (match (get-in stack [:env sym-value])
    # Mark the stored quotation for evaluation by creating a Thunk out
    # of it, which is a Quotation that evaluates its contents when
    # pushed to the stack.
    (q (Quotation? q)) (:new Thunk (q :data))
    nil (errorf "Eval error: unknown word %s" sym-value)
    elem elem))

(defn eval
  ```
  Evaluate an unquoted symbol by looking it up in the stack
  environment; all other types evaluate to themselves.
  ```
  [stack sym]
  (match sym
    {:value sym-value :quoted? false} (lookup stack sym-value)
    _ sym))

(defn apply-quotation
  ```
  Quotation evaluation. Given any potentially unevaluated quotation,
  evaluate and push each element.
  ```
  [stack maybe-quote]
  (match maybe-quote
    (q (Quotation*? q)) (each elem (data q)
                          (->> elem
                               (eval stack)
                               (push stack)))
    not-a-quote (push stack not-a-quote)))

(extend-multi push
              [Stack Thunk]
              [stack thunk]
              (let [evaled (map |(eval stack $) (thunk :data))
                    q (:new Quotation evaled)]
                (apply-quotation stack q)))

(defn eval-and-push
  [stack symbol]
  (->> symbol
       (eval stack)
       (push stack)))