"""
    get_compute_function(graph::DAG, process::AbstractProcessDescription, machine::Machine)

Return a function of signature `compute_<id>(input::AbstractProcessInput)`, which will return the result of the DAG computation on the given input.
"""
function get_compute_function(graph::DAG, process::AbstractProcessDescription, machine::Machine)
    tape = gen_tape(graph, process, machine)

    initCaches = Expr(:block, tape.initCachesCode...)
    assignInputs = Expr(:block, expr_from_fc.(tape.inputAssignCode)...)
    code = Expr(:block, expr_from_fc.(tape.computeCode)...)

    functionId = to_var_name(UUIDs.uuid1(rng[1]))
    resSym = eval(gen_access_expr(entry_device(tape.machine), tape.outputSymbol))
    expr = Meta.parse(
        "function compute_$(functionId)(data_input::AbstractProcessInput) $(initCaches); $(assignInputs); $code; return $resSym; end",
    )

    func = eval(expr)

    return func
end

"""
    execute(graph::DAG, process::AbstractProcessDescription, machine::Machine, input::AbstractProcessInput)

Execute the code of the given `graph` on the given input particles.

This is essentially shorthand for
```julia
tape = gen_tape(graph, process, machine)
return execute_tape(tape, input)
```

See also: [`parse_dag`](@ref), [`parse_process`](@ref), [`gen_process_input`](@ref)
"""
function execute(graph::DAG, process::AbstractProcessDescription, machine::Machine, input::AbstractProcessInput)
    tape = gen_tape(graph, process, machine)
    return execute_tape(tape, input)
end
