1. Head to the 33rd Modeling Contest Poll and drink to your heart's desire.
    Dismiss Notice
  2. Choose your means of doom in the 17th Mini Mapping Contest Poll.
    Dismiss Notice
  3. A slave to two rhythms, the 22nd Terraining Contest is here.
    Dismiss Notice
  4. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  5. The die is cast - the 6th Melee Mapping Contest results have been announced. Onward to the Hive Cup!
    Dismiss Notice
  6. The glory of the 20th Icon Contest is yours for the taking!
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

JiffyJass - standalone Jass interpreter

Discussion in 'Warcraft Editing Tools' started by Aniki, Aug 14, 2020.

  1. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    562
    Resources:
    6
    Tools:
    1
    Maps:
    1
    Spells:
    1
    JASS:
    3
    Resources:
    6
    JiffyJass - standalone Jass interpreter

    Differences between Blizzard's Jass and JiffyJass:

    • characters in single quotes (rawcode literals) are used verbatim (no backslash escaping, i.e '\n' is an error)
    • there are no octal literals (0377 == 377, not 255)
    • globals blocks, types and natives can be declared in any order
    • variables that are not initialized on declaration are zero initialized
    • variable shadowing is not allowed
    • constant functions are not checked for global variable assignment
    • the binary '%' operator always returns a positive value (euclidean remainder)
    • an integer to real cast is also inserted in return statements
    • operations with reals (floating point numbers) can produce infinities and nans
    • strings are not Unicode aware
    • functions with any signature (not just code (taking/returing nothing)) can be used as values
    • arrays are first class values
    • maps, which are like arrays but their index/key can be any type, not just an integer
    • user defined types called structs


    Usage

    The command line invocation requires a command name followed by a command specific arguments:
    Code (Text):

    jj <command> <command-args>
     
    run command:
    Code (Text):

    jj run <files> [-- <script-args>]

    // examples:
    jj run main.j blizzard.j common.j
    jj run main.j -- arg1 arg2
    jj run common.j main.j // wrong file order
     
    Executes the script in the specified files by first initializing all global variables and then calls function main. The '--' separates the list of script files from the list of command line arguments that can be accessed by the script.
    The order of the script files is important. If file-1 depends on a declaration in file-2 then file-1 needs to come before file-2 in the run command invocation.

    check command:
    Code (Text):

    jj check <files>

    // examples:
    jj check main.j common.j
     
    Checks the specified files for parsing and typing errors. Does not run the script.

    help command:
    Code (Text):

    jj help
    jj // same as jj help
     
    Prints information about the other available commands.


    Alias declarations

    The 'alias' identifier is a reserved keyword in Jass (a variable with the name 'alias' cannot be declared). I don't know the semantics of the alias keyword in Blizzard's Jass but in JiffyJass it can be used to declare aliases to types, natives and functions.
    Code (vJASS):

    alias Foo = integer // 'Foo' is an alias for the 'integer' type
    globals
        Foo foo = 1
    endglobals

    native GetHandleId takes handle h returns integer
    alias H2I = GetHandleId // 'H2I' is an alias for the 'GetHandleId' native

    function veryLongFunctionName takes nothing returns nothing
    endfunction
    alias shorterName = veryLongFunctionName // 'shorterName' is an alias for the 'veryLongFunctionName' function
     



    Functions as values

    All functions can now be used as values, i.e they can be stored in variables, passed as arguments and returned from functions. There are no anonymous functions/lambdas though.

    Code (vJASS):

    function foo takes nothing returns nothing
        call jjPrintln("foo()")
    endfunction

    function bar takes nothing returns nothing
        call jjPrintln("bar()")
    endfunction

    function square takes integer x returns integer
        return x*x
    endfunction

    function fns1 takes nothing returns nothing
        local (function takes nothing returns nothing) f1
        local code f2  // 'code' is an alias for the above function type
        local (function takes integer returns integer) f3

        set f1 = function foo
        call f1()
        set f2 = bar // the function keyword can be omitted
        call f2()
        set f3 = square
        call jjPrintln(I2S(f3(2)))
    endfunction
     



    Arrays as values

    Arrays are now first class values i.e they can be stored in variables, passed as arguments and returned from functions. There are 2 new keywords that are used to create and destroy array values. The keyword 'new' is used to create a new array value with a specified element type. The 'delete' keyword is used to destroy an array value when it's no longer needed.

    Code (vJASS):

    alias ArrInt = integer array

    function sum takes integer n, ArrInt xs returns integer
        local integer sum = 0
        local integer a = 0
        loop
        exitwhen a == n
            set sum = sum + xs[a]
        set a = a + 1
        endloop
        return sum
    endfunction

    function main takes nothing returns nothing
        local ArrInt xs = new ArrInt
        set xs[0] = 1
        set xs[1] = 2
        set xs[2] = 3
        call jjPrintln(I2S(sum(3, xs)))
        delete xs
    endfunction
     


    For backwards compatibility global arrays are automatically 'new'ed. Local arrays without an initializer are zero initialized like other types.

    Code (vJASS):

    globals
        integer array xs1 = new integer array
        integer array xs2 // same as above, but the 'new integer array' is implicit here
        integer array xs3 = null // can use null if the initialization is done elsewhere
    endglobals
     


    There are no multidimensional arrays. One can emulate them with 1 dimensional arrays and indexing math or with jagged arrays.

    Code (vJASS):

    alias ArrInt = integer array
    alias ArrArrInt = ArrInt array

    function main takes nothing returns nothing
        local ArrArrInt xxs = new ArrArrInt
        set xxs[0] = new ArrInt
        set xxs[1] = new ArrInt
        set xxs[2] = new ArrInt

        set xxs[0][0] = 10
        set xxs[1][100] = 20
        set xxs[2][JASS_MAX_ARRAY_SIZE - 1] = 30

        call jjPrintln(I2S(xxs[0][0]))
        call jjPrintln(I2S(xxs[1][100]))
        call jjPrintln(I2S(xxs[2][JASS_MAX_ARRAY_SIZE - 1]))

        delete xxs[0]
        delete xxs[1]
        delete xxs[2]
        delete xxs
    endfunction
     


    There is no function overloading but there are builtin "generic" functions that can work with an array of any type. The placeholder type 'any' stands for any type.

    The functions 'arrlen', 'arrsetlen', 'arrput' and 'arrpop' query/modify an internal array "length" field. All arrays can still be indexed from 0 to JASS_ARRAY_SIZE-1 but this "length" field can be used to keep track of how many elements are logically in the array.

    Code (vJASS):

    // returns the value of the length field
    generic function arrlen takes any array xs returns integer

    // sets the value of the length field
    generic function arrsetlen takes any array xs, integer newLen returns nothing

    // the array's element type must match the type of 'x'
    // xs[len] = x; len += 1
    generic function arrput takes any array xs, any x returns nothing

    // if len == 0 then the zero value of the type is returned
    // if len > 0 then len -= 1; return xs[len]
    generic function arrpop takes any array xs returns any

    // copies/moves 'n' elements of array 'src' starting from index 'srcOff' to array 'dst'
    // dst[dstOff+0] = src[srcOff+0]
    // dst[dstOff+1] = src[srcOff+1]
    // ...
    // dst[dstOff+n - 1] = src[srcOff+n - 1]
    //
    // 'dst' and 'src' can overlap
    generic function arrmove takes integer n, any array dst, integer dstOff, any array src, integer srcOff returns nothing

    // 'start' and 'end' - half open interval [start, end)
    // dst[start] = x
    // dst[start+1] = x
    // ...
    // dst[start + (end - start) - 1] = x
    generic function arrset takes any x, any array dst, integer start, integer end returns nothing

    // returns the index of 'x' in 'xs' in the range [start, end)
    // if 'x' is not found then -1 is returned
    generic function arrlsearch takes any array xs, integer start, integer end, any x returns integer

    // returns the index of the first element in 'xs'/[start, end) for which the predicate 'p' returns true
    // if 'p' returns false for all of the elements in the range [start, end) then -1 is returned
    generic function arrlsearchfn takes any array xs, integer start, integer end, (function takes any x returns boolean) p returns integer

    // sorts the elements of 'xs'/[start, end) using the comparison function 'cmpFn'
    // the comparison function takes 2 arguments, 'a' and 'b', and returns:
    // an integer < 0 if 'a' < 'b'
    // an integer > 0 if 'a' > 'b'
    // and 0 if 'a' == 'b'
    generic function arrsort takes any array xs, integer start, integer end, (function takes any a, any b returns integer) cmpFn returns nothing

    // precondition: the 'xs' array must be sorted
    //
    // uses binary search to search for 'x' in 'xs'/[start, end) using the comparison function 'cmpFn' to narrow the search
    // the comparison function takes 2 arguments, 'a' and 'b', and returns:
    // an integer < 0 if 'a' < 'b'
    // an integer > 0 if 'a' > 'b'
    // and 0 if 'a' == 'b'
    //
    // returns the index of 'x', if 'x' is found (index >= 0)
    //
    // returns a biased index (index < 0) if 'x' is not found
    // the biased index can be "unbiased": unbiasedIdx = -biasedIdx - 1
    // an element can then be inserted at index = unbiasedIdx, such that the
    // 'xs' remains sorted
    generic function arrbsearch takes any x, any array xs, integer start, integer end, (function takes any a, any b returns integer) cmpFn returns integer


    alias ArrCode = code array

    function foo takes nothing returns nothing
        call jjPrintln("foo()")
    endfunction

    function bar takes nothing returns nothing
        call jjPrintln("bar()")
    endfunction

    function main takes nothing returns nothing
        local ArrCode fns = new ArrCode
        local integer n
        local integer a

        call arrput(fns, foo)
        call arrput(fns, bar)

        set n = arrlen(fns)
        set a = 0
        loop
        exitwhen a == n
            call fns[a]()
        set a = a + 1
        endloop

        loop
        exitwhen 0 == arrlen(fns)
            call arrpop(fns)()
        endloop
    endfunction
     



    Maps

    Maps/hashtables are similar to arrays but their index/key type is not restricted to integers. For symmetry with arrays they are automatically 'new'ed in globals blocks as well.

    Code (vJASS):

    alias MapStrInt = (map takes string returns integer)

    globals
        MapStrInt m1 = new MapStrInt
        MapStrInt m2 // same as above, but the 'new MapStrInt' is implicit here
        MapStrInt m3 = null // can use null if the initialization is done elsewhere
    endglobals

    function main takes nothing returns nothing
        set m1["A"] = 10

        call jjPrintln(I2S(m1["A"]))

         // if the key is not found the zero value of the type is returned
        call jjPrintln(I2S(m1["B"]))

        delete m1
        delete m2

        // passing null values to delete is okay
        delete m3
    endfunction
     


    There are a few "generic" functions for maps as well. Again, the type 'any' here stands for any type.

    Code (vJASS):

    // stores the keys of the map in the array 'keys' and returns the number of keys
    // the key type of the map must match the element type of the array
    generic function mapkeys takes (map takes any returns any) m, any array keys returns integer

    // removes key 'key' and its associated value from 'm'
    generic function mapdel takes (map takes any returns any) m, any key returns nothing

    // returns true if key 'key' is in 'm', otherwise returns false
    generic function maphave takes (map takes any returns any) m, any key returns boolean


    alias MapStrInt = (map takes string returns integer)

    function main takes nothing returns nothing
        local MapStrInt m = new MapStrInt
        local string array keys  = new string array
        local integer n
        local integer a

        set m["A"] = 10
        set m["B"] = 20

        set n = mapkeys(m, keys)
        set a = 0
        loop
        exitwhen a == n
            call jjPrintln("m[" + keys[a] + "] = " + I2S(m[keys[a]]))
        set a = a + 1
        endloop

        set a = n - 1
        loop
        exitwhen a == -1
            if maphave(m, keys[a]) then
                call jjPrintln("removing key '" + keys[a] + "'")
                call mapdel(m, keys[a])
            endif
        set a = a - 1
        endloop

        set n = mapkeys(m, keys)
        call jjPrintln(I2S(n))

        delete m
        delete keys
    endfunction
     



    User defined types/structs

    Structs are an aggregation of fields. They have reference semantics just like arrays and maps, i.e an assignment of 2 variables of a struct type does not copy the values of their corresponding fields, instead the two variables refer to the same struct value. Structs can extend other structs, this is the same as copying the fields of the base struct to the fields of the extending struct. If a struct does not extend another struct then it implicitly extends the 'Any' struct, which has no fields. Struct values have a builtin 'typename' field which returns the name of their struct type. This can be used to test the runtime type of a struct value and to safely do a downcast.

    Code (vJASS):

    struct Point2D
        real x
        real y
    endstruct

    function newPoint2D takes real x, real y returns Point2D
        local Point2D p = new Point2D
        set p.x = x
        set p.y = y
        return p
    endfunction

    function printPoint2D takes Point2D p returns nothing
        call jjPrintln("Point2D { x: " + R2S(p.x) + ", y: " + R2S(p.y) + " }")
    endfunction

    struct Point3D extends Point2D
        real z
    endstruct

    function newPoint3D takes real x, real y, real z returns Point2D
        local Point3D p = new Point3D
        set p.x = x
        set p.y = y
        set p.z = z
        return p
    endfunction

    function printPoint3D takes Point3D p returns nothing
        call jjPrintln("Point3D { x: " + R2S(p.x) + ", y: " + R2S(p.y) + ", z: " + R2S(p.z) + " }")
    endfunction

    function main takes nothing returns nothing
        local Point2D array pts
        local Point2D p
        local string T
        local integer n
        local integer a

        set pts = new Point2D array
        call arrput(pts, newPoint2D(1, 2))
        call arrput(pts, newPoint3D(3, 4, 5))
        call arrput(pts, newPoint2D(6, 7))

        set n = arrlen(pts)
        set a = 0
        loop
        exitwhen a == n
            set p = pts[a]
            set T = p.typename

            if Point2D == T then
                call printPoint2D(p)
            elseif Point3D == T then
                // downcast to Point3D
                call printPoint3D(p.(Point3D))
            else
                call assert(false)
            endif

        set a = a + 1
        endloop
    endfunction
     


    Another way to do dynamic dispatch, instead of the case analysis above. is to use fields of function types.

    Code (vJASS):

    struct Shape
        (function takes Shape s returns real) getArea
        (function takes Shape s returns string) toString
        real x
        real y
    endstruct

    function shapeGetArea takes Shape s returns real
        return s.getArea(s)
    endfunction

    function shapeToString takes Shape s returns string
        return s.toString(s)
    endfunction

    struct Rect extends Shape
        real w
        real h
    endstruct

    function rectGetArea takes Shape s returns real
        local Rect r = s.(Rect) // downcast
        return r.w * r.h
    endfunction

    function rectToString takes Shape s returns string
        local Rect r = s.(Rect)
        return "Rect { x: " + R2S(r.x) + ", y: " + R2S(r.y) + ", w: " + R2S(r.w) + ", h: " + R2S(r.h) + " }"
    endfunction

    function newRect takes real x, real y, real w, real h returns Rect
        local Rect r = new Rect
        set r.getArea = rectGetArea
        set r.toString = rectToString
        set r.x = x
        set r.y = y
        set r.w = w
        set r.h = h
        return r
    endfunction

    struct Circle extends Shape
        real r
    endstruct

    function circleGetArea takes Shape s returns real
        local Circle c = s.(Circle)
        return 3.14159 * c.r*c.r
    endfunction

    function circleToString takes Shape s returns string
        local Circle c = s.(Circle)
        return "Circle { x: " + R2S(c.x) + ", y: " + R2S(c.y) + ", r: " + R2S(c.r) + " }"
    endfunction

    function newCircle takes real x, real y, real r returns Circle
        local Circle c = new Circle
        set c.getArea = circleGetArea
        set c.toString = circleToString
        set c.x = x
        set c.y = y
        set c.r = r
        return c
    endfunction

    function main takes nothing returns nothing
        local Shape array shapes
        local Shape s
        local integer n
        local integer a

        set shapes = new Shape array
        call arrput(shapes, newRect(1, 2, 3, 4))
        call arrput(shapes, newCircle(5, 6, 7))
        call arrput(shapes, newRect(8, 9, 10, 11))

        set n = arrlen(shapes)
        set a = 0
        loop
        exitwhen a == n
            set s = shapes[a]
            call jjPrintln(shapeToString(s) + ", area: " + R2S(shapeGetArea(s)))
        set a = a + 1
        endloop
    endfunction
     



    Changelog


    1.0.12
    • bug fix: 'jjGetFileInfo' now does call 'CloseHandle'

    1.0.11
    • bug fix: comparison operators with real arguments in function argument context should now work
    • bug fix: S2I can now handle negative integers ("-1234")

    1.0.10
    • added the natives 'jjStringSearch', 'jjErrPrint', 'jjErrPrintln', 'jjGetCwd', 'jjSetCwd', 'jjCreateDir', 'jjRemoveDir', 'jjRemoveFile', 'jjDirGetFilenames', 'jjGetFileInfo', 'jjTimepointNowHi', 'jjTimepointNowLo', 'jjCompareTimepoints and 'jjBreakTimepoint'
    • natives that take string arguments to files/directories assume UTF-8 encoding
    • the strings returned by 'jjGetScriptArg' use UTF-8 encoding now

    1.0.9
    • added the functions 'arrmove', 'arrset', 'arrlsearch', 'arrlsearchfn', 'arrsort' and 'arrbsearch'
    • common.j now documents the generic functions

    1.0.8
    • removed the trigger and hashtable related natives because they can now be implemented in userland
    • added continue keyword for jumping at the start of a loop
    • all functions can now be used as values
    • arrays are now first class values
    • added maps
    • added user defined types/structs

    1.0.7
    • the alias keyword can now be used to declare aliases for types, natives and functions

    1.0.6
    • new function: assert (see 'jj help run')
    • the debug keyword can now be used to disable statements (see 'jj help run')

    1.0.5
    • new natives: jjTypecastS2I and jjTypecastI2S

    1.0.4
    • bug fix: arrays should now really be zero initialized

    1.0.3
    • crash fix: recovering from parse errors should no longer crash

    1.0.2
    • bug fix: assignment to constant crash
    • new native: jjBitcastI2R

    1.0.1
    • initial release

     

    Attached Files:

    Last edited: Oct 19, 2020
  2. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    562
    Resources:
    6
    Tools:
    1
    Maps:
    1
    Spells:
    1
    JASS:
    3
    Resources:
    6
    Big-ish update =). See changes for version 1.0.8.
     
  3. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    What are the advantages of JJ over

    1) Lua
    2) Wurst
    3) VJass

    ?
     
  4. Chaosy

    Chaosy

    Tutorial Reviewer

    Joined:
    Jun 9, 2011
    Messages:
    11,058
    Resources:
    18
    Icons:
    1
    Maps:
    1
    Spells:
    10
    Tutorials:
    6
    Resources:
    18
    The alias functionality is unique, I think the Any type as well.
     
  5. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    562
    Resources:
    6
    Tools:
    1
    Maps:
    1
    Spells:
    1
    JASS:
    3
    Resources:
    6
    I don't know... but you can let me know if you find any =).

    I know of a few disadvantages though:
    • there is no manual (the first post is hardly a manual...)
    • there are still lots of bugs probably (it's called JiffyJass because it takes less than a jiffy to run into a bug =), jk)
     
  6. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Yea, your new programming language should have clear advantages over the existing offerings, otherwise you are wasting your talent.

    For example with your talent
    You could write a vjass to lua preprocessor
    Or you could join the Wurst team and improve Wurst
    Or you can ask vexorian (if he's still alive) for jasshelper source and improve that

    If a brand new thing doesn't have any advantages, then it's an inferior version of the things that already exist.

    Here are advantages of these languages over yours:
    1 Lua - Industry standard for game scripting, mature language, supported by blizzard, battle-proven by netease wc3 to work properly. More efficient than jass.
    2 Wurst - Supports dynamic closures (Anon Functions). 'nuff said.
    3 Vjass - Wc3 standard. Supported by Blizzard. Battle proven for over 10 years of modding (99.9% no bugs). Efficient. Has TONS of free open source libraries/resources. Back-compatible with all contemporary versions of wc3.
     
  7. Retera

    Retera

    Tool Reviewer

    Joined:
    Apr 19, 2008
    Messages:
    1,028
    Resources:
    27
    Models:
    18
    Tools:
    2
    Maps:
    6
    Reforged HD Models:
    1
    Resources:
    27
    Hey, this looks interesting. Is JJ able to be included as a library in other projects?



    Here are some unit tests from a Java game that I am building on libgdx. My game has an in-progress jass interpreter that i used for some basic ingame tests but I have not spent time to make it fully developed.

    What would be the feasibility of including JiffyJass into my game? Is JiffyJass open source, so that it could be ported to Java, for example?
     
  8. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    562
    Resources:
    6
    Tools:
    1
    Maps:
    1
    Spells:
    1
    JASS:
    3
    Resources:
    6
    For the compilation of the script, JJ currently allocates memory and never frees it. There are tons of calls to 'exit' (process termination) throughout. Both of these things are unacceptable for a library... Writing anything, not just an interpreter, that's meant to be used as a library, is way way harder. So... you should stick to your Jass implementation and improve it, or switch to Lua (which is very much meant to be used as a library), or QuickJs, or anything else really (that was written by someone that knew what they were doing =)).

    If it weren't for some of your other videos (like the one in which you implement a parabolic projectile attacks in half an hour), I would say that you were pulling my leg, and making a recording of the regular game.... What you are doing is "next level". Kudos to you sir.


    I've written JiffyJass for my own amusement (and because I didn't want the name to go to waste, jiffy just sounded cool to me).

    I wouldn't touch jasshelper's source even if it was the last codebase on Earth (no offense to Vexorian).
     
  9. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    And why is that? Just curious. It seems JJ is just another vjass clone with some extra features to me, an untrained observer.

    I always wanted to ask someone who has made or making a vjass clone on why they do that instead of improving vjass...


    I guess you answered that question in the post above... "Amusement". heh.
     
  10. Retera

    Retera

    Tool Reviewer

    Joined:
    Apr 19, 2008
    Messages:
    1,028
    Resources:
    27
    Models:
    18
    Tools:
    2
    Maps:
    6
    Reforged HD Models:
    1
    Resources:
    27
    I actually think you're very wrong on understanding what JiffyJass is, but I am on vacation and did not try it yet personally. I'm just operating based on the written description of what JiffyJass is.

    JassHelper from Vexorian is a transpiler. It reads "vJASS code" and spits out equivalent JASS code, which is typically then used inside of a Warcraft 3 map. [It was also made using a technology called Delphi that I do not have experience with. It looked like compiling your own jasshelper from source is monstrous and difficult because Delphi programming language is not something people are taught nowadays.]

    My current cursory understanding of JiffyJass is that it allows you to execute JASS syntax code without using the Warcraft 3 game. Perhaps if you were an avid Warcraft 3 map developer, and you wanted to write a program to automatically add some entries to "war3mapSkin.txt" when you save your map as a folder -- or generate some extra code to put in your map -- you could write that generator program in jiffyjass.

    I was able to confirm this by looking at the example common.j included with JiffyJass. It includes natives such as:

    Code (Text):
    native jjReadEntireFile takes string fileName returns string
    native jjWriteEntireFile takes string fileName, string s returns boolean
    This is wholly different than vJASS in scope to the point that they probably should not be compared because they are not technologies achieving a similar purpose. That doesn't even mean one or the other is better. You could potentially use JassHelper to use high level language concepts that you then transpile to Jass, and then you could execute that Jass code using JiffyJass.

    So if you are a map script developer looking for a faster way to program the behavior of your game map, most likely JiffyJass is not the technology you are looking for, since there would be no way to ever embed the JiffyJass.exe interpreter into your map. Your map just cannot and will not ever have "native jjReadEntireFile" because Warcraft 3 does not permit us to read file by path. JiffyJass can do this, however, because it does not run from inside the map sandbox.
     
  11. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,789
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    There have been multiple attempts to improve upon JassHelper's source code, but nothing ever stuck. I know there were some bugs and backward compatibility issues with some of them.

    Also, the source code is a complete mess of spaghetti code.
     
  12. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    I'd like to say my interest in this is purely of academic curiosity and I'm only wishing to understand certain things...

    Is that true? I'd be interested in a standalone interpreter that can be plugged into another game engine in the future. But then again, we got LUA for that... Why wont you use LUA for your project?

    The purpose is same from point of view of a map developer, and that's stuff like move units, print stuff on screen, make projectiles, apply damage, do triggers, etc.

    Yeah can't fault people for not wanting to touch that, but the depth of resources available for vjass means the benefit for the community is additive on 10 years of modding, and that by itself is worth hundreds if not thousands of hours. If a new language is made then it would have to do what the Wurst team does, which is recreate most of the utility libraries. That's hellava job to do... more so than just rewriting vjass code not to be a giant cancer to work with.
     
  13. Retera

    Retera

    Tool Reviewer

    Joined:
    Apr 19, 2008
    Messages:
    1,028
    Resources:
    27
    Models:
    18
    Tools:
    2
    Maps:
    6
    Reforged HD Models:
    1
    Resources:
    27
    The point I was trying to make is that to the best of my current knowledge, the statement quoted above is false.
     
  14. Blarto

    Blarto

    Joined:
    Jan 17, 2010
    Messages:
    150
    Resources:
    1
    Spells:
    1
    Resources:
    1
    And why is that?

    I'm interested in this language but cannot see its benefits over lua...