HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[cjass] RegisterTypes a macro library

10-01-2009, 05:10 AM#1
weaaddar
I've created a small little set of macros to ease the pain of lacking templates, lacking hashtable structs, and other still features to come.
The idea is to basically create simple one-liner methods that can be called while passing type information. These oneliners are simple, and will be inlined by vJass's optimizer, however we give the object's a uniform naming schema allowing one to call them as if they were generic. Once you have this Library in play it becomes easy to create generic classes.
However, there are some cons as these aren't truly natively supported you must mention type information for inheriting types.

Registering a type requires passing 6 pieces of information, the type,typename that appears in HT functions, method to return a hash value, basename that appears in HT functions,defaultvalue, and a to string method)
e.g. int,Integer,,Integer,0,I2S
unit,UnitHandle,GetHandleId,Handle,null,GetUnitName
string,Str,StringHash,String,null,
item,ItemHandle,GetHandleId,Handle,null,GetItemName

StructType,Integer,StructType.StaticMethodThatReturnsInteger,Integer,0,StructType.StaticMethodThatRe turnsString

Here is the entire library::
Code:
define <GetHashCode>(T) = GetHashCode_##T;
define <HashTableLoad>(T) = HashTableLoad_##T;
define <HashTableSave>(T) = HashTableSave_##T;
define <HashTableHave>(T) = HashTableHave_##T;
define <HashTableRemove>(T) = HashTableRemove_##T;
define <DefaultVal>(T) = DefaultVal_##T();
define <Stringify>(T) = Stringify_##T;
define RegisterType(T, TypeName,HashMethod, BaseName,DefaultValue,TtoString) = 
{
    T HashTableLoad(T)(hashtable ht,int pk,int ck)
    {
        return Load##TypeName(ht,pk,ck)
    }
    void HashTableSave(T)(hashtable ht,int pk,int ck,T value)
    {
        Save##TypeName(ht,pk,ck,value); 
    }
    
    bool HashTableHave(T)(hashtable ht,int pk,int ck)
    {
        return HaveSaved##BaseName(ht,pk,ck);
    }
    void HashTableRemove(T)(hashtable ht,int pk,int ck)
    {
        RemoveSaved##BaseName(ht,pk,ck);
    }
    int GetHashCode(T)(T key)
    {
        return HashMethod(key);
    }
    constant T DefaultVal_##T()
    {
        return DefaultValue;
    }
    
    string Stringify(T)(T obj)
    {
        return TtoString(obj);
    }
}


And some usage examples::
Collapse JASS:
RegisterType(int,Integer,,Integer,0,I2S);
RegisterType(string,Str,StringHash,String,null,);
RegisterType(unit,UnitHandle,GetHandleId,Handle,null,GetUnitName);

Great now why exactly would you want this in your map?
So you can make all sorts of interesting types. For instance, here is Dict(Tk,Tv) and List(T). Dict(Tk,Tv) is like Vex's table, except it takes any type for the key, and any type for the value. And List(T) is a fixed capacity or infinite length array with some helper functions thrown in for good measure.
Simplify calling section::
Code:
define Dict(Tk,Tv) = Dict_##Tk##Tv SPACE
define <new Dict>(Tk,Tv) = Dict(Tk,Tv).create

define List(T) = List_##T SPACE
define <new List>(T) = List(T).create
Expand InitDict:
Expand InitList method:

These can be applied to any registered type. You can even register these complex types.
Collapse JASS:
RegisterType(List(int),Integer,,Integer,0,List(int).AsString);
RegisterType(Dict(int,int),Integer,,Integer,0,Dict(int,int).AsString);
InitList(int);
InitList(List(int));
InitDict(int,int);
InitList(Dict(int,int));

I'm not going to bother submitting these as resources on the site as I realize only 4 wierdos like cJass, and I'm sure there exist efficient Lists and Dictionaries. These were merely examples and proof of concepts. Unfortunately, this objects will slow down if you try to use larger sizes just like normal vJass objects.
10-01-2009, 10:52 PM#2
Strilanc
It's common to use angle brackets for generic types: Cup<T> instead of Cup(T).

You should make the register type macro private. "RegisterType" is sortof a generic name, and If people want more types they should be putting the calls inside library not outside of it.
10-02-2009, 02:36 AM#3
weaaddar
D's templates are in parens. However, the real reason I'm using parens is that cJass currently doesn't have templatatic macro definitions.

Anyway this is just a way to create a uniform calling pattern, so you can use hashtables in macros/defines without constantly having to use multiple definitions. I included a strigifier as I felt it was a common need, stringifying things. Hashing is also useful for storing as keys. The rest of the methods are the standard api.