mauro3 / Traits.jl

Exploration of traits in Julia
Other
39 stars 6 forks source link

@traitfn macro fails to parse deeply nested types correctly #32

Open pkalikman opened 8 years ago

pkalikman commented 8 years ago

E.g.:

@traitdef SomeTrait{Type1,Type2} begin
     some_function(Int64,Array{Type1,1},Array{Type2,1}) -> Int64
     other_function(Int64,Array{Type1,1},Array{Type2,1}) -> Array{Int64,1}
end

And suppose

@assert istrait(SomeTrait{FirstType1,FirstType2})
@assert istrait(SomeTrait{SecondType1,SecondType2})

Then

@traitfn function work_with_pairs{
     FirstType1,FirstType2,SecondType1,SecondType2;
     SomeTrait{FirstType1,SecondType1},
     SomeTrait{FirstType2,SecondType2}}(
     some_int::Int64,
     first_tuples::Array{Tuple{FirstType1,FirstType2},1},
     second_tuples::Array{Tuple{SecondType1,SecondType2},1})
...
end

Gets an error when the macro expands. Using macroexpand I was able to establish that essentially the references to FirstType1 etc. inside Tuple inside Array aren't being parsed consistently to/from X1, X2, i.e. there is a point at which one should convert back between X1 and FirstType1, but the macro does not, so the identifier is undefined when the function tries to compile. Therefore if you do exactly the above, but rename FirstType1 to X1 and so on in the order these appear, then this actually works:

@traitfn function work_with_pairs{
     X1,X2,X3,X4;
     SomeTrait{X1,X3},
     SomeTrait{X2,X4}}(
     some_int::Int64,
     first_tuples::Array{Tuple{X1,X2},1},
     second_tuples::Array{Tuple{X3,X4},1})
end

So I'm using this as a workaround for now, but it seems that it should be straightforward to fix; I just haven't taken the time to unpack the substitution logic in @traitfn.

Thanks

mauro3 commented 8 years ago

Thanks for the report, PR welcome ;-)