Skip to content

Commit 56086d0

Browse files
committed
implement comprehensions as collect of a Generator
this removes `static_typeof` and `type_goto` fixes #7258
1 parent 7b3f529 commit 56086d0

14 files changed

+38
-289
lines changed

base/abstractarray.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -912,8 +912,8 @@ typed_hcat{T}(::Type{T}) = Array{T}(0)
912912
## cat: special cases
913913
vcat{T}(X::T...) = T[ X[i] for i=1:length(X) ]
914914
vcat{T<:Number}(X::T...) = T[ X[i] for i=1:length(X) ]
915-
hcat{T}(X::T...) = T[ X[j] for i=1, j=1:length(X) ]
916-
hcat{T<:Number}(X::T...) = T[ X[j] for i=1, j=1:length(X) ]
915+
hcat{T}(X::T...) = T[ X[j] for i=1:1, j=1:length(X) ]
916+
hcat{T<:Number}(X::T...) = T[ X[j] for i=1:1, j=1:length(X) ]
917917

918918
vcat(X::Number...) = hvcat_fill(Array{promote_typeof(X...)}(length(X)), X)
919919
hcat(X::Number...) = hvcat_fill(Array{promote_typeof(X...)}(1,length(X)), X)

base/arraymath.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ function ctranspose(A::AbstractMatrix)
324324
end
325325
ctranspose{T<:Real}(A::AbstractVecOrMat{T}) = transpose(A)
326326

327-
transpose(x::AbstractVector) = [ transpose(v) for i=1, v in x ]
328-
ctranspose{T}(x::AbstractVector{T}) = T[ ctranspose(v) for i=1, v in x ] #Fixme comprehension
327+
transpose(x::AbstractVector) = [ transpose(v) for i=1:1, v in x ]
328+
ctranspose{T}(x::AbstractVector{T}) = T[ ctranspose(v) for i=1:1, v in x ]
329329

330330
_cumsum_type{T<:Number}(v::AbstractArray{T}) = typeof(+zero(T))
331331
_cumsum_type(v) = typeof(v[1]+v[1])

base/inference.jl

+5-106
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@ end
4343
type InferenceState
4444
sp::SimpleVector # static parameters
4545
label_counter::Int # index of the current highest label for this function
46-
fedbackvars::Dict{SSAValue, Bool}
4746
mod::Module
4847
currpc::LineNum
49-
static_typeof::Bool
5048

5149
# info on the state of inference and the linfo
5250
linfo::LambdaInfo
@@ -71,7 +69,6 @@ type InferenceState
7169
backedges::Vector{Tuple{InferenceState, Vector{LineNum}}}
7270
# iteration fixed-point detection
7371
fixedpoint::Bool
74-
typegotoredo::Bool
7572
inworkq::Bool
7673
# optimization
7774
optimize::Bool
@@ -158,13 +155,13 @@ type InferenceState
158155

