WIP: patches for TensorOperations.jl

Dear Tim,

this is my first attempt at making some changes to cartesian.jl. I have added the possibility of having multiple dimensionality parameters as a tuple (N1,N2,...) and added a call to `exprresolve` for the `bodyfunc`, so that one can use `@nloops` and friends with simple arithmetic expressions.

Some questions/issues remain.
1) I wanted to add the possibility to specify the dimensions to explicitly build in the macro syntax, so that you could do something like 
```julia
@ngenerate N returntype SOME_CONSTANT_LIST function f(...)
end
```
However, I don't know how to force evaluation of SOME_CONSTANT_LIST in the module where this macro is called, so I now call this is
```@eval @ngenerate N returntype $SOME_CONSTANT_LIST function f(...)```
and then use the code in line 48 and 52 to assign the value in args[1] to dims. There is probably a better way to do this, but I am still learning to understand all the subtleties of  `esc` and `$(Expr(:quote,...))` etc.

2) I have 2 separated methods for the `ngenerate` function, one where `itersym` is a Symbol (your original version) and one where `itersym` is a tuple of Symbols. In the latter one, I decided to remove all splatting functionality since it seemed like a hassle to make this work with splatting (I also don't see a use case where you have different parameters N1, N2, etc and you want to splat with respect to one of them). 

3) There was still a Base.Cartesian in your original `ngenerate` function, which I replaced (line 129). Another issue with this line. It calls `generate1` with as first argument `$(symbol(itersym))` and another argument `$itersym`. I was thinking that this corresponds to having the first argument of `generate1` of type `Symbol`, and then the other argument, called `N`, of type `Int`, when this function is generated. However, it turns out that `$(symbol(itersym))` and `$itersym` produce the same AST, so that I had to define a method definition for `generate1` where the first argument is of type `Union(Symbol,Int)`. This strikes me as unintended behaviour. The fact that this still works is because all `N`'s in the prototype also get replaced by their integer value, and thus the `sreplace!` in `generate1` isn't really doing anything anymore (as far as I can tell, I am not very qualified in examining this kind of metaprogramming).




My apologies, the new commit I just pushed seems to have already replaced this line comment. In the way `ngenerate` is currently written, it expects `dims` to be a `Vector{NTuple{K,Int}}`, with `K` the number of parameters `N1`, …, `NK`. So that seems to be different from what is returned by this `evaldims` suggestion.

On 15 Jul 2014, at 23:57, Tim Holy <notifications@github.com> wrote:

> In src/Cartesian.jl:
> 
> >      isfuncexpr(funcexpr) || error("Requires a function expression")
> > -    esc(ngenerate(itersym, returntypeexpr, funcexpr.args[1], N->sreplace!(copy(funcexpr.args[2]), itersym, N)))
> > +    
> > +    if isa(itersyms, Symbol)
> > +        dims = length(args) == 1 ? [1:CARTESIAN_DIMS] : args[1]
> But of course you'll have to evaluate that dims expression, e.g.,
> 
> function evaldims(ex::Expr)
>     if ex.head == :tuple
>         dims = [evaldims(arg) for arg in ex.args]
>     elseif ex.head == :(:) && length(ex.args) == 2 && all(x->isa(x, Int), ex.args)
>         dims = ex.args[1]:ex.args[2]
>     else
>         error("Cannot parse dims")
>     end
>     dims
> end
> —
> Reply to this email directly or view it on GitHub.
>