Basic concepts

GPScript is a programming language designed specifically for use with Gig Performer. Rather than integrating an existing language such as Lua, Python or ChaiScript and living with some compromises, we felt it worthwhile to have an essentially seamless environment that would immediately make sense. The clean syntax reflects that integration. GPScript is influenced more by Algol/Pascal. While we will assume for now that the reader has at least some basic understanding of programming there will be plenty of samples to help users to get up to speed quickly.

As mentioned above, GPScript is a strongly typed language; every variable must be declared along with a type. However, along with the usual types such as integers, strings, doubles and so forth, GPScript has built-in types that represent plugins, widgets, various kinds of LFOs and some special purpose types such as NoteTracker and ChordRecognizer.

So as easily as you can write

var i : Integer

to represent an integer value and perform operations such as addition and subtraction, you can write

var A800 : MidiInBlock

Which represents a named MidiInBlock, presumably associated with an A800 MIDI keyboard controller. Now you can do operations such as manipulate incoming MIDI messages before sending them on to whatever audio plugin is connected to it.

GPScript includes the usual looping and conditional statements and of course you can define your own functions. There is also an extensive collection of efficient built-in functions you can leverage.

A list of built-in functions is provided in the included reference.

Tip

The top of the GPScript editor window has two buttons that provide you with templates to help you get started as well as system function code completion.

../../_images/script-editor-with-left-buttons-highlighted.png

Statements

Assignment

Syntax:

<Identifier> ':=' <Expression>

Assign an expression to a variable. For example:

a := 42
b := a + 1

// You can also write an assignment using just the '=' character
str = "I don't like C syntax"

For

Syntax:

For <Assignment> ';' <BoolExpression> ';' <Assignment> Do
    <Statements>
End

The For loop lets you iterate a statement block until the Boolean expression evaluates to false. It is often used to process an array of values. For Example:

For i = 0; i < 10; i = i + 1 Do
    //statements here
End

While

Syntax:

Syntax: While <BoolExpression> Do
    <Statements>
End

The While statement lets you loop though a block of statements until the Boolean expression evaluates to false. The important difference between a While loop and a For loop is that the former does not have an explicit clause to update the expression to be tested. An example for the While loop:

Done = false
While !Done Do
    // Statements, one of which ultimately sets Done to true
End

Caution

Be very careful with both these looping constructs. If the condition does not ultimately evaluate to false, the loop will never end and Gig Performer will hang.

If

Syntax:

If <BoolExpression> Then
    <Statements>
[ [ Elsif <BoolExpression> Then
    <Statements>]
Else
    <Statements> ]
End

This is the usual conditional test. The requirement for End prevents bugs due to the dangling else problem. The Elsif clause (as many as you need) is optional as is the Else clause.

Select

Syntax:

Select
    [<BoolExpression> Do
    <Statements>]
End

The Select statement is a better option than the If statement when you need to test for many conditions. While similar in concept to the C switch statement or the Pascal case statement, the Select statement doesn’t require each case to be a constant value.

Select
    a > b Do
        Print("A is greater than B")

    TimeNow() - previousTime > 1000 Do
        Print("At least one second has passed")
        previousTime = TimeNow()

    true Do
        Print("This executes if none of the other expressions were true")
End

Function calls

System functions

GPScript includes a large and growing collection of system functions for a variety of purposes such as math functions (rounding or scaling numbers), creation and modification of MIDI messages, management of function generators. A list of functions that are built into GPScript is provided in the included reference.

User functions

You can also write your own functions in GPScript.

Syntax:

Function <name> ([<identifier> : <type> [, <identifier> : <type>]]) [Autotype] [Returns <type>]
    <Local variable declarations>

    <Statements>
End

Functions must have a unique name. Zero or more parameters can be defined and parameters are always passed in by value. Note that types such as Widgets, Plugins and dynamic arrays are objects and so what’s really being passed by value is the reference (a pointer) to the object.

The Autotype keyword is used to let a function be a little (not a lot) more forgiving about the types of the parameters that are passed into it. In the example here, the use of Autotype allows a function to accept integers or doubles (and strings of course):

Function Add(x, y : String) Autotype
    Print(x + y)
End

Initialization
    Add(1, 2)
End

An autotyped function with a MidiMessage parameter will accept calls with specific kinds of messages such as NoteMessage or ControlChangeMessage.

Functions can optionally return a value in which case the Returns clause must be present. If the Returns clause is present, then a variable called result exists in the function scope and whatever is assigned to that variable will be the return value. There is no mechanism to return from the middle of a function.

Examples:

Function SumNumbers(a,b,c : integer) Returns Integer
    result = a + b + c
End
Function PlayMajorChord(keyboard : MidiInBlock, root : NoteMessage)
    SendNow(keyboard, root)               // Original note
    SendNow(keyboard, Transpose(root, 4)) // The third
    SendNow(keyboard, Transpose(root, 7)) // The fifth
End

Operators

In this chapter, you will learn about operators in GPScript.

Arithmetic operators

GPScript supports the normal +, -, * and / arithmetic binary operators on integers and on floating point numbers. There is also a modulo operator % which works only with integers.

Boolean operators

GPScript has the usual comparison operators (<, >, <=, >=, ==, !=) as well as boolean operators (And, Or, Not). Precedence rules are such that you very rarely require parentheses. GPScript also has a ternary operator following the style of Algol and, more recently, Haskell:

Result = If widgetValue > 0.5 Then 1 Else 0 End

Note that the Else is not optional in the ternary operator.

The And and Or operators can also be used with integer expressions on both sides in which case these operators perform bitwise and and or operations respectively. The operators << and >> meaning ShiftLeft and ShiftRight respectively can also be used with integers.

The in operator

The in operator allows the left hand side, normally an integer (Integer) or a floating point number (Double) to be tested against an integer or floating point respectively range. So you can write:

If n in [C3..C4] Then

The variable n would normally be an integer type. However, this will also work if n is a NoteMessage or a ControlChangeMessage and in these cases the note number or controller number will be used.

Unary prefix operators

A single - (minus) can be used as a number prefix to invert the sign of that number. The keyword not can be used to invert a boolean value or expression.

Unary postfix operators

The hash sign # can follow a identifier whose type is a parameter (Scriptlet plugins only) and returns the numeric parameter number associated with that parameter.

AsNoteNames operator

The operator AsNoteNames followed by an integer range creates a string array whose values are strings of MIDI note names matching the integer range.

Usage with string arrays:

Var notes : String Array = AsNoteNames C3 .. E3

is equivalent to writing:

Var notes : String Array = ["C3", "C#3", "D3", "D#3", "E3"]

Usage with scriptlet parameters:

Var notes : parameter AsNoteNames C3 .. E3 = "C3"

This is equivalent to writing:

Var notes : parameter "C3", "C#3", "D3", "D#3", "E3"  = "C3"

Note the slightly different syntax between the two versions. In the former, we have created a string array and are assigning a sequence of strings to it. In the latter, the sequence of strings causes the parameter to be a discrete parameter and the assignment is used to specify the initial value of the parameter.

String concatenation

The + operator is overloaded for strings and is used to concatenate two strings together.

Append scalar to array

The <-- assignment can be used in place of a regular assignment operation and serves to append a scalar to an array of the same type. This mechanism works for Integer, Double, Boolean, String and MidiMessage types.

var
    s : Integer array = [1,2,3]
Initialization
    s <-- 42   // Appends 42 to the end of the array
End