~ chicken-core (master) /chicken-syntax.scm


   1;;;; chicken-syntax.scm - non-standard syntax extensions
   2;
   3; Copyright (c) 2008-2022, The CHICKEN Team
   4; Copyright (c) 2000-2007, Felix L. Winkelmann
   5; All rights reserved.
   6;
   7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
   8; conditions are met:
   9;
  10;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
  11;     disclaimer. 
  12;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  13;     disclaimer in the documentation and/or other materials provided with the distribution. 
  14;   Neither the name of the author nor the names of its contributors may be used to endorse or promote
  15;     products derived from this software without specific prior written permission. 
  16;
  17; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
  20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25; POSSIBILITY OF SUCH DAMAGE.
  26
  27
  28(declare
  29  (unit chicken-syntax)
  30  (uses expand internal)
  31  (disable-interrupts)
  32  (fixnum) )
  33
  34;; IMPORTANT: These macros expand directly into fully qualified names
  35;; from the scrutinizer and support modules.
  36
  37#+(not debugbuild)
  38(declare
  39  (no-bound-checks)
  40  (no-procedure-checks))
  41
  42(import (scheme)
  43        (chicken base)
  44        (chicken fixnum)
  45        (chicken syntax)
  46        (chicken internal)
  47        (chicken platform))
  48
  49(include "common-declarations.scm")
  50(include "mini-srfi-1.scm")
  51
  52;;; Exceptions:
  53(set! ##sys#chicken.condition-macro-environment
  54  (let ((me0 (##sys#macro-environment)))
  55
  56(##sys#extend-macro-environment
  57 'handle-exceptions
  58 `((call-with-current-continuation . scheme#call-with-current-continuation))
  59 (##sys#er-transformer
  60  (lambda (form r c)
  61    (##sys#check-syntax 'handle-exceptions form '(_ variable _ . _))
  62    (let ((k (r 'k))
  63	  (args (r 'args)))
  64      `((,(r 'call-with-current-continuation)
  65	 (##core#lambda
  66	  (,k)
  67	  (chicken.condition#with-exception-handler
  68	   (##core#lambda (,(cadr form)) (,k (##core#lambda () ,(caddr form))))
  69	   (##core#lambda
  70	    ()
  71	    (##sys#call-with-values
  72	     (##core#lambda () ,@(cdddr form))
  73	     (##core#lambda
  74	      ,args
  75	      (,k (##core#lambda () (##sys#apply ##sys#values ,args))))))))))))))
  76
  77(##sys#extend-macro-environment
  78 'condition-case
  79 `((memv . scheme#memv))
  80 (##sys#er-transformer
  81  (lambda (form r c)
  82    (##sys#check-syntax 'condition-case form '(_ _ . _))
  83    (let ((exvar (r 'exvar))
  84	  (kvar (r 'kvar))
  85	  (%and (r 'and))
  86	  (%memv (r 'memv))
  87	  (%else (r 'else)))
  88      (define (parse-clause c)
  89	(let* ((var (and (symbol? (car c)) (car c)))
  90	       (kinds (if var (cadr c) (car c)))
  91	       (body (if var
  92			 `(##core#let ((,var ,exvar)) ,@(cddr c))
  93			 `(##core#let () ,@(cdr c)))))
  94	  (if (null? kinds)
  95	      `(,%else ,body)
  96	      `((,%and ,kvar ,@(map (lambda (k)
  97				      `(,%memv (##core#quote ,k) ,kvar)) kinds))
  98		,body))))
  99      `(,(r 'handle-exceptions) ,exvar
 100	(##core#let ((,kvar (,%and (##sys#structure? ,exvar
 101						     (##core#quote condition))
 102				   (##sys#slot ,exvar 1))))
 103		    ,(let ((clauses (map parse-clause (cddr form))))
 104		       `(,(r 'cond)
 105			 ,@clauses
 106			 ,@(if (assq %else clauses)
 107			       `()   ; Don't generate two else clauses
 108			       `((,%else (chicken.condition#signal ,exvar)))))))
 109	,(cadr form))))))
 110
 111(macro-subset me0 ##sys#default-macro-environment)))
 112
 113
 114;;; type-related syntax
 115
 116(set! ##sys#chicken.type-macro-environment
 117  (let ((me0 (##sys#macro-environment)))
 118
 119(##sys#extend-macro-environment
 120 ': '()
 121 (##sys#er-transformer
 122  (lambda (x r c)
 123    (##sys#check-syntax ': x '(_ symbol _ . _))
 124    (if (not (memq #:compiling ##sys#features))
 125	'(##core#undefined)
 126	(let* ((type1 (strip-syntax (caddr x)))
 127	       (name1 (cadr x)))
 128	  ;; we need pred/pure info, so not using
 129	  ;; "chicken.compiler.scrutinizer#check-and-validate-type"
 130	  (let-values (((type pred pure)
 131			(chicken.compiler.scrutinizer#validate-type
 132			 type1
 133			 (strip-syntax name1))))
 134	    (cond ((not type)
 135		   (##sys#syntax-error ': "invalid type syntax" name1 type1))
 136		  (else
 137		   `(##core#declare
 138		     (type (,name1 ,type1 ,@(cdddr x)))
 139		     ,@(if pure `((pure ,name1)) '())
 140		     ,@(if pred `((predicate (,name1 ,pred))) '()))))))))))
 141
 142(##sys#extend-macro-environment
 143 'the '()
 144 (##sys#er-transformer
 145  (lambda (x r c)
 146    (##sys#check-syntax 'the x '(_ _ _))
 147    (if (not (memq #:compiling ##sys#features))
 148	(caddr x)
 149	`(##core#the ,(chicken.compiler.scrutinizer#check-and-validate-type (cadr x) 'the)
 150		     #t
 151		     ,(caddr x))))))
 152
 153(##sys#extend-macro-environment
 154 'assume '()
 155 (syntax-rules ()
 156   ((_ ((var type) ...) body ...)
 157    (let ((var (the type var)) ...) body ...))))
 158
 159(##sys#extend-macro-environment
 160 'define-specialization '()
 161 (##sys#er-transformer
 162  (lambda (x r c)
 163    (cond ((not (memq #:compiling ##sys#features)) '(##core#undefined))
 164	  (else
 165	   (##sys#check-syntax 'define-specialization x '(_ (variable . #(_ 0)) _ . #(_ 0 1)))
 166	   (let* ((head (cadr x))
 167		  (name (car head))
 168		  (args (cdr head))
 169		  (alias (gensym name))
 170		  (rtypes (and (pair? (cdddr x)) (strip-syntax (caddr x))))
 171		  (%define (r 'define))
 172		  (body (if rtypes (cadddr x) (caddr x))))
 173	     (let loop ((args args) (anames '()) (atypes '()))
 174	       (cond ((null? args)
 175		      (let ((anames (reverse anames))
 176			    (atypes (reverse atypes))
 177			    (spec
 178			     `(,alias ,@(let loop2 ((anames anames) (i 1))
 179					  (if (null? anames)
 180					      '()
 181					      (cons (vector i)
 182						    (loop2 (cdr anames) (fx+ i 1))))))))
 183			`(##core#begin
 184			  (##core#local-specialization
 185			   ,name
 186			   ,alias
 187			   ,(cons atypes
 188				  (if (and rtypes (pair? rtypes))
 189				      (list
 190				       (map (cut chicken.compiler.scrutinizer#check-and-validate-type
 191					      <>
 192					      'define-specialization)
 193					    rtypes)
 194				       spec)
 195				      (list spec))))
 196			  (##core#declare (inline ,alias) (hide ,alias))
 197			  (,%define (,alias ,@anames)
 198				    (##core#let ,(map (lambda (an at)
 199							(list an `(##core#the ,at #t ,an)))
 200						      anames atypes)
 201						,body)))))
 202		     (else
 203		      (let ((arg (car args)))
 204			(cond ((symbol? arg)
 205			       (loop (cdr args) (cons arg anames) (cons '* atypes)))
 206			      ((and (list? arg) (fx= 2 (length arg)) (symbol? (car arg)))
 207			       (loop
 208				(cdr args)
 209				(cons (car arg) anames)
 210				(cons
 211				 (chicken.compiler.scrutinizer#check-and-validate-type
 212				  (cadr arg)
 213				  'define-specialization)
 214				 atypes)))
 215			      (else (##sys#syntax-error
 216				     'define-specialization
 217				     "invalid argument syntax" arg head)))))))))))))
 218
 219(##sys#extend-macro-environment
 220 'compiler-typecase '()
 221 (##sys#er-transformer
 222  (lambda (x r c)
 223    (##sys#check-syntax 'compiler-typecase x '(_ _ . #((_ . #(_ 1)) 1)))
 224    (let ((val (memq #:compiling ##sys#features))
 225	  (var (gensym))
 226	  (ln (get-line-number x)))
 227      `(##core#let ((,var ,(cadr x)))
 228	 (##core#typecase
 229	  ,ln
 230	  ,var		; must be variable (see: CPS transform)
 231	  ,@(map (lambda (clause)
 232		 (let ((hd (strip-syntax (car clause))))
 233		   (list
 234		    (if (eq? hd 'else)
 235			'else
 236			(if val
 237			    (chicken.compiler.scrutinizer#check-and-validate-type
 238			     hd
 239			     'compiler-typecase)
 240			    hd))
 241		    `(##core#begin ,@(cdr clause)))))
 242		 (cddr x))))))))
 243
 244(##sys#extend-macro-environment
 245 'define-type '()
 246 (##sys#er-transformer
 247  (lambda (x r c)
 248    (##sys#check-syntax 'define-type x '(_ variable _))
 249    (cond ((not (memq #:compiling ##sys#features)) '(##core#undefined))
 250	  (else
 251	   (let ((name (strip-syntax (cadr x)))
 252		 (%quote (r 'quote))
 253		 (t0 (strip-syntax (caddr x))))
 254	     `(##core#elaborationtimeonly
 255	       (##sys#put/restore!
 256		(,%quote ,name)
 257		(,%quote ##compiler#type-abbreviation)
 258		(,%quote
 259		 ,(chicken.compiler.scrutinizer#check-and-validate-type
 260		   t0 'define-type name))))))))))
 261
 262(macro-subset me0 ##sys#default-macro-environment)))
 263
 264;;; Syntax-related syntax (for use in macro transformers)
 265
 266(set! ##sys#chicken.syntax-macro-environment
 267  (let ((me0 (##sys#macro-environment)))
 268
 269(##sys#extend-macro-environment
 270 'syntax
 271 '()
 272 (##sys#er-transformer
 273  (lambda (x r c)
 274    (##sys#check-syntax 'syntax x '(_ _))
 275    `(##core#syntax ,(cadr x)))))
 276
 277(##sys#extend-macro-environment
 278 'begin-for-syntax '()
 279 (##sys#er-transformer
 280  (lambda (x r c)
 281    (##sys#check-syntax 'begin-for-syntax x '(_ . #(_ 0)))
 282    (##sys#register-meta-expression `(##core#begin ,@(cdr x)))
 283    `(##core#elaborationtimeonly (##core#begin ,@(cdr x))))))
 284
 285(##sys#extend-macro-environment
 286 'define-for-syntax '()
 287 (##sys#er-transformer
 288  (lambda (form r c)
 289    (##sys#check-syntax 'define-for-syntax form '(_ _ . _))
 290    `(,(r 'begin-for-syntax)
 291      (,(r 'define) ,@(cdr form))))))
 292
 293
 294;;; Compiler syntax
 295
 296(##sys#extend-macro-environment
 297 'define-compiler-syntax '()
 298 (syntax-rules ()
 299   ((_ name)
 300    (##core#define-compiler-syntax name #f))
 301   ((_ name transformer)
 302    (##core#define-compiler-syntax name transformer))))
 303
 304(##sys#extend-macro-environment
 305 'let-compiler-syntax '()
 306 (syntax-rules ()
 307   ((_ (binding ...) body ...)
 308    (##core#let-compiler-syntax (binding ...) body ...))))
 309
 310(macro-subset me0 ##sys#default-macro-environment)))
 311
 312
 313;;; Non-standard macros that provide core/"base" functionality:
 314
 315(set! ##sys#chicken.base-macro-environment
 316  (let ((me0 (##sys#macro-environment)))
 317
 318(##sys#extend-macro-environment
 319 'define-constant
 320 '()
 321 (##sys#er-transformer
 322  (lambda (form r c)
 323    (##sys#check-syntax 'define-constant form '(_ variable _))
 324    `(##core#define-constant ,@(cdr form)))))
 325
 326(##sys#extend-macro-environment
 327 'define-record '()
 328 (##sys#er-transformer
 329  (lambda (x r c)
 330    (##sys#check-syntax 'define-record x '(_ variable . _))
 331    (let* ((type-name (cadr x))
 332	   (plain-name (strip-syntax type-name))
 333	   (prefix (symbol->string plain-name))
 334	   (tag (if (##sys#current-module)
 335		    (symbol-append
 336		     (##sys#module-name (##sys#current-module)) '|#| plain-name)
 337		    plain-name))
 338	   (slots (cddr x))
 339	   (%define (r 'define))
 340	   (%setter (r 'chicken.base#setter))
 341	   (%getter-with-setter (r 'chicken.base#getter-with-setter))
 342	   (slotnames
 343	    (map (lambda (slot)
 344		   (cond ((symbol? slot) slot)
 345			 ((and (pair? slot)
 346			       (c (car slot) %setter) 
 347			       (pair? (cdr slot))
 348			       (symbol? (cadr slot))
 349			       (null? (cddr slot)))
 350			  (cadr slot))
 351			 (else
 352			  (##sys#syntax-error
 353			   'define-record "invalid slot specification" slot))))
 354		 slots)))
 355      `(##core#begin
 356	(,%define ,type-name (##core#quote ,tag))
 357	(,%define 
 358	 ,(string->symbol (string-append "make-" prefix))
 359	 (##core#lambda 
 360	  ,slotnames
 361	  (##sys#make-structure (##core#quote ,tag) ,@slotnames)))
 362	(,%define
 363	 ,(string->symbol (string-append prefix "?"))
 364	 (##core#lambda (x) (##sys#structure? x (##core#quote ,tag))))
 365	,@(let mapslots ((slots slots) (i 1))
 366	    (if (eq? slots '())
 367		slots
 368		(let* ((a (car slots))
 369		       (has-setter (not (symbol? a)))
 370		       (slotname (symbol->string (if has-setter (cadr a) a)))
 371		       (setr (string->symbol (string-append prefix "-" slotname "-set!")))
 372		       (getr (string->symbol (string-append prefix "-" slotname)))
 373		       (setrcode
 374			`(##core#lambda 
 375			  (x val)
 376			  (##core#check (##sys#check-structure x (##core#quote ,tag)))
 377			  (##sys#block-set! x ,i val) ) ))
 378		  (cons
 379		   `(##core#begin
 380		     ,@(if has-setter
 381			   '()
 382			   `((,%define ,setr ,setrcode)))
 383		     (,%define
 384		      ,getr
 385		      ,(if has-setter
 386			   `(,%getter-with-setter
 387			     (##core#lambda
 388			      (x) 
 389			      (##core#check (##sys#check-structure x (##core#quote ,tag)))
 390			      (##sys#block-ref x ,i) )
 391			     ,setrcode)
 392			   `(##core#lambda 
 393			     (x)
 394			     (##core#check (##sys#check-structure x (##core#quote ,tag)))
 395			     (##sys#block-ref x ,i) ) ) ) )
 396		   (mapslots (##sys#slot slots 1) (fx+ i 1)) ) ) ) ) ) ) ) ) )
 397
 398(##sys#extend-macro-environment
 399 'receive
 400 '()
 401 (##sys#er-transformer
 402  (lambda (form r c)
 403    (##sys#check-syntax 'receive form '(_ _ . #(_ 0)))
 404    (cond ((null? (cddr form))
 405	   `(##sys#call-with-values (##core#lambda () ,@(cdr form)) ##sys#list) )
 406	  (else
 407	   (##sys#check-syntax 'receive form '(_ lambda-list _ . #(_ 1)))
 408	   (let ((vars (cadr form))
 409		 (exp (caddr form))
 410		 (rest (cdddr form)))
 411	     (if (and (pair? vars) (null? (cdr vars)))
 412		 `(##core#let ((,(car vars) ,exp)) ,@rest)
 413		 `(##sys#call-with-values 
 414		   (##core#lambda () ,exp)
 415		   (##core#lambda ,vars ,@rest)) ) ) ) ) )))
 416
 417(##sys#extend-macro-environment
 418 'declare '()
 419 (##sys#er-transformer
 420  (lambda (form r c)
 421    `(##core#declare ,@(cdr form)))))
 422
 423(##sys#extend-macro-environment
 424 'delay-force
 425 '()
 426 (##sys#er-transformer
 427  (lambda (form r c)
 428    (##sys#check-syntax 'delay-force form '(_ _))
 429    `(##sys#make-promise (##core#lambda () ,(cadr form))))))
 430
 431(##sys#extend-macro-environment
 432 'include '()
 433 (##sys#er-transformer
 434  (lambda (form r c)
 435    (##sys#check-syntax 'include form '(_ . #(string 1)))
 436    `(##core#begin ,@(map (lambda (x) `(##core#include ,x #f))
 437                       (cdr form))))))
 438
 439(##sys#extend-macro-environment
 440 'include-ci '()
 441 (##sys#er-transformer
 442  (lambda (form r c)
 443    (##sys#check-syntax 'include-ci form '(_ . #(string 1)))
 444    `(##core#begin ,@(map (lambda (x) `(##core#include-ci ,x #f))
 445                       (cdr form))))))
 446
 447(##sys#extend-macro-environment
 448 'include-relative '()
 449 (##sys#er-transformer
 450  (lambda (form r c)
 451    (##sys#check-syntax 'include-relative form '(_ . #(string 1)))
 452    `(##core#begin ,@(map (lambda (x) 
 453                            `(##core#include ,x ,##sys#current-source-filename))
 454                       (cdr form))))))
 455
 456(##sys#extend-macro-environment
 457 'fluid-let '()
 458 (##sys#er-transformer
 459  (lambda (form r c)
 460    (##sys#check-syntax 'fluid-let form '(_ #((variable _) 0) . _))
 461     (let* ((clauses (cadr form))
 462	   (body (cddr form))
 463	   (ids (##sys#map car clauses))
 464	   (new-tmps (##sys#map (lambda (x) (r (gensym))) clauses))
 465	   (old-tmps (##sys#map (lambda (x) (r (gensym))) clauses)))
 466       `(##core#let
 467	 (,@(map ##sys#list new-tmps (##sys#map cadr clauses))
 468	  ,@(map ##sys#list old-tmps
 469		 (let loop ((n (length clauses)))
 470		   (if (eq? n 0)
 471		       '()
 472		       (cons #f (loop (fx- n 1))) ) ) ) )
 473	 (##sys#dynamic-wind
 474	  (##core#lambda ()
 475		    ,@(map (lambda (ot id) `(##core#set! ,ot ,id))
 476			   old-tmps ids)
 477		    ,@(map (lambda (id nt) `(##core#set! ,id ,nt))
 478			   ids new-tmps)
 479		    (##core#undefined) )
 480	  (##core#lambda () ,@body)
 481	  (##core#lambda ()
 482		    ,@(map (lambda (nt id) `(##core#set! ,nt ,id))
 483			   new-tmps ids)
 484		    ,@(map (lambda (id ot) `(##core#set! ,id ,ot))
 485			   ids old-tmps)
 486		    (##core#undefined) ) ) ) ) )))
 487
 488(##sys#extend-macro-environment
 489 'parameterize '()
 490 (##sys#er-transformer
 491  (lambda (form r c)
 492    (define (pname p)
 493      (if (symbol? p)
 494	  (gensym p)
 495	  (gensym "parameter")))
 496    (##sys#check-syntax 'parameterize form '#(_ 2))
 497    (let* ((bindings (cadr form))
 498	   (body (cddr form))
 499	   (convert? (r 'convert?))
 500	   (params (##sys#map car bindings))
 501	   (vals (##sys#map cadr bindings))
 502	   (param-aliases (##sys#map (lambda (z) (r (pname z))) params))
 503	   (saveds (##sys#map (lambda (z) (r (gensym 'saved))) params))
 504	   (temps (##sys#map (lambda (z) (r (gensym 'tmp))) params)) )
 505      `(##core#let
 506	,(map ##sys#list param-aliases params) ; These may be expressions
 507	(##core#let
 508	 ,(map ##sys#list saveds vals)
 509	 (##core#let
 510	  ;; Inner names are actually set.  This hides the exact
 511	  ;; ordering of the let if any call/cc is used in the
 512	  ;; value expressions (see first example in #1336).
 513	  ,(map ##sys#list saveds saveds)
 514	  (##core#let
 515	   ((,convert? (##core#the boolean #t #t))) ; Convert only first time extent is entered!
 516	   (##sys#dynamic-wind
 517	    (##core#lambda ()
 518	      (##core#let
 519	       ;; First, call converters (which may throw exceptions!)
 520	       ,(map (lambda (p s temp)
 521		       `(,temp (##core#if ,convert? (,p ,s #t #f) ,s)))
 522		     param-aliases saveds temps)
 523	       ;; Save current values so we can restore them later
 524	       ,@(map (lambda (p s) `(##core#set! ,s (,p)))
 525		      param-aliases saveds)
 526	       ;; Set parameters to their new values.  This can't fail.
 527	       ,@(map (lambda (p t) `(,p ,t #f #t)) param-aliases temps)
 528	       ;; Remember we already converted (only call converters once!)
 529	       (##core#set! ,convert? #f)))
 530	    (##core#lambda () ,@body)
 531	    (##core#lambda ()
 532	      (##core#let
 533	       ;; Remember the current value of each parameter.
 534	       ,(map (lambda (p s temp) `(,temp (,p)))
 535		     param-aliases saveds temps)
 536	       ;; Restore each parameter to its old value.
 537	       ,@(map (lambda (p s) `(,p ,s #f #t)) param-aliases saveds)
 538	       ;; Save current value for later re-invocations.
 539	       ,@(map (lambda (s temp) `(##core#set! ,s ,temp))
 540		      saveds temps))))))))))))
 541
 542(##sys#extend-macro-environment
 543 'require-library
 544 '()
 545 (##sys#er-transformer
 546  (lambda (x r c)
 547    `(##core#begin
 548      ,@(map (lambda (x)
 549	       (let-values (((name lib _ _ _ _) (##sys#decompose-import x r c 'import)))
 550		 (if (not lib)
 551		     '(##core#undefined)
 552		     `(##core#require ,lib ,name))))
 553	     (cdr x))))))
 554
 555(##sys#extend-macro-environment
 556 'when '()
 557 (##sys#er-transformer
 558  (lambda (form r c)
 559    (##sys#check-syntax 'when form '#(_ 2))
 560    `(##core#if ,(cadr form)
 561		(##core#begin ,@(cddr form))))))
 562
 563(##sys#extend-macro-environment
 564 'unless '()
 565 (##sys#er-transformer
 566  (lambda (form r c)
 567    (##sys#check-syntax 'unless form '#(_ 2))
 568    `(##core#if ,(cadr form)
 569		(##core#undefined)
 570		(##core#begin ,@(cddr form))))))
 571
 572(##sys#extend-macro-environment
 573 'set!-values '()
 574 (##sys#er-transformer
 575  (lambda (form r c)
 576    (##sys#check-syntax 'set!-values form '(_ lambda-list _))
 577    (##sys#expand-multiple-values-assignment (cadr form) (caddr form)))))
 578
 579(set! chicken.syntax#define-values-definition
 580  (##sys#extend-macro-environment
 581   'define-values '()
 582   (##sys#er-transformer
 583    (lambda (form r c)
 584      (##sys#check-syntax 'define-values form '(_ lambda-list _))
 585      `(##core#begin
 586	,@(##sys#decompose-lambda-list
 587	   (cadr form)
 588	   (lambda (vars argc rest)
 589	     (for-each (lambda (nm)
 590			 (let ((name (##sys#get nm '##core#macro-alias nm)))
 591			   (##sys#register-export name (##sys#current-module))))
 592		       vars)
 593	     (map (lambda (nm) `(##core#ensure-toplevel-definition ,nm))
 594		  vars)))
 595	,(##sys#expand-multiple-values-assignment (cadr form) (caddr form)))))))
 596
 597(##sys#extend-macro-environment
 598 'let-values '()
 599 (##sys#er-transformer
 600  (lambda (form r c)
 601    (##sys#check-syntax 'let-values form '(_ list . _))
 602    (let ((vbindings (cadr form))
 603	  (body (cddr form)))
 604      (letrec ((append* (lambda (il l)
 605			  (if (not (pair? il))
 606			      (cons il l)
 607			      (cons (car il)
 608				    (append* (cdr il) l)))))
 609	       (map* (lambda (proc l)
 610		       (cond ((null? l) '())
 611			     ((not (pair? l)) (proc l))
 612			     (else (cons (proc (car l)) (map* proc (cdr l))))))))
 613	(let* ([llists (map car vbindings)]
 614	       [vars (let loop ((llists llists) (acc '()))
 615		       (if (null? llists)
 616			   acc
 617			   (let* ((llist (car llists))
 618				  (new-acc
 619				   (cond ((list? llist) (append llist acc))
 620					 ((pair? llist) (append* llist acc))
 621					 (else (cons llist acc)))))
 622			     (loop (cdr llists) new-acc))))]
 623	       [aliases (map (lambda (v) (cons v (r (gensym v)))) vars)]
 624	       [lookup (lambda (v) (cdr (assq v aliases)))]
 625	       [llists2 (let loop ((llists llists) (acc '()))
 626			  (if (null? llists)
 627			      (reverse acc)
 628			      (let* ((llist (car llists))
 629				     (new-acc
 630				      (cond ((not (pair? llist)) (cons (lookup llist) acc))
 631					    (else (cons (map* lookup llist) acc)))))
 632				(loop (cdr llists) new-acc))))])
 633	  (let fold ([llists llists]
 634		     [exps (map (lambda (x) (cadr x)) vbindings)]
 635		     [llists2 llists2] )
 636	    (cond ((null? llists)
 637		   `(##core#let
 638		     ,(map (lambda (v) (##sys#list v (lookup v))) vars) 
 639		     ,@body) )
 640		  ((and (pair? (car llists2)) (null? (cdar llists2)))
 641		   `(##core#let
 642		     ((,(caar llists2) ,(car exps)))
 643		     ,(fold (cdr llists) (cdr exps) (cdr llists2)) ) )
 644		  (else
 645		   `(##sys#call-with-values
 646		     (##core#lambda () ,(car exps))
 647		     (##core#lambda
 648		      ,(car llists2) 
 649		      ,(fold (cdr llists) (cdr exps) (cdr llists2))) ) ) ) ) ) ) ) ) ) )
 650
 651(##sys#extend-macro-environment
 652 'let*-values '()
 653 (##sys#er-transformer
 654  (lambda (form r c)
 655    (##sys#check-syntax 'let*-values form '(_ list . _))
 656    (let ((vbindings (cadr form))
 657	  (body (cddr form))
 658	  (%let-values (r 'let-values)) )
 659      (let fold ([vbindings vbindings])
 660	(if (null? vbindings)
 661	    `(##core#let () ,@body)
 662	    `(,%let-values (,(car vbindings))
 663			   ,(fold (cdr vbindings))) ) ) ))))
 664
 665;;XXX do we need letrec*-values ?
 666(##sys#extend-macro-environment
 667 'letrec-values '()
 668 (##sys#er-transformer
 669  (lambda (form r c)
 670    (##sys#check-syntax 'letrec-values form '(_ #((lambda-list . _) 0) . _))
 671    (let ((vbindings (cadr form))
 672          (body (cddr form)))
 673      (let ((vars  (map car vbindings))
 674            (exprs (map cadr vbindings)))
 675        `(##core#let
 676          ,(map (lambda (v) (##sys#list v '(##core#undefined)))
 677                (foldl (lambda (l v) ; flatten multi-value formals
 678                         (##sys#append l (##sys#decompose-lambda-list
 679					  v (lambda (a _ _) a))))
 680                       '()
 681                       vars))
 682          ,@(map ##sys#expand-multiple-values-assignment vars exprs)
 683          ,@body))))))
 684
 685(##sys#extend-macro-environment
 686 'letrec*
 687 '()
 688 (##sys#er-transformer
 689  (lambda (x r c)
 690    (##sys#check-syntax 'letrec* x '(_ #((variable _) 0) . #(_ 1)))
 691    (check-for-multiple-bindings (cadr x) x "letrec*")
 692    `(##core#letrec* ,@(cdr x)))))
 693
 694(##sys#extend-macro-environment
 695 'nth-value 
 696 `((list-ref . scheme#list-ref))
 697 (##sys#er-transformer
 698  (lambda (form r c)
 699    (##sys#check-syntax 'nth-value form '(_ _ _))
 700    (let ((v (r 'tmp)))
 701      `(##sys#call-with-values
 702	(##core#lambda () ,(caddr form))
 703	(##core#lambda ,v (,(r 'list-ref) ,v ,(cadr form))))))))
 704
 705(##sys#extend-macro-environment
 706 'define-inline '()
 707 (##sys#er-transformer
 708  (lambda (form r c)
 709    (letrec ([quotify-proc 
 710	      (lambda (xs id)
 711		(##sys#check-syntax id xs '#(_ 1))
 712		(let* ([head (car xs)]
 713		       [name (if (pair? head) (car head) head)]
 714		       [val (if (pair? head)
 715				`(##core#lambda ,(cdr head) ,@(cdr xs))
 716				(cadr xs) ) ] )
 717		  (when (or (not (pair? val)) 
 718			    (and (not (eq? '##core#lambda (car val)))
 719				 (not (c (r 'lambda) (car val)))))
 720		    (##sys#syntax-error
 721		     'define-inline "invalid substitution form - must be lambda"
 722		     name val) )
 723		  (list name val) ) ) ] )
 724      `(##core#define-inline ,@(quotify-proc (cdr form) 'define-inline)))) ) )
 725
 726(##sys#extend-macro-environment
 727 'and-let* '()
 728 (##sys#er-transformer
 729  (lambda (form r c)
 730    (##sys#check-syntax 'and-let* form '(_ #(_ 0) . _))
 731    (let ((bindings (cadr form))
 732	  (body (cddr form)))
 733      (let fold ([bs bindings] [last #t])
 734	(if (null? bs)
 735	    `(##core#begin ,last . ,body)
 736	    (let ([b (car bs)]
 737		  [bs2 (cdr bs)] )
 738	      (cond [(not (pair? b))
 739                     (##sys#check-syntax 'and-let* b 'variable)
 740                     (let ((var (r (gensym))))
 741                       `(##core#let ((,var ,b))
 742                          (##core#if ,var ,(fold bs2 var) #f)))]
 743		    [(null? (cdr b))
 744                     (let ((var (r (gensym))))
 745                       `(##core#let ((,var ,(car b)))
 746                          (##core#if ,var ,(fold bs2 var) #f)))]
 747		    [else
 748		     (##sys#check-syntax 'and-let* b '(variable _))
 749		     (let ((var (car b)))
 750		       `(##core#let ((,var ,(cadr b)))
 751			 (##core#if ,var ,(fold bs2 var) #f)))]))))))))
 752
 753
 754
 755;;; Optional argument handling:
 756
 757;;; Copyright (C) 1996 by Olin Shivers.
 758;;;
 759;;; This file defines three macros for parsing optional arguments to procs:
 760;;; 	(LET-OPTIONALS  arg-list ((var1 default1) ...) . body)
 761;;; 	(LET-OPTIONALS* arg-list ((var1 default1) ...) . body)
 762;;; 	(:OPTIONAL rest-arg default-exp)
 763;;;
 764;;; The LET-OPTIONALS macro is defined using the Clinger/Rees
 765;;; explicit-renaming low-level macro system. You'll have to do some work to
 766;;; port it to another macro system.
 767;;;
 768;;; The LET-OPTIONALS* and :OPTIONAL macros are defined with simple
 769;;; high-level macros, and should be portable to any R4RS system.
 770;;;
 771;;; These macros are all careful to evaluate their default forms *only* if
 772;;; their values are needed.
 773;;;
 774;;; The only non-R4RS dependencies in the macros are ERROR 
 775;;; and CALL-WITH-VALUES.
 776;;; 	-Olin
 777
 778;;; (LET-OPTIONALS arg-list ((var1 default1) ...) 
 779;;;   body
 780;;;   ...)
 781;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 782;;; This form is for binding a procedure's optional arguments to either
 783;;; the passed-in values or a default.
 784;;;
 785;;; The expression takes a rest list ARG-LIST and binds the VARi to
 786;;; the elements of the rest list. When there are no more elements, then
 787;;; the remaining VARi are bound to their corresponding DEFAULTi values.
 788;;;
 789;;; - The default expressions are *not* evaluated unless needed.
 790;;;
 791;;; - When evaluated, the default expressions are carried out in the *outer*
 792;;;   environment. That is, the DEFAULTi forms do *not* see any of the VARi
 793;;;   bindings.
 794;;;
 795;;;   I originally wanted to have the DEFAULTi forms get eval'd in a LET*
 796;;;   style scope -- DEFAULT3 would see VAR1 and VAR2, etc. But this is
 797;;;   impossible to implement without side effects or redundant conditional
 798;;;   tests. If I drop this requirement, I can use the efficient expansion
 799;;;   shown below. If you need LET* scope, use the less-efficient 
 800;;;   LET-OPTIONALS* form defined below.
 801;;;
 802;;; Example:
 803;;; (define (read-string! str . maybe-args)
 804;;;   (let-optionals maybe-args ((port (current-input-port))
 805;;;                              (start 0)
 806;;;                              (end (string-length str)))
 807;;;     ...))
 808;;;
 809;;; expands to:
 810;;; 
 811;;; (let* ((body (lambda (port start end) ...))
 812;;;        (end-def (lambda (%port %start) (body %port %start <end-default>)))
 813;;;        (start-def (lambda (%port) (end-def %port <start-default>)))
 814;;;        (port-def  (lambda () (start-def <port-def>))))
 815;;;   (if (null? rest) (port-def)
 816;;;       (let ((%port (car rest))
 817;;; 	        (rest (cdr rest)))
 818;;; 	  (if (null? rest) (start-def %port)
 819;;; 	      (let ((%start (car rest))
 820;;; 		    (rest (cdr rest)))
 821;;; 	        (if (null? rest) (end-def %port %start)
 822;;; 		    (let ((%end (car rest))
 823;;; 			  (rest (cdr rest)))
 824;;; 		      (if (null? rest) (body %port %start %end)
 825;;; 			  (error ...)))))))))
 826
 827
 828;;; (LET-OPTIONALS args ((var1 default1) ...) body1 ...)
 829
 830(##sys#extend-macro-environment
 831 'let-optionals 
 832 `((null? . scheme#null?)
 833   (car . scheme#car)
 834   (cdr . scheme#cdr))
 835 (##sys#er-transformer
 836  (lambda (form r c)
 837    (##sys#check-syntax 'let-optionals form '(_ _ . _))
 838    (let ((arg-list (cadr form))
 839	  (var/defs (caddr form))
 840	  (body (cdddr form)))
 841
 842      ;; This guy makes the END-DEF, START-DEF, PORT-DEF definitions above.
 843      ;; I wish I had a reasonable loop macro.
 844
 845      (define (make-default-procs vars body-proc defaulter-names defs rename)
 846	(let recur ((vars (reverse vars))
 847		    (defaulter-names (reverse defaulter-names))
 848		    (defs (reverse defs))
 849		    (next-guy body-proc))
 850	  (if (null? vars) '()
 851	      (let ((vars (cdr vars)))
 852		`((,(car defaulter-names)
 853		   (##core#lambda ,(reverse vars)
 854			     (,next-guy ,@(reverse vars) ,(car defs))))
 855		  . ,(recur vars
 856			    (cdr defaulter-names)
 857			    (cdr defs)
 858			    (car defaulter-names)))))))
 859
 860
 861      ;; This guy makes the (IF (NULL? REST) (PORT-DEF) ...) tree above.
 862
 863      (define (make-if-tree vars defaulters body-proc rest rename)
 864	(let recur ((vars vars) (defaulters defaulters) (non-defaults '()))
 865	  (if (null? vars)
 866	      `(,body-proc . ,(reverse non-defaults))
 867	      (let ((v (car vars)))
 868		`(##core#if (,(r 'null?) ,rest)
 869		       (,(car defaulters) . ,(reverse non-defaults))
 870		       (##core#let ((,v (,(r 'car) ,rest)) ; we use car/cdr, because of rest-list optimization
 871			       (,rest (,(r 'cdr) ,rest)))
 872			      ,(recur (cdr vars)
 873				      (cdr defaulters)
 874				      (cons v non-defaults))))))))
 875
 876      (##sys#check-syntax 'let-optionals var/defs '#((variable _) 0))
 877      (##sys#check-syntax 'let-optionals body '#(_ 1))
 878      (let* ((vars (map car var/defs))
 879	     (prefix-sym (lambda (prefix sym)
 880			   (string->symbol (string-append prefix (symbol->string sym)))))
 881
 882	     ;; Private vars, one for each user var.
 883	     ;; We prefix the % to help keep macro-expanded code from being
 884	     ;; too confusing.
 885	     (vars2 (map (lambda (v) (r (prefix-sym "%" v)))
 886			 vars))
 887
 888	     (defs (map cadr var/defs))
 889	     (body-proc (r 'body))
 890
 891	     ;; A private var, bound to the value of the ARG-LIST expression.
 892	     (rest-var (r '_%rest))
 893
 894	     (defaulter-names (map (lambda (var) (r (prefix-sym "def-" var)))
 895				   vars))
 896
 897	     (defaulters (make-default-procs vars2 body-proc
 898					     defaulter-names defs gensym))
 899	     (if-tree (make-if-tree vars2 defaulter-names body-proc
 900				    rest-var gensym)))
 901
 902	`(,(r 'let*) ((,rest-var ,arg-list)
 903		      (,body-proc (##core#lambda ,vars . ,body))
 904		      . ,defaulters)
 905	  ,if-tree) ) ))))
 906
 907
 908;;; (optional rest-arg default-exp)
 909;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 910;;; This form is for evaluating optional arguments and their defaults
 911;;; in simple procedures that take a *single* optional argument. It is
 912;;; a macro so that the default will not be computed unless it is needed.
 913;;; 
 914;;; REST-ARG is a rest list from a lambda -- e.g., R in
 915;;;     (lambda (a b . r) ...)
 916;;; - If REST-ARG has 0 elements, evaluate DEFAULT-EXP and return that.
 917;;; - If REST-ARG has 1 element, return that element.
 918
 919(##sys#extend-macro-environment
 920 'optional 
 921 `((null? . scheme#null?)
 922   (car . scheme#car)
 923   (cdr . scheme#cdr) )
 924 (##sys#er-transformer
 925  (lambda (form r c)
 926    (##sys#check-syntax 'optional form '(_ _ . #(_ 0 1)))
 927    (let ((var (r 'tmp)))
 928      `(##core#let ((,var ,(cadr form)))
 929	(##core#if (,(r 'null?) ,var) 
 930		   ,(optional (cddr form) #f)
 931		   (,(r 'car) ,var)))))))
 932
 933
 934;;; (LET-OPTIONALS* args ((var1 default1) ... [rest]) body1 ...)
 935;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 936;;; This is just like LET-OPTIONALS, except that the DEFAULTi forms
 937;;; are evaluated in a LET*-style environment. That is, DEFAULT3 is evaluated
 938;;; within the scope of VAR1 and VAR2, and so forth.
 939;;;
 940;;; - If the last form in the ((var1 default1) ...) list is not a 
 941;;;   (VARi DEFAULTi) pair, but a simple variable REST, then it is
 942;;;   bound to any left-over values. For example, if we have VAR1 through
 943;;;   VAR7, and ARGS has 9 values, then REST will be bound to the list of
 944;;;   the two values of ARGS. If ARGS is too short, causing defaults to
 945;;;   be used, then REST is bound to '().
 946
 947(##sys#extend-macro-environment
 948 'let-optionals* 
 949 `((null? . scheme#null?)
 950   (car . scheme#car)
 951   (cdr . scheme#cdr))
 952 (##sys#er-transformer
 953  (lambda (form r c)
 954    (##sys#check-syntax 'let-optionals* form '(_ _ list . _))
 955    (let ((args (cadr form))
 956	  (var/defs (caddr form))
 957	  (body (cdddr form))
 958	  (%null? (r 'null?))
 959	  (%car (r 'car))
 960	  (%cdr (r 'cdr)))
 961      (let ((rvar (r 'tmp)))
 962	`(##core#let
 963	  ((,rvar ,args))
 964	  ,(let loop ((args rvar) (vardefs var/defs))
 965	     (if (null? vardefs)
 966		 `(##core#let () ,@body)
 967		 (let ((head (car vardefs)))
 968		   (if (pair? head)
 969		       (let ((rvar2 (r 'tmp2)))
 970			 `(##core#let ((,(car head) (##core#if (,%null? ,args)
 971							       ,(cadr head)
 972							       (,%car ,args)))
 973				       (,rvar2 (##core#if (,%null? ,args) 
 974							  (##core#quote ())
 975							  (,%cdr ,args))) )
 976				      ,(loop rvar2 (cdr vardefs)) ) )
 977		       `(##core#let ((,head ,args)) ,@body) ) ) ) ) ) ) ))))
 978
 979;;; SRFI-9:
 980
 981(##sys#extend-macro-environment
 982 'define-record-type
 983 `()
 984 (##sys#er-transformer
 985  (lambda (form r c)
 986    (##sys#check-syntax 
 987     'define-record-type 
 988     form
 989     '(_ variable #(variable 1) variable . _)) 
 990    (let* ((type-name (cadr form))
 991	   (plain-name (strip-syntax type-name))
 992	   (tag (if (##sys#current-module)
 993		    (symbol-append
 994		     (##sys#module-name (##sys#current-module))
 995		     '|#| plain-name)
 996		    plain-name))
 997	   (conser (caddr form))
 998	   (pred (cadddr form))
 999	   (slots (cddddr form))
 1000	   (%define (r 'define))
1001           (%vector (r 'vector))
1002           (%let (r 'let))
1003           (%tagvar (r 'tag))
1004	   (%getter-with-setter (r 'chicken.base#getter-with-setter))
1005	   (vars (cdr conser))
1006	   (x (r 'x))
1007	   (y (r 'y))
1008	   (slotnames (map car slots)))
1009      ;; Check for inconsistencies in slot names vs constructor args
1010      (for-each (lambda (vname)
1011		  (unless (memq vname slotnames)
1012		    (##sys#syntax-error
1013		     'define-record-type
1014		     "unknown slot name in constructor definition"
1015		     vname)))
1016		vars)
1017      `(##core#begin
1018	(,%define ,type-name (,%vector (##core#quote ,tag)))
1019	(,%define ,(car conser)
1020           (,%let ((,%tagvar ,type-name))
1021                  (##core#lambda ,(cdr conser)
1022                                 (##sys#make-structure 
1023                                                       ,%tagvar
1024                                                       ,@(map (lambda (sname)
1025                                                                (if (memq sname vars)
1026                                                                    sname
1027                                                                    '(##core#undefined) ) )
1028                                                           slotnames) ) ) ))
1029	(,%define ,pred
1030           (,%let ((,%tagvar ,type-name))
1031                  (##core#lambda (,x)
1032                                 (##sys#structure? ,x ,%tagvar))))
1033	,@(let loop ((slots slots) (i 1))
1034	    (if (null? slots)
1035		'()
1036		(let* ((slot (car slots))
1037		       (settable (pair? (cddr slot))) 
1038		       (setr (and settable (caddr slot)))
1039		       (ssetter (and (pair? setr)
1040				     (pair? (cdr setr))
1041				     (c 'setter (car setr))
1042				     (cadr setr)))
1043		       (get `(##core#lambda 
1044			      (,x)
1045			      (##core#check
1046			       (##sys#check-structure
1047				,x
1048				,%tagvar
1049				(##core#quote ,(cadr slot))))
1050			      (##sys#block-ref ,x ,i) ) )
1051		       (set (and settable
1052				 `(##core#lambda
1053				   (,x ,y)
1054				   (##core#check
1055				    (##sys#check-structure
1056				     ,x
1057				     ,%tagvar
1058				     (##core#quote ,ssetter)))
1059				   (##sys#block-set! ,x ,i ,y)) )))
1060		  `((,%define
1061		     ,(cadr slot)
1062                     (,%let ((,%tagvar ,type-name))
1063                            ,(if (and ssetter (c ssetter (cadr slot)))
1064                                 `(,%getter-with-setter ,get ,set)
1065                                 get)))
1066		    ,@(if settable
1067			  (if ssetter
1068			      (if (not (c ssetter (cadr slot)))
1069				  `((,%let ((,%tagvar ,type-name))
1070                                       ((##sys#setter ##sys#setter) ,ssetter ,set)))
1071				  '())
1072			      `((,%define ,setr (,%let ((,%tagvar ,type-name)) ,set))))
1073			  '())
1074		    ,@(loop (cdr slots) (add1 i)) ) ) ) ) ) ) ) ) )
1075
1076
1077;;; SRFI-26:
1078
1079(##sys#extend-macro-environment
1080 'cut 
1081 `((apply . scheme#apply))
1082 (##sys#er-transformer
1083  (lambda (form r c)
1084    (let ((%<> (r '<>))
1085	  (%<...> (r '<...>))
1086	  (%apply (r 'apply)))
1087      (when (null? (cdr form))
1088        (##sys#syntax-error 'cut "you need to supply at least a procedure" form))
1089      (let loop ([xs (cdr form)] [vars '()] [vals '()] [rest #f])
1090	(if (null? xs)
1091	    (let ([rvars (reverse vars)]
1092		  [rvals (reverse vals)] )
1093	      (if rest
1094		  (let ([rv (r (gensym))])
1095		    `(##core#lambda
1096		      (,@rvars . ,rv)
1097		      (,%apply ,(car rvals) ,@(cdr rvals) ,rv) ) )
1098		  ;;XXX should we drop the begin?
1099		  `(##core#lambda ,rvars ((##core#begin ,(car rvals)) ,@(cdr rvals)) ) ) )
1100	    (cond ((c %<> (car xs))
1101		   (let ([v (r (gensym))])
1102		     (loop (cdr xs) (cons v vars) (cons v vals) #f) ) )
1103		  ((c %<...> (car xs))
1104		   (if (null? (cdr xs))
1105		       (loop '() vars vals #t)
1106		       (##sys#syntax-error
1107			'cut
1108			"tail patterns after <...> are not supported"
1109			form)))
1110		  (else (loop (cdr xs) vars (cons (car xs) vals) #f)) ) ) ) ) )))
1111
1112(##sys#extend-macro-environment
1113 'cute 
1114 `((apply . scheme#apply))
1115 (##sys#er-transformer
1116  (lambda (form r c)
1117    (let ((%apply (r 'apply))
1118	  (%<> (r '<>))
1119	  (%<...> (r '<...>)))
1120      (when (null? (cdr form))
1121        (##sys#syntax-error 'cute "you need to supply at least a procedure" form))
1122      (let loop ([xs (cdr form)] [vars '()] [bs '()] [vals '()] [rest #f])
1123	(if (null? xs)
1124	    (let ([rvars (reverse vars)]
1125		  [rvals (reverse vals)] )
1126	      (if rest
1127		  (let ([rv (r (gensym))])
1128		    `(##core#let 
1129		      ,bs
1130		      (##core#lambda (,@rvars . ,rv)
1131				(,%apply ,(car rvals) ,@(cdr rvals) ,rv) ) ) )
1132		  `(##core#let ,bs
1133			  (##core#lambda ,rvars (,(car rvals) ,@(cdr rvals)) ) ) ) )
1134	    (cond ((c %<> (car xs))
1135		   (let ([v (r (gensym))])
1136		     (loop (cdr xs) (cons v vars) bs (cons v vals) #f) ) )
1137		  ((c %<...> (car xs))
1138		   (if (null? (cdr xs))
1139		       (loop '() vars bs vals #t)
1140		       (##sys#syntax-error
1141			'cute
1142			"tail patterns after <...> are not supported"
1143			form)))
1144		  (else 
1145		   (let ([v (r (gensym))])
1146		     (loop (cdr xs) 
1147			   vars
1148			   (cons (list v (car xs)) bs)
1149			   (cons v vals) #f) ) ))))))))
1150
1151
1152;;; SRFI-31
1153
1154(##sys#extend-macro-environment
1155 'rec '()
1156 (##sys#er-transformer
1157  (lambda (form r c)
1158    (##sys#check-syntax 'rec form '(_ _ . _))
1159    (let ((head (cadr form)))
1160      (if (pair? head)
1161	  `(##core#letrec* ((,(car head) 
1162			     (##core#lambda ,(cdr head)
1163					    ,@(cddr form))))
1164			   ,(car head))
1165	  `(##core#letrec* ((,head ,@(cddr form))) ,head))))))
1166
1167
1168;;; SRFI-55
1169
1170(##sys#extend-macro-environment
1171 'require-extension
1172 '()
1173 (##sys#er-transformer
1174  (lambda (x r c)
1175    `(,(r 'import) ,@(cdr x)))))
1176
1177
1178;;; Assertions
1179
1180(##sys#extend-macro-environment
1181 'assert '()
1182 (##sys#er-transformer
1183  (let ((string-append string-append))
1184    (lambda (form r c)
1185      (##sys#check-syntax 'assert form '#(_ 1))
1186      (let* ((exp (cadr form))
1187	     (msg-and-args (cddr form))
1188	     (msg (optional msg-and-args "assertion failed"))
1189	     (tmp (r 'tmp)))
1190	(when (string? msg)
1191	  (and-let* ((ln (get-line-number form)))
1192	    (set! msg (string-append "(" ln ") " msg))))
1193	`(##core#let ((,tmp ,exp))
1194	   (##core#if (##core#check ,tmp)
1195		      ,tmp
1196		      (##sys#error
1197		       ,msg
1198		       ,@(if (pair? msg-and-args)
1199			     (cdr msg-and-args)
1200			     `((##core#quote ,(strip-syntax exp))))))))))))
1201
1202;; R7RS guard & guard-aux copied verbatim from the draft.
1203(##sys#extend-macro-environment
1204  'guard '()
1205  (##sys#er-transformer
1206    (lambda (form r c)
1207      (let ((%=> (r '=>))
1208            (%else (r 'else))
1209            (%begin (r 'begin))
1210            (%let (r 'let))
1211            (%if (r 'if))
1212            (%or (r 'or))
1213            (%var (r 'var))
1214            (%apply (r 'apply))
1215            (%values (r 'values))
1216            (%condition (r 'condition))
1217            (%call-with-values (r 'call-with-values))
1218            (%guard-k (r 'guard-k))
1219            (%handler-k (r 'handler-k))
1220            (%lambda (r 'lambda)))
1221        (##sys#check-syntax 'guard form '(_ (variable . #(_ 1)) . #(_ 1)))
1222        (let ((var (caadr form))
1223              (clauses (cdadr form))
1224              (es (cddr form)))
1225          (define (guard-aux reraise body more)
1226            (cond ((and (pair? body) (c %else (car body))
1227                        (null? more))
1228                   `(,%begin ,@(cdr body)))
1229                  ((and (pair? body) (pair? (cdr body)) (pair? (cddr body))
1230                        (c %=> (cadr body)))
1231                   (let ((%temp (r 'temp)))
1232                     `(,%let ((,%temp ,(car body)))
1233                             (,%if ,%temp 
1234                                   (,(caddr body) ,%temp)
1235                                   ,(if (null? more)
1236                                        reraise
1237                                        (guard-aux reraise (car more) (cdr more)))))))
1238                  ((and (pair? body) (null? (cdr body)))
1239                   (if (null? more)
1240                       `(,%or ,(car body) ,reraise)
1241                       (let ((%temp (r 'temp)))
1242                         `(,%let ((,%temp ,(car body)))
1243                                 (,%if ,%temp
1244                                       ,%temp
1245                                       ,(guard-aux reraise (car more) (cdr more)))))))
1246                  ((and (pair? body) (pair? (cdr body)))
1247                   `(,%if ,(car body)
1248                          (,%begin ,@(cdr body))
1249                          ,(if (null? more)
1250                               reraise
1251                               (guard-aux reraise (car more) (cdr more)))))))
1252          `((scheme#call-with-current-continuation
1253              (,%lambda (,%guard-k)
1254                (scheme#with-exception-handler
1255                  (,%lambda (,%condition)
1256                    ((scheme#call-with-current-continuation
1257                       (,%lambda (,%handler-k)
1258                         (,%guard-k
1259                           (,%lambda ()
1260                             (,%let ((,var ,%condition))
1261                                ,(guard-aux
1262                                  `(,%handler-k
1263                                     (,%lambda ()
1264                                       (scheme#raise-continuable ,%condition)))
1265                                   (car clauses) (cdr clauses)))))))))
1266                  (,%lambda ()
1267                    (scheme#call-with-values
1268                      (,%lambda () ,@es)
1269                      (,%lambda args
1270                        (,%guard-k
1271                           (,%lambda ()
1272                              (,%apply ,%values args)))))))))))))))
1273
1274(macro-subset me0 ##sys#default-macro-environment)))
1275
1276
1277;;; "time"
1278
1279(set! ##sys#chicken.time-macro-environment
1280  (let ((me0 (##sys#macro-environment)))
1281
1282(##sys#extend-macro-environment
1283 'time '()
1284 (##sys#er-transformer
1285  (lambda (form r c)
1286    (let ((rvar (r 't)))
1287      `(##core#begin
1288	(##sys#start-timer)
1289	(##sys#call-with-values
1290	 (##core#lambda () ,@(cdr form))
1291	 (##core#lambda
1292	  ,rvar
1293	  (##sys#display-times (##sys#stop-timer))
1294	  (##sys#apply ##sys#values ,rvar))))))))
1295
1296(macro-subset me0 ##sys#default-macro-environment)))
1297
1298;;; case-lambda (SRFI-16):
1299
1300(set! ##sys#scheme.case-lambda-macro-environment
1301  (let ((me0 (##sys#macro-environment)))
1302
1303(##sys#extend-macro-environment
1304 'case-lambda 
1305 `((>= . scheme#>=)
1306   (car . scheme#car)
1307   (cdr . scheme#cdr)
1308   (eq? . scheme#eq?)
1309   (length . scheme#length))
1310 (##sys#er-transformer
1311  (lambda (form r c)
1312    (##sys#check-syntax 'case-lambda form '(_ . _))
1313    (define (genvars n)
1314      (let loop ([i 0])
1315	(if (fx>= i n)
1316	    '()
1317	    (cons (r (gensym)) (loop (fx+ i 1))) ) ) )
1318    (let* ((mincount (apply min (map (lambda (c)
1319				       (##sys#decompose-lambda-list 
1320					(car c)
1321					(lambda (vars argc rest) argc) ) )
1322				     (cdr form))))
1323	   (minvars (genvars mincount))
1324	   (rvar (r 'rvar))
1325	   (lvar (r 'lvar))
1326	   (%>= (r '>=))
1327	   (%eq? (r 'eq?))
1328	   (%car (r 'car))
1329	   (%cdr (r 'cdr))
1330	   (%length (r 'length)))
1331      `(##core#lambda
1332	,(append minvars rvar)
1333	(##core#let
1334        ((,lvar (,%length ,rvar)))
1335	 ,(foldr
1336	   (lambda (c body)
1337	     (##sys#decompose-lambda-list
1338	      (car c)
1339	      (lambda (vars argc rest)
1340		(##sys#check-syntax 'case-lambda (car c) 'lambda-list)
1341		`(##core#if ,(let ((a2 (fx- argc mincount)))
1342			       (if rest
1343				   (if (zero? a2)
1344				       #t
1345				       `(,%>= ,lvar ,a2) )
1346				   `(,%eq? ,lvar ,a2) ) )
1347			    ,(receive (vars1 vars2)
1348				 (split-at (take vars argc) mincount)
1349			       (let ((bindings
1350				      (let build ((vars2 vars2) (vrest rvar))
1351					(if (null? vars2)
1352					    (cond (rest `(##core#let ((,rest ,vrest)) ,@(cdr c)))
1353						  ((null? (cddr c)) (cadr c))
1354						  (else `(##core#let () ,@(cdr c))) )
1355					    (let ((vrest2 (r (gensym))))
1356					      `(##core#let ((,(car vars2) (,%car ,vrest))
1357							    (,vrest2 (,%cdr ,vrest)) )
1358							   ,(if (pair? (cdr vars2))
1359								(build (cdr vars2) vrest2)
1360								(build '() vrest2) ) ) ) ) ) ) )
1361				 (if (null? vars1)
1362				     bindings
1363				     `(##core#let ,(map list vars1 minvars) ,bindings) ) ) )
1364			    ,body) ) ) )
1365	   '(##core#check (##sys#error (##core#immutable (##core#quote "no matching clause in call to 'case-lambda' form"))))
1366	   (cdr form))))))))
1367
1368(macro-subset me0 ##sys#default-macro-environment)))
1369
1370;; register features
1371
1372(register-feature! 'srfi-2 'srfi-8 'srfi-9 'srfi-11 'srfi-15 'srfi-16 'srfi-26 'srfi-31 'srfi-55)
Trap