HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

vJass fun

08-21-2007, 03:52 AM#1
weaaddar
vJass's text macros allow some interesting ideas like generic programming. It allows you to create arrays which you can treat as first class members. This gives you the ability to pass them as parameters to functions which is extremely useful and basically helps makes generic utility classes more viable.
Collapse JASS:
globals 
    constant integer SIZE=20
endglobals

//! textmacro declareArray takes TYPE,TYPENAME
type $TYPENAME$Array extends $TYPE$ array[SIZE]
//! endtextmacro

//! textmacro mathBPCode takes TYPE, TYPENAME
static method max_$TYPENAME$ takes $TYPE$ a,$TYPE$ b returns $TYPE$
    if(a>b)then
        return a
    endif
    return b
endmethod

static method min_$TYPENAME$ takes $TYPE$ a,$TYPE$ b returns $TYPE$
    if(a>b)then
        return b
    endif
    return a
endmethod

static method findMax$TYPENAME$ takes $TYPENAME$Array list returns  $TYPE$
    local integer i=1
    local $TYPE$ max=list[0]
    loop
        exitwhen i>SIZE
        if( list[i]>max)then
            set max=list[i]
        endif
        set i=i+1
    endloop
    return max
endmethod
//! endtextmacro


//! runtextmacro declareArray("integer","int")
//! runtextmacro declareArray("real","real")
//! runtextmacro declareArray("iComparable","iComparable")

struct Math
    static integer MAX_INT=2147483647
    static integer MIN_INT=-(2147483648)
    //! runtextmacro mathBPCode("integer","int")
    //! runtextmacro mathBPCode("real","real")
    //! runtextmacro mathBPCode("iComparable","iComparable")
    static method round takes real x returns integer
        return R2I(x+0.5)
    endmethod
    static method floor takes real x returns integer
        return R2I(x)
    endmethod
endstruct
The above code implements a basic Math class that has some static methods, including a method that finds the max element in a pair of comparable types, or the max element in an array of comparables. Unfortuantly, vJass doesn't expose the length of these first class arrays, which is odd as it is used in vJass's allocation. But since you can declare global variables anywhere it doesn't hurt to just create a variable. If it really irks you, in theory you can create a struct that encapsulates the array, adds the .length member and overwrite the [] and []= operators.

More over, though as you probably expected these first class arrays do no such compile time checkings so the seemingly horrible
Collapse JASS:
//foo is an integerArray which has a size of 20
foo[-1] //this is valid?
foo[21] // this will compile as well
Whats worse is that those statements are very unlikely to crash and will be accessing data not belonging to foo.
Yup, these first class arrays behave as pointers. So why not treat them as such. We can now have "real" pass-by-reference semantics.

Collapse JASS:

type stringPointer extends string array[1]

function StringsAreImmutable takes string s returns nothing
    set s="Strings are immutable, so whatever you thought this was doing well it isn't"
endfunction

function StringPointersAreMutable takes stringPointer sp returns nothing
    // sp refers to the actual stringpointer, sp[0] holds the value of this string pointer
    set sp[0]="StringPointers will change the actual reference though."
endfunction

....
local string s="String"
local stringPointer sp=stringPointer.create()
set sp[0]=s 
call print(s) // "String"
call StringsAreImmutable(s)
call print(s) // "String"
call StringPointersAreMutable(sp)
call print(sp) // "StringPointers will change the actual reference though."

This can be useful when needing a means to output multiple parameters from a function and creates cleaner looking code
Collapse JASS:
function retrieveUnitFromGC takes string key1,key2,unitPointer up return bolean //returns false if it fails
... //logic here
endfunction

if(!retrieveUnitFromGC("Map1","Hero",my_up))then
        print("No save data found, creating new hero")
        //logic
else
        print("Hero found of level "+I2S(GetHeroLevel(my_up[0])))
endif

Unfortuantly, vJass still has a long way to go. We still need to deal with the normalization of the language (natives act like C code, non-natives like Java?) and building an even optional standard library can be very useful. A richer syntax for the text macro would be nice to but beggers can't be choosers
08-21-2007, 04:20 AM#2
Vexorian
Quote:
Unfortuantly, vJass doesn't expose the length of these first class arrays, which is odd as it is used in vJass's allocation

