dynamic.fnl

Branches > main > d3c0a10 > files / nvim / pack / plugins / opt / conjure / fnl / conjure / dynamic.fnl

(local {: autoload : define} (require :conjure.nfnl.module))
(local core (autoload :conjure.nfnl.core))

(local M (define :conjure.dynamic))

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

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

(fn M.new [base-value]
  (assert-value-function! base-value)
  (let [stack [base-value]]
    (fn [x ...]
      (if (= get-stack-key x)
        stack
        ((core.last stack) x ...)))))

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

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

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

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

M