|
752 | 752 | (let* ((field-names (safe-field-names field-names field-types))
|
753 | 753 | (any-ctor
|
754 | 754 | ;; definition with Any for all arguments
|
755 |
| - `(function ,(with-wheres |
756 |
| - `(call ,(if (pair? params) |
757 |
| - `(curly ,name ,@params) |
758 |
| - name) |
759 |
| - ,@field-names) |
760 |
| - (map (lambda (b) (cons 'var-bounds b)) bounds)) |
| 755 | + `(function (call (|::| |#ctor-self#| |
| 756 | + ,(with-wheres |
| 757 | + `(curly (core Type) ,(if (pair? params) |
| 758 | + `(curly ,name ,@params) |
| 759 | + name)) |
| 760 | + (map (lambda (b) (cons 'var-bounds b)) bounds))) |
| 761 | + ,@field-names) |
761 | 762 | (block
|
762 | 763 | ,@locs
|
763 | 764 | (call new ,@field-names)))))
|
|
791 | 792 | (define (num-non-varargs args)
|
792 | 793 | (count (lambda (a) (not (vararg? a))) args))
|
793 | 794 |
|
794 |
| -(define (new-call Tname type-params sparams params args field-names field-types) |
| 795 | +;; selftype?: tells us whether the called object is the type being constructed, |
| 796 | +;; i.e. `new()` and not `new{...}()`. |
| 797 | +(define (new-call Tname type-params sparams params args field-names field-types selftype?) |
795 | 798 | (if (any kwarg? args)
|
796 | 799 | (error "\"new\" does not accept keyword arguments"))
|
797 | 800 | (let ((nnv (num-non-varargs type-params)))
|
|
801 | 804 | (error "too many type parameters specified in \"new{...}\"")))
|
802 | 805 | (let* ((Texpr (if (null? type-params)
|
803 | 806 | `(outerref ,Tname)
|
804 |
| - `(curly (outerref ,Tname) |
805 |
| - ,@type-params))) |
806 |
| - (tn (make-ssavalue)) |
| 807 | + (if selftype? |
| 808 | + '|#ctor-self#| |
| 809 | + `(curly (outerref ,Tname) |
| 810 | + ,@type-params)))) |
| 811 | + (tn (if (symbol? Texpr) Texpr (make-ssavalue))) |
807 | 812 | (field-convert (lambda (fld fty val)
|
808 | 813 | (if (equal? fty '(core Any))
|
809 | 814 | val
|
810 | 815 | `(call (top convert)
|
811 |
| - ,(if (and (equal? type-params params) (memq fty params) (memq fty sparams)) |
| 816 | + ,(if (and (not selftype?) (equal? type-params params) (memq fty params) (memq fty sparams)) |
812 | 817 | fty ; the field type is a simple parameter, the usage here is of a
|
813 | 818 | ; local variable (currently just handles sparam) for the bijection of params to type-params
|
814 | 819 | `(call (core fieldtype) ,tn ,(+ fld 1)))
|
|
823 | 828 | (let ((argt (make-ssavalue))
|
824 | 829 | (nf (make-ssavalue)))
|
825 | 830 | `(block
|
826 |
| - (= ,tn ,Texpr) |
| 831 | + ,@(if (symbol? tn) '() `((= ,tn ,Texpr))) |
827 | 832 | (= ,argt (call (core tuple) ,@args))
|
828 | 833 | (= ,nf (call (core nfields) ,argt))
|
829 | 834 | (if (call (top ult_int) ,nf ,(length field-names))
|
|
835 | 840 | (new ,tn ,@(map (lambda (fld fty) (field-convert fld fty `(call (core getfield) ,argt ,(+ fld 1) (false))))
|
836 | 841 | (iota (length field-names)) (list-head field-types (length field-names))))))))
|
837 | 842 | (else
|
838 |
| - `(block |
839 |
| - (= ,tn ,Texpr) |
840 |
| - (new ,tn ,@(map field-convert (iota (length args)) (list-head field-types (length args)) args))))))) |
| 843 | + `(block |
| 844 | + ,@(if (symbol? tn) '() `((= ,tn ,Texpr))) |
| 845 | + (new ,tn ,@(map field-convert (iota (length args)) (list-head field-types (length args)) args))))))) |
841 | 846 |
|
842 | 847 | ;; insert item at start of arglist
|
843 | 848 | (define (arglist-unshift sig item)
|
|
850 | 855 | ((length= lno 3) (string " around " (caddr lno) ":" (cadr lno)))
|
851 | 856 | (else "")))
|
852 | 857 |
|
| 858 | +;; convert constructor signature from X(...) to (|#ctor-self#|::Type{X})(...), |
| 859 | +;; or return #f if we can't |
| 860 | +(define (ctor-sig sig) |
| 861 | + (cond ((or (eq? (car sig) '|::|) (eq? (car sig) 'where)) |
| 862 | + (let ((s2 (ctor-sig (cadr sig)))) |
| 863 | + (and s2 `(,(car sig) ,s2 ,@(cddr sig))))) |
| 864 | + ((eq? (car sig) 'call) |
| 865 | + (let ((head (cadr sig))) |
| 866 | + (if (decl? head) |
| 867 | + (if (eq? (cadr head) '|#ctor-self#|) |
| 868 | + sig ;; already in the required form |
| 869 | + #f) |
| 870 | + `(call (|::| |#ctor-self#| (curly (core Type) ,head)) ,@(cddr sig))))) |
| 871 | + (else #f))) |
| 872 | + |
853 | 873 | (define (ctor-def name Tname ctor-body sig body wheres)
|
854 | 874 | (let* ((curly? (and (pair? name) (eq? (car name) 'curly)))
|
855 | 875 | (curlyargs (if curly? (cddr name) '()))
|
856 | 876 | (name (if curly? (cadr name) name))
|
857 | 877 | (sparams (map car (map analyze-typevar wheres))))
|
858 | 878 | (cond ((not (eq? name Tname))
|
859 |
| - `(function ,(with-wheres `(call ,(if curly? |
860 |
| - `(curly ,name ,@curlyargs) |
861 |
| - name) |
862 |
| - ,@sig) |
863 |
| - wheres) |
| 879 | + `(function ,sig |
864 | 880 | ;; pass '() in order to require user-specified parameters with
|
865 | 881 | ;; new{...} inside a non-ctor inner definition.
|
866 |
| - ,(ctor-body body '() sparams))) |
| 882 | + ,(ctor-body body '() sparams #f))) |
867 | 883 | (else
|
868 |
| - `(function ,(with-wheres `(call ,(if curly? |
869 |
| - `(curly ,name ,@curlyargs) |
870 |
| - name) |
871 |
| - ,@sig) |
872 |
| - wheres) |
873 |
| - ,(ctor-body body curlyargs sparams)))))) |
| 884 | + (let ((newsig (ctor-sig sig))) |
| 885 | + `(function ,(or newsig sig) |
| 886 | + ,(ctor-body body curlyargs sparams (not (not newsig))))))))) |
874 | 887 |
|
875 | 888 | ;; rewrite calls to `new( ... )` to `new` expressions on the appropriate
|
876 | 889 | ;; type, determined by the containing constructor definition.
|
877 | 890 | (define (rewrite-ctor ctor Tname params field-names field-types)
|
878 |
| - (define (ctor-body body type-params sparams) |
| 891 | + (define (ctor-body body type-params sparams selftype?) |
879 | 892 | (pattern-replace (pattern-set
|
880 | 893 | (pattern-lambda
|
881 | 894 | (call (-/ new) . args)
|
882 | 895 | (new-call Tname type-params sparams params
|
883 |
| - (map (lambda (a) (ctor-body a type-params sparams)) args) |
884 |
| - field-names field-types)) |
| 896 | + (map (lambda (a) (ctor-body a type-params sparams selftype?)) args) |
| 897 | + field-names field-types selftype?)) |
885 | 898 | (pattern-lambda
|
886 | 899 | (call (curly (-/ new) . p) . args)
|
887 | 900 | (new-call Tname p sparams params
|
888 |
| - (map (lambda (a) (ctor-body a type-params sparams)) args) |
889 |
| - field-names field-types))) |
| 901 | + (map (lambda (a) (ctor-body a type-params sparams selftype?)) args) |
| 902 | + field-names field-types #f))) |
890 | 903 | body))
|
891 | 904 | (pattern-replace
|
892 | 905 | (pattern-set
|
| 906 | + ;; recognize `(t::(Type{X{T}} where T))(...)` as an inner-style constructor for X |
| 907 | + (pattern-lambda (function (-$ (call (|::| self (where (curly (core (-/ Type)) name) . wheres)) . sig) |
| 908 | + (|::| (call (|::| self (where (curly (core (-/ Type)) name) . wheres)) . sig) _t)) |
| 909 | + body) |
| 910 | + (ctor-def name Tname ctor-body (cadr __) body wheres)) |
893 | 911 | ;; definitions without `where`
|
894 | 912 | (pattern-lambda (function (-$ (call name . sig) (|::| (call name . sig) _t)) body)
|
895 |
| - (ctor-def name Tname ctor-body sig body #f)) |
| 913 | + (ctor-def name Tname ctor-body (cadr __) body #f)) |
896 | 914 | (pattern-lambda (= (-$ (call name . sig) (|::| (call name . sig) _t)) body)
|
897 |
| - (ctor-def name Tname ctor-body sig body #f)) |
| 915 | + (ctor-def name Tname ctor-body (cadr __) body #f)) |
898 | 916 | ;; definitions with `where`
|
899 | 917 | (pattern-lambda (function (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body)
|
900 |
| - (ctor-def name Tname ctor-body sig body wheres)) |
| 918 | + (ctor-def name Tname ctor-body (cadr __) body wheres)) |
901 | 919 | (pattern-lambda (= (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body)
|
902 |
| - (ctor-def name Tname ctor-body sig body wheres))) |
| 920 | + (ctor-def name Tname ctor-body (cadr __) body wheres))) |
903 | 921 |
|
904 | 922 | ;; flatten `where`s first
|
905 | 923 | (pattern-replace
|
|
0 commit comments