Compiler for an "extended" version of the Mindustry logic language

Related tags

Command-line minblur
Overview

Minblur Compiler

Minblur is a compiler for a superset of "logic" programming language in the game Mindustry. It helps reduce code-duplication, making it easier to reuse the same logic in different places in your code without extra instructions.

Try out the online demo in your browser now!

Features

Minblur is a strict superset of Mindustry's regular "logic" text language, meaning you can copy-paste existing code into the compiler and it'll work. Then you can start to modify you code to use advanced features including...

Labels

One of the major pain-points with "logic text" is that jump instructions use numbers to indicate their destination, so inserting or removing code will break jumps. The solution is labels. A label is a name that will be resolved into a jump destination.

start:
  read isOn cell1 0
  jump $label:start equal isOn 0
  radar player any any distance @this 1 p
  sensor isDead p @dead
  jump $label:start equal isDead true

Constants

Code has lots of numbers, especially when dealing with memory cells and unit control. Keeping track of which number means what can be challenging, especially as the project grows and there are multiple processors involved. Is health at cell index 4, or 5? Constants help solve this problem.

# Define a constant
.define health_index 5

# A $ indicates a constant, which will be replaced with the correct value
# by the compiler. Also # starts a comment.
read health cell1 $health_index

# You can also have constant-expressions like this: ${<expression>}
.define player_index 2
read health cell1 ${player_index + 3}

# There are some shortcuts for common constant expressions, like getting a label address.
# These take the form "$<function>:<value>". So this:
jump $label:HesDeadJim health lessThan 0
# is the same as this
jump ${label("HesDeadJim")} health lessThan 0
HesDeadJim:

Macros

Code duplication is an issue, especially when dealing with multiple logic processors that have similar code but one or two slightly different values. You could just have a few set instructions at the top of each processor, but you still have to keep them in sync and it's annoying. Macros to the rescue! Macros allow you to generate the same code but with different constants.

# This macro takes one argument: controller
# Inside the macro, use $controller to reference the value
.macro shoot_control(controller)
  start:
  sensor shoot $controller @shooting
  sensor aimX $controller @shootX
  sensor aimY $controller @shootY
  set i 0
  fire_loop:
  getlink bldg i
  m! i += 1
  # Don't try to control the controller
  jump $label:fire_end equal bldg $controller
  control shoot bldg bldgAimX bldgAimY shoot 0
  fire_end:
  m! jump(fire_loop, i < @links)
  m! jump(start)
.endmacro
# Here lancer1 is the controller
shoot_control!(lancer1)
# Here salvo2 is the controller
shoot_control!(salvo2)

Macro arguments can be split across mutliple lines as long as they're between braces or parenthesies. If a macro is all on one line, the braces/parenthesies may be skipped.

.macro dummy(arg0, arg1, arg2)
  # Does nothing
.endmacro
dummy!(
    bla,
    bla,
    bla,
)
dummy!{ abc, def,
  ghi }
# No braces or parenthesies necessary
dummy! abd, def, ghi

Math Macro

One of the built-in macros is math! or just m!. It has its own syntax and is designed to make writing math expressions, and mindustry code in general, much easier. Some functions (e.g. read()) have return values and can be used in expressions like normal. Other functions (e.g. jump()) have no return, and can only be called as their own statement (see the example). In the list of functions below a -> result after the function means it returns the result parameter of the given instruction, and can be used in expressions like you'd expect. Note that the math functions are usually the op instruction.

sensor bx lancer1 @x
sensor by lancer1 @y
# These are math one-liners
start:
m! {
  dx = bx - @x
  dist = len(dx, by - @y)
}
print len
# Conditional jump
m! jump(print_out, len > 20)
print " - far away"
print_out:
printflush message1
# Unconditional jump
m! jump(start)

Functions

  • read(cell, index) -> result
  • write(value, cell, index)
  • draw(...) - The draw instruction
  • print(to) - The print instruction
  • drawflush()
  • printflush()
  • getlink(index) -> result
  • control(...) - The control instruction
  • radar(target1, target2, target3, sort, source, order) -> result - The radar instruction
  • sensor(from, sense_type) -> result
  • jump(label) OR jump(label, condition) - The jump function has two versions, the first generates an "always" jump, the second generates a conditional jump.
  • max(a, b) -> result
  • min(a, b) -> result
  • angle(x, y) -> result
  • len(x, y) -> result
  • noise(x, y) -> result
  • abs(x) -> result
  • log(a, b) -> result
  • log10(x) -> result
  • floor(x) -> result
  • ceil(x) -> result
  • sqrt(x) -> result
  • rand(x) -> result
  • sin(x) -> result
  • cos(x) -> result
  • tan(x) -> result
  • asin(x) -> result
  • acos(x) -> result
  • atan(x) -> result

