summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Listopadov <andreyorst@gmail.com>2022-09-07 22:50:35 +0300
committerAndrey Listopadov <andreyorst@gmail.com>2022-09-07 22:50:35 +0300
commitc97f013651a262a62e094b69655bc0adb504dfcc (patch)
tree5391922c16026efe0abdbfb6dffa700359aa2bd4
parent75a3214d5b04cbd3ca4ca1ce2f07d9ea0da952b1 (diff)
support automatic relative require in the ns macro
-rw-r--r--init-macros.fnl58
-rw-r--r--init.fnl4
2 files changed, 39 insertions, 23 deletions
diff --git a/init-macros.fnl b/init-macros.fnl
index a8d3e70..569bee7 100644
--- a/init-macros.fnl
+++ b/init-macros.fnl
@@ -33,7 +33,25 @@ SOFTWARE.")
(var current-ns nil)
+(fn has? [tbl sym]
+ ;; searches for the given symbol in a table.
+ (var has false)
+ (each [_ elt (ipairs tbl) :until has]
+ (set has (= sym elt)))
+ has)
+
+(fn make-require [module relative?]
+ (let [module (tostring module)]
+ (if relative?
+ `(if (: (or ... "") :match "(.+%.)[^.]+")
+ (require (.. (: (or ... "") :match "(.+%.)[^.]+") ,module))
+ (= ... "init")
+ (require ,module)
+ (require (.. ... "." ,module)))
+ `(require ,module))))
+
(fn ns [name commentary requirements]
+ "Namespace declaration macro."
(set current-ns name)
(let [bind-table [name]
require-table [{}]
@@ -43,20 +61,21 @@ SOFTWARE.")
(match requirements
[:require & requires]
(each [_ spec (ipairs requires)]
- (match spec
- (where (or [module :as alias :refer names]
- [module :refer names :as alias]))
- (do (table.insert bind-table (collect [_ name (ipairs names) :into {'&as alias}]
- (values (tostring name) name)))
- (table.insert require-table `(require ,(tostring module))))
- [module :as alias]
- (do (table.insert bind-table alias)
- (table.insert require-table `(require ,(tostring module))))
- [module :refer names]
- (do (table.insert bind-table (collect [_ name (ipairs names)]
- (values (tostring name) name)))
- (table.insert require-table `(require ,(tostring module))))
- _ (assert-compile false "wrong require syntax" name)))
+ (let [relative? (has? spec :relative)]
+ (match spec
+ (where (or [module :as alias :refer names]
+ [module :refer names :as alias]))
+ (do (table.insert bind-table (collect [_ name (ipairs names) :into {'&as alias}]
+ (values (tostring name) name)))
+ (table.insert require-table (make-require module relative?)))
+ [module :as alias]
+ (do (table.insert bind-table alias)
+ (table.insert require-table (make-require module relative?)))
+ [module :refer names]
+ (do (table.insert bind-table (collect [_ name (ipairs names)]
+ (values (tostring name) name)))
+ (table.insert require-table (make-require module relative?)))
+ _ (assert-compile false "wrong require syntax" name))))
nil nil
_ (assert-compile false "wrong require syntax" name))
(if (string? commentary)
@@ -70,6 +89,10 @@ SOFTWARE.")
;;; def
(fn def [...]
+ {:fnl/docstring "Name binding macro similar to `local` but acts in terms of current
+namespace set with the `ns` macro, unless `:private` was passed before
+the binding name."
+ :fnl/arglist [([name initializer]) ([meta name initializer])]}
(match [...]
(where (or [:private name val]
[{:private true} name val]))
@@ -98,13 +121,6 @@ SOFTWARE.")
(fn vfirst [x] x)
(fn vrest [_ ...] ...)
-(fn has? [arglist sym]
- ;; searches for the given symbol in a table.
- (var has false)
- (each [_ arg (ipairs arglist) :until has]
- (set has (= sym arg)))
- has)
-
(fn length* [arglist]
;; Gets "length" of variadic arglist, stopping at first & plus 1 arg.
;; Additionally checks whether there are more than one arg after &.
diff --git a/init.fnl b/init.fnl
index 1e87284..ccb705f 100644
--- a/init.fnl
+++ b/init.fnl
@@ -31,8 +31,8 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM‚ DAMAGES OR OTHER
LIABILITY‚ WHETHER IN AN ACTION OF CONTRACT‚ TORT OR OTHERWISE‚ ARISING FROM‚
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE."
- (:require [lazy-seq :as lazy]
- [itable :as itable]))
+ (:require [lazy-seq :as lazy :relative]
+ [itable :as itable :relative]))
;;; Utility functions