Skip to content

Defines

Defines provide compile-time text substitution. They come in five forms: simple, parameterized, append (+=), prepend (=+), and literal.

Simple Defines

define NAME := value

Wherever NAME appears, it is replaced with value at compile time.

define TYPE.MEM_CLEAR := -123547689
define BOOL.TRUE := (bool_validator = bool_validator)
define BOOL.FALSE := (bool_validator # bool_validator)
define CASE.ELSE := (080000000H to 07FFFFFFH)

define use_ram_report := lib.is_dev_mode()
define path_on := (NodeEnv[nenv].info.path_cancelled = FALSE and self_invalid = FALSE)

Parameterized Defines

define NAME(#param1#, #param2#) := expression

Single-expression substitution with parameters (like inline macros):

define EP(#par#) := ENGINE_PAR_#par#
define float(#x#) := real(#x#)
define check_ref(#type#, #ref#) := (#ref# > -1 and #type#.is_alloc[#ref#] > 0)
define node_arg(#arg#) := ivls.flow_args[Voice[self].flow, Voice[self].stage, #arg#]

Usage:

EP(VOLUME)           // -> ENGINE_PAR_VOLUME
float(my_int)        // -> real(my_int)
check_ref(Voice, vo) // -> (vo > -1 and Voice.is_alloc[vo] > 0)

Validation Defines

define Voice.validate.input(#v#) := (in_range(#v#, 0, ivls.input_type.SIZE - 1))
define Voice.validate.note(#v#) := (in_range(#v#, 0, 127))
define Voice.validate.vel(#v#) := (in_range(#v#, 1, 127))
define Voice.validate.runtime(#v#) := (#v# >= -1)
define Voice.validate.event(#v#) := (BOOL.TRUE)

Append (+=) and Prepend (=+)

Append

Extends an existing define by appending to it. Fundamental for building extensible lists:

define CLUSTER_TABLE += Voice
define DEBUGS += IVLS_ALL_NODES
define FLOWS += steparp.seq_step_notify

Member Extension Pattern

Libraries contribute members to shared clusters:

// In fades.ksp
define Voice.ADD_MEMBERS += Stl.Modulation.MEMBERS
define Voice.ADD_INIT += Stl.Modulation.INIT

// In legato-base.ksp
define Voice.ADD_MEMBERS += Stl.LegatoInfo.MEMBERS
define Voice.ADD_INIT += Stl.LegatoInfo.INIT

// Base system combines all
define Voice.MEMBERS := Voice.BASE_MEMBERS, Voice.ADD_MEMBERS
define Voice.INIT_LIST := Voice.BASE_INIT, Voice.ADD_INIT

Multi-line Defines

The ... continuation token allows readable multi-line lists:

define IVLS_BASE_NODES := Ivls.NodeUI, ...
                          Ivls.STL, ...
                          Ivls.VoiceOps, ...
                          Ivls.Flows, ...
                          Ivls.Keymaps, ...
                          Ivls.NodeEnv, ...
                          Ivls.Runtimes, ...
                          Ivls.VMC
define Voice.BASE_MEMBERS := ...
    input, ...
    runtime, ...
    auto_release, ...
    vo_parent, ...
    vo_child, ...
    vo_left, ...
    vo_right, ...
...
    flow, ...
    stage, ...
    note, ...
    vel, ...
    midi_ch, ...
    volume, ...
    pan, ...
    tune, ...
    dyn_layer, ...
    rr

Blank lines with ... create visual groupings. Inline comments use { }.


Recursive Resolution

Defines reference other defines, resolved recursively at compile time:

define IVLS_BASE_NODES := Ivls.NodeUI, Ivls.STL, Ivls.VoiceOps, ...
define IVLS_NODES := MyNode
define IVLS_ALL_NODES := IVLS_BASE_NODES, IVLS_NODES, Stl.Lib_Post

When IVLS_ALL_NODES is expanded, IVLS_BASE_NODES is first resolved to its full list (including Ivls.STL which is itself a multi-node define), then IVLS_NODES, producing a flat list.


Defines as Lists (for literate_macro)

Define lists are consumed by literate_macro for code generation:

// Generate constants for each node
const ivls.node
    literate_macro(#l#) on IVLS_ALL_NODES
end const

// Generate name mappings
literate_macro(ivls.node_names[ivls.node.#l#] := "#l#") on IVLS_ALL_NODES

// Generate declarations
literate_macro(declare Node.#l# := #n#) on IVLS_ALL_NODES

Member lists are consumed by the type system:

const #type#.field
    literate_post_macro(#l#) on #type#.MEMBERS
end const

literate_post_macro(type._Property(#type#, #l#)) on #type#.MEMBERS

See Also