~subsetpark/ec

ref: 91f88d6a778e1f17c8e3bed2586333e1100b013f ec/src/eval.janet -rw-r--r-- 1.9 KiB
91f88d6a — Zach Smith Move Symbol to parser 3 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)
(import /src/calc)

(def define (:new calc/Adverb
                  :arity 2
                  :type :define
                  :fun-ref (fn define [stack]
                             (let [sym (calc/pop stack)
                                   q (calc/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 (calc/Quotation? q)) (:new calc/Thunk (calc/data q))
    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 (calc/Quotation*? q)) (each elem (calc/data q)
                               (->> elem
                                    (eval stack)
                                    (calc/push stack)))
    not-a-quote (calc/push stack not-a-quote)))

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

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