Skip to content

Commit

Permalink
fully redesign constructors to use call overloading
Browse files Browse the repository at this point in the history
this does not work yet, but gets past the first bootstrap stage.

so far this is a significant net simplification.
  • Loading branch information
JeffBezanson committed Oct 11, 2014
1 parent 5b03766 commit 51a3069
Show file tree
Hide file tree
Showing 20 changed files with 280 additions and 455 deletions.
8 changes: 8 additions & 0 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ function getindex(T::NonTupleType, vals...)
return a
end

function getindex(::Type{Any}, vals::ANY...)
a = Array(Any,length(vals))
for i = 1:length(vals)
a[i] = vals[i]
end
return a
end

getindex(T::(Type...)) = Array(T,0)

# T[a:b] and T[a:s:b] also construct typed ranges
Expand Down
31 changes: 31 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,34 @@ end
typealias ByteString Union(ASCIIString,UTF8String)

include(fname::ByteString) = ccall(:jl_load_, Any, (Any,), fname)

# constructors for built-in types

TypeVar(n::Symbol) =
ccall(:jl_new_typevar, Any, (Any, Any, Any), n, Union(), Any)::TypeVar
TypeVar(n::Symbol, ub::ANY) =
ccall(:jl_new_typevar, Any, (Any, Any, Any), n, Union(), ub::Type)::TypeVar
TypeVar(n::Symbol, lb::ANY, ub::ANY) =
ccall(:jl_new_typevar, Any, (Any, Any, Any), n, lb::Type, ub::Type)::TypeVar
TypeVar(n::Symbol, b::Bool) =
ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, Union(), Any, b)::TypeVar
TypeVar(n::Symbol, ub::ANY, b::Bool) =
ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, Union(), ub::Type, b)::TypeVar
TypeVar(n::Symbol, lb::ANY, ub::ANY, b::Bool) =
ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, lb::Type, ub::Type, b)::TypeVar

TypeConstructor(p::ANY, t::ANY) = ccall(:jl_new_type_constructor, Any, (Any, Any), p::Tuple, t::Type)

Expr(hd::Symbol, args::ANY...) = ccall(:jl_new_expr, Any, (Any, Any), hd, args)::Expr

LineNumberNode(n::Int) = ccall(:jl_new_struct, Any, (Any,Any...), LineNumberNode, n)::LineNumberNode
LabelNode(n::Int) = ccall(:jl_new_struct, Any, (Any,Any...), LabelNode, n)::LabelNode
GotoNode(n::Int) = ccall(:jl_new_struct, Any, (Any,Any...), GotoNode, n)::GotoNode
QuoteNode(x::ANY) = ccall(:jl_new_struct, Any, (Any,Any...), QuoteNode, x)::QuoteNode
NewvarNode(s::Symbol) = ccall(:jl_new_struct, Any, (Any,Any...), NewvarNode, s)::NewvarNode
TopNode(s::Symbol) = ccall(:jl_new_struct, Any, (Any,Any...), TopNode, s)::TopNode

Module(name::Symbol) = ccall(:jl_f_new_module, Any, (Any,), name)::Module
Module() = Module(:anonymous)

Task(f::ANY) = ccall(:jl_new_task, Any, (Any, Int), f::Function, 0)::Task
79 changes: 28 additions & 51 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type CallStack
prev::Union(EmptyCallStack,CallStack)
sv::StaticVarInfo

CallStack(ast, mod, types, prev) = new(ast, mod, types, false, 0, Bottom, prev)
CallStack(ast, mod, types::ANY, prev) = new(ast, mod, types, false, 0, Bottom, prev)

This comment has been minimized.

Copy link
@jakebolewski

jakebolewski Oct 14, 2014

Member

Why is this change needed?

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Oct 14, 2014

Member

Presumably to avoid excess specialization of the CallStack constructor.

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Oct 14, 2014

Author Member

Yes - that particular slot sees basically every potential call signature in the system.

end

inference_stack = EmptyCallStack()
Expand Down Expand Up @@ -516,10 +516,6 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY)
end
tf = get(t_func::ObjectIdDict, f, false)
if is(tf,false)
# struct constructor
if isstructtype(f)
return f
end
# unknown/unhandled builtin
return Any
end
Expand Down Expand Up @@ -828,30 +824,25 @@ end
function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e)
if is(f,_apply) && length(fargs)>1
a2type = argtypes[2]
if isType(a2type) && isleaftype(a2type.parameters[1])
af = a2type.parameters[1]
_methods(af,(),0)
else
af = isconstantfunc(fargs[2], sv)
end
af = isconstantfunc(fargs[2], sv)

