~ 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