Replies: 9 comments 5 replies
|
Two more brief ideas:
|
|
Wow! You have a lot of ideas for improvement.
I dislike the current system. I'd prefer that all variables declared outside a method (in the top level) are considered global. There should be a main function (def main) (case insensitive) which is the program's entry point. Rather than putting all code at the top (global) level. If you don't have main, then you might make every line of code at global scope automatially "in main"- this is a copy of what C# does recently. So if you have a variable in main, it's local. If it is outside of main, it's global. Done.
Never used external variables (don't know what these are) but sounds like you want a declare statement for these (based on later ideas you mention)
Yeah, I think
Dislike the word allocate here because two CPUs might be sharing memory and it sounds like this CPU is authorative when it is not. Declare makes sense. Though we might have a lot of declares... You'll need
I think it is good form to copy these linked components to named variables in the code anyway. You can achieve both with the right declare statements. There is a gotcha here though. My prefered code structure is If you don't put the copy of linked components in the loop, those links will break if the relevant structures are built after the CPU starts looping (or if they are destroyed and replaced). |
|
Enums Might be useful to have a function say int() which outputs 0,1,2,3 for different enum labels. And one say str() which outputs the relevant tag as a string for debugging.
You could achieve this (probably) with a "pointer" being a pair of - a link to the relevant array function (jump table) and the length of the array. From there you can dynamically compute the jumps required. Length can also be used for range checks. Structs would indeed be nice to have. |
|
@tom-leys Thanks for your feedback! Having these conversations helps really a lot. I think it is time I flesh out my objectives explicitly here:
This makes sense, and having a main function would automatically enforce a nice structure of declarations, but I don't want to have to support two different ways of doing this. Given the choice I'll opt for global scope main code. A small plus is that variable names in functions are mangled, while variable names outside functions are not, which is consistent and feels intuitive. Code blocks will allow you to enclose the main code in
As there would be no code outside of main, global variables would have to be declared anyway - there would be no other way to put them there. So having to declare globals explicitly seems natural now.
External variables represent memory cell/bank slots. More about them is here: Variables and constants. In Mindcode as designed by @francois, no variables were declared, even the external ones. So they needed the prefix to be identifiable. I still kinda like it - they're such a different beasts that having them stand out in the code seems useful to me. I'm now tending towards declaring them explicitly, in which case the prefix can be dropped. Again, users can choose whatever convention they want for them.
I originally wanted to do this, but as there isn't any string manipulation in mlog whatsoever, everything needs to be resolved at the compile time. I couldn't handle the However, maybe I could keep just A global replace of
I'll keep
There's a particular problem, though: say I use I might allow to declare linked blocks explicitly, say
Yes, I've run into this as well. I don't think this can be resolved at the language level, but I'll add a chapter to tips and tricks. I usually load blocks dynamically to solve both delayed building and dynamic block linking (where the name isn't fixed anyway) issues: |
|
I'll create issues for individual topic where some concrete idea has already emerged. Relevant passages in the original post will be replaced with a reference to the specific issue. |
|
Updated the initial post to reflect current developments. |
|
I've updated the priorities a bit. I want to introduce processor-variables backed arrays as soon as possible, since I believe that currently it is a feature which will bring the greatest benefit. While pondering the implementation I realized that arrays of records/structures would be very useful performance-wise. Storing structure members in several separate variables would mean that retrieving each member at given index would require separate function call, while accessing a structure in an array would require just one function call. There will still be difficulties and optimization challenges, but structures will have additional benefits, e.g. for function return values. |
|
Updated the initial after the pre-release of Mindcode 3.0. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Preamble
This describes currently contemplated upcoming changes to Mindcode. Comments and suggestions are welcome.
The document is updated occasionally. Already implemented changes are removed from this description during updates.
Change in default language target
The default language target will be bumped to
8as soon as regular Mindustry 8 release is made.Roadmap
A broad plan for the next few releases. Everything may change, though.
See changelog in the development branch for a list of features ready for the upcoming release.
Upcoming release
Changes intended for the next regular release.
breakin code blocksNext releases
These are topics that I'm spending time thinking about. One of these should appear in the next release after the upcoming one.
end()funcion should avoid them (and should, therefore, be implemented as ajumpand not asend). Candidates for initialization code:Active
These are topics that I'm currently planning to implement.
Small tasks backlog
These are relatively small tasks that might be slipped in when I feel like it.
Shelf
These are topics that I've spent some time thinking about and still want them, but they're in a distant future at best.
fallthroughandyieldin case expressionsIssue details
Autolinked variables
Support for declaring a variable as a block of a certain type, e.g.
Mindcode would generate code to iterate through linked blocks and automatically assign them to variables:
msgwould be assigned the first block of type@messagebuttonwouldRefactoring of Mindustry Logic functions
Implementing namespaces would allow better organization of Mindcode functions into related groups (e.g., separate namespace for world-processor functions).
The current system would be accessible in one namespace for backwards compatibility, new systems would come with their own namespaces.
Redesign of optimization options
Instead of configuring optimization by individual optimizer, allow each optimization to be configured independently. The options would be structured hierarchically, e.g.:
opt.if-expression.value-propagationopt.if-expression.instruction-propagationopt.if-expression.forward-assignmentopt.data-flow.preserve-globalsopt.data-flow.preserve-mainopt.data-flow.constant-foldingopt.data-flow.constant-foldingopt.print-merging.use-formatPossible values in the set directive would be
on,offandforce.forcewould force the optimization even when it would be deemed dangerous by the optimizer (e.g., print merging using theformatinstruction in presence of{0}string literals).#setdirectives will set all values in given subtree, e.g.Furthermore, the general optimization levels won't be used to choose the optimization 'intrusiveness' or 'riskiness,' but to choose how much effort is put into optimizations. On lower levels, more expensive optimizations (in terms of compiler/optimizer effort) will be skipped.
fallthroughandyieldin case expressionsThe
fallthroughkeyword can be used in awhenbranch incaseexpression to transfer the control to the next branch:When
numberis 1, the code will print "onetwo". Whennumberis 2, the output will be just "two".fallthroughcan be used anywhere in thewhenbranch, for example, inside anifstatement.The
yieldkeyword can be used in a when branch in case expression to terminate the evaluation of the case expression and provide the resulting value (the code will output "even"):The value after
yieldwill be optional; when not given, the resulting value of the case expression will benull.Memory model
Optimizations of external variables are planned for the future. These should prevent unnecessary reads and writes from/to memory blocks. To help the compiler with these optimizations, it will be possible to assign a memory block or a variable one of three possible memory models:
volatile: this means that the external memory may be modified by another processor, and therefore reads and writes from/to this memory must not be eliminated from the code.aliased: this means that another processor will not modify the external memory, but the memory block might be accessed using two different variables.restricted: this means the memory block will never be accessed using two different variables.A memory model can be assigned to a memory block, or to a concrete slot inside a memory block. Model assigned to a slot has precedence over a model assigned to the whole block. Conflicting assignments on a block or slot level cause compilation error. Declaring a variable as restricted when it can be inferred from a code it is actually aliased causes a compilation error.
Example (the syntax is outdated and wonky):
Enums
It will be possible to declare enums using the
enumkeyword:Mindcode will assign values to the enums as it sees fit. There are no guarantees on the numbers whatsoever, except preserving the declaration order. They could be instruction addresses inside a case expression, for example, if there's just one case expression.
Mindcode will provide functions to access enum properties (e.g.
element.name,element.next,element.previous). They might be a bit costly to use.Support for enums in list iteration Loops:
for i in enum_name.Function pointers
Note
This text is outdated and doesn't incorporate the upcoming adoption of types in Mindcode and the possibility of implementing lambdas/function pointers through interfaces.
Function pointers would allow storing a function address in a variable and calling the function through that variable. The internal mechanism is briefly described in the road map.
Assigning a function address to a variable could happen in several ways:
All reactions