if !is(af,false)
af = _ieval(af)
if isa(af,Function) || isa(af,DataType)
if isa(af,Function)
aargtypes = map(to_tuple_of_Types, argtypes[3:end])
return abstract_apply(af, aargtypes, vtypes, sv, e)
end
end
# TODO: this slows down inference a lot
# if !(a2type===Function || a2type===DataType) && isleaftype(a2type)
# # would definitely use call()
# call_func = isconstantfunc(fargs[1])
# if !is(call_func,false)
# aargtypes = Any[ to_tuple_of_Types(argtypes[i]) for i=2:length(argtypes) ]
# aargtypes[1] = (aargtypes[1],) # don't splat "function"
# return abstract_apply(_ieval(call_func), tuple(aargtypes...), vtypes, sv, e)
# end
# end
if !(a2type===Function) && isleaftype(a2type)
# would definitely use call()
call_func = isconstantfunc(fargs[1], sv)
if !is(call_func,false)
aargtypes = Any[ to_tuple_of_Types(argtypes[i]) for i=2:length(argtypes) ]
aargtypes[1] = (aargtypes[1],) # don't splat "function"
return abstract_apply(_ieval(call_func), tuple(aargtypes...), vtypes, sv, e)
end
end
return Any
end
if isgeneric(f)
Expand Down Expand Up @@ -897,9 +888,9 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e)
# TODO: call() case
return Any
end
if !isa(f,Function) && !isa(f,DataType) && !isa(f,IntrinsicFunction) && _iisdefined(:call)
if !isa(f,Function) && !isa(f,IntrinsicFunction) && _iisdefined(:call)
call_func = _ieval(:call)
return abstract_call(call_func, e.args, tuple(Any[typeof(f),argtypes...]...), vtypes, sv, e)
return abstract_call(call_func, e.args, tuple(Any[abstract_eval_constant(f),argtypes...]...), vtypes, sv, e)
end
rt = builtin_tfunction(f, fargs, argtypes)
#print("=> ", rt, "\n")
Expand Down Expand Up @@ -933,21 +924,7 @@ function abstract_eval_call(e, vtypes, sv::StaticVarInfo)
return result
end
ft = abstract_eval(called, vtypes, sv)
if isType(ft)
st = ft.parameters[1]
if isa(st,TypeVar)
st = st.ub
end
if isa(st,DataType)
_methods(st,(),0)
if isgeneric(st) && isleaftype(st)
return abstract_call_gf(st, fargs, argtypes, e)
end
# struct constructor
return st
end
end
if !(Function <: ft) && typeintersect(DataType, ft)==Bottom && _iisdefined(:call)
if !(Function <: ft) && _iisdefined(:call)
call_func = _ieval(:call)
return abstract_call(call_func, e.args, tuple(Any[ft,argtypes...]...), vtypes, sv, e)
end
Expand Down Expand Up @@ -1300,6 +1277,10 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
end
end
end
# TODO: typeinf currently gets stuck without this
if linfo.name === :abstract_interpret || linfo.name === :tuple_elim_pass || linfo.name === :abstract_call_gf
return (linfo.ast, Any)
end

ast0 = def.ast

Expand Down Expand Up @@ -1621,6 +1602,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
# just the return type in place of it.
tfarr[idx+1] = rec ? frame.result : fulltree
tfarr[idx+2] = rec
#tfunc_idx = idx+1
else
def.tfunc[tfunc_idx] = rec ? frame.result : fulltree
def.tfunc[tfunc_idx+1] = rec
Expand Down Expand Up @@ -2063,7 +2045,7 @@ end
# static parameters are ok if all the static parameter values are leaf types,
# meaning they are fully known.
function inlineable(f, e::Expr, atypes, sv, enclosing_ast)
if !(isa(f,Function) || isstructtype(f) || isa(f,IntrinsicFunction))
if !(isa(f,Function) || isa(f,IntrinsicFunction))
return NF
end
argexprs = e.args[2:end]
Expand Down Expand Up @@ -2675,18 +2657,13 @@ function inlining_pass(e::Expr, sv, ast)
end
if is(e.head,:call1)
e.head = :call
ET = exprtype(arg1)
if isType(ET)
f = ET.parameters[1]
else
f1 = f = isconstantfunc(arg1, sv)
if !is(f,false)
f = _ieval(f)
end
if f1===false || !(isa(f,Function) || isa(f,Type) || isa(f,IntrinsicFunction))
f = _ieval(:call)
e.args = Any[f, e.args...]
end
f1 = f = isconstantfunc(arg1, sv)
if !is(f,false)
f = _ieval(f)
end
if f1===false || !(isa(f,Function) || isa(f,IntrinsicFunction))
f = _ieval(:call)
e.args = Any[f, e.args...]
end

