• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

t.real[X] vs t[X].real

Status
Not open for further replies.
One can force jasshelper to inline the calls to the native hashtable functions just like Table does with it's t.<type>[<child-key>], but with a reversed syntax, i.e t[<child-key>].<type>. There is a small overhead, i.e a single method call per function (usually) and 1 extra adition and 1 extra subtraction per lookup:
JASS:
library Ht

globals
    private hashtable ht = InitHashtable()
endglobals

struct Ht
    static integer pk1
    static integer pk2

    // set the parent key, and make 2 copies of it
    method set_pk takes nothing returns nothing
        set pk1 = this
        set pk2 = this
    endmethod

    method operator[] takes integer i returns thistype
        return this + i
    endmethod

    method operator int= takes integer r returns nothing
        call SaveInteger(ht, pk1, this - pk2, r) // this - pk2 = i
    endmethod
    method operator int takes nothing returns integer
        return LoadInteger(ht, pk1, this - pk2)
    endmethod

    method operator real= takes real r returns nothing
        call SaveReal(ht, pk1, this - pk2, r)
    endmethod

    method operator real takes nothing returns real
        return LoadReal(ht, pk1, this - pk2)
    endmethod

endstruct

endlibrary

function main takes nothing returns nothing
    local Ht ht = Ht.create()
    local real r
    local integer i
    call ht.set_pk() // it's possible to forget to call this and we'll save/load to/from some other Ht instance =)

    set ht[1].int = 4
    set i = ht[1]

    set ht[2].real = 6.28
    set r = ht[2].real
endfunction

The above gets compiled to:
JASS:
globals
//globals from Ht:
constant boolean LIBRARY_Ht=true
hashtable Ht___ht= InitHashtable()
//endglobals from Ht


//JASSHelper struct globals:
constant integer si__Ht=1
integer si__Ht_F=0
integer si__Ht_I=0
integer array si__Ht_V
integer s__Ht_pk1
integer s__Ht_pk2

endglobals


//Generated allocator of Ht
function s__Ht__allocate takes nothing returns integer
 local integer this=si__Ht_F
    if (this!=0) then
        set si__Ht_F=si__Ht_V[this]
    else
        set si__Ht_I=si__Ht_I+1
        set this=si__Ht_I
    endif
    if (this>8190) then
        return 0
    endif

    set si__Ht_V[this]=-1
 return this
endfunction

//Generated destructor of Ht
function s__Ht_deallocate takes integer this returns nothing
    if this==null then
        return
    elseif (si__Ht_V[this]!=-1) then
        return
    endif
    set si__Ht_V[this]=si__Ht_F
    set si__Ht_F=this
endfunction

//library Ht:



    // set the parent key, and make 2 copies of it
    function s__Ht_set_pk takes integer this returns nothing
        set s__Ht_pk1=this
        set s__Ht_pk2=this
    endfunction

    function s__Ht__getindex takes integer this,integer i returns integer
        return this + i
    endfunction

    function s__Ht__set_int takes integer this,integer r returns nothing
        call SaveInteger(Ht___ht, s__Ht_pk1, this - s__Ht_pk2, r) // this - pk2 = i
    endfunction
    function s__Ht__get_int takes integer this returns integer
        return LoadInteger(Ht___ht, s__Ht_pk1, this - s__Ht_pk2)
    endfunction

    function s__Ht__set_real takes integer this,real r returns nothing
        call SaveReal(Ht___ht, s__Ht_pk1, this - s__Ht_pk2, r)
    endfunction

    function s__Ht__get_real takes integer this returns real
        return LoadReal(Ht___ht, s__Ht_pk1, this - s__Ht_pk2)
    endfunction



//library Ht ends

function main takes nothing returns nothing
    local integer ht= s__Ht__allocate()
    local real r
    local integer i
    call s__Ht_set_pk(ht) // it's possible to forget to call this and we'll save/load to/from some other Ht instance =)

    call SaveInteger(Ht___ht, s__Ht_pk1, (((ht) + (1))) - s__Ht_pk2, (4)) // INLINED!!
    set i=((ht) + (1)) // INLINED!!

    call SaveReal(Ht___ht, s__Ht_pk1, (((ht) + (2))) - s__Ht_pk2, ((6.28)*1.0)) // INLINED!!
    set r=(LoadReal(Ht___ht, s__Ht_pk1, (((ht) + (2))) - s__Ht_pk2)) // INLINED!!

call ExecuteFunc("jasshelper__initstructs9086449")

endfunction



//Struct method generated initializers/callers:

function jasshelper__initstructs9086449 takes nothing returns nothing


endfunction

And as we can see, the hashtable functions are called inlined.

PS: this is my second attempt at this =).

edit: latest version
JASS:
library Ht

//! novjass

// Usage:

globals
    Ht ht
endglobals

function main takes nothing returns nothing
    local integer hid
    local integer my_int

    // on init
    set ht = Ht.create()

    // in "create"
        call ht.select()
        set hid = ht.h2i(/*CreateTrigger()*/ null)
        set my_int = 42
        set ht[hid].int = my_int

        // inlined:
        set ht.select()[ht.h2i(/*CreateTrigger()*/ null)].int = 42

    // in "handler"
        call ht.select()
        set hid = ht.h2i(/*GetTriggeringTrigger()*/ null)
        set my_int = ht[hid].int

        // inlined:
        set my_int = ht.select()[ht.h2i(/*CreateTrigger()*/ null)].int

        if ht[hid].int_e() then
            call BJDebugMsg(I2S(my_int))

            call ht[hid].int_d()
            if not ht[hid].int_e() then
                call BJDebugMsg("removed " + I2S(my_int))
            endif
        endif
endfunction

//! endnovjass

globals
    private hashtable ht = InitHashtable()
endglobals

struct Ht
    private static integer pk1
    private static integer pk2

    static method h2i takes handle h returns integer
        return GetHandleId(h)
    endmethod
    static method s2i takes string s returns integer
        return StringHash(s)
    endmethod

    // set the parent key, and make 2 copies of it
    method select takes nothing returns thistype
        set pk1 = this
        set pk2 = this
        return this
    endmethod

    method operator[] takes integer i returns thistype
        return this + i
    endmethod

    method operator int= takes integer x returns nothing
        call SaveInteger(ht, pk1, this - pk2, x) // this - pk2 = i
    endmethod
    method operator int takes nothing returns integer
        return LoadInteger(ht, pk1, this - pk2)
    endmethod
    method int_e takes nothing returns boolean // int-exists?
        return HaveSavedInteger(ht, pk1, this - pk2)
    endmethod
    method int_d takes nothing returns nothing // int-delete/destroy
        call RemoveSavedInteger(ht, pk1, this - pk2)
    endmethod

endstruct

endlibrary
 
Last edited:
Status
Not open for further replies.
Top