Eval Macro

Due to how the parser works you can not use a constant in place of the instruction name itself (see the example below). The easiest way around this is the eval! macro which will do text-replacement and then parse that text.

.define INSTR set
# This will NOT work
$INSTR a 5
# This WILL work
eval!($INSTR a 5)

# This code:
.define index 1
eval!(set name${index} 4)
# Will generate this:
# set name1 4

Comments

Comments start with a # and continue until the end of the line. Comments starting with #! will be copied into the final output (though Mindustry will remove them when code is copied into the game itself). These output comments can be useful to denote code for different processors, if all your code is in one file.

Using the example from the Macros section, adding some comments would help make the output easier to read and make the sections more clear.

# This is a comment
#! Lancer code
shoot_control!(lancer1)
#! Salvo code
shoot_control!(salvo2)
#! End of code
Comments
  • Syntax error detected where there is not one

    Syntax error detected where there is not one

    When try and compile the code

    set i 0
    getlink turret i
    jump 0 strictEqual turret @null
    radar player ally any distance turret 1 p
    sensor x p @shootX
    sensor y p @shootY
    sensor s p @shooting
    control shoot turret x y s
    op add i i 1
    jump 1 always x y
    

    i get the error message

    Error in test.txt
    | syntax error at 8:1 near 'c' => expected label, instruction, or directive
    |   at 8:1 near 'c' => OneOf
    
    Error:
    
    opened by XenonLog01 1
  • Parser improvements, fixes #7 (partially).

    Parser improvements, fixes #7 (partially).

    Most of this commit is refactoring the instruction parsing code to make it less brittle and pave the way for future improvements. Truly improved error messages will require a custom nom error type, but this should suffice for now.

    This also includes several clippy fixes, more tests, the usual.

    opened by Bindernews 0
  • Discovered today that labels ARE a thing in mlog, so yeah

    Discovered today that labels ARE a thing in mlog, so yeah

    Named labels are already supported in mlog. Need to remove $label:<name> and support local labels differently. Example:

    ## initialization {
        @Cursor.initialization:
            ## @Error.initialization() {
                set @Error.initialization.return @counter
                jump @Error.initialization always
            ## }
    
            ## @Warnings.initialization() {
                set @Warnings.initialization.return @counter
                jump @Warnings.initialization always
            ## }
    
            ## @State.initialization() {
                set @State.initialization.return @counter
                jump @State.initialization always
            ## }
    
            ## Switch
            set @Noise._switch null
            ## Display
            set @Noise._display null
            ## Block
            set @Noise._displayType @large-logic-display
            ## Integer
            set @Noise._displayResolution 176
    
            ## @Noise.Main() {
                set @Noise.Main.return @counter
                jump @Noise.Main always
            ## }
        end
        ## }
    
    bug 
    opened by Bindernews 0
  • Enable label declarations in math macro

    Enable label declarations in math macro

    Motivating example:

    m! ore = sorter1
    m! i = 0
    loop:
    m! {
      obj = getlink(i)
      i += 1
      type = sensor(obj, @type)
      jump(loop_end, type != @unloader)
      control(configure, obj, ore, 0, 0, 0)
    }
    loop_end:
    m! jump(loop, i < @links)
    

    This could all be in one m! macro but you can't create labels yet, so it's split up.

    enhancement 
    opened by Bindernews 0
  • Not allowed dashes in variable names, that valid in original mlog

    Not allowed dashes in variable names, that valid in original mlog

    Correct code in mlog:

    sensor res_count nucleus1 @surge-alloy
    

    doesn't transpile:

    Error in example.mblur
    | syntax error at 1:1 near 's' => expected label, instruction, or directive
    |   at 1:1 near 's' => OneOf
    

    and I even can not find any workaround for this.

    opened by stork3214 2
  • "if" statements in m! macro

    Jumps are fine, but having if statements would be much nicer. It'll be a decent chunk of work, so it's not a priority but the idea is here.

    Example syntax:

    m! {
      if x < 5 {
        jump(loop)
      }
    }
    
    enhancement 
    opened by Bindernews 0
