• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

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

Status
Not open for further replies.
Level 13
Joined
Nov 7, 2014
Messages
571
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