- Joined
- Aug 18, 2009
- Messages
- 4,099
ExpositionI have searched for new ways to write my vJass codes. Particularly, the semi-optimal encapsulation always annoyed me. You cannot nest libraries, you may do so with scopes but equal-labelled identifiers of parents are in the way nor will be overshadowed, same when extending structs. Private implementing of modules was not introduced, so modules are actually only nestable textmacros but without parameters, quasi like import. Well, now it does not seem like vJass is still going on with development, so I do something on my own.
Structs are fairly good since they allow a short notation on calling through their instances. When you extend structs, the members of the parent will simply get transfered, resulting in you being unable to redeclare its identifiers. Even if you could overshadow them, you would not be able to access them anymore. A precise indicator is missing, folders in structs. It's a simple strategy: You jump from one struct into another by using a local identifier in the origin struct that redirects to the target struct by returning an instance of this target struct.
Read "Realization" to see single steps of how to acquire this target and which problems may appear. It finalizes in my current solution.
RealizationThat would be my basic approach how I wanted it:
JASS:scope SurpriseBag public struct B static method Goal takes nothing returns nothing endmethod endstruct endscope struct A static SurpriseBag_B B endstruct
Now you could write
JASS:call A.B.Goal()
This works already for the static call. But it's harder to go via an instance of A because you would need to pass the id of this instance to struct B and cast again. This is because "B" shall be a folder of A, store information for the instance of A you enter B with and therefore need to identify to which A instance it belongs.
This means it's necessary to assign each B instance to its parallel A instance.
JASS:scope SurpriseBag public struct B method Goal takes nothing returns nothing endmethod static method StaticGoal takes nothing returns nothing endmethod endstruct endscope struct A SurpriseBag_B B static method create takes nothing returns thistype local thistype this = thistype.allocate() set this.B = this return this endmethod endstruct
Call:
JASS:call <InstanceOfA>.B.Goal()
But it ain't that easy. It would only work this way if you allocated the instance, which isn't a must since you would want to have deeper nestings without necessarily allocating.
Unit.Position.X.Get() for example, you would create a new Unit but not a new Position, this should just work as a folder that contains the inner part X. You also would not want to write this create-method with modifyings everytime, which would be error-prone anyway.
So my idea: Allocate each instance onInit but immediately destroy them again. Their members will not be reset. I also use some textmacros here to finalize the shape and BaseStruct/Folder/Struct are meant for avoiding name conflicts as you might have a inner struct Position for both Units and Items for example.
Current versionJASS://! textmacro Folder takes name scope Folder$name$ //! endtextmacro //! textmacro LinkToStruct takes folder, name Folder$folder$_Struct$name$ $name$ //! endtextmacro //! textmacro Struct takes name public struct Struct$name$ //! endtextmacro //! textmacro BaseStruct takes name struct $name$ static thistype THIS = NULL //! endtextmacro globals trigger InitLinks_DUMMY_TRIGGER = CreateTrigger() integer InitLinks_ITERATION integer InitLinks_THREAD_BREAK_COUNTER constant integer InitLinks_THREAD_BREAK_LIMIT = 1500 endglobals globals constant boolean DEBUG = true constant integer STRUCT_EMPTY = 0 constant integer STRUCT_MAX = 8190 constant integer STRUCT_MIN = 1 endglobals module InitStructLinks private static method InitStructLinks2 takes nothing returns nothing local integer iteration = InitLinks_ITERATION loop call thistype(iteration).deallocate() set iteration = iteration - 1 exitwhen (iteration < STRUCT_MIN) set InitLinks_THREAD_BREAK_COUNTER = InitLinks_THREAD_BREAK_COUNTER + 1 exitwhen (InitLinks_THREAD_BREAK_COUNTER > InitLinks_THREAD_BREAK_LIMIT) endloop if (iteration > STRUCT_EMPTY) then set InitLinks_ITERATION = iteration set InitLinks_THREAD_BREAK_COUNTER = 0 call TriggerEvaluate(InitLinks_DUMMY_TRIGGER) else static if (DEBUG) then set InitLinks_ITERATION = STRUCT_EMPTY endif endif endmethod private static method InitStructLinks takes nothing returns nothing local integer iteration = InitLinks_ITERATION loop call thistype.allocate() set iteration = iteration - 1 exitwhen (iteration < STRUCT_MIN) set InitLinks_THREAD_BREAK_COUNTER = InitLinks_THREAD_BREAK_COUNTER + 1 exitwhen (InitLinks_THREAD_BREAK_COUNTER > InitLinks_THREAD_BREAK_LIMIT) endloop if (iteration > STRUCT_EMPTY) then set InitLinks_ITERATION = iteration set InitLinks_THREAD_BREAK_COUNTER = 0 call TriggerEvaluate(InitLinks_DUMMY_TRIGGER) else static if (DEBUG) then set InitLinks_ITERATION = STRUCT_EMPTY endif endif endmethod private static method onInit takes nothing returns nothing local boolexpr condition = Condition(function thistype.InitStructLinks) set InitLinks_ITERATION = STRUCT_MAX set InitLinks_THREAD_BREAK_COUNTER = 0 call TriggerClearConditions(InitLinks_DUMMY_TRIGGER) call TriggerAddCondition(InitLinks_DUMMY_TRIGGER, condition) call TriggerEvaluate(InitLinks_DUMMY_TRIGGER) call DestroyBoolExpr(condition) set condition = null static if (DEBUG) then if (InitLinks_ITERATION > STRUCT_EMPTY) then call BJDebugMsg("InitLinks: thread break in " + InitStructLinks.name + " with " + I2S(InitLinks_ITERATION)) endif endif set condition = Condition(function thistype.InitStructLinks2) set InitLinks_ITERATION = STRUCT_MAX set InitLinks_THREAD_BREAK_COUNTER = 0 call TriggerClearConditions(InitLinks_DUMMY_TRIGGER) call TriggerAddCondition(InitLinks_DUMMY_TRIGGER, condition) call TriggerEvaluate(InitLinks_DUMMY_TRIGGER) call DestroyBoolExpr(condition) set condition = null endmethod endmodule //! textmacro LinkToStruct takes folder, struct Folder$folder$_Struct$struct$ $struct$ = this implement InitStructLinks //! endtextmacro
JASS://Example //! runtextmacro Folder("Apple") //! runtextmacro Struct("Worm") endstruct endscope //! runtextmacro BaseStruct("Apple", "Apple") //! runtextmacro LinkToStruct("Apple", "Worm") endstruct //Worm is an inner part of Apple
Last edited: