FeatureRequest: Functions
RotzRohr opened this issue · 15 comments
Why do we need functions?
Bc that would help players make the code more readable
Here is how i would implement functions
For normal players
Functions can only be called in a main function
So it would look like this
name "SimpleFunction"
EVERY 20 TICKS DO
RUN FUNCTION A
END
FUNCTION A
-- do something
END
So calling a Function in a function would not be possible
Why? Bc otherwise players could create loops which crash the server
Lets say a player knows what he does
Then he can create Advanced Functions which can be called in loops how often the player wants
Maybe also make a gamerule to disallow that (For servers)
This would look like this
name "AdvancedFunction"
EVERY 20 TICKS DO
RUN FUNCTION A
END
AFUNCTION A
-- do something
RUN FUNCTION B
END
AFUNCTION B
-- do something
END
Obviously whis would also allow this
name "MixedFunction"
EVERY 20 TICKS DO
RUN FUNCTION A
END
FUNCTION A
-- do something
RUN FUNCTION B
END
AFUNCTION B
-- do something
END
But what would the actual use of functions be? SFM doesn't have variables or return values, pretty sure it can't do math so there's no (good) way to limit recursion.
I could limit recursion without giving the language math capabilities, but yeah I'm not sure what the use case is
The use case:
given this code
name "Worker"
EVERY 100 TICKS DO
FORGET
INPUT FROM ItemInput_SaltDust
OUTPUT TO EACH Electrolyzer_Chlorine TOP SIDE
FORGET
INPUT FROM Electrolyzer_Chlorine BOTTOM SIDE
OUTPUT TO EACH ItemBuffer_SD
FORGET
INPUT fluid:: FROM Electrolyzer_Chlorine BOTTOM SIDE
OUTPUT fluid:: TO EACH FluidBuffer_Chlorine
FORGET
INPUT FROM ItemInput_NickelOre
OUTPUT TO EACH MaceleratorFrom_NickelOre_To_RawNickel TOP SIDE
FORGET
INPUT FROM MaceleratorFrom_NickelOre_To_RawNickel BOTTOM SIDE
OUTPUT TO ItemBuffer_RawNickel
FORGET
INPUT FROM ItemBuffer_RawNickel
OUTPUT TO MaceleratorFrom_RawNickel_To_NickelDust TOP SIDE
FORGET
INPUT FROM MaceleratorFrom_RawNickel_To_NickelDust BOTTOM SIDE
OUTPUT TO ItemBuffer_NickelDust
FORGET
INPUT FROM ItemInput_RawIron
OUTPUT TO EACH CentrifugeFrom_RawIron_To_ManganeseCrushedDust TOP SIDE
FORGET
INPUT FROM CentrifugeFrom_RawIron_To_ManganeseCrushedDust BOTTOM SIDE
OUTPUT iron_dust TO ItemBuffer_IronDust
OUTPUT manganese_crushed_dust TO ItemBuffer_ManganeseCrushedDust
FORGET
INPUT FROM ItemBuffer_ManganeseCrushedDust
OUTPUT TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM FluidBuffer_SulfuricAcid
OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM FluidInput_SulfuricAcid
OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM ChemicalReactor_MSS BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_MSS
FORGET
INPUT fluid:: FROM FluidBuffer_MSS
OUTPUT fluid:: TO Electrolyzer_MTD TOP SIDE
FORGET
INPUT FROM Electrolyzer_MTD BOTTOM SIDE
OUTPUT TO ItemBuffer_MTD
FORGET
INPUT fluid:: FROM Electrolyzer_MTD BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_SulfuricAcid
FORGET
INPUT FROM ItemBuffer_MTD
OUTPUT To Packager_MD TOP SIDE
FORGET
INPUT FROM ItemBuffer_CTD
OUTPUT To Packager_CD TOP SIDE
FORGET
INPUT FROM Packager_MD BOTTOM SIDE
OUTPUT TO ItemBuffer_MD
FORGET
INPUT FROM Packager_CD BOTTOM SIDE
OUTPUT TO ItemBuffer_CD
FORGET
INPUT FROM ItemBuffer_CCD
OUTPUT TO ChemicalReactor_CHS
FORGET
INPUT fluid:: FROM FluidBuffer_HA
OUTPUT fluid:: TO ChemicalReactor_CHS
FORGET
INPUT fluid:: FROM ChemicalReactor_CHS BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_CHS
FORGET
INPUT fluid:: FROM FluidBuffer_CHS BOTTOM SIDE
OUTPUT fluid:: TO Electrolyzer_CTD TOP SIDE
FORGET
INPUT FROM Electrolyzer_CTD BOTTOM SIDE
OUTPUT TO ItemBuffer_CTD
FORGET
INPUT fluid:: FROM Electrolyzer_CTD
OUTPUT fluid::hydrogen TO FluidBuffer_Hydrogen
OUTPUT fluid::chlorine TO FluidBuffer_Chlorine
FORGET
INPUT FROM ItemInput_Redstone
OUTPUT TO EACH Centrifuge_RD TOP SIDE
FORGET
INPUT FROM Centrifuge_RD BOTTOM SIDE
OUTPUT ruby_dust TO ItemBuffer_RD
OUTPUT iron_dust TO ItemBuffer_IronDust
OUTPUT quartz_dust TO ItemBuffer_QD
OUTPUT neodymium_tiny_dust TO ItemBuffer_NTD
FORGET
INPUT FROM ItemBuffer_RD
OUTPUT TO EACH Centrifuge_CCD TOP SIDE
FORGET
INPUT FROM Centrifuge_CCD BOTTOM SIDE
OUTPUT chromium_crushed_dust TO ItemBuffer_CCD
OUTPUT aluminum_dust TO ItemBuffer_AD
FORGET
INPUT fluid:: FROM FluidBuffer_Hydrogen
OUTPUT fluid:: TO ChemicalReactor_HA
FORGET
INPUT fluid:: FROM FluidInput_Hydrogen
OUTPUT fluid:: TO ChemicalReactor_HA
FORGET
INPUT fluid:: FROM FluidBuffer_Chlorine
OUTPUT fluid:: TO ChemicalReactor_HA
FORGET
INPUT fluid:: FROM ChemicalReactor_HA
OUTPUT fluid:: TO FluidBuffer_HA
END
EVERY 400 TICKS DO
INPUT FROM ItemBuffer_NickelDust
OUTPUT TO MixerMain TOP SIDE
FORGET
INPUT FROM ItemBuffer_IronDust
OUTPUT TO MixerMain TOP SIDE
FORGET
INPUT FROM ItemBuffer_MD
OUTPUT TO MixerMain TOP SIDE
FORGET
INPUT FROM ItemBuffer_CD
OUTPUT TO MixerMain TOP SIDE
END
EVERY 100 TICKS DO
INPUT FROM MixerMain BOTTOM SIDE
OUTPUT TO ItemOutput_SSD
END
EVERY 10 TICKS DO
INPUT forge_energy:: FROM Energy SOUTH SIDE
OUTPUT forge_energy:: TO EACH NeedsEnergy TOP SIDE
END
As we can see it has no structure at all
Even if i would have them orderd like the functions this code would not look much better
This is how the improved version would look like (I used ChatGPT bc i even cant get through that even more (so expect parts to be wrong or from an alternate universe))
name "Worker"
EVERY 100 TICKS DO
RUN ProcessSalt
RUN ProcessChlorine
RUN ProcessNickelOre
RUN ProcessRawIron
RUN ProcessChemicals
END
EVERY 400 TICKS DO
RUN ProcessMixerOutput
END
EVERY 100 TICKS DO
INPUT FROM MixerMain BOTTOM SIDE
OUTPUT TO ItemOutput_SSD
END
EVERY 10 TICKS DO
INPUT forge_energy:: FROM Energy SOUTH SIDE
OUTPUT forge_energy:: TO EACH NeedsEnergy TOP SIDE
END
FUNCTION ProcessMixerInputs
FORGET
INPUT FROM ItemBuffer_NickelDust
OUTPUT TO MixerMain TOP SIDE
FORGET
INPUT FROM ItemBuffer_IronDust
OUTPUT TO MixerMain TOP SIDE
FORGET
INPUT FROM ItemBuffer_MD
OUTPUT TO MixerMain TOP SIDE
FORGET
INPUT FROM ItemBuffer_CD
OUTPUT TO MixerMain TOP SIDE
END
FUNCTION ProcessSalt
FORGET
INPUT FROM ItemInput_SaltDust
OUTPUT TO EACH Electrolyzer_Chlorine TOP SIDE
END
FUNCTION ProcessChlorine
FORGET
INPUT FROM Electrolyzer_Chlorine BOTTOM SIDE
OUTPUT TO EACH ItemBuffer_SD
FORGET
INPUT fluid:: FROM Electrolyzer_Chlorine BOTTOM SIDE
OUTPUT fluid:: TO EACH FluidBuffer_Chlorine
END
FUNCTION ProcessNickelOre
FORGET
INPUT FROM ItemInput_NickelOre
OUTPUT TO EACH MaceleratorFrom_NickelOre_To_RawNickel TOP SIDE
FORGET
INPUT FROM MaceleratorFrom_NickelOre_To_RawNickel BOTTOM SIDE
OUTPUT TO ItemBuffer_RawNickel
FORGET
INPUT FROM ItemBuffer_RawNickel
OUTPUT TO MaceleratorFrom_RawNickel_To_NickelDust TOP SIDE
FORGET
INPUT FROM MaceleratorFrom_RawNickel_To_NickelDust BOTTOM SIDE
OUTPUT TO ItemBuffer_NickelDust
END
FUNCTION ProcessRawIron
FORGET
INPUT FROM ItemInput_RawIron
OUTPUT TO EACH CentrifugeFrom_RawIron_To_ManganeseCrushedDust TOP SIDE
FORGET
INPUT FROM CentrifugeFrom_RawIron_To_ManganeseCrushedDust BOTTOM SIDE
OUTPUT iron_dust TO ItemBuffer_IronDust
OUTPUT manganese_crushed_dust TO ItemBuffer_ManganeseCrushedDust
END
FUNCTION ProcessChemicals
FORGET
INPUT FROM ItemBuffer_ManganeseCrushedDust
OUTPUT TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM FluidBuffer_SulfuricAcid
OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM FluidInput_SulfuricAcid
OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM ChemicalReactor_MSS BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_MSS
FORGET
INPUT fluid:: FROM FluidBuffer_MSS
OUTPUT fluid:: TO Electrolyzer_MTD TOP SIDE
FORGET
INPUT FROM Electrolyzer_MTD BOTTOM SIDE
OUTPUT TO ItemBuffer_MTD
FORGET
INPUT fluid:: FROM Electrolyzer_MTD BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_SulfuricAcid
END
END
I don't see how this is different from using code comments tho
-- Process chemicals
EVERY 20 TICKS DO
INPUT FROM ItemBuffer_ManganeseCrushedDust
OUTPUT TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM FluidBuffer_SulfuricAcid
OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM FluidInput_SulfuricAcid
OUTPUT fluid:: TO EACH ChemicalReactor_MSS TOP SIDE
FORGET
INPUT fluid:: FROM ChemicalReactor_MSS BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_MSS
FORGET
INPUT fluid:: FROM FluidBuffer_MSS
OUTPUT fluid:: TO Electrolyzer_MTD TOP SIDE
FORGET
INPUT FROM Electrolyzer_MTD BOTTOM SIDE
OUTPUT TO ItemBuffer_MTD
FORGET
INPUT fluid:: FROM Electrolyzer_MTD BOTTOM SIDE
OUTPUT fluid:: TO FluidBuffer_SulfuricAcid
END
-- process raw iron
EVERY 20 TICKS DO
INPUT FROM ItemInput_RawIron
OUTPUT TO EACH CentrifugeFrom_RawIron_To_ManganeseCrushedDust TOP SIDE
FORGET
INPUT FROM CentrifugeFrom_RawIron_To_ManganeseCrushedDust BOTTOM SIDE
OUTPUT iron_dust TO ItemBuffer_IronDust
OUTPUT manganese_crushed_dust TO ItemBuffer_ManganeseCrushedDust
END
Sure comments can also do the Job
But i think functions would do the job much better (or a combo of both) (my opinion)
And when functions would be implemented you could also directly also implement return types (int boolean and void)
Which would def step up the sfm game
And now you might say but there is no way to store informations like int`s
You could just count items in a chest and use the container as a int
Example
name "Worker"
EVERY 100 TICKS DO
RUN FUNCTION DoSomething
END
AFUNCTION VOID IncreaseIntA
-- code
END
AFUNCTION VOID DecreaseIntA
-- code
END
AFUNCTION VOID EmptyIntA
-- code
END
AFUNCTION INT GetIntA
-- code
END
AFUNCTION VOID DoSomething
IF RUN FUNCTION GetIntA >= 10 THEN
RUN FUNCTION EmptyIntA
END
ELSE
RUN FUNCTION DoSomething
END
END
You can use the ChatGPT'd output and replace the functions with EVERY 100 TICKS DO
and get pretty much the same result.
An advantage I see is that it would give each program a sort of "main" or "entry" function. Reading the first loop with the function example I could generally see what the program is supposed to do - as opposed to finding a comment at the start of every loop. I think this feature would be especially nice if there was a quick way to scroll to the function declaration line.
name "Worker"
EVERY 100 TICKS DO
RUN ProcessSalt
RUN ProcessChlorine
RUN ProcessNickelOre
RUN ProcessRawIron
RUN ProcessChemicals
END
perhaps code folding would meet the need until variables and functions are introduced
something like
EVERY TICK DO ▶ -- move energy
EVERY 20 TICKS DO ▶ -- process salt
EVERY 40 TICKS DO ▶ -- move nickel
It would be easier to implicitly fold on IF/ELSE/END and DO/END. Or it could be comment style with --#region
to explicitly fold.
When you want to do before you do the function it would be need to also have this
REGION START "Desc"
-- code
REGION END
and then you can also fold these.
Obv it should also then allow this
REGION START "Desc1"
REGION START "Desc2"
-- code
REGION END
REGION END
(When the functions are implemented they should also be foldable)
It would be easier to implicitly fold on IF/ELSE/END and DO/END. Or it could be comment style with
--#region
to explicitly fold.
Yes it should also automatically fold on IF/ELSE/END and DO/END
But in addtion
REGION START "Desc"
-- code
REGION END
this would be pretty nice
Comment style for explicit marking would be better since it doesn't actually matter to the program. It's something only for the editor.
Comment style for explicit marking would be better since it doesn't actually matter to the program. It's something only for the editor.
But the avarage player learned that he has a start and a END
so either it would be
REGION START "Desc"
-- code
REGION END
or
--#region-start"Desc"
-- code
--#region-end
if the comment is not including start and end this would not be possible
REGION START "Desc1"
REGION START "Desc2"
-- code
REGION END
REGION END
Could just let people use
Every 20 ticks do
Do -- thing1
Input from chest
Output to chest2
Forget
End
Do -- thing2
Input fluid:: from tank1
Output fluid:: to tank2
End
End
Could just let people use
Every 20 ticks do Do -- thing1 Input from chest Output to chest2 Forget End Do -- thing2 Input fluid:: from tank1 Output fluid:: to tank2 End End
Still does not allow for reuse of code but its a start
with code folding i could actually see this being usefull
Alternativly you could do it like this
name "Worker"
Every 20 ticks do
RUN moveitems
RUN movefluids
End
Do "moveitems"
Input from chest
Output to chest2
End
Do "movefluids"
Input fluid:: from tank1
Output fluid:: to tank2
End