cardillan / mindcode Goto Github PK
View Code? Open in Web Editor NEWA high level language for Mindustry Logic and Mindustry Schematics.
Home Page: http://mindcode.herokuapp.com/
License: MIT License
A high level language for Mindustry Logic and Mindustry Schematics.
Home Page: http://mindcode.herokuapp.com/
License: MIT License
The following code doesn't compile:
getlink(index).enabled = false
It is necessary to rewrite it to
device = getlink(index)
device.enabled = false
Supporting direct property access will require updating ANTLR syntax.
I think it would be useful to have break
and next
implemented for loops. (Also, having loop
implemented would be a bit cleaner than having to do while true
all the time).
Thanks for your hard work!
Good evening
I tried to write a function that takes an object type like @ground-factory
and then, it searches the linked blocks for this type. If found, it returns the object:
// Gets the block which is linked to the Processor
// Example: linkedBlock = GetLinkedBlock(@ground-factory)
def GetLinkedBlock(type)
res = null
idxN = 0
thisBlock = getlink(idxN)
while thisBlock != null && res === null
if thisBlock.type == type
res = thisBlock
end
idxN += 1
thisBlock = getlink(idxN)
end
res
end
The function returns 1
if a block is found.
Therefore, I guess that Custom Functions can just return numbers. Is that right?
Thanks a lot, kind regards,
Thomas
Currently, there isn't a boolean negation operator. Both negation operators that are currently defined (!
and not
) compile to an op flip/not
instruction (the operator is called "flip" in GUI and "not" in Mindustry "assembly" language), which produces bitwise negation. This means that the following code
while not switch1.enabled
print("Press the button to start...")
printflush(message1)
end
won't work (switch1.enabled produces 1 when the button is pressed, and bitwise negation makes it into -2).
I propose creating a new unary operator ~
for bitwise negation, and repurposing both !
and not
for boolean negation. However, this change could break existing code. @francois, shall I do this?
Good evening
my mindcode source created more than 1000 Lines of Mindustry Logic instructions (I have tried to create a generic Ressource manager for factories using drones).
Btw.: Good to know: If one tries to import more than 1000 Logic instructions into Mindustry, then the game will silently remove all instructions after the 1000th line :-( Therefore, one starts searching non-existent bugs...
This issue is maybe the result of the AST design, maybe it's a bug. I know programming compiler optimization is hard work and I was not able to find the source of this issue.
I report the problem anyway.
You can close it again as "it's too much work" - after all, we're talking about a game. π
This code:
x = 1
Creates two Mindustry Logic instructions:
set tmp0 1
set x tmp0
end
This optimization would make the compiled code twice as fast ππ
Thanks a lot, kind regards,
Thomas
Good morning @francois
Thanks a lot for all your work!,
I have tried to compile mindcode and used your Native installation guide. Until to the commit from Apr 12, 2021 Permit "indirect" sensor references
compiling works perfectly:
git checkout 03ecee928ce36ae33303e2b37f428c2f63634adb
mvn clean compile exec:java
β¦ everything Ok
But if I move to the next release, Github Commit: Prepared separate web application using Spring Web
I get a compiler error:
git checkout ab1ad052502e8f24a404cc064ca9840316b38534
mvn clean compile exec:java
[INFO] Reactor Summary:
[INFO]
[INFO] mindcode-compiler 1.0.0 ............................ FAILURE [ 3.806 s]
[INFO] webapp 0.0.1-SNAPSHOT .............................. SKIPPED
[INFO] Mindcode 1.0.0-SNAPSHOT ............................ SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.383 s
[INFO] Finished at: 2021-04-20T10:43:38+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:java (default-cli) on project mindcode-compiler: The parameters 'mainClass' for go
al org.codehaus.mojo:exec-maven-plugin:3.0.0:java are missing or invalid -> [Help 1]
β¦
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginParameterException
Unfortunately, I don't know Maven at all, so it's a bit tricky to find the cause. About Java, I know the version is always important - it's fine, I guess:
java.exe -version
openjdk version "11.0.10" 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)
C:\GitWork\Clones\GitHub\Game - Mindustry - mindcode\src [(ab1ad05...)]
mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: C:\Portable\Java-Maven\apache-maven-3.6.3\bin\..
Java version: 11.0.10, vendor: AdoptOpenJDK, runtime: C:\Portable\Java-JDK\jdk-11
Default locale: de_CH, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
I can not attach a html-file with the output of mvn clean compile exec:java -e
and mvn clean compile exec:java -e -X
, therefore I have added a pdf, so that the colors are preserved - this is much easier to read.
mvn clean compile exec_java -e -X.html.pdf
mvn clean compile exec_java -e.html.pdf
I really hope this is just a minor config issue. Please let me know if I can send you more information.
Thanks a lot, kind regards,
Thomas
The PrintMerger optimizer merges print instructions across printflush() calls:
print("foo")
printflush(message1)
print("bar")
printflush(message2)
produces
printflush message1
print "foobar"
printflush message2
end
Hello @francois
Because I constantly had problems recognising the associated if
/ end
in Mindcode and because of the copy/paste I constantly overlooked wrong ==
and =
. Therefore I wrote a small extension for Mindcode for Visual Studio Code to highlight the Mindcode Syntax / Grammar.
I cannot promise that I will be able to maintain it reliably, but at least it is already a help today :-)
Here is a Screenshot of the Extension in VS Code:
Kind regards,
Thomas
Source:
unloader1.config(@copper,0)
unloader1.config(@copper)
Output:
set __tmp0 0
control config unloader1 @copper __tmp0 0 0
sensor __tmp1 unloader1 @config
end
when triangle()
is compiled, it cuts off the last variable. This breaks anything you try to draw using it. triangle(x1,y1,x2,y2,x3,y3)
becomes draw triangle x1 y1 x2 y2 x3
Mindustry-provided function 'lookup' is not implemented.
At this moment, the code produced by Mindcode compiler is mostly Mindustry v6 compatible, although a support for the wait
instruction (which is v7 specific) was already added. For a full v7 support, the following is necessary:
lookup
was already reported - #57, but there's also stop
, packcolor
, some new math operations (asin
, acos
, atan
) and perhaps more.status
World processor instructionThere's a problem in the ImproveConditionalJumps optimizer: it assumes that notEqual
is the opposite operation to strictEqual
, but that isn't true: notEqual
coerces types, and won't therefore distinguish between null
and 0
.
It can lead to compiled code that doesn't work as intended. This code snippet:
if @unit.dead === 0
print("alive")
end
is meant to print "alive" it the @unit
variable is not null
and its @dead
property is equal to 0
(in other words, only if the unit is bound and alive). Optimized code, however, looks like this:
sensor __tmp0 @unit @dead
jump 4 notEqual __tmp0 0
print "alive"
jump 0 always 0 0
end
This will print "alive" even if there's no bound unit (and the @unit
variable is therefore null
).
I think ImproveConditionalJumps shouldn't modify strictEqual
comparisons.
Good morning
In the last two days, I suspected that my mind was slipping because I could no longer do the math. What a relief that the optimizer is probably a little too active in the variable initialization:
With this code:
x = 1
print("\n x: ", x)
print("\n x+x: ", x+x)
the compiler does not initialize the variable x
, but it calculates afterwards with the uninitialized variables to get x+x
:
set __tmp2 "\n x+x: "
print "\n x: "
print 1
op add __tmp3 x x
print __tmp2
print __tmp3
end
For the other readers: This small workaround (let's the compiler calculate the variable x
by adding 0
) solves the problem:
x = 1 + 0
print("\n x: ", x)
print("\n x+x: ", x+x)
Thanks a lot, kind regards,
Thomas
Following code does not compile when break statement included. When commented out, compiles.
allocate stack in cell1
n = 0
reactor = getlink(n)
lowest = 1
while reactor != null
print("type: ", reactor.type)
if (reactor.type != @thorium-reactor)
print("not reactor!")
break
end
pct_avail = reactor.cryofluid / reactor.liquidCapacity
lowest = (pct_avail < lowest) ? pct_avail : lowest
// print(n, ": pct_avail is: ",pct_avail,"\n")
reactor.enabled = pct_avail >= 0.25
n += 1
reactor = getlink(n)
end
print("lowest is: ",lowest)
printflush(message1)
As the title says, there isn't any information about the need of a PostgreSQL database in the README. The first time I tried to run it locally I spent some time trying to figure out why it didn't work.
Also, please add a note about the JDBC_DATABASE_URL
in the readme, and how to pass credentials with it. (for example, adding ?user=<user>&password=<password>
to the end of the URL)
I plan to implement the following restructuralizations as part of this issue:
mindcode.bat
will be created to run the command line compiler in Windows,mindcode
script for Linux will be updated to reflect the change of path to compiler jars -- the change is simple, but I won't be able to test it after the change.input :
ubind(@mega)
uradar(enemy,any,any,true,distance,e)
if e
if e === null
pass
else
if distance < 25
target(e.x, e.y, true)
print("state: attacking,")
end
end
end
result :
ubind @mega
jump 11 notEqual e true
jump 4 notEqual e null
jump 10 always 0 0
jump 10 greaterThanEq distance 25
sensor __tmp7 e @x
sensor __tmp8 e @y
ucontrol target __tmp7 __tmp8 true 0 0
print "state: attacking,"
plus if you put uradar in a if statement it outputs this
uradar enemy any any true distance e __tmp0
jump 12 notEqual __tmp0 true
in uradar adding __tmp0 is invalid.
Good evening
I have tried to use the max() function and I've got this error:
a = max(1,2)
Don't know how to handle function named [max]
Therefore I have tested all Mindustry Logic op
commands and I guess that those are missing: (I have created a task list if someone would like to fix them :-))
op log10 result param1 param2
op noise result param1 param2
op len result param1 param2
op angle result param1 param2
op max result param1 param2
op min result param1 param2
op and result param1 param2
op xor result param1 param2
op shl result param1 param2
op shr result param1 param2
op idiv result param1 param2
Kind regards,
Thomas
uradar(enemy,any,any,distance,0,1,e)
when put ouside if statement isn't compiled gives nothing
This code doesn't compile:
if a 1 elsif b 2 end
whereas this does:
if a 1 elsif b 2 else 3 end
The behavior is identical with and without optimization. Is it designed like this, or should the else branch be optional after the elsif branch?
The expression a = (b > c) ? 1 : (d > e) ? 2 : 3
, when compiled, produces somewhat unexpected parse tree:
rest=Seq{
rest=NoOp{},
last=Assignment{
var=VarRef{name='a'},
value=IfExpression{
condition=IfExpression{
condition=BinaryOp{left=VarRef{name='b'}, op='>', right=VarRef{name='c'}},
trueBranch=NumericLiteral{literal='1'},
falseBranch=BinaryOp{left=VarRef{name='d'}, op='>', right=VarRef{name='e'}}
},
trueBranch=NumericLiteral{literal='2'},
falseBranch=NumericLiteral{literal='3'}
}
}
}
Turns out the code was parsed this way (added parentheses for clarity)
a = ((b > c) ? 1 : (d > e)) ? 2 : 3
,
while I'd expect it to be
a = (b > c) ? 1 : ((d > e) ? 2 : 3)
.
With huge help from Google, I found out that this change
expression : indirectpropaccess # indirect_prop_access
| propaccess # property_access
- | cond=expression QUESTION_MARK true_branch=expression COLON false_branch=expression # ternary_op
+ | cond=expression QUESTION_MARK (true_branch=expression COLON false_branch=expression) # ternary_op
| case_expr # case_expression
| if_expr # if_expression
would do the trick (I took the idea from Stackoverflow - it is a different problem, but the parentheses in ternary op definition are there). I don't think I fully comprehend the change, but it seems to work pretty well. Specifically, a parse tree of this abomination
a = (x > y)
? (b > c) ? (d > e) ? 1 : 2 : (f > g) ? 3 : 4
: (h > i) ? (j > k) ? 5 : 6 : (l > m) ? 7 : 8
works as I'd expect - it evaluates the "innermost" ternary operators first. For reference, the resulting parse tree is
rest=Seq{
rest=NoOp{},
last=Assignment{
var=VarRef{name='a'},
value=IfExpression{
condition=BinaryOp{left=VarRef{name='x'}, op='>', right=VarRef{name='y'}},
trueBranch=IfExpression{
condition=BinaryOp{left=VarRef{name='b'}, op='>', right=VarRef{name='c'}},
trueBranch=IfExpression{
condition=BinaryOp{left=VarRef{name='d'}, op='>', right=VarRef{name='e'}},
trueBranch=NumericLiteral{literal='1'},
falseBranch=NumericLiteral{literal='2'}
},
falseBranch=IfExpression{
condition=BinaryOp{left=VarRef{name='f'}, op='>', right=VarRef{name='g'}},
trueBranch=NumericLiteral{literal='3'},
falseBranch=NumericLiteral{literal='4'}
}
},
falseBranch=IfExpression{
condition=BinaryOp{left=VarRef{name='h'}, op='>', right=VarRef{name='i'}},
trueBranch=IfExpression{
condition=BinaryOp{left=VarRef{name='j'}, op='>', right=VarRef{name='k'}},
trueBranch=NumericLiteral{literal='5'},
falseBranch=NumericLiteral{literal='6'}
},
falseBranch=IfExpression{
condition=BinaryOp{left=VarRef{name='l'}, op='>', right=VarRef{name='m'}},
trueBranch=NumericLiteral{literal='7'},
falseBranch=NumericLiteral{literal='8'}
}
}
}
}
}
@francois, shall I create a PR with this grammar modification? I'm asking specifically because it has the potential to break existing Mindcode code.
Good evening
This is a nice to have suggestion.
It's great that mindcode abstracts the mindustry logic, but with the sensor function, it would be great if one could call it directly. The background is that sometimes things are computed at runtime. For example, we dynamically calculate which resource is required. Next, we must know if a building contains this resource:
// At runtime, we have calculated that we need lead
RequiredRessource = @lead
// How can we test if a building contains this resource?
// Something like this would be great:
RessourceStock = sensor(factory1, RequiredRessource)
// The actual solutions is verbose:
RscStock = case RequiredRessource
when @silicon
factory1.silicon
when @lead
factory1.lead
β¦
end
I find the possibility that abstraction can also make things more cumbersome interesting. I was never aware of that before.
The following code
alive = @unit.dead === 0
if alive
print(alive)
end
compiled with optimization produces:
sensor __tmp0 @unit @dead
jump 4 notEqual __tmp0 0
print alive
jump 4 always 0 0
end
A correct result would be more akin to this:
sensor __tmp0 @unit @dead
op strictEqual alive __tmp0 0
jump 4 equal alive 0
print alive
jump 4 always 0 0
end
I don't think it's caused by dead code elimination, as alive
is clearly used. Other optimization probably should only remove variables that are created by the compiler itself (the __tmp
ones) -- that could be an easy check to add.
I'll try to fix the issue, I'm putting it here for reference.
(Edited to fix the examples.)
Same function, when it has a parameter, even if unused, compiles. When it does not, error:
Syntax error: [@42,182:184='def',<5>,17:0] on line 17:0: mismatched input 'def' expecting <EOF>
Example code:
allocate stack in cell1
def delay(n, fps)
_x = 0
deadline = @tick + n * fps
while @tick < deadline
_x += 1
end
end
def delay2(n)
print("test")
end
def delay3()
print("test")
end
delay(1, 60)
delay2(1)
delay3()
Good evening @francois
if I understand Custom Functions the right way and they are able to return a result:
allocate stack in cell1
// Just return the number 123
def test(n)
123
end
then Custom Functions are broken :-(
// res = test(1)
is activated then the script stops workingallocate stack in cell1
// Just return the number 123
def test(n)
123
end
print("\nInitializing App")
printflush(message1)
// If the following line is activated, then the script stops working
// res = test(1)
print("\ntest: ", res)
ProcessLoop += 1
print("\nProcessLoop: ", ProcessLoop)
printflush(message1)
Thanks a lot, kind regards,
Thomas
uradar
's result variable gets replaced by a temporary variable - which is promptly never used again, meaning I need to edit the output code to use it. I can't use the optimizer, since uradar
disappears completely with it.
ubind(@mono)
uradar(enemy, any, any, distance, 0, 1, result)
print(result.x)
printflush(message1)
...will compile into uradar enemy any any distance __tmp0 __tmp1 __tmp2
. __tmp2
is never seen again - result
is correctly used in later instructions though.
By the way, I think the reason it gets removed in optimization is because __tmp2
flags the whole line as redundant since it's never referenced again, even through it shouldn't be there in the first place. It's not an issue with the optimizer, rather the compiler itself.
Just an idea I had: inline functions. A bit like macros, they would replace the invocation of said function with a copy of the function.
This would serve two purposes: you wouldn't need a stack (or memory) and they could also return values other than numbers; they could also return objects.
Obviously, they couldn't be used in recursion.
Good afternoon
I just have a side note: I have found a somewhat troublesome oddity in the parser, it stumbles if we comment out when
:
// This Code generates:
// Syntax error: [@3,6:9='case',<3>,2:0] on line 2:0: mismatched input 'case' expecting
n = 1
case n
// when 1
when 2
print(2)
end
Thanks a lot, kind regards,
Thomas
They are not provided anything as it should be by they give an error
Good afternoon
If users come directly to Mindcode and do not study the Mindustry Logic commands first, then the difference between ==
and ===
is unclear.
Could you please describe it in the Syntax?
Thanks a lot, kind regards,
Thomas
Good evening
Unfortunately, I had overlooked that mindode does not understand the bitwise not operator
. The Mindustry Game calls it Flip
in its GUI, but the Mindustry Logic command is called as usual op not
:
set TestVar 0xf
op not Result TestVar b
print TestVar
print Result
// Printed output (as expected):
15
-16
Thanks a lot, kind regards,
Thomas
ore1 = @lead
ore2 = @coal
container = container1
o1 = container.ore1
o2 = container.ore2
ore = o1>o2? ore2 : ore1
generated
sensor o1 container @ore1
sensor o2 container @ore2
jump 16 notEqual o2 true
set __tmp9 ore2
jump 17 always 0 0
set __tmp9 ore1
op greaterThan ore o1 __tmp9
It should be something like
sensor o1 container @ore1
sensor o2 container @ore2
jump 16 lessThanEq o1 o2
set ore ore2
jump 17 always 0 0
set ore ore1
I compile this code:
CENTER = foundation1
if uradar(enemy,any,any,distance,0,1,rslt)
if len(rslt.x - @unit.x,rslt.y - @unit.y) < 20
end()
end
end
if ulocate(damaged, dmgx, dmgy, dmgbuilding)
approach(dmgx, dmgy, 5)
target(dmgx, dmgy, true)
else
approach(CENTER.x + 10 * sin(@tick), CENTER.y + 10 * cos(@tick), 2)
end
and the result contains the following lines:
jump 14 always 0 0
jump 15 always 0 0
They are both jumps to the very next line, and would be very unneccesary(and will slow down the processor).
They should be deleted by the optimizer.
This code(again):
CENTER = foundation1
if uradar(enemy,any,any,distance,0,1,rslt)
if len(rslt.x - @unit.x,rslt.y - @unit.y) < 20
end()
end
end
if ulocate(damaged, dmgx, dmgy, dmgbuilding)
approach(dmgx, dmgy, 5)
target(dmgx, dmgy, true)
else
approach(CENTER.x + 10 * sin(@tick), CENTER.y + 10 * cos(@tick), 2)
end
compiled, the last 3 lines are:
set __tmp27 2
ucontrol approach __tmp21 __tmp26 __tmp27 0 0
end
That is redundant: we can eliminate __tmp27 and run ucontrol approach __tmp21 __tmp26 2 0 0
instead.
Summing up: ANY not-changed temporary variables should be eliminated
PS: I know Java, and I can help make a PR(and make commits) if you want(altho I have very little time)
Variables passed to the getlink function aren't considered used and are eliminated by optimization. For example, this code:
index1 = 1
index2 = 2
print(index2)
block0 = getlink(0)
block1 = getlink(index1)
block2 = getlink(index2)
print(block0)
print(block1)
print(block2)
compiled with optimization produces this output:
set index2 2
print index2
getlink block0 __tmp2
getlink block1 index1
getlink block2 index2
print block0
print block1
print block2
end
The output is missing set instructions to set index1 and __tmp2 variables. Setting index2 is included, as it figures in the print instruction.
A workaround is to use other operation to mark the variable as used, as demonstrated with the index2 variable.
Good evening
I am afraid that this is a problem of the Mindustry programming language... I report it anyway. Either as information for other mindcode users or maybe as a bug report.
I created this Test scenario:
On startup, the code searches all blocks which are linked to the processor
The found Switch-Block is dynamically assigned to the variable SwitchBlock
message1 just displays the value of the variable SwitchBlock
: is it == null
or != null
?
After some seconds, the SwitchBlock is removed from the Map
Now, we have the issue: The variable SwitchBlock
does not reflect the removed Switch-Block: it is still not null:
I tested it using this Code:
// message1 is used to display Debug Messages
Msg1Block = message1
// Will be executed *just once*
if ProcessorLoop == null
ProcessorLoop = 0
// Search the Switch-Block, which is assigned to the Processor
idxN = 0
thisBlock = getlink(idxN)
while thisBlock != null
if thisBlock.type == @switch
// We've found the Switch-Block - assign it to a Variable
SwitchBlock = thisBlock
end
idxN += 1
thisBlock = getlink(idxN)
end
end
// Just display a heartbeat :-)
print("\n", ProcessorLoop)
// During this test, the referenced SwitchBlock will be removed from the Game-Map
// therefore, SwitchBlock *should* get null - but it does not:
if SwitchBlock == null
print ("\nTest result: SwitchBlock == null")
else
print ("\nTest result: SwitchBlock != null")
end
printflush(Msg1Block)
// Count Processor Loops
ProcessorLoop += 1
Thanks a lot, kind regards,
Thomas
for example:
allocate stack in bank1
def T(n)
if n>0
print(n)
T(n-1)
print(n)
end
end
T(2)
printflush(message1)
in this case, n becomes a local. I would expect the output of this program to be: 2112
but it is not, and it seems like n is being globally altered in the recursive function, which makes sense in Logic. The project seems to go though much effort to push return addresses and parameters on the stack, but locals are not maintained (it seems).
Am I understanding this wrong? Did I write my program above incorrectly to expect 2112 as the output? Although I haven't figured out why... the program actually prints "20" and that's it. If I do T(3) it will print "30" and that's it.
I am interested in understanding this better!
Originally posted by @TheAtomAnt in #34
The priority of operators, as currently defined, is somewhat unusual. In Mindcode, we have:
? :
=
, /=
, **=
, -=
, +=
, *=
**
!
, not
(see also #72 for this)*
, /
, \
, %
+
, -
<<
, >>
<
, <=
, >
, >=
==
, !=
, ===
&
, |
, ^
and
, &&
or
, ||
-
(this isn't working at the moment, but let's ignore it)Some of this can be a bit surprising. Compared to other languages, both the ternary operator and assignments are way too high. The most obvious example I stumbled upon is a = b > c ? 0 : 1
, which gets compiled to a wee bit unusual a = b > (c ? 0 : 1)
. I don't use assignments as expressions much, but it would in all probability behave in similarly unexpected ways.
I propose changing the order to a more common one (I tried to do it according to Ruby):
!
, not
, ~
**
-
(I'll try to make it work while at it)*
, /
, \
, %
+
, -
<<
, >>
&
|
, ^
(this would mean splitting the binop_bitwise_op
category in two, all others are just reordering of existing terms)<
, <=
, >
, >=
==
, !=
, ===
and
, &&
or
, ||
? :
=
, /=
, **=
, -=
, +=
, *=
@francois, as this is again a code-breaking change (hopefully last from me for some while), would you be ok with me implementing this?
I tried to use elsif
the other day. The compiler didn't throw any warnings or errors, and seemed to produce valid output, but the code didn't work.
Unless I made a mistake: I think it would be useful if either the compiler throws an error when it encounters elsif
, or just implement it.
Good evening @francois
thanks a lot for the compiler optimizer!, it is very powerful, I am testing it...
I have noted a strange behaviour with indirect heap allocation:
cell3
and not HEAPPTR
// Source
HEAPPTR = cell3
allocate heap in HEAPPTR
$a = 1
$b = 2
$c = 3
// The compiler uses 'cell3' and not 'HEAPPTR' for the 1st command:
write 1 cell3 0
write 2 HEAPPTR 1
write 3 HEAPPTR 2
end
// Source
HEAPPTR = cell3
allocate heap in HEAPPTR
print($a)
$a = 1
$b = 2
$c = 3
// here, the compiler always use 'HEAPPTR' :-)
set HEAPPTR cell3
read __tmp1 HEAPPTR 0
print __tmp1
write 1 HEAPPTR 0
write 2 HEAPPTR 1
write 3 HEAPPTR 2
end
Thanks a lot, kind regards,
Thomas
the input
ulocate(building,core, false, outx, outy,found,myCore)
generates
ulocate building core false @copper outx outy __tmp10 found
I think it should be
ulocate building core false @copper outx outy found, myCore
It looks like it has decided to hard code the found parameter of ulocate to a new temporary variable to use it as the result.
If thios is a deliberate descision then perhaps it could be documented in the syntax?
This is about a feature I plan to add to Mindcode, although it probably will take some time.
My typical workflow with Mindcode is currently centered around code development. I write and compile code, then paste it into some processor in one of my game saves to test it, and when it looks good I update the schematics containing the entire setup. This is sometimes bothersome - I might forget whether I've updated a particular schematics, I might need to build the schematics afresh to get the processor and all contained blocks to an initial state, and I need to type the name again when saving the updated schematics back.
Therefore I'm going to create a schematics builder. It would provide two main functionalities:
Obviously there would be a command-line version for both of these functions, but since inputs and outputs are both texts, it is quite straightforward to add support to the webapp as well.
The usage I envision is this:
It should be possible - and quite simple - co create simpler schematics definition by hand from scratch, for example if the schematics should contain just the processor and a few basic objects (switch, message, memory cell).
Schematics structure isn't that complicated: basically it is a list of tiles with their positions, contained types, rotation and block type-specific configuration. Processor code and linked blocks are encoded in this configuration.
At this point I'm not sure what format or syntax to use for the schematics definition. Initial version should allow to:
Some future version might provide additional functionality to:
Hello François
thank you very much for your great work!,
The syntax of the Mindustry Logic and the behavior of the commands is often terrible and so it is ingenious to have mindcode to fix the behavior of the Mindustry Logic commands :-)
It's great to have SW developers who knows how to program a compiler :-)
I have a question:
Here, we define the name of the assigned Memory-Cell/-Bank Block to cell1
:
allocate heap in cell1[0 ... 16], stack in cell1[16 ... 64]
Because the name of this block can change in the game, it would be useful if we could something like this:
memBlockName = "cell2"
allocate heap in memBlockName[0 ... 16], stack in memBlockName[16 ... 64]
Because this code does not work, I guess it is not possible,
You already use $
as a prefix for global variables. Maybe you could define a prefix that defines a Text-Macro (which just replaces a keyword by its replacement string before the Code will be compiled), e.g.
// The Compiler will replace `#memBlockName` with `cell2` before it startes compiling the code
#memBlockName = "cell2"
allocate heap in memBlockName[0 ... 16], stack in #memBlockName[16 ... 64]
Maybe a text macro function would open more useful possibility... But maybe it is also a stupid idea.
Thanks a lot, kind regards,
Thomas
this: uradar(enemy,any,any,distance,0,1,rslt)
generates this:
set __tmp0 0
uradar enemy any any distance __tmp0 __tmp1 __tmp2
where __tmp0 is supposed to be the order, __tmp1 should be the found
output, and __tmp2
should be the dest.
However, the processor UI shows:
"target enemy and any and any order __tmp1 sort distance outpot __tmp2
That is, __tmp0 is ignored, and __tmp1 is used as the order
input, which is NULL.
Furthermore, this, used as an if
condition, jumps over the statement if (tmp2!=true),
it should actually be (tmp2===null).(Don't rely on automatic type conversion unless you must!)
The if expression generates jump to the else branch by comparing the value of the condition expression to true
:
However, true
in Mindustry 7 is a constant equal to 1
. The else branch is therefore executed only if the condition evaluates to something other than 1. The expected behavior is that the else branch is executed when the condition evaluates to 0.
While expression has an identical issue.
The fix is easy:
pipeline.emit(new LogicInstruction("jump", elseBranch, "equal", cond, "false"));
This might require some changes to keep the optimizers responsive to the generated code, though.
Currently, these functions don't work and using them results the error Unknown ucontrol opcode
.
payTake
payDrop
boost
pathfind
idle
stop
They already are handled in LogicInstructionGenerator
, but aren't handled by DeadCodeEliminator#visitUcontrol
, where the exception is thrown.
https://github.com/francois/mindcode/blob/cc56523ce82547292f802023ec458727a47ca69d/src/main/java/info/teksol/mindcode/mindustry/DeadCodeEliminator.java#L293-L343
Mindcode allows to use escaped double quotes in string literals, like this:
print("\"Hi!\"")
However, Mindustry Logic doesn't support double quotes in strings, escaped or not, in any form - it refuses pasted code completely if it contains them. Mindustry 7 replaces double quotes with single quotes when entered via user interface, so Mindcode was updated to replace double quotes inside strings with single quotes as well.
Do not use double quotes in strings, though, the support for them might be completely removed in the future.
The following code
inline def d(n)
n
end
print(1 < d(2))
printflush(message1)
produces
op lessThan __tmp1 1 __fn0_n
print __tmp1
printflush message1
end
The FunctionParameterOptimizer mistakenly removes assignment to function parameter __fn0_n
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.