|
693 | 693 | ,@locs |
694 | 694 | (call (curly ,name ,@params) ,@field-names))))) |
695 | 695 |
|
696 | | -(define (new-call Tname type-params params args field-names field-types) |
| 696 | +(define (new-call Tname type-params sparams params args field-names field-types) |
697 | 697 | (if (any kwarg? args) |
698 | 698 | (error "\"new\" does not accept keyword arguments")) |
699 | 699 | (if (length> params (length type-params)) |
700 | 700 | (error "too few type parameters specified in \"new{...}\"")) |
701 | | - (let ((Texpr (if (null? type-params) |
702 | | - `(outerref ,Tname) |
703 | | - `(curly (outerref ,Tname) |
704 | | - ,@type-params)))) |
| 701 | + (if (length> type-params (length params)) |
| 702 | + (error "too many type parameters specified in \"new{...}\"")) |
| 703 | + (let* ((Texpr (if (null? type-params) |
| 704 | + `(outerref ,Tname) |
| 705 | + `(curly (outerref ,Tname) |
| 706 | + ,@type-params))) |
| 707 | + (tn (make-ssavalue)) |
| 708 | + (field-convert (lambda (fld fty val) |
| 709 | + (if (equal? fty '(core Any)) |
| 710 | + val |
| 711 | + `(call (top convert) |
| 712 | + ,(if (and (equal? type-params params) (memq fty params) (memq fty sparams)) |
| 713 | + fty ; the field type is a simple parameter, the usage here is of a |
| 714 | + ; local variable (currently just handles sparam) for the bijection of params to type-params |
| 715 | + `(call (core fieldtype) ,tn ,(+ fld 1))) |
| 716 | + ,val))))) |
705 | 717 | (cond ((length> (filter (lambda (a) (not (vararg? a))) args) (length field-names)) |
706 | 718 | `(call (core throw) (call (top ArgumentError) |
707 | 719 | ,(string "new: too many arguments (expected " (length field-names) ")")))) |
708 | 720 | ((any vararg? args) |
709 | 721 | (if (every (lambda (ty) (equal? ty '(core Any))) |
710 | 722 | field-types) |
711 | 723 | `(splatnew ,Texpr (call (core tuple) ,@args)) |
712 | | - (let ((tn (make-ssavalue))) |
| 724 | + (let ((argt (make-ssavalue)) |
| 725 | + (nf (make-ssavalue))) |
713 | 726 | `(block |
714 | 727 | (= ,tn ,Texpr) |
715 | | - (splatnew ,tn (call (top convert_prefix) |
716 | | - (curly (core Tuple) |
717 | | - ,@(map (lambda (fld) |
718 | | - `(call (core fieldtype) ,tn (quote ,fld))) |
719 | | - field-names)) |
720 | | - (call (core tuple) ,@args))))))) |
| 728 | + (= ,argt (call (core tuple) ,@args)) |
| 729 | + (= ,nf (call (core nfields) ,argt)) |
| 730 | + (if (call (top ult_int) ,nf ,(length field-names)) |
| 731 | + (call (core throw) (call (top ArgumentError) |
| 732 | + ,(string "new: too few arguments (expected " (length field-names) ")")))) |
| 733 | + (if (call (top ult_int) ,(length field-names) ,nf) |
| 734 | + (call (core throw) (call (top ArgumentError) |
| 735 | + ,(string "new: too many arguments (expected " (length field-names) ")")))) |
| 736 | + (new ,tn ,@(map (lambda (fld fty) (field-convert fld fty `(call (core getfield) ,argt ,(+ fld 1) false))) |
| 737 | + (iota (length field-names)) (list-head field-types (length field-names)))))))) |
721 | 738 | (else |
722 | | - (if (equal? type-params params) |
723 | | - `(new ,Texpr ,@(map (lambda (fty val) |
724 | | - (if (equal? fty '(core Any)) |
725 | | - val |
726 | | - `(call (top convert) ,fty ,val))) |
727 | | - (list-head field-types (length args)) args)) |
728 | | - (let ((tn (make-ssavalue))) |
729 | | - `(block |
730 | | - (= ,tn ,Texpr) |
731 | | - (new ,tn ,@(map (lambda (fld val) |
732 | | - `(call (top convert) |
733 | | - (call (core fieldtype) ,tn (quote ,fld)) |
734 | | - ,val)) |
735 | | - (list-head field-names (length args)) args))))))))) |
| 739 | + `(block |
| 740 | + (= ,tn ,Texpr) |
| 741 | + (new ,tn ,@(map field-convert (iota (length args)) (list-head field-types (length args)) args))))))) |
736 | 742 |
|
737 | 743 | ;; insert item at start of arglist |
738 | 744 | (define (arglist-unshift sig item) |
|
745 | 751 | ((length= lno 3) (string " around " (caddr lno) ":" (cadr lno))) |
746 | 752 | (else ""))) |
747 | 753 |
|
748 | | -(define (ctor-def name Tname params bounds sig ctor-body body wheres) |
| 754 | +(define (ctor-def name Tname ctor-body sig body wheres) |
749 | 755 | (let* ((curly? (and (pair? name) (eq? (car name) 'curly))) |
750 | 756 | (curlyargs (if curly? (cddr name) '())) |
751 | | - (name (if curly? (cadr name) name))) |
| 757 | + (name (if curly? (cadr name) name)) |
| 758 | + (sparams (map car (map analyze-typevar wheres)))) |
752 | 759 | (cond ((not (eq? name Tname)) |
753 | 760 | `(function ,(with-wheres `(call ,(if curly? |
754 | 761 | `(curly ,name ,@curlyargs) |
|
757 | 764 | wheres) |
758 | 765 | ;; pass '() in order to require user-specified parameters with |
759 | 766 | ;; new{...} inside a non-ctor inner definition. |
760 | | - ,(ctor-body body '()))) |
| 767 | + ,(ctor-body body '() sparams))) |
761 | 768 | (else |
762 | 769 | `(function ,(with-wheres `(call ,(if curly? |
763 | 770 | `(curly ,name ,@curlyargs) |
764 | 771 | name) |
765 | 772 | ,@sig) |
766 | 773 | wheres) |
767 | | - ,(ctor-body body curlyargs)))))) |
| 774 | + ,(ctor-body body curlyargs sparams)))))) |
768 | 775 |
|
769 | 776 | (define (function-body-lineno body) |
770 | 777 | (let ((lnos (filter linenum? body))) |
771 | 778 | (if (null? lnos) '() (car lnos)))) |
772 | 779 |
|
773 | 780 | ;; rewrite calls to `new( ... )` to `new` expressions on the appropriate |
774 | 781 | ;; type, determined by the containing constructor definition. |
775 | | -(define (rewrite-ctor ctor Tname params bounds field-names field-types) |
776 | | - (define (ctor-body body type-params) |
| 782 | +(define (rewrite-ctor ctor Tname params field-names field-types) |
| 783 | + (define (ctor-body body type-params sparams) |
777 | 784 | (pattern-replace (pattern-set |
778 | 785 | (pattern-lambda |
779 | 786 | (call (-/ new) . args) |
780 | | - (new-call Tname type-params params |
781 | | - (map (lambda (a) (ctor-body a type-params)) args) |
| 787 | + (new-call Tname type-params sparams params |
| 788 | + (map (lambda (a) (ctor-body a type-params sparams)) args) |
782 | 789 | field-names field-types)) |
783 | 790 | (pattern-lambda |
784 | 791 | (call (curly (-/ new) . p) . args) |
785 | | - (new-call Tname p params |
786 | | - (map (lambda (a) (ctor-body a type-params)) args) |
| 792 | + (new-call Tname p sparams params |
| 793 | + (map (lambda (a) (ctor-body a type-params sparams)) args) |
787 | 794 | field-names field-types))) |
788 | 795 | body)) |
789 | 796 | (pattern-replace |
790 | 797 | (pattern-set |
791 | 798 | ;; definitions without `where` |
792 | 799 | (pattern-lambda (function (-$ (call name . sig) (|::| (call name . sig) _t)) body) |
793 | | - (ctor-def name Tname params bounds sig ctor-body body #f)) |
| 800 | + (ctor-def name Tname ctor-body sig body #f)) |
794 | 801 | (pattern-lambda (= (-$ (call name . sig) (|::| (call name . sig) _t)) body) |
795 | | - (ctor-def name Tname params bounds sig ctor-body body #f)) |
| 802 | + (ctor-def name Tname ctor-body sig body #f)) |
796 | 803 | ;; definitions with `where` |
797 | 804 | (pattern-lambda (function (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body) |
798 | | - (ctor-def name Tname params bounds sig ctor-body body wheres)) |
| 805 | + (ctor-def name Tname ctor-body sig body wheres)) |
799 | 806 | (pattern-lambda (= (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body) |
800 | | - (ctor-def name Tname params bounds sig ctor-body body wheres))) |
| 807 | + (ctor-def name Tname ctor-body sig body wheres))) |
801 | 808 |
|
802 | 809 | ;; flatten `where`s first |
803 | 810 | (pattern-replace |
|
853 | 860 | (block |
854 | 861 | (global ,name) |
855 | 862 | ,@(map (lambda (c) |
856 | | - (rewrite-ctor c name params bounds field-names field-types)) |
| 863 | + (rewrite-ctor c name params field-names field-types)) |
857 | 864 | defs2))) |
858 | 865 | ;; "outer" constructors |
859 | 866 | ,@(if (and (null? defs) |
|
0 commit comments