From 72ff4422208b096e7374768ae49f050b8457f361 Mon Sep 17 00:00:00 2001 From: Kai Gunger Date: Sun, 23 Nov 2025 01:40:52 -0500 Subject: Update spec (unfinished) --- spec/1.md | 668 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 397 insertions(+), 271 deletions(-) (limited to 'spec/1.md') diff --git a/spec/1.md b/spec/1.md index bc1ad65..62e46f5 100644 --- a/spec/1.md +++ b/spec/1.md @@ -6,332 +6,467 @@ Normal TNSL project structure has a root source folder with TNSL files contained within the folder and sub-folders. It is normal for the root folder to represent a single library or binary, although there is no strict rule enforcing this. Standard organization is to place sub-modules in sub-folders. The file name for the module's entry point should match the folder name. -The file representing the compile target is known as the root file, which generally resides in the root source folder. This file will contain a main method, and/or the pre-processor statement `rootfile` to denote the root of a library. If both are present, the compiler will generate an executable by default. +The file representing the compile target is known as the root file, which generally resides in the root source folder. If the program is built as an executible, it requires a function with the name `main` as the entrypoint to the program. ### TNSL Files TNSL files end with the `.tnsl` extension and may contain the following: -- Comments -- Pre-processor statements - Modules - Constant and variable definitions -- Named function blocks +- Enum declarations - Struct definitions +- Named function blocks - Method and interface blocks +- Import statements +- Asm statements -The following may only occur within named function or method blocks: +There are other language constructs which may only be used within functions: - Re-assignment of variables - Control flow blocks -- Function calls +- Value statements - Anonymous blocks (Scope blocks) +- Stream semantics -## Section 2 - Blocks - -### TNSL Block Notation +Comments may appear anywhere in the file -Blocks in tnsl consist of a slash `/` and a character denoting the type of block. The reverse of these symbols end the block. The three types of blocks are comment, pre-processor, and code. Code blocks can be further broken down into modules, functions, control flow, methods, and interfaces. +### Comments - Examples of standard block opening and closing characters: +Comments begin with `#` and end with a new line. Comment blocks start with `/#` and end with `#/`. - /# - open comment - #/ - close comment - - /: - open pre-processor - :/ - close pre-processor - - /; - open code - ;/ - close code - -In addition to the standard opening and closing characters, there exist "swivel" character sets to quickly close and open a block type +## Section 2 - Blocks - ;; - close code, then open code - #; - close comment, open code - ;# - close code, open comment - :: - close pre-processor, open preprocessor - #: - close comment, open pre-processor - :# - close pre-processor, open comment +Blocks in TNSL open with `/;` and close with `;/`. Keywords directly after the opening (and on the same line) affect the type of block created. +A quicker syntax for closing and re-opening a new block is to use `;;` which is equivalent to `;//;`; this can be helpful with series of `else if` blocks and `case` blocks. ### Modules Modules are akin to namespaces in C++ -They hold a group of related modules, functions, structs, and variables. These named definitions may be used by other projects if the `export` keyword is used in conjunction with the `module` keywor; otherwise, the names are not exported into the file's symbol table. +They hold a group of related sub-modules, functions, structs, and variables. +These named definitions may be used by other projects if the `export` keyword is used before the `module` keyword. +Otherwise, the names are not exported into the program/library's symbol table. ### Module definition example: *File a.tnsl (project a)* - - /; export module pubmod - /; module hidden - # Can access all from pubmod, and pubmod.hidden - ;/ - # Can access all from pubmod, and pubmod.hidden - ;/ +``` +/; export module pubmod + /; module hidden + # Can access all from pubmod, and pubmod.hidden + ;/ # Can access all from pubmod, and pubmod.hidden +;/ +# Can access all from pubmod, and pubmod.hidden +``` *File aa.tnsl (project a)* - - /; my_function_a - # Can access all from pubmod, and pubmod.hidden - ;/ +``` +/; my_function_a # Can access all from pubmod, and pubmod.hidden +;/ +# Can access all from pubmod, and pubmod.hidden +``` *File b.tnsl (project b)* - - /; my_function - # Can access all from pubmod, but not pubmod.hidden - ;/ - # Can access all from pubmod, but not pubmod.hidden +``` +/; my_function + # Can import all from pubmod, but not pubmod.hidden +;/ +# Can import all from pubmod, but not pubmod.hidden +``` ### Functions -TNSL functions are code blocks whose definition contains none of the following: control flow keywords, the module keyword, the method keyword. TNSL functions are called methods if they are contained within a method block. TNSL methods may only be called with relation to the user defined type they are linked to. If a TNSL function has no user defined name, it is anonymous. Anonymous functions can be stored as void type variables or called immediately. If an anonymous function is not stored, it is interpreted as inline and called immediately (this is known as a scope block). +Functions are blocks followed by a user defined name (not a keyword). +Functions may have inputs and/or outputs. +Inputs are enclosed by `()` and outputs are enclosed by `[]` -Function blocks may have inputs and/or outputs. Inputs are enclosed by `()` and outputs are enclosed by `[]` - -Input lists must begin with a type and conclude with at least one named parameter. If no type is given after a comma, it is assumed that the previous type carries over. +Input lists may begin with a type or be empty. +If they begin with a type they must conclude with at least one named parameter. +Parameters are separated by commas and use the previous type unless a new one is specified. Output lists consist of a comma seperated list of types. -Either of these may be omitted for no input and/or output. +Functions *may* be overloaded (that is, two functions may share names but have differing input type lists). +Overloaded functions *must not* share the same inputs and differing outputs, but *may* have both differing inputs and differing outputs. +Symbols can be defined in a separate build file or auto-generated by the compiler. +There is a standard for how the compiler will auto-generate names; this can be found in another chapter. + +### Function definition example: + +*simple function with no inputs or outputs named "my_function"* +``` +/; my_function + tnsl.print("Hello from my_function!") +;/ +``` + +*functions with inputs and/or outputs* +``` +/; my_second_function (int input1, bool input2) [bool, int] + return input2, input1 +;/ + +/; sum_lists ({}int a, b) [int] + int sum = 0 + + /; loop (int i = 0; i < len a) [++i] + sum += a{i} + ;/ + + /; loop (int i = 0; i < len b) [++i] + sum += b{i} + ;/ +;/ + +int global_lol = 0 + +/; next [int] + return ++global_lol +;/ + +/; set_global (int i) + global_lol = i +;/ +``` -TNSL functions may have their call stack modified by the `raw` and/or `inline` keywords. If the `inline` keyword is placed before the function declaration, the function will still be exported (if it is being exported), but any time it is used in the project's code, it will be optimized as if in-line. +### Control Flow Blocks -The use of the `raw` keyword has several effects: the function will have no generated assembly preamble, the function will allow `raw return` statements, the function will not be optimized, and the function will allow `asm` statements. Any function may be labeled `raw`, even `main` and anonymous functions. +Control flow blocks begin with the keywords `if`, `else`, `loop`, `match`, `case`, or `default`. -Functions *may* be overloaded (that is, two functions may share names but have differing input type lists). Overloaded functions *may not* share the same inputs and differing outputs, but *may* have both differing inputs and differing outputs. +Control flow blocks have a series of lists, generally these can be thought of as 'beginnings' encased in "()" and 'endings' encased in "[]". +What 'beginning' and 'ending' mean varries by the type of block and is explained below. -Examples: +### `if` Blocks - # simple function with no inputs or outputs named "my_function" - /; my_function - - ;/ +`if` blocks generally work as you would expect in other procedural languages. +They can be followed by any number of `else if` blocks as well as a final `else` block. - # function with inputs and outputs - /; my_second_function ( input1, input2 ) [ , , ... , ] - - ;/ +The 'beginning' "()" of an `if` or `else if` block is a series of statements separated by `;`. +These are executed in order. The last of these must evaluate to a boolean (type `bool` with value `true` or `false`). +The code within the if block is executed if the boolean evaluates to `true` and does not execute if the boolean evaluates to `false`. - # funtion with a scope block - /; my_third_function - - # a scope block - /; - - ;/ - ;/ +If any block in the series has a condition which evaluates to true then it is executed and the others are skipped. +If none evaluate to true then the `else` block will execute if present. -### Control Flow Blocks +The 'ending' "[]" of an `if` block is currently reserved and has undefined behavior. -Control flow blocks are code blocks whose definitions contain the keywords if, else, loop, match, case, or default. +*Examples:* +``` +/; if (true) + tnsl.print("this always prints") +;/ -For if, else, loop, and match any inputs and/or outputs are a semicolon-separated list of statements. For case or default, only inputs are accepted in the form of a single value. Any variables defined in these inputs or outputs are scoped to the block only. Control flow blocks may not actually output any values; instead, any statements in the output are evaluated when the block ends, weather it loops or not. +/; if (false) + tnsl.print("this never prints") +;; else if (true) + tnsl.print("this one will now print") +;; else + tnsl.print("this never prints either") +;/ -Examples: +/; if (0 !== 0) + tnsl.print("you have to use boolean values") +;; else if (1 < 0) + tnsl.print("standard equality operators work, see appendix for a list.") +;; else if (int i = 0; i < 2 && 5 > i) + tnsl.print("Statements!") +;/ - # simple if block - /; if ( ) - - ;/ +/; if (false) + tnsl.print("this never prints") +;; else if (false) + tnsl.print("this never prints either") +;; else + tnsl.print("this one will now print") +;/ +``` - # if block with else and else if - /; if ( ; ... ; ) - - ;; else if ( ; ... ; ) - - ;; else - - ;/ +### `loop` Blocks - # loop block - /; loop ( ; ... ; ) - [ ; ... ; ] +The `loop` block can be configured (based on weather or not each boolean statement is omitted) to act as any type of loop. - - ;/ +The 'beginning' "()" of a `loop` is similar to an `if` in that it is a series of statements; however in the case of a `loop` the conditional is optional and defaults to `true` if omitted. +If the conditional evaluates to `true` then the inner code is evaluated. - # match block - /; match ( ; ... ; ) +The 'ending' "[]" of a `loop` is similar to the 'beginning' of the loop as it a series of statements with an optional conditional at the end. +If the conditional is omitted here it defaults to the same as the conditional from the 'beginning'. +Each of these statements are evaluated at the end of the loop and if the conditional evaluates to `true` then the loop repeats its execution from just after the 'beginning'. - /; case - - ;; case - - # Continue here would fall through to default - ;; default - - ;/ - ;/ +*Examples* +``` +# Same as a do ... while block +/; loop [ ] + +;/ -### Loops +# Same as a while loop +/; loop ( ) + +;/ -The `loop` block can be configured (based on weather or not each boolean statement is omitted) to act as any type of loop. +# Infinite loop +/; loop + +;/ -The *first* conditional is the **initial run condition**. It decides weather the loop is entered at all. If omitted, defaults to `true`, creating a `do ... while` type block. +# Adding statements to mimic a for loop +# Since i++ is not a bool it does not count +# as the conditional +/; loop (int i = 0; i < 10) [i++] + +;/ +``` -The *second* conditional is the **subsequent run condition**. It decides weather the loop continues to loop or not. If omitted, it *mirrors* the **initial run condition** (this is equivalent to a `for` or `while` block). +### `match` Blocks -Examples: - - # Same as a do ... while block - /; loop [ ] - - ;/ +`TODO` - # Same as a while loop - /; loop ( ) - - ;/ +#### `case` Block - # Infinite loop - /; loop - - ;/ +`TODO` - # Adding statements to mimic a for loop - /; loop (int i = 0; i < 10) [i++] - - ;/ +#### `default` Block -## Section 3 - Statements +`TODO` -### TNSL Statement Notation +## Section 3 - Types -There are three types of tnsl statements: code, pre-processor, and comment. Code statements begin with `;` and end at the next statement. Pre-processor statements begin with `:` and end at the next statement. Comment statements (line comments) begin with `#` and end at the next new line. After a line comment ends, the previous statement resumes. +An exhaustive list of built-in and special types can be found in Appendix B. -### Variable Declaration +### Standard Types in `tnsl` -Declaring a variable is done by referencing a type and then giving a list of names for the new variables. Optionally, a list of values may be given to initialize the new variables. +The standard set of types will be familiar to programmers with experience in procedural languages. +Some common types are: -Variables may be augmented by the following keywords: `const`, `volatile`, and/or `static`. +- Signed integer variants (positive or negative): `int`, `int8`, `int16`, `int32`, `int64` +- Unsigned integer variants (positive only): `uint`, `uint8`, `uint16`, `uint32`, `uint64` +- Floating point variants: `float`, `float32`, `float64` +- Boolean (`true` or `false`): `bool` +- -Declaring a variable as `const` means that it is a constant and must be immediately initialized. A constant may not be re-assigned a value. +TNSL restricts valid platforms to those with byte addressable memory and whose processors support at least 16-bit integers. -Declaring a variable as `volatile` means that the compiler will not attempt to optimize operations performed on it. +TNSL basic types with unspecified length (`int`,`uint`, and `float`) default to the largest supported in standard registers (non-SIMD or vector operations). -Declaring a variable `static` means that the value will be kept between function calls. Static variables may create race conditions when paired with threads. +I.E. for x86_32 `int` defaults to `int32`, on x86_64 `int` defaults to `int64` -Examples: +### `libtnsl` Types - # list with initialization - ;int a, b = 0, 1 - - # single without initialization - ;int c - - # list with partial initialization - ;int d, e = 0 # d is defined, but e is not +The following are well supported but rely on libtnsl: -## Section 4 - Types +- The meta-type: `type` +- The vector (SIMD) type: `vect` -An exhaustive list of built-in types can be found in Appendix B. +They are discussed in more detail in the advanced features section of the specification. -### The `void` Type +### Pointers -The `void` type represents one of two things: an unknown data type, or a function. When the void type is paired with input and output parameters `void( )[ ]` it represents a function. When it is not paired with these things it represents an unknown data type. +Pointer types are prefixed with the `~` (pointer to) operator. +This operator serves as both part of the type, and as a way to get a pointer from a variable. -Pure `void` types can not be created. Function types are *always* references to the function, more like pointers than data holders. Otherwise, void types must be created as pure pointers. In this case, they are in a sense "un-typed" pointers which do not know the length of the object they are pointing at, only the address. +The de-reference operator `` ` `` is used as a postfix to pointer variables when getting or setting the underlying value. -Examples: +*Examples* +``` +# define int i as 0 +int i = 0 - # simple function - /; func_1 - ;/ +# pointer to int i +~int p = ~i - # void example func - /; func_2 +# set the value of i using p (i is set to 1) +p` = 1 - # create a void type and assign it func_1's value - ;void()[] func_ref = func_1 - - # call func_1 using func_ref - ;func_ref() - ;/ +/; if (i == 1) + tnsl.print("That's pointers!") +;/ +``` -More examples of pointer voids are available in the pointers section of this document. +### References -### Arrays +Reference types are typically for use in function parameters but can be defined anywhere. Their type signature ends in the de-reference operator `` ` ``. -In memory, arrays store their length as a uint, then immediately follow with the contents of the array. This way, all arrays can be checked for length with the `len` operator. +A few quirks of reference types: -Arrays are created by prefixing a type with `{ <# of elements> }` or simply `{}` so long as the array is immediately initialized. One can similarly access an element of an array by suffixing the variable name with `{ }`. +- Reference types are similar to pointers and must be initialized with a pointer to be useful. +- When accessed or set in a normal statement they automatically de-reference the pointer they hold. +- When set in definition or function call they expect a pointer to the underlying variable they will access. +- The pointer which the reference variable uses can be set by prefixing with `~` -When initializing or assigning a new value to an entire array, use `{}` to encase a list of values. +*Examples* +``` +# this will be our underlying integer +int a = 0 -The length of the array can be gotten by `len ` +# basic definition and immediate assignment of a reference type +# (immediate assignment is special as it allows setting the +# pointer of the reference without use of the ~ operator) +int` r = ~a -Examples: +# sets or gets in normal statements will use the underlying 'a' - # create an array of five integers - ;{5}int i +# a becomes 1 +r = 1 - # assign values to the array - ;i{0} = 0 - ;i{1} = 2 - ;i{2} = 0 - ;i{3} = 2 - ;i{4} = 1 +# b is defined and set to 1 +int b = r - # store the length of the array - ;uint array_length = len i +# an example of declaration without immediate assignment +int` s - # create an initialized array with length five - ;{}int j = {1, 2, 3, 4, 5} +# setting what 's' points to requires use of the ~ operator +~s = ~a - # loop through the array and add them. - /; loop (int k = 0; k < array_length) [k++] +# a becomes 2 +s++ - ;i{k} += j{k} - ;/ +# a function with a reference parameter +/; add_one (int` i) + i++ +;/ +# you must explicitly call using a pointer to the variable being referenced +add_one(~a) -### Pointers +/; if (a == 3) + tnsl.print("a is now three") +;/ +``` -Pointer types are created using the `~` (pointer to) operator. This operator serves as both part of the type, and as a way to get a pointer from a type. To de-reference a pointer into it's base type, use the `` ` `` (de-reference) operator. +### Fixed-length Arrays -Passing by reference can be done by prefixing the type with the de-reference operator. This type is only available in function parameter declaration. To call a function with this type, a pointer to the desired variable must be given. +Arrays are a repeated sequence of the same type of data in memory. -Examples: +Arrays store their length as a `uint` and immediately follow with the contents of the array. All arrays can be checked for length with the `len` operator. + +Arrays are created by prefixing a type with `{ <# of elements> }`. +One can similarly access an element of an array by suffixing the variable name with `{ }`. - # define int - ;int i +When initializing or assigning a new value to an entire array, use `{}` to encase a list of values. - # pointer to i - ;~int p = ~i +The length of the array can be gotten by `len ` - # set i using p - ;`p = 1 +*Examples* +``` +# create an array of five integers +{5}int i + +# assign values to the array +i{0} = 0 +i{1} = 2 +i{2} = 0 +i{3} = 2 +i{4} = 1 + +# store the length of the array (5) +uint array_length = len i + +# create an initialized array with length five +{5}int j = {1, 2, 3, 4, 5} + +# loop through the array and add them. +/; loop (int k = 0; k < array_length) [k++] + i{k} += j{k} +;/ +``` + +### Unknown-length Arrays + +When creating an array where the length is not known at compile time (or accepting an array with unknown length as a parameter) use the `{}` prefix. + +***When would I use this?*** +- When defining an array within a function body or module the compiler will optimize however it thinks is best and is functionally equivalent to a fixed length array. +- The difference matters more when **defining functions** or **defining structs** since in this case `{}` ***always*** denotes a ***pointer*** to an array. + - This can be useful when you want to accept arbitrarily long lists or have a recursive struct which has an array of itself as a member. + +*Examples* +``` +# when defining an array +{}int i = {1, 2, 3, 4} +{}int j = {5, 6, 7, 8, 9, 10} + +# when defining a recursive struct +struct Node { + int i, + # using a fixed-length here would result in a + # compile time error because the size could + # not be computed + {}Node sub +} + +# when defining a function +/; sum({}int arr) [int] + int out = 0 + /; loop (int i = 0; i < len arr) [++i] + out += arr{i} + ;/ +;/ + +# sum can take any array of integers +int a = sum(i), b = sum(j) +``` + +### NOTE: Evaluation Order + +Order of evaluation of type prefixes and postfixes is first all prefixes in right to left order then all postfixes in left to right order. +This can be overridden using parenthesis. + +*Convoluted Examples* +``` +# a reference to a pointer which points to an int +~int` +(~int)` + +# a reference to a reference to an array (unknown length) which holds pointers to floats +{}~float`` +({}(~(float))`` + +``` - # a function taking a pass by reference - /; add_two (`int i) - i += 2 - ;/ +### The `void` Type - # calling add_two in two different ways - ;add_two(p) - ;add_two(~i) +The `void` type can represent two different things: unknown memory or a function. +When `void` is prefixed with `~` it represents a pointer to arbitrary memory (byte aligned). +When the void type is paired with input and output parameters `void( )[ ]` it represents a function. This is considered part of the type and is not a postifx. - # i is now 5 +*Examples* +``` +# simple function +/; func_1 + tnsl.print("hello!") +;/ + +# void example func +/; func_2 + + # create a void type and assign it func_1's value + void()[] func_ref = func_1 + + # call func_1 using func_ref + func_ref() +;/ +``` ### Casting Types -Casting between types uses the standard input and output enclosing `()` and `[]` in conjunction. Place a value in the input enclosing characters and a type to output in the output enclosing characters to cast one type to another (`( )[ ]`). +Cast by enclosing a value in `()` and following with the type to cast to enclosed in `[]`. -Examples: +*Examples* +``` +# define an int and a float +int i = 10 +float f = 11.5 - # define an int and a float - ;int i = 10 - ;float f = 11.5 +# define a void pointer and set it to reference i +~void v = ~i - # define a void pointer and set it to reference i - ;~void v = ~i - - # define an int pointer and cast the void pointer to initialize it - ;~int p = (v)[~int] +# define an int pointer and cast the void pointer to initialize it +~int p = (v)[~int] - # cast the float to an int and set the value of i - ;`p = (f)[int] +# cast the float to an int and set the value of i +p` = (f)[int] +``` ### Defining Types @@ -363,7 +498,7 @@ Examples: ;/ ;/ -### Interfaces +### Interface Types Interfaces are defined using the `interface` keyword. Interfaces have methods but no struct or members to accompany them. Instances of interfaces may not be created. Methods defined by interfaces must be overridden unless marked in the interface. Such marked methods may call on other methods, but may not use any members as interfaces have none. @@ -394,7 +529,7 @@ Example: ;/ ;/ -### Enums +### Enum Types Enums are defined using the `enum` keyword. An enum represents a set of possible states, and requires a single output type which can be compared. @@ -421,6 +556,10 @@ Examples: ROCK } +## Section 4 - Statements + +`TODO` + ## Section 5 - Operators An exhaustive list of operators can be found in Appendix A @@ -429,114 +568,101 @@ An exhaustive list of operators can be found in Appendix A Operator precedence is as follows (from greatest to least): - Pointer operators (p0): - - ~ - address of - - ` - de-reference - - - Access operator (p1): +``` +Pointer operators (p0): - . - get/access +~ - address of +` - de-reference - Increment/de-increment (p2): - ++ - increment +Access operator (p1): - -- - de-increment +. - get/access - Multiplication/division (p3): +Increment/de-increment (p2): - * - multiply +++ - increment - / - divide +-- - de-increment - Addition and subtraction (p4): +Multiplication/division (p3): - + - addition +* - multiply - - - subtraction +/ - divide - Modulus (p5): +Addition and subtraction (p4): - % - modulus ++ - addition +- - subtraction - Bitwise operators (p6): - & - and +Modulus (p5): - | - nor +% - modulus - ^ - xor - << - shift left - - >> - shift right +Bitwise operators (p6): - !& - nand +& - and - !| - nor +| - nor - !^ - xand +^ - xor - ! - not (bitwise or boolean) +<< - shift left +>> - shift right - Boolean operators (p7): +!& - nand - && - boolean and +!| - nor - || - boolean or +!^ - xand - == - boolean eq +! - not (bitwise or boolean) - > - greater than - < - less than - - !&& - boolean nand +Boolean operators (p7): - !|| - boolean nor +&& - boolean and - !== - boolean neq +|| - boolean or - !> - boolean not greater than +== - boolean eq - !< - boolean not less than +> - greater than - >== - boolean greater than or equal to +< - less than - <== - boolean less than or equal to +!&& - boolean nand -## Section 6 - `raw` and `asm` +!|| - boolean nor -### The `raw` Keyword +!== - boolean neq -The `raw` keyword can be used in four different scenarios, and each has a different meaning. +!> - boolean not greater than -1. The `raw` keyword can be used in function definitions. These effects were discussed in section 2.2. +!< - boolean not less than -2. The `raw` keyword may be used in conjunction with the `return` keyword, but only inside of raw functions. This causes an instant return regardless of stack or register state. It is recommended to clean up function and provide return types before using this. +>== - boolean greater than or equal to -3. The `raw` keyword may be used with the `struct` keyword to create a raw struct. Raw structs can not contain user defined types or generics. Raw types encode no type information and may not be extended. Raw structs, unlike static or dynamic structs, are only as wide their members. - - Static and dynamic structs contain a small amount of information pertaining to their actual type and generics so may be larger than only their members. - - In addition, since static and dynamic structs may be extended, they may not be the initially defined type and may be larger, further complicating matters. +<== - boolean less than or equal to +``` -4. The `raw` keyword may be used with the `enum` keyword to create a raw enum. Raw enums only have at most one state per bit and may bitwise or and bitwise and to generate a full state. Raw enums are much akin to bit-masks. +## Section 6 - `asm` -### The `asm` Keyword +`TODO` -The `asm` keyword may be used in `raw` functions or blocks to produce raw asm code for the assembler. Any valid assembly code may be used, and certain extensions are available such as variable pointer references. +## Section 7 - Crosscalling to C -Syntax: +`TODO` - ;asm "" ## License -- cgit v1.2.3