|
337 | 337 |
|
338 | 338 | ;; construct the (method ...) expression for one primitive method definition, |
339 | 339 | ;; assuming optional and keyword args are already handled |
340 | | -(define (method-def-expr- name sparams argl body (rett '(core Any))) |
| 340 | +(define (method-def-expr- name sparams argl argl-stmts body (rett '(core Any))) |
341 | 341 | (if |
342 | 342 | (any kwarg? argl) |
343 | 343 | ;; has optional positional args |
|
356 | 356 | (dfl (map caddr kws))) |
357 | 357 | (receive |
358 | 358 | (vararg req) (separate vararg? argl) |
359 | | - (optional-positional-defs name sparams req opt dfl body |
| 359 | + (optional-positional-defs name sparams req opt dfl argl-stmts body |
360 | 360 | (append req opt vararg) rett))))) |
361 | 361 | ;; no optional positional args |
362 | 362 | (let* ((names (map car sparams)) |
|
442 | 442 | ,@(map make-assignment names vals) |
443 | 443 | ,expr)) |
444 | 444 |
|
445 | | -(define (keywords-method-def-expr name sparams argl body rett) |
| 445 | +(define (keywords-method-def-expr name sparams argl argl-stmts body rett) |
446 | 446 | (let* ((kargl (cdar argl)) ;; keyword expressions (= k v) |
447 | 447 | (annotations (map (lambda (a) `(meta ,(cadr a) ,(arg-name (cadr (caddr a))))) |
448 | 448 | (filter nospecialize-meta? kargl))) |
|
530 | 530 | ;; strip type off function self argument if not needed for a static param. |
531 | 531 | ;; then it is ok for cl-convert to move this definition above the original def. |
532 | 532 | ,@not-optional ,@vararg) |
| 533 | + argl-stmts |
533 | 534 | (insert-after-meta `(block |
534 | 535 | ,@stmts) |
535 | 536 | (cons `(meta nkw ,(+ (length vars) (length restkw))) |
|
538 | 539 |
|
539 | 540 | ;; call with no keyword args |
540 | 541 | ,(method-def-expr- |
541 | | - name positional-sparams pargl-all |
| 542 | + name positional-sparams pargl-all argl-stmts |
542 | 543 | `(block |
543 | 544 | ,@(keep-first linenum? (without-generated prologue)) |
| 545 | + ,@(filter identity argl-stmts) |
544 | 546 | ,(let (;; call mangled(vals..., [rest_kw,] pargs..., [vararg]...) |
545 | 547 | (ret `(return (call ,mangled |
546 | 548 | ,@(if ordered-defaults keynames vals) |
|
558 | 560 | ;; if there are optional positional args, we need to be able to reference the function name |
559 | 561 | ,(if (any kwarg? `(,@pargl ,@vararg)) (gensy) UNUSED) |
560 | 562 | (call (core kwftype) ,ftype)) ,kwdecl ,@pargl ,@vararg) |
| 563 | + argl-stmts |
561 | 564 | `(block |
562 | 565 | ;; propagate method metadata to keyword sorter |
563 | 566 | ,@(map propagate-method-meta (filter meta? prologue)) |
|
571 | 574 | `(meta ,(cadr m) ,@(filter (lambda (v) (not (memq v keynames))) |
572 | 575 | (cddr m)))) |
573 | 576 | (filter nospecialize-meta? prologue)) |
| 577 | + ,@(filter identity argl-stmts) |
574 | 578 | ;; If not using slots for the keyword argument values, still declare them |
575 | 579 | ;; for reflection purposes. |
576 | 580 | ,@(if ssa-keyvars? |
|
655 | 659 | (else |
656 | 660 | (loop filtered (cdr params)))))) |
657 | 661 |
|
658 | | -(define (optional-positional-defs name sparams req opt dfl body overall-argl rett) |
| 662 | +;; Get the list of all symbols introduced either by the `args` or by any |
| 663 | +;; destructuring expression for that arg in `argl-stmts`. |
| 664 | +(define (arg-introduced-syms args argl-stmts) |
| 665 | + (apply append! (map |
| 666 | + (lambda (arg stmt) |
| 667 | + (if stmt (find-assigned-vars stmt) (list arg))) |
| 668 | + args argl-stmts))) |
| 669 | + |
| 670 | +(define (optional-positional-defs name sparams req opt dfl argl-stmts body overall-argl rett) |
659 | 671 | (let ((prologue (without-generated (extract-method-prologue body)))) |
660 | 672 | `(block |
661 | 673 | ,@(map (lambda (n) |
662 | 674 | (let* ((passed (append req (list-head opt n))) |
663 | 675 | ;; only keep static parameters used by these arguments |
664 | | - (sp (filter-sparams (cons 'list passed) sparams)) |
665 | | - (vals (list-tail dfl n)) |
666 | | - (absent (list-tail opt n)) ;; absent arguments |
| 676 | + (sp (filter-sparams (cons 'list passed) sparams)) |
| 677 | + (vals (list-tail dfl n)) |
| 678 | + (absent (list-tail opt n)) ;; absent arguments |
| 679 | + (absent-syms (arg-introduced-syms absent (list-tail argl-stmts n))) |
| 680 | + (passed-stmts (list-head argl-stmts (+ (length req) n))) |
667 | 681 | (body |
668 | 682 | (if (any vararg? (butlast vals)) |
669 | 683 | ;; Forbid splat in all but the final default value |
|
674 | 688 | ;; contain "e" such that... |
675 | 689 | (any (lambda (a) |
676 | 690 | ;; "e" is in an absent arg |
| 691 | + ;; (or other symbol introduced |
| 692 | + ;; by destructuring an absent arg) |
677 | 693 | (contains (lambda (u) |
678 | 694 | (eq? u e)) |
679 | 695 | a)) |
680 | | - absent)) |
| 696 | + absent-syms)) |
681 | 697 | defaultv)) |
682 | 698 | vals) |
683 | 699 | ;; then add only one next argument |
684 | 700 | `(block |
685 | 701 | ,@prologue |
| 702 | + ,@(filter identity passed-stmts) |
686 | 703 | (call ,(arg-name (car req)) ,@(map arg-name (cdr passed)) ,(car vals))) |
687 | 704 | ;; otherwise add all |
688 | 705 | `(block |
689 | 706 | ,@prologue |
| 707 | + ,@(filter identity passed-stmts) |
690 | 708 | (call ,(arg-name (car req)) ,@(map arg-name (cdr passed)) ,@vals)))))) |
691 | | - (method-def-expr- name sp passed body))) |
| 709 | + (method-def-expr- name sp passed argl-stmts body))) |
692 | 710 | (iota (length opt))) |
693 | | - ,(method-def-expr- name sparams overall-argl body rett)))) |
| 711 | + ,(method-def-expr- name sparams overall-argl argl-stmts body rett)))) |
694 | 712 |
|
695 | 713 | ;; strip empty (parameters ...), normalizing `f(x;)` to `f(x)`. |
696 | 714 | (define (remove-empty-parameters argl) |
|
729 | 747 | ;; definitions without keyword arguments are passed to method-def-expr-, |
730 | 748 | ;; which handles optional positional arguments by adding the needed small |
731 | 749 | ;; boilerplate definitions. |
732 | | -(define (method-def-expr name sparams argl body rett) |
| 750 | +(define (method-def-expr name sparams argl argl-stmts body rett) |
733 | 751 | (let ((argl (throw-unassigned-kw-args (remove-empty-parameters argl)))) |
734 | 752 | (if (has-parameters? argl) |
735 | 753 | ;; has keywords |
736 | 754 | (begin (check-kw-args (cdar argl)) |
737 | | - (keywords-method-def-expr name sparams argl body rett)) |
| 755 | + (keywords-method-def-expr name sparams argl argl-stmts body rett)) |
738 | 756 | ;; no keywords |
739 | | - (method-def-expr- name sparams argl body rett)))) |
| 757 | + (method-def-expr- name sparams argl argl-stmts body rett)))) |
740 | 758 |
|
741 | 759 | (define (struct-def-expr name params super fields mut) |
742 | 760 | (receive |
|
1184 | 1202 | (reverse (cons '(null) stmts)))) |
1185 | 1203 | (let ((a (transform-arg (car argl)))) |
1186 | 1204 | (loop (cdr argl) (cons (car a) newa) |
1187 | | - (if (cdr a) (cons (cdr a) stmts) stmts)))))) |
| 1205 | + (cons (cdr a) stmts)))))) |
1188 | 1206 |
|
1189 | 1207 | (define (expand-function-def- e) |
1190 | 1208 | (let* ((name (cadr e)) |
|
1226 | 1244 | (farg (if (decl? argname) |
1227 | 1245 | (adj-decl argname) |
1228 | 1246 | `(|::| |#self#| (call (core Typeof) ,argname)))) |
1229 | | - (body (insert-after-meta body (cdr argl-stmts))) |
| 1247 | + (body (insert-after-meta body (filter identity (cdr argl-stmts)))) |
1230 | 1248 | (argl (cdr argl)) |
1231 | 1249 | (argl (fix-arglist |
1232 | 1250 | (arglist-unshift argl farg) |
|
1236 | 1254 | (name (if (or (decl? name) (and (pair? name) (memq (car name) '(curly where)))) |
1237 | 1255 | #f name))) |
1238 | 1256 | (expand-forms |
1239 | | - (method-def-expr name sparams argl body rett)))) |
| 1257 | + (method-def-expr name sparams argl (cdr argl-stmts) body rett)))) |
1240 | 1258 | (else |
1241 | 1259 | (error (string "invalid assignment location \"" (deparse name) "\"")))))) |
1242 | 1260 |
|
|
0 commit comments