159156
inmodule = isdefined(linfo, :def) ? linfo.def.module : current_module() # toplevel thunks are inferred in the current module
160157
frame = new(
161-
sp, nl, Dict{SSAValue, Bool}(), inmodule, 0, false,
158+
sp, nl, inmodule, 0,
162159
linfo, la, s, Union{}, W, n,
163160
cur_hand, handler_at, n_handlers,
164161
ssavalue_uses, ssavalue_init,
165162
ObjectIdDict(), #Dict{InferenceState, Vector{LineNum}}(),
166163
Vector{Tuple{InferenceState, Vector{LineNum}}}(),
167-
false, false, false, optimize, inlining, needtree, false)
164+
false, false, optimize, inlining, needtree, false)
168165
push!(active, frame)
169166
nactive[] += 1
170167
return frame
@@ -1068,8 +1065,6 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState)
10681065
return abstract_eval_constant(e)
10691066
end
10701067
e = e::Expr
1071-
# handle:
1072-
# call null new & static_typeof
10731068
if is(e.head,:call)
10741069
t = abstract_eval_call(e, vtypes, sv)
10751070
elseif is(e.head,:null)
@@ -1103,42 +1098,6 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState)
11031098
t = abstract_eval_constant(val)
11041099
end
11051100
end
1106-
elseif is(e.head,:static_typeof)
1107-
var = e.args[1]
1108-
t = widenconst(abstract_eval(var, vtypes, sv))
1109-
if isa(t,DataType) && typeseq(t,t.name.primary)
1110-
# remove unnecessary typevars
1111-
t = t.name.primary
1112-
end
1113-
if is(t,Bottom)
1114-
# if we haven't gotten fed-back type info yet, return Bottom. otherwise
1115-
# Bottom is the actual type of the variable, so return Type{Bottom}.
1116-
if get!(sv.fedbackvars, var, false)
1117-
t = Type{Bottom}
1118-
else
1119-
sv.static_typeof = true
1120-
end
1121-
elseif isleaftype(t)
1122-
t = Type{t}
1123-
elseif isleaftype(sv.linfo.specTypes)
1124-
if isa(t,TypeVar)
1125-
t = Type{t.ub}
1126-
else
1127-
t = Type{t}
1128-
end
1129-
else
1130-
# if there is any type uncertainty in the arguments, we are
1131-
# effectively predicting what static_typeof will say when
1132-
# the function is compiled with actual arguments. in that case
1133-
# abstract types yield Type{<:T} instead of Type{T}.
1134-
# this doesn't really model the situation perfectly, but
1135-
# "isleaftype(inference_stack.types)" should be good enough.
1136-
if isa(t,TypeVar) || isvarargtype(t)
1137-
t = Type{t}
1138-
else
1139-
t = Type{TypeVar(:_,t)}
1140-
end
1141-
end
11421101
elseif is(e.head,:method)
11431102
t = (length(e.args) == 1) ? Any : Void
11441103
elseif is(e.head,:copyast)
@@ -1666,23 +1625,19 @@ function typeinf_frame(frame)
16661625
W = frame.ip
16671626
s = frame.stmt_types
16681627
n = frame.nstmts
1669-
@label restart_typeinf
16701628
while !isempty(W)
16711629
# make progress on the active ip set
16721630
local pc::Int = first(W), pc´::Int
16731631
while true # inner loop optimizes the common case where it can run straight from pc to pc + 1
16741632
#print(pc,": ",s[pc],"\n")
16751633
delete!(W, pc)
16761634
frame.currpc = pc
1677-
frame.static_typeof = false
16781635
frame.cur_hand = frame.handler_at[pc]
16791636
stmt = frame.linfo.code[pc]
16801637
changes = abstract_interpret(stmt, s[pc]::Array{Any,1}, frame)
16811638
if changes === ()
1682-
# if there was a Expr(:static_typeof) on this line,
1683-
# need to continue to the next pc even though the return type was Bottom
1684-
# otherwise, this line threw an error and there is no need to continue
1685-
frame.static_typeof || break
1639+
# this line threw an error and there is no need to continue
1640+
break
16861641
changes = s[pc]
16871642
end
16881643
if frame.cur_hand !== ()
@@ -1732,26 +1687,6 @@ function typeinf_frame(frame)
17321687
s[l] = newstate
17331688
end
17341689
end
1735-
elseif is(hd, :type_goto)
1736-
for i = 2:length(stmt.args)
1737-
var = stmt.args[i]::SSAValue
1738-
# Store types that need to be fed back via type_goto
1739-
# in ssavalue_init. After finishing inference, if any
1740-
# of these types changed, start over with the fed-back
1741-
# types known from the beginning.
1742-
# See issue #3821 (using !typeseq instead of !subtype),
1743-
# and issue #7810.
1744-
id = var.id+1
1745-
vt = frame.linfo.ssavaluetypes[id]
1746-
ot = frame.ssavalue_init[id]
1747-
if ot===NF || !(vtot && otvt)
1748-
frame.ssavalue_init[id] = vt
1749-
if get(frame.fedbackvars, var, false)
1750-
frame.typegotoredo = true
1751-
end
1752-
end
1753-
frame.fedbackvars[var] = true
1754-
end
17551690
elseif is(hd, :return)
17561691
pc´ = n + 1
17571692
rt = abstract_eval(stmt.args[1], s[pc], frame)
@@ -1821,39 +1756,6 @@ function typeinf_frame(frame)
18211756
end
18221757

18231758
if finished || frame.fixedpoint
1824-
if frame.typegotoredo
1825-
# if any type_gotos changed, clear state and restart.
1826-
frame.typegotoredo = false
1827-
for ll = 2:length(s)
1828-
s[ll] = ()
1829-
end
1830-
empty!(W)
1831-
push!(W, 1)
1832-
frame.cur_hand = ()
1833-
frame.handler_at = Any[ () for i=1:n ]
1834-
frame.n_handlers = 0
1835-
frame.linfo.ssavaluetypes[:] = frame.ssavalue_init
1836-
@goto restart_typeinf
1837-
else
1838-
# if a static_typeof was never reached,
1839-
# use Union{} as its real type and continue
1840-
# running type inference from its uses
1841-
# (one of which is the static_typeof)
1842-
# TODO: this restart should happen just before calling finish()
1843-
for (fbvar, seen) in frame.fedbackvars
1844-
if !seen
1845-
frame.fedbackvars[fbvar] = true
1846-
id = (fbvar::SSAValue).id + 1
1847-
for r in frame.ssavalue_uses[id]
1848-
if !is(s[r], ()) # s[r] === () => unreached statement
1849-
push!(W, r)
1850-
end
1851-
end
1852-
@goto restart_typeinf
1853-
end
1854-
end
1855-
end
1856-
18571759
if finished
18581760
finish(frame)
18591761
else # fixedpoint propagation
@@ -2056,7 +1958,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::InferenceState, undefs, pass)
20561958

