Function: hif-expand-token-list

hif-expand-token-list is a byte-compiled function defined in hideif.el.gz.

Signature

(hif-expand-token-list TOKENS &optional MACRONAME EXPAND_LIST LEVEL)

Documentation

Perform expansion on TOKENS till everything expanded.

Self-reference (directly or indirectly) tokens are not expanded. EXPAND_LIST is the list of macro names currently being expanded, used for detecting self-reference. Function-like macros with calling depth LEVEL 0 does not expand arguments, this is to emulate the stringification behavior of C++ preprocessor.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/hideif.el.gz
(defun hif-expand-token-list (tokens &optional macroname expand_list level)
  "Perform expansion on TOKENS till everything expanded.
Self-reference (directly or indirectly) tokens are not expanded.
EXPAND_LIST is the list of macro names currently being expanded, used for
detecting self-reference.
Function-like macros with calling depth LEVEL 0 does not expand arguments,
this is to emulate the stringification behavior of C++ preprocessor."
  (catch 'self-referencing
    (let ((expanded nil)
          (remains (hif-define-operator
                    (hif-token-concatenation
                     (hif-token-stringification tokens))))
          tok rep)
      (setq level (if level level 0))
      (if macroname
          (setq expand_list (cons macroname expand_list)))
      ;; Expanding all tokens till list exhausted
      (while (setq tok (pop remains))
        (if (memq tok expand_list)
            ;; For self-referencing tokens, don't expand it
            (throw 'self-referencing tokens))
        (push
         (cond
          ((or (memq tok hif-valid-token-list)
               (numberp tok)
               (stringp tok))
           tok)

          ((setq rep (hif-lookup tok))
           (if (and (listp rep)
                    (eq (car rep) 'hif-define-macro)) ; A defined macro
               ;; Recursively expand it
               ;; only in defined macro do we increase the nesting LEVEL
               (if (cadr rep) ; Argument list is not nil
                   (if (not (or (eq (car remains) 'hif-lparen)
                                ;; hif-space hif-lparen
                                (and (eq (car remains) 'hif-space)
                                     (eq (cadr remains) 'hif-lparen)
                                     (setq remains (cdr remains)))))
                       ;; No argument list, no invocation
                       tok
                     ;; Argumented macro, get arguments and invoke it.
                     ;; Dynamically bind `hif-token-list' and `hif-token'
                     ;; for `hif-macro-supply-arguments'
                     (let* ((hif-token-list (cdr remains))
                            (hif-token nil)
                            (parmlist
                             (if (zerop level)
                                 (hif-get-argument-list t)
                               (mapcar (lambda (a)
                                         (hif-expand-token-list
                                          a nil nil (1+ level)))
                                       (hif-get-argument-list t))))
                            (result
                             (hif-expand-token-list
                              (hif-macro-supply-arguments tok parmlist)
                              tok expand_list (1+ level))))
                       (setq remains (cons hif-token hif-token-list))
                       result))
                 ;; Argument list is nil, direct expansion
                 (setq rep (hif-expand-token-list
                            (nth 2 rep) ; Macro's token list
                            tok expand_list))
                 ;; Replace all remaining references immediately
                 (setq remains (cl-substitute tok rep remains))
                 rep)
             ;; Lookup tok returns an atom
             rep))

          ;;[2013-10-22 16:06:12 +0800] Must keep the token, removing
          ;; this token might results in an incomplete expression that
          ;; cannot be parsed further.
          ;;((= 1 (hif-defined tok)) ; defined (hif-defined tok)=1,
          ;;  ;;but empty (hif-lookup tok)=nil, thus remove this token
          ;; (setq remains (delete tok remains))
          ;; nil)

          (t ; Usual IDs
           tok))

         expanded))

      (flatten-tree (nreverse expanded)))))