|
367 | 367 | `(block (method ,name) ,mdef (unnecessary ,name)) ;; return the function
|
368 | 368 | mdef)))))
|
369 | 369 |
|
370 |
| -;; keyword default values that can be assigned right away. however, this creates |
371 |
| -;; a quasi-bug (part of issue #9535) where it can be hard to predict when a |
372 |
| -;; keyword argument will throw an UndefVarError. |
373 |
| -(define (const-default? x) |
374 |
| - (or (number? x) (string? x) (char? x) (and (pair? x) (memq (car x) '(quote inert))) |
375 |
| - (eq? x 'true) (eq? x 'false))) |
| 370 | +;; wrap expr in nested scopes assigning names to vals |
| 371 | +(define (scopenest names vals expr) |
| 372 | + (if (null? names) |
| 373 | + expr |
| 374 | + `(let (block |
| 375 | + ,(scopenest (cdr names) (cdr vals) expr)) |
| 376 | + (= ,(car names) ,(car vals))))) |
376 | 377 |
|
377 | 378 | (define empty-vector-any '(call (core AnyVector) 0))
|
378 | 379 |
|
|
434 | 435 | (rkw (if (null? restkw) '() (symbol (string (car restkw) "..."))))
|
435 | 436 | (mangled (symbol (string "#" (if name (undot-name name) 'call) "#"
|
436 | 437 | (string (current-julia-module-counter)))))
|
437 |
| - (flags (map (lambda (x) (gensy)) vals))) |
| 438 | + (tempnames (map (lambda (x) (gensy)) keynames))) |
438 | 439 | `(block
|
439 | 440 | ;; call with no keyword args
|
440 | 441 | ,(method-def-expr-
|
441 | 442 | name positional-sparams (append pargl vararg)
|
442 | 443 | `(block
|
443 | 444 | ,@prologue
|
444 |
| - ,@(if (not ordered-defaults) |
445 |
| - '() |
446 |
| - (append! (map (lambda (kwname) `(local ,kwname)) keynames) |
447 |
| - (map make-assignment keynames vals))) |
448 |
| - ;; call mangled(vals..., [rest_kw,] pargs..., [vararg]...) |
449 |
| - (return (call ,mangled |
450 |
| - ,@(if ordered-defaults keynames vals) |
451 |
| - ,@(if (null? restkw) '() (list empty-vector-any)) |
452 |
| - ,@(map arg-name pargl) |
453 |
| - ,@(if (null? vararg) '() |
454 |
| - (list `(... ,(arg-name (car vararg)))))))) |
| 445 | + ,(let (;; call mangled(vals..., [rest_kw,] pargs..., [vararg]...) |
| 446 | + (ret `(return (call ,mangled |
| 447 | + ,@(if ordered-defaults keynames vals) |
| 448 | + ,@(if (null? restkw) '() (list empty-vector-any)) |
| 449 | + ,@(map arg-name pargl) |
| 450 | + ,@(if (null? vararg) '() |
| 451 | + (list `(... ,(arg-name (car vararg))))))))) |
| 452 | + (if ordered-defaults |
| 453 | + (scopenest keynames vals ret) |
| 454 | + ret))) |
455 | 455 | #f)
|
456 | 456 |
|
457 | 457 | ;; call with keyword args pre-sorted - original method code goes here
|
|
483 | 483 | ,(if (any kwarg? pargl) (gensy) UNUSED)
|
484 | 484 | (call (core kwftype) ,ftype)) (:: ,kw (core AnyVector)) ,@pargl ,@vararg)
|
485 | 485 | `(block
|
486 |
| - ;; initialize keyword args to their defaults, or set a flag telling |
487 |
| - ;; whether this keyword needs to be set. |
488 |
| - ,@(map (lambda (kwname) `(local ,kwname)) keynames) |
489 |
| - ,@(map (lambda (name dflt flag) |
490 |
| - (if (const-default? dflt) |
491 |
| - `(= ,name ,dflt) |
492 |
| - `(= ,flag true))) |
493 |
| - keynames vals flags) |
| 486 | + ;; temp variables that will be assigned if their corresponding keywords are passed. |
| 487 | + ;; `isdefined` is then used to check whether default values should be evaluated. |
| 488 | + ,@(map (lambda (v) `(local ,v)) tempnames) |
494 | 489 | ,@(if (null? restkw) '()
|
495 | 490 | `((= ,rkw ,empty-vector-any)))
|
496 | 491 | ;; for i = 1:(length(kw)>>1)
|
|
499 | 494 | ;; ii = i*2 - 1
|
500 | 495 | (= ,ii (call (top -) (call (top *) ,i 2) 1))
|
501 | 496 | (= ,elt (call (core arrayref) ,kw ,ii))
|
502 |
| - ,(foldl (lambda (kvf else) |
503 |
| - (let* ((k (car kvf)) |
| 497 | + ,(foldl (lambda (kn else) |
| 498 | + (let* ((k (car kn)) |
504 | 499 | (rval0 `(call (core arrayref) ,kw
|
505 | 500 | (call (top +) ,ii 1)))
|
506 | 501 | ;; note: if the "declared" type of a KW arg
|
|
528 | 523 | ,T)
|
529 | 524 | T)))
|
530 | 525 | rval0)))
|
531 |
| - ;; if kw[ii] == 'k; k = kw[ii+1]::Type; end |
532 |
| - `(if (comparison ,elt === (quote ,(decl-var k))) |
533 |
| - (block |
534 |
| - (= ,(decl-var k) ,rval) |
535 |
| - ,@(if (not (const-default? (cadr kvf))) |
536 |
| - `((= ,(caddr kvf) false)) |
537 |
| - '())) |
| 526 | + ;; if kw[ii] == 'k; k_temp = kw[ii+1]::Type; end |
| 527 | + `(if (comparison ,elt === (quote ,(cdr kn))) |
| 528 | + (= ,(decl-var k) ,rval) |
538 | 529 | ,else)))
|
539 | 530 | (if (null? restkw)
|
540 | 531 | ;; if no rest kw, give error for unrecognized
|
|
547 | 538 | ,rkw (tuple ,elt
|
548 | 539 | (call (core arrayref) ,kw
|
549 | 540 | (call (top +) ,ii 1)))))
|
550 |
| - (map list vars vals flags)))) |
| 541 | + (map (lambda (k temp) |
| 542 | + (cons (if (decl? k) `(,(car k) ,temp ,(caddr k)) temp) |
| 543 | + (decl-var k))) |
| 544 | + vars tempnames)))) |
551 | 545 | ;; set keywords that weren't present to their default values
|
552 |
| - ,@(apply append |
553 |
| - (map (lambda (name dflt flag) |
554 |
| - (if (const-default? dflt) |
555 |
| - '() |
556 |
| - `((if ,flag (= ,name ,dflt))))) |
557 |
| - keynames vals flags)) |
558 |
| - ;; finally, call the core function |
559 |
| - (return (call ,mangled |
560 |
| - ,@keynames |
561 |
| - ,@(if (null? restkw) '() (list rkw)) |
562 |
| - ,@(map arg-name pargl) |
563 |
| - ,@(if (null? vararg) '() |
564 |
| - (list `(... ,(arg-name (car vararg)))))))) |
| 546 | + ,(scopenest keynames |
| 547 | + (map (lambda (v dflt) `(if (isdefined ,v) |
| 548 | + ,v |
| 549 | + ,dflt)) |
| 550 | + tempnames vals) |
| 551 | + `(return (call ,mangled ;; finally, call the core function |
| 552 | + ,@keynames |
| 553 | + ,@(if (null? restkw) '() (list rkw)) |
| 554 | + ,@(map arg-name pargl) |
| 555 | + ,@(if (null? vararg) '() |
| 556 | + (list `(... ,(arg-name (car vararg))))))))) |
565 | 557 | #f)
|
566 | 558 | ;; return primary function
|
567 | 559 | ,(if (not (symbol? name))
|
|
2590 | 2582 | glob)
|
2591 | 2583 | (if lam ;; update in-place the list of local variables in lam
|
2592 | 2584 | (set-car! (cddr lam)
|
2593 |
| - (append! (caddr lam) real-new-vars real-new-vars-def))) |
| 2585 | + (append real-new-vars real-new-vars-def (caddr lam)))) |
2594 | 2586 | (insert-after-meta ;; return the new, expanded scope-block
|
2595 | 2587 | (if (and (pair? body) (eq? (car body) 'block))
|
2596 | 2588 | body
|
|
0 commit comments