Releases(v0.1.0)
Owner
Binder News
Binder News
Vyper-Compiler Version Manager in Rust

Vyper Compiler Version Manager in Rust Install $ cargo install --git https://github.com/storming0x/vvm-rs --locked vvm-rs Install from source $ git c

Storming0x 26 Dec 15, 2022
Fast, minimal, feature-rich, extended formatting syntax for Rust!

Formatting Tools Fast, minimal, feature-rich, extended formatting syntax for Rust! Features include: Arbitrary expressions inside the formatting brace

Casper 58 Dec 26, 2022
rpsc is a *nix command line tool to quickly search for file systems items matching varied criterions like permissions, extended attributes and much more.

rpsc rpsc is a *nix command line tool to quickly search for file systems items matching varied criterions like permissions, extended attributes and mu

null 3 Dec 15, 2022
A superset of PHP with extended syntax and runtime capabilities.

PXP PXP is a superset of the PHP programming language that provides an extended set of syntax rules and language features to improve developer experie

PXP 188 Jan 29, 2023
The module graph logic for Deno CLI

deno_graph The module graph/dependency logic for the Deno CLI. This repository is a Rust crate which provides the foundational code to be able to buil

Deno Land 67 Dec 14, 2022
Extract core logic from qdrant and make it available as a library.

Qdrant lib Why? Qdrant is a vector search engine known for its speed, scalability, and user-friendliness. While it excels in its domain, it currently

Tyr Chen 27 Jan 1, 2024
An awesome language and its compiler.

Calocom Project Build Build with cargo-make Just run cargo make in the root directory of the project. Or, if you want to build it in release mode, run

Aoyang Yu 31 Sep 16, 2022
Open-source compiler for the Papyrus scripting language of Bethesda games.

Open Papyrus Compiler This project is still WORK IN PROGRESS. If you have any feature requests, head over to the Issues tab and describe your needs. Y

erri120 22 Dec 5, 2022
Compiler frontend for the PureScript programming language.

purescript-analyzer Goals Provide an independent frontend for providing information for IDE tooling, separate from the compiler. Implement a rich edit

Justin Garcia 16 Jul 25, 2023
An interpreter and compiler for the Brainfuck language.

Brainrust ?? An interpreter and compiler for the Brainfuck language. Prerequisites You need a LLVM 16.0.* installation on your system. On Windows, you

Michael Gerhold 4 Nov 4, 2023
A more intuitive version of du in rust

A more intuitive version of du in rust

andy.boot 3k Sep 20, 2021
IntelliJ version of the Afterglow Sublime Text theme

Afterglow IntelliJ This theme for IntelliJ is based on the the Afterglow Sublime Text theme, and replaces the default sidebar icons and colour of Inte

Sidney Just 81 Jun 29, 2022
Nvm - Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions

Node Version Manager Table of Contents Intro About Installing and Updating Install & Update Script Additional Notes Troubleshooting on Linux Troublesh

nvm.sh 63.8k Jan 7, 2023
Python PEP-440 Version Parsing

PyVer (WIP) Python PEP-440 Version Parsing This package allows for parsing Python PEP-440 version numbers and comparisons between PEP-440 Versions Usa

Allstreamer 3 Sep 18, 2022
An enhanced version of filetime, which can set file creation time on Windows.

filetime_creation Documentation An enhanced version of filetime, which can set file creation time on Windows. Internally, this use SetFileTime Win32 A

29 4 Dec 5, 2022
Python PEP-440 Version Parsing

PyVer Python PEP-440 Version Parser This package allows for parsing Python PEP-440 version numbers and for comparisons between PEP-440 version numbers

null 3 Sep 18, 2022
A bring-your-own-mutex version of once_cell.

generic_once_cell generic_once_cell is a generic no_std version of once_cell. Internal synchronization for initialization is provided as type paramete

Martin Kröning 3 Nov 28, 2022
A library for python version numbers and specifiers, implementing PEP 440

PEP440 in rust A library for python version numbers and specifiers, implementing PEP 440 Not yet on crates.io due to PyO3/pyo3#2786. use std::str::Fro

konstin 9 Dec 22, 2022
Run the right version of python, in the right environment, for your project

rpy Do you deal with lots of virtual python environments? rpy is for you! Before rpy: ~/dev/prj$ env PYTHONPATH=src/py path/to/my/interpreter src/py/m

Aquatic Capital Management 2 Dec 8, 2022