Skip to content

Commit

Permalink
System library - findLinkedBlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
cardillan committed Nov 3, 2024
1 parent 1b1d343 commit 25f340f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ All notable changes to this project will be documented in this file.
* Added [vararg (variable arity) functions](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#vararg-functions).
* Added [function overloading](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#function-overloading).
* Added the possibility to specify custom instructions not known to Mindcode through the [`mlog()` function](doc/syntax/SYNTAX-5-OTHER.markdown#creating-custom-mlog-instructions).
* Added the [`findLinkedBlocks` function](doc/syntax/SYSTEM-LIBRARY.markdown#findlinkedblocks) to the system library.

### Changed

Expand Down
8 changes: 4 additions & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
Please read the [syntax](doc/syntax/SYNTAX.markdown) document for a complete description of Mindcode syntax. You can also use the code examples in the web application to get familiar with Mindcode.

> [!IMPORTANT]
> In the [2.3.0 release](CHANGELOG.markdown#230---2024-10-16), Mindcode introduces a stricter form of the syntax where semicolons and the `do`/`then` keywords are no longer optional. The original syntax is deprecated, but will be available for some time through the `#relaxed;` directive, which can be put at the beginning of your code. Other changes to the syntax include compulsory `out` keywords for output function call arguments and using the `@` prefix for Mindustry built-in variables used as properties. The old syntax is still supported, but generates a warning. See [Strict and Relaxed syntax](doc/syntax/SYNTAX-STRICT-RELAXED.markdown).
> In the [2.3.0 release](CHANGELOG.markdown#230---2024-10-16), Mindcode introduces a stricter form of the syntax where semicolons and the `do`/`then` keywords are no longer optional. The original syntax is deprecated, but will be available for some time through the `#relaxed;` directive, which can be put at the beginning of your code. Other changes to the syntax include compulsory `out` keywords for output function call arguments and using the `@` prefix for Mindustry built-in variables used as properties. The old syntax is still supported, but generates a warning. See [Strict and Relaxed syntax](doc/syntax/SYNTAX-STRICT-RELAXED.markdown) for a description of all changes to the syntax.
>
> The relaxed variant of the syntax will be eventually removed.
Expand All @@ -22,16 +22,16 @@ The most important recent changes to Mindcode include:

* Mindustry Logic 8
* Full support for the Mindustry Logic in the upcoming [Mindustry version 8](/doc/syntax/MINDUSTRY-8.markdown).
* A [system library of useful functions](doc/syntax/SYSTEM-LIBRARY.markdown) is available when compiling for Mindustry Logic 8.
* Basic functionality
* Significant improvement in reporting error messages generated during compilation.
* Ability to inject the mlog code to Mindustry processors via the [Mlog Watcher mod](doc/syntax/TOOLS-MLOG-WATCHER.markdown).
* Support for running the compiled mlog code in an emulated processor.
* Tool for [partial decompilation](doc/syntax/TOOLS-MLOG-DECOMPILER.markdown) of an existing mlog code into Mindcode.
* Mindcode syntax
* User-defined functions may provide additional return values through [output parameters](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#function-parameters).
* User-defined functions enhancements: user-defined functions may provide additional return values through [output parameters](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#function-parameters), can accept [variable number of arguments](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#vararg-functions) and can be [overloaded](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#function-overloading).
* New mechanism for [program parametrization](doc/syntax/SYNTAX-1-VARIABLES.markdown#program-parameters).
* Improved [List iteration loops](doc/syntax/SYNTAX-3-STATEMENTS.markdown#list-iteration-loops) supporting more than one loop variable and modification of the list elements.
* [Remarks](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#remarks) can be now included in the compiled code.
* Improved [List iteration loops](doc/syntax/SYNTAX-3-STATEMENTS.markdown#list-iteration-loops) supporting more than one loop variable and modification of the list elements while iterating.

See [changelog](CHANGELOG.markdown) for a comprehensive list of changes.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class CompilerProfile {
public static final int MAX_INSTRUCTIONS = 100_000;
public static final int MAX_INSTRUCTIONS_WEBAPP = 1500;
public static final int DEFAULT_INSTRUCTIONS = 1000;
public static final int DEFAULT_WEBAPP_PASSES = 3;
public static final int DEFAULT_WEBAPP_PASSES = 5;
public static final int DEFAULT_CMDLINE_PASSES = 25;
public static final int DEFAULT_STEP_LIMIT_WEBAPP = 1_000_000;
public static final int DEFAULT_STEP_LIMIT_CMDLINE = 10_000_000;
Expand Down
66 changes: 47 additions & 19 deletions compiler/src/main/resources/library/sys.mnd
Original file line number Diff line number Diff line change
Expand Up @@ -12,93 +12,93 @@ end;

// Small display transformations

def rotateLeftSmall()
void rotateLeftSmall()
rotate(90);
translate(0, - DISPLAY_SIZE_SMALL);
end;

def rotateRightSmall()
void rotateRightSmall()
rotate(270);
translate(- DISPLAY_SIZE_SMALL, 0);
end;

def upsideDownSmall()
void upsideDownSmall()
rotate(180);
translate(- DISPLAY_SIZE_SMALL, - DISPLAY_SIZE_SMALL);
end;

def flipVerticalSmall()
void flipVerticalSmall()
scale(1, -1);
translate(0, - DISPLAY_SIZE_SMALL);
end;

def flipHorizontalSmall()
void flipHorizontalSmall()
scale(-1, 1);
translate(- DISPLAY_SIZE_SMALL, 0);
end;

// Large display transformations

def rotateLeftLarge()
void rotateLeftLarge()
rotate(90);
translate(0, - DISPLAY_SIZE_LARGE);
end;

def rotateRightLarge()
void rotateRightLarge()
rotate(270);
translate(- DISPLAY_SIZE_LARGE, 0);
end;

def upsideDownLarge()
void upsideDownLarge()
rotate(180);
translate(- DISPLAY_SIZE_LARGE, - DISPLAY_SIZE_LARGE);
end;

def flipVerticalLarge()
void flipVerticalLarge()
scale(1, -1);
translate(0, - DISPLAY_SIZE_LARGE);
end;

def flipHorizontalLarge()
void flipHorizontalLarge()
scale(-1, 1);
translate(- DISPLAY_SIZE_LARGE, 0);
end;

// Generic display transformations

def rotateLeft(display)
void rotateLeft(display)
case display.@type
when @logic-display then rotateLeftSmall();
when @large-logic-display then rotateLeftLarge();
else stopProcessor();
end;
end;

def rotateRight(display)
void rotateRight(display)
case display.@type
when @logic-display then rotateRightSmall();
when @large-logic-display then rotateRightLarge();
else stopProcessor();
end;
end;

def upsideDown(display)
void upsideDown(display)
case display.@type
when @logic-display then upsideDownSmall();
when @large-logic-display then upsideDownLarge();
else stopProcessor();
end;
end;

def flipVertical(display)
void flipVertical(display)
case display.@type
when @logic-display then flipVerticalSmall();
when @large-logic-display then flipVerticalLarge();
else stopProcessor();
end;
end;

def flipHorizontal(display)
void flipHorizontal(display)
case display.@type
when @logic-display then flipHorizontalSmall();
when @large-logic-display then flipHorizontalLarge();
Expand All @@ -108,14 +108,42 @@ end;

// Scaling

def scaleSmallToLarge()
void scaleSmallToLarge()
scale(DISPLAY_SIZE_LARGE / DISPLAY_SIZE_SMALL, DISPLAY_SIZE_LARGE / DISPLAY_SIZE_SMALL);
end;

def scaleLargeToSmall()
void scaleLargeToSmall()
scale(DISPLAY_SIZE_SMALL / DISPLAY_SIZE_LARGE, DISPLAY_SIZE_SMALL / DISPLAY_SIZE_LARGE);
end;

// BLOCKS

inline void findLinkedBlocks(title, message, linkMap...)
do
print(title);
n = @links;
while n > 0 do
n = n - 1;
block = getlink(n);
print("\nFound: ", block);
type = block.@type;
for requested, name, out variable, required in linkMap do
if requested == type then
variable = block;
if requested == @message then message = block; end;
end;
end;
end;

foundAll = 1;
for requested, name, out variable, required in linkMap do
print($"\n$name: $variable");
if required then foundAll &= variable; end;
end;
printflush(message);
loop while !foundAll;
end;

// UNITS

// Searches for and binds a free unit of given type. If no free unit of given type can be found
Expand Down Expand Up @@ -226,7 +254,7 @@ end;

// Formats a number into the text buffer, without external memory.
// The text buffer must not contain placeholders {0} and {1}. It must contain at least one other placeholder ({2} or higher).
def formatNumber(n)
void formatNumber(n)
n = floor(n);
if n < 0 then
format("-{2}"); // Prepend the minus sign
Expand All @@ -246,7 +274,7 @@ end;

// Prints the number straight away
// The text buffer must not contain any placeholders lower than {3}.
def printNumber(n)
void printNumber(n)
print("{2}");
formatNumber(n);
end;
Expand Down
84 changes: 67 additions & 17 deletions doc/syntax/SYSTEM-LIBRARY.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Mindcode comes equipped with a system library. At this moment, the library is just a single source file, `sys.mnd`, which is automatically compiled together with each source file, both in the command line compiler and in the web app. The library is only included if the language target is 8A or higher, as it contains functions that build upon some of the instructions that will be added in the upcoming Mindustry 8 version.

To use the functions and constants provided by the system library in your program, you need to compile for Mindustry Logic 8 y including `#set target = ML8A` in your program.
To use the functions and constants provided by the system library in your program, you need to compile for Mindustry Logic 8 by including `#set target = ML8A` in your program.

The system library is an experimental feature. The functions provided by the library and the mechanism for its inclusion in your program may change in future releases.

Expand Down Expand Up @@ -37,29 +37,29 @@ The following functions use graphics transformation to rotate the graphics outpu

Definitions:

* `def rotateRightSmall()`
* `def rotateRightLarge()`
* `def rotateRight(display)`
* `void rotateRightSmall()`
* `void rotateRightLarge()`
* `void rotateRight(display)`

Rotates the output to the right (clockwise) by 90 degrees for a small or a large display, or for a display given as an argument.

### rotateLeft

Definitions:

* `def rotateLeftSmall()`
* `def rotateLeftLarge()`
* `def rotateLeft(display)`
* `void rotateLeftSmall()`
* `void rotateLeftLarge()`
* `void rotateLeft(display)`

Rotates the output to the left (counterclockwise) by 90 degrees for a small or a large display, or for a display given as an argument.

### upsideDown

Definitions:

* `def upsideDownSmall()`
* `def upsideDownLarge()`
* `def upsideDown(display)`
* `void upsideDownSmall()`
* `void upsideDownLarge()`
* `void upsideDown(display)`

Rotates the output by 180 degrees (upside down) for a small or a large display, or for a display given as an argument.

Expand All @@ -69,19 +69,19 @@ Rotates the output by 180 degrees (upside down) for a small or a large display,

Definitions:

* `def flipVerticalSmall()`
* `def flipVerticalLarge()`
* `def flipVertical(display)`
* `void flipVerticalSmall()`
* `void flipVerticalLarge()`
* `void flipVertical(display)`

Flips the output vertically (along the Y axis) for a small or a large display, or for a display given as an argument.

### flipHorizontal

Definitions:

* `def flipHorizontalSmall()`
* `def flipHorizontalLarge()`
* `def flipHorizontal(display)`
* `void flipHorizontalSmall()`
* `void flipHorizontalLarge()`
* `void flipHorizontal(display)`

Flips the output horizontally (along the X axis) for a small or a large display, or for a display given as an argument.

Expand All @@ -99,6 +99,44 @@ Definition: `def scaleLargeToSmall()`

Scales the graphics output so that an output that targets a large display gets displayed over the entire area of a small display.

# Blocks

# findLinkedBlocks

Definition: `inline void findLinkedBlocks(title, message, linkMap...)`

Searches blocks linked to the processor for blocks of the required type, and assigns them to given variables if found. Can wait till a block of the required type is linked to the processor.

This function is useful to dynamically locate blocks of given types, instead of using the predefined link name. By locating the blocks dynamically, it is not necessary to link a block to the processor under a particular name, such as `message1` or `switch1`. The function isn't well suited when two blocks of the same type are needed (e.g. two switches), but can handle situations where a single variable can accept multiple block types (e.g. either memory cell or memory bank).

Function outputs status information while it is running.

Inputs and outputs:

* `title`: title to be used as part of the status information.
* `message`: initial block to use to output status information. Typically `message1`.
* `linkMap`: definition of the required blocks. Each blocks needs four variables:
* `requested`: type of the requested block, e.g. `@switch`.
* `name`: name of the block to use as part of the status information.
* `out variable`: variable to receive the block
* `required`: if `true`, the function will wait until a block of given type is linked to the processor. If false, the function doesn't wait.

Example of a call to this function:

```
#set target = ML8A;
findLinkedBlocks("Example program.\nTrying to locate linked blocks", message1,
@large-logic-display, "Display", out display, true,
@message, "Message", out message, false,
@switch, "Switch", out switch, false,
@memory-bank, "Memory", out memory, true,
@memory-cell, "Memory", out memory, true
);
```

When the function call ends, the `display` and `memory` variables are set to a large display or memory cell/memory bank respectively. `message` and `switch` are set if corresponding blocks are linked to the processor, otherwise are `null`.

# Units

## findFreeUnit
Expand Down Expand Up @@ -148,7 +186,9 @@ The status of the search is output to `SYS_MESSAGE`. Either set the message to a

# Text output

## `formatNumber(n)`
## formatNumber

Definition: `void formatNumber(n)`

Formats the number passed in as a parameter into the text buffer, using comma as thousands separator. Fractional part of the number to be printed is ignored.

Expand All @@ -168,6 +208,16 @@ To use the function, the text buffer must not contain placeholders `{0}`, `{1}`
> [!TIP]
> While the functions is optimized for performance, formatting numbers is many times slower than just printing them using the `print()` function.
## printNumber

Definition: `void printNumber(n)`

Prints the number passed in as a parameter into the text buffer, using comma as thousands separator. Fractional part of the number to be printed is ignored.

To use the function, no placeholder lower than `{3}` may be present in the text buffer.

See also [`formatNumber`](#formatnumber)

# Utility functions

## `distance(x1, y1, x2, y2)`
Expand Down

0 comments on commit 25f340f

Please sign in to comment.