• 🏆 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!

LuckyParser: an abandoned JASS parser concept

Should JassHelper be updated?


  • Total voters
    56
Status
Not open for further replies.
You dont have to use the compiler do you?

I probably should :p

Some Suggestions for Luck:
- {} => Operator for array declaration
- :: => Operator for methods when used outside of the struct
- protected => Keyword for functions like onInit or onDestroy (Same as private, but it could be added for senseless reasons)
- ^ => Operator for Exponents (2^3 -> 2 * 2 * 2

I'm just throwing out some ideas to help you with your "operator" problem =P
 
These are some of the "benefits" I see in using Lucky Parser so far:

  • Optional parameters
  • "procedures" allow you to use more dynamic pre-processing than JassHelper, like increasing or decreasing an otherwise constant variable, or evaluating expressions like string != "" during compile-time instead of dynamically in-game.
  • No bugs. Can't guarantee this for the beta release at the end of the months, but I won't let bugs stay around.
  • nothing spam(): is faster to write and easier to read than function spam takes nothing returns nothing
  • General formatting shortcuts reduce development time (while, foreach, print, etc.)
  • More powerful pre-processing control in general.
  • The ability to freely declare onInit and onLoad multiple times
  • All initializers in a library fire before initializers in a library that requires it.
  • More dynamic hooks that allow you to hook the return, the beginning or completely replace the function.
  • Object-oriented programming that allows, for example, GetTriggerUnit().data.
  • More dynamic strings. Character strings, multiline strings and normal strings. Automatic I2S/R2S placement to allow syntax like "string" + integer

The general format might look like this:

Code:
library libName(libRequirement1, ...2, etc.): # Comment
    
 
    static integer i # A global integer, "internal" privacy
    
 
    boolean spam(integer(a, b, c), real r=0): # function spam takes integer a, integer b, integer c, real r = 0 returns boolean
        return a + b + c == r
    
 
    nothing check():
        local static integer i # A global variable privatized to this function
        
        foreach(i, 16): # Loops i from 0 to 15, not counting 16
            
            local integer j # A local variable declaration
            
            foreach(j, i, 0, -1): # Loops j from i to 0, decreasing by 1 per loop
                DoNothing()
    
 
    onInit: # A block executed during initialization, prioritized top-first
        
 
    onInit.priority: # A priority initializer, initialized before any others, prioritized with other priority onInit's top-first
    
 
    """
        A multi-line block comment.
    """
 
# Unindenting ends any block
 

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
539
If you have a dictarray, you can use da[parentKey][childKey] = this. Alternatively, you can nest dictionaries to accomplish similar looking things.

Ruby has a nice way of doing this.
Code:
h1 = Hash.new
h2 = Hash.new 66
h3 = Hash.new do |hash, key| # gets called if key is not in the hash
    hash[key] = Hash.new # also returns the new hash
end

h1[:non_existant_key] #=> nil
h2[:non_existant_key] #=> 66
h3[:non_existant_key] #=> {} # a new hash

For a possible std-lib...
 

BBQ

BBQ

Level 4
Joined
Jun 7, 2011
Messages
97
For the syntax highlighting, may I suggest jEdit over Notepad++? The highlighting capabilities of jEdit are infinite times better than those of Notepad++.

But on the other hand, Notepad++ is much more widely used, so I don't know.
 

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
539
JASS:
GetTriggerUnit.kill()
I seriously hope you don't do this.

You should have another operator, such as : like Lua, to do that dirty work. Leave . to the big kids.

Care to elaborate?
I'm not fluent in Lua, so correct me if i'm wrong, but as far as i understand the :-operator, it's only used because Lua itself has no understanding of object-orientation and so does not know smth. like 'this' (or in Lua 'self'. But you could choose another name for it, if you don't use the 'function table:name' convention). So the :-operator only acts as syntactic sugar for providing 'self' in functions?
So, as this new language knows it's object-orientated and knows what 'this' or 'self' means, there is no need for the :-operator, no?
 
Level 3
Joined
Jun 3, 2010
Messages
47
You can't get rid of the "function" keyword for callbacks and such.

Behold: A world without the function keyword.
JASS:
function handler takes nothing returns nothing
endfunction

function CrashGame takes nothing returns nothing
    call Player(14821424) // does this crash? pretend it does if it doesn't
endfunction

globals
    code handler = CrashGame
endglobals

function onInit takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    // if there's no function keyword, am I adding the handler variable or the function?
    call TriggerAddAction(t, handler)
endfunction
 

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
539
You can't get rid of the "function" keyword for callbacks and such.

Behold: A world without the function keyword.
JASS:
function handler takes nothing returns nothing
endfunction

function CrashGame takes nothing returns nothing
    call Player(14821424) // does this crash? pretend it does if it doesn't
endfunction

globals
    code handler = CrashGame
endglobals

function onInit takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    // if there's no function keyword, am I adding the handler variable or the function?
    call TriggerAddAction(t, handler)
endfunction

You can get rid of it if you only provide one scope for both variables and functions.
So the above would just throw an compiler error.
 
That's a good point and I appreciate that. In most cases, I've found myself using anonymous functions, so it's good to have more than one brain working on this so I can have a fresh perspective.

