diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 27344b7ad..9ec4510a7 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -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 diff --git a/README.markdown b/README.markdown index b61ada2d1..6a66a03ca 100644 --- a/README.markdown +++ b/README.markdown @@ -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. @@ -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. diff --git a/compiler/src/main/java/info/teksol/mindcode/compiler/CompilerProfile.java b/compiler/src/main/java/info/teksol/mindcode/compiler/CompilerProfile.java index 654e27a94..b3805fd66 100644 --- a/compiler/src/main/java/info/teksol/mindcode/compiler/CompilerProfile.java +++ b/compiler/src/main/java/info/teksol/mindcode/compiler/CompilerProfile.java @@ -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; diff --git a/compiler/src/main/resources/library/sys.mnd b/compiler/src/main/resources/library/sys.mnd index 7648cf84c..1eb6c7700 100644 --- a/compiler/src/main/resources/library/sys.mnd +++ b/compiler/src/main/resources/library/sys.mnd @@ -12,61 +12,61 @@ 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(); @@ -74,7 +74,7 @@ def rotateLeft(display) end; end; -def rotateRight(display) +void rotateRight(display) case display.@type when @logic-display then rotateRightSmall(); when @large-logic-display then rotateRightLarge(); @@ -82,7 +82,7 @@ def rotateRight(display) end; end; -def upsideDown(display) +void upsideDown(display) case display.@type when @logic-display then upsideDownSmall(); when @large-logic-display then upsideDownLarge(); @@ -90,7 +90,7 @@ def upsideDown(display) end; end; -def flipVertical(display) +void flipVertical(display) case display.@type when @logic-display then flipVerticalSmall(); when @large-logic-display then flipVerticalLarge(); @@ -98,7 +98,7 @@ def flipVertical(display) end; end; -def flipHorizontal(display) +void flipHorizontal(display) case display.@type when @logic-display then flipHorizontalSmall(); when @large-logic-display then flipHorizontalLarge(); @@ -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 @@ -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 @@ -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; diff --git a/doc/syntax/SYSTEM-LIBRARY.markdown b/doc/syntax/SYSTEM-LIBRARY.markdown index f3db55921..af2de87ab 100644 --- a/doc/syntax/SYSTEM-LIBRARY.markdown +++ b/doc/syntax/SYSTEM-LIBRARY.markdown @@ -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. @@ -37,9 +37,9 @@ 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. @@ -47,9 +47,9 @@ Rotates the output to the right (clockwise) by 90 degrees for a small or a large 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. @@ -57,9 +57,9 @@ Rotates the output to the left (counterclockwise) by 90 degrees for a small or a 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. @@ -69,9 +69,9 @@ 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. @@ -79,9 +79,9 @@ Flips the output vertically (along the Y axis) for a small or a large display, o 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. @@ -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 @@ -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. @@ -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)`