Skip to content
This repository was 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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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