- Joined
- Aug 18, 2009
- Messages
- 4,099
Greetings
I am using a system called Structfollowers and am trying to improve it at the moment by shortening things and making it more secure, which is where I ran into some problem. But first a few explanations of the system:
Thereby, a link shall be created from one struct to another of this kind:
From struct A I can access its "inner" structs FolderA_B/FolderA_C/FolderA_D by going over the variables B/C/D. These variables are not static since every struct instance shall also transfer its own index to the inner struct.
For
"this" should be assigned to thistype(3) in the test method. So the variable B of A(3) has to be set to 3, too. The question for now is how to effectively initialize the variables for each instance.
You cannot assume that every instance of A is fetched by the normal .allocate() method. Additionally, I would like to have done all initializations only once in the beginning. This means there have to be functions that iterate through the whole struct and set the variables.
Either (simplified)
or
Either everything in one method or separated. Now, it is enwrapped in a textmacro for practical use.
And there a problem appears. If I would be to use the first method (everything together), I would write
and insert it into the function hull:
This means that I would need an initial and an end mark for this hull. However, the struct instance variable has still to be declared and this cannot be done inside a method. Ergo, one textmacro does not suffice.
That is why I wrote it this way till now:
This is not that nice because of redundance and error-proneness. You could forget to initialize a single member for example. The compiler would not mind.
So I tried it via the second possibility: To have an own init method for each link:
Well, now, these init functions have to be executed and vJass only allows one onInit per struct/module. If I would do every call manually, it would be inconvenient again and also error-prone like above. In vJass, it is nearly impossible to export code to a marker. An exception would be //! inject, which only works one time for main and one time for config, another would be the struct instance initialization on allocate():
The variable B would be set to 4 on allocation here and you can abuse it and enter non-constant values like integer B = this. But I would like to keep the normal allocate function and generating code via external tool via lua script also has its problems.
One possibility that I had still seen was to work with static ifs. Basically, in the onInit method, I had to know which InitLink methods exist. Since I cannot ask for each combination of characters, it would be nice if the methods were enumerated.
How could I number them all the way through only using the textmacro inputs and without adding the number as parameter?
This lead me to the following construction:
Unfortunately, static ifs are badly made in vJass. On the first run InitLink1 gets created, nothing after that. This originates from the circumstance that, while checking .exists, it looks whether the searched function is somewhere above and in case this function is declared in a as false evaluated static if block, this counts nonetheless. It would be the same if I used an own constant boolean variable. Therefore I cannot obtain another outcome each textmacro call with static ifs because everything would be falsly declared after the first time.
So, anyone got another idea?
edit: solved, I am allocating all instances now and immediately deallocate them again onInit. Thus, the links are set, the normal allocation method is still usable and the function gets run by a private onInit method in a module that is implemented into the textmacro. Implementing the same module only works once but does not throw an error.
I am using a system called Structfollowers and am trying to improve it at the moment by shortening things and making it more secure, which is where I ran into some problem. But first a few explanations of the system:
Thereby, a link shall be created from one struct to another of this kind:
JASS:
scope FolderA
public struct B
method test takes nothing returns nothing
endmethod
endstruct
public struct C
endstruct
public struct D
endstruct
endscope
struct A
FolderA_B B
FolderA_C C
FolderA_D D
endstruct
From struct A I can access its "inner" structs FolderA_B/FolderA_C/FolderA_D by going over the variables B/C/D. These variables are not static since every struct instance shall also transfer its own index to the inner struct.
For
JASS:
call A(3).B.test()
"this" should be assigned to thistype(3) in the test method. So the variable B of A(3) has to be set to 3, too. The question for now is how to effectively initialize the variables for each instance.
You cannot assume that every instance of A is fetched by the normal .allocate() method. Additionally, I would like to have done all initializations only once in the beginning. This means there have to be functions that iterate through the whole struct and set the variables.
Either (simplified)
JASS:
static method InitLinks takes nothing returns nothing
local integer i = STRUCT_MAX
loop
set thistype(i).B = i
set thistype(i).C = i
set thistype(i).D = i
exitwhen (i == STRUCT_MIN)
set i = i - 1
endloop
endmethod
or
JASS:
static method InitLinkB takes nothing returns nothing
local integer i = STRUCT_MAX
loop
set thistype(i).B = i
exitwhen (i == STRUCT_MIN)
set i = i - 1
endloop
endmethod
JASS:
static method InitLinkC takes nothing returns nothing
local integer i = STRUCT_MAX
loop
set thistype(i).C = i
exitwhen (i == STRUCT_MIN)
set i = i - 1
endloop
endmethod
JASS:
static method InitLinkD takes nothing returns nothing
local integer i = STRUCT_MAX
loop
set thistype(i).D = i
set i = i - 1
exitwhen (i == STRUCT_MIN)
endloop
endmethod
Either everything in one method or separated. Now, it is enwrapped in a textmacro for practical use.
JASS:
struct A
//! runtextmacro LinkToStruct("A", "B")
//! runtextmacro LinkToStruct("A", "C")
//! runtextmacro LinkToStruct("A", "D")
endstruct
And there a problem appears. If I would be to use the first method (everything together), I would write
JASS:
//! textmacro LinkToStruct takes folder, struct
set thistype(i).$struct$ = i
//! endtextmacro
and insert it into the function hull:
JASS:
static method InitLinks takes nothing returns nothing
local integer i = STRUCT_MAX
loop
//here comes the textmacro calls
exitwhen (i == STRUCT_MIN)
set i = i - 1
endloop
endmethod
This means that I would need an initial and an end mark for this hull. However, the struct instance variable has still to be declared and this cannot be done inside a method. Ergo, one textmacro does not suffice.
That is why I wrote it this way till now:
JASS:
struct A
//! runtextmacro LinkToStruct("A", "B") //declaring the variables
//! runtextmacro LinkToStruct("A", "C")
//! runtextmacro LinkToStruct("A", "D")
//! runtextmacro InitLinksToStruct_Start()
//! runtextmacro InitLinksToStruct_NewMember("B")
//! runtextmacro InitLinksToStruct_NewMember("C")
//! runtextmacro InitLinksToStruct_NewMember("D")
//! runtextmacro InitLinksToStruct_Ending()
endstruct
This is not that nice because of redundance and error-proneness. You could forget to initialize a single member for example. The compiler would not mind.
So I tried it via the second possibility: To have an own init method for each link:
JASS:
//! textmacro LinkToStruct $folder$, $struct$
Folder$folder$_$struct$
static method InitLink$struct$ takes nothing returns nothing
...
endmethod
//! endtextmacro
Well, now, these init functions have to be executed and vJass only allows one onInit per struct/module. If I would do every call manually, it would be inconvenient again and also error-prone like above. In vJass, it is nearly impossible to export code to a marker. An exception would be //! inject, which only works one time for main and one time for config, another would be the struct instance initialization on allocate():
JASS:
struct A
integer B = 4
endstruct
The variable B would be set to 4 on allocation here and you can abuse it and enter non-constant values like integer B = this. But I would like to keep the normal allocate function and generating code via external tool via lua script also has its problems.
One possibility that I had still seen was to work with static ifs. Basically, in the onInit method, I had to know which InitLink methods exist. Since I cannot ask for each combination of characters, it would be nice if the methods were enumerated.
JASS:
static method InitLink1 takes nothing returns nothing
//initialize B
endmethod
static method InitLink2 takes nothing returns nothing
//initialize C
endmethod
static method InitLink3 takes nothing returns nothing
//initialize D
endmethod
static method onInit takes nothing returns nothing
static if thistype.InitLink1.exists then
call thistype.InitLink1()
endif
static if thistype.InitLink2.exists then
call thistype.InitLink2()
endif
static if thistype.InitLink3.exists then
call thistype.InitLink3()
endif
static if thistype.InitLink4.exists then
call thistype.InitLink4()
endif
static if thistype.InitLink5.exists then
call thistype.InitLink5()
endif
...//for a fixed maximum amount
endmethod
How could I number them all the way through only using the textmacro inputs and without adding the number as parameter?
JASS:
//! runtextmacro LinkToStruct("A", "B")
This lead me to the following construction:
JASS:
//! textmacro LinkToStruct takes folder, struct
Folder$folder$_$struct$ $struct$
static if not thistype.InitLink1.exists then
static method InitLink1 takes nothing returns nothing
...
endmethod
else
static if not thistype.InitLink2.exists then
static method InitLink2 takes nothing returns nothing
...
endmethod
else
static if not thistype.InitLink3.exists then
static method InitLink3 takes nothing returns nothing
...
endmethod
else
...
endif
endif
endif
//! textmacro
Unfortunately, static ifs are badly made in vJass. On the first run InitLink1 gets created, nothing after that. This originates from the circumstance that, while checking .exists, it looks whether the searched function is somewhere above and in case this function is declared in a as false evaluated static if block, this counts nonetheless. It would be the same if I used an own constant boolean variable. Therefore I cannot obtain another outcome each textmacro call with static ifs because everything would be falsly declared after the first time.
So, anyone got another idea?
edit: solved, I am allocating all instances now and immediately deallocate them again onInit. Thus, the links are set, the normal allocation method is still usable and the function gets run by a private onInit method in a module that is implemented into the textmacro. Implementing the same module only works once but does not throw an error.
Last edited: