**Note: this feature is experimental and the API might change frequently**

`toexpr(ex)`

turns any expression (`ex`

) into the equivalent `Expr`

which is suitable for `eval`

. The `SymbolicUtils.Code`

module provides some combinators which provides the ability to construct more complex expressions than just function calls. These include:

Let blocks

Functions with arguments and keyword arguments

Functions with arguments which are to be de-structured

Expressions that set array elements in-place

Expressions that create an array similar in type to a reference array (currently supports

`Array`

,`StaticArrays.SArray`

, and`LabelledArrays.SLArray`

)Expressions that create sparse arrays

**Do using SymbolicUtils.Code to get the following bindings**

`toexpr`

`toexpr(ex, [st,])`

Convert a symbolic expression into an `Expr`

, suitable to be passed into `eval`

.

For example,

```
julia> @syms a b
(a, b)
julia> toexpr(a+b)
:((+)(a, b))
julia> toexpr(a+b) |> dump
Expr
head: Symbol call
args: Array{Any}((3,))
1: + (function of type typeof(+))
2: Symbol a
3: Symbol b
```

Note that the function is an actual function object.

For more complex expressions, see other code-related combinators,

Namely `Assignment`

, `Let`

, `Func`

, `SetArray`

, `MakeArray`

, `MakeSparseArray`

and `MakeTuple`

.

To make your own type convertible to Expr using `toexpr`

define `toexpr(x, st)`

and forward the state `st`

in internal calls to `toexpr`

. `st`

is state used to know when to leave something like `y(t)`

as it is or when to make it `var"y(t)"`

. E.g. when `y(t)`

is itself the argument of a function rather than `y`

.

These are all exported when you do `using SymbolicUtils.Code`

`Assignment(lhs, rhs)`

An assignment expression. Shorthand `lhs ← rhs`

(`\leftarrow`

)

`Let(assignments, body[, let_block])`

A Let block.

`assignments`

is a vector of`Assignment`

s`body`

is the body of the let block`let_block`

boolean (default=true) – do not create a let block if false.

`Func(args, kwargs, body[, pre])`

A function.

`args`

is a vector of expressions`kwargs`

is a vector of`Assignment`

s`body`

is the body of the function`pre`

a vector of expressions to be prepended to the function body, for example, it could be`[Expr(:meta, :inline), Expr(:meta, :propagate_inbounds)]`

to create an`@inline @propagate_inbounds`

function definition.

**Special features in args**:

args can contain

`DestructuredArgs`

call expressions

For example,

```
julia> @syms a b c t f(d) x(t) y(t) z(t)
(a, b, c, t, f(::Number)::Number, x(::Number)::Number, y(::Number)::Number, z(::Number)::Number)
julia> func = Func([a,x(t), DestructuredArgs([b, y(t)]), f], # args
[c ← 2, z(t) ← 42], # kwargs
f((a + b + c) / x(t) + y(t) + z(t)));
julia> toexpr(func)
:(function (a, var"x(t)", var"##arg#255", f; c = 2, var"z(t)" = 42)
let b = var"##arg#255"[1], var"y(t)" = var"##arg#255"[2]
f((+)(var"y(t)", var"z(t)", (*)((+)(a, b, c), (inv)(var"x(t)"))))
end
end)
```

the second argument is a

`DestructuredArgs`

, in the`Expr`

form, it is given a random name, and is expected to receive a vector or tuple of size 2 containing the values of`b`

and`y(t)`

. The let block that is automatically generated "destructures" these arguments.`x(t)`

and`y(t)`

have been replaced with`var"x(t)"`

and`var"y(t)"`

symbols throughout

the generated Expr. This makes sure that we are not actually calling the expressions `x(t)`

or `y(t)`

but instead passing the right values in place of the whole expression.

`f`

is also a function-like symbol, same as`x`

and`y`

, but since the`args`

array contains`f`

as itself rather than as say,`f(t)`

, it does not become a`var"f(t)"`

. The generated function expects a function of one argument to be passed in the position of`f`

.

An example invocation of this function is:

```
julia> executable = eval(toexpr(func))
#10 (generic function with 1 method)
julia> executable(1, 2.0, [2,3.0], x->string(x); var"z(t)" = sqrt(42))
"11.98074069840786"
```

`SpawnFetch{ParallelType}(funcs [, args], reduce)`

Run every expression in `funcs`

in its own task, the expression should be a `Func`

object and is passed to `Threads.Task(f)`

. If `Func`

takes arguments, then the arguments must be passed in as `args`

–a vector of vector of arguments to each function in `funcs`

. We don't use `@spawn`

in order to support RuntimeGeneratedFunctions which disallow closures, instead we interpolate these functions or closures as smaller RuntimeGeneratedFunctions.

`reduce`

function is used to combine the results of executing `exprs`

. A SpawnFetch expression returns the reduced result.

Use `Symbolics.MultithreadedForm`

ParallelType from the Symbolics.jl package to get the RuntimeGeneratedFunction version SpawnFetch.

`ParallelType`

can be used to define more parallelism types SymbolicUtils supports `Multithreaded`

type. Which spawns threaded tasks.

`SetArray(inbounds, arr, elems)`

An expression representing setting of elements of `arr`

.

By default, every element of `elems`

is copied over to `arr`

,

but if `elems`

contains `AtIndex(i, val)`

objects, then `arr[i] = val`

is performed in its place.

`inbounds`

is a boolean flag, `true`

surrounds the resulting expression in an `@inbounds`

.

`MakeArray(elems, similarto, [output_eltype=nothing])`

An expression which constructs an array.

`elems`

is the output array`similarto`

can either be a type, or some symbol that is an array whose type needs to be emulated. If`similarto`

is a StaticArrays.SArray, then the output array is also created as an`SArray`

, similarly, an`Array`

will result in an`Array`

, and a`LabelledArrays.SLArray`

will result in a labelled static array.`output_eltype`

: if set, then forces the element type of the output array to be this. by default, the output type is inferred automatically.

You can define:

```
@inline function create_array(A::Type{<:MyArray},a
::Nothing, d::Val{dims}, elems...) where dims
# and
@inlline function create_array(::Type{<:MyArray}, T, ::Val{dims}, elems...) where dims
```

which creates an array of size `dims`

using the elements `elems`

and eltype `T`

, to allow `MakeArray`

to create arrays similarto `MyArray`

s.

`MakeSpaseArray(array)`

An expression which creates a `SparseMatrixCSC`

or a `SparseVector`

.

The generated expression contains the sparsity information of `array`

,

it only creates the `nzval`

field at run time.

`MakeTuple(tup)`

Make a Tuple from a tuple of expressions.

`LiteralExpr(ex)`

Literally `ex`

, an `Expr`

. `toexpr`

on `LiteralExpr`

recursively calls `toexpr`

on any interpolated symbolic expressions.

© Shashi Gowda, Yingbo Ma, Mason Protter. Last modified: August 23, 2022. Website built with Franklin.jl and PkgPage.jl.