src/Metaprogramming.jl

Wed, 22 Dec 2021 11:14:38 +0200

author
Tuomo Valkonen <tuomov@iki.fi>
date
Wed, 22 Dec 2021 11:14:38 +0200
changeset 35
d881275c6564
child 37
f8be66557e0f
permissions
-rw-r--r--

Add metaprogramming tools and fast multidimensional loops.

##################
# Metaprogramming
##################

"""
`module AlgTools.MetaProgramming`

This module implements helpers for metaprogramming, used, e.g., by `Loops`.
It includes the macros `@foldl`, `@all`, and `@map` and the metaprogramming
functions `foldl_exprs`, `all_exprs`, `map_exprs`, `lift_exprs`, and `sequence_exprs`.
"""

module Metaprogramming

##############
# Our exports
##############

export @foldl,
       @all,
       @map,
       foldl_exprs,
       all_exprs,
       map_exprs,
       lift_exprs,
       sequence_exprs

###########################################
# Support functions for macro construction
###########################################

""""
`foldl_exprs(f, a)`

Does `foldl` on the `Expr`s in `a` with the `f`, a `Function` or another `Expr`
representing a function. Returns new `Expr` with the expanded `foldl` operation.
"""
function foldl_exprs(f :: Expr, a)
   return foldl((b, c) -> :($f($b, $c)), a)
end

function foldl_exprs(f :: Function, a)
   return foldl((b, c) -> :($(f(b, c))), a)
end

""""
`all_exprs(a...)`

Does `all` on the `Expr`s in `a`.
Returns new `Expr` with the expanded `all` operation.
"""
function all_exprs(a)
   return foldl((b, c) -> :( $b && $c ), a)
end

""""
`map_exprs(f, a...)`

Does `map` on the `Expr`s in `a` with the `f`, a `Function` or another `Expr`
representing a function. Returns a new `NTuple` with `Expr`s for the result of
applying a to all elements of `a`.
"""
function map_exprs(f :: Expr , a)
   return ([ :( $f($b) ) for b ∈ a ]...,)
end

function map_exprs(f :: Function , a)
   return ([ :( $(f(b)) ) for b ∈ a ]...,)
end

""""
`lift_exprs(a)`

Turns a `Tuple` `a` of `Expr`s into an `Expr` containing `Tuple`.
"""
function lift_exprs(a)
    return :( ($(a...),) )
end

"""
`sequence_exprs(a)`

Turns a `Tuple` `a` of `Expr`s into an `Expr` with each original expr on its own line (separated by `;`).
"""
function sequence_exprs(a)
    return foldl_exprs((b, c) -> :( $b; $c ), a)
end


#########
# Macros
#########

""""
`@foldl(f, a...)`

A basic macro version of `foldl`.
"""
macro foldl(f, a...)
    return foldl_exprs(f, a)
end

""""
`@all(a...)`

A macro version of `all`.
"""
macro all(a...)
    # Implementation based on @foldl:
    #return :( @foldl((b, c) -> b && c, $(a...))  )
    # Direct implementation produces prettier generated code:
    return all_exprs(a)
end

""""
`map(f, a...)`

A macro version of `map`.
"""
macro map(f, a...)
    return lift_exprs(map_exprs(f, a))
end

end # module

mercurial