HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Fun with textmacros

01-17-2007, 12:59 PM#1
Vexorian
Collapse JASS:
//! textmacro csarray takes type, name, size
 scope $name$
    globals
        $type$ array $name$
        private integer array V
        private integer N=0
        private integer I=1
        private boolean array U

        public constant integer size=$size$

    endglobals

    public function create takes nothing returns integer
     local integer id
        if (N>0) then
            set N=N-1
            set id=V[N]
        elseif (I+$size$>8190) then
            debug call BJDebugMsg("Warning : no space for array: $name$ $type $size$")
            return 0
        else
            set id=I
            set I=I+$size$
        endif
        if( U[id]) then
            debug call BJDebugMsg("Warning : used slot for array: $name$ $type $size$")
            return create()
        endif
        set U[id]=true
        return id
    endfunction

    public function createInit takes $type$ inival returns integer
     local integer id
     local integer a
        if (N>0) then
            set N=N-1
            set id=V[N]
        elseif (I+$size$>8190) then
            debug call BJDebugMsg("Warning : no space for array: $name$ $type $size$")
            return 0
        else
            set id=I
            set I=I+$size$
        endif
        if( U[id]) then
            debug call BJDebugMsg("Warning : used slot for array: $name$ $type $size$")
            return create()
        endif
        set U[id]=true
        set a=id
        loop
            exitwhen a==id+$size$
            set $name$[a]=inival
            set a=a+1
        endloop
        return id
    endfunction

    public function destroy takes integer id returns nothing
        if (not U[id]) then
            debug call BJDebugMsg("Warning: double/invalid id free attemp for array : $name$ $type$ $size$")
            return
        endif
        set V[N]=id
        set N=N+1
        set U[id]=false
    endfunction

    //Easier but slower:
    public function setIndex takes integer id, integer index, $type$ value returns nothing
        set $name$[id+index]=value        
    endfunction

    public function getIndex takes integer id, integer index returns $type$
        return $name$[id+index]
    endfunction

    public function isValidId takes integer id returns boolean
        return U[id]
    endfunction

 endscope
//! endtextmacro



Collapse JASS:

//! runtextmacro csarray("integer","cool","5")

function keks takes nothing returns nothing
 local integer A=cool_create()
 local integer B=cool_createInit(56)

 local integer i=0

    loop
        exitwhen i==cool_size
        set cool[A+i]=i
        set i=i+1
    endloop
    set i=0
    loop
        exitwhen i==cool_size
        call BJDebugMsg(": "+I2S(cool[B+i]-cool[A+i]))
        set i=i+1
    endloop
    
    call cool_destroy(A)
    call cool_destroy(B)
 
endfunction

As useful as it is , it is also kind of a mess, I guess I have to continue the plan of making these arrays a native vJass feature thus let them use the more direct [] syntax.
01-17-2007, 02:42 PM#2
rulerofiron99
So what does it do?
01-17-2007, 02:59 PM#3
rain9441
Its like a template class in C++, which are amazingly useful for containers.

