Skip to content
This repository has been archived by the owner on Feb 7, 2019. It is now read-only.

M3/heisenbug #11

Closed
wants to merge 15 commits into from
Closed
413 changes: 317 additions & 96 deletions src/Traits.jl

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/base_fixes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ function Base.func_for_method(m::Method, tt, env)
end
end
println(" endof ok-warning.")


# eltype for dicts
Base.eltype{K}(::Type{Associative{K}}) = (K,Any)
Base.eltype(::Type{Associative}) = (Any,Any)
24 changes: 12 additions & 12 deletions src/commontraits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,19 @@ end

@traitdef Assoc{X} <: Indexable{X} begin
K,V = eltype(X)

# note, ObjectId dict is not part of this interface
haskey(X, All)
get(X, All, All)
get(Function, X, All)
get!(X, All, All)
get!(Function, X, All)
getkey(X, All, All)
delete!(X, All) -> X
pop!(X, All)
pop!(X, All, All)
merge(X, All...) -> X
merge!(X, All...)
haskey(X, Any)
get(X, Any, Any)
get(Function, X, Any)
get!(X, Any, Any)
get!(Function, X, Any)
getkey(X, Any, Any)
delete!(X, Any) -> X
pop!(X, Any)
pop!(X, Any, Any)
# merge(X, Any...) -> X
# merge!(X, Any...)
# provieds
# keys(X) -> Base.KeyIterator
# values(X) -> Base.ValueIterator
Expand Down
67 changes: 32 additions & 35 deletions src/traitdef.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#
# It looks like
# @traitdef Cmp{X,Y} <: Eq{X,Y} begin
# T = eltype(X) # associated type
# isless(x,y) -> Bool
# @constraints begin
# X==Y
Expand Down Expand Up @@ -95,7 +96,7 @@ function parsebody(body::Expr)
isassoc(ex::Expr) = ex.head==:(=) # associated types
isconstraints(ex::Expr) = ex.head==:macrocall # constraints

outfns = Expr(:dict)
outfns = :(Traits.FDict())
constr = :(Bool[])
assoc = quote end
for ln in Lines(body)
Expand Down Expand Up @@ -132,49 +133,60 @@ function parseconstraints!(constr, block)
end

function parsefnstypes!(outfns, ln)
# parse one line containing a function definition
function parsefn(def)
# Parse to get function signature.
# parses f(X,Y), f{X <:T}(X,Y) and X+Y
tvars = Any[]
if isa(def.args[1], Symbol) # f(X,Y)
# into f and _f(...)

# getsymbol = gensym
getsymbol(fn) = symbol("__"*string(fn))

_fn = deepcopy(def)
if isa(def.args[1], Symbol) # f(X,Y) or X+Y
fn = def.args[1]
_fn.args[1] = getsymbol(fn)
elseif def.args[1].head==:curly # f{X}(X,Y)
fn = def.args[1].args[1]
# get
tvars = def.args[1].args[2:end]
_fn.args[1].args[1] = getsymbol(fn)
else
throw(TraitException(
"Something went wrong parsing the trait definition body with line:\n$ln"))
"Something went wrong parsing the trait function definition:\n$fn"))
end
argtype = :()
append!(argtype.args, def.args[2:end])
return fn, argtype, tvars
# transform X->::X
for i=2:length(_fn.args)
@show _fn.args[i]
_fn.args[i] = :(::$(_fn.args[i]))
end
@show fn, _fn
return fn, _fn
end
function parseret!(rettype, ln)
# parse to get return types
while ln.head!=:block
ln = ln.args[end]
end
tmp = rettype.args
rettype.args = Any[]
push!(rettype.args, ln.args[end])
rettype.args = Any[] # per-pend
push!(rettype.args, :($(ln.args[end])())) # e.g. Bool(), the () is for return_types to work
append!(rettype.args, tmp)
end


rettype = :()
tuplereturn = false
if ln.head==:tuple
tuplereturn = true
# several ret-types:
# f1(X,Y) -> X,Y
append!(rettype.args, ln.args[2:end])
for r in ln.args[2:end]
push!(rettype.args, :($r()))
end
ln = ln.args[1]
end

if ln.head==:(->) # f1(X,Y) -> x
parseret!(rettype, ln)
fn, argtype, tvars = parsefn(ln.args[1])
fn, _fn = parsefn(ln.args[1])
elseif ln.head==:call # either f1(X,Y) or X + Y -> Z
if isa(ln.args[end], Expr) && ln.args[end].head==:(->) # X + Y -> Z
def = Expr(:call)
Expand All @@ -187,37 +199,22 @@ function parsefnstypes!(outfns, ln)
parseret!(rettype, ln)
else # f1(X,Y)
def = ln
rettype = :(Any,)
rettype = :(Any(),)
end
fn, argtype, tvars = parsefn(def)
fn, _fn = parsefn(def)
else
throw(TraitException(
"Something went wrong parsing the trait definition body with line:\n$ln"))
end
# replace types with constraints by TypeVars
tmp = Any[]
for t in tvars
if isa(t,Symbol)
#error("Having a ")
push!(tmp,t)
else
push!(tmp,t.args[1])
end
end
# trans = Dict(zip([t.args[1] for t in tvars], tvars)) # this will error if there is a type-var without constraints!
trans = Dict(zip(tmp,tvars))
translate!(argtype.args, trans)
tvar2tvar!(argtype.args)
subt2tvar!(rettype.args)
translate!(rettype.args, trans)
tvar2tvar!(rettype.args)

# if return is not a tuple, ditch the tuple
if !tuplereturn
rettype = rettype.args[1]
end

push!(outfns.args, :($fn => ($argtype, $rettype)))
# make _fn
_fn = :($_fn = $rettype)
push!(outfns.args, :($fn => $_fn))
end

# 3) piece it together
Expand Down Expand Up @@ -274,7 +271,7 @@ macro traitdef(head, body)
# make sure a generic function of all associated types exisits

traitbody = quote
methods::Dict{Union(Function,DataType), Tuple}
methods::Traits.FDict
constraints::Vector{Bool}
assoctyps::Vector{Any}
function $((name))()
Expand Down
Loading