Files
kraken/bf.kp
Nathan Braswell 8e296d57c8 Add atom syntax
2020-05-12 09:19:01 -04:00

51 lines
2.4 KiB
Plaintext

; Use the power of GLL reader macros to implement
; BF support
; Add atoms as length 1 vectors with nice syntax for deref
(def! make-atom (fn* (x) [x]))
(def! set-atom! (fn* (x y) (set-nth! x 0 y)))
(def! get-atom (fn* (x) (nth x 0)))
(add_grammer_rule 'form ["@" 'form] (fn* (xs) `(get-atom ~(nth xs 1))))
; Define our tokens as BF atoms
; Ugly b/c using 1-length vectors as atoms
(add_grammer_rule 'bfs_atom ["<"] (fn* (xs) '(set-atom! cursor (- @cursor 1))))
(add_grammer_rule 'bfs_atom [">"] (fn* (xs) '(set-atom! cursor (+ @cursor 1))))
(add_grammer_rule 'bfs_atom ["\\+"] (fn* (xs) '(set-nth! tape @cursor (+ (nth tape @cursor) 1))))
(add_grammer_rule 'bfs_atom ["-"] (fn* (xs) '(set-nth! tape @cursor (- (nth tape @cursor) 1))))
(add_grammer_rule 'bfs_atom [","] (fn* (xs) '(let* (value (nth input @inptr)) (do (set-atom! inptr (+ 1 @inptr)) (do (set-nth! tape @cursor value))))))
(add_grammer_rule 'bfs_atom ["."] (fn* (xs) '(set-atom! output (cons (nth tape @cursor) @output))))
; Define strings of BF atoms
(add_grammer_rule 'bfs ['bfs_atom *] (fn* (xs) (nth xs 0)))
; Add loop as an atom
(add_grammer_rule 'bfs_atom ["\\[" 'bfs "]"] (fn* (xs)
`(let* (f (fn* (f)
(if (= 0 (nth tape @cursor))
nil
(do ,(nth xs 1) (f f)))))
(f f))))
; For now, stick BFS rule inside an unambigious BFS block
; and add compilation/implementation
; Note that this compilation into the underlying Lisp
; happens at macro evaluation time. If this code were
; to be compiled to C, it would be compiled all the way
; to C code with no trace of the original BF code.
(add_grammer_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"]
(fn* (xs)
`(fn* (input)
(let* (
tape (vector 0 0 0 0 0)
cursor (make-atom 0)
inptr (make-atom 0)
output (make-atom (vector))
)
(do (println "beginning bfs") ,(nth xs 4) (nth output 0))))))
; Let's try it out! This BF program prints the input 3 times
(println (bf { ,>+++[<.>-] } [1337]))
; we can also have it compile into our main program
(def! main (fn* () (do (println "BF: " (bf { ,>+++[<.>-] } [1337])) 0)))