~ chicken-core (chicken-5) /tests/dirty-macros.scm


   1; How to write dirty R5RS macros
   2; http://groups.google.com/groups?selm=87oflzcdwt.fsf%40radish.petrofsky.org
   3; How to write seemingly unhygienic macros using syntax-rules 
   4; Date: 2001-11-19 01:23:33 PST 
   5;
   6; $Id: dirty-macros.scm,v 1.10 2003/08/16 02:13:32 oleg Exp oleg $
   7
   8; Extract a colored identifier from a form
   9;    extract? SYMB BODY CONT-T CONT-F
  10; BODY is a form that may contain an occurence of an identifier that
  11; refers to the same binding occurrence as SYMB, perhaps with a different
  12; color. CONT-T and CONT-F are forms of the shape (K-HEAD K-IDL . K-ARGS)
  13; where K-IDL are K-ARGS are lists.
  14; If the extract? macro finds the identifier in question, it expands into
  15; CONT-T, to be more precise, into
  16;   (K-HEAD (extr-id . K-IDL) . K-ARGS)
  17; where extr-id is the extracted colored identifier. If the identifier
  18; SYMB does not occur in BODY at all, the extract macro expands into CONT-F,
  19; to be more precise,
  20;   (K-HEAD (SYMB . K-IDL) . K-ARGS)
  21
  22(define-syntax m-symbol?
  23  (syntax-rules ()
  24    ((_ maybe-symbol kt kf)
  25     (letrec-syntax
  26       ((ok
  27	  (syntax-rules ()
  28	    ((_) kt)))
  29	 (test
  30	  (syntax-rules ()
  31	    ((_ maybe-symbol) (ok))
  32	    ((_ x) kf))))
  33       (test abracadabra)))))
  34
  35(define-syntax m-symb-equal?
  36  (syntax-rules ()
  37    ((_ symb b kt kf)
  38	(let-syntax
  39	  ((symb (syntax-rules ()
  40		   ((_) kf)))
  41	   (ok (syntax-rules ()
  42		   ((_) kt))))
  43	  (let-syntax
  44	    ((test (syntax-rules ()
  45		     ((_ b) (symb))
  46		     ((_ x) kf))))
  47	    (test ok))))))
  48
  49(define-syntax extract?
  50  (syntax-rules ()
  51    ((_ symb body _cont-t _cont-f)
  52      (letrec-syntax
  53	((lp
  54           (syntax-rules (symb)
  55	      ((_ d symb stack (cont-head symb-l . cont-args) cont-f)
  56	       (cont-head (d . symb-l) . cont-args)) ; symb has occurred
  57	      ((_ d (x . y) stack . rest)   ; if body is a composite form,
  58	       (lp x x (y . stack) . rest)) ; look inside
  59	      ((_ d1 d2 () cont-t (cont-head  symb-l . cont-args))
  60	       (cont-head (symb . symb-l) . cont-args)) ; symb does not occur
  61	      ((_ d1 d2 (x . y) . rest)
  62	       (lp x x y . rest)))))
  63	(lp body body () _cont-t _cont-f)))))
  64
  65; (define-syntax extract?
  66;   (syntax-rules ()
  67;     ((_ symb body _cont-t _cont-f)
  68;       (letrec-syntax
  69; 	((tr
  70;            (syntax-rules ()
  71; 	      ((_ d (x . y) tail . rest)   ; if body is a composite form,
  72; 	       (tr x x (y . tail) . rest)) ; look inside
  73; 	      ((_ x y () (cont-head symb-l . cont-args) 
  74; 		 (cont-headf symb-lf . cont-argsf))
  75; 	       (m-symb-equal? symb y 
  76; 		 (cont-head (x . symb-l) . cont-args) ; symb has occurred
  77; 	       (cont-headf (symb . symb-lf) . cont-argsf)));symb does not occur
  78; 	     ((_ d1 d2 (x . y) (cont-head symb-l . cont-args) cont-f) 
  79; 	       (m-symb-equal? symb d2
  80; 		 (cont-head (d1 . symb-l) . cont-args) ; symb has occurred
  81; 		 (tr x x y (cont-head symb-l . cont-args) cont-f))))))
  82; 	(tr body body () _cont-t _cont-f)))))
  83
  84; Extract a colored identifier from a form
  85;    extract SYMB BODY CONT
  86; BODY is a form that may contain an occurence of an identifier that
  87; refers to the same binding occurrence as SYMB, perhaps with a different
  88; color. CONT is a form of the shape (K-HEAD K-IDL . K-ARGS)
  89; where K-IDL are K-ARGS are S-expressions representing lists or the
  90; empty list.
  91; The extract macro expands into
  92;   (K-HEAD (extr-id . K-IDL) . K-ARGS)
  93; where extr-id is the extracted colored identifier. If symbol SYMB does
  94; not occur in BODY at all, extr-id is identical to SYMB.
  95
  96
  97(define-syntax extract
  98  (syntax-rules ()
  99    ((_ symb body cont)
 100     (extract? symb body cont cont))))
 101
 102; Extract several colored identifiers from a form
 103;    extract* SYMB-L BODY CONT
 104; where SYMB-L is the list of symbols to extract, and BODY and CONT
 105; has the same meaning as in extract, see above.
 106; 
 107; The extract* macro expands into
 108;   (K-HEAD (extr-id-l . K-IDL) . K-ARGS)
 109; where extr-id-l is the list of extracted colored identifiers. The extraction
 110; itself is performed by the macro extract.
 111
 112(define-syntax extract*
 113  (syntax-rules ()
 114    ((_ (symb) body cont)      ; only one symbol: use extract to do the job
 115     (extract symb body cont))
 116    ((_ _symbs _body _cont)
 117     (letrec-syntax
 118	 ((ex-aux		; extract symbol-by-symbol
 119	   (syntax-rules ()
 120	     ((_ found-symbs () body cont)
 121	      (reverse () found-symbs cont))
 122	     ((_ found-symbs (symb . symb-others) body cont)
 123	      (extract symb body
 124		       (ex-aux found-symbs symb-others body cont)))
 125	     ))
 126	  (reverse		; reverse the list of extracted symbols
 127	   (syntax-rules ()     ; to match the order of SYMB-L
 128	     ((_ res () (cont-head () . cont-args))
 129	      (cont-head res . cont-args))
 130	     ((_ res (x . tail) cont)
 131	      (reverse (x . res) tail cont)))))
 132       (ex-aux () _symbs _body _cont)))))
 133
 134; Writing weakly referentially opaque macros
 135
 136; A binding-capturing macro with an explicit specification
 137; of the captured variable
 138(define-syntax m1-i
 139  (syntax-rules ()
 140    ((_ i val body) (let ((i val)) body))))
 141
 142(display
 143   (m1-i i 10 (* 1 i)))
 144(newline) ;==> 10
 145
 146; A dirty macro m1 that extracts i from its argument and expands
 147; into an invocation of m1-i:
 148
 149(define-syntax m1-dirty-v1
 150  (syntax-rules ()
 151    ((_ _val _body)
 152     (let-syntax
 153	 ((cont
 154	   (syntax-rules ()
 155	     ((_ (symb) val body) (let ((symb val)) body) ))))
 156       (extract i _body (cont () _val _body))))))
 157
 158(display
 159   (m1-dirty-v1 10 (* 1 i))
 160)
 161(newline)
 162
 163(display
 164   (m1-dirty-v1 10
 165     (m1-dirty-v1 20 (* 1 i)))
 166)
 167(newline)
 168
 169
 170; A macro that re-defines itself in its expansion
 171;  m1-dirty-v2 val body
 172; expands into
 173; (let ((i val)) body)
 174; and also re-defines itself in the scope of body.
 175
 176(define-syntax m1-dirty-v2
 177  (syntax-rules ()
 178    ((_ _val _body)
 179     (letrec-syntax
 180	 ((doit		    ; it's the continuation from extract*
 181	   (syntax-rules () ; myself-symb i-symb are colored ids extracted
 182	     ((_ (myself-symb i-symb) val body)      ; from the 'body'
 183	      (let ((i-symb val))  ; first bind the symbol i
 184		(letrec-syntax	   ; now re-define oneself
 185		    ((myself-symb
 186		      (syntax-rules ()
 187			((_ val__ body__)
 188			 (extract* (myself-symb i-symb) body__
 189				  (doit () val__ body__))))))
 190		  body))))))
 191       (extract* (m1-dirty-v2 i) _body
 192		 (doit () _val _body))))))
 193
 194(display "m1-dirty-v2")
 195(newline)
 196(display
 197   (m1-dirty-v2 10 (* 1 i))
 198)
 199(newline)
 200; => 10
 201
 202(display
 203   (m1-dirty-v2 10
 204     (m1-dirty-v2 20 
 205       (m1-dirty-v2 30 (* 1 i))))
 206)
 207(newline)
 208
 209(display
 210  (let ((i 1))
 211   (m1-dirty-v2 10 (* 1 i)))
 212)
 213(newline)
 214; => 1
 215
 216; A self-perpetuating smearing let
 217;   (mylet ((var init)) body)
 218; expands into
 219;   (let ((var init)) body')
 220; where body' is body wrapped into redefinitions of mylet
 221; and a macro m1-dirty-v3
 222
 223; This macro is closed (no free variables)
 224(define-syntax dirty-m-gen
 225  (syntax-rules ()
 226    ((_ name let-name _symb_ _body_)
 227     (let-syntax
 228	 ((name
 229	   (syntax-rules ()
 230	     ((_ _val _body)
 231	      (let-syntax
 232		  ((cont
 233		    (syntax-rules ()
 234		      ((_ (symb) val body) (let ((symb val)) body) ))))
 235		(extract _symb_ _body (cont () _val _body)))))))
 236       _body_))))
 237
 238; (define-syntax mylet
 239;   (syntax-rules ()
 240;     ((_ ((_var _init)) _body)
 241;      (letrec-syntax
 242; 	 ((doit		    ; it's the continuation from extract*
 243; 	   (syntax-rules () ; myself-symb etc. are extr. colored ids extracted
 244; 	     ((_ (myself-symb dirty-m-symb i-symb) ((var init)) body) 
 245; 	      (let ((var init))     ; first do the binding
 246; 		(letrec-syntax	    ; now re-define oneself
 247; 		    ((myself-symb
 248; 		      (syntax-rules ()
 249; 			((_ ((var__ init__)) body__)
 250; 			 (extract* (myself-symb dirty-m-symb i-symb)
 251; 				   (var__ body__)
 252; 				  (doit () ((var__ init__)) body__))))))
 253; 		  (dirty-m-gen      ; re-generate the dirty macro
 254; 		   dirty-m-symb myself-symb i-symb
 255; 		  body)))))))
 256;        (extract* (mylet m1-dirty-v3 i) (_var _body)
 257; 		 (doit () ((_var _init)) _body))))))
 258
 259;      (letrec-syntax 
 260;        ((ex
 261; 	 (syntax-rules ()
 262; 	   ((_ (mylet-symb mm-symb foo-symb) ((var init)) body)
 263; 	    (let ((var init))
 264; 	      (make-mm mm-symb foo-symb
 265; 		  (letrec-syntax 
 266; 		      ((mylet-symb
 267; 			(syntax-rules ()
 268; 			  ((_ ((var_ init_)) body_)
 269; 		       (extract* (mylet-symb mm-symb foo-symb) (var_ body_)
 270; 				  (ex () ((var_ init_)) body_))))))
 271; 		 body)))
 272; 	    ))))
 273;        (extract* (mylet mm foo) (_var _body)
 274; 		 (ex () ((_var _init)) _body))))))
 275
 276; (display "m1-dirty-v3")
 277; (newline)
 278; (display
 279;  (mylet ((i 1))
 280; 	(m1-dirty-v3 10 (* 1 i)))
 281; )
 282; (newline)
 283
 284; (display
 285;  (mylet ((i 1))
 286; 	(mylet ((i 10))
 287; 		     (m1-dirty-v3 20 (* 1 i))))
 288; )
 289; (newline)
 290
 291; (display
 292;  (mylet ((i 1))
 293; 	(m1-dirty-v3 10
 294; 		     (m1-dirty-v3 20 (* 1 i))))
 295; )
 296; (newline)
 297
 298
 299; A macro that generates a dirty macro:
 300;    m1-dirty BODY
 301; expands into a definition of a macro
 302;    NAME BODY
 303; which in turn expands into (let ((SYMB 10)) BODY) 
 304; such that the binding captures any free occurences of SYMB in BODY.
 305
 306; (define-syntax m1-dirty
 307;   (syntax-rules ()
 308;     ((_ _symb _body)
 309;      (let-syntax
 310; 	 ((doit
 311; 	   (syntax-rules ()
 312; 	     ((_ (symb) val body)
 313; 	      (let ((symb val)) body)))))
 314;        (extract _symb _body (doit () 10 _body))))))
 315
 316; Macro: make-mm NAME SYMB BODY
 317; In the scope of BODY, define a macro NAME that expands into a symbol SYMB
 318
 319(define-syntax make-mm
 320  (syntax-rules ()
 321    ((_ name symb body)
 322      (let-syntax 
 323	 ((name
 324	   (syntax-rules ()
 325	     ((_) symb))))
 326	body))))
 327
 328; (define-syntax mylet
 329;   (syntax-rules (foo)
 330;     ((_ ((var init)) body)
 331; 	(extract foo (var)
 332; 	 (make-mm-in ((var init)) body)))))
 333
 334; (mylet ((var init)) body)
 335; expands into
 336; (let ((var init)) body')
 337; where body' is the body wrapped in the re-definitions of mylet and macro mm.
 338
 339(define-syntax mylet
 340  (syntax-rules ()
 341    ((_ ((_var _init)) _body)
 342     (letrec-syntax 
 343       ((doit			; The continuation from extract*
 344	 (syntax-rules ()       ; mylet-symb, etc. are extracted from body
 345	   ((_ (mylet-symb mm-symb foo-symb) ((var init)) body)
 346	    (let ((var init))	; bind the 'var' first
 347	      (make-mm mm-symb foo-symb  ; now re-generate the macro mm
 348		  (letrec-syntax 
 349		      ((mylet-symb       ; and re-define myself
 350			(syntax-rules ()
 351			  ((_ ((var_ init_)) body_)
 352		       (extract* (mylet-symb mm-symb foo-symb) (var_ body_)
 353				  (doit () ((var_ init_)) body_))))))
 354		 body)))
 355	    ))))
 356       (extract* (mylet mm foo) (_var _body)
 357		 (doit () ((_var _init)) _body))))))
 358
 359(display "mylet")
 360(newline)
 361(define foo 1)
 362(display
 363 (mylet ((x 1)) (list (mm) x))
 364)
 365(newline)
 366
 367(display
 368 (mylet ((foo 2)) (list (mm) foo))
 369)
 370(newline)
 371
 372; ;(let ((foo 3)) (mylet ((foo 4)) (list foo (mm))))
 373;(mylet ((foo 2)) (mylet ((foo 3)) (list foo (mm))))
 374
 375(display
 376 (mylet ((foo 3)) (mylet ((foo 4)) (mylet ((foo 5)) (list foo (mm)))))
 377)
 378(newline)
 379
 380(display
 381 (mylet ((foo 3))
 382    (mylet ((thunk (lambda () (mm))))
 383     (mylet ((foo 4)) (list foo (mm) (thunk)))))
 384)
 385(newline)
 386
 387; The following are definitions of let, let* and letrec, straight out of R5RS.
 388; The only difference is that the definitions use custom-bound 
 389; let, let*, letrec and lambda identifiers, which we explicitly pass 
 390; to the macros in the first argument.
 391
 392(define-syntax glet		; let, straight out of R5RS
 393  (syntax-rules ()
 394    ((_ (let let* letrec lambda) ((name val) ...) body1 body2 ...)
 395     ((lambda (name ...) body1 body2 ...) val ...))
 396    ((_ (let let* letrec lambda) tag ((name val) ...) body1 body2 ...)
 397     ((letrec ((tag
 398		(lambda (name ...) body1 body2 ...))) tag) val ...))))
 399
 400(define-syntax glet*		; let*, straight out of R5RS
 401  (syntax-rules ()
 402    ((_ mynames () body1 body2 ...)
 403     (let () body1 body2 ...))
 404    ((_ (let let* letrec lambda)
 405	((name1 val1) (name2 val2) ...) body1 body2 ...)
 406     (let ((name1 val1)) (let* ((name2 val2) ...) body1 body2 ...)))))
 407
 408; A shorter implementations of letrec, see
 409; "Re: Widespread bug (arguably) in letrec when an initializer returns twice"
 410; comp.lang.scheme, 2001-05-21 10:30:34 PST and 2001-05-21 14:56:49 PST
 411; http://groups.google.com/groups?selm=7eb8ac3e.0105210930.21542605%40posting.google.com
 412; http://groups.google.com/groups?selm=87ae468j7x.fsf%40app.dial.idiom.com
 413
 414(define-syntax gletrec
 415  (syntax-rules ()
 416    ((_ (mlet let* letrec lambda) ((var init) ...) . body)
 417     (mlet ((var 'undefined) ...)
 418       (let ((temp (list init ...)))  ; the native let will do fine here
 419         (begin (begin (set! var (car temp)) (set! temp (cdr temp))) ...
 420         (let () . body)))))))
 421
 422; This macro defiles its body
 423; It re-defines all the let-forms and the lambda, and defines
 424; a non-hygienic macro 'mm'. Whenever any binding is introduced,
 425; the let-forms, the lambdas and 'mm' are redefined.
 426; The redefined lambda acts as if it were infected by a virus, which
 427; keeps spreading within lambda's body to infect other lambda's there.
 428
 429(define-syntax defile
 430  (syntax-rules ()
 431    ((_ dbody)
 432     (letrec-syntax
 433	 ((do-defile
 434	   (syntax-rules ()	; all the shadowed symbols
 435	     ((_ (let-symb let*-symb letrec-symb lambda-symb mm-symb foo-symb)
 436		 body-to-defile)
 437	      (letrec-syntax
 438		  ((let-symb		; R5RS definition of let
 439		    (syntax-rules ()
 440		      ((_ . args)
 441		       (glet (let-symb let*-symb letrec-symb lambda-symb)
 442			     . args))))
 443
 444		   (let*-symb		; Redefinition of let*
 445		    (syntax-rules ()
 446		      ((_ . args) 
 447		       (glet* (let-symb let*-symb letrec-symb lambda-symb) 
 448			      . args))))
 449
 450		   (letrec-symb		; Redefinition of letrec
 451		    (syntax-rules ()
 452		      ((_ . args) 
 453		       (gletrec (let-symb let*-symb letrec-symb lambda-symb) 
 454			      . args))))
 455		       
 456		   (lambda-symb         ; re-defined, infected lambda
 457		    (syntax-rules ()
 458		      ((_ _vars _body)
 459		       (letrec-syntax 
 460			   ((doit
 461			     (syntax-rules ()
 462			       ((_ (mylet-symb mylet*-symb myletrec-symb
 463					       mylambda-symb mymm-symb 
 464					       myfoo-symb) vars body)
 465				(lambda-native vars
 466				  (make-mm mymm-symb myfoo-symb
 467				    (do-defile	; proliferate in the body
 468				     (mylet-symb mylet*-symb myletrec-symb
 469						 mylambda-symb
 470						 mymm-symb myfoo-symb)
 471				     body))))))
 472			    (proliferate
 473			     (syntax-rules ()
 474			       ((_ dummy __vars __body)
 475				(extract* (let-symb let*-symb 
 476						    letrec-symb lambda-symb
 477						    mm-symb foo-symb)
 478					  (__vars __body)
 479					  (doit () __vars __body)))))
 480			    (stop-infection
 481			     (syntax-rules ()
 482			       ((_ dummy __vars __body)
 483				(lambda-native __vars __body))))
 484			    )
 485			 (extract? mm-symb _vars
 486			    ; true-continuation
 487			    (stop-infection () _vars _body)
 488			    ; false-cont
 489			    (proliferate () _vars _body))
 490			 ))))
 491
 492		   (lambda-native	; capture the native lambda
 493		    (syntax-rules ()
 494		      ((_ . args) (lambda . args))))
 495		   )
 496
 497		body-to-defile)))))
 498
 499       (extract* (let let* letrec lambda mm foo) dbody
 500		 (do-defile () dbody))
 501       ))))
 502
 503
 504;(mylet ((foo 2)) (mylet ((x 3)) (mylet ((foo 4)) (list (mm) foo))))
 505(display "defile")
 506(display "now.\n" (current-error-port))
 507(newline)
 508(defile
 509  (display
 510   (let ((foo 2)) (list (mm) foo))
 511   )
 512)
 513(newline)
 514; ==> (2 2)
 515
 516(defile
 517  (display
 518   (let ((foo 2)) (let ((foo 3)) (let ((foo 4)) (list (mm) foo))))
 519   )
 520)
 521(newline)
 522; ==> (4 4)
 523
 524(defile
 525  (display
 526   (let ((foo 2))
 527     (let ((foo 3) (bar (list (mm) foo)))
 528       (list foo (mm) bar)))
 529   )
 530)
 531(newline)
 532; ==> (3 3 (2 2)) 
 533
 534(defile
 535  (display
 536   (let ((foo 2))
 537     (list
 538      ((letrec ((bar (lambda () (list foo (mm))))
 539		(foo 3))
 540	bar))
 541      foo (mm)))))
 542(newline)
 543;==> ((3 3) 2 2) 
 544
 545(defile
 546  (display
 547   (let ((foo 2))
 548     (let foo ((flag #t) (lst (list foo (mm))))
 549       (if flag ((mm) #f (list lst lst)) lst)))))
 550(newline)
 551; ==> ((2 2) (2 2)) 
 552
 553(defile
 554  (display
 555  (let* ((foo 2) 
 556	 (i 3)
 557	 (foo 4) 
 558	 (ft (lambda () (mm))) ; will capture binding of foo to 4
 559	 (foo 5)
 560	 (ft1 (lambda (foo) (mm))) ; will  capture the arg of ft1
 561	 (foo 6))
 562    (list foo (mm) (ft) (ft1 7) '(mm))))
 563  )
 564(newline)
 565; ==> (6 6 4 7 (mm))
 566
 567; the use of (mm) (separately-defined macro) is equivalent to the use of variable foo -- 
 568; (define-macro (mm) foo) -- dirty macro
 569
 570
 571; Re-defining the global let
 572
 573(define-syntax dlet
 574  (syntax-rules ()
 575    ((_ new-let-symb . args) 
 576     ; just renaming of new-let-symbol with 'let'
 577     (let-syntax
 578	 ((ren 
 579	   (syntax-rules ()
 580	     ((_ list) (defile (let . args))))))
 581       (ren let1)))))
 582
 583
 584(display "dlet")
 585(newline)
 586(display
 587 (dlet list ((foo 2)) (list (mm) foo))
 588 )
 589
 590; (define-syntax old-let
 591;   (syntax-rules ()
 592;     ((_ . args) (let . args))))
 593; (define-syntax old-let*
 594;   (syntax-rules ()
 595;     ((_ . args) (let* . args))))
 596; (define-syntax old-letrec
 597;   (syntax-rules ()
 598;     ((_ . args) (letrec . args))))
 599; (define-syntax old-lambda
 600;   (syntax-rules ()
 601;     ((_ . args) (lambda . args))))
 602
 603; (define-syntax let
 604;    (syntax-rules ()
 605;      ((_ . args) (defile1 (glet (old-let old-let* old-letrec lambda) . args)))))
 606; ; (define-syntax let
 607; ;    (syntax-rules ()
 608; ;      ((_ . args) (defile1 (old-let . args)))))
 609
 610
 611; (define-syntax defile1
 612;   (syntax-rules ()
 613;     ((_ dbody)
 614;      (letrec-syntax
 615; 	 ((do-defile
 616; 	   (syntax-rules ()	; all the shadowed symbols
 617; 	     ((_ (let-symb let*-symb letrec-symb lambda-symb mm-symb foo-symb)
 618; 		 body-to-defile)
 619; 	      (letrec-syntax
 620; 		  ((let-symb		; R5RS definition of let
 621; 		    (syntax-rules ()
 622; 		      ((_ . args)
 623; 		       (glet (let-symb let*-symb letrec-symb lambda-symb)
 624; 			     . args))))
 625
 626; 		   (let*-symb		; Redefinition of let*
 627; 		    (syntax-rules ()
 628; 		      ((_ . args) 
 629; 		       (glet* (let-symb let*-symb letrec-symb lambda-symb) 
 630; 			      . args))))
 631
 632; 		   (letrec-symb		; Redefinition of letrec
 633; 		    (syntax-rules ()
 634; 		      ((_ . args) 
 635; 		       (gletrec (let-symb let*-symb letrec-symb lambda-symb) 
 636; 			      . args))))
 637		       
 638; 		   (lambda-symb         ; re-defined, infected lambda
 639; 		    (syntax-rules ()
 640; 		      ((_ _vars _body)
 641; 		       (letrec-syntax 
 642; 			   ((doit
 643; 			     (syntax-rules ()
 644; 			       ((_ (mylet-symb mylet*-symb myletrec-symb
 645; 					       mylambda-symb mymm-symb 
 646; 					       myfoo-symb) vars body)
 647; 				(lambda-native vars
 648; 				  (make-mm mymm-symb myfoo-symb
 649; 				    (do-defile	; proliferate in the body
 650; 				     (mylet-symb mylet*-symb myletrec-symb
 651; 						 mylambda-symb
 652; 						 mymm-symb myfoo-symb)
 653; 				     body)))))))
 654; 			 (extract* (let-symb let*-symb letrec-symb lambda-symb
 655; 					     mm-symb foo-symb)
 656; 				   (_vars _body)
 657; 				   (doit () _vars _body))))))
 658
 659; 		   (lambda-native	; capture the native lambda
 660; 		    (syntax-rules ()
 661; 		      ((_ . args) (lambda . args))))
 662; 		   )
 663
 664; 		body-to-defile)))))
 665
 666;        (extract* (let let* letrec lambda mm foo) dbody
 667; 		 (do-defile () dbody))
 668;        ))))
 669
 670; ; (define-syntax let
 671; ;   (syntax-rules ()
 672; ;     ((_ . args) (dlet let . args))))
 673
 674
 675
 676; ; (define-syntax alet
 677; ;   (syntax-rules ()
 678; ;     ((_ . args) 
 679; ;      (let-syntax
 680; ; 	 ((doit
 681; ; 	   (syntax-rules ()
 682; ; 	      ((_ (let-symb) body) (defile1 let-symb (blet . body))))))
 683; ;        (extract* (blet) args (doit () args))))))
 684
 685
 686; (display "corrupted-let")
 687; (newline)
 688; (display
 689;  (let ((foo 2)) (list (mm) foo))
 690;  )
 691
 692; (newline)
 693; (display
 694;    (let ((foo 2)) (let ((foo 3)) (let ((foo 4)) (list (mm) foo))))
 695;    )
 696; (newline)
 697; ; ==> (4 4)
 698
 699; (display
 700;    (let ((foo 2))
 701;      (let ((foo 3) (bar (list (mm) foo)))
 702;        (list foo (mm) bar)))
 703;    )
 704; (newline)
 705; ; ==> (3 3 (2 2)) 
 706
 707; (display
 708;    (let ((foo 2))
 709;      (list
 710;       ((letrec ((bar (lambda () (list foo (mm))))
 711; 		(foo 3))
 712; 	bar))
 713;       foo (mm))))
 714; (newline)
 715; ;==> ((3 3) 2 2) 
 716
 717; (display
 718;    (let ((foo 2))
 719;      (let foo ((flag #t) (lst (list foo (mm))))
 720;        (if flag ((mm) #f (list lst lst)) lst))))
 721; (newline)
 722; ; ==> ((2 2) (2 2)) 
 723
 724; (display
 725;  (let ()
 726;   (let* ((foo 2) 
 727; 	 (i 3)
 728; 	 (foo 4) 
 729; 	 (ft (lambda () (mm))) ; will capture binding of foo to 4
 730; 	 (foo 5)
 731; 	 (ft1 (lambda (foo) (mm))) ; will  capture the arg of ft1
 732; 	 (foo 6))
 733;     (list foo (mm) (ft) (ft1 7) '(mm))))
 734;   )
 735; (newline)
 736; ; ==> (6 6 4 7 (mm))
 737
 738
 739(define-syntax defile-what
 740  (syntax-rules ()
 741    ((_ dirty-macro-name dirty-macro-name-gen captured-symbol dbody)
 742     (letrec-syntax
 743	 ((do-defile
 744	   (syntax-rules ()	; all the shadowed symbols
 745	     ((_ (let-symb let*-symb letrec-symb lambda-symb mm-symb foo-symb)
 746		 body-to-defile)
 747	      (letrec-syntax
 748		  ((let-symb		; R5RS definition of let
 749		    (syntax-rules ()
 750		      ((_ . args)
 751		       (glet (let-symb let*-symb letrec-symb lambda-symb)
 752			     . args))))
 753
 754		   (let*-symb		; Redefinition of let*
 755		    (syntax-rules ()
 756		      ((_ . args) 
 757		       (glet* (let-symb let*-symb letrec-symb lambda-symb) 
 758			      . args))))
 759
 760		   (letrec-symb		; Redefinition of letrec
 761		    (syntax-rules ()
 762		      ((_ . args) 
 763		       (gletrec (let-symb let*-symb letrec-symb lambda-symb) 
 764			      . args))))
 765		       (lambda-symb         ; re-defined, infected lambda
 766		    (syntax-rules ()
 767		      ((_ _vars _body)
 768		       (letrec-syntax 
 769			   ((doit
 770			     (syntax-rules ()
 771			       ((_ (mylet-symb mylet*-symb myletrec-symb
 772					       mylambda-symb mymm-symb 
 773					       myfoo-symb) vars body)
 774				(lambda-native vars
 775				  (dirty-macro-name-gen mymm-symb myfoo-symb
 776				    (do-defile	; proliferate in the body
 777				     (mylet-symb mylet*-symb myletrec-symb
 778						 mylambda-symb
 779						 mymm-symb myfoo-symb)
 780				     body))))))
 781			    (proliferate
 782			     (syntax-rules ()
 783			       ((_ dummy __vars __body)
 784				(extract* (let-symb let*-symb 
 785						    letrec-symb lambda-symb
 786						    mm-symb foo-symb)
 787					  (__vars __body)
 788					  (doit () __vars __body)))))
 789			    (stop-infection
 790			     (syntax-rules ()
 791			       ((_ dummy __vars __body)
 792				(lambda-native __vars __body))))
 793			    )
 794			 (extract? mm-symb _vars
 795			    ; true-continuation
 796			    (stop-infection () _vars _body)
 797			    ; false-cont
 798			    (proliferate () _vars _body))
 799			 ))))
 800
 801; 		   (lambda-symb         ; re-defined, infected lambda
 802; 		    (syntax-rules ()
 803; 		      ((_ _vars _body)
 804; 		       (letrec-syntax 
 805; 			   ((doit
 806; 			     (syntax-rules ()
 807; 			       ((_ (mylet-symb mylet*-symb myletrec-symb
 808; 					       mylambda-symb mymm-symb 
 809; 					       myfoo-symb) vars body)
 810; 				(lambda-native vars
 811; 				  (dirty-macro-name-gen mymm-symb myfoo-symb
 812; 				    (do-defile	; proliferate in the body
 813; 				     (mylet-symb mylet*-symb myletrec-symb
 814; 						 mylambda-symb
 815; 						 mymm-symb myfoo-symb)
 816; 				     body)))))))
 817; 			 (extract* (let-symb let*-symb letrec-symb lambda-symb
 818; 					     mm-symb foo-symb)
 819; 				   (_vars _body)
 820; 				   (doit () _vars _body))))))
 821
 822		   (lambda-native	; capture the native lambda
 823		    (syntax-rules ()
 824		      ((_ . args) (lambda . args))))
 825		   )
 826
 827		body-to-defile)))))
 828
 829       (extract* (let let* letrec lambda dirty-macro-name captured-symbol) dbody
 830		 (do-defile () dbody))
 831       ))))
 832
 833
 834(define-syntax let-defiled-syntax
 835  (syntax-rules ()
 836    ((_ var-to-capture ((dm-name dm-body)) body)
 837     (let-syntax
 838	 ((dm-generator
 839	   (syntax-rules ()
 840	     ((_ dmg-name var-to-capture dmg-outer-body)
 841	      (let-syntax 
 842		  ((dmg-name dm-body))
 843		dmg-outer-body)))))
 844       (defile-what
 845	 dm-name dm-generator var-to-capture body)
 846       ))))
 847
 848(display "defile-what") (newline)
 849(display
 850 (let-defiled-syntax
 851  bar ((mbar (syntax-rules () ((_ val) (+ bar val)))))
 852  (let ((bar 1)) (let ((bar 2)) (mbar 2))))
 853)
 854(newline)
 855
 856(display "defile-what") (newline)
 857(display
 858 (let-defiled-syntax
 859  quux ((mquux (syntax-rules () ((_ val) (+ quux quux val)))))
 860  (let* ((bar 1) (quux 0) (quux 2) 
 861	 (lquux (lambda (x) (mquux x)))
 862	 (quux 3)
 863	 (lcquux (lambda (quux) (mquux quux)))) ; will tripple its arg
 864    (list (+ quux quux) (mquux 0) (lquux 2) (lcquux 5)))))
 865(newline)
 866; ==> (6 6 6 15)
 867
 868; testing shadowing
 869(display "test shadowing") (newline)
 870(display
 871 (let-defiled-syntax
 872  quux ((mquux (syntax-rules () ((_ val) (+ quux quux val)))))
 873    (let* ((bar 1) (quux 0) (quux 2) 
 874	   (lquux (lambda (x) (mquux x)))
 875	   (mquux (lambda (val) 0))
 876	   (lcquux (lambda (quux) (mquux quux)))) ; will tripple its arg
 877      (list (+ quux quux) (mquux 0) (lquux 2) (lcquux 5)))))
 878(newline)
 879; ==> (4 0 6 0)
 880(display
 881 (let-syntax
 882  ((mquux (syntax-rules () ((_ val) (+ quux quux val)))))
 883  (let ((mquux (lambda (val) 0)))
 884    (let* ((bar 1) (quux 0) (quux 2) 
 885	   (lquux (lambda (x) (mquux x)))
 886	   (lcquux (lambda (quux) (mquux quux)))) ; will tripple its arg
 887      (list (+ quux quux) (mquux 0) (lquux 2) (lcquux 5))))))
 888(newline)
 889; ==> (4 0 0 0)
 890
 891(display
 892 (let-defiled-syntax
 893  quux ((mquux (syntax-rules () ((_ val) (+ quux quux val)))))
 894  (let-syntax ((mquux (syntax-rules () ((_ val) 0))))
 895    (let* ((bar 1) (quux 0) (quux 2) 
 896	   (lquux (lambda (x) (mquux x)))
 897	   (lcquux (lambda (quux) (mquux quux)))) ; will tripple its arg
 898      (list (+ quux quux) (mquux 0) (lquux 2) (lcquux 5))))))
 899; ==> (4 0 0 0)
 900
 901(display
 902  (defile
 903    (let-syntax
 904      ((test2
 905	 (syntax-rules (mm)
 906	   ((_ mm) 'okay)
 907	   ((_ x) 'wrong))))
 908      (list
 909	(test2 mm)
 910	(let ((foo 3)) (test2 mm))))))
 911(newline)
 912
 913; extracting on a different sort of criteria
 914
 915;   extract2 MARKER BODY CONT
 916; Search the body for the occurrence of the form (SYMB MARKER . REST)
 917; where SYMB is a symbol. MARKER is a string, boolean, or number.
 918; For simplicity, we don't check that SYMB
 919; is a symbol, but we could: see a macro m-symbol?.
 920; CONT is a list (K-HEAD () . K-REST)
 921; If we found such a form, expand into
 922; (K-HEAD SYMB  . K-REST)
 923; If we didn't find what we searched for, expand into
 924; (K-HEAD nai . K-REST)
 925
 926
 927(define-syntax extract2
 928  (syntax-rules ()
 929    ((_ _marker _body _cont)
 930      (letrec-syntax
 931	((lp
 932           (syntax-rules ()
 933	      ((_ (symb _marker . rest) stack (cont-head () . cont-args))
 934	       (cont-head symb . cont-args)) ; found
 935	      ((_ (x . y) stack cont)   ; if body is a composite form,
 936	       (lp x (y . stack) cont)) ; look inside
 937	      ((_ d () (cont-head () . cont-args))
 938	       (cont-head nai . cont-args)) ; symb does not occur
 939	      ((_ d (x . y) cont)
 940	       (lp x y cont)))))
 941	(lp _body () _cont)))))
 942
 943
 944(define-syntax loop
 945  (syntax-rules ()
 946    ((_ . exps)
 947      (let-syntax
 948	((cont
 949	   (syntax-rules ()
 950	     ((_ ident exps_)
 951	       (call-with-current-continuation
 952		 (lambda (k)
 953		   (let ((ident (lambda (dummy value) (k value))))
 954		     (let f ()
 955		       (begin 'prevent-empty-begin . exps_)
 956		       (f)))))))))
 957	(extract2 "this one" exps (cont () exps))))))
 958
 959
 960(display "loop") (newline)
 961(display (loop (break "this one" 'foo)))
 962(newline)
 963; ==> foo
 964
 965(display "nested loop") (newline)
 966(display
 967  (loop
 968    (loop
 969      (break "this one" 'foo))
 970    (break "this one" 'bar)))
 971; ==> bar
 972(newline)
 973
 974(display "loop: shadowing") (newline)
 975(display
 976  (let ((break (lambda (dummy x) x)))
 977    (loop (break "this one" 'foo))
 978    (break "this one" 'bar)))
 979(newline)
 980
 981; Petrofsky:
 982; There are problems with writing extensions to loop.  Suppose we want
 983; to write loop-while, which adds a test that is checked once each time
 984; around the loop, and still binds an exit procedure.  We might think it
 985; could be written like this:
 986
 987(define-syntax loop-while
 988  (syntax-rules ()
 989    ((_ test exp ...)
 990      (loop
 991	(if (not test) (break "this one" #f))
 992	exp ...))))
 993
 994(display "loop-while") (newline)
 995(display
 996  (let ((n 0))
 997    (loop-while (< n 5)
 998      (set! n (+ n 1)))
 999    n))
 1000; ==> 5
1001(newline)
1002
1003(display
1004  (loop
1005    (let ((n 0))
1006      (loop-while (< n 5)
1007	(set! n (+ n 1))
1008	(if (= n 2)
1009	  (break "this one" 'foo)))
1010      (break "this one" 'bar))))
1011(newline)
1012
1013
1014; (define-syntax make-lambda 
1015;   (syntax-rules ()
1016;     ((_ . args) (lambda . args))))
1017
1018; (define-syntax make-lambda 
1019;   (syntax-rules ()
1020;     ((_ bindings body ...)
1021;       (let () (define (proc . bindings) body ...)
1022; 	proc))))
1023
1024(define-syntax make-lambda 
1025  (syntax-rules ()
1026    ((_ bindings body ...)
1027      (let-syntax () (define (proc . bindings) body ...)
1028	proc))))
1029
1030(define-syntax lambda
1031  (syntax-rules ()
1032    ((_ bindings body1 body2 ...)
1033     (make-lambda bindings
1034       (display "OK") (newline)
1035       (begin body1 body2 ...)))))
1036
1037(display "lambda-test") (newline)
1038(let ((p (lambda (x y z) (list x y z))))
1039  (display (p 1 2 3)))
1040(newline)
1041
1042(define-syntax mm
1043  (syntax-rules ()
1044    ((_ dummy) foo)
1045    ((_ dummy k) (k foo))))
1046
1047(define-syntax make-mm
1048  (syntax-rules ()
1049    ((_ mm foo bodies)
1050      (let-syntax
1051	((mm
1052	   (syntax-rules ()
1053	     ((_ dummy) foo)
1054	     ((_ dummy (kh () . kargs)) (kh foo . kargs)))))
1055	. bodies))))
1056
1057(define-syntax recolor
1058  (syntax-rules ()
1059    ((_ from to bodies . rest)
1060      (let-syntax 
1061	((ren
1062	   (syntax-rules ()
1063	     ((_ from) bodies))))
1064	(ren to)))))
1065
1066(define-syntax nai
1067  (syntax-rules ()
1068    ((_ dummy (kh () . kargs)) (kh nai . kargs))))
1069
1070(define-syntax lambda
1071  (syntax-rules ()
1072    ((_ bindings . bodies)
1073      (letrec-syntax
1074	((test
1075	   (syntax-rules ()
1076	     ((_ symb exp _kt _kf)
1077	       (letrec-syntax
1078		 ((loop
1079		    (syntax-rules (symb)
1080		      ((_ d () kt kf) kf)
1081		      ((_ (s . r1) (symb . r2) (kh () . kargs) kf)
1082			(kh s . kargs))
1083		      ((_ d (x . rest) kt kf) (loop rest rest kt kf)))))
1084		 (loop exp exp _kt _kf)))))
1085	 (doit
1086	   (syntax-rules ()
1087	     ((_ foo orig-foo bindings_ bodies_)
1088	       (extract2 "mm" bodies_
1089		 (cont () foo orig-foo bindings_ bodies_)))))
1090	 (cont
1091	   (syntax-rules ()
1092	     ((_ mm bindings_ bodies_)
1093	      (mm dummy (cont2 () mm bindings_ bodies_)))))
1094	  (cont2
1095	    (syntax-rules ()
1096	      ((_ xxx foo mm bindings_ bodies_)
1097	       (test foo bindings_
1098		 (cont3 () mm bindings_ bodies_)
1099		 (make-lambda bindings_ bodies_)))))
1100	  (cont3
1101	    (syntax-rules ()
1102	      ((_ foo mm bindings_ bodies_)
1103		(make-lambda bindings_
1104		  (make-mm mm foo
1105		    bodies_))))))
1106	(extract2 "mm" bodies
1107	  (cont () bindings bodies))))))
1108
1109
1110; (define-syntax let
1111;   (syntax-rules ()
1112;     ((_ ((v i)) . bodies)
1113;       ((lambda (v) . bodies) i))))
1114
1115(define-syntax let*
1116  (syntax-rules ()
1117    ((_ () . bodies) (begin . bodies))
1118    ((_ ((v i) . rest) . bodies)
1119      ((lambda (v) (let* rest . bodies)) i))))
1120;    ((_ . args) (glet* (let let* letrec lambda) . args))))
1121
1122(display (let* ((foo 2)) (list foo (mm "mm"))))
1123
1124(display
1125 (let* ((foo 2) 
1126	(i 3)
1127	(foo 4) 
1128	(ft (lambda () (mm "mm")))  ; will capture binding of foo to 4
1129	(foo 5)
1130	(ft1 (lambda (foo) (mm "mm")))	; will  capture the arg of ft1
1131	(foo 6))
1132   (list foo (mm "mm") (ft) (ft1 7) '(mm "mm"))))
1133(newline)
1134; ==> (6 6 4 7 (mm))
1135
1136
Trap