20571959
e = e::Expr
20581960
head = e.head
2059-
if is(head,:static_typeof) || is(head,:line) || is(head,:const)
1961+
if is(head,:line) || is(head,:const)
20601962
return e
20611963
elseif is(head,:(=))
20621964
e.args[2] = eval_annotate(e.args[2], vtypes, sv, undefs, pass)
@@ -2282,9 +2184,6 @@ function effect_free(e::ANY, sv, allow_volatile::Bool)
22822184
elseif isa(e,Expr)
22832185
e = e::Expr
22842186
head = e.head
2285-
if head === :static_typeof
2286-
return true
2287-
end
22882187
if head === :static_parameter || head === :meta || head === :line ||
22892188
head === :inbounds || head === :boundscheck
22902189
return true

base/range.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ maximum(r::UnitRange) = isempty(r) ? throw(ArgumentError("range must be non-empt
372372
minimum(r::Range) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : min(first(r), last(r))
373373
maximum(r::Range) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : max(first(r), last(r))
374374

375-
ctranspose(r::Range) = [x for _=1, x=r]
375+
ctranspose(r::Range) = [x for _=1:1, x=r]
376376
transpose(r::Range) = r'
377377

378378
# Ranges are immutable

base/sparse/sparsematrix.jl

+10-10
Original file line numberDiff line numberDiff line change
@@ -3071,8 +3071,8 @@ end
30713071

30723072
function vcat(X::SparseMatrixCSC...)
30733073
num = length(X)
3074-
mX = [ size(x, 1) for x in X ]
3075-
nX = [ size(x, 2) for x in X ]
3074+
mX = Int[ size(x, 1) for x in X ]
3075+
nX = Int[ size(x, 2) for x in X ]
30763076
m = sum(mX)
30773077
n = nX[1]
30783078

@@ -3089,7 +3089,7 @@ function vcat(X::SparseMatrixCSC...)
30893089
Ti = promote_type(Ti, eltype(X[i].rowval))
30903090
end
30913091

3092-
nnzX = [ nnz(x) for x in X ]
3092+
nnzX = Int[ nnz(x) for x in X ]
30933093
nnz_res = sum(nnzX)
30943094
colptr = Array{Ti}(n + 1)
30953095
rowval = Array{Ti}(nnz_res)
@@ -3131,8 +3131,8 @@ end
31313131

31323132
function hcat(X::SparseMatrixCSC...)
31333133
num = length(X)
3134-
mX = [ size(x, 1) for x in X ]
3135-
nX = [ size(x, 2) for x in X ]
3134+
mX = Int[ size(x, 1) for x in X ]
3135+
nX = Int[ size(x, 2) for x in X ]
31363136
m = mX[1]
31373137
for i = 2 : num
31383138
if mX[i] != m; throw(DimensionMismatch("")); end
@@ -3143,7 +3143,7 @@ function hcat(X::SparseMatrixCSC...)
31433143
Ti = promote_type(map(x->eltype(x.rowval), X)...)
31443144

31453145
colptr = Array{Ti}(n + 1)
3146-
nnzX = [ nnz(x) for x in X ]
3146+
nnzX = Int[ nnz(x) for x in X ]
31473147
nnz_res = sum(nnzX)
31483148
rowval = Array{Ti}(nnz_res)
31493149
nzval = Array{Tv}(nnz_res)
@@ -3199,16 +3199,16 @@ Concatenate matrices block-diagonally. Currently only implemented for sparse mat
31993199
"""
32003200
function blkdiag(X::SparseMatrixCSC...)
32013201
num = length(X)
3202-
mX = [ size(x, 1) for x in X ]
3203-
nX = [ size(x, 2) for x in X ]
3202+
mX = Int[ size(x, 1) for x in X ]
3203+
nX = Int[ size(x, 2) for x in X ]
32043204
m = sum(mX)
32053205
n = sum(nX)
32063206

32073207
Tv = promote_type(map(x->eltype(x.nzval), X)...)
32083208
Ti = promote_type(map(x->eltype(x.rowval), X)...)
32093209

32103210
colptr = Array{Ti}(n + 1)
3211-
nnzX = [ nnz(x) for x in X ]
3211+
nnzX = Int[ nnz(x) for x in X ]
32123212
nnz_res = sum(nnzX)
32133213
rowval = Array{Ti}(nnz_res)
32143214
nzval = Array{Tv}(nnz_res)
@@ -3449,7 +3449,7 @@ function trace{Tv}(A::SparseMatrixCSC{Tv})
34493449
s
34503450
end
34513451

3452-
diag(A::SparseMatrixCSC) = [d for d in SpDiagIterator(A)]
3452+
diag{Tv}(A::SparseMatrixCSC{Tv}) = Tv[d for d in SpDiagIterator(A)]
34533453

34543454
function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti})
34553455
if (size(v,1) != 1 && size(v,2) != 1)

src/alloc.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,12 @@ jl_sym_t *body_sym;
8888
jl_sym_t *method_sym; jl_sym_t *core_sym;
8989
jl_sym_t *enter_sym; jl_sym_t *leave_sym;
9090
jl_sym_t *exc_sym; jl_sym_t *error_sym;
91-
jl_sym_t *static_typeof_sym;
9291
jl_sym_t *globalref_sym;
9392
jl_sym_t *new_sym; jl_sym_t *using_sym;
9493
jl_sym_t *const_sym; jl_sym_t *thunk_sym;
9594
jl_sym_t *anonymous_sym; jl_sym_t *underscore_sym;
9695
jl_sym_t *abstracttype_sym; jl_sym_t *bitstype_sym;
97-
jl_sym_t *compositetype_sym; jl_sym_t *type_goto_sym;
96+
jl_sym_t *compositetype_sym;
9897
jl_sym_t *global_sym; jl_sym_t *list_sym;
9998
jl_sym_t *dot_sym; jl_sym_t *newvar_sym;
10099
jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym;

src/codegen.cpp

+1-13
Original file line numberDiff line numberDiff line change
@@ -3109,7 +3109,7 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx)
31093109
if (jl_is_expr(expr)) {
31103110
jl_sym_t *head = ((jl_expr_t*)expr)->head;
31113111
// some expression types are metadata and can be ignored in statement position
3112-
if (head == line_sym || head == type_goto_sym || head == meta_sym)
3112+
if (head == line_sym || head == meta_sym)
31133113
return;
31143114
// fall-through
31153115
}
@@ -3283,18 +3283,6 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx)
32833283
literal_pointer_val(bnd));
32843284
}
32853285
}
3286-
else if (head == static_typeof_sym) {
3287-
jl_value_t *extype = expr_type((jl_value_t*)ex, ctx);
3288-
if (jl_is_type_type(extype)) {
3289-
extype = jl_tparam0(extype);
3290-
if (jl_is_typevar(extype))
3291-
extype = ((jl_tvar_t*)extype)->ub;
3292-
}
3293-
else {
3294-
extype = (jl_value_t*)jl_any_type;
3295-
}
3296-
return mark_julia_const(extype);
3297-
}
32983286
else if (head == new_sym) {
32993287
jl_value_t *ty = expr_type(args[0], ctx);
33003288
size_t nargs = jl_array_len(ex->args);

src/interpreter.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,6 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s)
223223
else if (ex->head == copyast_sym) {
224224
return jl_copy_ast(eval(args[0], s));
225225
}
226-
else if (ex->head == static_typeof_sym) {
227-
return (jl_value_t*)jl_any_type;
228-
}
229226
else if (ex->head == exc_sym) {
230227
return ptls->exception_in_transit;
231228
}
@@ -429,7 +426,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s)
429426
jl_throw(args[0]);
430427
}
431428
else if (ex->head == boundscheck_sym || ex->head == inbounds_sym || ex->head == fastmath_sym ||
432-
ex->head == simdloop_sym || ex->head == meta_sym || ex->head == type_goto_sym) {
429+
ex->head == simdloop_sym || ex->head == meta_sym) {
433430
return jl_nothing;
434431
}
435432
jl_errorf("unsupported or misplaced expression %s", jl_symbol_name(ex->head));

src/jltypes.c

-2
Original file line numberDiff line numberDiff line change
@@ -3993,7 +3993,6 @@ void jl_init_types(void)
39933993
exc_sym = jl_symbol("the_exception");
39943994
enter_sym = jl_symbol("enter");
39953995
leave_sym = jl_symbol("leave");
3996-
static_typeof_sym = jl_symbol("static_typeof");
39973996
new_sym = jl_symbol("new");
39983997
const_sym = jl_symbol("const");
39993998
global_sym = jl_symbol("global");
@@ -4004,7 +4003,6 @@ void jl_init_types(void)
40044003
abstracttype_sym = jl_symbol("abstract_type");
40054004
bitstype_sym = jl_symbol("bits_type");
40064005
compositetype_sym = jl_symbol("composite_type");
4007-
type_goto_sym = jl_symbol("type_goto");
40084006
toplevel_sym = jl_symbol("toplevel");
40094007
dot_sym = jl_symbol(".");
40104008
boundscheck_sym = jl_symbol("boundscheck");

0 commit comments

Comments
 (0)