Replies: 2 comments
-
|
Seeing mlogjs/mlogjs#236, I'm starting to think that Mindcode might provide a way around shadowing global variables too. On the other hand, I'm planning to add namespaces in not too distant future, and maybe a mechanism for accessing shadowed variables might emerge naturally from it. |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
A first preview of Mindcode 3.0 was published: |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Mindcode 3.0 is planned for release in a few weeks. To make the transition easier, please make sure your Mindcode compiles under the
strictsyntax, which is the default.Mindcode 3.0
Version 3.0 comes with an updated compiler containing many components that were rewritten completely from scratch. These components include grammar definition, parser and code generator - optimizations were largely unaffected by the rewrite. Code which compiled under the
strict(the default) syntax of Mindcode 2.5.0 or later will compile in the version 3.0 as well and should produce the same result (the generated code and execution timing may be different).New features
The rewritten compiler brings these new features and changes:
print($"Sum: ${a + b}.");. Any expression, including e.g. function calls, can be used in the curly braces. Enhanced comments have the same capabilities:/// Sum: ${a + b}.%rrggbbor%rrggbbaa, e.g.%ff0000is bright red.total++or--limit, for example.void foo() end;, ordo while @time < endTime;.type = getlink(index).@typegetlink(index++).enabled = false;getMessageBlock().printflush()beginandend).loopkeyword indo loop whileloops is optional. The keyword will be deprecated and eventually dropped.New experimental features
Breaking changes
A new system of selecting Mindustry Logic version targets was adopted.
Removed features
Mindcode 3.0 removed most of the features which were deprecated in previous versions of Mindcode. As a result, the following elements of Mindcode syntax are no longer supported:
printf()function in Mindustry Logic 7 language target.The relaxed syntax mode in Mindcode 2.x defined some language elements as optional. All these elements are no longer optional and must be always specified:
@prefix for Mindustry built-in variables used as properties (e.g.vault1.@coalinstead ofvault1.coal),outmodifier when passing an output argument to a Mindustry Logic built-in function,dokeyword in loops,thenkeyword inifandcaseexpressions.Promoted experimental features
The following features are no longer considered experimental:
requirekeyword and--appendcommand-line argument for adding a system library or another external file to the compiled code.mlogandmlogSafefunctions for creating custom instructions.sort-variablescompiler directiveadvancedlevel)advancedlevel)formatinstruction when compiling for Mindustry Logic 8 (now available onbasiclevel)basic/advancedlevel)New features
Selected new features are described in greater detail here.
Mindustry Logic versioning
Mindcode uses the
targetdirective and command-line option to specify which version of Mindustry Logic and Mindcode syntax to use when compiling source code. A new system for specifying these targets was adopted.The target versions consist of a major and minor version number. As of now, these versions exist:
Version 8.0 will be the version corresponding to the official Mindustry 8 release. Possible further enhancements of Mindustry 8 or, possibly, of the Mindcode language will be incorporated as separate versions with updated minor version number.
The target can be set using either just a major, or both major and minor version numbers. When specifying both numbers, the specified version is used. When specifying just the major version, the most recent minor version in given major category is used. Example:
To use a world-processor variant of Mindcode language, it is necessary to add
Was a suffix to the version number:The same names of version targets is used with the
-t/--targetcommand-line option.Syntax modes
Mindcode 3.0 again supports a strict and relaxed syntax modes, but they work different from strict and relaxed syntax modes in Mindcode 2.x.
Relaxed syntax is the default one in Mindcode 3.0. Code which compiled under strict syntax in 2.X (which was the default one in 2.x) compiles under the relaxed syntax in Mindcode 3.0.
Relaxed syntax
Relaxed syntax is useful for shorter scripts, as it requires less boilerplate code.
print("Hello!"); printflush(message1);is a valid source code).cell1orswitch2).$prefix, the variable is external. A place in the heap is assigned to the variable, and the variable is implicitly global.COUNT) and is accessible from all code blocks and functions.Strict syntax
Note
Strict syntax is currently an experimental feature and its rules might still change.
Strict syntax is useful for larger projects, as it enforces additional rules designed to make source code more maintainable. Code adhering to the strict syntax produces the same output when compiled under the relaxed syntax as when compiled under the strict syntax.
beginandendkeywords), or in a function.paramdeclarations do not need to be declared separately (e.g.param message = message1;does not requirelinked message1;to be declared beforehand). These linked blocks can then be accessed in code only via the parameter (messagein this case), not the linked block itself (message1would not be recognized in later code unless explicitly declared).allocate heap/allocate stackdeclarations do not need to be separately declared (e.g.allocate heap in cell1does not requirelinked cell1to be declared beforehand). Linked blocks used inallocatedeclarations cannot be accessed directly, and the specified linked block (cell1in this case) would not be recognized in later code unless explicitly declared.The requirement to declare variables explicitly helps with spotting misspelled variable names, as unknown variable names cause compilation errors, as well as helping identify some cases when a single variable is used for multiple different purposes, as repeated variable declaration also causes compilation errors.
Mixed syntax
To help with a transition of relaxed syntax code to the strict standard, a third
mixedsyntax mode is available. In this mode, code is compiled under the relaxed syntax, but all violations of the strict syntax rules are reported as warnings.Code blocks
Code block is a sequence of expressions or statements enclosed in a larger syntactic element. Code blocks can be nested. For example:
Mindcode now also provides an explicit code block:
Code block defined at the topmost level is called 'main code block' and contains the main program code. At this moment more than one code block is allowed, and in a compiled program the code from the main code block(s) is executed. In strict syntax mode (see below), all executable code must be placed either in a main code block, or in a function:
In relaxed mode, an implicit main code block is created containing all executable code.
Variable declarations
The following types of variables now can be explicitly declared:
Note
Variables created using a declaration are called 'explicit' or 'declared' variables. Variables used in the code without prior declaration are called 'implicit' variables.
Unlike implicit variables, the declared variables are valid in the scope they're declared in: global, main or local. Global variables are accessible from anywhere in the program, main and local variables from the code block they're declared in. It is possible to use names corresponding to linked blocks (e.g.
wave1) for declared variables.When a main or local variable has the same name as a global variable, the global variable is hidden and cannot be accessed in the corresponding code block.
Regular variables
Regular variables are declared using this syntax:
When declaring global variables, these additional modifiers can be used:
noinit: this modifier suppresses the "uninitialized variable" warning for the declared variable. Uninitialized global variables retain the last value assigned to them in the last iteration of the program. This modifier cannot be used if the variable is assigned an initial value.volatile: the compiler assumes that volatile variables can be changed externally and handles them correspondingly. The only known mechanism for external modification of a variables is thesyncinstruction, therefore variables used with this instruction should be declaredvolatile.Modifiers can be specified in any order.
External variables
External variables must be declared in global scope and are therefore always global. External variables can use the
$prefix, but can be declared without it. The$prefix is part of the variable name:$ais different froma.To use external variables, a heap needs to be allocated first using
allocate heapdeclaration. A variable is assigned the lowest unoccupied slot from the heap. If the heap doesn't have enough capacity for the variable, an error occurs.externalis a modifier, and thevarkeyword is optional whenexternalis used. Modifiers can be specified in any order. When declaring external variables, these additional modifiers can be used:cached: the value of the variable is read from the external memory just once at the variable creation and is kept in a processor variable. When using the variable value, the processor variable is used. When assigning a new value to the variable, the processor variable is updated, and the value is also written to the memory. It is assumed that only the current program changes the value of the corresponding external memory slot.noinit: this modifier is only meaningful with thecachedmodifier. When used, the initial value of the variable is not read from the memory slot at all, the variable only allows to write new values to the memory slot. This modifier cannot be used if the variable is assigned an initial value.Cached variables are useful for situations where you want to store latest values in a memory to be reused when the processor is reset. Noinit cached variables are useful for unidirectional sending of data between processors. In both cases, you can read from the variables without any performance penalty, but all writes are automatically propagated to the memory without any explicit code.
Linked variables
Linked variables must be declared in global scope and are therefore always global. When an initial value is not assigned to the variable, the variable identifier is the name of the linked block:
linked cell1;declares acellvariable representing thecell1block linked to the processor. When an initial value is assigned to the variable, the assigned value must be a name of the linked block, while the variable identifier will be used to represent the variable in the program:linked up = switch1, down = switch2;. This is useful to assign symbolic names to linked blocks.A warning is generated if the name of the linked block used in variable declaration is not recognized, however the linked block is created. This way, it is possible to use linked blocks unrecognized by Mindcode (e.g. blocks from a mod).
linkedis a modifier, and thevarkeyword is optional whenlinkedis used. Modifiers can be specified in any order. When declaring external variables, these additional modifiers can be used:noinit: this modifier disables the generation of the guard code (see below).Guard code for linked variables
When declaring a linked variable, Mindcode generates a guard code (single instruction per declared variable) which blocks execution until a block is linked to the processor under the expected name:
compiles to
Additionally, guard code is generated for undeclared linked blocks used in the
allocatedeclaration (e.g.allocate heap in bank1;will generate guard code forbank1). To disable guard code generation in this case, explicitly declare the variable usingnoinitkeyword:Guard code is not generated for linked variables that were not explicitly declared, for linked variables declared with the
noinitmodifier, and when guard code generation is disabled by the#set link-guards = false;compiler directive or the--link-guards falsecommand-line argument.Undeclared linked blocks used as parameter values (e.g.
param memory = bank1;) also do not generate guard code.Variable scopes
Implicit main variables are valid in all code outside functions. Implicit local variables are valid in their entire function.
Explicit variables are limited to the code block they're declared in:
Variable names can be reused in non-overlapping scopes:
Variable resolution can be especially confusing when not using main code blocks:
Properly enclosing the code in main code block makes the actual variable scope much clearer:
For this reason, we strongly suggest to enclose the code in main code block when using variable declarations, and to avoid using the same name for global and main/local variables.
Mixing explicit and implicit variables
In the
relaxedandmixedsyntax modes it is possible to use both explicit and implicit declared variables.When encountering a variable identifier in the relaxed or mixed syntax, Mindcode attempts to resolve the variable using already known variables. If a known variable is not found, an implicit variable, valid for the entire function or all main code blocks, is created. Consequently, the following errors may occur when mixing explicit and implicit variables:
These errors do not arise if all variables using the same name are always declared, or none of them is.
Mlog variable name generation
Implicit and explicit variable names used in source code are translated to mlog using these rules:
.variable(a.prefix):variable(a:prefix):fnX:variable(a:prefix both to the function counter and a variable name)*tmpX(*tmp+ counter):fnXX*retaddr/:fnXX*retval*spIf the same main or local variable is declared multiple times in the same function (in different code blocks), they actually represent different variables within a program. In this case, a unique numerical suffix is appended to variables created in the second and subsequent declarations, separated by
.(a dot):compiles into
Beta Was this translation helpful? Give feedback.
All reactions