Skip to content

The CKSP Syntax

The cksp syntax introduces a dialect of vanilla ksp that incorporates syntax elements from Python, TypeScript, and Lua, allowing for the use of more advanced programming abstractions and modularity when developing Kontakt instruments. This can improve both the readability and maintainability of the code. In the following sections, we will explore the syntax of cksp in detail. The sections are focussed on the specific features and do not explain the individual transformations or lowerings that cksp performs to convert the code into valid vanilla ksp. I might add those in the future, but for now, you can find descriptions on some of the transformations in our paper Retrofitting a Virtual Instrument DSL with Programming Abstractions.

The new syntax features that cksp brings in addition to those of vanilla ksp or sublime ksp have grown considerably, so here is a brief overview of the most important ones. Each feature is linked to a more detailed explanation in the Syntax section.

  • Scopes and Local Variables


    1
    2
    3
    4
    5
    6
    declare j := 5
    for i in range(5)
        declare j := 0
        message(j)            // Outputs 0
    end for
    message(j)                // Outputs 5, as the outer j is restored
    

    In addition to global variables in the on init callback, cksp allows for lexical scoping where you can define local variables anywhere, with them only being valid within their scope. This allows the use of variables with the same name in different scopes without conflicts. Scopes and Local Variables

  • Custom Data Structures


    1
    2
    3
    4
    5
    6
    7
    8
    struct Note
        declare pitch: int
        declare velocity: int
    
        function play(self): int
            return play_note(self.pitch, self.velocity, 0, -1)
        end function
    end struct
    

    With cksp, you can create custom data structures that contain methods applicable to the data structure. Additionally, operators can be overloaded to support custom types. Custom Data Structures

  • Typed Functions with Return Values


    1
    2
    3
    4
    5
    6
    7
    8
    function find_first_even(numbers: int[]) : int
        for num in numbers
            if (num mod 2 = 0)
                return num // Early return if even number is found
            end if
        end for
        return -1 // Return -1 if no even number is found
    end function
    

    You can now define functions with return values and types to improve the readability and maintainability of your code. Using return statements, you can control the flow of execution and return values to the caller. Typed Functions

  • Easy Array Iteration with for-each Loops


    Iterating over certain Dimensions
    1
    2
    3
    for idx, elem in pairs(ndarray[0, *])
        message(idx, elem)
    end for
    
    Iterating over Lists of Strings
    1
    2
    3
    for idx, elem in pairs(["Attack", "Sustain", "Release"])
        message(idx, elem)
    end for
    

    With cksp, you can iterate over arrays with a simple loop. Using pairs you can iterate over array elements, dimensions in multidimensional arrays, ranges, or even lists of strings. For-Each Loops

  • Ternary Expressions


    1
    2
    3
    declare x := 5
    declare result := x > 0 ? "Positive" : "Negative"
    message(result)
    

    With cksp, you can use ternary expressions to simplify conditional assignments and improve code readability. Ternary Expressions