if is(f, ^) || is(f, .^)
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/cholmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ type c_CholmodTriplet{Tv<:CHMVTypes,Ti<:CHMITypes}
j::Ptr{Ti}
x::Ptr{Tv}
z::Ptr{Void}
stype:Cint
stype::Cint

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Oct 11, 2014

Member

Yikes. That's a typo fix that should be ported to master and release-0.3. cc: @jiahao, @andreasnoack

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Oct 11, 2014

Author Member

Already on master.

itype::Cint
xtype::Cint
dtype::Cint
Expand Down
6 changes: 3 additions & 3 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ subtypes(x::DataType) = subtypes(Main, x)
subtypetree(x::DataType, level=-1) = (level == 0 ? (x, []) : (x, Any[subtypetree(y, level-1) for y in subtypes(x)]))

# function reflection
isgeneric(f::ANY) = (isa(f,Function)||isa(f,DataType)) && isa(f.env,MethodTable)
isgeneric(f::ANY) = (isa(f,Function) && isa(f.env,MethodTable))

function_name(f::Function) = isgeneric(f) ? f.env.name : (:anonymous)

Expand Down Expand Up @@ -126,8 +126,8 @@ function methods(f::Function)
f.env
end

methods(t::DataType) = (_methods(t,Tuple,0); # force constructor creation
t.env)
#methods(t::DataType) = (_methods(t,Tuple,0); # force constructor creation
# t.env)

function length(mt::MethodTable)
n = 0
Expand Down
60 changes: 30 additions & 30 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,39 @@ type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N}
first_index::Int

# Note: no bounds-checking on construction. See issue #4044

#linear indexing constructor (scalar)
if N == 0 && length(I) == 1 && A <: Array
function SubArray(p::A, i::(Int,))
new(p, i, (), Int[], i[1])
end
#linear indexing constructor (ranges)
elseif N == 1 && length(I) == 1 && A <: Array
function SubArray(p::A, i::(UnitRange{Int},))
new(p, i, (length(i[1]),), [1], first(i[1]))
end
function SubArray(p::A, i::(Range{Int},))
new(p, i, (length(i[1]),), [step(i[1])], first(i[1]))
end
else
function SubArray(p::A, i::I)
newdims = Array(Int, 0)
newstrides = Array(Int, 0)
newfirst = 1
pstride = 1
for j = 1:length(i)
if isa(i[j], Int)
newfirst += (i[j]-1)*pstride
else
push!(newdims, length(i[j]))
#may want to return error if step(i[j]) <= 0
push!(newstrides, isa(i[j],UnitRange) ? pstride :
pstride * step(i[j]))
newfirst += (first(i[j])-1)*pstride
end
pstride *= size(p,j)
global call
function call{T,A<:Array,I<:(Any,)}(::Type{SubArray{T,0,A,I}}, p::A, i::(Int,))
new(p, i, (), Int[], i[1])
end

function call{T,A<:Array,I<:(Any,)}(::Type{SubArray{T,1,A,I}}, p::A, i::(UnitRange{Int},))
new(p, i, (length(i[1]),), [1], first(i[1]))
end

function call{T,A<:Array,I<:(Any,)}(::Type{SubArray{T,1,A,I}}, p::A, i::(Range{Int},))
new(p, i, (length(i[1]),), [step(i[1])], first(i[1]))
end

function SubArray(p::A, i::I)
newdims = Array(Int, 0)
newstrides = Array(Int, 0)
newfirst = 1
pstride = 1
for j = 1:length(i)
if isa(i[j], Int)
newfirst += (i[j]-1)*pstride
else
push!(newdims, length(i[j]))
#may want to return error if step(i[j]) <= 0
push!(newstrides, isa(i[j],UnitRange) ? pstride :
pstride * step(i[j]))
newfirst += (first(i[j])-1)*pstride
end
new(p, i, tuple(newdims...), newstrides, newfirst)
pstride *= size(p,j)
end
new(p, i, tuple(newdims...), newstrides, newfirst)
end
end

Expand Down
Loading

0 comments on commit 51a3069

Please sign in to comment.