Skip to content

Commit

Permalink
Convert dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
russtoku committed Aug 31, 2024
1 parent e41f241 commit 30eea22
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 47 deletions.
98 changes: 98 additions & 0 deletions fnl/conjure-spec/dynamic_spec.fnl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
(local {: describe : it} (require :plenary.busted))
(local assert (require :luassert.assert))

(local dyn (require :conjure.dynamic))

(describe "conjure.dynamic"
(fn []
(describe "new-and-unbox"
(fn []
(let [foo (dyn.new #(do :bar))]
(it "new returns a function"
(fn []
(assert.are.equals :function (type foo))))
(it "function is wrapped"
(fn []
(assert.are.equals :bar (foo)))))))

(describe "bind"
(fn []
(let [foo (dyn.new #(do 1))]
(it "one level deep"
(fn []
(assert.are.equals 1 (foo))))
(it "two levels deep"
(fn []
(dyn.bind
{foo #(do 2)}
(fn [expected]
(assert.are.equals expected (foo)))
2)))
(it "no more than two levels deep"
(fn []
(dyn.bind
{foo #(do 2)}
(fn []
(assert.are.equals 2 (foo))
(dyn.bind
{foo #(do 3)}
(fn []
(assert.are.equals 3 (foo))))
(dyn.bind
{foo #(error "OHNO")}
(fn []
(let [(ok? result) (pcall foo)]
(assert.are.equals false ok?)
(assert.are.equals result "OHNO"))))
(assert.are.equals 2 (foo)))))))))

(describe "set!"
(fn []
(let [foo (dyn.new #(do 1))]
(it "one level deep"
(fn []
(assert.are.equals (foo) 1)))
(it "more than two levels deep"
(fn []
(dyn.bind
{foo #(do 2)}
(fn []
(assert.are.equals (foo) 2)
(assert.are.equals nil (dyn.set! foo #(do 3)))
(assert.are.equals (foo) 3))))))))

(describe "set-root!"
(fn []
(let [foo (dyn.new #(do 1))]
(it "one level deep"
(fn []
(assert.are.equals (foo) 1)))
(it "three levels deep"
(fn []
(dyn.bind
{foo #(do 2)}
(fn []
(assert.are.equals (foo) 2)
(assert.are.equals nil (dyn.set-root! foo #(do 3)))
(assert.are.equals (foo) 2)))))
(it "remembers binding from three levels deep"
(fn []
(assert.are.equals (foo) 3)))
(it "four levels deep"
(fn []
(dyn.set-root! foo #(do 4))))
(it "remembers binding from four levels deep"
(fn []
(assert.are.equals (foo) 4))))))

(describe "type-guard"
(fn []
(let [(ok? result) (pcall dyn.new :foo)]
(it "direct call of conjure.dynamic value fails"
(fn []
(assert.are.equals false ok?)
))
(it "returns why failed"
(fn []
(assert.is_not_nil (string.match result "conjure.dynamic values must always be wrapped in a function"))
nil)))))))
25 changes: 13 additions & 12 deletions fnl/conjure/dynamic.fnl
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
(import-macros {: module : def : defn : defonce : def- : defn- : defonce- : wrap-last-expr : wrap-module-body : deftest} :nfnl.macros.aniseed)
(local {: autoload} (require :nfnl.module))
(local a (autoload :conjure.aniseed.core))

(module conjure.dynamic
{autoload {a conjure.aniseed.core}})
(local get-stack-key :conjure.dynamic/get-stack)

(def- get-stack-key :conjure.dynamic/get-stack)

(defn- assert-value-function! [value]
(fn assert-value-function! [value]
(when (not= :function (type value))
(error "conjure.dynamic values must always be wrapped in a function")))

(defn new [base-value]
(fn new [base-value]
(assert-value-function! base-value)
(var stack [base-value])
(fn [x ...]
(if (= get-stack-key x) stack
((a.last stack) x ...))))

(defn- run-binds! [f binds]
(fn run-binds! [f binds]
(a.map-indexed
(fn [[dyn new-value]]
(assert-value-function! new-value)
(f (dyn get-stack-key) new-value))
binds))

(defn bind [binds f ...]
(fn bind [binds f ...]
(run-binds! table.insert binds)
(let [(ok? result) (pcall f ...)]
(run-binds! #(table.remove $1) binds)
(if ok?
result
(error result))))

(defn set! [dyn new-value]
(fn set! [dyn new-value]
(assert-value-function! new-value)
(let [stack (dyn get-stack-key)
depth (a.count stack)]
(a.assoc stack depth new-value))
nil)

(defn set-root! [dyn new-value]
(fn set-root! [dyn new-value]
(assert-value-function! new-value)
(a.assoc (dyn get-stack-key) 1 new-value)
nil)

*module*
{: new
: bind
: set!
: set-root!}
156 changes: 156 additions & 0 deletions lua/conjure-spec/dynamic_spec.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 30eea22

Please sign in to comment.