;; [[file:shen-elisp.org::*License][License:1]]
;; -*- lexical-binding: t -*-
;; Copyright (c) 2015-2026 Aditya Siram. All Rights Reserved.
;; BSD 3-Clause License: http://opensource.org/licenses/BSD-3-Clause
;; License:1 ends here

;; [[file:shen-elisp.org::*Dependencies][Dependencies:1]]
(require 'cl-macs)
;; Dependencies:1 ends here

;; [[file:shen-elisp.org::*Implementation Constants][Implementation Constants:1]]
(defconst shen/prefix "shen/")
;; Implementation Constants:1 ends here

;; [[file:shen-elisp.org::*Symbols][Symbols:1]]
(defsubst shen/symbol-p (X)
  (not (or (consp X) (bufferp X) (vectorp X) (numberp X) (stringp X))))
;; Symbols:1 ends here

;; [[file:shen-elisp.org::*Symbols][Symbols:2]]
(defsubst shen/intern (String)
  (intern String))
;; Symbols:2 ends here

;; [[file:shen-elisp.org::*Symbols][Symbols:3]]
(defsubst shen/symbol->string (X)
  (symbol-name X))
;; Symbols:3 ends here

;; [[file:shen-elisp.org::*Prefixing Utilities][Prefixing Utilities:1]]
(defun shen/internal/prefix-symbol (X)
  (if (shen/symbol-p X)
      (intern (concat shen/prefix (symbol-name X)))
    X))
;; Prefixing Utilities:1 ends here

;; [[file:shen-elisp.org::*Prefixing Utilities][Prefixing Utilities:2]]
(defun shen/internal/symbol-prefixed-p (X)
  (and (shen/symbol-p X) (string-prefix-p shen/prefix (symbol-name X))))
;; Prefixing Utilities:2 ends here

;; [[file:shen-elisp.org::*Prefixing Utilities][Prefixing Utilities:3]]
(defun shen/internal/unprefix-symbol (X)
  (if (shen/internal/symbol-prefixed-p X)
      (intern (substring (symbol-name X) (length shen/prefix)))
    X))
;; Prefixing Utilities:3 ends here

;; [[file:shen-elisp.org::*Assignments][Assignments:1]]
(defun shen/set (X Y)
  (set (intern (concat shen/prefix (symbol-name X)))
       (let ((prefixed))
         (or  (and (symbolp Y)
                   (not (shen/internal/symbol-prefixed-p Y))
                   (progn
                     (setq prefixed (shen/internal/prefix-symbol Y))
                     (or (boundp prefixed)
                         (fboundp prefixed)))
                   prefixed)
              Y))))

(defun shen/value (X)
  (condition-case ex
      (symbol-value (intern (concat shen/prefix (symbol-name X))))
    ('error (error (format "%s has not been assigned" X)))))
;; Assignments:1 ends here

;; [[file:shen-elisp.org::*KLambda Constants][KLambda Constants:1]]
(shen/set '*home-directory* "")
(shen/set '*stoutput* standard-output)
(shen/set '*stinput* [()])
(shen/set '*language* "Elisp")
(shen/set '*implementation* system-configuration)
(shen/set '*porters* "Aditya Siram")
(shen/set '*release* emacs-version)
(shen/set '*port* 1.7)
(shen/set '*os* (symbol-name system-type))
;; KLambda Constants:1 ends here

;; [[file:shen-elisp.org::*Boolean Operations][Boolean Operations:1]]
(defsubst shen/internal/shen->predicate (X)
  (eq X 'true))
(defsubst shen/internal/predicate->shen (X)
  (if X (quote true) (quote false)))
;; Boolean Operations:1 ends here

;; [[file:shen-elisp.org::*Boolean Operations][Boolean Operations:2]]
(defmacro shen/if (X Y Z)
  `(if (eq ,X 'true) ,Y ,Z))
(defmacro shen/and (X Y) `(shen/internal/predicate->shen (and (eq ,X 'true) (eq ,Y 'true))))
(defmacro shen/or (X Y) `(shen/internal/predicate->shen (or (eq ,X 'true) (eq ,Y 'true))))
;; Boolean Operations:2 ends here

;; [[file:shen-elisp.org::*Boolean Operations][Boolean Operations:3]]
(defmacro shen/cond (&rest CASES)
  (let* ((predicates-quoted-cases
          (mapcar (lambda (predicate-result-pair)
                    (list (if (shen/symbol-p (nth 0 predicate-result-pair))
                              (list 'quote (nth 0 predicate-result-pair))
                            (list 'shen/internal/shen->predicate (nth 0 predicate-result-pair)))
                          (nth 1 predicate-result-pair)))
                  CASES))
         (fallthrough-added (append predicates-quoted-cases (list '(t (error "One of the cond predicates must be true."))))))
    `(cond ,@fallthrough-added)))
;; Boolean Operations:3 ends here

;; [[file:shen-elisp.org::*Lambdas][Lambdas:3]]
(defmacro shen/lambda (X Y)
  (if (eq X nil)
      `(lambda () ,Y)
    `(lambda (,X) ,Y)))
;; Lambdas:3 ends here

;; [[file:shen-elisp.org::*Lets][Lets:2]]
(defmacro shen/let (X Y Z)
  `(let ((,X ,Y)) ,Z))
;; Lets:2 ends here

;; [[file:shen-elisp.org::*Defuns][Defuns:1]]
(defmacro shen/defun (F Args Body) `(defun ,F ,Args ,Body))
;; Defuns:1 ends here

;; [[file:shen-elisp.org::*Equality][Equality:1]]
(defun shen/internal/= (X Y)
  (cond ((and (stringp X) (stringp Y)) (string-equal X Y))  ;;; (ref:strings-and-numbers)
        ((and (numberp X) (numberp Y)) (= X Y))
        ((and (symbolp X) (symbolp Y)) (eq X Y))
        (t
         (or (equal X Y) ;;; (ref:obvious-equality-test)
             (cond
              ((and (consp X) (consp Y))
               (let ((LengthX (safe-length X))
                     (LengthY (safe-length Y)))
                 (and
                  (= LengthX LengthY)
                  (let ((SoFar 't)
                        (InnerListsX (list X))
                        (InnerListsY (list Y))
                        (FirstTime 't)
                        (CurrentIndex 0))
                    (while (and SoFar InnerListsX InnerListsY)
                      (let* ((CurrentListX (pop InnerListsX))
                             (CurrentListY (pop InnerListsY))
                             (Iterate
                              (lambda ()
                                (let ((I 0))
                                  (while (and SoFar (< I LengthX))
                                    (let* ((CurrentX (nth I CurrentListX))
                                           (CurrentY (nth I CurrentListY)))
                                      (cond
                                       ((not (equal (type-of CurrentX) (type-of CurrentY))) ;;; (ref:elements are of the same type)
                                        (setq SoFar nil))
                                       ((and (consp CurrentX) (consp CurrentY)) ;;; (ref:store the inner list)
                                        (progn
                                          (push CurrentX InnerListsX)
                                          (push CurrentY InnerListsY)))
                                       (t (setq SoFar (shen/internal/= CurrentX CurrentY)))) ;;; (ref:compare the elements)
                                      (setq I (1+ I))))))))
                        (if (not FirstTime)
                            (progn
                              (setq FirstTime nil)
                              (setq LengthX (safe-length CurrentListX))
                              (setq LengthY (safe-length CurrentListY))
                              (setq SoFar (= LengthX LengthY))
                              (funcall Iterate))
                          (funcall Iterate))))
                    SoFar))))
              ((and (hash-table-p X) (hash-table-p Y)) ;;; (ref:compare hash tables)
               (and (= (hash-table-count X) (hash-table-count Y))
                    (string=  ;;; (ref:hash table comparison)
                     (prin1-to-string X)
                     (prin1-to-string Y))))
              (t nil))))))

(defsubst shen/= (X Y)
  (shen/internal/predicate->shen (shen/internal/= X Y)))
;; Equality:1 ends here

;; [[file:shen-elisp.org::*Other Generic Functions][Other Generic Functions:1]]
(defmacro shen/freeze (X)
  `(function (lambda nil ,X)))
(defsubst shen/type (X MyType) (declare (ignore MyType)) X)
;; Other Generic Functions:1 ends here

;; [[file:shen-elisp.org::*Lists][Lists:1]]
(defsubst shen/cons (A Rest)
  (cons A Rest))
;; Lists:1 ends here

;; [[file:shen-elisp.org::*Lists][Lists:2]]
(defsubst shen/hd (List)    (car List))
(defsubst shen/tl (List)    (cdr List))
(defsubst shen/cons? (List) (shen/internal/predicate->shen (consp List)))
;; Lists:2 ends here

;; [[file:shen-elisp.org::*Strings][Strings:1]]
(defun shen/str (X)
  (cond ((null X) (error "null is not an atom in Shen; str cannot convert it to a string.~%"))
        ((or (symbolp X) (functionp X)) (symbol-name X))
        ((numberp X) (number-to-string X))
        ((stringp X) X)
        ((and (bufferp X) (buffer-file-name X)) (buffer-name X))
        ((eq X standard-input) "standard-input")
        ((eq X standard-output) "standard-output")
        (t
         (error (format "%s is not an atom, stream or closure; str cannot convert it to a string." X)))))
;; Strings:1 ends here

;; [[file:shen-elisp.org::*Strings][Strings:2]]
(defsubst shen/pos (S N) (string (aref S N)))
;; Strings:2 ends here

;; [[file:shen-elisp.org::*Strings][Strings:3]]
(defsubst shen/tlstr (X) (substring X 1))
;; Strings:3 ends here

;; [[file:shen-elisp.org::*Strings][Strings:4]]
(defsubst shen/string? (S) (shen/internal/predicate->shen (stringp S)))
(defsubst shen/cn (Str1 Str2) (concat Str1 Str2))
(defsubst shen/n->string (N) (string N))
(defsubst shen/string->n (S) (string-to-char S))
;; Strings:4 ends here

;; [[file:shen-elisp.org::*Error Handling][Error Handling:1]]
(define-error 'shen/error "Shen error" 'error)
(defsubst shen/simple-error (E)
  (signal 'shen/error
          (if (stringp E)
              (list E)
            E)))
(defmacro shen/trap-error (X F)
  `(condition-case ex ,X ('error (funcall ,F ex))))
(defsubst shen/error-to-string (E) (format "%s" E))
;; Error Handling:1 ends here

;; [[file:shen-elisp.org::*Vectors][Vectors:1]]
(defsubst shen/absvector (N) (make-hash-table :size N :rehash-size 3.0 :test 'shen/internal/hash-table-test))
(defsubst shen/address-> (Vector N Value) (progn (puthash N Value Vector) Vector))
(defsubst shen/<-address (Vector N) (gethash N Vector))
(defsubst shen/absvector? (X) (shen/internal/predicate->shen (hash-table-p X)))
;; Vectors:1 ends here

;; [[file:shen-elisp.org::*Vectors][Vectors:2]]
(define-hash-table-test
 'shen/internal/hash-table-test
 (lambda (X Y)
   (shen/internal/= X Y))
 (lambda (X)
   (cond
    ((numberp X) X)
    ((consp X) (sxhash (prin1-to-string X)))
    ((hash-table-p X)
     (sxhash (prin1-to-string X)))
    (t (sxhash X)))))
;; Vectors:2 ends here

;; [[file:shen-elisp.org::*Arithmetic Operations][Arithmetic Operations:1]]
(defconst shen/multiplication-limit (floor (sqrt most-positive-fixnum)))
(defconst shen/addition-limit (floor (/ most-positive-fixnum 2)))
;; Arithmetic Operations:1 ends here

;; [[file:shen-elisp.org::*Arithmetic Operations][Arithmetic Operations:2]]
(defun shen/number-op (X Y max op)
  (cond
   ((and (integerp X) (integerp Y))
    (if (and (< X max)
             (> X (- max))
             (< Y max)
             (> Y (- max)))
        (apply op (list X Y))
      (apply op (list (float X) (float Y)))))
   ((and (floatp X) (numberp Y)) (apply op (list X (float Y))))
   ((and (numberp X) (floatp Y)) (apply op (list (float X) Y)))
   (t (error (format "Trying to %s. Both %s and %s must be numbers" op X Y)))))
;; Arithmetic Operations:2 ends here

;; [[file:shen-elisp.org::*Arithmetic Operations][Arithmetic Operations:3]]
(defsubst shen/* (X Y) (shen/number-op X Y shen/multiplication-limit #'*))
(defsubst shen/+ (X Y) (shen/number-op X Y shen/addition-limit #'+))
(defsubst shen/- (X Y) (shen/number-op X Y shen/addition-limit #'-))
;; Arithmetic Operations:3 ends here

;; [[file:shen-elisp.org::*Arithmetic Operations][Arithmetic Operations:4]]
(defsubst shen// (X Y)
  (cond
   ((or (not (numberp X)) (not (numberp Y)))
    (error (format "Both %s and %s must be numbers." X Y)))
   ((and (integerp X) (integerp Y))
    (let* ((Div (/ (float X) (float Y)))
           (Truncated (floor Div)))
      (if (= Truncated Div)
          Truncated
        Div)))
   (t (/ (float X) (float Y)))))
;; Arithmetic Operations:4 ends here

;; [[file:shen-elisp.org::*Arithmetic Operations][Arithmetic Operations:5]]
(defsubst shen/> (X Y)     (shen/internal/predicate->shen (> X Y)))
(defsubst shen/< (X Y)     (shen/internal/predicate->shen (< X Y)))
(defsubst shen/>= (X Y)    (shen/internal/predicate->shen (>= X Y)))
(defsubst shen/<= (X Y)    (shen/internal/predicate->shen (<= X Y)))
(defsubst shen/number? (N) (shen/internal/predicate->shen (numberp N)))
;; Arithmetic Operations:5 ends here

;; [[file:shen-elisp.org::*Time][Time:1]]
(defconst shen/2^16 65536)
(defun shen/get-time (Time)
  (cl-flet
      ((timespec-to-number (spec)
         (let* ((high (nth 0 spec))
                (low (nth 1 spec)))
           (+ (* high shen/2^16) low))))
    (cond ((eq Time 'run) (timespec-to-number (get-internal-run-time)))
          ((eq Time 'real)(timespec-to-number (current-time)))
          ((eq Time 'unix)(timespec-to-number (current-time)))
          (t (error (format "get-time does not understand parameter %s." Time))))))
;; Time:1 ends here

;; [[file:shen-elisp.org::*Streams and I/O][Streams and I/O:1]]
(defsubst shen/streamp (X) (and (bufferp X) (buffer-file-name X)))
;; Streams and I/O:1 ends here

;; [[file:shen-elisp.org::*Streams and I/O][Streams and I/O:2]]
(defun shen/open (Path Direction)
  (let* ((Path (concat (file-name-as-directory (shen/value '*home-directory*))
                       (file-relative-name Path)))
         (Buffer (find-buffer-visiting Path)))
    (if Buffer
        (progn
          (with-current-buffer Buffer
            (goto-char (point-min)))
          Buffer)
      (cond
       ((equal Direction 'in)
        (if (not (file-exists-p Path))
            (error (format "Path does not exist: %s" Path))
          (progn
            (setq Buffer (find-file-noselect Path))
            (with-current-buffer
                Buffer
              (progn
                (setq buffer-read-only 't)
                (setq-local shen/shen-buffer 't)
                (goto-char (point-min))))
            Buffer)))
       ((equal Direction 'out)
        (progn
          (setq Buffer (find-buffer-visiting Path))
          (if (bufferp Buffer)
              (if (and (buffer-local-value 'buffer-read-only Buffer) (buffer-local-value 'shen/shen-buffer Buffer))
                  (error (format  "A stream to %s already open read-only. Call (close \"%s\") followed by (open \"%s\" 'out). " Path Path Path))
                Buffer)
            (progn
              (setq Buffer (find-file-noselect Path))
              (with-current-buffer Buffer
                (progn
                  (goto-char (point-max))
                  (setq-local shen/shen-buffer 't)))))))))))
;; Streams and I/O:2 ends here

;; [[file:shen-elisp.org::*Streams and I/O][Streams and I/O:3]]
(defun shen/close (Stream)
  (if (not Stream)
      (error "Stream is nil.")
    (if (and (local-variable-p 'shen/shen-buffer Stream)
             (buffer-local-value 'shen/shen-buffer Stream))
        (cond ((buffer-local-value 'buffer-read-only Stream) (kill-buffer Stream))
              (t (with-current-buffer
                     Stream
                   (progn
                     (write-file (buffer-file-name Stream))
                     (kill-buffer Stream)
                     '())))))))

(defun shen/write-byte (Byte &optional S)
  (if S
      (cond
       ((bufferp S)
        (if (not (local-variable-p 'buffer-read-only S))
            (error (format "Buffer %s is read-only." S))
          (if (buffer-local-value 'shen/shen-buffer S)
              (write-char Byte S)
            (error (format "Buffer %s was not opened by Shen." S)))))
       ((functionp S) ;; (ref:write-byte-function)
        (funcall S Byte))
       (t (write-char (shen/stoutput) Byte)))
    (funcall (shen/stoutput) Byte)))

(defun shen/read-byte (&optional S)
  (cond
   ((and (bufferp S) (buffer-file-name S))
    (with-current-buffer S
      (let ((current-byte))
        (if (eq (point) (point-max))
            -1
          (progn
            (setq current-byte (get-byte))
            (forward-char)
            current-byte)))))
   ((vectorp S) (if (not (aref S 0))
                    -1
                  (pop (aref S 0))))
   (t (error (format "Unrecognized stream format %s" S)))))
;; Streams and I/O:3 ends here

;; [[file:shen-elisp.org::*Lookup][Lookup:1]]
(defun shen/internal/lookup-with-default (KEY ALIST DEFAULT)
  (car (or (assoc-default KEY ALIST) (list DEFAULT))))
;; Lookup:1 ends here

;; [[file:shen-elisp.org::AST Getter][AST Getter]]
(defun shen/internal/get-element-at (path ast)
  (let ((res ast))
    (dolist (current-index (reverse path) res)
      (if (listp current-index)
          (setq res (nthcdr (car current-index) res))
        (setq res (nth current-index res))))))
;; AST Getter ends here

;; [[file:shen-elisp.org::AST Setter][AST Setter]]
(defun shen/internal/nset-element-at (path ast new-element)
  (if (not path)
      (setf ast new-element)
    (let ((place-fn)
          (path (reverse path))
          (make-place-fn
           (lambda (path target)
             (if (listp path)
                 `(nthcdr ,path ,target)
               `(nth ,path ,target)))))
      (progn
        (dotimes (current-index (length path) nil)
          (setq place-fn
                (funcall make-place-fn
                         (nth current-index path)
                         (if (= current-index 0)
                             'ast
                           place-fn))))
        (if (or (consp new-element) (shen/symbol-p new-element))
            (eval `(setf ,place-fn (quote ,new-element)) 't)
          (eval `(setf ,place-fn ,new-element)) 't)
        ast))))
;; AST Setter ends here

;; [[file:shen-elisp.org::*Find All][Find All:1]]
(defun shen/internal/find-all (X ast)
  (if (not (consp ast))
      'shen/not-found
    (let ((lists-left-to-search `((() ,ast)))
          (found 'shen/not-found))
      (while lists-left-to-search
        (let* ((search-candidate (car lists-left-to-search))
               (search-candidate-path (nth 0 search-candidate))
               (current-list (nth 1 search-candidate)))
          (progn
            (setq lists-left-to-search (cdr lists-left-to-search))
            (dotimes (current-index (length current-list) nil)
              (let ((current-element (nth current-index current-list))
                    (current-path (cons current-index search-candidate-path)))
                (if (equal X current-element)
                    (if (consp found)
                        (push current-path found)
                      (setq found (list current-path)))
                  (if (consp current-element)
                      (push `(,current-path ,current-element)
                            lists-left-to-search))))))))
      found)))
;; Find All:1 ends here

;; [[file:shen-elisp.org::*Find Containing List][Find Containing List:1]]
(defun shen/internal/list-containing-first-occurrence-of (list-pred ast)
  (if (not (consp ast))
      'shen/not-found
    (let ((lists-left-to-search `((() ,ast)))
          (found 'shen/not-found))
      (progn
        (while (and lists-left-to-search (eq found 'shen/not-found))
          (let* ((search-candidate (car lists-left-to-search))
                 (search-candidate-path (nth 0 search-candidate))
                 (current-list (nth 1 search-candidate))
                 (current-list-length (length current-list)))
            (if (funcall list-pred current-list)
                (setq found search-candidate-path)
              (progn
                (setq lists-left-to-search
                      (append
                       (let ((reversed-lists-in-current-list))
                         (dotimes (current-index current-list-length (reverse reversed-lists-in-current-list))
                           (if (consp (nth current-index current-list))
                               (setq reversed-lists-in-current-list
                                     (cons (list (cons current-index search-candidate-path)
                                                 (nth current-index current-list))
                                           reversed-lists-in-current-list)))))
                       (cdr lists-left-to-search)))))))
        found))))
;; Find Containing List:1 ends here

;; [[file:shen-elisp.org::*Path Utilities][Path Utilities:1]]
(defun shen/internal/get-path-relative-to (parent-path path)
  (and (shen/internal/starts-with-path parent-path path)
       (shen/internal/path-slice path 0 (- (length path) (length parent-path)))))

(defun shen/internal/starts-with-path (parent-path path)
  (and (<= (length parent-path) (length path))
       (equal parent-path
              (shen/internal/path-slice path
                                        (- (length path)
                                           (length parent-path))))))

(defun shen/internal/get-path-parent (path) (cdr path))

(defun shen/internal/path-slice (path start &optional end)
  (let ((start-to-end (nthcdr start path))
        (res))
    (if end
        (dotimes (i (- (if (< end (length path))
                           end
                         (length path))
                       start)
                    (nreverse res))
          (push (nth i start-to-end) res))
      start-to-end)))
;; Path Utilities:1 ends here

;; [[file:shen-elisp.org::*AST Modification][AST Modification:1]]
(defun shen/internal/modify-ast (ast paths tx-fn)
  (let ((deepest-first (sort paths (lambda (A B) (> (length A) (length B)))))
        (current-ast ast))
    (dolist (path deepest-first current-ast)
      (setq current-ast
            (shen/internal/nset-element-at path ast (funcall tx-fn path ast))))))
;; AST Modification:1 ends here

;; [[file:shen-elisp.org::*Detect Dotted Pair][Detect Dotted Pair:1]]
(defun shen/internal/dotted-pair? (X)
  (and (consp X) (not (consp (cdr X)))))
;; Detect Dotted Pair:1 ends here

;; [[file:shen-elisp.org::*List Filtering][List Filtering:1]]
(defun shen/internal/partition (pred Xs)
  (let ((a)
        (b))
    (dotimes (i (length Xs) (list a b))
      (push (nth i Xs)
            (if (funcall pred (nth i Xs)) a b)))))
;; List Filtering:1 ends here

;; [[file:shen-elisp.org::*List Filtering][List Filtering:2]]
(defun shen/internal/filter (pred Xs &optional include-index)
  (let ((accum))
    (dotimes (i (length Xs) accum)
      (if (funcall pred (nth i Xs))
          (push (if include-index
                    (list (nth i Xs) i)
                  (nth i Xs))
                accum)))))
;; List Filtering:2 ends here

;; [[file:shen-elisp.org::*List Filtering][List Filtering:3]]
(defun shen/internal/index-of (pred Xs)
  (let ((found)
        (index 0))
    (while (and (not found) (< index (length Xs)))
      (progn
        (if (funcall pred (nth index Xs))
            (setq found index))
        (setq index (+ index 1))))
    found))
;; List Filtering:3 ends here

;; [[file:shen-elisp.org::*List Filtering][List Filtering:4]]
(defun shen/internal/delete-first-eq (needle Xs)
  (let ((index (shen/internal/index-of (lambda (X) (eq X needle)) Xs)))
    (if index
        (let ((current-index 0)
              (copy))
          (while (< current-index (length Xs))
            (progn
              (if (not (= current-index index))
                  (push (nth current-index Xs) copy))
              (setq current-index (1+ current-index))))
          (nreverse copy))
      Xs)))
;; List Filtering:4 ends here

;; [[file:shen-elisp.org::*Walking The AST][Walking The AST:1]]
(defun shen/internal/get-function-symbol-and-funcall-paths (ast)
  (let ((namespace-only)        ;; (ref:namespace-only)
        (quote-only)            ;; (ref:quote-only)
        (possibly-apply-function)) ;; (ref:possibly-apply-function)
    (if (not (consp ast))
        (if (shen/symbol-p ast)
            (list nil '(nil) '(nil) nil nil)
          (list nil nil nil nil nil))
      (let ((current-path)                     ;; (ref:current-path)
            (current-list ast)                 ;; (ref:current-list)
            (current-list-length (length ast)) ;; (ref:current-list-length)
            (current-index 0)                  ;; (ref:current-index)
            (locally-scoped-symbols)           ;; (ref:locally-scoped-symbols)
            (inner-lists)                      ;; (ref:inner-lists)
            (cond-predicate-action-p)
            (inner-lists-in-cond-form))        ;; (ref:inner-lists-in-cond-form)
        (while (or (< current-index current-list-length) ;; (ref:continue iterating)
                   inner-lists)
          (cond
           ((and (= current-index current-list-length) inner-lists) ;; (ref:sublists left)
            (progn
              (setq locally-scoped-symbols (nth 0 (car inner-lists)))
              (setq current-path (nth 1 (car inner-lists)))
              (setq cond-predicate-action-p (nth 2 (car inner-lists)))
              (setq inner-lists-in-cond-form nil)
              (setq inner-lists (cdr inner-lists))
              (setq current-list (shen/internal/get-element-at current-path ast))
              (setq current-index 0)
              (setq current-list-length (length current-list))))
           ((and (< current-index current-list-length)              ;; (ref:not a list)
                 (not (consp (nth current-index current-list))))
            (let ((current-token (nth current-index current-list)))
              (if (= 0 current-index)
                  (if (and (not (eq current-token 'nil))
                           (shen/symbol-p current-token))
                      (progn
                        (if (and (not (memq current-token locally-scoped-symbols))
                                 (not (eq current-token 'defun)))
                            (push (cons 0 current-path)
                                  namespace-only))
                        (cond
                         ((or (eq current-token 'lambda)
                              (eq current-token 'shen/lambda)) ;; (ref:lambda form)
                          (progn
                            (push (nth 1 current-list) locally-scoped-symbols)
                            (setq current-index 2)))
                         ((eq current-token 'defun) ;; (ref:defun form)
                          (progn
                            (push (cons 1 current-path) namespace-only)
                            (setq locally-scoped-symbols
                                  (append (nth 2 current-list) locally-scoped-symbols))
                            (setq current-index 3)))
                         ((or (eq current-token 'let)
                              (eq current-token 'shen/let))  ;; (ref:let form)
                          (progn
                            (push (nth 1 current-list) locally-scoped-symbols)
                            (setq current-index 2)))
                         ((or (eq current-token 'cond)
                              (eq current-token 'shen/cond)) ;; (ref:cond form)
                          (progn
                            (setq inner-lists-in-cond-form 't)
                            (setq current-index 1)))
                         (t
                          (progn
                            (if (not cond-predicate-action-p)
                                (push (list (cons 0 current-path)
                                            (memq current-token locally-scoped-symbols))
                                      possibly-apply-function))
                            (setq current-index 1)))))
                    (setq current-index (1+ current-index)))
                (if (and (not (eq current-token 'nil))
                         (shen/symbol-p current-token))
                    (progn
                      (if (not (memq current-token locally-scoped-symbols))
                          (push (cons current-index current-path)
                                quote-only))
                      (setq current-index (1+ current-index)))
                  (setq current-index (1+ current-index))))))
           ((and (< current-index current-list-length)             ;; (ref:a sublist)
                 (consp (nth current-index current-list)))
            (progn
              (if (and (= 0 current-index) (not cond-predicate-action-p))
                  (push (list (cons current-index current-path)
                              nil)
                        possibly-apply-function))
              (push (list locally-scoped-symbols
                          (cons current-index current-path)
                          inner-lists-in-cond-form)
                    inner-lists)
              (setq current-index (+ current-index 1))))
           (t nil)))
        (list namespace-only quote-only possibly-apply-function))))) ;; (ref:returns)
;; Walking The AST:1 ends here

;; [[file:shen-elisp.org::Primitive Macros][Primitive Macros]]
(setq shen/*primitive-macros*
      '(shen/if
        shen/and
        shen/or
        shen/cond
        shen/lambda
        shen/let
        defun
        shen/freeze
        shen/trap-error))
;; Primitive Macros ends here

;; [[file:shen-elisp.org::*Function Application][Function Application:2]]
(defun shen/internal/apply-function (f args locally-scoped)
  (cond
   (locally-scoped       ;;(ref:higher-order function)
    `(shen/internal/apply-higher-order-function ,f (list ,@args)))
   ((consp f)            ;;(ref:a list)
    `(shen/internal/apply-function-expression ,f (list ,@args)))
   (t
    (if (fboundp 'shen/arity)
        (let ((arity (shen/internal/check-partial-application f (length args)))) ;; (ref:known arity)
          (if (= arity -1)
              `(,f ,@args)
            `(shen/internal/apply-partially (function ,f) (list ,@args))))
      `(,f ,@args)))))

(defun shen/internal/apply-higher-order-function (f args)
  (condition-case apply-ex (apply f args)
    ('void-function
     (shen/internal/apply-higher-order-function (shen/internal/prefix-symbol f) args))
    ('wrong-number-of-arguments
     (condition-case ex
         (let ((arity (shen/internal/check-partial-application f (length args))))
           (if (= arity -1)
               (signal (car apply-ex) (cdr apply-ex))
             (apply (eval (shen/internal/make-lambda-expression f arity (length args)) 't) args)))
       ('wrong-number-of-arguments
        (shen/internal/apply-incrementally f args))))))

(defun shen/internal/apply-function-expression (exp args)
  (condition-case ex (apply exp args)
    ('wrong-number-of-arguments (shen/internal/apply-incrementally exp args))))

(defun shen/internal/apply-partially (f args)
  (let ((arity (shen/internal/check-partial-application f (length args))))
    (if (= arity -1)
        (apply f args)
      (apply (eval (shen/internal/make-lambda-expression f arity (length args)) 't) args))))

(defun shen/internal/make-lambda-expression (f arity num-args) ;; (ref:curried lambda)
  (let* ((all-args (let ((single-apply-args)
                         (blast-apply-args))
                     (dotimes (i arity (list (reverse blast-apply-args)
                                             (reverse single-apply-args)))
                       (push (intern (concat "A" (number-to-string i)))
                             (if (and num-args (< i num-args))
                                 blast-apply-args
                               single-apply-args)))))
         (blast-apply-args (nth 0 all-args))
         (single-apply-args (nth 1 all-args))
         (expression `(apply (function ,f) (list ,@(append blast-apply-args single-apply-args)))))
    (dolist (arg (reverse single-apply-args) expression)
      (setq expression `(shen/lambda ,arg ,expression)))
    (if blast-apply-args
        `(lambda ,blast-apply-args ,expression)
      expression)))

(defun shen/internal/apply-incrementally (f args) ;; (ref:incremental application)
  (let ((result f)
        (current-args args))
    (while current-args
      (setq result (funcall result (car current-args)))
      (setq current-args (cdr current-args)))
    result))

(defun shen/internal/check-partial-application (f num-args)
  (let ((arity (condition-case ex (shen/arity (shen/internal/unprefix-symbol f)) ('error -1))))
    (cond
     ((eq -1 arity) -1)
     ((= arity num-args) -1)
     ((> num-args arity) -1)
     (t arity))))
;; Function Application:2 ends here

;; [[file:shen-elisp.org::*Detecting Recursive Calls][Detecting Recursive Calls:1]]
(defun shen/internal/find-recursive-call-paths (function-name args ast)
  (if (not (consp ast))
      'shen/not-found
    (let ((lists-left-to-search `((() ,ast))) ;; (ref:lists-left-to-search)
          (found 'shen/not-found))  ;; (ref:tail-calls-found)
      (while lists-left-to-search
        (let* ((search-candidate (car lists-left-to-search))
               (search-candidate-path (nth 0 search-candidate))
               (current-list (nth 1 search-candidate))
               (current-list-length (length current-list))
               (current-head (car current-list))
               (push-if-list     ;; (ref:push-if-list)
                (lambda (indexes)
                  (mapc
                   (lambda (index)
                     (if (consp (nth index current-list))
                         (setq lists-left-to-search
                               (append lists-left-to-search
                                       (list
                                        (list (cons index search-candidate-path)
                                              (nth index current-list)))))))
                   indexes))))
          (progn
            (setq lists-left-to-search (cdr lists-left-to-search))
            (cond ((and (eq current-head function-name)
                        (= (length (cdr current-list)) (length args)))
                   (if (not (consp found))
                       (setq found (list search-candidate-path))
                     (push search-candidate-path found)))
                  ((eq current-head 'shen/cond)
                   (progn
                     (mapc
                      (lambda (action-index-pair)
                        (setq lists-left-to-search
                              (let ((path-to-action
                                     (append (list 1 (1+ (nth 1 action-index-pair)))
                                             search-candidate-path)))
                                (append lists-left-to-search
                                        (list
                                         (list path-to-action
                                               (nth 0 action-index-pair)))))))
                      (mapcar
                       (lambda (predicate-action-index)
                         (list (nth 1 (nth 0 predicate-action-index))
                               (nth 1 predicate-action-index)))
                       (shen/internal/filter  ;; (ref:cond-filter)
                        (lambda (predicate-action-pair)
                          (consp (nth 1 predicate-action-pair)))
                        (cdr current-list)
                        't)))))
                  ((eq current-head 'shen/if)
                   (if (= 4 current-list-length)
                       (funcall push-if-list '(2 3))
                     (funcall push-if-list '(2))))
                  ((eq current-head 'shen/trap-error)
                   (funcall push-if-list '(1 2)))
                  ((or (eq current-head 'shen/let)
                       (eq current-head 'defun))
                   (funcall push-if-list '(3)))
                  ((eq current-head 'shen/lambda)
                   (funcall push-if-list '(2)))
                  (t (funcall push-if-list (list (- current-list-length 1))))))))
      found)))
;; Detecting Recursive Calls:1 ends here

;; [[file:shen-elisp.org::*Detecting Function Application Context][Detecting Function Application Context:1]]
(defun shen/start-of-function-chain (tail-call-path ast)
  (let* ((from-the-top (reverse tail-call-path))
         (current-from-top-path)
         (path-left-to-tail-call (reverse tail-call-path))
         (start tail-call-path) ;; (ref:start-accumulator)
         (locally-scoped))
    (cl-flet ((append-and-advance
                (X &optional reset-start)
                (progn
                  (setq start
                        (if reset-start ;; (ref:reset-start)
                            tail-call-path
                          current-from-top-path))
                  (setq current-from-top-path
                        (append (reverse (shen/internal/path-slice path-left-to-tail-call 0 X))
                                current-from-top-path)
                        path-left-to-tail-call (shen/internal/path-slice path-left-to-tail-call X))

                  )))
      (while (not (equal current-from-top-path tail-call-path))
        (let* ((current-list (shen/internal/get-element-at current-from-top-path ast))
               (current-head (car current-list)))
          (cond
           ((or (not (shen/symbol-p current-head))
                (eq 'shen/if current-head))  ;; (ref:if-stop-recording)
            (append-and-advance 1 't))
           ((eq 'defun current-head)    ;; (ref:defun-stop-recording)
            (progn
              (setq locally-scoped (append (nth 2 current-list) locally-scoped))
              (append-and-advance 1 't)))
           ((or
             (eq 'shen/let current-head)
             (eq 'shen/lambda current-head)) ;;; (ref:let-or-lambda-stop-recording)
            (progn
              (setq locally-scoped (append (list (nth 1 current-list)) locally-scoped))
              (append-and-advance 1 't)))
           ((eq 'shen/cond current-head)     ;;; (ref:cond-stop-recording)
            (append-and-advance 2 't))
           ((eq 'shen/do current-head)       ;;; (ref:do-stop-recording)
            (append-and-advance 1 't))
           (t (append-and-advance 1)))))
      start)))
;; Detecting Function Application Context:1 ends here

;; [[file:shen-elisp.org::*Getting the Tail Calls][Getting the Tail Calls:1]]
(defun shen/internal/get-tail-call-paths (ast)
  (let* ((function-name (nth 1 ast))
         (args (nth 2 ast))
         (body (nth 3 ast))
         (recursive-call-paths (shen/internal/find-recursive-call-paths function-name args body)))
    (if (eq recursive-call-paths 'shen/not-found)
        'shen/not-found
      (let ((accum))
        (dolist (tail-call-path recursive-call-paths (if accum (reverse accum) 'shen/not-found))
          (let* ((context (shen/start-of-function-chain tail-call-path body)))
            (if (equal context tail-call-path)
                (push (append tail-call-path (list 3)) accum))))))))
;; Getting the Tail Calls:1 ends here

;; [[file:shen-elisp.org::*Generating A TCO'ed Function][Generating A TCO'ed Function:1]]
(defun shen/trampoline-body (ast)
  (let* ((args (nth 2 ast))
         (body (nth 3 ast))
         (tail-trampoline (make-symbol "tail-trampoline")))
    `(cl-flet ((,tail-trampoline ,args ,body))
       (let ((result (funcall (function ,tail-trampoline) ,@args)))
         (while (vectorp result)
           (setq result (apply (function ,tail-trampoline) (aref result 0))))
         result))))
;; Generating A TCO'ed Function:1 ends here

;; [[file:shen-elisp.org::*Modifying The AST][Modifying The AST:1]]
(defun shen/internal/parse-ast (ast)
  (if (not (consp ast))
      (if (shen/symbol-p ast) (list 'quote ast) ast)
    (let* ((function-and-symbol-paths (shen/internal/get-function-symbol-and-funcall-paths ast)) ;;; (ref:paths)
           (namespace-only (nth 0 function-and-symbol-paths))
           (quote-only (nth 1 function-and-symbol-paths))
           (possibly-apply-function (nth 2 function-and-symbol-paths))
           (current-ast ast))
      (progn
        (shen/internal/namespace-and-quote current-ast namespace-only quote-only) ;;; (ref:quote and namespace)
        (let ((apply-function (shen/internal/filter
                               (lambda (path-local)
                                 (let ((token (shen/internal/get-element-at (nth 0 path-local) ast)))
                                   (not (memq token shen/*primitive-macros*))))
                               possibly-apply-function)))
          (if (eq (car current-ast) 'defun) ;;; (ref:defun form)
              (let* ((tail-call-paths (shen/internal/get-tail-call-paths ast)))
                (if (not (eq tail-call-paths 'shen/not-found))
                    (let ((not-in-tail-call apply-function)
                          (in-tail-call))
                      (progn
                        (dolist (path tail-call-paths nil)
                          (let* ((tco-non-tco-pair ;;; (ref:inside the recursive call)
                                  (shen/internal/partition
                                   (lambda (apply-function-path-local)
                                     (shen/internal/starts-with-path path (nth 0 apply-function-path-local)))
                                   not-in-tail-call))
                                 (funcalled-tco
                                  (let* ((normalized-paths
                                          (shen/internal/filter
                                           (lambda (path-local) (not (equal (nth 0 path-local) '(0))))
                                           (mapcar
                                            (lambda (in-tco-path-local)
                                              (list
                                               (shen/internal/get-path-relative-to path (nth 0 in-tco-path-local))
                                               (nth 1 in-tco-path-local)))
                                            (nth 0 tco-non-tco-pair))))
                                         (tail-call (shen/internal/get-element-at path current-ast)))
                                    (list
                                     path
                                     `(vector (list ,@(cdr (shen/internal/add-funcalls tail-call normalized-paths)))))))) ;;; (ref:package up the arguments)
                            (progn
                              (setq not-in-tail-call (nth 1 tco-non-tco-pair))
                              (push funcalled-tco in-tail-call))))
                        (dolist (path-tail-call in-tail-call nil)  ;;; (ref:Sub in the recurs marker)
                          (shen/internal/modify-ast current-ast (list (nth 0 path-tail-call))
                                                    (lambda (path current-ast) (nth 1 path-tail-call))))
                        (setq current-ast (shen/internal/add-funcalls current-ast not-in-tail-call)) ;;; (ref:rest of the function applications)
                        (setq current-ast `(defun ,(nth 1 current-ast) ,(nth 2 current-ast) ,(shen/trampoline-body current-ast))))) ;;; (ref:write out the defun)
                  (setq current-ast (shen/internal/add-funcalls current-ast apply-function)))
                current-ast)
            (progn
              (setq current-ast (shen/internal/add-funcalls current-ast apply-function))
              current-ast)))))))
;; Modifying The AST:1 ends here

;; [[file:shen-elisp.org::*Modifying The AST][Modifying The AST:2]]
(defun shen/internal/namespace-and-quote (ast namespace-only-paths quote-only-paths)
  (progn
    (shen/internal/modify-ast ast namespace-only-paths
                              (lambda (path ast)
                                (let ((element (shen/internal/get-element-at path ast)))
                                  (if (not (shen/internal/symbol-prefixed-p element))
                                      (shen/internal/prefix-symbol (shen/internal/get-element-at path ast))
                                    element))))
    (shen/internal/modify-ast ast quote-only-paths
                              (lambda (path ast)
                                (list 'quote (shen/internal/get-element-at path ast))))
    ast))
;; Modifying The AST:2 ends here

;; [[file:shen-elisp.org::*Modifying The AST][Modifying The AST:3]]
(defun shen/internal/add-funcalls (ast apply-function)
  (let ((paths-only (mapcar (lambda (path-local) (nth 0 path-local)) apply-function)))
    (shen/internal/modify-ast ast (mapcar #'shen/internal/get-path-parent paths-only)
                              (lambda (path ast)
                                (let* ((current-funcalled-list (shen/internal/get-element-at path ast))
                                       (function-name (car current-funcalled-list))
                                       (function-arguments (cdr current-funcalled-list)))
                                  (shen/internal/apply-function
                                   function-name
                                   function-arguments
                                   (shen/internal/lookup-with-default (cons 0 path) apply-function nil)))))))
;; Modifying The AST:3 ends here

;; [[file:shen-elisp.org::*(Unused) Isolating and Filling][(Unused) Isolating and Filling:1]]
(defun shen/make-holed-context (tail-call-path function-chain-path ast)
  (let* ((function-chain (shen/internal/get-element-at function-chain-path ast))
         (tail-call (shen/internal/get-element-at tail-call-path ast))
         (tail-call-relative-path
          (shen/internal/path-slice tail-call-path 0
                                    (- (length tail-call-path)
                                       (length function-chain-path)))))
    (shen/internal/nset-element-at tail-call-relative-path function-chain 'shen/__hole__)))

(defun shen/used-in-context (context locally-scoped)
  (mapcar (lambda (symbol-index-pair)
            (nth 1 symbol-index-pair))
          (shen/internal/filter
           (lambda (v)
             (not (eq 'shen/not-found (shen/internal/find-all v context))))
           locally-scoped
           't)))

(defun shen/substitute-in-context (context locally-scoped-alist)
  (let ((current-context context))
    (dolist (locally-scoped-pair locally-scoped-alist current-context)
      (let* ((name (nth 0 locally-scoped-pair))
             (value (nth 1 locally-scoped-pair))
             (all-matching-paths (shen/internal/find-all name current-context)))
        (if (not (eq all-matching-paths 'shen/not-found))
            (dolist (path all-matching-paths nil)
              (shen/internal/nset-element-at path current-context value)))))))
;; (Unused) Isolating and Filling:1 ends here

;; [[file:shen-elisp.org::*Consolidate Call Chains][Consolidate Call Chains:1]]
(defun shen/internal/consolidate (ast matcher-fn collector-fn tx-fn)
  (let* ((current-ast ast)
         (location-containing-chain
          (shen/internal/list-containing-first-occurrence-of matcher-fn ast)))
    (while (not (eq location-containing-chain 'shen/not-found))
      (let ((current-chain (shen/internal/get-element-at location-containing-chain current-ast))
            (accum))
        (progn
          (while (funcall matcher-fn current-chain)
            (let ((collected (funcall collector-fn accum current-chain)))
              (setq accum (nth 0 collected))
              (setq current-chain (nth 1 collected))))
          (setq current-ast
                (shen/internal/nset-element-at
                 location-containing-chain
                 current-ast
                 (funcall tx-fn accum current-chain)))
          (setq location-containing-chain
                (shen/internal/list-containing-first-occurrence-of matcher-fn current-ast)))))
    current-ast))
;; Consolidate Call Chains:1 ends here

;; [[file:shen-elisp.org::*Consolidate Cons][Consolidate Cons:1]]
(defun shen/internal/consolidate-cons (ast)
  (shen/internal/consolidate
   ast
   (lambda (current-list)
     (and current-list
          (consp current-list)
          (eq 3 (length current-list))
          (eq (nth 0 current-list) 'shen/cons)))
   (lambda (accum current-chain)
     (list (cons (nth 1 current-chain) accum)
           (nth 2 current-chain)))
   (lambda (accum remaining-chain)
     (if (eq remaining-chain 'nil)
         `(list ,@(reverse accum))
       `(append (list ,@(reverse accum)) ,remaining-chain)))))
;; Consolidate Cons:1 ends here

;; [[file:shen-elisp.org::*Consolidate @s][Consolidate @s:1]]
(defun shen/internal/consolidate-@s (ast)
  (shen/internal/consolidate
   ast
   (lambda (current-list)
     (and current-list
          (consp current-list)
          (eq 3 (length current-list))
          (eq (nth 0 current-list) 'shen/@s)))
   (lambda (accum current-chain)
     (list (cons (nth 1 current-chain) accum)
           (nth 2 current-chain)))
   (lambda (accum remaining-chain)
     (list 'concat (cons 'concat (reverse accum)) remaining-chain))))
;; Consolidate @s:1 ends here

;; [[file:shen-elisp.org::*Consolidate tl][Consolidate tl:1]]
(defun shen/internal/consolidate-tl (ast)
  (shen/internal/consolidate
   ast
   (lambda (current-list)
     (and current-list
          (consp current-list)
          (eq 2 (length current-list))
          (eq (nth 0 current-list) 'shen/tl)))
   (lambda (accum current-chain)
     (list (if (not accum) 1 (+ accum 1))
           (nth 1 current-chain)))
   (lambda (accum remaining-chain)
     (list 'nthcdr accum remaining-chain))))
;; Consolidate tl:1 ends here

;; [[file:shen-elisp.org::*Add 1+'s][Add 1+'s:1]]
(defun shen/internal/add-1+ (ast)
  (shen/internal/consolidate
   ast
   (lambda (current-list)
     (and current-list
          (consp current-list)
          (eq 3 (length current-list))
          (and (eq (nth 0 current-list) 'shen/+)
               (or (eq (nth 1 current-list) 1)
                   (eq (nth 2 current-list) 1)))))
   (lambda (accum current-list)
     (if (eq (nth 1 current-list) 1)
         (list (nth 2 current-list) nil)
       (list (nth 1 current-list) nil)))
   (lambda (accum remaining-chain)
     (list '1+ accum))))
;; Add 1+'s:1 ends here

;; [[file:shen-elisp.org::*Nil Comparisons To Null][Nil Comparisons To Null:1]]
(defun shen/internal/nil-to-null (ast)
  (shen/internal/consolidate
   ast
   (lambda (current-list)
     (and current-list
          (consp current-list)
          (eq 3 (length current-list))
          (and (eq (nth 0 current-list) 'shen/=)
               (or (eq (nth 1 current-list) 'nil)
                   (eq (nth 2 current-list) 'nil)))))
   (lambda (accum current-list)
     (if (eq (nth 1 current-list) 'nil)
         (list (nth 2 current-list) nil)
       (list (nth 1 current-list) nil)))
   (lambda (accum remaining-chain)
     `(shen/internal/predicate->shen (null ,accum)))))
;; Nil Comparisons To Null:1 ends here

;; [[file:shen-elisp.org::*Performance][Performance:1]]
(setq shen/internal/*performance-overrides*
      '((map . (defun shen/map (F Xs)
                 (mapcar (lambda (X)
                           (shen/internal/apply-higher-order-function F (list X)))
                         Xs)))
        (shen.lazyderef . (defun shen/shen\.lazyderef
                              (X ProcessN)
                            (let ((Current X)
                                  (KeepLooking t))
                              (while KeepLooking
                                (shen/if
                                 (shen/shen.pvar? Current)
                                 (shen/let Value (shen/shen.valvector Current ProcessN)
                                           (shen/if (shen/= Value 'shen.-null-)
                                                    (setq KeepLooking nil)
                                                    (setq Current Value)))
                                 (setq KeepLooking nil)))
                              Current)))
        (append . (defun shen/append (Xs Ys) (append Xs Ys)))
        (shen.string->bytes . (defun shen/shen.string->bytes (S)
                                (string-to-list S)))
        (sum . (defun shen/sum (Xs) (apply #'+ Xs)))
        (hash . (defun shen/hash (N Div) (sxhash N)))
        (shen.mod . (defun shen/shen.mod (N Div) (mod N Div)))
        (integer? . (defun shen/integer? (N) (shen/internal/predicate->shen (integerp N))))
        (abs . (defun shen/shen.abs (N) (abs N)))
        (nth . (defun shen/nth (I Xs) (nth I Xs)))
        (element? . (defun shen/element? (Element Xs)
                      (let ((SearchList Xs)
                            (Found nil)
                            (Length (length Xs))
                            (Current 0))
                        (while (and (not Found) SearchList)
                          (setq Found (shen/internal/= Element (pop SearchList))))
                        (shen/internal/predicate->shen Found))))
        (shen.compose . (defun shen/shen.compose
                            (Fs X)
                          (let ((Result X))
                            (dolist (F Fs Result)
                              (setq Result (funcall F Result))))))))
;; Performance:1 ends here

;; [[file:shen-elisp.org::*Performance][Performance:2]]
(setq shen/internal/*dict-overrides*
      '((shen.dict . (defun shen/shen\.dict
                         (Size)
                       (let ((Dict (shen/absvector 4))
                             (Contents (shen/absvector Size)))
                         (progn
                           (shen/address-> Dict 0 'dictionary)
                           (shen/address-> Dict 1 Size)
                           (shen/address-> Dict 2 0)
                           (shen/address-> Dict 3 Contents)
                           Dict))))
        (shen.dict-> . (defun shen/shen\.dict->
                           (Dict Key Value)
                         (let* ((Count (shen/shen\.dict-count Dict))
                                (Contents (shen/<-address Dict 3))
                                (Exists (shen/<-address Contents Key)))
                           (progn
                             (if (not Exists)
                                 (shen/address-> Dict 2 (1+ Count)))
                             (shen/address-> Contents Key Value)))))
        (shen.<-dict . (defun shen/shen\.<-dict
                           (Dict Key)
                         (let* ((Contents (shen/<-address Dict 3))
                                (Existing (shen/<-address Contents Key)))
                           (if (not Existing)
                               (shen/freeze (shen/simple-error "value not found"))
                             Existing))))
        (shen.dict-rm . (defun shen/shen\.dict-rm
                            (Dict Key)
                          (let* ((Count (shen/shen\.dict-count Dict))
                                 (Contents (shen/<-address Dict 3))
                                 (Exists (shen/<-address Contents Key)))
                            (if (not Exists)
                                Key
                              (progn
                                (remhash Key Contents)
                                (shen/address-> Dict 2 (1- Count))
                                Key)))))
        (shen.dict-keys . (defun shen/shen\.dict-keys
                              (Dict)
                            (let* ((Contents (shen/<-address Dict 3)))
                              (hash-table-keys Contents))))
        (shen.dict-values . (defun shen/shen\.dict-values
                                (Dict)
                              (let* ((Contents (shen/<-address Dict 3)))
                                (hash-table-values Contents))))
        (shen.dict-fold . (defun shen/shen\.dict-fold
                              (F Dict Acc)
                            (let ((Contents (shen/<-address Dict 3)))
                              (progn
                                (setq NewAcc Acc)
                                (maphash
                                 (lambda (Key Value)
                                   (setq NewAcc (shen/internal/apply-higher-order-function F (list Key Value NewAcc))))
                                 Contents)
                                NewAcc))))
        (put . (defun shen/put
                   (X Pointer Y Dict)
                 (let* ((Contents (shen/<-address Dict 3))
                        (X-Contents (shen/<-address Contents X)))
                   (if X-Contents
                       (progn
                         (puthash Pointer Y X-Contents)
                         Y)
                     (progn
                       (setq X-Contents (shen/absvector 100))
                       (puthash X X-Contents Contents)
                       (puthash Pointer Y X-Contents)
                       Y)))))
        (unput . (defun shen/unput
                     (X Pointer Dict)
                   (let* ((Contents (shen/<-address Dict 3))
                          (X-Contents (shen/<-address Contents X)))
                     (progn
                       (if X-Contents
                           (remhash Pointer X-Contents))
                       X))))
        (get . (defun shen/get
                   (X Pointer Dict)
                 (let* ((Contents (shen/<-address Dict 3))
                        (X-Contents (shen/<-address Contents X))
                        (Pointer-Contents (if X-Contents (shen/<-address X-Contents Pointer))))
                   (if (not Pointer-Contents)
                       (shen/simple-error "value not found")
                     Pointer-Contents))))))
;; Performance:2 ends here

;; [[file:shen-elisp.org::*Namespacing][Namespacing:1]]
(setq shen/internal/*namespacing-overrides*
      '((function . (defun shen/function (S)
                      (shen/shen\.lookup-func
                       (shen/internal/unprefix-symbol S))))))
;; Namespacing:1 ends here

;; [[file:shen-elisp.org::*Bug Fixes][Bug Fixes:1]]
(setq shen/internal/*bugfix-overrides*
      '((untrack . (defun shen/untrack (F)
                     (progn
                       (shen/set shen.*tracking*
                                 (shen/internal/delete-first-eq
                                  F
                                  (shen/value shen.*tracking*)))
                       (shen/eval (shen/ps F)))))))
;; Bug Fixes:1 ends here

;; [[file:shen-elisp.org::*Evaluate KLambda][Evaluate KLambda:1]]
(defun shen/internal/kl-to-elisp (Kl)
  (shen/internal/nil-to-null
   (shen/internal/add-1+
    (shen/internal/consolidate-tl
     (shen/internal/consolidate-@s
      (shen/internal/consolidate-cons (shen/internal/parse-ast Kl)))))))
;; Evaluate KLambda:1 ends here

;; [[file:shen-elisp.org::*Evaluate KLambda][Evaluate KLambda:2]]
(defun shen/eval-kl (X)
  (if (and (consp X) (eq (car X) 'defun))
      (progn
        (byte-compile (eval (shen/internal/kl-to-elisp (copy-tree X)) 't))
        (nth 1 X))
    (eval (shen/internal/kl-to-elisp X) 't)))
;; Evaluate KLambda:2 ends here

;; [[file:shen-elisp.org::*Generate From Seed KLambda Files][Generate From Seed KLambda Files:1]]
(defun shen/internal/add-overrides (overrides table)
  (mapc
   (lambda (override)
     (puthash (car override)
              (cdr override)
              table))
   overrides))

(setq shen/*overrides*
      (let ((table (make-hash-table :test 'equal)))
        (shen/internal/add-overrides
         (append
          shen/internal/*performance-overrides*
          shen/internal/*dict-overrides*
          shen/internal/*namespacing-overrides*
          shen/internal/*bugfix-overrides*)
         table)
        table))
;; Generate From Seed KLambda Files:1 ends here

;; [[file:shen-elisp.org::*Evaluating Bootstrapped KLambda][Evaluating Bootstrapped KLambda:1]]
(defun shen/patch-klambda (ast)
  (if (eq (car ast) 'defun)
      (let ((override (gethash (nth 1 ast) shen/*overrides*)))
        (or override
            (shen/internal/parse-ast ast)))
    (let ((patched (gethash ast shen/*overrides* )))
      (or patched
          (shen/internal/parse-ast ast)))))
;; Evaluating Bootstrapped KLambda:1 ends here

;; [[file:shen-elisp.org::*Evaluating Bootstrapped KLambda][Evaluating Bootstrapped KLambda:2]]
(defun shen/kl-to-buffer (X B)
  (with-current-buffer B
    (save-excursion
      (goto-char (point-max))
      (insert (pp-to-string
               (shen/internal/nil-to-null
                (shen/internal/add-1+
                 (shen/internal/consolidate-tl
                  (shen/internal/consolidate-@s
                   (shen/internal/consolidate-cons
                    (shen/patch-klambda X)))))))))))
;; Evaluating Bootstrapped KLambda:2 ends here

;; [[file:shen-elisp.org::*Providing The Primitives][Providing The Primitives:1]]
(provide 'shen-primitives)
;; Providing The Primitives:1 ends here
