From 4a28e6a7c3d2d32d52fdaf9241726e057ea7243b Mon Sep 17 00:00:00 2001
From: Mike Nolta <mike@nolta.net>
Date: Sat, 20 Jul 2013 17:42:26 -0400
Subject: [PATCH] deprecate concatenating [a,b,...] and T[a,b,...]

closes #2488, closes #3737
---
 base/abstractarray.jl | 64 +++++++++++++++++++++++++++++++++++++------
 base/array.jl         |  4 +++
 src/julia-parser.scm  | 26 ++++++++----------
 src/julia-syntax.scm  | 53 ++++++++++++++---------------------
 4 files changed, 91 insertions(+), 56 deletions(-)

diff --git a/base/abstractarray.jl b/base/abstractarray.jl
index 0a8b5b787bfd2..9e427cfc0c6b1 100644
--- a/base/abstractarray.jl
+++ b/base/abstractarray.jl
@@ -5,6 +5,46 @@ typealias AbstractMatrix{T} AbstractArray{T,2}
 
 ## Basic functions ##
 
+vect() = Array(None, 0)
+vect{T}(X::T...) = T[ X[i] for i=1:length(X) ]
+function _vect(X...)
+    T = promote_type(map(typeof, X)...)
+    T[ X[i] for i=1:length(X) ]
+end
+
+const _oldstyle_array_vcat_ = true
+
+if _oldstyle_array_vcat_
+    function oldstyle_vcat_warning(n::Int)
+        if n == 1
+            before = "a"
+            after  = "a;"
+        elseif n == 2
+            before = "a,b"
+            after  = "a;b"
+        else
+            before = "a,b,..."
+            after  = "a;b;..."
+        end
+        warn_once("[$before] concatenation is deprecated; use [$after] instead")
+    end
+    function vect(A::AbstractArray...)
+        oldstyle_vcat_warning(length(A))
+        vcat(A...)
+    end
+    function vect(X...)
+        for a in X
+            if typeof(a) <: AbstractArray
+                oldstyle_vcat_warning(length(X))
+                break
+            end
+        end
+        vcat(X...)
+    end
+else
+    vect(X...) = _vect(X...)
+end
+
 size{T,n}(t::AbstractArray{T,n}, d) = (d>n ? 1 : size(t)[d])
 eltype(x) = Any
 eltype{T,n}(::AbstractArray{T,n}) = T
@@ -627,6 +667,11 @@ end
 ## cat: general case
 
 function cat(catdim::Integer, X...)
+    T = promote_type(map(x->isa(x,AbstractArray) ? eltype(x) : typeof(x), X)...)
+    cat_t(catdim, T, X...)
+end
+
+function cat_t(catdim::Integer, typeC::Type, X...)
     nargs = length(X)
     dimsX = map((a->isa(a,AbstractArray) ? size(a) : (1,)), X)
     ndimsX = map((a->isa(a,AbstractArray) ? ndims(a) : 1), X)
@@ -671,7 +716,6 @@ function cat(catdim::Integer, X...)
 
     ndimsC = max(catdim, d_max)
     dimsC = ntuple(ndimsC, compute_dims)::(Int...)
-    typeC = promote_type(map(x->isa(x,AbstractArray) ? eltype(x) : typeof(x), X)...)
     C = similar(isa(X[1],AbstractArray) ? full(X[1]) : [X[1]], typeC, dimsC)
 
     range = 1
@@ -687,12 +731,15 @@ end
 vcat(X...) = cat(1, X...)
 hcat(X...) = cat(2, X...)
 
+typed_vcat(T::Type, X...) = cat_t(1, T, X...)
+typed_hcat(T::Type, X...) = cat_t(2, T, X...)
+
 cat{T}(catdim::Integer, A::AbstractArray{T}...) = cat_t(catdim, T, A...)
 
 cat(catdim::Integer, A::AbstractArray...) =
     cat_t(catdim, promote_type(map(eltype, A)...), A...)
 
-function cat_t(catdim::Integer, typeC, A::AbstractArray...)
+function cat_t(catdim::Integer, typeC::Type, A::AbstractArray...)
     # ndims of all input arrays should be in [d-1, d]
 
     nargs = length(A)
@@ -753,6 +800,9 @@ end
 vcat(A::AbstractArray...) = cat(1, A...)
 hcat(A::AbstractArray...) = cat(2, A...)
 
+typed_vcat(T::Type, A::AbstractArray...) = cat_t(1, T, A...)
+typed_hcat(T::Type, A::AbstractArray...) = cat_t(2, T, A...)
+
 # 2d horizontal and vertical concatenation
 
 function hvcat{T}(rows::(Int...), as::AbstractMatrix{T}...)
