~ 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