dbaumgarten / yodk

Development Kit for Starbase's ingame programming language YOLOL
MIT License
57 stars 16 forks source link

Macro: dynamic variable naming #105

Open quonic opened 2 years ago

quonic commented 2 years ago

Is your feature request related to a problem? Please describe. I'm trying to write useful macros that allow only calling one macro. There currently isn't a way to dynamically create variables, but I think macros would be perfect for the job.

Writing hundreds of similar macros is a bit tedious. Take for example these two macros and expand that to 100 similar functioning macros, but with additional parameters.

macro BatteryTotalTwo(Bat1,Bat2) expr
    Bat1+Bat2
end
macro BatteryTotalThree(Bat1,Bat2,Bat3) expr
    Bat1+Bat2+Bat3
end

Describe the solution you'd like Something to akin to the following would make the whole thing much easier to maintain and others easier to utilize.

macro BatteryTotal(BatName,BatCount) block
    BatTotal=sum(
        for i = 0; i < BatCount; i++ then
            {BatName+i}
        end
    )
end

Resulting yolol code:

B=:B0+:B1+:B2+:B3+:B4+:B5+:B6+:B7+:B8+:B9+:B10+:B11+:B12+:B13+:B14+:B15

For when the line length is to long:

B=:B0+:B1+:B2+:B3+:B4+:B5+:B6+:B7+:B8+:B9+:B10+:B11+:B12+:B13+:B14+:B15
B=B+B16

Describe alternatives you've considered

I don't know how the syntax should be, but I hope that the above gives some inkling of what I'm trying to communicate.

dbaumgarten commented 2 years ago

I understand why something like this would be helpfull. But the hard part here is to find a proper syntax for it. It must be clear to the user that there is compile-time code-generation going on, and that it's not regular code. In your example it would be pretty confusing to the user that he can't pass a variable as BatCount to the macro.

I have been thinking about adding a template-engine to the mix, kind of like the C preprocessor, that could be used for code-generation. But I fear that that might be complete overkill.

quonic commented 2 years ago

I'm just throwing out ideas and seeing what sticks.

Maybe a template-engine based on a subset of the lua syntax, limited to string manipulation or only string output? Let the end user build their own micro template-engine.

Or maybe include go code or something, that what ever functions from that include could be called and the resulting string output would be passed on as nolol to yodk.

dbaumgarten commented 2 years ago

Go has it's own built-in templating language: https://pkg.go.dev/text/template Just adding it ass a step before the actual nolol-compilation would be pretty simple.

But thats adding a whole new (quite complicated) language to the mix. And I am also unsure about the interaction between the templating and yolol. It could make things quite chaotic, especially be throwing of the line-numbering in error-messages.

quonic commented 2 years ago

After sleeping on this for a while. What about some kind of string builder that takes a variable, number, and delimiter (":a",1,3,"+") that then builds up the following example :a1+:a2+:a3 ?

dbaumgarten commented 2 years ago

The issue i see with that is: What happens once the generated expression reaches the char-limit? As this feature would mainly be used with fiel-names, which usually are a bit long, that would happen quite fast. Currently there is no feature to split an expression accross multiple lines (and because of the possible timing-issues such a feature will probably never exist).

Such a "builder"-feature would need to generate seperate statements, which can then be merged into as few lines as possible by the compiler (possibly in combination with #52 )

quonic commented 2 years ago

Maybe someone will find this useful or not.

Here is what I'm using as a stop gap.

It's looking for something formatted like this // %Bat,1,20,:Bat,+ and outputs this:

Bat=:Bat1+:Bat2+:Bat3+:Bat4+:Bat5+:Bat6+:Bat7+:Bat8+:Bat9+:Bat10
Bat=Bat+:Bat11+:Bat12+:Bat13+:Bat14+:Bat15+:Bat16+:Bat17+:Bat18
Bat=Bat+:Bat19

It looks for lines starting with // %. Splits the lines by ,. Uses Bat for the temp variable and the :Bat for the base name(iteration through 1 to 20, adding it to the end of :Bat). Using the + as the "delimiter". All the while making sure the line length doesn't go beyond 70 characters. The + could be anything really, like a math equation.

dbaumgarten commented 2 years ago

I am glad you found a workaround for yourself.

I still would like to add something like this natively to nolol, but I still haven't found a way of doing to, without introducing a gigantic amount of complexity...