Skip to content

Commit

Permalink
Multiple input files to Mindcode compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
cardillan committed Sep 29, 2024
1 parent e406abe commit e5ba63b
Show file tree
Hide file tree
Showing 69 changed files with 889 additions and 721 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ Experimental features may contain bugs or produce suboptimal code, and are subje
* Added support for multiple loop variables in [list iteration loops](doc/syntax/SYNTAX-3-STATEMENTS.markdown#list-iteration-loops). Each iteration processes as many elements from the list as there are loop variables.
* Added an `out` keyword to be used with loop control variables in list iteration loop, allowing [list elements to be modified](/doc/syntax/SYNTAX-3-STATEMENTS.markdown#modifications-of-values-in-the-list).
* Added a new GUI option to choose optimization level in the web app when compiling Mindcode or building Schemacode.
* Added a capability to run the compiled code on an emulated processor, by using a `Compile and Run` button in the web app, or the [`--run` command line option](/doc/syntax/TOOLS-CMDLINE.markdown#running-the-compiled-code). The output is shown in a separate control in the web app, or written to the log when using the command line tool.
* Added new optimization level, `experimental`. On this setting, the Data Flow optimizer doesn't assume the assignments to global variables might be changed by editing the compiled code, allowing to perform more optimizations on them. Program parameters must be used instead of global variables for program parametrization if this optimization level is used.
* Added a capability to run the compiled code on an emulated processor, by using a `Compile and Run` button in the web app, or the [`--run` command line option](/doc/syntax/TOOLS-CMDLINE.markdown#running-the-compiled-code). The output is shown in a separate control in the web app, or written to the log when using the command line tool.
* Added a capability to the command line tool to compile several source files at once using the [`--append` command line argument](doc/syntax/TOOLS-CMDLINE.markdown#additional-input-files).
* Added new optimization level, `experimental`. On this setting, the [Data Flow optimizer](doc/syntax/SYNTAX-6-OPTIMIZATIONS.markdown#data-flow-optimization) doesn't assume the assignments to global variables might be changed by editing the compiled code, allowing to perform more optimizations on them. Program parameters must be used instead of global variables for program parametrization if this optimization level is used.
* Added [formattable string literals](doc/syntax/SYNTAX.markdown#formattable-string-literals), which allow formatting outputs of the `print` and `println` functions the same way as `printf` does.
* Added [enhanced comments](doc/syntax/SYNTAX-4-FUNCTIONS.markdown#enhanced-comments), an alternative way to enter remarks.
* Added new [`sort-variables` compiler directive](doc/syntax/SYNTAX-5-OTHER.markdown#option-sort-variables) which ensures that user variables will be accessed in a well-defined order, to make inspecting the variables in the Mindustry processors **Vars** screen easier.
Expand Down
9 changes: 4 additions & 5 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

Welcome to **Mindcode**, a high-level language for [Mindustry](https://github.com/Anuken/Mindustry). Mindustry is a game in the tower-defense genre. Mindustry added Logic in late 2020. Logic is a programming language, closer to assembly than a high-level language. Mindcode aims to make Mindustry programming easier for everyone.

Mindcode focuses of the following priorities:
The perils of using a high-level language for Mindustry code are inefficient code generation and the possibility of compiler bugs. Mindcode strives to address both of these issues:

* Simplicity: support for easy creation of short scripts as well as larger projects. Names and identifiers for Mindustry Logic objects and functions are derived from Mindustry Logic itself with minimal alterations.
* Efficiency: while there's still a lot of room for improvement, the mlog code produced by Mindcode is remarkably efficient thanks to many different [optimizations](doc/syntax/SYNTAX-6-OPTIMIZATIONS.markdown). Especially optimizations which [reduce runtime by increasing code size](doc/syntax/SYNTAX-6-OPTIMIZATIONS.markdown#optimization-for-speed) are quite unique among mlog compilers.
* Reliability: the project uses a battery of automated tests, including running the compiled code on an emulated processor, to ensure the compiled code works as expected. While [bugs do occur](https://github.com/cardillan/mindcode/issues?q=label%3Abug+), they often pertain to new functionality and get usually resolved quickly.
* Efficiency: while there's still a lot of room for improvement, the mlog code produced by Mindcode is quite efficient today. Mindcode is capable of simplifying expressions, removing unnecessary or unreachable code and using available instruction space to produce faster code by unrolling loops or inlining functions automatically.
* Reliability: this project uses a battery of automated tests, including running the compiled code on an emulated processor, to ensure the compiled code works as expected. While [bugs do occur](https://github.com/cardillan/mindcode/issues?q=label%3Abug+), they usually get resolved quickly.

> [!NOTE]
> Please have a look at planned [upcoming changes to Mindcode](https://github.com/cardillan/mindcode/discussions/142). These changes will be substantial, and any comments and suggestions are welcome now while the changes are still being deliberated.
Expand All @@ -33,7 +32,7 @@ A [changelog](CHANGELOG.markdown) is now maintained for releases.
Mindcode is available at http://mindcode.herokuapp.com/. Write some Mindcode in the _Mindcode Source Code_ text area, then press the **Compile** button. The _Mindustry Logic_ text area will contain the Logic version of your Mindcode. Copy the compiled version. Back in Mindustry, edit your processor, then use the **Edit** button in the Logic UI.
Select **Import from Clipboard**. Mindustry is now ready to execute your code.

You can also use the **Compile and Run** button to execute the compiled code right away on an emulated processor. If your code doesn't interact with a contents of the Mindustry world, the output produced by your code will be displayed.
You can also use the **Compile and Run** button to execute the compiled code right away on an emulated processor. If your code doesn't interact with a contents of the Mindustry world, the output produced by `print` statements in your code will be displayed.

It is also possible use the [command line tool](doc/syntax/TOOLS-CMDLINE.markdown) to compile your files, even copying the compiled code into the clipboard automatically if desired. The command line compiler can be set up in the following way:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import info.teksol.mindcode.compiler.CompilerMessage;
import info.teksol.mindcode.compiler.CompilerOutput;
import info.teksol.mindcode.compiler.CompilerProfile;
import info.teksol.mindcode.compiler.SourceFile;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.impl.type.FileArgumentType;
import net.sourceforge.argparse4j.inf.ArgumentGroup;
Expand All @@ -12,6 +13,7 @@
import net.sourceforge.argparse4j.inf.Subparsers;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static info.teksol.mindcode.compiler.CompilerFacade.compile;
Expand Down Expand Up @@ -49,6 +51,12 @@ Subparser appendSubparser(Subparsers subparsers, FileArgumentType inputFileType,
.nargs("?")
.setDefault(new File("-"));

files.addArgument("-a", "--append")
.help("Additional Mindcode source file to be compiled along with the input file. Such additional files may " +
"contain common functions. More than one file may be added this way.")
.type(Arguments.fileType().verifyCanRead())
.nargs("*");

addCompilerOptions(subparser, defaults);
addRunOptions(subparser, defaults);
addOptimizationOptions(subparser, defaults);
Expand Down Expand Up @@ -77,12 +85,23 @@ from the Mindustry World. Sole exceptions are memory cells (cell1 to cell9) and
.setDefault(defaults.getStepLimit());
}

private SourceFile readFile(File file, boolean multiple) {
return new SourceFile(isStdInOut(file) || !multiple ? "" : file.getPath(), readInput(file));
}

@Override
void handle(Namespace arguments) {
CompilerProfile compilerProfile = createCompilerProfile(arguments);
String sourceCode = readInput(arguments.get("input"));
List<File> inputs = new ArrayList<>();
inputs.add(arguments.get("input"));
List<File> others = arguments.get("append");
if (others != null) {
inputs.addAll(others);
}

List<SourceFile> sourceFiles = inputs.stream().map(f -> readFile(f, inputs.size() >1)).toList();

final CompilerOutput<String> result = compile(sourceCode, compilerProfile);
final CompilerOutput<String> result = compile(sourceFiles, compilerProfile);

File output = resolveOutputFile(arguments.get("input"), arguments.get("output"), ".mlog");
File logFile = resolveOutputFile(arguments.get("input"), arguments.get("log"), ".log");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ which must be one of the following:

All actions take the name of input file and the name of output file as an argument. When the given input or output is
a text file, the argument is optional and when not specified, the standard input/output is used. Use `-` to explicitly
specify standard input or output for input or output file.
specify standard input or output for input or output file.

### Additional input files

When performing the _Compile Mindcode_ action, it is possible to use the `-a` or `--append` command line parameter to specify additional source files to be compiled along with the input file. The source files are parsed separately and error messages that may be generated during the compilation include the name of the file where the error occurred.

This feature is experimental and will be ultimately replaced by [support for modules](https://github.com/cardillan/mindcode/issues/149).

## Log file

Expand Down
2 changes: 1 addition & 1 deletion doc/syntax/SYNTAX-1-VARIABLES.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ the entire `if DEBUG ... end` statement will be skipped and not included in the
>
> `const FMT = $"Position: ($x, $y)";
>
> The formattable string literal must be passed directly into the `print` or `println` functions.
> The formattable string literal must be passed directly into the `print`, `println`, `printf` or `remark` functions.
## Built-in icons

Expand Down
35 changes: 16 additions & 19 deletions doc/syntax/SYNTAX-6-OPTIMIZATIONS.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ updated to replace the temporary variable with the target variable used in the s

The optimization is performed only when the following conditions are met:

1. The `set` instruction assigns from a temporary variable.
2. The temporary variable is used in exactly one other instruction. The other instruction
* The `set` instruction assigns from a temporary variable.
* The temporary variable is used in exactly one other instruction. The other instruction
immediately precedes the instruction producing the temporary variable.
3. All arguments of the other instruction referencing the temporary variable are output ones.
* All arguments of the other instruction referencing the temporary variable are output ones.

`push` and `pop` instructions are ignored by the above algorithm. `push`/`pop` instructions of any eliminated variables
are removed by the [Stack Optimization](#stack-optimization) down the line.
Expand All @@ -35,11 +35,9 @@ statement.

The optimization is performed only when the following conditions are met:

1. The set instruction assigns to a case-expression temporary variable.
2. The set instruction is the first of all those using the temporary variable (the check is based on absolute
instruction sequence in the program, not on the actual program flow).
3. Each subsequent instruction using the temporary variable conforms to the code generated by the compiler
(i.e. has the form of `jump target <condition> __astX testValue`)
* The set instruction assigns to a case-expression temporary variable.
* The set instruction is the first of all those using the temporary variable (the check is based on absolute instruction sequence in the program, not on the actual program flow).
* Each subsequent instruction using the temporary variable conforms to the code generated by the compiler (i.e. has the form of `jump target <condition> __astX testValue`)

`push` and `pop` instructions are ignored by the above algorithm. `push`/`pop` instructions of any eliminated variables
are removed by the stack usage optimization down the line.
Expand Down Expand Up @@ -93,19 +91,18 @@ jump label <inverse of comparison>/<comparison> A B

Prerequisites:

1. `jump` is an `equal`/`notEqual` comparison to `false`,
2. `var` is a temporary variable,
3. `var` is not used anywhere in the program except these two instructions,
4. `<comparison>` has an inverse/`<comparison>` exists as a condition.
* `jump` is an `equal`/`notEqual` comparison to `false`,
* `var` is a temporary variable,
* `var` is not used anywhere in the program except these two instructions,
* `<comparison>` has an inverse/`<comparison>` exists as a condition.

## Single Step Elimination

This optimizer simplifies the following sequences of jump that are a result of certain combinations of optimizations:

1. A conditional or unconditional jump targeting the next instruction (such a jump is obviously unnecessary).
2. A conditional or unconditional jump identical to the next instruction (unconditional jumps would be also
eliminated by Unreachable Code Elimination, but that isn't true for conditional jumps).
3. On the `advanced` level, the `end` instruction at the very end of the program is removed, as the processor will jump to the first instruction of the program upon reaching the end of the instruction list anyway.
* A conditional or unconditional jump targeting the next instruction (such a jump is obviously unnecessary).
* A conditional or unconditional jump identical to the next instruction (unconditional jumps would be also eliminated by Unreachable Code Elimination, but that isn't true for conditional jumps).
* On the `advanced` level, the `end` instruction at the very end of the program is removed, as the processor will jump to the first instruction of the program upon reaching the end of the instruction list anyway.

## Expression Optimization

Expand Down Expand Up @@ -324,7 +321,7 @@ understandable, but the optimizer would have to be more complex and therefore mo
> code.
>
> **On basic and advanced optimization levels, global variables are handled in the same way as program parameters. On the experimental level, global
> variables are fully optimized in a way similar to main or local variables. Always use program parameters for allowing program
> variables are fully optimized in a way similar to main or local variables. Always use program parameters for program
> parametrization.**
### Optimization levels
Expand Down Expand Up @@ -757,7 +754,7 @@ The loop optimization improves loops with the condition at the beginning by perf
The result of the first two optimizations in the list can be seen here:

```
LIMIT = 10;
param LIMIT = 10;
for i in 0 ... LIMIT do
cell1[i] = 1;
end;
Expand Down Expand Up @@ -966,7 +963,7 @@ end;
copy(cell1, cell2, 10);
// This produces a loop that CANNOT be unrolled: SIZE is not a constant value
SIZE = 10;
param SIZE = 10;
copy(cell1, cell2, SIZE);
// Some loops containing expressions in the condition can still be unrolled,
Expand Down
2 changes: 1 addition & 1 deletion doc/syntax/SYNTAX.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Supporting tools:

Additional information on Mindcode and Mindustry Logic:

* [Troubleshooting Mindcode](TROUBLESHOOTING.markdown))
* [Troubleshooting Mindcode](TROUBLESHOOTING.markdown)
* [Mindustry Tips and Tricks](MINDUSTRY-TIPS-N-TRICKS.markdown)

---
Expand Down
15 changes: 12 additions & 3 deletions doc/syntax/TOOLS-CMDLINE.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ which must be one of the following:

All actions take the name of input file and the name of output file as an argument. When the given input or output is
a text file, the argument is optional and when not specified, the standard input/output is used. Use `-` to explicitly
specify standard input or output for input or output file.
specify standard input or output for input or output file.

### Additional input files

When performing the _Compile Mindcode_ action, it is possible to use the `-a` or `--append` command line parameter to specify additional source files to be compiled along with the input file. The source files are parsed separately and error messages that may be generated during the compilation include the name of the file where the error occurred.

This feature is provisional and will be ultimately replaced by [Mindcode modules](https://github.com/cardillan/mindcode/issues/149).

## Log file

Expand Down Expand Up @@ -87,8 +93,8 @@ Actions:
## Compile Mindcode action help

```
usage: mindcode cm [-h] [-c] [-l [LOG]] [-t {6,7s,7w,7as,7aw}] [-i {1..100000}] [-e {1..1000}] [-g {SIZE,SPEED,AUTO}]
[-r {NONE,PASSIVE,ACTIVE}]
usage: mindcode cm [-h] [-c] [-l [LOG]] [-a [APPEND [APPEND ...]]] [-t {6,7s,7w,7as,7aw}] [-i {1..100000}]
[-e {1..1000}] [-g {SIZE,SPEED,AUTO}] [-r {NONE,PASSIVE,ACTIVE}]
[--sort-variables [{LINKED,PARAMS,GLOBALS,MAIN,LOCALS,ALL,NONE} [{LINKED,PARAMS,GLOBALS,MAIN,LOCALS,ALL,NONE} ...]]]
[--no-signature] [--run] [--run-steps {1..1000000000}] [-o LEVEL] [--temp-variables-elimination LEVEL]
[--case-expression-optimization LEVEL] [--dead-code-elimination LEVEL] [--jump-normalization LEVEL]
Expand All @@ -112,6 +118,9 @@ input/output files:
specified, or stdout when input is stdin. Use "-" to force stdout output.
-l, --log [LOG] Output file to receive compiler messages; uses input file with .log extension when no file is
specified.
-a, --append [APPEND [APPEND ...]]
Additional Mindcode source file to be compiled along with the input file. Such additional
files may contain common functions. More than one file may be added this way.
compiler options:
-t, --target {6,7s,7w,7as,7aw}
Expand Down
Loading

0 comments on commit e5ba63b

Please sign in to comment.