@@ -830,22 +880,20 @@ function hvcat_fill(a, xs)
     a
 end
 
-function hvcat(rows::(Int...), xs::Number...)
+function typed_hvcat(T::Type, rows::(Int...), xs...)
     nr = length(rows)
     nc = rows[1]
-    #error check
     for i = 2:nr
         if nc != rows[i]
             error("hvcat: row ", i, " has mismatched number of columns")
         end
     end
-    T = typeof(xs[1])
-    for i=2:length(xs)
-        T = promote_type(T,typeof(xs[i]))
-    end
     hvcat_fill(Array(T, nr, nc), xs)
 end
 
+hvcat(rows::(Int...), xs::Number...) =
+    typed_hvcat(promote_type(map(typeof, xs)...), rows, xs...)
+
 ## Reductions and scans ##
 
 function isequal(A::AbstractArray, B::AbstractArray)
diff --git a/base/array.jl b/base/array.jl
index a66cb5e9e5b26..d8bdc050e94b6 100644
--- a/base/array.jl
+++ b/base/array.jl
@@ -165,12 +165,15 @@ function getindex(T::NonTupleType, vals...)
     return a
 end
 
+if _oldstyle_array_vcat_
 # T[a:b] and T[a:s:b] also contruct typed ranges
 function getindex{T<:Number}(::Type{T}, r::Ranges)
+    warn_once("T[a:b] concatenation is deprecated; use T[a:b;] instead")
     copy!(Array(T,length(r)), r)
 end
 
 function getindex{T<:Number}(::Type{T}, r1::Ranges, rs::Ranges...)
+    warn_once("T[a:b,...] concatenation is deprecated; use T[a:b;...] instead")
     a = Array(T,length(r1)+sum(length,rs))
     o = 1
     copy!(a, r1, o)
@@ -181,6 +184,7 @@ function getindex{T<:Number}(::Type{T}, r1::Ranges, rs::Ranges...)
     end
     return a
 end
+end
 
 function fill!{T<:Union(Int8,Uint8)}(a::Array{T}, x::Integer)
     ccall(:memset, Ptr{Void}, (Ptr{Void}, Int32, Csize_t), a, x, length(a))
diff --git a/src/julia-parser.scm b/src/julia-parser.scm
index ff74e1cbb3c24..99ea113d7980d 100644
--- a/src/julia-parser.scm
+++ b/src/julia-parser.scm
@@ -787,14 +787,10 @@
                              (loop (list 'typed_dict ex))
                              (loop (list 'ref ex)))
                          (case (car al)
+                           ((vect)  (loop (list* 'ref ex (cdr al))))
                            ((dict)  (loop (list* 'typed_dict ex (cdr al))))
                            ((hcat)  (loop (list* 'typed_hcat ex (cdr al))))
-                           ((vcat)
-                            (if (any (lambda (x)
-                                       (and (pair? x) (eq? (car x) 'row)))
-                                     (cdr al))
-                                (loop (list* 'typed_vcat ex (cdr al)))
-                                (loop (list* 'ref ex (cdr al)))))
+                           ((vcat)  (loop (list* 'typed_vcat ex (cdr al))))
                            ((comprehension)
                             (loop (list* 'typed_comprehension ex (cdr al))))
                            ((dict_comprehension)
@@ -1223,21 +1219,20 @@
 		       (error (string "missing comma or " closer
 				      " in argument list"))))))))))
 
-; parse [] concatenation expressions and {} cell expressions
-(define (parse-vcat s first closer)
+(define (parse-vect s first closer)
   (let loop ((lst '())
 	     (nxt first))
     (let ((t (require-token s)))
       (if (eqv? t closer)
 	  (begin (take-token s)
-		 (cons 'vcat (reverse (cons nxt lst))))
+		 (cons 'vect (reverse (cons nxt lst))))
 	  (case t
 	    ((#\,)
 	     (take-token s)
 	     (if (eqv? (require-token s) closer)
 		 ;; allow ending with ,
 		 (begin (take-token s)
-			(cons 'vcat (reverse (cons nxt lst))))
+			(cons 'vect (reverse (cons nxt lst))))
 		 (loop (cons nxt lst) (parse-eq* s))))
 	    ((#\;)
 	     (error "unexpected semicolon in array expression"))
@@ -1247,7 +1242,7 @@
 	     (error "missing separator in array expression")))))))
 
 (define (parse-dict s first closer)
-  (let ((v (parse-vcat s first closer)))
+  (let ((v (parse-vect s first closer)))
     (if (any dict-literal? (cdr v))
         (if (every dict-literal? (cdr v))
             `(dict ,@(cdr v))
@@ -1283,7 +1278,7 @@
 		 (if (pair? outer)
 		     (fix 'vcat (update-outer vec outer))
 		     (if (or (null? vec) (null? (cdr vec)))
-			 (fix 'vcat vec)     ; [x]   => (vcat x)
+			 (fix 'vect vec)     ; [x]   => (vect x)
 			 (fix 'hcat vec))))  ; [x y] => (hcat x y)
 	  (case t
 	    ((#\; #\newline)
@@ -1324,8 +1319,8 @@
                 (else
                  (parse-dict s first closer)))
               (case (peek-token s)
-                ((#\,)
-                 (parse-vcat s first closer))
+                ((#\, closer)
+                 (parse-vect s first closer))
                 ((for)
                  (take-token s)
                  (parse-comprehension s first closer))
@@ -1597,6 +1592,7 @@
                  (if (null? vex)
                      '(cell1d)
                      (case (car vex)
+                       ((vect)  `(cell1d ,@(cdr vex)))
                        ((comprehension)
                         `(typed_comprehension (top Any) ,@(cdr vex)))
                        ((dict_comprehension)
@@ -1632,7 +1628,7 @@
 	  ((eqv? t #\[ )
 	   (take-token s)
 	   (let ((vex (parse-cat s #\])))
-             (if (null? vex) '(vcat) vex)))
+             (if (null? vex) '(vect) vex)))
 
 	  ;; string literal
 	  ((eqv? t #\")
diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm
index ec3429dd97aec..9aa38442fb472 100644
--- a/src/julia-syntax.scm
+++ b/src/julia-syntax.scm
@@ -1477,7 +1477,10 @@
    (pattern-lambda (: a b)
 		   `(call (top colon) ,a ,b))
 
-   ;; hcat, vcat
+   ;; vect, hcat, vcat
+   (pattern-lambda (vect . a)
+                   `(call (top vect) ,@a))
+
    (pattern-lambda (hcat . a)
 		   `(call (top hcat) ,@a))
 
@@ -1497,38 +1500,22 @@
 		       `(call (top vcat) ,@a)))
 
    (pattern-lambda (typed_hcat t . a)
-                   (let ((result (gensy))
-                         (ncols (length a)))
-                     `(block
-                       (if (call (top !) (call (top isa) ,t Type))
-                           (call error "invalid array index"))
-                       (= ,result (call (top Array) ,t 1 ,ncols))
-                       ,@(map (lambda (x i) `(call (top setindex!) ,result ,x ,i))
-                              a (cdr (iota (+ ncols 1))))
-                       ,result)))
-
-   (pattern-lambda (typed_vcat t . rows)
-     (if (any (lambda (x) (not (and (pair? x) (eq? 'row (car x))))) rows)
-         (error "invalid array literal")
-         (let ((result (gensy))
-               (nrows (length rows))
-               (ncols (length (cdar rows))))
-           (if (any (lambda (x) (not (= (length (cdr x)) ncols))) rows)
-               (error "invalid array literal")
-               `(block
-                 (if (call (top !) (call (top isa) ,t Type))
-                     (call error "invalid array index"))
-                 (= ,result (call (top Array) ,t ,nrows ,ncols))
-                 ,@(apply nconc
-                     (map
-                       (lambda (row i)
-                         (map
-                           (lambda (x j) `(call (top setindex!) ,result ,x ,i ,j))
-                           (cdr row)
-                           (cdr (iota (+ ncols 1)))))
-                       rows
-                       (cdr (iota (+ nrows 1)))))
-                 ,result)))))
+                   `(call (top typed_hcat) ,t ,@a))
+
+   (pattern-lambda (typed_vcat t . a)
+		   (if (any (lambda (x)
+			      (and (pair? x) (eq? (car x) 'row)))
+			    a)
+		       ;; convert nested hcat inside vcat to hvcat
+		       (let ((rows (map (lambda (x)
+					  (if (and (pair? x) (eq? (car x) 'row))
+					      (cdr x)
+					      (list x)))
+					a)))
+			 `(call (top typed_hvcat) ,t
+				(tuple ,@(map length rows))
+				,@(apply nconc rows)))
+		       `(call (top typed_vcat) ,t ,@a)))
 
    ;; transpose operator
    (pattern-lambda (|'| a) `(call ctranspose ,a))