Unless I am misunderstanding you, vJass does expose their lengths

Collapse JASS:
type aaa extends integer array [5]

function aaaa takes aaa returns integer
    return aaa.size
endfunction



I'll add the syntax error for [-1] and [oversize] on arrays....
08-21-2007, 05:20 AM#3
PipeDream
References are the whole point to vJass. Giving structs array slots doesn't earn you anything in that department. The macro stuff is interesting even though it's ugly as hell. It demonstrates we could have a serious polymorphic type system if someone felt like writing it.

If you're interested in compile time checking, the field is today so mature that you can find lectures and notes online oriented at undergrads. I implemented an uninitialized variable checker which works well in practice in JAST. Doing serious stuff like proving loop termination I will have to leave to the CS people though.

Don't know what you mean by the difference between natives and nonnatives.
If by standard library you mean like libc, that's basically all in common.j.
08-21-2007, 06:57 AM#4
cohadar
Quote:
Originally Posted by Vexorian
I'll add the syntax error for [-1] and [oversize] on arrays....

At run-time?
That would slow things a bit....
08-21-2007, 12:37 PM#5
Vexorian
syntax errors don't tend to happen in run-time
08-21-2007, 01:00 PM#6
cohadar
I misunderstood you,
As far as I know vJASS is already checking for oversize,
apparently you cannot have custom arrays bigger than 1000
08-21-2007, 01:18 PM#7
Vexorian
[quote]
Collapse JASS:
//foo is an integerArray which has a size of 20
foo[-1] //this is valid?
foo[21] // this will compile as well@

Just checked and jasshelper does give a syntax error when you use an index higher than the size.

adding for -1
08-21-2007, 02:58 PM#8
weaaddar
[quote=Vexorian]
Quote:
Collapse JASS:
//foo is an integerArray which has a size of 20
foo[-1] //this is valid?
foo[21] // this will compile as well@

Just checked and jasshelper does give a syntax error when you use an index higher than the size.

adding for -1
Cool,
The help file never mentioned the .size field parameter so thats why I assumed it didn't exist. I only tested -1, I didn't actually try a value greater than size

I'd actually really like to see extension methods ala C# orcas as a means to do wrapping of common.j methods ie.
Collapse JASS:
struct IntUtil
method toString takes this integer returns nothing
I2S(this)
endmethod
endstruct
//later on you can now do this
1.toString()

And Pipedream is right this version of reference arrays isn't very interesting. Unless you use a memory array and a pointer struct that has an address. That way you can do Ptr.adr=locationInMemoryArray, and then ptr[0]=stuff. But thats dary type of stuff.
and a richer macro language so that we can design our own constructs and make the heniously ugly macros look prettier. We should get rid of the whole //! runtextmacro syntax. Throwing $ $ around everything should be suffecient if you really are concerned with people accidentally using them. That way we can create certain inline functions and constants that the optimizer would anyway inline. i.e.

Collapse JASS:
DECLARE $MYID$ 'I001'
DECLARE $ISNULLOREMPTY(x)$ ((x==null) or (x==""))
But we might be losing a bit of typesafety in doing so

Also perhaps you can add something like a static identifier to structs i.e.
Collapse JASS:
static struct math
So that vJass doesn't create the arrays and code for creating math objects as it is strictly for utility.

Pipedream I mean stuff like this

Collapse JASS:
//Currently we have native struct/object methods like
// these are essientially static methods on the the structs
GetUnitName(GetTriggerUnit())
//non-native means of call struct methods...
MyInstanceOfStruct.getName()

//constructor for native
Location(1,2)
//constructor for nonnative
pair.Create(1,2)

//deconstructor for native
RemoveLocation(l)
//deconstructor for nonnative
p.destroy()
08-21-2007, 04:35 PM#9
PipeDream
Oh sure, I love ruby syntax. Would be pretty neurotic to go through common.j manually wrapping each function though.
08-21-2007, 05:33 PM#10
Vexorian
Quote:
Originally Posted by PipeDream
Oh sure, I love ruby syntax. Would be pretty neurotic to go through common.j manually wrapping each function though.
"the plan" was always to eventually make wrappers of the natives, but that idea is in the queue after adding properties.