Login
7 branches 0 tags
Ben (X13/Arch) Removed :bytecode-op type 23a2d9d 2 years ago 993 Commits
nujel / stdlib / meta.nuj
;;; Nujel - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
;;; This project uses the MIT license, a copy should be included under /LICENSE
;;;
;;; Introspection and procedures returning info about the runtime

(defn describe/closure (c i)
      :cat :compiler
      :internal
      (when c
            (if (= c root-closure)
                (cat (cat (int (or i 0)) "# <root environment>")
                     "\r\n")
                (do (def data (closure/data c))
                    (def l (length data))
                  (cat (int (or i 0)) "# "
                       (string/write c)
                       " - "
                       (resolve '*module* c)
                       " - "
                       (if (< l 16)
                           (string/write data)
                           "-+- Very big tree structure -+-")
                       "\r\n"
                       (describe/closure (closure/caller c) (+ (int (or i 0)) 1)))))))

(defn stacktrace ()
      (print (describe/closure (closure/caller (current-lambda)))))

(def print/error (let*
                   (defn print/error/wrap (i v)
                         (case i
                               (0 v)
                               (2 (string/write v))
                               (3 (describe/closure v))
                               (otherwise (string v))))

                   (defn print/error/iter (error i)
                         (if error
                             (cons (print/error/wrap i (car error))
                                   (print/error/iter (cdr error) (+ 1 i)))
                             (cons "" #nil)))

                   (defn print/error (error)
                         "Display ERROR in a nice, human readable way"
                         (print (join (print/error/iter error 0) "\r\n")))))

(defn closure/documentation (o)
      (meta o :documentation))

(defn closure/cat (o)
      (or (meta o :cat) :unsorted))

(defn closure/name (o)
      (if (procedure? o)
          (or (meta o :name)
              (closure/name (closure/parent o)))
          'unknown))

(def describe (let*
                (defn describe/thing (o)
                      "Describe a specific value O"
                      (def documentation (closure/documentation o))
                      (def name (closure/name o))
                      (pfmt "({}" (closure/name o))
                      (def arguments (closure/arguments o))
                      (if (pair? arguments)
                          (doseq (arg arguments (println ")"))
                                 (when arg (pfmt " {arg}")))
                          (pfmt " . {arguments})"))
                      (pfmtln "\n{documentation}")
                      #nil)

                (defn describe/string (a)
                      "Descibe whatever value string A resolves to"
                      (describe/thing (resolve (string->symbol a))))

                (defn describe (fun) "Describe FUN, if there is documentation available"
                      (if (string? fun)
                          (describe/string fun)
                          (describe/thing fun)))))

(def root-closure (current-closure))

(defmacro deftest l #nil) ; Tests should be skipped when compiling

(defmacro comment body
          "Does nothing, mainly used for commenting out
          parts of an expression, but having the sub expressions
          be available so you can use them easily via nujel-mode."
          :cat :documentation
          (deftest #nil (let (x #nil) (comment (set! x #t)) x))

          #nil)