~ chicken-core (chicken-5) fea4d53e6f3966c4c15bdb35f75bc1ce71bc62a8
commit fea4d53e6f3966c4c15bdb35f75bc1ce71bc62a8 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri Aug 1 16:14:04 2025 +0200 Commit: Peter Bex <peter@more-magic.net> CommitDate: Tue Aug 5 13:55:13 2025 +0200 Add `expand1` procedure in module (chicken syntax). (original patch by John Croisant, slightly modified to avoid bootstrapping issue) Like `expand` but expands the form only once, instead of repeating until a non-macro form is produced. This is helpful when debugging macros because you can see the intermediate results of the expansion. Also add `,x`, which is like `,x` but uses `expand1` instead of `expand`. The form is expanded only once, then pretty-printed. Signed-off-by: felix <felix@call-with-current-continuation.org> Signed-off-by: Peter Bex <peter@more-magic.net> diff --git a/chicken.syntax.import.scm b/chicken.syntax.import.scm index d11a3ffa..81b61eaf 100644 --- a/chicken.syntax.import.scm +++ b/chicken.syntax.import.scm @@ -31,6 +31,7 @@ 'chicken.syntax 'expand '((expand . chicken.syntax#expand) + (expand1 . chicken.syntax#expand1) (get-line-number . chicken.syntax#get-line-number) (read-with-source-info . chicken.syntax#read-with-source-info) (strip-syntax . chicken.syntax#strip-syntax) diff --git a/csi.scm b/csi.scm index 2a4c8477..e3c95d2e 100644 --- a/csi.scm +++ b/csi.scm @@ -424,16 +424,28 @@ EOF (lambda () (let ((name (read))) (cond ((not name) - (##sys#switch-module #f) - (printf "; resetting current module to toplevel~%")) - ((##sys#find-module (##sys#resolve-module-name name #f) #f) => - (lambda (m) - (##sys#switch-module m) - (printf "; switching current module to `~a'~%" name))) - (else - (printf "undefined module `~a'~%" name)))))) + (##sys#switch-module #f) + (printf "; resetting current module to toplevel~%")) + ((##sys#find-module (##sys#resolve-module-name name #f) #f) => + (lambda (m) + (##sys#switch-module m) + (printf "; switching current module to `~a'~%" name))) + (else + (printf "undefined module `~a'~%" name)))))) ",m MODULE switch to module with name `MODULE'") +(toplevel-command + 'x1 + (let ((pretty-print pretty-print)) + (lambda () + (let ([expr (read)]) + ;; avoid bootstrapping issue, as chicken.syntax is not + ;; imported dynamically by bootstrap compiler + ;; this can be replaced by "expand1" later + (pretty-print (strip-syntax (chicken.syntax#expand1 expr))) + (##sys#void)))) + ",x1 EXP Pretty print expand1-ed expression EXP") + ;;; Parse options from string: diff --git a/expand.scm b/expand.scm index a329c4ba..858c9f68 100644 --- a/expand.scm +++ b/expand.scm @@ -36,6 +36,7 @@ (module chicken.syntax (expand + expand1 get-line-number read-with-source-info strip-syntax @@ -305,6 +306,9 @@ (loop exp2) exp2) ) ) ) +(define (expand1 exp #!optional (se (##sys#current-environment)) cs?) + (nth-value 0 (##sys#expand-0 exp se cs?)) ) + ;;; Extended (DSSSL-style) lambda lists ; diff --git a/manual/Module (chicken syntax) b/manual/Module (chicken syntax) index 1f1e44a4..19e550be 100644 --- a/manual/Module (chicken syntax) +++ b/manual/Module (chicken syntax) @@ -301,6 +301,14 @@ comparison {{(compare sym 'abc)}} should be written as {{(compare sym If {{X}} is a macro-form, expand the macro (and repeat expansion until expression is a non-macro form). Returns the resulting expression. +==== expand1 + +<procedure>(expand1 X)</procedure> + +If {{X}} is a macro-form, expand the macro only once. Unlike +{{expand}}, does not repeat expansion when the resulting expression is +itself a macro-form. Returns the resulting expression. + === Macro helper procedures ==== begin-for-syntax diff --git a/manual/Using the interpreter b/manual/Using the interpreter index de1f3097..14cda247 100644 --- a/manual/Using the interpreter +++ b/manual/Using the interpreter @@ -117,6 +117,8 @@ The toplevel loop understands a number of special commands: ; ,x EXP : Pretty-print macroexpanded expression {{EXP}} (the expression is not evaluated). +; ,x1 EXP : Like {{,x}} but {{EXP}} is expanded only one step, using {{expand1}}. + You can define your own toplevel commands using the {{toplevel-command}} procedure (see [[Module (chicken csi)]]).Trap