With that you'll be able to (with 1 line of code) create an array of any type, and have get/set/create/init methods for them. I'm guessing the next step for Vexorian is a template for hash tables, linked lists, binary trees... you name it.
01-18-2007, 02:42 PM#4
rain9441
More fun with textmacros (A minor addition to vex's project)

Collapse JASS:
//! textmacro csarray takes type, name, size, cmpf
 scope $name$
    globals
        $type$ array $name$
        private integer array V
        private integer N=0
        private integer I=1
        private boolean array U

        public constant integer size=$size$

    endglobals

    public function create takes nothing returns integer
     local integer id
        if (N>0) then
            set N=N-1
            set id=V[N]
        elseif (I+$size$>8190) then
            debug call BJDebugMsg("Warning : no space for array: $name$ $type $size$")
            return 0
        else
            set id=I
            set I=I+$size$
        endif
        if( U[id]) then
            debug call BJDebugMsg("Warning : used slot for array: $name$ $type $size$")
            return create()
        endif
        set U[id]=true
        return id
    endfunction

    public function createInit takes $type$ inival returns integer
     local integer id
     local integer a
        if (N>0) then
            set N=N-1
            set id=V[N]
        elseif (I+$size$>8190) then
            debug call BJDebugMsg("Warning : no space for array: $name$ $type $size$")
            return 0
        else
            set id=I
            set I=I+$size$
        endif
        if( U[id]) then
            debug call BJDebugMsg("Warning : used slot for array: $name$ $type $size$")
            return create()
        endif
        set U[id]=true
        set a=id
        loop
            exitwhen a==id+$size$
            set $name$[a]=inival
            set a=a+1
        endloop
        return id
    endfunction

    public function destroy takes integer id returns nothing
        if (not U[id]) then
            debug call BJDebugMsg("Warning: double/invalid id free attemp for array : $name$ $type$ $size$")
            return
        endif
        set V[N]=id
        set N=N+1
        set U[id]=false
    endfunction

    public function sortrange takes integer a, integer b returns nothing
        local integer j = a
        local integer k = b
        local $type$ p
        local $type$ t

        set p = $name$[GetRandomInt(a,b)]
        loop
            exitwhen j > k
            loop
                exitwhen $cmpf$($name$[j],p) <= 0
                exitwhen j >= b
                set j = j + 1
            endloop

            loop
                exitwhen $cmpf$($name$[k],p) >= 0
                exitwhen k <= a
                set k = k - 1
            endloop
            if ( j < k ) then
                set t = $name$[j]
                set $name$[j] = $name$[k]
                set $name$[k] = t
                set j = j + 1
                set k = k - 1
            elseif ( j == k ) then
                set k = k - 1
            endif
        endloop

        if ( a < k ) then
            call sortrange(a,k)
        endif
        if ( j < b ) then
            call sortrange(j,b)
        endif
    endfunction

    public function sort takes integer id returns nothing
        call sortrange(id, id + size - 1)
    endfunction
    //Easier but slower:
    public function setIndex takes integer id, integer index, $type$ value returns nothing
        set $name$[id+index]=value        
    endfunction

    public function getIndex takes integer id, integer index returns $type$
        return $name$[id+index]
    endfunction

    public function isValidId takes integer id returns boolean
        return U[id]
    endfunction

 endscope
//! endtextmacro

Only changes are the textmacro variable cmpf (Compare Function), public function's sort and sortrange.

And to use:

Collapse JASS:

function IntegerCompare takes integer a, integer b returns integer
    if ( a < b ) then
        return -1
    elseif ( a == b ) then
        return 0
    endif
    return 1
endfunction
    

//! runtextmacro csarray("integer","cool","12","IntegerCompare")

function keks takes nothing returns nothing
 local integer A=cool_create()

 local integer i=0

    loop
        exitwhen i==cool_size
        set cool[A+i]=GetRandomInt(1,50)
        call BJDebugMsg(": "+I2S(cool[A+i]))
        set i=i+1
    endloop
    call cool_sort(A)
    set i = 0
    loop
        exitwhen i==cool_size
        call BJDebugMsg(":: "+I2S(cool[A+i]))
        set i=i+1
    endloop
    
    call cool_destroy(A)
endfunction



I think vex is onto something....
NOTE*: sorting will leak local pivot values and swap variables every time in the case where csarray is instantiated with types such as unit, location, rect, timer, etc. If Vex is eager enough, perhaps a //! if then else preprocess could remedy the situation... e.g.
Collapse JASS:
//! if $type$ == "unit" then
set p = null
set t = null
//! endif

I was able to sort integer arrays of size ~450 consistantly (with triggersleepaction(0) before and after the call), any higher and I hit thread execution limits. This is without inlining, and using that horrible compare function.

When I changed IntegerCompare to simply return a-b, i could sort arrays of size ~550.

When I manually inlined "a <= b" into the sort equation, I could sort arrays of size ~750