|
| 1 | +abstract type StaticContext end |
| 2 | +abstract type DefaultStaticContext <: StaticContext end |
| 3 | + |
| 4 | +struct DefaultCtx <: DefaultStaticContext end |
| 5 | + |
| 6 | +""" |
| 7 | +```julia |
| 8 | +static_type(ctx::StaticContext, x) |
| 9 | +static_type(x) |
| 10 | +``` |
| 11 | +
|
| 12 | +Returns an object similar to `x` with contents converted based on rules |
| 13 | +specified by `ctx`. `static_type` can be used for types or for objects. |
| 14 | +
|
| 15 | +For the default case, this converts `Array`s to `MallocArray`s and |
| 16 | +`String`s to `MallocString`s. |
| 17 | +
|
| 18 | +To define your own rules, create a new `StaticContext` and then define |
| 19 | +two versions of `static_type` for each type you would like to convert. |
| 20 | +One converts the value, and one converts the type. Here is the builtin |
| 21 | +example for converting Arrays: |
| 22 | + |
| 23 | +``` |
| 24 | +struct MyCtx <: StaticContext end |
| 25 | +static_type(ctx::MyCtx, x::Array) = MallocArray(x) |
| 26 | +static_type(ctx::MyCtx, ::Type{Array{T,N}}) where {T,N} = MallocArray{T,N} |
| 27 | +``` |
| 28 | +For this context struct, inherit from `StaticTools.DefaultStaticContext` |
| 29 | +to build on the defaults, or inherit from `StaticTools.StaticContext` |
| 30 | +to define rules from scratch. |
| 31 | +
|
| 32 | +`static_type` is mainly useful for converting objects that are heavily |
| 33 | +paramaterized. The SciML infrastructure has a lot of this. The main |
| 34 | +objects like a `DiffEq.Integrator` has many type parameters, and by |
| 35 | +default, some are not amenable to static compilation. `static_type` |
| 36 | +can be used to convert them to forms that can help numerical code to |
| 37 | +be statically compiled. |
| 38 | +
|
| 39 | +`static_type` cannot convert all objects automatically. It transforms |
| 40 | +all type parameters and the contents of each field in an object |
| 41 | +(recursively). But, some objects do not define a "fully specified" |
| 42 | +constructor. In some cases, another method, `static_type_contents` |
| 43 | +can help by returning the components to help for a manual invocation |
| 44 | +of the constructor. |
| 45 | +
|
| 46 | +Note that any `Malloc`-objects created through this function must still be |
| 47 | +`free`d manually if you do not wish to leak memory. |
| 48 | +""" |
| 49 | +static_type(x) = static_type(DefaultCtx(), x) |
| 50 | +static_type(ctx::DefaultStaticContext, x::Array) = MallocArray(x) |
| 51 | +static_type(ctx::DefaultStaticContext, ::Type{Array{T,N}}) where {T,N} = MallocArray{T,N} |
| 52 | +static_type(ctx::DefaultStaticContext, x::Vector{Vector{T}}) where {T} = MallocArray(MallocArray.(x)) |
| 53 | +static_type(ctx::DefaultStaticContext, ::Type{Vector{Vector{T}}}) where {T} = MallocVector{MallocVector{T}} |
| 54 | +static_type(ctx::DefaultStaticContext, x::Tuple) = tuple((static_type(ctx, y) for y in x)...) |
| 55 | +static_type(ctx::DefaultStaticContext, x::String) = MallocString(x) |
| 56 | +static_type(ctx::DefaultStaticContext, ::Type{String}) = MallocString |
| 57 | + |
| 58 | +# version for types including parameters |
| 59 | +function static_type(ctx::StaticContext, ::Type{T}) where {T} |
| 60 | + (!isconcretetype(T) || length(T.parameters) == 0) && return T |
| 61 | + return T.name.wrapper{(static_type(ctx, p) for p in T.parameters)...} |
| 62 | +end |
| 63 | + |
| 64 | +function static_type(ctx::StaticContext, x::T) where T |
| 65 | + length(fieldnames(T)) == 0 && return x |
| 66 | + newtypes, newfields = static_type_contents(ctx, x) |
| 67 | + if length(newtypes) > 0 |
| 68 | + return T.name.wrapper{newtypes...}(newfields...) |
| 69 | + else |
| 70 | + return T.name.wrapper(newfields...) |
| 71 | + end |
| 72 | +end |
| 73 | + |
| 74 | +""" |
| 75 | +```julia |
| 76 | +static_type_contents(ctx::StaticContext, x) |
| 77 | +static_type_contents(x) |
| 78 | +``` |
| 79 | +
|
| 80 | +Returns a tuple with: |
| 81 | +
|
| 82 | +* a vector of type parameters for `x` transformed by `static_type` |
| 83 | +* a vector of the contents of the fields in `x` transformed by |
| 84 | + `static_type` |
| 85 | +
|
| 86 | +Results can be useful for defining objects that do not define a |
| 87 | +fully specified constructor. |
| 88 | +""" |
| 89 | +static_type_contents(x) = static_type_contents(DefaultCtx(), x) |
| 90 | +function static_type_contents(ctx::StaticContext, x::T) where T |
| 91 | + newtypes = [static_type(ctx, p) for p in T.parameters] |
| 92 | + newfields = [static_type(ctx, getfield(x, i)) for i in 1:fieldcount(T)] |
| 93 | + return newtypes, newfields |
| 94 | +end |
| 95 | + |
0 commit comments