From aa8ee40a9ea1a93e58114fffd2e2b8c3dd51e04a Mon Sep 17 00:00:00 2001
From: jake bolewski <jakebolewski@gmail.com>
Date: Wed, 25 Feb 2015 23:01:17 -0500
Subject: [PATCH] some more fieldname refactoring

---
 base/deepcopy.jl   |  7 ++++---
 base/inference.jl  |  4 ++--
 base/reflection.jl | 17 ++++++++++++++---
 base/serialize.jl  | 11 ++++++-----
 base/show.jl       | 13 +++++++------
 5 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/base/deepcopy.jl b/base/deepcopy.jl
index 4677cdebc729e5..ef6b4c9a034c07 100644
--- a/base/deepcopy.jl
+++ b/base/deepcopy.jl
@@ -27,17 +27,18 @@ function deepcopy_internal(x, stackdict::ObjectIdDict)
 end
 
 function _deepcopy_t(x, T::DataType, stackdict::ObjectIdDict)
-    isbits(T) | isempty(T.names) && return x
+    nf = nfields(T)
+    (isbits(T) || nf == 0) && return x
     if T.mutable
         y = ccall(:jl_new_struct_uninit, Any, (Any,), T)
         stackdict[x] = y
-        for i in 1:length(T.names)
+        for i in 1:nf
             if isdefined(x,i)
                 y.(i) = deepcopy_internal(x.(i), stackdict)
             end
         end
     else
-        fields = Any[deepcopy_internal(x.(i), stackdict) for i in 1:length(T.names)]
+        fields = Any[deepcopy_internal(x.(i), stackdict) for i in 1:nf]
         y = ccall(:jl_new_structv, Any, (Any, Ptr{Void}, UInt32),
                   T, pointer(fields), length(fields))
     end
diff --git a/base/inference.jl b/base/inference.jl
index be9337540df011..c0cb447a9daa30 100644
--- a/base/inference.jl
+++ b/base/inference.jl
@@ -343,7 +343,7 @@ const getfield_tfunc = function (A, s0, name)
                 end
             end
         end
-        for i=1:length(s.names)
+        for i=1:nfields(s)
             if is(s.names[i],fld)
                 R = s.types[i]
                 if s.parameters === ()
@@ -360,7 +360,7 @@ const getfield_tfunc = function (A, s0, name)
             return Bottom
         end
         i::Int = A[2]
-        if i < 1 || i > length(s.names)
+        if i < 1 || i > nfields(s)
             return Bottom
         end
         return s.types[i]
diff --git a/base/reflection.jl b/base/reflection.jl
index ab81b66e5abcf3..13ab59623bfef7 100644
--- a/base/reflection.jl
+++ b/base/reflection.jl
@@ -27,8 +27,8 @@ end
 fieldnames(m::Module, all::Bool, imported::Bool) = ccall(:jl_module_fieldnames, Array{Symbol,1}, (Any,Int32,Int32), m, all, imported)
 fieldnames(m::Module, all::Bool) = fieldnames(m, all, false)
 fieldnames(m::Module) = fieldnames(m, false, false)
-fieldnames(t::DataType) = collect(t.names)
 
+fieldnames(t::DataType) = collect(t.names)
 function fieldnames(v)
     t = typeof(v)
     if !isa(t,DataType)
@@ -37,6 +37,17 @@ function fieldnames(v)
     return fieldnames(t)
 end
 
+fieldname(t::DataType, i::Integer) = t.names[i]
+
+nfields(t::DataType) = length(t.names)
+function nfields(v)
+    t = typeof(v)
+    if !isa(DataType)
+        throw(ArgumentError("cannot call nfields() on a non-composite type"))
+    end
+    return nfields(t)
+end
+
 isconst(s::Symbol) =
     ccall(:jl_is_const, Int32, (Ptr{Void}, Any), C_NULL, s) != 0
 
