+(export 'test-parse-c-type)
+(defun test-parse-c-type (string)
+ "Parse STRING as a C type, with optional kernel, and show the results."
+ (with-input-from-string (in string)
+ (let* ((*module-type-map* (make-hash-table))
+ (charscan (make-instance 'charbuf-scanner
+ :stream in
+ :filename "<string>"))
+ (tokscan (make-instance 'sod-token-scanner
+ :char-scanner charscan
+ :filename "<string>")))
+ (with-parser-context (token-scanner-context :scanner tokscan)
+ (multiple-value-bind (value winp consumedp)
+ (parse (seq ((decls (parse-c-type tokscan))
+ (type (parse-declarator tokscan decls :abstractp t))
+ :eof)
+ type))
+ (declare (ignore consumedp))
+ (if winp
+ (values t (car value) (cdr value)
+ (princ-to-string (car value)))
+ (values nil value)))))))
+
+(export 'test-parser)
+(defmacro test-parser ((scanner &key) parser input)
+ "Convenient macro for testing parsers at the REPL.
+
+ This is a macro so that the parser can use the fancy syntax. The name
+ SCANNER is bound to a `sod-token-scanner' reading tokens from the INPUT
+ string. Then the PARSER is invoked and three values are returned: a
+ `successp' flag indicating whether the parser succeeded; the result,
+ output or error indicator, of the parser; and a list consisting of the
+ lookahead token type and value, and a string containing the untokenized
+ remaining input."
+ (once-only (input)
+ (with-gensyms (char-scanner value winp consumedp where)
+ `(let* ((,char-scanner (make-string-scanner ,input))
+ (,scanner (make-instance 'sod-token-scanner
+ :char-scanner ,char-scanner
+ :filename "<test-input>")))
+ (with-parser-context (token-scanner-context :scanner ,scanner)
+ (multiple-value-bind (,value ,winp ,consumedp) (parse ,parser)
+ (declare (ignore ,consumedp))
+ (let ((,where (scanner-capture-place ,char-scanner)))
+ (values ,winp ,value
+ (list (token-type ,scanner) (token-value ,scanner)
+ (subseq ,input ,where))))))))))
+
+;;;--------------------------------------------------------------------------
+;;; Calisthenics.
+
+(export 'exercise)
+(defun exercise ()
+ "Exercise the pieces of the metaobject protocol.
+
+ In some Lisps, the compiler is run the first time methods are called, to
+ do fancy just-in-time optimization things. This is great, only the
+ program doesn't actually run for very long and a lot of that work is
+ wasted because we're going to have to do it again next time the program
+ starts. Only, if we exercise the various methods, or at least a large
+ fraction of them, before we dump an image, then everything will be fast.
+
+ That's the theory anyway. Call this function before you dump an image and
+ see what happens."
+
+ (clear-the-decks)
+ (dolist (reason '(:h :c))
+ (with-output-to-string (bitbucket)
+ (output-module *builtin-module* reason bitbucket)))
+
+ (clear-the-decks))
+