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, 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)))))