2 ;████████╗██╗ ██╗██╗ ██╗███╗ ██╗
3 ;╚══██╔══╝██║ ██║██║ ██║████╗ ██║
4 ; ██║ ███████║██║ ██║██╔██╗ ██║
5 ; ██║ ██╔══██║██║ ██║██║╚██╗██║
6 ; ██║ ██║ ██║╚██████╔╝██║ ╚████║
7 ; ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
9 ;Copyright © 2023 Simon Forman
11 ;This file is part of Thun
13 ;Thun is free software: you can redistribute it and/or modify
14 ;it under the terms of the GNU General Public License as published by
15 ;the Free Software Foundation, either version 3 of the License, or
16 ;(at your option) any later version.
18 ;Thun is distributed in the hope that it will be useful,
19 ;but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;GNU General Public License for more details.
23 ;You should have received a copy of the GNU General Public License
24 ;along with Thun. If not see <http://www.gnu.org/licenses/>.
28 (import (chicken string))
32 ;(load "defs.scm") ; csc -prologue defs.scm joy.scm
34 (chicken-script (load "defs.scm"))
38 ;██╗███╗ ██╗████████╗███████╗██████╗ ██████╗ ██████╗ ███████╗████████╗███████╗██████╗
39 ;██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██╔════╝██╔══██╗
40 ;██║██╔██╗ ██║ ██║ █████╗ ██████╔╝██████╔╝██████╔╝█████╗ ██║ █████╗ ██████╔╝
41 ;██║██║╚██╗██║ ██║ ██╔══╝ ██╔══██╗██╔═══╝ ██╔══██╗██╔══╝ ██║ ██╔══╝ ██╔══██╗
42 ;██║██║ ╚████║ ██║ ███████╗██║ ██║██║ ██║ ██║███████╗ ██║ ███████╗██║ ██║
43 ;╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
46 (define (joy stack expression dict)
47 ;(joy-trace stack expression)
48 (if (null? expression)
50 (if (string? (car expression))
52 (joy-eval (car expression) stack (cdr expression) dict)
54 (joy (cons (car expression) stack) (cdr expression) dict))))
56 (define (joy-eval symbol stack expression dict)
58 ((or "+" "add") ((joy-func +) stack expression dict))
59 ((or "-" "sub") ((joy-func -) stack expression dict))
60 ((or "*" "mul") ((joy-func *) stack expression dict))
61 ((or "/" "div") ((joy-func quotient) stack expression dict)) ; but for negative divisor, no!?
62 ((or "%" "mod") ((joy-func modulo) stack expression dict))
64 ("<" ((joy-func <) stack expression dict))
65 (">" ((joy-func >) stack expression dict))
66 ("<=" ((joy-func <=) stack expression dict))
67 (">=" ((joy-func >=) stack expression dict))
68 ("=" ((joy-func =) stack expression dict))
69 ((or "<>" "!=") ((joy-func not-equal) stack expression dict))
71 ("bool" (joy-bool stack expression dict))
73 ("dup" (values (cons (car stack) stack) expression dict))
74 ("pop" (values (cdr stack) expression dict))
75 ("stack" (values (cons stack stack) expression dict))
76 ("swaack" (values (cons (cdr stack) (car stack)) expression dict))
77 ("swap" (values (cons (cadr stack) (cons (car stack) (cddr stack))) expression dict))
79 ("concat" ((joy-func append) stack expression dict))
80 ("cons" ((joy-func cons) stack expression dict))
81 ("first" (values (cons (caar stack) (cdr stack)) expression dict))
82 ("rest" (values (cons (cdar stack) (cdr stack)) expression dict))
84 ("i" (joy-i stack expression dict))
85 ("dip" (joy-dip stack expression dict))
86 ("branch" (joy-branch stack expression dict))
87 ("loop" (joy-loop stack expression dict))
89 (_ (if (hash-table-exists? dict symbol)
90 (values stack (append (hash-table-ref dict symbol) expression) dict)
91 (error (conc "Unknown word: " symbol))))))
93 (define (not-equal a b) (not (= a b)))
96 (lambda (stack expression dict)
97 (values (cons (op (cadr stack) (car stack)) (cddr stack)) expression dict)))
100 (define (joy-bool stack expression dict)
101 (values (cons (joy-bool-term (car stack)) (cdr stack)) expression dict))
103 (define (joy-bool-term term)
104 (cond ((boolean? term) term)
105 ((number? term) (not-equal 0 term))
106 ((list? term) (not (null? term)))
110 ; ██████╗ ██████╗ ███╗ ███╗██████╗ ██╗███╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗
111 ;██╔════╝██╔═══██╗████╗ ████║██╔══██╗██║████╗ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗██╔════╝
112 ;██║ ██║ ██║██╔████╔██║██████╔╝██║██╔██╗ ██║███████║ ██║ ██║ ██║██████╔╝███████╗
113 ;██║ ██║ ██║██║╚██╔╝██║██╔══██╗██║██║╚██╗██║██╔══██║ ██║ ██║ ██║██╔══██╗╚════██║
114 ;╚██████╗╚██████╔╝██║ ╚═╝ ██║██████╔╝██║██║ ╚████║██║ ██║ ██║ ╚██████╔╝██║ ██║███████║
115 ; ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
118 (define (joy-i stack expression dict)
119 (values (cdr stack) (append (car stack) expression) dict))
121 (define (joy-dip stack expression dict)
123 (append (car stack) (cons (cadr stack) expression))
126 (define (joy-branch stack expression dict)
127 (let ((flag (caddr stack))
128 (false_body (cadr stack))
129 (true_body (car stack)))
130 (values (cdddr stack)
131 (append (if flag true_body false_body) expression)
134 (define (joy-loop stack expression dict)
135 (let ((flag (cadr stack))
138 (if flag (append body (cons body (cons "loop" expression))) expression)
142 ;██████╗ █████╗ ██████╗ ███████╗███████╗██████╗
143 ;██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗
144 ;██████╔╝███████║██████╔╝███████╗█████╗ ██████╔╝
145 ;██╔═══╝ ██╔══██║██╔══██╗╚════██║██╔══╝ ██╔══██╗
146 ;██║ ██║ ██║██║ ██║███████║███████╗██║ ██║
147 ;╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝
150 (define (string-replace str from to)
151 (string-intersperse (string-split str from #t) to))
153 (define (tokenize str)
155 (string-replace (string-replace str "]" " ] ") "[" " [ ")))
157 (define (tokenator token)
158 (cond ((string->number token) (string->number token))
159 ((string=? token "true") #t)
160 ((string=? token "false") #f)
163 (define (expect-right-bracket tokens acc)
165 (error "Missing closing bracket.")
166 (expect-right-bracket-lookahead (car tokens) (cdr tokens) acc)))
168 (define (expect-right-bracket-lookahead token tokens acc)
170 ("]" (values acc tokens))
171 ("[" (receive (sub_list rest) (expect-right-bracket tokens '())
172 (receive (el rrest) (expect-right-bracket rest acc)
173 (values (cons sub_list el) rrest))))
174 (_ (receive (el rest) (expect-right-bracket tokens acc)
175 (values (cons (tokenator token) el) rest)))))
177 (define (one-token-lookahead token tokens)
179 ("]" (error "Extra closing bracket."))
180 ("[" (expect-right-bracket tokens '()))
181 (_ (values (tokenator token) tokens))))
183 (define (parse0 tokens acc)
186 (receive (term rest_of_tokens)
187 (one-token-lookahead (car tokens) (cdr tokens))
188 (cons term (parse0 rest_of_tokens acc)))))
190 (define (parse tokens) (parse0 tokens '()))
192 (define (text->expression text) (parse (tokenize text)))
195 ;██████╗ ██████╗ ██╗███╗ ██╗████████╗███████╗██████╗
196 ;██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗
197 ;██████╔╝██████╔╝██║██╔██╗ ██║ ██║ █████╗ ██████╔╝
198 ;██╔═══╝ ██╔══██╗██║██║╚██╗██║ ██║ ██╔══╝ ██╔══██╗
199 ;██║ ██║ ██║██║██║ ╚████║ ██║ ███████╗██║ ██║
200 ;╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
203 (define (joy-term->string term)
204 (cond ((boolean? term) (if term "true" "false"))
205 ((number? term) (->string term))
206 ((list? term) (conc "[" (joy-expression->string term) "]"))
209 (define (joy-expression->string expr)
210 (string-intersperse (map joy-term->string expr) " "))
213 ;██████╗ ███████╗███████╗██╗███╗ ██╗██╗████████╗██╗ ██████╗ ███╗ ██╗███████╗
214 ;██╔══██╗██╔════╝██╔════╝██║████╗ ██║██║╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝
215 ;██║ ██║█████╗ █████╗ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗
216 ;██║ ██║██╔══╝ ██╔══╝ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║
217 ;██████╔╝███████╗██║ ██║██║ ╚████║██║ ██║ ██║╚██████╔╝██║ ╚████║███████║
218 ;╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
222 (load-defs! (make-hash-table string=? string-hash)))
224 (define (load-defs! dict)
225 (for-each (lambda (def) (add-def! def dict)) (defs))
226 ; defs is defined in defs.scm
229 (define (add-def! def dict)
230 (let ((def_list (text->expression def)))
231 (hash-table-set! dict (car def_list) (cdr def_list))))
234 ;██████╗ ███████╗██████╗ ██╗
235 ;██╔══██╗██╔════╝██╔══██╗██║
236 ;██████╔╝█████╗ ██████╔╝██║
237 ;██╔══██╗██╔══╝ ██╔═══╝ ██║
238 ;██║ ██║███████╗██║ ███████╗
239 ;╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝
242 (define (prompt) (display "joy? ") (read-line))
244 (define (main-loop stack0 dict0)
245 (let ((text (prompt)))
246 (if (not (eof-object? text))
247 (receive (stack dict) (joy stack0 (text->expression text) dict0)
248 (print (joy-expression->string (reverse stack)))
249 (main-loop stack dict))
252 (define (joy-trace stack expression)
253 (print (conc (joy-expression->string (reverse stack)) " . " (joy-expression->string expression))))
255 (main-loop '() (initialize))
258 ;(display (doit "5 [] cons [4] concat first"))
259 ;(display (doit "5 down_to_zero"))
260 ;(display (doit "1 2 true [4 5 false] loop <"))