@@ -48,7 +59,7 @@ object_id(x::ANY) = ccall(:jl_object_id, UInt, (Any,), x)
 
 # type predicates
 isimmutable(x::ANY) = (isa(x,Tuple) || !typeof(x).mutable)
-isstructtype(t::DataType) = t.names!=() || (t.size==0 && !t.abstract)
+isstructtype(t::DataType) = nfields(t) != 0 || (t.size==0 && !t.abstract)
 isstructtype(x) = false
 isbits(t::DataType) = !t.mutable & t.pointerfree & isleaftype(t)
 isbits(t::Type) = false
@@ -59,7 +70,7 @@ typeintersect(a::ANY,b::ANY) = ccall(:jl_type_intersection, Any, (Any,Any), a, b
 typeseq(a::ANY,b::ANY) = a<:b && b<:a
 
 function fieldoffsets(x::DataType)
-    offsets = Array(Int, length(x.names))
+    offsets = Array(Int, nfields(x))
     ccall(:jl_field_offsets, Void, (Any, Ptr{Int}), x, offsets)
     offsets
 end
diff --git a/base/serialize.jl b/base/serialize.jl
index d3a12d014067fc..ee1174d0b47ce2 100644
--- a/base/serialize.jl
+++ b/base/serialize.jl
@@ -315,11 +315,12 @@ function serialize(s, x)
         return write_as_tag(s, x)
     end
     t = typeof(x)
+    nf = nfields(t)
     serialize_type(s, t)
-    if length(t.names)==0 && t.size>0
+    if nf == 0 && t.size > 0
         write(s, x)
     else
-        for i in 1:length(t.names)
+        for i in 1:nf
             if isdefined(x, i)
                 serialize(s, getfield(x, i))
             else
@@ -527,11 +528,11 @@ end
 
 # default DataType deserializer
 function deserialize(s, t::DataType)
-    if length(t.names)==0 && t.size>0
+    nf = nfields(t)
+    if nf == 0 && t.size > 0
         # bits type
         return read(s, t)
     end
-    nf = length(t.names)
     if nf == 0
         return ccall(:jl_new_struct, Any, (Any,Any...), t)
     elseif isbits(t)
@@ -552,7 +553,7 @@ function deserialize(s, t::DataType)
         end
     else
         x = ccall(:jl_new_struct_uninit, Any, (Any,), t)
-        for i in 1:length(t.names)
+        for i in 1:nf
             tag = int32(read(s, UInt8))
             if tag==0 || !is(deser_tag[tag], UndefRefTag)
                 ccall(:jl_set_nth_field, Void, (Any, Csize_t, Any), x, i-1, handle_deserialize(s, tag))
diff --git a/base/show.jl b/base/show.jl
index 18e8727f6a1e5d..41c5b39cf1e8f5 100644
--- a/base/show.jl
+++ b/base/show.jl
@@ -6,7 +6,8 @@ function show(io::IO, x::ANY)
     t = typeof(x)::DataType
     show(io, t)
     print(io, '(')
-    if t.names !== () || t.size==0
+    nf = nfields(t)
+    if nf != 0 || t.size==0
         recorded = false
         oid = object_id(x)
         shown_set = get(task_local_storage(), :SHOWNSET, nothing)
@@ -22,15 +23,15 @@ function show(io::IO, x::ANY)
                 push!(shown_set, oid)
                 recorded = true
 
-                n = length(t.names)
-                for i=1:n
-                    f = t.names[i]
+                nf = nfields(t)
+                for i=1:nf
+                    f = fieldname(t, i)
                     if !isdefined(x, f)
                         print(io, undef_ref_str)
                     else
                         show(io, x.(f))
                     end
-                    if i < n
+                    if i < nf
                         print(io, ',')
                     end
                 end
@@ -735,7 +736,7 @@ end
 function xdump(fn::Function, io::IO, x, n::Int, indent)
     T = typeof(x)
     print(io, T, " ")
-    if isa(T, DataType) && length(T.names) > 0
+    if isa(T, DataType) && nfields(T) > 0
         println(io)
         if n > 0
             for field in fieldnames(T)