_ _ | `. .' | _ _ | \_..._/ | the | | | | / _ _ \ |\_/| __ _ | |_ ___ _ __ ___ __ _ | | __ `-| / \ / \ |-' / __| / _` || __|/ __|| '_ \ / _ \ / _` || |/ / --| | | | | |-- | (__ | (_| || |_ \__ \| |_) || __/| (_| || < .'\ \_/ _._ \_/ /`. \___| \__,_| \__||___/| .__/ \___| \__,_||_|\_\ `~..______ .~' _____| | `. | / ._____/ reference `.| \_) A cross-platform, expression oriented programming language for implementing modding support into your GameMaker Studio 2.3 games. /( > w <") b Developed by [katsaii] ([GitHub] page). Logo design by [mashmerlow]. ================================================================================ Contents (link) ================================================================================ - Installation - Disclaimer - Features - Configuration Basic Usage
Compiling Programs - Executing Programs - Customising The Standard Library
Syntax
Lexical Grammar Statements Expressions
Standard Library
- Constants - Functions - Operators
Library Reference
scr_catspeak_process scr_catspeak_config scr_catspeak_init scr_catspeak_error scr_catspeak_vm scr_catspeak_ir scr_catspeak_intcode scr_catspeak_compiler scr_catspeak_lexer scr_catspeak_token scr_catspeak_alloc
Futures Reference
scr_future scr_future_file
- Theory - License ================================================================================ Installation (link) .txt ================================================================================
1) Get a recent release of Catspeak from the [GitHub releases page]. You should see a download for a file with the extension `.yymps`. 2) Open your project file in the GameMaker IDE. 3) Navigate to the toolbar at the top of the IDE and find "Tools". Click this and select "Import Local Package" from the drop-down menu. 4) Select the `.yymps` file you downloaded, and follow the wizard to import the Catspeak resources. If you're not sure what to import, click "Add All". Now you're setup, see the [Basic Usage] section for some introductory examples, or the [Configuration] section for details about what can be customised within the Catspeak engine.
================================================================================ Disclaimer (link) .txt ================================================================================
Catspeak is currently a solo project (by [katsaii]), and is being maintained in my free-time. However, if you want to make a suggestion or report a bug, please do report it on [GitHub] and I will try to review it as soon as possible!
================================================================================ Features (link) .txt ================================================================================
- **Minimal setup required** ... ready to use after installation. No need to call any weird "init" or "update" functions. (Unless you want to, as a treat!) - **Cross-platform** ... allowing mods to work on any platform out of the box. Tried and tested on the VM and YYC exports on windows, as well as HTML5. - **Sandboxed execution environment** ... so modders cannot modify the sensitive parts of your game you don't want them to. - **Customisable standard library** ... exposing only the functions you want modders to have access to. See the section on [Customising the Standard Library] for more information and examples. - **Performant runtime** ... capable of interpreting thousands of (and even tens of thousands of) Catspeak scripts per step. (Dependent on the complexity of your scripts.) - **Asynchronous execution over multiple steps** ... making it impossible for modders to freeze your game with infinite loops. - **Intelligent process manager** ... so no time is wasted idly waiting for new Catspeak programs to appear. - **Failsafes to catch unresponsive Catspeak processes**. Customise how this is done through the [catspeak_config] function. - **Call GML code from Catspeak**. Just use the syntax you're familiar with: `is_string(value)`. See more in the [Syntax] section. - **Call Catspeak code from GML** ... using the [catspeak_execute] function. See [Basic Usage] for some examples. - **Simple, relaxed syntax** ... but still similar enough to GML to be familiar. - **Pre-compilation of scripts** ... to both reduce load times when initialising mods or obfuscate production code. (Coming Soon!) - **Compiler internals exposed and well-documented** ... in order to give power users as much control over their programs as possible. (See the [Library Reference].) - **Cute name and mascot**.
================================================================================ Configuration (link) .txt ================================================================================
The primary method of configuring Catspeak is through the [catspeak_config] function. This function exposes a struct containing all the global settings, such as how long processes are allowed to run before they become unresponsive. **Please read** the documentation for [catspeak_config] to get an in-depth description of what each option does. Below are a couple of examples showing how to read/write configurations: ``` var configs = catspeak_config(); configs.frameAllocation = 0.25; // only run Catspeak for 25% of a frame configs.processTimeLimit = 5; // all processes can run for 5 seconds // before being forced to stop // get the current process time limit var timeLimit = configs.processTimeLimit; ```
================================================================================ Basic Usage (link) .txt ================================================================================
In Catspeak, Compiling and running programs are separate steps. You should aim to perform any compilation of scripts during a loading screen so that running your programs is much faster.
Compiling Programs (link) .txt ==============================================================================
The first step to running your Catspeak programs involves compiling the source code from its human-readable form into an executable form. This can be done in two ways: from a GML string, or from a character buffer.
Compiling From A String (link) .txt ----------------------------------------------------------------------------
If your Catspeak program is stored within a GML string, you can use the [catspeak_compile_string] function to compile it. Consider the following program: ``` // counts to 10 and then returns a message var src = @' let n = 0 while (n <= 10) { print n n = it + 1 } return "blast off!" '; ``` You can use the [catspeak_compile_string] function to asynchronously compile the sourc code: ``` var process = catspeak_compile_string(src); ``` The `process` variable stores a reference to a [CatspeakProcess] responsible for compiling your code. Once the process is complete, you can retreive the result using the [andThen] method: ``` process.andThen(function(code) { show_message("success!"); }); ``` If the program fails to compile, this callback function will never execute. In this case, you will need to use the `andCatch` method to catch the compilation error: ``` process.andCatch(function(err) { show_message("oh no, an error occurred!"); }); ``` For more information on this behaviour, see the [Future] definition. If after running this example you see a pop-up window with the message "success!", then **congratulations!** You have successfully compiled your first Catspeak program. For information on how to run this program, see the [Executing Programs] section.
Compiling From A Buffer (link) .txt ----------------------------------------------------------------------------
Compiling a buffer works similarly to [Compiling From a String], except you use the [catspeak_compile_buffer] function: ``` catspeak_compile_buffer(buff).andThen(function(code) { show_message(code.disassembly()); }); ``` Different from the [catspeak_compile_string] function, the buffer version accepts an additional parameter, that if set to `true` will automatically delete the buffer once the compiler process ends so you don't have to. By default, this is set to `false`.
Executing Programs (link) .txt ==============================================================================
The second step to running your Catspeak programs is to interpret the compiled code. This can be done using the `catspeak_execute` function. Following on from the example shown in [Compiling From a String], the function contained in the `code` variable can be interpreted like so: ``` catspeak_execute(code).andThen(function(result) { show_message(result); }); ``` This will spawn a new [CatspeakProcess] which goes through the process of interpreting the compiled code. Once the program has finished running, the callback to the [andThen] method is called with the result of the program. In this example, the result was the string `"blast off!"`, so a pop-up window with the message "blast off!" will be shown. If everything went to plan, you should have just compiled and executed your first Catspeak program! NOTE: If you do not care about the result of the program, you can omit the [andThen] method call.
Customising The Standard Library (link) .txt ==============================================================================
You can expose additional functions and constants to Catspeak programs by using [catspeak_add_function] and [catspeak_add_constant]. For example, adding a new function to display a "hello" message in a pop-up window: ``` catspeak_add_function("say_hello", function() { show_message("hello"); }); ``` From now on, any Catspeak **new** programs will be able to use the `say_hello` function.
================================================================================ Syntax (link) .txt ================================================================================
Catspeak is a simple imperative language with a vaguely similar syntax to GML. As an example, consider the following program written in GML to calculate the factorial of a number `n`: ``` // GML CODE function factorial(n) { var m = 1; if (n > 1) { m = n * factorial(n - 1); } return m; } factorial(5); // output: 120 ``` NOTE: This example is intentionally verbose in order to showcase: variables, function declarations, identifiers, "if" statements, function calls, assignment statements, return statements, and comments. Below is the same program written in Catspeak: ``` -- CATSPEAK CODE factorial = fun(n) { let m = 1 if (n > 1) { m = n * factorial(n - 1) } return m } factorial(5) -- output: 120 ``` There are some immediately obvious differences here, such as the `m` variable being declared using `let` instead of `var`, `fun` instead of `function`, and comments using `--` instead of `//`. All of these differences (and more) are described in the [Lexical Grammar] section.
Lexical Grammar (link) .txt ==============================================================================
Catspeak source code is a sequence of ASCII characters. This unfortunately means that Unicode support is not guaranteed to work, but results in a faster compiler. This sequence of characters first needs to be transformed into larger groups of characters called "tokens". The following sections will cover what each of these tokens are composed of.
Whitespace (link) .txt ----------------------------------------------------------------------------
For the most part, Catspeak is whitespace insensitive. There are exceptions to this for [Identifiers] and [Automatic Semicolon Insertion], but otherwise Catspeak ignores the following characters: - Character tabulation '\t' (code point U+0009) - Line feed '\n' (code point U+000A) - Line tabulation '\v' (code point U+000B) - Form feed '\f' (code point U+000C) - Carriage return '\r' (code point U+000D) - Space (code point U+0020) - Next Line (code point U+0085)
Comments (link) .txt ----------------------------------------------------------------------------
The only way to add a comment in Catspeak is to use the special `--` symbol. This will ignore all of the characters after it until a new line is reached. For example: ``` -- this is a Catspeak comment! ``` NOTE: Unlike GML, Catspeak does not support multi-line comments. Use multiple comments instead. NOTE: Because Catspeak allows for custom operators, you **must only** use `--` and not something like `---` or `--//`; otherwise it will be considered a custom operator identifier. For more information, see the [Operator Identifiers] section.
Identifiers (link) .txt ----------------------------------------------------------------------------
Identifiers are mainly used for variable names in Catspeak. The most common kind of identifier is the alphanumeric identifier. These identifiers start with a letter and are followed by a sequence of other letters, numbers, underscores (_), or apostrophes ('). An example of an identifier which uses all of these is `Can't_count_to_10`. The following identifiers are invalid: ``` _invalid 1Invalid 'INVALID' ```
Raw Identifiers (link) .txt --------------------------------------------------------------------------
Raw identifiers are a special type of identifier which starts and ends with the backtick symbol: ``` let `1st-of-march` = "2022-03-01" ``` You can use any valid identifier character between the backticks, in whatever order you decide. This includes [Operator Identifiers].
Operator Identifiers (link) .txt --------------------------------------------------------------------------
Operators in Catspeak aren't special, they are just a kind of identifier which use symbols instead of letters or numbers. Below is a list of valid characters which can be used as operators, sorted by highest precedence to lowest precedence. highest precedence (7): `#`, `.`, `@` (6): `%`, `\` . (5): `*`, `/` . (4): `+`, `-` . (3): `!`, `<`, `=`, `>`, `?`, `~` . (2): `&` (1): `^`, `|` lowest precedence (0): `$`, `:`, `;` Operators on the same line share the same precedence. You can combine as many, or as few, of these symbols together to create your very own operator. Here are a few: `>>=`, `><>`, `;~;`, `>*^-^*<`. The precedence of the new operator will be the same as its first character. So the `>>=` operator will have the same precedence as `>=`.
Keywords (link) .txt ----------------------------------------------------------------------------
Catspeak reserves the following identifiers as keywords: - `--` see [Comments] - `=` see [Let Statements] and [Assignment Expressions] - `:` see [Struct Expressions] - `;` see [Automatic Semicolon Insertion] - `.` see [Accessor Expressions] - `...` see [Automatic Semicolon Insertion] - `do` see [Block Expressions] - `if` see [If Expressions] - `else` see [If Expressions] - `while` see [While Expressions] - `for` (reserved in case of `for` loops) - `loop` (reserved in case of infinite loops) - `let` see [Let Statements] - `fun` see [Function Expressions] - `break` see [Break Expressions] - `continue` see [Continue Expressions] - `return` see [Return Expressions] - `impl` (reserved in case of constructor functions) - `new` (reserved in case of constructor functions) - `self` (reserved in case of method binding) - `and` (reserved in case of short-circuit AND) - `or` (reserved in case of short-circuit OR)
Literals (link) .txt ----------------------------------------------------------------------------
A literal in Catspeak is either a [Numeric Literal] or [String Literal].
Numeric Literals (link) .txt --------------------------------------------------------------------------
Numeric literals are a sequence of ASCII digits, optionally separated by a single decimal point: ``` 1234567890 3.1415 ```
String Literals (link) .txt --------------------------------------------------------------------------
There are two types of string literal in Catspeak. The most common is a sequence of characters starting and ending in double quotes ("): ``` let hi = "hello world" ``` This type of string allows the following escape sequences to be used: - \" Quotation mark - \ Escape new line - \\ Backslash - \t Character tabulation - \n Line feed - \v Line tabulation - \f Form feed - \r Carriage return The other type of string is the **raw string**. A raw string is prefixed by the `@` character, and does not interpret any of the previously mentioned escape sequences: ``` let hi_again = @"\hello\" ```
Automatic Semicolon Insertion (link) .txt ----------------------------------------------------------------------------
Automatic semicolon insertion is a process used to help Catspeak understand when a statement has ended so that another can begin. A semicolon or new line will be expected after the [Let Statement] and [Expression Statement]. All new lines are considered semicolons unless it is preceeded by the `...` operator, or one of the following tokens: - Parens: `(`, `[`, `{` - Built-in operators: `.`, `:`, `,`, `=` - Keywords: `do`, `if`, `else`, `while`, `for`, `let`, `fun` - User-defined operators, see [Operator Identifiers] This means that in order to write Catspeak code in the Allman style, you must use `...` to tell Catspeak that you are continuing the line: ``` while (x == y) ... { something() } ``` This is not necessary for styles where the first `{` appears on the same line: ``` while (x == y) { something() } ``` NOTE: Although none of the examples in this document will use them, you can add explicit semicolons after each of your statements if you prefer.
Statements (link) .txt ==============================================================================
Unlike GML, Catspeak only has two kinds of statement: [Let Statements] and [Expression Statements]. This is because Catspeak is an expression-oriented language, so things like "if" statements become [If Expressions].
Let Statements (link) .txt ----------------------------------------------------------------------------
The `let` statement creates a new local variable in the current block scope. It can optionally be followed by an initialiser expression. If no initialiser expression is used, then the variable will be initialised to `undefined`: ``` let a = 1 + 3 -- initialised to the value 3 let b -- initialised to undefined ``` Unlike GML, catspeak variables are no longer visible after the end of their enclosing block scope, unless another variable of the same name exists in an outer scope.
Expression Statements (link) .txt ----------------------------------------------------------------------------
Most often, an expression statement will evaluate its expression and ignore the result. There is an exception to this rule with [Do Expressions].
Expressions (link) .txt ==============================================================================
An expression is is a term which always produces a value, and may be composed of many sub-expressions. All statements you would typically find in GML appear as expressions in Catspeak. This includes [Break Expressions], [Return Expressions], and [Continue Expressions], all of which return the **never** type; indicating that the expression never returns.
Terminal Expressions (link) .txt ----------------------------------------------------------------------------
Terminal expressions are either non-operator [Identifiers] or [Literals]. These expressions have no further sub-expressions, hence the name.
Operator Expressions (link) .txt ----------------------------------------------------------------------------
Operator expressions can either be unary or binary. A unary operator expression is an operator identifier followed by an [Accessor Expression], [Terminal Expression], or [Grouped Expression]: ``` let unary = -2; ``` A binary operator is made up of an operator identifier sandwiched between two expressions: ``` let binary = 0.1 + 0.9 ``` Both unary and operator expressions are sugar for [Call Expressions]: ``` let unary = `-`(2) let binary = `+`(0.1, 0.9) ```
Assignment Expressions (link) .txt ----------------------------------------------------------------------------
Assignment expressions are made up of two sub-expressions separated by the `=` symbol. The value of the right-hand-side expression will be assigned to the memory location pointed to by the left-hand-side expression. NOTE: The value of an assignment expression will be the value assigned to the variable on the left-hand-side of the expression: ``` let a let b = a = 1 print a == b -- outputs: true ```
It Expressions (link) .txt --------------------------------------------------------------------------
Catspeak does not have reference types. Because of this, it cannot support typical incrementation operators such as `+=`. To solve this problem, Catspeak has an `it` keyword: ``` x = it + 1 -- behaves like x += 1 would in GML ``` The value of the `it` expression will be the value of the left-hand-side sub-expression of its containing assignment expression. So, in the above example, the value of `it` will be the value of the `x` variable. The nice thing about this syntax is it generalises to any expression or function call: ``` x = update(it) ``` This becomes noticable useful when handling [Accessor Expressions]: ``` arr.[0] = update(it) ``` instead of ``` arr.[0] = update(arr.[0]) ```
Grouped Expressions (link) .txt ----------------------------------------------------------------------------
A grouped expression wraps a single sub-expression between `(` and `)`, evaluating the sub-expression. This is typically used to make the precedence of the inner expression clear: ``` let a = 1 + 2 * 3 -- 7 let b = (1 + 2) * 3 -- 9 ```
Array Expressions (link) .txt ----------------------------------------------------------------------------
Arrays are a sequence of comma-separated sub-expressions wrapped between `[` and `]`: ``` let array = [1, 2, 3] ``` For information on how to modify array values see [Accessor Expressions].
Struct Expressions (link) .txt ----------------------------------------------------------------------------
Structs are a sequence of comma-separated key-value pairs wrapped between `{` and `}`: ``` let struct = { x: 1, y: 2 } ``` Typically, the key-value pairs are separated by a single `:`. However, there is a short-hand syntax for when the key and value use the same identifier: ``` { a, b, c } ``` is short for ``` { a: a, b: b, c: c } ``` Typically, the key for a struct element must be a [Terminal Expression]; these are either [Identifiers] or [Literals]. However, using an expression for the key value is allowed, so long as the expression is between `[` and `]`: ``` { ["hello" ++ "world"]: 123 } ``` For information on how to modify struct values see [Accessor Expressions].
Call Expressions (link) .txt ----------------------------------------------------------------------------
A call expression calls a function with a set of arguments. The call syntax in Catspeak is a lot less restrictive than GML, allowing parenthesis on the arguments to be optional. This allows for the creation of statement-like function calls, like the `print` function found in the [Standard Library]: ``` print("hello", "world") -- this is also valid: print "hello", "world" ```
Accessor Expressions (link) .txt ----------------------------------------------------------------------------
An accessor expression will allow you to access the elements of an array or struct. They consist of two expressions separated by a `.` symbol. The right-hand-side expression must be a [Terminal Expression], **or** an expression wrapped between `[` and `]`: ``` array.[0] struct.x struct.["y"] ``` NOTE: The `struct.x` syntax is short-hand for `struct.["x"]`. Depending on which side of an [Assignment Expression] the accessor expression is on, determines whether an element will be "get" or "set".
Block Expressions (link) .txt ----------------------------------------------------------------------------
The block expression is used to execute multiple statements or control flow expressions before returning a final result. Create a block expression by using the `do` keyword, following by a sequence of [Statements] wrapped between `{` and `}`: ``` let a = do { let a = 1 let b = 2 a + b } ``` The result returned by the block expression will be the result of the last expression in the block. If there is no expression, then the result will be `undefined`. Reiterating what was said in the [Let Statements] section, all local variables defined within a block expression will become inaccessible after the block has ended. This is different from GML variables, whose definitions are hoisted.
If Expressions (link) .txt ----------------------------------------------------------------------------
The syntax for `if` expressions is similar to GML `if` statements: ``` if (a > b) { -- a is greater than b } else { -- a is not greater than b } ``` Just like GML, the `else` clause is optional. However, unlike GML, only an `if` expression can be used after an `else` clause. So shortcuts `else while` or `else do` are not allowed.
And Expressions (link) .txt ----------------------------------------------------------------------------
Similar to GML, Catspeak has native `and` operators: ``` a and b ``` In this example, if the expression `a` evaluates to `true`, then the result of the expression is the value of `b`. Otherwise, the value of `a` is used. NOTE: If `a` is false, the value of `b` is **never calculated**.
Or Expressions (link) .txt ----------------------------------------------------------------------------
Similar to GML, Catspeak has native `or` operators: ``` a or b ``` In this example, if the expression `a` evaluates to `false`, then the result of the expression is the value of `b`. Otherwise, the value of `a` is used. NOTE: If `a` is true, the value of `b` is **never calculated**.
Loop Expressions (link) .txt ----------------------------------------------------------------------------
The only type of loop Catspeak currently supports is the [While Expression].
While Expressions (link) .txt --------------------------------------------------------------------------
The `while` expression resembles [If Expressions], except the `while` keyword is used instead of `if`: ``` while (a > b) { a = it - 1 } ``` Unlike [If Expressions], the `while` expression will continue to repeat the code between the `{` and `}` until the condition evaluates to `false`. Use [Break Expressions] or [Continue Expressions] to exit the loop or skip to the next iteration early.
Function Expressions (link) .txt ----------------------------------------------------------------------------
Catspeak lets you define new functions using the `fun` keyword, followed by a block of code to execute: ``` let say_hello = fun() { print "Hello!" } ``` To create a function which accepts arguments, include the names of the arguments after the `fun` keyword: ``` let add = fun(a, b) { return a + b } ``` Just like [Call Expressions], the parenthesis around these arguments are optional: ``` let add = fun a, b { return a + b } ``` NOTE: All functions in Catspeak are anonymous.
Continue Expressions (link) .txt ----------------------------------------------------------------------------
The `continue` expression will immediately jump to the start of the current loop body, entering the next iteration of the loop if one exists.
Break Expressions (link) .txt ----------------------------------------------------------------------------
The `break` expression will immediately jump to the end of the current loop body: ``` let n = 0 while (n < 100) { n = n + 1 if (n > 10) { break } } print n -- outputs: 11 ```
Return Expressions (link) .txt ----------------------------------------------------------------------------
The `return` expression will immediately terminate the current function call and returns its argument as its result. If no argument is given, `undefined` is used as the result instead. ``` let max = fun(a, b) { if (a > b) { return a } return b } ```
================================================================================ Standard Library (link) .txt ================================================================================
Catspeak has a small standard library which contains common constants and functions that are considered necessary for all programs. If you have any suggestions on what could be added to this standard library, please submit them to the [GitHub] page.
Constants (link) .txt ==============================================================================
Catspeak shares all the primitive constants of GML, these are: - `undefined` - `true` - `false` - `NaN` - `infinity` However, instead of `pointer_null` Catspeak uses just `null`. This is in order to maintain compatibility with JSON.
Functions (link) .txt ==============================================================================
Catspeak exposes the following GML functions for checking the types of values and performing conversions: - `bool` - `is_array` - `is_nan` - `is_undefined` - `string` - `is_bool` - `is_numeric` - `is_vec3` - `real` - `is_infinity` - `is_ptr` - `is_vec4` - `int64` - `is_int32` - `is_real` - `typeof` - `is_int64` - `is_string` - `instanceof` - `is_method` - `is_struct` In addition to these functions, there are two Catspeak-specific functions: - `print` takes a variable number of values and prints them to the console window. Internally this behaves like `show_debug_message`. - `len` returns the number of items in a GML array or struct.
Operators (link) .txt ==============================================================================
Catspeak shares many operators with GML, but there are some differences. Listed below are the default operators defined by Catspeak. You can find their precedences in the section on [Operator Identifiers]. - `.` field accessor - `<` less-than - `%` remainder - `<=` inclusive less-than - `*` multiplication - `!` logical negation - `/` division - `~` bitwise negation - `//` integer division - `>>` bitwise right-shift - `-` subtraction, negation - `<<` bitwise left-shift - `+` addition - `&&` logical **AND** - `++` string addition - `&` bitwise **AND** - `==` equals - `^^` logical **XOR** - `!=` not-equals - `^` bitwise **XOR** - `>` greater-than - `||` logical **OR** - `>=` inclusive greater-than - `|` bitwise **OR** NOTE: All operators are left-associative in Catspeak. NOTE: Unlike GML, the operators `&&` and `||` are **not short-circuiting**. This means that both the left and right hand-side of the operator will be evaluated immediately. If you need this behaviour, you should use [And Expressions] and [Or Expressions]. Catspeak does not have `xor`, `mod` and `div` operators. You will need to use `^^`, `%`, and `//` instead.
================================================================================ Library Reference (link) .md ================================================================================
The following sections feature documentation for all public Catspeak functions, macros, and structs.
scr_catspeak_process (link) .gml ==============================================================================
The primary user-facing interface for compiling and executing Catspeak programs.
function catspeak_execute (link) .gml ----------------------------------------------------------------------------
Creates a new Catspeak runtime process for this Catspeak function. This function is also compatible with GML functions. @param scr: Function | Struct.CatspeakFunction The GML or Catspeak function to execute. @param (optional) args: Array<Any> The array of arguments to pass to the function call. Defaults to the empty array. @returns a value of Struct.CatspeakProcess
function catspeak_compile_buffer (link) .gml ----------------------------------------------------------------------------
Creates a new Catspeak compiler process for a buffer containing Catspeak code. @param buff: ID.Buffer A reference to the buffer containing the source code to compile. @param (optional) consume: Bool Whether the buffer should be deleted after the compiler process is complete. Defaults to `false`. @param (optional) offset: Real The offset in the buffer to start parsing from. Defaults to 0, the start of the buffer. @param (optional) size: Real The length of the buffer input. Any characters beyond this limit will be treated as the end of the file. Defaults to `infinity`. @returns a value of Struct.CatspeakProcess
function catspeak_compile_string (link) .gml ----------------------------------------------------------------------------
Creates a new Catspeak compiler process for a string containing Catspeak code. This will allocate a new buffer to store the string, if that isn't ideal then you will have to create and write to your own buffer, then pass it into the [catspeak_compile_buffer] function instead. @param src: Any The value containing the source code to compile. @returns a value of Struct.CatspeakProcess
function catspeak_create_buffer_from_string (link) .gml ----------------------------------------------------------------------------
A helper function for creating a buffer from a string. @param src: String The source code to convert into a buffer. @returns a value of Id.Buffer
struct CatspeakProcess extends Future (link) .gml ----------------------------------------------------------------------------
Constructs a new asynchronous Catspeak process. Instances of this struct will be managed globally by the Catspeak execution engine. Execution time is divided between all active processes so each gets a chance to progress. @param resolver: Function A function which performs the necessary operations to progress the state of this future. It accepts a single function as a parameter. Call this function with the result of the future to complete the computation.
scr_catspeak_config (link) .gml ==============================================================================
The primary user-facing interface for configuring the Catspeak execution engine. Many parts of the Catspeak engine expose configuration features. These are: - "frameAllocation" should be a number in the range [0, 1]. Determines what percentage of a game frame should be reserved for processing Catspeak programs. Catspeak will only spend this time when necessary, and will not sit idly wasting time. A value of 1 will cause Catspeak to spend the whole frame processing, and a value of 0 will cause Catspeak to only process a single instruction per frame. The default setting is 0.5 (50% of a frame). This leaves enough time for the other components of your game to complete, whilst also letting Catspeak be speedy. - "processTimeLimit" should be a number greater than 0. Determines how long (in seconds) a process can run for before it is assumed unresponsive and terminated. The default value is 1 second. Setting this to `infinity` is technically possible, but will not be officially supported. - "keywords" is a struct whose keys map to [CatspeakToken] values. This struct can be modified to customise the keywords expected by the Catspeak compiler. For example, if you would like to use "func" for functions (instead of the default "fun"), you can add a new definition: ``` var keywords = catspeak_config().keywords; keywords[$ "func"] = CatspeakToken.FUN; variable_struct_remove(keywords, "fun"); // delete the old keyword ``` Please take care when modifying this struct because any changes will be **permanent** until you close and re-open the game.
function catspeak_config (link) .gml ----------------------------------------------------------------------------
Configures various global settings of the Catspeak compiler and runtime. See the list in [scr_catspeak_config] for configuration values and their usages. @returns a value of Struct
function catspeak_add_function (link) .gml ----------------------------------------------------------------------------
Permanently adds a new Catspeak function to the default standard library. @param name: String The name of the function to add. @param f: Function The function to add, will be converted into a method if a script ID is used. @param ...: Any The remaining key-value pairs to add, in the same pattern as the two previous arguments.
function catspeak_add_constant (link) .gml ----------------------------------------------------------------------------
Permanently adds a new Catspeak constant to the default standard library. If you want to add a function, use the [catspeak_add_function] function instead because it makes sure your value will be callable from within Catspeak. @param name: String The name of the constant to add. @param value: Any The value to add. @param ...: Any The remaining key-value pairs to add, in the same pattern as the two previous arguments.
scr_catspeak_init (link) .gml ==============================================================================
Initialises core components of the Catspeak compiler. This includes any uninitialised global variables.
macro CATSPEAK_VERSION (link) .gml ----------------------------------------------------------------------------
The compiler version, should be updated before each release.
function catspeak_force_init (link) .gml ----------------------------------------------------------------------------
Makes sure that all Catspeak global variables are initialised. Only needs to be called if you are trying to use Catspeak from a script, or through `gml_pragma`. Otherwise you can just ignore this.
scr_catspeak_error (link) .gml ==============================================================================
Responsible for the creation and manipulation of Catspeak errors raised by the compiler and runtime environment. Actual error information is located in instances of the [CatspeakError] struct. This struct may also contain debug information, located in instances of [CatspeakLocation].
struct CatspeakLocation (link) .gml ----------------------------------------------------------------------------
Represents a line and column number in a Catspeak source file. @param line: Real The line number this position is found on. @param (optional) column: Real The column number this position is found on. This is the number of characters since the previous new-line character; therefore, tabs are considered a single column, not 2, 4, 8, etc. columns.
method clone (link) .gml --------------------------------------------------------------------------
Returns an exact copy of this debug information. @returns a value of Struct.CatspeakLocation @example ``` var a = new CatspeakLocation(10, 20); var b = a.clone(); ```
method reflect (link) .gml --------------------------------------------------------------------------
Copies values from this location to a new [CatspeakLocation] without creating a new instance. @deprecated This function is deprecated and its usage is discouraged! Use [assign] instead. @param source: Struct.CatspeakLocation The target location to sample from.
method assign (link) .gml --------------------------------------------------------------------------
Assigns the values of another instance of [CatspeakLocation] to this instance. @param source: Struct.CatspeakLocation The target location to sample from. @example ``` var a = new CatspeakLocation(10, 20); var b = new CatspeakLocation(-1); b.assign(a); // copies the line and column values from `a` to `b` ```
method toString (link) .gml --------------------------------------------------------------------------
Renders this Catspeak location. If a line number and column number both exist, then the format will be `(line N, column M)`. Otherwise, if only a line number exists, the format will be `(line N)`. If this source location also includes a debug text, it is also included in the debug output between square brackets. @returns a value of String @example ``` show_message(new CatspeakLocation(20)); // (line 20) show_message(new CatspeakLocation(20, 16)); // (line 20, column 16) ```
struct CatspeakError (link) .gml ----------------------------------------------------------------------------
Represents an error raised by the Catspeak runtime. Follows a similar structure to the built-in error struct. @param location: Struct.CatspeakLocation The location where this error occurred. @param (optional) message: String The error message to display. Defaults to "No message".
method toString (link) .gml --------------------------------------------------------------------------
Renders this Catspeak error with its location followed by the error message. @param (optional) verbose: Bool Whether to include the stack trace as part of the error output. @returns a value of String
function catspeak_assert (link) .gml ----------------------------------------------------------------------------
Raises a Catspeak error at this location, with this message, if an assertion condition is not true. @param condition: Bool The condition to check. Use `false` to raise an exception. @param pos: Struct.CatspeakLocation The location where this error occurred. @param (optional) message: String The error message to display.
scr_catspeak_vm (link) .gml ==============================================================================
Handles the code execution stage of the Catspeak runtime.
struct CatspeakVM (link) .gml ----------------------------------------------------------------------------
Creates a new Catspeak virtual machine, responsible for the execution of Catspeak IR.
method pushCallFrame (link) .gml --------------------------------------------------------------------------
Creates a new executable callframe for this IR. @param self_: Struct The "self" scope to use when calling this function. @param ir: Struct.CatspeakFunction The Catspeak IR to execute. The VM is pretty stupid, so if the code is not well-formed, there are likely to be runtime errors and misbehaviour. @param (optional) args: Array<Any> The arguments to pass to this VM call. @param (optional) argo: Real The offset in the arguments array to start at. @param (optional) argc: Real The number of arguments in the arguments array.
method reuseCallFrame (link) .gml --------------------------------------------------------------------------
An unsafe function which can be used as a shortcut if you are going to reuse the previous callframe with the same settings. There are no checks that a valid callframe even exists, so keep that in mind.
method reuseCallFrameWithArgs (link) .gml --------------------------------------------------------------------------
An unsafe function similar to [reuseCallFrame], except a new set of arguments can be passed into the frame. @param args: Array<Any> The arguments to pass to this VM call. @param (optional) argo: Real The offset in the arguments array to start at. @param (optional) argc: Real The number of arguments in the arguments array.
method popCallFrame (link) .gml --------------------------------------------------------------------------
Removes the top callframe from the stack.
method inProgress (link) .gml --------------------------------------------------------------------------
Returns whether the VM is in progress.
method runProgram (link) .gml --------------------------------------------------------------------------
Performs a `n`-many steps of the execution process. Just like the compiler, these steps try to be discrete so that the VM can be paused if necessary. However, this does not account for external code that may perform large amounts of processing, such as a GML function containing a computationally expensive loop. @param n: Real The number of steps of process.
scr_catspeak_ir (link) .gml ==============================================================================
Handles the flat, executable representation of Catspeak programs.
struct CatspeakFunction (link) .gml ----------------------------------------------------------------------------
Represents the executable Catspeak VM code. Also exposes methods for constructing custom IR manually. @param (optional) name: String The name to give this function, defaults to "main". @param (optional) parent: Struct.CatspeakFunction The function this new function was defined in. Inherits its global variables.
method setGlobal (link) .gml --------------------------------------------------------------------------
Sets the value of a global variable with this name. @param name: String The name of the global variable to set. @param value: Any The value to assign to this global variable.
method setGlobalFunction (link) .gml --------------------------------------------------------------------------
Behaves similarly to [setGlobal], except if the value is not a method it is converted into a method type. @param name: String The name of the global variable to set. @param value: Any The value to assign to this global variable.
method getGlobal (link) .gml --------------------------------------------------------------------------
Gets the value of a global variable with this name. @param name: String The name of the global variable to get. @returns a value of Any
method existsGlobal (link) .gml --------------------------------------------------------------------------
Returns whether a global variable exists with this name. @param name: String The name of the global variable to get. @returns a value of Bool
method getGlobalNames (link) .gml --------------------------------------------------------------------------
Returns the names of all created global variables @returns a value of Array<String>
method emitBlock (link) .gml --------------------------------------------------------------------------
Adds a Catspeak block to the end of this function. @param block: Struct.CatspeakBlock The Catspeak block to insert. @returns a value of Struct.CatspeakBlock
method emitFunction (link) .gml --------------------------------------------------------------------------
Creates a new sub-function and returns its reference. @param (optional) name: String The name of the sub-function. @returns a value of Struct.CatspeakFunction
method emitRegister (link) .gml --------------------------------------------------------------------------
Allocates space for a new Catspeak register. This just returns the id of the register, since there is no "physical" representation. @param (optional) pos: Struct.CatspeakLocation The debug info for this register. @returns a value of Real
method emitPermanentRegister (link) .gml --------------------------------------------------------------------------
Returns the next persistent register ID. Persistent registers are not allocated immediately, they hold a temporary ID until the rest of the code is generated. Once this is complete, these special registers are allocated at the end of the register list. This is done in order to avoid messing up CALLSPAN instruction optimisations, where arguments are expected to be adjacent. @param (optional) pos: Struct.CatspeakLocation The debug info for this register. @returns a value of Real
method discardRegister (link) .gml --------------------------------------------------------------------------
Discards a register so it can be recycled somewhere else. @param reg: Any The register or accessor to check.
method emitUnreachable (link) .gml --------------------------------------------------------------------------
Emits the special unreachable "register." The existence of this flag will make dead code elimination easier in an optimisation phase. @returns a value of Real
method isUnreachable (link) .gml --------------------------------------------------------------------------
Returns whether a register is unreachable. Used to perform dead code elimination. @param reg: Any The register or accessor to check. @returns a value of Bool
method emitConstant (link) .gml --------------------------------------------------------------------------
Generates the code to assign a set of constants to a set of temporary registers. @param value: Any The constant value to load. @returns a value of Any
method emitPermanentConstant (link) .gml --------------------------------------------------------------------------
Generates the code to assign a constant to a permanent register. @param value: Any The constant value to load. @returns a value of Any
method emitArgs (link) .gml --------------------------------------------------------------------------
Generates the code assign the arguments array into a sequence of registers. @param reg: Any The register or accessor containing the register to write to. NOTE: this will also write values to following `n`-many registers, depending on how many arguments you decide to load statically. Therefore, you should make sure to pre-allocate the registers for arguments before you make this call. @param n: Any The number of arguments to load. @returns a value of Any
method emitGlobalGet (link) .gml --------------------------------------------------------------------------
Generates the code to read a global variable. @param name: String The name of the global to read. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method emitGlobalSet (link) .gml --------------------------------------------------------------------------
Generates the code to write to a global variable. @param name: String The name of the global to write to. @param reg: Any The register or accessor containing the value to write. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method emitReturn (link) .gml --------------------------------------------------------------------------
Generates the code to return a value from this function. Since statements are expressions, this returns the never register. @param (optional) reg: Any The register or accessor containing the value to return. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Real
method emitMove (link) .gml --------------------------------------------------------------------------
Generates the code to move the value of one register to another. @param source: Any The register or accessor containing the value to move. @param dest: Any The register or accessor containing the destination to move to. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction.
method emitClone (link) .gml --------------------------------------------------------------------------
Generates the code to clone a value into a manually managed register. @param reg: Any The register or accessor containing the value to copy. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction.
method emitCloneTemp (link) .gml --------------------------------------------------------------------------
Generates the code to clone a value into a temporary register. This is useful for optimising function calls, since it helps align all arguments so they're adjacent. @param reg: Any The register or accessor containing the value to copy. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction.
method emitJump (link) .gml --------------------------------------------------------------------------
Generates the code to jump to a new block of code. @param block: Struct.CatspeakBlock The block to jump to.
method emitJumpFalse (link) .gml --------------------------------------------------------------------------
Generates the code to jump to a new block of code if a condition is false. @param block: Struct.CatspeakBlock The block to jump to. @param condition: Any The register or accessor containing the condition code to check.
method emitJumpTrue (link) .gml --------------------------------------------------------------------------
Generates the code to jump to a new block of code if a condition is true. @param block: Struct.CatspeakBlock The block to jump to. @param condition: Any The register or accessor containing the condition code to check.
method emitCallSelf (link) .gml --------------------------------------------------------------------------
Generates the code to call a Catspeak function. Returns a register containing the result of the call. This version takes an additional argument for setting the "self". @param self_: Any The register or accessor containing self value. @param callee: Any The register or accessor containing function to be called. @param args: Array<Any> The array of registers or accessors containing the arguments to pass. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method emitCall (link) .gml --------------------------------------------------------------------------
Generates the code to call a Catspeak function. Returns a register containing the result of the call. @param callee: Any The register or accessor containing function to be called. @param args: Array<Any> The array of registers or accessors containing the arguments to pass. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method emitSelf (link) .gml --------------------------------------------------------------------------
Generates the code to get the current "self" context. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method emitCode (link) .gml --------------------------------------------------------------------------
Emits a new Catspeak intcode instruction for the current block. Returns the array containing the instruction information. @param inst: Enum.CatspeakIntcode The Catspeak intcode instruction to perform. @param returnReg: Real The register to return the value to. If the return value is ignored, then use `undefined`. @param ...: Any The parameters to emit for this instruction, can be any kind of value, but most likely will be register IDs. @returns a value of Array<Any>
method emitCodeHoisted (link) .gml --------------------------------------------------------------------------
Emits a new Catspeak intcode instruction, hoisted into the initialisation block. @param inst: Enum.CatspeakIntcode The Catspeak intcode instruction to perform. @param returnReg: Real The register to return the value to. If the return value is ignored, then use `undefined`. @param ...: Any The parameters to emit for this instruction, can be any kind of value, but most likely will be register IDs. @returns a value of Array<Any>
method emitGet (link) .gml --------------------------------------------------------------------------
Attempts to get the value of an accessor if it exists. If the accessor does not implement the `getValue` function, a Catspeak error is raised. @param accessor: Any The register or accessor to get the value of. @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method emitSet (link) .gml --------------------------------------------------------------------------
Attempts to get the value of an accessor if it exists. If the accessor does not implement the `getValue` function, a Catspeak error is raised. @param accessor: Any The register or accessor to set the value of. @param value: Any The register or accessor to assign to the accessor @param (optional) pos: Struct.CatspeakLocation The debug info for this instruction. @returns a value of Any
method lastCode (link) .gml --------------------------------------------------------------------------
Returns a reference to the last instruction emitted to this function. If no instruction exists in the current block, `undefined` is returned instead. @returns a value of Array<Any>
method lastCodeHoisted (link) .gml --------------------------------------------------------------------------
Returns a reference to the last instruction emitted to the initialisation block, ignoring the final branch instruction. If no instruction exists, then `undefined` is returned instead. @returns a value of Array<Any>
method patchInst (link) .gml --------------------------------------------------------------------------
Modifies the opcode component of this instruction. @deprecated This function is deprecated and its usage is discouraged! @param inst: Array<Any> The instruction to modify. @param code: Enum.CatspeakIntcode The opcode to replace the current opcode with.
method patchInstReturn (link) .gml --------------------------------------------------------------------------
Modifies the return register of this instruction. @deprecated This function is deprecated and its usage is discouraged! @param inst: Array<Any> The instruction to modify. @param reg: Real The register to return the result of the instruction to.
method patchArg (link) .gml --------------------------------------------------------------------------
Modifies the return register of this instruction. Fair warning: this is a dumb operation, so no checks are performed to validate that the value you're replacing is correct. This may result in undefined behaviour at runtime! Only use this function if you absolutely know what you're doing. @param inst: Array<Any> The instruction to modify. @param argIdx: Real The ID of the argument to modify. @param reg: Real The register containing to value to replace.
method patchPermanentRegisters (link) .gml --------------------------------------------------------------------------
Backpatches the current set of persistent registers, and promotes them to true registers.
method toString (link) .gml --------------------------------------------------------------------------
Debug display for Catspeak functions, attempts to resemble the GML function `toString` behaviour.
method disassembly (link) .gml --------------------------------------------------------------------------
Returns the disassembly for this IR function.
struct CatspeakBlock (link) .gml ----------------------------------------------------------------------------
Represents a block of executable code. @param (optional) name: Any The name to give this block, leave blank for no name. @param (optional) pos: Struct.CatspeakLocation The debug info for this block.
struct CatspeakAccessor (link) .gml ----------------------------------------------------------------------------
Represents a special assignment target which generates different code depending on whether it used as a getter or setter. The simplest example is with array and struct accessors, but it is not limited to just this. The `getValue` function expects no arguments and should return a register ID. The `setValue` function expects a single argument, a register containing the value to set, and should return a register containing the result of the assignment. If there is no result, return `undefined`.
struct CatspeakReadOnlyAccessor extends CatspeakAccessor (link) .gml ----------------------------------------------------------------------------
Used for constants, compile error on attempted assignment to constant value. @param reg: Real The register to mark as read-only.
struct CatspeakTempRegisterAccessor extends CatspeakAccessor (link) .gml ----------------------------------------------------------------------------
Used for call return values, most cases expect the value to be read once and then be discarded. This adds a sanity check so that a compiler error is raised if this fails. @param reg: Real The register to read from once. @param ir: Struct.CatspeakFunction The IR function associated with this register. @param (optional) count: Real The number of times this register can be read before it's discarded. Defaults to 1 time.
scr_catspeak_intcode (link) .gml ==============================================================================
Boilerplate for the [CatspeakIntcode] enum.
enum CatspeakIntcode (link) .gml ----------------------------------------------------------------------------
Represents a kind of Catspeak VM instruction.
function catspeak_intcode_show (link) .gml ----------------------------------------------------------------------------
Gets the name for a value of [CatspeakIntcode]. Will return `<unknown>` if the value is unexpected. @param value: Enum.CatspeakIntcode The value of [CatspeakIntcode] to convert. @returns a value of String
function catspeak_intcode_read (link) .gml ----------------------------------------------------------------------------
Parses a string into a value of [CatspeakIntcode]. Will return `undefined` if the value cannot be parsed. @param str: Any The string to parse. @returns a value of Enum.CatspeakIntcode
function catspeak_intcode_valueof (link) .gml ----------------------------------------------------------------------------
Returns the integer representation for a value of [CatspeakIntcode]. Will return `undefined` if the value is unexpected. @param value: Enum.CatspeakIntcode The value of [CatspeakIntcode] to convert. @returns a value of Real
function catspeak_intcode_sizeof (link) .gml ----------------------------------------------------------------------------
Returns the number of elements of [CatspeakIntcode]. @returns a value of Real
scr_catspeak_compiler (link) .gml ==============================================================================
Handles the parsing and codegen stage of the Catspeak compiler.
struct CatspeakCompiler (link) .gml ----------------------------------------------------------------------------
Creates a new Catspeak compiler, responsible for converting a stream of [CatspeakToken] into executable code. @param lexer: Struct.CatspeakLexer The iterator that yields tokens to be consumed by the compiler. Must be a struct with at least a [next] method on it. @param (optional) ir: Struct.CatspeakFunction The Catspeak IR target to write code to, if left empty a new target is created. This can be accessed using the `ir` field on a compiler instance.
method advance (link) .gml --------------------------------------------------------------------------
Advances the parser and returns the current token. @returns a value of Enum.CatspeakToken
method matches (link) .gml --------------------------------------------------------------------------
Returns true if the current token matches this token kind. @param kind: Enum.CatspeakToken The token kind to expect. @returns a value of Bool
method satisfies (link) .gml --------------------------------------------------------------------------
Returns true if the current token satisfies a predicate. @param predicate: Function The predicate to call on the peeked token, must return a Boolean value. @returns a value of Bool
method consume (link) .gml --------------------------------------------------------------------------
Attempts to match against a token and advances the parser if there was a match. Returns whether the match was successful. @param kind: Enum.CatspeakToken The token kind to expect. @returns a value of Bool
method consumeLinebreaks (link) .gml --------------------------------------------------------------------------
A helper function which consumes any line breaks which may appear in an unexpected location.
method error (link) .gml --------------------------------------------------------------------------
@desc Throws a [CatspeakError] for the current token. @param (optional) message: String The error message to use.
method errorAndAdvance (link) .gml --------------------------------------------------------------------------
Advances the parser and throws an for the current token. @param (optional) message: String The error message to use.
method expects (link) .gml --------------------------------------------------------------------------
Throws a [CatspeakError] if the current token is not the expected token. Advances the parser otherwise. @param kind: Enum.CatspeakToken The token kind to expect. @param (optional) message: String The error message to use.
method expectsSemicolon (link) .gml --------------------------------------------------------------------------
Throws a [CatspeakError] if the current token is not a semicolon or new line. Advances the parser otherwise. @param (optional) message: String The error message to use.
method declareLocal (link) .gml --------------------------------------------------------------------------
Allocates a new register for a local variable and returns its reference. @param name: String The name of the variable to declare. @param (optional) initReg: Real The accessor containing the initialiser expression, or `undefined` if there is no initialiser. @returns a value of Real
method getVar (link) .gml --------------------------------------------------------------------------
Looks up a variable by name and returns its register. If the variable does not exist, then a global constant is loaded from the runtime interface. @param name: String The name of the variable to search for. @returns a value of Real
method pushState (link) .gml --------------------------------------------------------------------------
Stages a new compiler production. @param state: Function The production to insert. Since this is a FIFO data structure, take care to queue up states in reverse order of the expected execution. @returns a value of Struct
method pushResult (link) .gml --------------------------------------------------------------------------
Pushes a register which can be used to pass arguments into compiler states. @param result: Any The result to push onto the stack. Typically this is a register ID.
method topResult (link) .gml --------------------------------------------------------------------------
Returns the top result in the result stack without removing it. @returns a value of Any
method popResult (link) .gml --------------------------------------------------------------------------
Pops the top value of the result stack and returns it. @returns a value of Any
method pushBlock (link) .gml --------------------------------------------------------------------------
Starts a new lexical scope. @param (optional) inherit: Bool Whether to inherit the previous scope, defaults to true.
method popBlock (link) .gml --------------------------------------------------------------------------
Pops the current block scope and returns its value. Any variables defined in this scope are freed up to be used by new declarations. @returns a value of Any
method pushIt (link) .gml --------------------------------------------------------------------------
Pushes the new accessor for the `it` keyword onto the stack. @param reg: Any The register or accessor representing the left-hand-side of an assignment expression.
method topIt (link) .gml --------------------------------------------------------------------------
Returns the accessor for the `it` keyword. @returns a value of Any
method popIt (link) .gml --------------------------------------------------------------------------
Pops the top accessor the `it` keyword represents.
method pushLoop (link) .gml --------------------------------------------------------------------------
Pushes the loop onto the stack. @param breakBlock: Struct.CatspeakBlock The block to jump to if `break` is used. @param continueBlock: Struct.CatspeakBlock The block to jump to if `continue` is used. @param : Struct
method topLoop (link) .gml --------------------------------------------------------------------------
Returns the data for the current loop. @returns a value of Struct
method popLoop (link) .gml --------------------------------------------------------------------------
Pops the top loop.
method inProgress (link) .gml --------------------------------------------------------------------------
Returns whether the compiler is in progress.
method emitProgram (link) .gml --------------------------------------------------------------------------
Performs `n`-many steps of the parsing and code generation process. The steps are discrete so that compilation can be paused if necessary, e.g. to avoid freezing the game for large files. @param n: Real The number of steps of process.
struct CatspeakLocalScope (link) .gml ----------------------------------------------------------------------------
Represents a lexically scoped block of code in the compiler. @param parent: Struct.CatspeakLocalScope The parent scope to inherit. @param inherit: Bool The whether to actually inherit the parent scope.
struct CatspeakGlobalAccessor (link) .gml ----------------------------------------------------------------------------
An accessor for global variable accessor expressions. @param compiler: Struct.CatspeakCompiler The Catspeak compiler which generated this accessor. @param name: String The name of the global variable.
struct CatspeakCollectionAccessor (link) .gml ----------------------------------------------------------------------------
An accessor for array and object access expressions. @param compiler: Struct.CatspeakCompiler The Catspeak compiler which generated this accessor. @param collection: Any The register or accessor containing the collection to access. @param index: Any The register or accessor containing the index to access.
scr_catspeak_lexer (link) .gml ==============================================================================
Handles the lexical analysis stage of the Catspeak compiler.
struct CatspeakLexer (link) .gml ----------------------------------------------------------------------------
Tokenises the contents of a GML buffer. The lexer does not take ownership of this buffer, but it may mutate it so beware. Therefore you should make sure to delete the buffer once parsing is complete. @param buff: Id.Buffer The ID of the GML buffer to use. @param (optional) offset: Real The offset in the buffer to start parsing from. Defaults to 0, the start of the buffer. @param (optional) size: Real The length of the buffer input. Any characters beyond this limit will be treated as the end of the file. Defaults to `infinity`.
method registerByte (link) .gml --------------------------------------------------------------------------
Updates the line and column numbers of the lexer, also updates the. current length of the lexeme, in bytes. @param byte: Real The byte to consider.
method registerLexeme (link) .gml --------------------------------------------------------------------------
Registers the current lexeme as a string.
method clearLexeme (link) .gml --------------------------------------------------------------------------
Resets the current lexeme.
method advance (link) .gml --------------------------------------------------------------------------
@desc Advances the scanner and returns the current byte. @returns a value of Real
method peek (link) .gml --------------------------------------------------------------------------
@desc Peeks `n` bytes ahead of the current buffer offset. @param n: Real The number of bytes to look ahead. @returns a value of Real
method advanceWhile (link) .gml --------------------------------------------------------------------------
@desc Advances the lexer whilst a bytes contain some expected ASCII descriptor, or until the end of the file is reached. @param predicate: Function The predicate to satisfy. @param (optional) condition: Bool The condition to expect. Defaults to `true`, set the `false` to invert the condition. @returns a value of Real
method nextWithWhitespace (link) .gml --------------------------------------------------------------------------
Advances the lexer and returns the next [CatspeakToken]. This includes additional whitespace and control tokens, like: line breaks `;`, line continuations `...`, and comments `--`. @returns a value of Enum.CatspeakToken
method next (link) .gml --------------------------------------------------------------------------
Advances the lexer and returns the next [CatspeakToken], ingoring any comments, whitespace, and line continuations. @returns a value of Enum.CatspeakToken
function catspeak_token_is_operator (link) .gml ----------------------------------------------------------------------------
Returns whether a Catspeak token is a valid operator. @param token: Enum.CatspeakToken The ID of the token to check. @returns a value of Bool
function catspeak_token_is_expression (link) .gml ----------------------------------------------------------------------------
Returns whether a Catspeak token can start a new expression. @param token: Enum.CatspeakToken The ID of the token to check. @returns a value of Bool
function catspeak_token_skips_newline (link) .gml ----------------------------------------------------------------------------
Returns whether a Catspeak token ignores any succeeding newline characters. @param token: Enum.CatspeakToken The ID of the token to check. @returns a value of Bool
function catspeak_string_to_token_keyword (link) .gml ----------------------------------------------------------------------------
Converts a string into a keyword token if once exists. If the keyword doesn't exist, `undefined` is returned instead. @param str: String The lexeme to look-up the keyword for. @returns a value of Enum.CatspeakToken
function catspeak_byte_to_token (link) .gml ----------------------------------------------------------------------------
Converts an ASCII character into a Catspeak token. This is only an informed prediction judging by the first character of a token. @param char: Real The character to check. @returns a value of Enum.CatspeakToken
scr_catspeak_token (link) .gml ==============================================================================
Boilerplate for the [CatspeakToken] enum.
enum CatspeakToken (link) .gml ----------------------------------------------------------------------------
Represents a kind of Catspeak token.
function catspeak_token_show (link) .gml ----------------------------------------------------------------------------
Gets the name for a value of [CatspeakToken]. Will return `<unknown>` if the value is unexpected. @param value: Enum.CatspeakToken The value of [CatspeakToken] to convert. @returns a value of String
function catspeak_token_read (link) .gml ----------------------------------------------------------------------------
Parses a string into a value of [CatspeakToken]. Will return `undefined` if the value cannot be parsed. @param str: Any The string to parse. @returns a value of Enum.CatspeakToken
function catspeak_token_valueof (link) .gml ----------------------------------------------------------------------------
Returns the integer representation for a value of [CatspeakToken]. Will return `undefined` if the value is unexpected. @param value: Enum.CatspeakToken The value of [CatspeakToken] to convert. @returns a value of Real
function catspeak_token_sizeof (link) .gml ----------------------------------------------------------------------------
Returns the number of elements of [CatspeakToken]. @returns a value of Real
scr_catspeak_alloc (link) .gml ==============================================================================
The Catspeak engine creates a lot of garbage sometimes, this module is responsible for the allocation and collection of that garbage.
function catspeak_collect (link) .gml ----------------------------------------------------------------------------
Forces the Catspeak engine to collect any discarded resources.
================================================================================ Futures Reference (link) .md ================================================================================
The [Future library] is used by Catspeak in order to better organise asynchronous processes. The following sections document its usage.
scr_future (link) .gml ==============================================================================
A [Future] is method of organising asynchronous code in a more manageable way compared to nested callbacks. This library contains methods of creating and combining new futures.
enum FutureState (link) .gml ----------------------------------------------------------------------------
The different progress states of a [Future].
struct Future (link) .gml ----------------------------------------------------------------------------
Constructs a new future, allowing for deferred execution of code depending on whether it was accepted or rejected.
method accept (link) .gml --------------------------------------------------------------------------
Accepts this future with the supplied argument. @param (optional) value: Any The value to reject.
method reject (link) .gml --------------------------------------------------------------------------
Rejects this future with the supplied argument. @param (optional) value: Any The value to reject.
method resolved (link) .gml --------------------------------------------------------------------------
Returns whether this future has been resolved. A resolved future may be the result of being accepted OR rejected. @returns a value of Bool
method andThen (link) .gml --------------------------------------------------------------------------
Sets the callback function to invoke once the process is complete. @param callback: Function The function to invoke. @returns a value of Struct.Future
method andCatch (link) .gml --------------------------------------------------------------------------
Sets the callback function to invoke if an error occurrs whilst the process is running. @param callback: Function The function to invoke. @returns a value of Struct.Future
method andFinally (link) .gml --------------------------------------------------------------------------
Sets the callback function to invoke if this promise is resolved. @param callback: Function The function to invoke. @returns a value of Struct.Future
function future_all (link) .gml ----------------------------------------------------------------------------
Creates a new [Future] which is accepted only when all other futures in an array are accepted. If any future in the array is rejected, then the resulting future is rejected with its value. If all futures are accepted, then the resulting future is accepted with an array of their values. @param futures: Array<Struct.Future> The array of futures to await. @returns a value of Struct.Future
function future_any (link) .gml ----------------------------------------------------------------------------
Creates a new [Future] which is accepted if any of the futures in an array are accepted. If all futures in the array are rejected, then the resulting future is rejected with an array of their values. @param futures: Array<Struct.Future> The array of futures to await. @returns a value of Struct.Future
function future_settled (link) .gml ----------------------------------------------------------------------------
Creates a new [Future] which is accepted when all of the futures in an array are either accepted or rejected. @param futures: Array<Struct.Future> The array of futures to await. @returns a value of Struct.Future
function future_ok (link) .gml ----------------------------------------------------------------------------
Creates a new [Future] which is immediately accepted with a value. If the value itself it an instance of [Future], then it is returned instead. @param value: Any The value to create a future from. @returns a value of Struct.Future
function future_error (link) .gml ----------------------------------------------------------------------------
Creates a new [Future] which is immediately rejected with a value. If the value itself it an instance of [Future], then it is returned instead. @param value: Any The value to create a future from. @returns a value of Struct.Future
function is_future (link) .gml ----------------------------------------------------------------------------
Returns whether this value represents a future instance. @param value: Any The value to check. @returns a value of Bool
scr_future_file (link) .gml ==============================================================================
Wrapper functions for file handling tasks.
macro FUTURE_FILE_TITLE (link) .gml ----------------------------------------------------------------------------
The default title used for game saves.
function future_file_read (link) .gml ----------------------------------------------------------------------------
Loads a buffer asynchronously and returns a new [Future]. This future is accepted if the file was loaded successfully; or rejected if there was a problem, such as the file not existing. @param group: String The name of the group to match. @param path: String The path of the file to read. @param (optional) title: String The title used to identify this file. Defaults to "Save File". @returns a value of Struct.Future
function future_file_read_string (link) .gml ----------------------------------------------------------------------------
Similar to [future_file_read], except the result is converted into a string value. @param group: String The name of the group to match. @param path: String The path of the file to read. @param (optional) title: String The title used to identify this file. Defaults to "Save File". @returns a value of Struct.Future
function future_file_write (link) .gml ----------------------------------------------------------------------------
Saves a buffer asynchronously and returns a new [Future]. This future is accepted if the file was saved successfully; or rejected if there was a problem saving the file. @param group: String The name of the group to match. @param path: String The path of the file to write to. @param buffer: Id.Buffer The ID of the buffer to write. @param (optional) title: String The title used to identify this file. Defaults to "Save File". @returns a value of Struct.Future
function future_file_write_string (link) .gml ----------------------------------------------------------------------------
Similar to [future_file_write], except the input is converted into a string buffer before being written to the destination. @param group: String The name of the group to match. @param path: String The path of the file to read. @param value: Any The value to write to the file. Implicitly converted into a string. @param (optional) title: String The title used to identify this file. Defaults to "Save File". @returns a value of Struct.Future
================================================================================ Theory (link) .txt ================================================================================
The challenge Catspeak faces as a modding language for GML is the lack of threads or syntactic sugar to write proper asynchronous code. Because GML is (mostly) is a single-threaded language, using a recursive method for parsing and interpreting the code would cause the application to freeze on very large inputs. This immediately rules out using recursive descent parsing, pratt parsing, and tree-walk interpreters. The problem of interpreting code had an existing solution: use a flat representation for the executable code. You may have heard of "bytecode" or "intcode" before, which are both flat representations of code. In fact, assembly code (which bytecode resembles) is also a flat representation. Not only would this be faster to execute (in theory), imperative code is very easy to "pause" compared to recursive approaches. This idea of a flat execution model was successfully applied to the Catspeak compiler by using pushdown automata instead of a typical recursive parsing method. This enables Catspeak programs to be passively compiled, executed, and paused at any time so the main thread is never blocked by heavy loads.
================================================================================ License (link) ================================================================================
MIT License Copyright (c) 2021 Katsaii Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------- |\ /| >(OwO)< Little Catspeak \(