I'd prefer to throw a syntax error for this case. Because it's such an improbability and because there are really powerful scoping protocols in Luck, I feel that requiring the "function" keyword here would be overkill.

While I have intentionally kept some more robust words like "integer" instead of "int" and "boolean" instead of "bool" to keep things fairly intuitive, the disappearing "function" keyword is a change for the better, for some reasons.

Edit: "local integer array five[5]" would be silly. Why limit your array?

Frotty, I'm not sure what you're referring to by "local array" as that is already included in vanilla JASS.

One thing that you can do is local static integer array spam to create a global that's localized to the function. This is something I've gotten a lot of use out of when building my libraries and it has a bright future because it's AWESOME. OK, maybe I had too much sugar today.
 

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
539
Lately i was thinking if something like an autodestroy operator would make sense. Like in c, only allocating on the stack.
Code:
//don't mind the random syntax, just playing around
//also, normally you would do the action inside the enum-callback

//A spell action
function action nothing -> nothing
    let caster=GetTriggerUnit()
    let level=GetUnitAbilityLevel(caster, Id)
    let range=Range(level)
    GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(caster), GetUnitY(caster), range, null)
    ForGroup(ENUM_GROUP, autodestroy lambda nothing -> nothing
        UnitDamageTarget(caster, GetEnumUnit(), Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
    end)
end

// translated to
struct lambda_12
    unit caster
    integer level
    real range
endstruct

globals
    lambda_12 global_lambda_12
endglobals

function anonymous_function_12 takes nothing returns nothing
    call UnitDamageTarget(global_lambda_12.caster, GetEnumUnit(), Damage(global_lambda_12.level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
endfunction

function action takes nothing nothing nothing
    local unit caster=GetTriggerUnit()
    local integer level=GetUnitAbilityLevel(caster, Id)
    local real range=Range(level)
    local lambda_12 generated__1=lamda_12.create()
    call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(caster), GetUnitY(caster), range, null)
    set generated__1.caster=caster
    set generated__1.level=level
    set generated__1.range=range
    set global_lambda_12=generated__1
    call ForGroup(ENUM_GROUP, function anonymous_function_12)
    call generated__1.destroy()
endfunction
One problem with the above is ofcourse, that for different types of callbacks we would need to store the struct different (group-callbacks versus timer-callbacks). But that's a whole different discussion.

That way we could easily create closures, because we could easily differentiate between closures used for callbacks (see above) and closures which are used later (example).
Code:
//now without autodestroy
function adder integer x -> Function<integer,integer>
    return lambda integer y -> integer
        return x+y
    end
end

//...
let f=adder(7)
//...
print(f(5)) #-> 12
Or for things like event-data
Code:
//again, actions of a spell
function Actions nothing -> nothing
    local autodestroy event_data event=GetEventData()
    event.caster.do_some_damage(event.target)
    create_some_effect_in_between(event.caster, event.target)
    if event.level then
        //generated: event.destroy()
        return
    end
    event.caster.do_circle_damage(event.target_x, event.target_y)
    //generated: event.destroy()
end
One problem could be:
Code:
return event.level
which would result in
Code:
call event.destroy()
return event.level
But it is solvable. Or it's forbidden.

Or temporary vectors needed for calculations. Or anything temporary.
I'm just not sure if it's really needed. Real closures would really be neat, but is it worth the hassle?

______
I also made some thoughts about (user-defined) arrays/hashtables in jass.
JASS:
    function bla takes nothing returns nothing
        local level=44
        local dynamic_array a=[1,2,level]
    endfunction
    // compiled to
    function bla takes nothing returns nothing
        local level=44
        local dynamic_array a=dynamic_array.create().set(0, 1).set(1,2).set(2,level)
    endfunction
One could create own arrays/hashtabels with only implementing two methods
JASS:
interface Array
    method set takes integer index, integer value returns Array
    method get takes integer index returns integer
endinterface
The way set returns Array or the implementation this it's possible to chain the methods like above and create variable length arrays
JASS:
struct dynamic_array implements Array
    static hashtable storage=InitHashtable()

    method set takes integer index, integer value returns thistype
        call SaveInteger(storage, integer(this), index, value)
        return this
    endmethod

    method get takes integer index returns integer
        return LoadInteger(storage, integer(this), index)
    endmethod
 
endstruct
JASS:
local dynamic_array a=[1]
local tree_based_dynamic_array b=[1,2]
local dynamic_array c=[6,7]
local fixed_length_array d=fixed_length_array.new(5, [8,7])
local dynamic_array e=[5=>6, 7=>8]
//...
local dynamic_array a=dynamic_array.new().set(0,1)
local tree_based_dynamic_array b=tree_based_dynamic_array.new().set(0,1).set(1,2)
local dynamic_array c=dynamic_array.new().set(0,6).set(1,7)
local fixed_length_array d=fixed_length_array.new(5, standart_array.new().set(0,8).set(1,7))
local dynamic_array e=dynamic_array.new().set(5,6).set(7,8)

I just wrote that all down. There are probably still some rough edges, but, yeah, that was what i was thinking about. May it be some inspiration for you.
 
Status
Not open for further replies.
Top