~subsetpark/ec

ref: 94834b663b7832d197e1f4d314b2e2f5b8e7a716 ec/main.janet -rw-r--r-- 2.3 KiB
94834b66 — Zach Smith Use parens for quotes 11 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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
(import /src/calc)
(import /src/print)
(import /src/parser)

(defn handle-signal
  [input]
  (let [str (string input)]
    (when (= str "") (os/exit 0))
    str))

(defn- display
  [data]
  (print (print/p data))
  "")

(defn- display-all
  [stack]
  (let [inner (map print/p stack)]
    (print (string/join inner " ")))
  "")

(defn- display-help
  []
  (each [k v] (pairs parser/dictionary)
    (printf "%s: %s" k (string (v :type))))
  "")

(defn- describe-all
  [q]
  (defn- describe
    [elem]
    (printf "%s\n\n%s: %s"
            (print/p elem)
            (string (elem :type))
            (elem :doc)))
  (each item (q :data)
    (describe item))
  "")

(defn- handle-special
  [s special]
  (case (freeze (string/trim special))
    "." (display (calc/peek s))
    "p" (display (calc/pop s))
    "s" (display-all (s :data))
    "?" (describe-all (calc/pop s))
    "??" (display-help)))

(defn handle-commands
  [s input]
  (each token input
    (match token
      @[:special patt] (handle-special s patt)
      _ (calc/push s token))))

(def- max-width 40)
(def delimiters-peg (peg/compile
                     ~{:main (+ :parens :brackets)
                       :parens (* (look -1 ")") (not "...") (to "("))
                       :brackets (* (look -1 "]") (not "...") (to "["))}))

(defn- truncate
  [peek]
  (var buf (buffer peek))
  (var last-length (length buf))
  
  (reverse! buf)
  
  (while (> (length buf) 40)
    (set buf (tracev (peg/replace delimiters-peg "..." buf)))
    (if (= (length buf) last-length) (break))
    (set last-length (length buf)))
  
  (string (reverse! buf)))

(defn- prompt
  [s]
  (->> s
       (calc/peek)
       (print/p)
       (truncate)
       (string/format "<%s> $ ")))

(defn repl
  []
  (def s (:new calc/Stack))
  (while true
    (def bak (array/slice (s :data)))
    (try (->> (getline (prompt s) @"" parser/dictionary)
              (handle-signal)
              (parser/parse)
              (handle-commands s))

      ([err fib]
        (eprint err)
        (if (os/getenv "EC_TRACEBACK")
          (propagate err fib)
          (put s :data bak))))))

(defn handle-line
  [line]
  (let [s (:new calc/Stack)]
    (->> line
         (parser/parse)
         (handle-commands s))
    (display-all (s :data))))

(defn main
  [_cmd & args]
  (if (empty? args)
    (repl)
    (handle-line (string/join args " "))))