diff --git a/base/base.jl b/base/base.jl index c5b6a55ef62c4..1309006009ab1 100644 --- a/base/base.jl +++ b/base/base.jl @@ -1,7 +1,7 @@ # important core definitions using Core: Intrinsics, arraylen, arrayref, arrayset, arraysize, - tuplelen, tupleref, convert_default, convert_tuple, kwcall, + tuplelen, tupleref, convert_default, kwcall, typeassert, apply_type import Core.Array # to add methods @@ -10,8 +10,21 @@ const NonTupleType = Union(DataType,UnionType,TypeConstructor) typealias Callable Union(Function,DataType) -convert(T, x) = convert_default(T, x, convert) -convert(T::Tuple, x::Tuple) = convert_tuple(T, x, convert) +convert(T, x) = convert_default(T, x, convert) + +convert(::(), ::()) = () +convert(::Type{Tuple}, x::Tuple) = x + +argtail(x, rest...) = rest +tupletail(x::Tuple) = argtail(x...) + +convert(T::(Any, Any...), x::(Any, Any...)) = + tuple(convert(T[1],x[1]), convert(tupletail(T), tupletail(x))...) + +convert{T}(::Type{(T...)}, x::Tuple) = cnvt_all(T, x...) +cnvt_all(T) = () +cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) + ptr_arg_convert{T}(::Type{Ptr{T}}, x) = convert(T, x) ptr_arg_convert(::Type{Ptr{Void}}, x) = x diff --git a/base/boot.jl b/base/boot.jl index 8cffca0dda6b1..e9a2f0c4e4c07 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -137,7 +137,7 @@ export # object model functions apply, fieldtype, getfield, setfield!, yieldto, throw, tuple, is, ===, isdefined, # arraylen, arrayref, arrayset, arraysize, tuplelen, tupleref, convert_default, - # convert_tuple, kwcall, + # kwcall, # type reflection issubtype, typeof, isa, # typeassert, apply_type, diff --git a/base/inference.jl b/base/inference.jl index ae26edc40f3b7..0ca86f5b93911 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -154,61 +154,20 @@ t_func[arraysize] = (1, 2, arraysize_tfunc) t_func[pointerref] = (2,2,(a,i)->(isa(a,DataType) && a<:Ptr ? a.parameters[1] : Any)) t_func[pointerset] = (3, 3, (a,v,i)->a) -function static_convert(to::ANY, from::ANY) - if !isa(to,Tuple) || !isa(from,Tuple) - if isa(to,TypeVar) - return to - end - if from <: to - return from - end - return typeintersect(from,to) +const convert_default_tfunc = function (to, from, f) + !isType(to) && return Any + to = to.parameters[1] + + if isa(to,TypeVar) + return to end - if is(to,Tuple) + if from <: to return from end - pl = length(to)::Int; cl = length(from)::Int - pseq = false - result = Array(Any, cl) - local pe # used across iterations - for i=1:cl - ce = from[i] - if pseq - elseif i <= pl - pe = to[i] - if isvarargtype(pe) - pe = pe.parameters[1] - pseq = true - elseif isa(pe,TypeVar) && isvarargtype(pe.ub) - pe = pe.ub.parameters[1] - pseq = true - end - else - return None - end - # tuple conversion calls convert recursively - if isvarargtype(ce) - R = abstract_call_gf(convert, (), (Type{pe}, ce.parameters[1]), ()) - #R = static_convert(pe, ce.parameters[1]) - isType(R) && (R = R.parameters[1]) - result[i] = Vararg{R} - else - R = abstract_call_gf(convert, (), (Type{pe}, ce), ()) - #R = static_convert(pe, ce) - isType(R) && (R = R.parameters[1]) - result[i] = R - end - end - a2t(result) -end -t_func[convert_default] = - (3, 3, (t,x,f)->(isType(t) ? static_convert(t.parameters[1],x) : Any)) -t_func[convert_tuple] = - (3, 3, (t,x,f)->(if isa(t,Tuple) && all(isType,t) - t = Type{map(t->t.parameters[1],t)} - end; - isType(t) ? static_convert(t.parameters[1],x) : - Any)) + return typeintersect(from,to) +end +t_func[convert_default] = (3, 3, convert_default_tfunc) + const typeof_tfunc = function (t) if isType(t) t = t.parameters[1] @@ -1516,6 +1475,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) # inlining can add variables sv.vars = append_any(f_argnames(fulltree), fulltree.args[2][1]) tuple_elim_pass(fulltree) + tupleref_elim_pass(fulltree.args[3], sv) linfo.inferred = true fulltree = ccall(:jl_compress_ast, Any, (Any,Any), def, fulltree) end @@ -1954,17 +1914,6 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) return (e.args[3],()) end end - if is(f, convert_tuple) && length(atypes)==3 - # convert((T...),x::(S...)) => x, when S<:T - istuple = isa(atypes[1],Tuple) # if true, is (Type{T}, Type{S}) not Type{(T, S)} - if (istuple && all(isType,atypes[1])) || (atypes[1] <: Tuple && isType(atypes[1])) && isleaftype(atypes[1]) - tparams = (istuple ? map(t->t.parameters[1], atypes[1]) : atypes[1].parameters[1]) - if atypes[2] <: tparams - # todo: if T expression has side effects??! - return (e.args[3],()) - end - end - end if length(atypes)==2 && is(f,unbox) && isa(atypes[2],DataType) && !atypes[2].mutable && atypes[2].pointerfree # remove redundant unbox return (e.args[3],()) @@ -2679,6 +2628,33 @@ function occurs_outside_tupleref(e::ANY, sym::ANY, sv::StaticVarInfo, tuplen::In return false end +# replace tupleref(tuple(exprs...), i) with exprs[i] +function tupleref_elim_pass(e::Expr, sv) + for i = 1:length(e.args) + ei = e.args[i] + if isa(ei,Expr) + tupleref_elim_pass(ei, sv) + if is_known_call(ei, tupleref, sv) && length(ei.args)==3 && + isa(ei.args[2],Expr) && isa(ei.args[3],Int) + e1 = ei.args[2] + j = ei.args[3] + if is_known_call(e1, tuple, sv) && (1 <= j < length(e1.args)) + ok = true + for k = 2:length(e1.args) + k == j+1 && continue + if !effect_free(e1.args[k], sv, true) + ok = false; break + end + end + if ok + e.args[i] = e1.args[j+1] + end + end + end + end + end +end + # eliminate allocation of unnecessary tuples function tuple_elim_pass(ast::Expr) sv = inference_stack.sv diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 07e7df2470d77..0b78db5b085d0 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -441,7 +441,7 @@ end ## permutedims -for (V, PT, BT) in [((:N,), BitArray, BitArray), ((:T,:N), Array, StridedArray)] +for (V, PT, BT) in {((:N,), BitArray, BitArray), ((:T,:N), Array, StridedArray)} @eval @ngenerate N typeof(P) function permutedims!{$(V...)}(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) dimsB = size(B) length(perm) == N || error("expected permutation of size $N, but length(perm)=$(length(perm))") diff --git a/base/precompile.jl b/base/precompile.jl index 68ee16acea8a9..fcdfad42cea5f 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -63,7 +63,6 @@ precompile(rr2id, (RemoteRef,)) precompile(isequal, (RemoteRef, WeakRef)) precompile(isequal, (RemoteRef, RemoteRef)) precompile(_ieval, (Symbol,)) -precompile(static_convert, (Nothing, Nothing)) precompile(setindex!, (Array{Any,1}, WeakRef, Int)) precompile(isequal, ((Int,Int),(Int,Int))) precompile(isequal, (Int,Int)) diff --git a/src/builtin_proto.h b/src/builtin_proto.h index 7b7a07695f366..4ae5efd5f2c49 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -32,7 +32,6 @@ JL_CALLABLE(jl_f_arrayset); JL_CALLABLE(jl_f_arraysize); JL_CALLABLE(jl_f_instantiate_type); JL_CALLABLE(jl_f_convert_default); -JL_CALLABLE(jl_f_convert_tuple); JL_CALLABLE(jl_f_new_type_constructor); JL_CALLABLE(jl_f_typevar); JL_CALLABLE(jl_f_union); diff --git a/src/builtins.c b/src/builtins.c index 6e0b08014f93e..3b53e7bcebcc1 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -564,51 +564,6 @@ JL_CALLABLE(jl_f_field_type) // conversion ----------------------------------------------------------------- -static jl_value_t *convert(jl_value_t *to, jl_value_t *x, jl_function_t *conv_f) -{ - jl_value_t *args[2]; - if (jl_subtype(x, (jl_value_t*)to, 1)) - return x; - args[0] = (jl_value_t*)to; args[1] = x; - return jl_apply(conv_f, args, 2); -} - -JL_CALLABLE(jl_f_convert_tuple) -{ - jl_tuple_t *to = (jl_tuple_t*)args[0]; - jl_tuple_t *x = (jl_tuple_t*)args[1]; - if (to == jl_tuple_type) - return (jl_value_t*)x; - size_t i, cl=jl_tuple_len(x), pl=jl_tuple_len(to); - jl_tuple_t *out = jl_alloc_tuple(cl); - JL_GC_PUSH1(&out); - jl_value_t *ce, *pe=NULL; - int pseq=0; - jl_function_t *f = (jl_function_t*)args[2]; - for(i=0; i < cl; i++) { - ce = jl_tupleref(x,i); - if (pseq) { - } - else if (i < pl) { - pe = jl_tupleref(to,i); - if (jl_is_vararg_type(pe)) { - pe = jl_tparam0(pe); - pseq = 1; - } - } - else { - out = NULL; - break; - } - assert(pe != NULL); - jl_tupleset(out, i, convert((jl_value_t*)pe, ce, f)); - } - JL_GC_POP(); - if (out == NULL) - jl_error("convert: invalid tuple conversion"); - return (jl_value_t*)out; -} - JL_CALLABLE(jl_f_convert_default) { jl_value_t *to = args[0]; @@ -1015,7 +970,6 @@ void jl_init_primitives(void) // functions for internal use add_builtin_func("convert_default", jl_f_convert_default); - add_builtin_func("convert_tuple", jl_f_convert_tuple); add_builtin_func("tupleref", jl_f_tupleref); add_builtin_func("tuplelen", jl_f_tuplelen); add_builtin_func("getfield", jl_f_get_field); diff --git a/src/dump.c b/src/dump.c index 5892da55435c5..f3f1d19571727 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1329,7 +1329,7 @@ void jl_init_serializer(void) jl_f_arraylen, jl_f_arrayref, jl_f_arrayset, jl_f_arraysize, jl_f_instantiate_type, jl_f_kwcall, - jl_f_convert_default, jl_f_convert_tuple, + jl_f_convert_default, jl_trampoline, jl_f_new_type_constructor, jl_f_typevar, jl_f_union, jl_f_methodexists, jl_f_applicable,