1#lang scheme/base 2 3(require syntax/docprovide) 4 5(require (only-in test-engine/test-engine 6 add-failed-check! failed-check 7 property-error property-fail) 8 (rename-in scheme/base (cons racket-cons)) 9 test-engine/racket-tests 10 test-engine/syntax 11 test-engine/srcloc 12 scheme/class) 13 14(require deinprogramm/sdp/private/module-begin 15 (except-in deinprogramm/signature/signature signature-violation) 16 (except-in deinprogramm/signature/signature-syntax property)) 17 18(require (for-syntax scheme/base) 19 (for-syntax stepper/private/syntax-property) 20 (for-syntax syntax/parse) 21 (for-syntax racket/struct-info) 22 syntax/parse) 23 24(require deinprogramm/sdp/record) 25 26(require (only-in lang/private/teachprims define-teach teach-equal? beginner-equal~?)) 27 28(require (for-syntax deinprogramm/private/syntax-checkers)) 29 30(require (for-syntax "rewrite-error-message.rkt")) 31(require "rewrite-error-message.rkt") 32 33(require (rename-in deinprogramm/quickcheck/quickcheck 34 (property quickcheck:property))) 35 36(provide provide lib planet rename-out require #%datum #%module-begin #%top-interaction) ; so we can use this as a language 37 38(provide (all-from-out deinprogramm/sdp/record)) 39(provide (rename-out (define-record define-record-functions))) 40(provide (all-from-out test-engine/racket-tests)) 41(provide signature define-contract : 42 contract ; legacy 43 one-of ; deprecated 44 -> mixed predicate enum combined list-of nonempty-list-of) 45(provide (rename-out (nonempty-list-of cons-list-of))) 46 47(provide number real rational integer integer-from-to natural 48 boolean true false 49 string symbol 50 empty-list 51 unspecific 52 any 53 property) 54 55(provide match) 56 57(define-syntax provide/rename 58 (syntax-rules () 59 ((provide/rename (here there) ...) 60 (begin 61 (provide (rename-out (here there))) ...)))) 62 63(provide/rename 64 (sdp-define define) 65 (sdp-let let) 66 (sdp-let* let*) 67 (sdp-letrec letrec) 68 (sdp-lambda lambda) 69 (sdp-lambda λ) 70 (sdp-cond cond) 71 (sdp-if if) 72 (sdp-else else) 73 (sdp-begin begin) 74 (sdp-and and) 75 (sdp-or or) 76 (sdp-dots ..) 77 (sdp-dots ...) 78 (sdp-dots ....) 79 (sdp-dots .....) 80 (sdp-dots ......) 81 (sdp-app #%app) 82 (sdp-top #%top) 83 (sdp-set! set!)) 84 85(provide sdp-advanced-lambda 86 sdp-advanced-define) 87 88(provide for-all ==> 89 check-property 90 expect expect-within expect-member-of expect-range) 91 92(provide quote) 93 94(provide-and-document 95 procedures 96 ("Zahlen" 97 (number? (any -> boolean) 98 "feststellen, ob ein Wert eine Zahl ist") 99 100 (= (number number number ... -> boolean) 101 "Zahlen auf Gleichheit testen") 102 (< (real real real ... -> boolean) 103 "Zahlen auf kleiner-als testen") 104 (> (real real real ... -> boolean) 105 "Zahlen auf größer-als testen") 106 (<= (real real real ... -> boolean) 107 "Zahlen auf kleiner-gleich testen") 108 (>= (real real real ... -> boolean) 109 "Zahlen auf größer-gleich testen") 110 111 (+ (number number number ... -> number) 112 "Summe berechnen") 113 (- (number number ... -> number) 114 "bei mehr als einem Argument Differenz zwischen der ersten und der Summe aller weiteren Argumente berechnen; bei einem Argument Zahl negieren") 115 (* (number number number ... -> number) 116 "Produkt berechnen") 117 (/ (number number number ... -> number) 118 "das erste Argument durch das Produkt aller weiteren Argumente berechnen") 119 (max (real real ... -> real) 120 "Maximum berechnen") 121 (min (real real ... -> real) 122 "Minimum berechnen") 123 (quotient (integer integer -> integer) 124 "ganzzahlig dividieren") 125 (remainder (integer integer -> integer) 126 "Divisionsrest berechnen") 127 (modulo (integer integer -> integer) 128 "Divisionsmodulo berechnen") 129 (sqrt (number -> number) 130 "Quadratwurzel berechnen") 131 (expt (number number -> number) 132 "Potenz berechnen (erstes Argument hoch zweites Argument)") 133 (abs (real -> real) 134 "Absolutwert berechnen") 135 136 ;; fancy numeric 137 (exp (number -> number) 138 "Exponentialfunktion berechnen (e hoch Argument)") 139 (log (number -> number) 140 "natürlichen Logarithmus (Basis e) berechnen") 141 142 ;; trigonometry 143 (sin (number -> number) 144 "Sinus berechnen (Argument in Radian)") 145 (cos (number -> number) 146 "Cosinus berechnen (Argument in Radian)") 147 (tan (number -> number) 148 "Tangens berechnen (Argument in Radian)") 149 (asin (number -> number) 150 "Arcussinus berechnen (in Radian)") 151 (acos (number -> number) 152 "Arcuscosinus berechnen (in Radian)") 153 (atan (number -> number) 154 "Arcustangens berechnen (in Radian)") 155 156 (exact? (number -> boolean) 157 "feststellen, ob eine Zahl exakt ist") 158 159 (integer? (any -> boolean) 160 "feststellen, ob ein Wert eine ganze Zahl ist") 161 (natural? (any -> boolean) 162 "feststellen, ob ein Wert eine natürliche Zahl (inkl. 0) ist") 163 164 (zero? (number -> boolean) 165 "feststellen, ob eine Zahl Null ist") 166 (positive? (number -> boolean) 167 "feststellen, ob eine Zahl positiv ist") 168 (negative? (number -> boolean) 169 "feststellen, ob eine Zahl negativ ist") 170 (odd? (integer -> boolean) 171 "feststellen, ob eine Zahl ungerade ist") 172 (even? (integer -> boolean) 173 "feststellen, ob eine Zahl gerade ist") 174 175 (lcm (integer integer ... -> natural) 176 "kleinstes gemeinsames Vielfaches berechnen") 177 178 (gcd (integer integer ... -> natural) 179 "größten gemeinsamen Teiler berechnen") 180 181 (rational? (any -> boolean) 182 "feststellen, ob eine Zahl rational ist") 183 184 (numerator (rational -> integer) 185 "Zähler eines Bruchs berechnen") 186 187 (denominator (rational -> natural) 188 "Nenner eines Bruchs berechnen") 189 190 (inexact? (number -> boolean) 191 "feststellen, ob eine Zahl inexakt ist") 192 193 (real? (any -> boolean) 194 "feststellen, ob ein Wert eine reelle Zahl ist") 195 196 (floor (real -> integer) 197 "nächste ganze Zahl unterhalb einer rellen Zahlen berechnen") 198 199 (ceiling (real -> integer) 200 "nächste ganze Zahl oberhalb einer rellen Zahlen berechnen") 201 202 (round (real -> integer) 203 "relle Zahl auf eine ganze Zahl runden") 204 205 (complex? (any -> boolean) 206 "feststellen, ob ein Wert eine komplexe Zahl ist") 207 208 (make-polar (real real -> number) 209 "komplexe Zahl aus Abstand zum Ursprung und Winkel berechnen") 210 211 (real-part (number -> real) 212 "reellen Anteil einer komplexen Zahl extrahieren") 213 214 (imag-part (number -> real) 215 "imaginären Anteil einer komplexen Zahl extrahieren") 216 217 (magnitude (number -> real) 218 "Abstand zum Ursprung einer komplexen Zahl berechnen") 219 220 (angle (number -> real) 221 "Winkel einer komplexen Zahl berechnen") 222 223 (exact->inexact (number -> number) 224 "eine Zahl durch eine inexakte Zahl annähern") 225 226 (inexact->exact (number -> number) 227 "eine Zahl durch eine exakte Zahl annähern") 228 229 ;; "Odds and ends" 230 231 (number->string (number -> string) 232 "Zahl in Zeichenkette umwandeln") 233 234 (string->number (string -> (mixed number false)) 235 "Zeichenkette in Zahl umwandeln, falls möglich") 236 237 (random (natural -> natural) 238 "eine natürliche Zufallszahl berechnen, die kleiner als das Argument ist") 239 240 (current-seconds (-> natural) 241 "aktuelle Zeit in Sekunden seit einem unspezifizierten Startzeitpunkt berechnen")) 242 243 ("boolesche Werte" 244 (boolean? (any -> boolean) 245 "feststellen, ob ein Wert ein boolescher Wert ist") 246 247 ((sdp-not not) (boolean -> boolean) 248 "booleschen Wert negieren") 249 250 (boolean=? (boolean boolean -> boolean) 251 "Booleans auf Gleichheit testen") 252 253 (true? (any -> boolean) 254 "feststellen, ob ein Wert #t ist") 255 (false? (any -> boolean) 256 "feststellen, ob ein Wert #f ist")) 257 258 ("Listen" 259 (empty list "die leere Liste") 260 ((sdp-cons cons) (%a (list-of %a) -> (list-of %a)) 261 "erzeuge ein Cons aus Element und Liste") 262 (cons? (any -> boolean) 263 "feststellen, ob ein Wert ein Cons ist") 264 (empty? (any -> boolean) 265 "feststellen, ob ein Wert die leere Liste ist") 266 267 (first ((list-of %a) -> %a) 268 "erstes Element eines Cons extrahieren") 269 (rest ((list-of %a) -> (list-of %a)) 270 "Rest eines Cons extrahieren") 271 272 (list (%a ... -> (list-of %a)) 273 "Liste aus den Argumenten konstruieren") 274 275 (length ((list-of %a) -> natural) 276 "Länge einer Liste berechnen") 277 278 (filter ((%a -> boolean) (list-of %a) -> (list-of %a)) 279 "Alle Elemente einer Liste extrahieren, für welche die Funktion #t liefert.") 280 281 (fold (%b (%a %b -> %b) (list-of %a) -> %b) 282 "Liste einfalten.") 283 284 285 ((sdp-append append) ((list-of %a) ... -> (list-of %a)) 286 "mehrere Listen aneinanderhängen") 287 288 (list-ref ((list-of %a) natural -> %a) 289 "das Listenelement an der gegebenen Position extrahieren") 290 291 (reverse ((list-of %a) -> (list-of %a)) 292 "Liste in umgekehrte Reihenfolge bringen")) 293 294 ;; #### Zeichen sollten noch dazu, Vektoren wahrscheinlich auch 295 296 ("Zeichenketten" 297 (string? (any -> boolean) 298 "feststellen, ob ein Wert eine Zeichenkette ist") 299 300 (string=? (string string string ... -> boolean) 301 "Zeichenketten auf Gleichheit testen") 302 (string<? (string string string ... -> boolean) 303 "Zeichenketten lexikografisch auf kleiner-als testen") 304 (string>? (string string string ... -> boolean) 305 "Zeichenketten lexikografisch auf größer-als testen") 306 (string<=? (string string string ... -> boolean) 307 "Zeichenketten lexikografisch auf kleiner-gleich testen") 308 (string>=? (string string string ... -> boolean) 309 "Zeichenketten lexikografisch auf größer-gleich testen") 310 311 (string-append (string string ... -> string) 312 "Hängt Zeichenketten zu einer Zeichenkette zusammen") 313 314 (strings-list->string ((list-of string) -> string) 315 "Eine Liste von Zeichenketten in eine Zeichenkette umwandeln") 316 317 (string->strings-list (string -> (list-of string)) 318 "Eine Zeichenkette in eine Liste von Zeichenketten mit einzelnen Zeichen umwandeln") 319 320 (string-length (string -> natural) 321 "Liefert Länge einer Zeichenkette")) 322 323 ("Symbole" 324 (symbol? (any -> boolean) 325 "feststellen, ob ein Wert ein Symbol ist") 326 (symbol=? (symbol symbol -> boolean) 327 "Sind zwei Symbole gleich?") 328 (symbol->string (symbol -> string) 329 "Symbol in Zeichenkette umwandeln") 330 (string->symbol (string -> symbol) 331 "Zeichenkette in Symbol umwandeln")) 332 333 ("Verschiedenes" 334 (signature? (any -> boolean) 335 "feststellen, ob ein Wert eine Signatur ist") 336 (equal? (%a %b -> boolean) 337 "zwei Werte auf Gleichheit testen") 338 (eq? (%a %b -> boolean) 339 "zwei Werte auf Selbheit testen") 340 ((sdp-write-string write-string) (string -> unspecific) 341 "Zeichenkette in REPL ausgeben") 342 (write-newline (-> unspecific) 343 "Zeilenumbruch ausgeben") 344 (violation (string -> unspecific) 345 "Programmm mit Fehlermeldung abbrechen") 346 347 (map ((%a -> %b) (list-of %a) -> (list-of %b)) 348 "Funktion auf alle Elemente einer Liste anwenden, Liste der Resultate berechnen") 349 (for-each ((%a -> %b) (list-of %a) -> unspecific) 350 "Funktion von vorn nach hinten auf alle Elemente einer Liste anwenden") 351 (apply (function (list-of %a) -> %b) 352 "Funktion auf Liste ihrer Argumente anwenden") 353 (read (-> any) 354 "Externe Repräsentation eines Werts in der REPL einlesen und den zugehörigen Wert liefern"))) 355 356(define cons 357 (lambda (f r) 358 (when (and (not (null? r)) 359 (not (pair? r))) 360 (raise 361 (make-exn:fail:contract 362 (string->immutable-string 363 (format "Zweites Argument zu cons ist keine Liste, sondern ~e" r)) 364 (current-continuation-marks)))) 365 (racket-cons f r))) 366 367(define-syntax sdp-cons 368 (let () 369 ;; make it work with match 370 (define-struct cons-info () 371 #:super struct:struct-info 372 #:property 373 prop:procedure 374 (lambda (_ stx) 375 (syntax-case stx () 376 ((self . args) (syntax/loc stx (cons . args))) 377 (else (syntax/loc stx cons))))) 378 (make-cons-info (lambda () 379 (list #f 380 #'cons 381 #'cons? 382 (list #'cdr #'car) 383 '(#f #f) 384 #f))))) 385 386(define (first l) 387 (when (not (pair? l)) 388 (raise 389 (make-exn:fail:contract 390 (string->immutable-string 391 (format "Argument zu first kein Cons, sondern ~e" l)) 392 (current-continuation-marks)))) 393 (car l)) 394 395(define (rest l) 396 (when (not (pair? l)) 397 (raise 398 (make-exn:fail:contract 399 (string->immutable-string 400 (format "Argument zu rest kein Cons, sondern ~e" l)) 401 (current-continuation-marks)))) 402 (cdr l)) 403 404(define empty '()) 405 406(define (empty? obj) 407 (null? obj)) 408 409(define (cons? obj) 410 (pair? obj)) 411 412(define-teach sdp append 413 (lambda args 414 (let loop ((args args) 415 (seen-rev '())) 416 (when (not (null? args)) 417 (let ((arg (car args))) 418 (when (and (not (null? arg)) 419 (not (pair? arg))) 420 (raise 421 (make-exn:fail:contract 422 (string->immutable-string 423 (format "Erstes Argument zu append keine Liste, sondern ~e; restliche Argumente:~a" 424 arg 425 (apply string-append 426 (map (lambda (arg) 427 (format " ~e" arg)) 428 (append (reverse seen-rev) 429 (list '<...>) 430 (cdr args)))))) 431 (current-continuation-marks)))) 432 (loop (cdr args) 433 (racket-cons arg seen-rev))))) 434 435 436 (apply append args))) 437 438(define fold 439 (lambda (unit combine lis) 440 (cond 441 ((empty? lis) unit) 442 ((pair? lis) 443 (combine (first lis) 444 (fold unit combine (rest lis)))) 445 (else 446 (raise 447 (make-exn:fail:contract 448 (string->immutable-string 449 (format "Drittes Argument zu fold keine Liste, sondern ~e; andere Argumente: ~e ~e" 450 lis 451 unit combine)) 452 (current-continuation-marks))))))) 453 454(define filter 455 (lambda (p? lis) 456 (when (not (procedure? p?)) 457 (raise 458 (make-exn:fail:contract 459 (string->immutable-string 460 (format "Erstes Argument zu filter keine Funktion, sondern ~e" p?)) 461 (current-continuation-marks)))) 462 (cond 463 ((empty? lis) '()) 464 ((pair? lis) 465 (if (p? (first lis)) 466 (racket-cons (first lis) 467 (filter p? (rest lis))) 468 (filter p? (rest lis)))) 469 (else 470 (raise 471 (make-exn:fail:contract 472 (string->immutable-string 473 (format "Zweites Argument zu filter keine Liste, sondern ~e" 474 lis)) 475 (current-continuation-marks))))))) 476 477;; This is copied from collects/lang/private/beginner-funs.rkt 478;; Test-suite support (require is really an effect 479;; to make sure that it's loaded) 480(require deinprogramm/test-suite) 481 482 483(define-for-syntax (raise-sdp-syntax-error form msg . exprs) 484 485 (define (expr->form expr) 486 (let ((sexpr (syntax->datum expr))) 487 (cond 488 ((identifier? expr) sexpr) 489 ((syntax->list expr) 490 => (lambda (lis) 491 (expr->form (car lis)))) 492 (else #f)))) 493 494 (let ((form 495 (or form 496 (if (pair? exprs) 497 (expr->form (car exprs)) 498 #f)))) 499 (raise 500 (exn:fail:syntax (if form 501 (string-append (format "~a" form) ": " msg) 502 msg) 503 (current-continuation-marks) 504 exprs)))) 505 506(define-for-syntax (binding-in-this-module? b) 507 (and (list? b) 508 (module-path-index? (car b)) 509 (let-values (((path base) (module-path-index-split (car b)))) 510 (and (not path) (not base))))) 511 512(define-for-syntax (transform-sdp-define stx mutable?) 513 (syntax-case stx () 514 ((sdp-define) 515 (raise-sdp-syntax-error 516 #f "Definition ohne Operanden" stx)) 517 ((sdp-define v) 518 (raise-sdp-syntax-error 519 #f "Definition erwartet zwei Operanden, nicht einen" stx)) 520 ((sdp-define var expr) 521 (begin 522 (check-for-id! 523 (syntax var) 524 "Der erste Operand der Definition ist kein Name") 525 526 (let ((binding (identifier-binding (syntax var)))) 527 (when binding 528 (if (binding-in-this-module? binding) 529 (raise-sdp-syntax-error 530 #f 531 "Zweite Definition für denselben Namen" 532 stx) 533 (raise-sdp-syntax-error 534 #f 535 "Dieser Name gehört einer eingebauten Funktion und kann nicht erneut definiert werden" (syntax var))))) 536 (if mutable? 537 (with-syntax 538 ((dummy-def (stepper-syntax-property 539 (syntax (define dummy (lambda () (set! var 'dummy)))) 540 'stepper-skip-completely 541 #t))) 542 (syntax/loc stx 543 (begin 544 dummy-def 545 (define var expr)))) 546 (syntax/loc stx (define var expr))))) 547 ((sdp-define v e1 e2 e3 ...) 548 (raise-sdp-syntax-error 549 #f "Definition mit mehr als zwei Operanden" stx)))) 550 551(define-syntax (sdp-define stx) 552 (transform-sdp-define stx #f)) 553 554(define-syntax (sdp-advanced-define stx) 555 (transform-sdp-define stx #t)) 556 557(define-for-syntax (check-body-definitions bodies) 558 (let ((pairs 559 (map (lambda (stx) 560 ;; want to be able to shadow global definitions 561 (syntax-case stx (sdp-define) 562 ((sdp-define) 563 (raise-sdp-syntax-error 564 #f "Definition ohne Operanden" stx)) 565 ((sdp-define v) 566 (raise-sdp-syntax-error 567 #f "Definition erwartet zwei Operanden, nicht einen" stx)) 568 ((sdp-define var expr) 569 (begin 570 (check-for-id! 571 (syntax var) 572 "Der erste Operand der Definition ist kein Name") 573 (cons #'var (syntax/loc stx (define var expr))))) 574 ((sdp-define v e1 e2 e3 ...) 575 (raise-sdp-syntax-error 576 #f "Definition mit mehr als zwei Operanden" stx)) 577 (else 578 (raise-sdp-syntax-error 579 #f "Hier muss Definition stehen" stx)))) 580 bodies))) 581 (let loop ((pairs pairs)) 582 (when (pair? pairs) 583 (let ((id (caar pairs))) 584 (cond 585 ((memf (lambda (p) 586 (bound-identifier=? id (car p))) 587 (cdr pairs)) 588 => (lambda (rest) 589 (raise-sdp-syntax-error 590 #f 591 "Zweite Definition für denselben Namen" 592 (cdar rest))))) 593 (loop (cdr pairs))))) 594 (map cdr pairs))) 595 596(define-syntax (sdp-let stx) 597 (syntax-case stx () 598 ((sdp-let ((var expr) ...) body0 ... body) 599 (begin 600 (check-for-id-list! 601 (syntax->list (syntax (var ...))) 602 "Kein Name in `let-Bindung") 603 (with-syntax (((body0 ...) (check-body-definitions (syntax->list #'(body0 ...))))) 604 (syntax/loc stx ((lambda (var ...) body0 ... body) expr ...))))) 605 ((sdp-let expr ...) 606 (raise-sdp-syntax-error 607 #f "`let'-Ausdruck erwartet eine Liste von Bindungen (Paare aus Name und Ausdruck) und einen Rumpf" stx)))) 608 609(define-syntax (sdp-let* stx) 610 (syntax-case stx () 611 ((sdp-let* () body0 ... body) 612 (syntax/loc stx (let () body0 ... body))) 613 ((sdp-let* ((var1 expr1) (var2 expr2) ...) body0 ... body) 614 (begin 615 (check-for-id! 616 (syntax var1) 617 "Kein Name in `let*'-Bindung") 618 (with-syntax (((body0 ...) (check-body-definitions (syntax->list #'(body0 ...))))) 619 (syntax/loc stx ((lambda (var1) 620 (sdp-let* ((var2 expr2) ...) body0 ... body)) 621 expr1))))) 622 ((sdp-let* expr ...) 623 (raise-sdp-syntax-error 624 #f "`let*'-Ausdruck erwartet eine Liste von Bindungen (Paare aus Name und Ausdruck) und einen Rumpf" stx)))) 625 626(define-syntax (sdp-letrec stx) 627 (syntax-case stx () 628 ((sdp-letrec ((var expr) ...) body0 ... body) 629 (begin 630 (check-for-id-list! 631 (syntax->list (syntax (var ...))) 632 "Kein Name in letrec-Bindung") 633 (with-syntax (((body0 ...) (check-body-definitions (syntax->list #'(body0 ...))))) 634 (syntax/loc stx (letrec ((var expr) ...) body0 ... body))))) 635 ((sdp-letrec expr ...) 636 (raise-sdp-syntax-error 637 #f "`letrec''-Ausdruck erwartet eine Liste von Bindungen (Paare aus Name und Ausdruck) und einen Rumpf" stx)))) 638 639(define-syntax (sdp-lambda stx) 640 (syntax-case stx () 641 ((sdp-lambda (var ...) body0 ... body) 642 (begin 643 (check-for-id-list! 644 (syntax->list (syntax (var ...))) 645 "Kein Name als Parameter der Abstraktion") 646 (with-syntax (((body0 ...) (check-body-definitions (syntax->list #'(body0 ...))))) 647 (syntax/loc stx (lambda (var ...) body0 ... body))))) 648 ((sdp-lambda var body ...) 649 (identifier? (syntax var)) 650 (raise-sdp-syntax-error 651 #f "Um die Parameter einer Abstraktion gehören Klammern" (syntax var))) 652 ((sdp-lambda var ...) 653 (raise-sdp-syntax-error 654 #f "Fehlerhafte Abstraktion" stx)))) 655 656(define-syntax (sdp-advanced-lambda stx) 657 (syntax-case stx () 658 ((sdp-lambda (var ...) body) 659 (begin 660 (check-for-id-list! 661 (syntax->list (syntax (var ...))) 662 "Kein Name als Parameter der Abstraktion") 663 (syntax/loc stx (lambda (var ...) body)))) 664 ((sdp-lambda (var ... . rest) body0 ... body) 665 (begin 666 (check-for-id-list! 667 (syntax->list (syntax (var ...))) 668 "Kein Name als Parameter der Abstraktion") 669 (unless (null? (syntax->datum #'rest)) 670 (check-for-id! 671 (syntax rest) 672 "Kein Name als Restlisten-Parameter der Abstraktion")) 673 (with-syntax (((body0 ...) (check-body-definitions (syntax->list #'(body0 ...))))) 674 (syntax/loc stx (lambda (var ... . rest) body0 ... body))))) 675 ((sdp-lambda var ...) 676 (raise-sdp-syntax-error 677 #f "Fehlerhafte Abstraktion" stx)))) 678 679(define-syntax (sdp-begin stx) 680 (syntax-case stx () 681 ((sdp-begin) 682 (raise-sdp-syntax-error 683 #f "`begin`-Ausdruck braucht mindestens einen Operanden" stx)) 684 ((sdp-begin expr1 expr2 ...) 685 (syntax/loc stx (begin expr1 expr2 ...))))) 686 687(define-for-syntax (local-expand-for-error stx ctx stops) 688 ;; This function should only be called in an 'expression 689 ;; context. In case we mess up, avoid bogus error messages. 690 (when (memq (syntax-local-context) '(expression)) 691 (local-expand stx ctx stops))) 692 693(define-for-syntax (ensure-expression stx k) 694 (if (memq (syntax-local-context) '(expression)) 695 (k) 696 (stepper-syntax-property #`(begin0 #,stx) 'stepper-skipto skipto/second))) 697 698;; A consistent pattern for stepper-skipto: 699(define-for-syntax (stepper-ignore-checker stx) 700 (stepper-syntax-property stx 'stepper-skipto '(syntax-e cdr syntax-e cdr car))) 701 702;; Raise a syntax error: 703(define-for-syntax (teach-syntax-error form stx detail msg . args) 704 (let ([form (if (eq? form '|function call|) ; #### 705 form 706 #f)] ; extract name from stx 707 [msg (apply format msg args)]) 708 (if detail 709 (raise-sdp-syntax-error form msg stx detail) 710 (raise-sdp-syntax-error form msg stx)))) 711 712;; The syntax error when a form's name doesn't follow a "(" 713(define-for-syntax (bad-use-error name stx) 714 (teach-syntax-error 715 name 716 stx 717 #f 718 "`~a' wurde an einer Stelle gefunden, die keiner offenen Klammer folgt" 719 name)) 720 721;; Use for messages "expected ..., found <something else>" 722(define-for-syntax (something-else v) 723 (let ([v (syntax-e v)]) 724 (cond 725 [(number? v) "eine Zahl"] 726 [(string? v) "eine Zeichenkette"] 727 [else "etwas anderes"]))) 728;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 729;; cond 730;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 731 732(define-syntax (sdp-cond stx) 733 (ensure-expression 734 stx 735 (lambda () 736 (syntax-case stx () 737 [(_) 738 (teach-syntax-error 739 'cond 740 stx 741 #f 742 "Bedingung und ein Ausdruck nach `cond' erwartet, aber da ist nichts")] 743 [(_ clause ...) 744 (let* ([clauses (syntax->list (syntax (clause ...)))] 745 [check-preceding-exprs 746 (lambda (stop-before) 747 (let/ec k 748 (for-each (lambda (clause) 749 (if (eq? clause stop-before) 750 (k #t) 751 (syntax-case clause () 752 [(question body0 ... answer) 753 (begin 754 (unless (and (identifier? (syntax question)) 755 (free-identifier=? (syntax question) #'sdp-else)) 756 (local-expand-for-error (syntax question) 'expression null)) 757 (local-expand-for-error #'(let () body0 ... answer) 'expression null))]))) 758 clauses)))]) 759 (let ([checked-clauses 760 (map 761 (lambda (clause) 762 (syntax-case clause (sdp-else) 763 [(sdp-else body0 ... answer) 764 (let ([lpos (memq clause clauses)]) 765 (when (not (null? (cdr lpos))) 766 (teach-syntax-error 767 'cond 768 stx 769 clause 770 "`else'-Bedingung gefunden, die nicht am Ende des `cond'-Ausdrucks steht")) 771 (with-syntax ([(body0 ...) (check-body-definitions (syntax->list #'(body0 ...)))] 772 [new-test (stepper-syntax-property (syntax #t) 'stepper-else #t)]) 773 (syntax/loc clause (new-test body0 ... answer))))] 774 [(question body0 ... answer) 775 (begin 776 (with-syntax ([(body0 ...) (check-body-definitions (syntax->list #'(body0 ...)))] 777 [verified (stepper-ignore-checker (syntax (verify-boolean question 'cond)))]) 778 (syntax/loc clause (verified body0 ... answer))))] 779 [() 780 (check-preceding-exprs clause) 781 (teach-syntax-error 782 'cond 783 stx 784 clause 785 "Bedingung und Ausdruck in Zweig erwartet, aber Zweig leer")] 786 [(question?) 787 (check-preceding-exprs clause) 788 (teach-syntax-error 789 'cond 790 stx 791 clause 792 "Zweig mit Bedingung und Ausdruck erwartet, aber Zweig enthält nur eine Form")] 793 [_else 794 (teach-syntax-error 795 'cond 796 stx 797 clause 798 "Zweig mit Bedingung und Ausdruck erwartet, aber ~a gefunden" 799 (something-else clause))])) 800 clauses)]) 801 ;; Add `else' clause for error (always): 802 (let ([clauses (append checked-clauses 803 (list 804 (with-syntax ([error-call (syntax/loc stx (error 'cond "alle Bedingungen ergaben #f"))]) 805 (syntax [else error-call]))))]) 806 (with-syntax ([clauses clauses]) 807 (syntax/loc stx (cond . clauses))))))] 808 [_else (bad-use-error 'cond stx)])))) 809 810(define-syntax sdp-else 811 (make-set!-transformer 812 (lambda (stx) 813 (define (bad expr) 814 (teach-syntax-error 815 'else 816 expr 817 #f 818 "hier nicht erlaubt, weil kein Bedingung in `cond'-Zweig")) 819 (syntax-case stx (set! x) 820 [(set! e expr) (bad #'e)] 821 [(e . expr) (bad #'e)] 822 [e (bad stx)])))) 823 824;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 825;; if 826;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 827 828(define-syntax (sdp-if stx) 829 (ensure-expression 830 stx 831 (lambda () 832 (syntax-case stx () 833 [(_ test then else) 834 (with-syntax ([new-test (stepper-ignore-checker (syntax (verify-boolean test 'if)))]) 835 (syntax/loc stx 836 (if new-test 837 then 838 else)))] 839 [(_ . rest) 840 (let ([n (length (syntax->list (syntax rest)))]) 841 (teach-syntax-error 842 'if 843 stx 844 #f 845 "Bedingung und zwei Ausdrücke erwartet, aber ~a Form~a gefunden" 846 (if (zero? n) "keine" n) 847 (if (= n 1) "" "en")))] 848 [_else (bad-use-error 'if stx)])))) 849 850;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 851;; or, and 852;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 853 854(define-syntaxes (sdp-or sdp-and) 855 (let ([mk 856 (lambda (where) 857 (let ([stepper-tag (case where 858 [(or) 'comes-from-or] 859 [(and) 'comes-from-and])]) 860 (with-syntax ([swhere where]) 861 (lambda (stx) 862 (ensure-expression 863 stx 864 (lambda () 865 (syntax-case stx () 866 [(_ . clauses) 867 (let ([n (length (syntax->list (syntax clauses)))]) 868 (let loop ([clauses-consumed 0] 869 [remaining (syntax->list #`clauses)]) 870 (if (null? remaining) 871 (case where 872 [(or) #`#f] 873 [(and) #`#t]) 874 (stepper-syntax-property 875 (stepper-syntax-property 876 (quasisyntax/loc 877 stx 878 (if #,(stepper-ignore-checker (quasisyntax/loc stx (verify-boolean #,(car remaining) 'swhere))) 879 #,@(case where 880 [(or) #`(#t 881 #,(loop (+ clauses-consumed 1) (cdr remaining)))] 882 [(and) #`(#,(loop (+ clauses-consumed 1) (cdr remaining)) 883 #f)]))) 884 'stepper-hint 885 stepper-tag) 886 'stepper-and/or-clauses-consumed 887 clauses-consumed))))] 888 [_else (bad-use-error where stx)])))))))]) 889 (values (mk 'or) (mk 'and)))) 890 891;; verify-boolean is inserted to check for boolean results: 892(define (verify-boolean b where) 893 (if (or (eq? b #t) (eq? b #f)) 894 b 895 (raise 896 (make-exn:fail:contract 897 (string->immutable-string 898 (format "~a: Testresultat ist nicht boolesch: ~e" where b)) 899 (current-continuation-marks))))) 900 901(define-teach sdp not 902 (lambda (b) 903 (verify-boolean b 'not) 904 (not b))) 905 906(define (boolean=? a b) 907 (verify-boolean a 'boolean=?) 908 (verify-boolean b 'boolean=?) 909 (eq? a b)) 910 911(define (verify-symbol b where) 912 (if (symbol? b) 913 b 914 (raise 915 (make-exn:fail:contract 916 (string->immutable-string 917 (format "~a: Wert ist kein Symbol: ~e" where b)) 918 (current-continuation-marks))))) 919 920(define (symbol=? a b) 921 (verify-symbol a 'symbol=?) 922 (verify-symbol b 'symbol=?) 923 (eq? a b)) 924 925(define-syntax (sdp-app stx) 926 (define (raise-operator-error no-op expr) 927 (raise-sdp-syntax-error #f 928 (format "Operator darf ~a sein, ist aber ~s" no-op (syntax->datum expr)) 929 expr)) 930 (syntax-case stx () 931 ((_) 932 (raise-sdp-syntax-error 933 #f "Zusammengesetzte Form ohne Operator" (syntax/loc stx ()))) 934 ((_ datum1 datum2 ...) 935 (number? (syntax->datum #'datum1)) 936 (raise-operator-error "keine Zahl" #'datum1)) 937 ((_ datum1 datum2 ...) 938 (boolean? (syntax->datum #'datum1)) 939 (raise-operator-error "kein boolesches Literal" #'datum1)) 940 ((_ datum1 datum2 ...) 941 (string? (syntax->datum #'datum1)) 942 (raise-operator-error "keine Zeichenkette" #'datum1)) 943 ((_ datum1 datum2 ...) 944 (char? (syntax->datum #'datum1)) 945 (raise-operator-error "kein Zeichen" #'datum1)) 946 ((_ datum1 datum2 ...) 947 (syntax/loc stx (#%app datum1 datum2 ...))))) 948 949(define (top/check-defined id) 950 (namespace-variable-value (syntax-e id) #t (lambda () (raise-not-bound-error id)))) 951 952(define-syntax (sdp-top stx) 953 (syntax-case stx () 954 ((_ . id) 955 ;; If we're in a module, we'll need to check that the name 956 ;; is bound.... 957 (if (not (identifier-binding #'id)) 958 (if (syntax-source-module #'id) 959 ;; ... but it might be defined later in the module, so 960 ;; delay the check. 961 (stepper-ignore-checker 962 (syntax/loc stx (#%app values (sdp-top-continue id)))) 963 ;; identifier-finding only returns useful information when inside a module. 964 ;; At the top-level we need to do the check at runtime. Also, note that at 965 ;; the top level there is no need for stepper annotations 966 (syntax/loc stx (#%app top/check-defined #'id))) 967 968 (syntax/loc stx (#%top . id)))))) 969 970(define-syntax (sdp-top-continue stx) 971 (syntax-case stx () 972 [(_ id) 973 ;; If there's still no binding, it's an "unknown name" error. 974 (if (not (identifier-binding #'id)) 975 ;; If there's still no binding, it's an "unknown name" error. 976 (raise-not-bound-error #'id) 977 978 ;; Don't use #%top here; id might have become bound to something 979 ;; that isn't a value. 980 #'id)])) 981 982(define-teach sdp write-string 983 (lambda (s) 984 (when (not (string? s)) 985 (error "Argument von write-string ist keine Zeichenkette")) 986 (display s))) 987 988(define (write-newline) 989 (newline)) 990 991(define (violation text) 992 (error text)) 993 994(define (string->strings-list s) 995 (map (lambda (c) (make-string 1 c)) (string->list s))) 996 997(define (strings-list->string l) 998 (if (null? l) 999 "" 1000 (string-append (car l) (strings-list->string (cdr l))))) 1001 1002(define integer (signature/arbitrary arbitrary-integer integer (predicate integer?))) 1003(define (integer-from-to lo hi) 1004 (unless (integer? lo) 1005 (error "Erstes Argument von integer-from-to ist keine ganze Zahl.")) 1006 (unless (integer? hi) 1007 (error "Zweites Argument von integer-from-to ist keine ganze Zahl.")) 1008 (unless (<= lo hi) 1009 (error "Das erste Argument von integer-from-to ist größer als das zweite.")) 1010 (signature/arbitrary (arbitrary-integer-from-to lo hi) integer-from-to 1011 (predicate (lambda (n) 1012 (and (integer? n) 1013 (<= lo n hi)))))) 1014(define number (signature/arbitrary arbitrary-real number (predicate number?))) 1015(define rational (signature/arbitrary arbitrary-rational rational (predicate rational?))) 1016(define real (signature/arbitrary arbitrary-real real (predicate real?))) 1017 1018(define (natural? x) 1019 (and (integer? x) 1020 (not (negative? x)))) 1021 1022(define natural (signature/arbitrary arbitrary-natural natural (predicate natural?))) 1023 1024(define boolean (signature/arbitrary arbitrary-boolean boolean (predicate boolean?))) 1025 1026(define (true? x) 1027 (eq? x #t)) 1028 1029(define (false? x) 1030 (eq? x #f)) 1031 1032(define true (signature true (enum #t))) 1033(define false (signature false (enum #f))) 1034 1035(define string (signature/arbitrary arbitrary-printable-ascii-string string (predicate string?))) 1036(define symbol (signature/arbitrary arbitrary-symbol symbol (predicate symbol?))) 1037(define empty-list (signature empty-list (enum empty))) 1038 1039(define unspecific (signature unspecific %unspecific)) 1040(define any (signature any %any)) 1041 1042;; aus collects/lang/private/teach.rkt 1043 1044;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1045;; dots (.. and ... and .... and ..... and ......) 1046;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1047 1048;; Syntax Identifier -> Expression 1049;; Produces an expression which raises an error reporting unfinished code. 1050(define-for-syntax (dots-error stx name) 1051 (quasisyntax/loc stx 1052 (error (quote (unsyntax name)) 1053 "Fertiger Ausdruck erwartet, aber da sind noch Ellipsen"))) 1054 1055;; Expression -> Expression 1056;; Transforms unfinished code (... and the like) to code 1057;; raising an appropriate error. 1058(define-syntax sdp-dots 1059 (make-set!-transformer 1060 (lambda (stx) 1061 (syntax-case stx (set!) 1062 [(set! form expr) (dots-error stx (syntax form))] 1063 [(form . rest) (dots-error stx (syntax form))] 1064 [form (dots-error stx stx)])))) 1065 1066(define-syntaxes (sdp-set! sdp-set!-continue) 1067 (let ((proc 1068 (lambda (continuing?) 1069 (lambda (stx) 1070 (ensure-expression 1071 stx 1072 (lambda () 1073 (syntax-case stx () 1074 ((_ id expr) 1075 (identifier? (syntax id)) 1076 (begin 1077 ;; Check that id isn't syntax, and not lexical. 1078 ((with-handlers ((exn:fail? (lambda (exn) void))) 1079 ;; First try syntax: 1080 ;; If it's a transformer binding, then it can take care of itself... 1081 (if (set!-transformer? (syntax-local-value (syntax id))) 1082 void ;; no lex check wanted 1083 (lambda () 1084 (raise-sdp-syntax-error 1085 #f 1086 "Nach set! wird eine gebundene Variable erwartet, aber da ist ein Schlüsselwort." 1087 stx))))) 1088 ;; If we're in a module, we'd like to check here whether 1089 ;; the identier is bound, but we need to delay that check 1090 ;; in case the id is defined later in the module. So only 1091 ;; do this in continuing mode: 1092 (when continuing? 1093 (when (and (not (identifier-binding #'id)) 1094 (syntax-source-module #'id)) 1095 (raise-sdp-syntax-error #f "Ungebundene Variable" #'id))) 1096 (if continuing? 1097 (syntax/loc stx (set! id expr)) 1098 (stepper-ignore-checker (syntax/loc stx (#%app values (sdp-set!-continue id expr))))))) 1099 ((_ id expr) 1100 (raise-sdp-syntax-error 1101 #f 1102 "Nach set! wird eine Variable aber da ist etwas anderes." 1103 #'id)) 1104 ((_ id) 1105 (raise-sdp-syntax-error 1106 #f 1107 "Nach set! wird eine Variable und ein Ausdruck erwartet - der Ausdruck fehlt." 1108 stx)) 1109 ((_) 1110 (raise-sdp-syntax-error 1111 #f 1112 "Nach set! wird eine Variable und ein Ausdruck erwartet, aber da ist nichts." 1113 stx)) 1114 (_else 1115 (raise-sdp-syntax-error 1116 #f 1117 "Inkorrekter set!-Ausdruck." 1118 stx))))))))) 1119 (values (proc #f) 1120 (proc #t)))) 1121 1122; QuickCheck 1123 1124(define-syntax (for-all stx) 1125 (syntax-case stx () 1126 ((_ (?clause ...) ?body0 ?body ...) 1127 (with-syntax ((((?id ?arb) ...) 1128 (map (lambda (pr) 1129 (syntax-case pr () 1130 ((?id ?signature) 1131 (identifier? #'?id) 1132 (with-syntax ((?error-call 1133 (syntax/loc #'?signature (error "Signatur hat keinen Generator")))) 1134 #'(?id 1135 (or (signature-arbitrary (signature ?signature)) 1136 ?error-call)))) 1137 (_ 1138 (raise-sdp-syntax-error #f "inkorrekte `for-all'-Klausel - sollte die Form (id signature) haben" 1139 pr)))) 1140 (syntax->list #'(?clause ...))))) 1141 1142 (stepper-syntax-property #'(quickcheck:property 1143 ((?id ?arb) ...) ?body0 ?body ...) 1144 'stepper-skip-completely 1145 #t))) 1146 ((_ ?something ?body0 ?body ...) 1147 (raise-sdp-syntax-error #f "keine Klauseln der Form (id contr)" 1148 stx)) 1149 ((_ ?something) 1150 (raise-sdp-syntax-error #f "Rumpf fehlt" stx)))) 1151 1152 1153(define-syntax (check-property stx) 1154 (unless (memq (syntax-local-context) '(module top-level)) 1155 (raise-sdp-syntax-error 1156 #f "`check-property' muss ganz außen stehen" stx)) 1157 (syntax-case stx () 1158 ((_ ?prop) 1159 (stepper-syntax-property 1160 (check-expect-maker stx #'check-property-error #'?prop '() 1161 'comes-from-check-property) 1162 'stepper-replace 1163 #'#t)) 1164 (_ (raise-sdp-syntax-error #f "`check-property' erwartet einen einzelnen Operanden" 1165 stx)))) 1166 1167(define quickcheck-config 1168 (make-config 100 1169 2000 1170 (lambda (n) 1171 (+ 3 (* n 2))) 1172 values)) 1173 1174(define (check-property-error test srcloc) 1175 (with-handlers ((exn:fail? 1176 (lambda (e) 1177 (add-failed-check! (failed-check (property-error srcloc e) 1178 (exn-srcloc e)))))) 1179 (call-with-values 1180 (lambda () 1181 (with-handlers 1182 ((exn:assertion-violation? 1183 (lambda (e) 1184 ;; minor kludge to produce comprehensible error message 1185 (if (eq? (exn:assertion-violation-who e) 'coerce->result-generator) 1186 (raise (make-exn:fail (string-append "Wert muss Eigenschaft oder boolesch sein: " 1187 ((error-value->string-handler) 1188 (car (exn:assertion-violation-irritants e)) 1189 100)) 1190 (exn-continuation-marks e))) 1191 (raise e))))) 1192 (check-results quickcheck-config (test)))) 1193 (lambda (ntest stamps result) 1194 (if (check-result? result) 1195 (begin 1196 (add-failed-check! (failed-check (property-fail srcloc result) #f)) 1197 #f) 1198 #t))))) 1199 1200(define (expect v1 v2) 1201 (quickcheck:property () (teach-equal? v1 v2))) 1202 1203(define (ensure-real who n val) 1204 (unless (real? val) 1205 (raise 1206 (make-exn:fail:contract 1207 (string->immutable-string 1208 (format "~a Argument ~e zu `~a' keine reelle Zahl." n val who)) 1209 (current-continuation-marks))))) 1210 1211(define (expect-within v1 v2 epsilon) 1212 (ensure-real 'expect-within "Drittes" epsilon) 1213 (quickcheck:property () (beginner-equal~? v1 v2 epsilon))) 1214 1215(define (expect-range val min max) 1216 (ensure-real 'expect-range "Erstes" val) 1217 (ensure-real 'expect-range "Zweites" min) 1218 (ensure-real 'expect-range "Drittes" max) 1219 (quickcheck:property () 1220 (and (<= min val) 1221 (<= val max)))) 1222 1223(define (expect-member-of val . candidates) 1224 (quickcheck:property () 1225 (ormap (lambda (cand) 1226 (teach-equal? val cand)) 1227 candidates))) 1228 1229(define property (signature (predicate (lambda (x) 1230 (or (boolean? x) 1231 (property? x)))))) 1232 1233 1234(define-syntax (match stx) 1235 (syntax-parse stx 1236 ((_ ?case:expr (?pattern0 ?body0:expr) (?pattern ?body:expr) ...) 1237 (let () 1238 (define (pattern-variables pat) 1239 (syntax-case pat (empty sdp-cons list quote ...) 1240 ((... ...) '()) 1241 (empty '()) 1242 (?var (identifier? #'?var) 1243 (if (eq? (syntax->datum #'?var) '_) 1244 '() 1245 (list #'?var))) 1246 (?lit (let ((d (syntax->datum #'?lit))) 1247 (or (string? d) (number? d) (boolean? d))) 1248 '()) 1249 ('?lit '()) 1250 ((sdp-cons ?pat1 ?pat2) 1251 (append (pattern-variables #'?pat1) (pattern-variables #'?pat2))) 1252 ((list) '()) 1253 ((list ?pat0 ?pat ...) 1254 (apply append (map pattern-variables (syntax->list #'(?pat0 ?pat ...))))) 1255 ((?const ?pat ...) 1256 (apply append (map pattern-variables (syntax->list #'(?pat ...))))))) 1257 (define (check pat) 1258 (let loop ((vars (pattern-variables pat))) 1259 (when (pair? vars) 1260 (let ((var (car vars))) 1261 (when (memf (lambda (other-var) 1262 (free-identifier=? var other-var)) 1263 (cdr vars)) 1264 (raise-sdp-syntax-error #f "Variable in match-Zweig kommt doppelt vor" 1265 var)) 1266 (loop (cdr vars)))))) 1267 (for-each check (syntax->list #'(?pattern0 ?pattern ...))) 1268 #'(let* ((val ?case) 1269 (nomatch (lambda () (match val (?pattern ?body) ...)))) 1270 (match-helper val ?pattern0 ?body0 (nomatch))))) 1271 ((_ ?case:expr) 1272 (syntax/loc stx (error 'match "keiner der Zweige passte"))))) 1273 1274 1275(define (list-length=? lis n) 1276 (cond 1277 ((zero? n) (null? lis)) 1278 ((null? lis) #f) 1279 (else 1280 (list-length=? (cdr lis) (- n 1))))) 1281 1282(define-syntax (match-helper stx) 1283 (syntax-case stx () 1284 ((_ ?id ?pattern0 ?body0 ?nomatch) 1285 (syntax-case #'?pattern0 (empty cons list quote ...) 1286 (empty 1287 #'(if (null? ?id) 1288 ?body0 1289 ?nomatch)) 1290 ((... ...) 1291 #'?body0) 1292 (?var (identifier? #'?var) 1293 (if (eq? (syntax->datum #'?var) '_) ; _ is magic 1294 #'?body0 1295 #'(let ((?var ?id)) 1296 ?body0))) 1297 (?lit (let ((d (syntax->datum #'?lit))) 1298 (or (string? d) (number? d) (boolean? d))) 1299 #'(if (equal? ?id ?lit) 1300 ?body0 1301 ?nomatch)) 1302 ('?lit 1303 #'(if (equal? ?id '?lit) 1304 ?body0 1305 ?nomatch)) 1306 ((cons ?pat1 ?pat2) 1307 #'(if (pair? ?id) 1308 (let ((f (first ?id)) 1309 (r (rest ?id))) 1310 (match-helper f ?pat1 1311 (match-helper r ?pat2 ?body0 ?nomatch) 1312 ?nomatch)) 1313 ?nomatch)) 1314 ((list) 1315 #'(if (null? ?id) 1316 ?body0 1317 ?nomatch)) 1318 ((list ?pat0 ?pat ...) 1319 (let* ((pats (syntax->list #'(?pat0 ?pat ...))) 1320 (cars (generate-temporaries pats)) 1321 (cdrs (generate-temporaries pats))) 1322 #`(if (and (pair? ?id) 1323 (list-length=? ?id #,(length pats))) 1324 #,(let recur ((ccdr #'?id) 1325 (pats pats) 1326 (cars cars) (cdrs cdrs)) 1327 (if (null? pats) 1328 #'?body0 1329 #`(let ((#,(car cars) (car #,ccdr)) 1330 (#,(car cdrs) (cdr #,ccdr))) 1331 (match-helper #,(car cars) #,(car pats) 1332 #,(recur (car cdrs) (cdr pats) (cdr cars) (cdr cdrs)) 1333 ?nomatch)))) 1334 ?nomatch))) 1335 ((?const ?pat ...) 1336 (identifier? #'?const) 1337 (let* ((fail (lambda () 1338 (raise-sdp-syntax-error #f "Operator in match muss ein Record-Konstruktor sein" 1339 #'?const))) 1340 (v (syntax-local-value #'?const fail))) 1341 (unless (struct-info? v) 1342 (fail)) 1343 1344 (apply 1345 (lambda (_ _cons pred rev-selectors _mutators ?) 1346 (let* ((pats (syntax->list #'(?pat ...))) 1347 (selectors (reverse rev-selectors)) 1348 (field-ids (generate-temporaries pats))) 1349 (unless (= (length rev-selectors) (length pats)) 1350 (raise-sdp-syntax-error #f "Die Anzahl der Felder im match stimmt nicht" #'?pattern0)) 1351 #`(if (#,pred ?id) 1352 #,(let recur ((pats pats) 1353 (selectors selectors) 1354 (field-ids field-ids)) 1355 (if (null? pats) 1356 #'?body0 1357 #`(let ((#,(car field-ids) (#,(car selectors) ?id))) 1358 (match-helper #,(car field-ids) #,(car pats) 1359 #,(recur (cdr pats) (cdr selectors) (cdr field-ids)) 1360 ?nomatch)))) 1361 ?nomatch))) 1362 (extract-struct-info v)))))))) 1363