- Joined
- Nov 7, 2014
- Messages
- 571
execute_func - a simple alternative to vJass's function objects and a type safe ExecuteFunc(<function-name-string>) for escaping the oplimit
vJass allows you to call functions/methods with func.evaluate(<args>) and func.execute(<args>)
example:
The generated script by jasshelper could look like:
So, some globals were added, 2 short functions were created and our function got copied
and a little bit modified so it all works correctly.
That's fine if we only had one function to .evaluate/.execute but if one is making
an average map (in terms of complexity) he would probably need to escape the oplimit
in a bit more places or use a library which would use .evaluate/.execute. And those generated
lines begin to add up.
What execute_func* allows, although less elegantly compared to .evaluate/.execute, is to call functions
that need to do a lot of work and could hit the oplimit.
The execute_func* "family" of functions work only with integers, reals and strings and only up to 3 parameters. (trying to avoid the combinatorial explosion...)
A simple naming convention is used:
When a function takes more than 1 parameter of the same type the letter of the type is
prepended with that count.
When a function doesn't take any parameters but returns an integer, real or a string the v letter is used in the
place of the parameters.
When a function returns nothing the v letter is not used, it's simply omitted.
Example usage:
The execute_func module's code (although the library/module is called executefunc because vJass complains):
And yes, that's a decent number of lines (~633), so if in your map you are using .evalute/.execute
only on a few functions and they are somewhat short, you should probably stick to .evalute/.execute instead.
vJass allows you to call functions/methods with func.evaluate(<args>) and func.execute(<args>)
example:
JASS:
function expensive_function takes integer i returns integer
local integer result = 21
// a lot of work needs to be done here and there are
set result = result + 1
// many
set result = result + 2
// many
// ....
// many lines
set result = result + 3
return result
endfunction
function main takes nothing returns nothing
// we don't want to hit the oplimit so we call .evaluate
local integer i = expensive_function.evaluate(3000)
endfunction
The generated script by jasshelper could look like:
JASS:
globals
//JASSHelper struct globals:
trigger array st___prototype1
integer f__result_integer
integer f__arg_integer1
endglobals
function sc___prototype1_execute takes integer i,integer a1 returns nothing
set f__arg_integer1=a1
call TriggerExecute(st___prototype1[i])
endfunction
function sc___prototype1_evaluate takes integer i,integer a1 returns integer
set f__arg_integer1=a1
call TriggerEvaluate(st___prototype1[i])
return f__result_integer
endfunction
function expensive_function takes integer i returns integer
local integer result= 21
// a lot of work needs to be done here
// and there are
set result=result + 1
// many
set result=result + 2
// many
// ....
// many lines
set result=result + 3
return result
endfunction
function main takes nothing returns nothing
// we don't want to hit the oplimit so we call .evaluate
local integer i= sc___prototype1_evaluate(1,3000)
call ExecuteFunc("jasshelper__initstructs32134833")
endfunction
//Struct method generated initializers/callers:
function sa___prototype1_expensive_function takes nothing returns boolean
local integer i=f__arg_integer1
local integer result= 21
set result=result + 1
set result=result + 2
set result=result + 3
set f__result_integer= result
return true
endfunction
function jasshelper__initstructs32134833 takes nothing returns nothing
set st___prototype1[1]=CreateTrigger()
call TriggerAddAction(st___prototype1[1],function sa___prototype1_expensive_function)
call TriggerAddCondition(st___prototype1[1],Condition(function sa___prototype1_expensive_function))
endfunction
So, some globals were added, 2 short functions were created and our function got copied
and a little bit modified so it all works correctly.
That's fine if we only had one function to .evaluate/.execute but if one is making
an average map (in terms of complexity) he would probably need to escape the oplimit
in a bit more places or use a library which would use .evaluate/.execute. And those generated
lines begin to add up.
What execute_func* allows, although less elegantly compared to .evaluate/.execute, is to call functions
that need to do a lot of work and could hit the oplimit.
The execute_func* "family" of functions work only with integers, reals and strings and only up to 3 parameters. (trying to avoid the combinatorial explosion...)
A simple naming convention is used:
JASS:
letter for type - type
i - integer
r - real
s - string
v - nothing (v for void, n could be confused for an iNteger)
When a function takes more than 1 parameter of the same type the letter of the type is
prepended with that count.
When a function doesn't take any parameters but returns an integer, real or a string the v letter is used in the
place of the parameters.
When a function returns nothing the v letter is not used, it's simply omitted.
Example usage:
JASS:
library executefuncDemo initializer init uses executefunc
function foo takes /*integer fooy*/ nothing returns nothing
local integer fooy = ef_i1
call BJDebugMsg("got foo: " + I2S(fooy))
endfunction
function pie takes nothing returns /*real*/ nothing
set ef_ret_r = bj_PI + bj_E
endfunction
function repeat_string takes /*string s, integer count*/ nothing returns /*string*/ nothing
local string s = ef_s1
local integer count = ef_i1
local string result = ""
loop
exitwhen count <= 0
set result = result + s
set count = count - 1
endloop
set ef_ret_s = result
endfunction
function init takes nothing returns nothing
local real my_pie
call execute_func_i(function foo, 5)
// NOTE: even though our "made up" signature for repeat_string is
// function repeat_string takes /*string s, integer count*/ nothing returns /*string*/ nothing
// the order of the parameters of execute_func_* is fixed: i, r, s
call BJDebugMsg(execute_func_is_s(function repeat_string, 10, "bar"))
set my_pie = execute_func_v_r(function pie)
call BJDebugMsg(R2S(my_pie))
endfunction
endlibrary
The execute_func module's code (although the library/module is called executefunc because vJass complains):
JASS:
library executefunc initializer execute_func_init
globals
force ef_force = CreateForce()
integer ef_i1 = 0
integer ef_i2 = 0
integer ef_i3 = 0
integer ef_ret_i = 0
real ef_r1 = 0
real ef_r2 = 0
real ef_r3 = 0
real ef_ret_r = 0
string ef_s1 = ""
string ef_s2 = ""
string ef_s3 = ""
string ef_ret_s = ""
endglobals
// This should be safer than ExecuteFunc("<function-name>")
// because it doesn't take a string, which could have a typo and won't
// be caught by the compiler.
function execute_func takes code func returns nothing
call ForForce(ef_force, func)
endfunction
// PARAMS COUNT: 0
// RETURN TYPE: integer
function execute_func_v_i takes code func returns integer
call execute_func(func)
return ef_ret_i
endfunction
// RETURN TYPE: real
function execute_func_v_r takes code func returns real
call execute_func(func)
return ef_ret_r
endfunction
// RETURN TYPE: string
function execute_func_v_s takes code func returns string
call execute_func(func)
return ef_ret_s
endfunction
// PARAMS COUNT: 1
// RETURN TYPE: nothing
function execute_func_i takes code func, integer i1 returns nothing
set ef_i1 = i1
call execute_func(func)
endfunction
function execute_func_r takes code func, real r1 returns nothing
set ef_r1 = r1
call execute_func(func)
endfunction
function execute_func_s takes code func, string s1 returns nothing
set ef_s1 = s1
call execute_func(func)
endfunction
// RETURN TYPE: integer
function execute_func_i_i takes code func, integer i1 returns integer
set ef_i1 = i1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_r_i takes code func, real r1 returns integer
set ef_r1 = r1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_s_i takes code func, string s1 returns integer
set ef_s1 = s1
call execute_func(func)
return ef_ret_i
endfunction
// RETURN TYPE: real
function execute_func_i_r takes code func, integer i1 returns real
set ef_i1 = i1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_r_r takes code func, real r1 returns real
set ef_r1 = r1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_s_r takes code func, string s1 returns real
set ef_s1 = s1
call execute_func(func)
return ef_ret_r
endfunction
// RETURN TYPE: string
function execute_func_i_s takes code func, integer i1 returns string
set ef_i1 = i1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_r_s takes code func, real r1 returns string
set ef_r1 = r1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_s_s takes code func, string s1 returns string
set ef_s1 = s1
call execute_func(func)
return ef_ret_s
endfunction
// PARAMS COUNT: 2
// RETURN TYPE: nothing
function execute_func_2i takes code func, integer i1, integer i2 returns nothing
set ef_i1 = i1
set ef_i2 = i2
call execute_func(func)
endfunction
function execute_func_ir takes code func, integer i1, real r1 returns nothing
set ef_i1 = i1
set ef_r1 = r1
call execute_func(func)
endfunction
function execute_func_is takes code func, integer i1, string s1 returns nothing
set ef_i1 = i1
set ef_s1 = s1
call execute_func(func)
endfunction
function execute_func_2r takes code func, real r1, real r2 returns nothing
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
endfunction
function execute_func_rs takes code func, real r1, string s1 returns nothing
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
endfunction
function execute_func_2s takes code func, string s1, string s2 returns nothing
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
endfunction
// RETURN TYPE: integer
function execute_func_2i_i takes code func, integer i1, integer i2 returns integer
set ef_i1 = i1
set ef_i2 = i2
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_ir_i takes code func, integer i1, real r1 returns integer
set ef_i1 = i1
set ef_r1 = r1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_is_i takes code func, integer i1, string s1 returns integer
set ef_i1 = i1
set ef_s1 = s1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_2r_i takes code func, real r1, real r2 returns integer
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_rs_i takes code func, real r1, string s1 returns integer
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_2s_i takes code func, string s1, string s2 returns integer
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_i
endfunction
// RETURN TYPE: real
function execute_func_2i_r takes code func, integer i1, integer i2 returns real
set ef_i1 = i1
set ef_i2 = i2
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_ir_r takes code func, integer i1, real r1 returns real
set ef_i1 = i1
set ef_r1 = r1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_is_r takes code func, integer i1, string s1 returns real
set ef_i1 = i1
set ef_s1 = s1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_2r_r takes code func, real r1, real r2 returns real
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_rs_r takes code func, real r1, string s1 returns real
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_2s_r takes code func, string s1, string s2 returns real
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_r
endfunction
// RETURN TYPE: string
function execute_func_2i_s takes code func, integer i1, integer i2 returns string
set ef_i1 = i1
set ef_i2 = i2
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_ir_s takes code func, integer i1, real r1 returns string
set ef_i1 = i1
set ef_r1 = r1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_is_s takes code func, integer i1, string s1 returns string
set ef_i1 = i1
set ef_s1 = s1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_2r_s takes code func, real r1, real r2 returns string
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_rs_s takes code func, real r1, string s1 returns string
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_2s_s takes code func, string s1, string s2 returns string
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_s
endfunction
// PARAMS COUNT: 3
// RETURN TYPE: nothing
function execute_func_3i takes code func, integer i1, integer i2, integer i3 returns nothing
set ef_i1 = i1
set ef_i2 = i2
set ef_i3 = i3
call execute_func(func)
endfunction
function execute_func_2ir takes code func, integer i1, integer i2, real r1 returns nothing
set ef_i1 = i1
set ef_i2 = i2
set ef_r1 = r1
call execute_func(func)
endfunction
function execute_func_2is takes code func, integer i1, integer i2, string s1 returns nothing
set ef_i1 = i1
set ef_i2 = i2
set ef_s1 = s1
call execute_func(func)
endfunction
function execute_func_i2r takes code func, integer i1, real r1, real r2 returns nothing
set ef_i1 = i1
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
endfunction
function execute_func_irs takes code func, integer i1, real r1, string s1 returns nothing
set ef_i1 = i1
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
endfunction
function execute_func_i2s takes code func, integer i1, string s1, string s2 returns nothing
set ef_i1 = i1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
endfunction
function execute_func_3r takes code func, real r1, real r2, real r3 returns nothing
set ef_r1 = r1
set ef_r2 = r2
set ef_r3 = r3
call execute_func(func)
endfunction
function execute_func_2rs takes code func, real r1, real r2, string s1 returns nothing
set ef_r1 = r1
set ef_r2 = r2
set ef_s1 = s1
call execute_func(func)
endfunction
function execute_func_r2s takes code func, real r1, string s1, string s2 returns nothing
set ef_r1 = r1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
endfunction
function execute_func_3s takes code func, string s1, string s2, string s3 returns nothing
set ef_s1 = s1
set ef_s2 = s2
set ef_s3 = s3
call execute_func(func)
endfunction
// RETURN TYPE: integer
function execute_func_3i_i takes code func, integer i1, integer i2, integer i3 returns integer
set ef_i1 = i1
set ef_i2 = i2
set ef_i3 = i3
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_2ir_i takes code func, integer i1, integer i2, real r1 returns integer
set ef_i1 = i1
set ef_i2 = i2
set ef_r1 = r1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_2is_i takes code func, integer i1, integer i2, string s1 returns integer
set ef_i1 = i1
set ef_i2 = i2
set ef_s1 = s1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_i2r_i takes code func, integer i1, real r1, real r2 returns integer
set ef_i1 = i1
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_irs_i takes code func, integer i1, real r1, string s1 returns integer
set ef_i1 = i1
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_i2s_i takes code func, integer i1, string s1, string s2 returns integer
set ef_i1 = i1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_3r_i takes code func, real r1, real r2, real r3 returns integer
set ef_r1 = r1
set ef_r2 = r2
set ef_r3 = r3
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_2rs_i takes code func, real r1, real r2, string s1 returns integer
set ef_r1 = r1
set ef_r2 = r2
set ef_s1 = s1
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_r2s_i takes code func, real r1, string s1, string s2 returns integer
set ef_r1 = r1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_i
endfunction
function execute_func_3s_i takes code func, string s1, string s2, string s3 returns integer
set ef_s1 = s1
set ef_s2 = s2
set ef_s3 = s3
call execute_func(func)
return ef_ret_i
endfunction
// RETURN TYPE: real
function execute_func_3i_r takes code func, integer i1, integer i2, integer i3 returns real
set ef_i1 = i1
set ef_i2 = i2
set ef_i3 = i3
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_2ir_r takes code func, integer i1, integer i2, real r1 returns real
set ef_i1 = i1
set ef_i2 = i2
set ef_r1 = r1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_2is_r takes code func, integer i1, integer i2, string s1 returns real
set ef_i1 = i1
set ef_i2 = i2
set ef_s1 = s1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_i2r_r takes code func, integer i1, real r1, real r2 returns real
set ef_i1 = i1
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_irs_r takes code func, integer i1, real r1, string s1 returns real
set ef_i1 = i1
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_i2s_r takes code func, integer i1, string s1, string s2 returns real
set ef_i1 = i1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_3r_r takes code func, real r1, real r2, real r3 returns real
set ef_r1 = r1
set ef_r2 = r2
set ef_r3 = r3
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_2rs_r takes code func, real r1, real r2, string s1 returns real
set ef_r1 = r1
set ef_r2 = r2
set ef_s1 = s1
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_r2s_r takes code func, real r1, string s1, string s2 returns real
set ef_r1 = r1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_r
endfunction
function execute_func_3s_r takes code func, string s1, string s2, string s3 returns real
set ef_s1 = s1
set ef_s2 = s2
set ef_s3 = s3
call execute_func(func)
return ef_ret_r
endfunction
// RETURN TYPE: string
function execute_func_3i_s takes code func, integer i1, integer i2, integer i3 returns string
set ef_i1 = i1
set ef_i2 = i2
set ef_i3 = i3
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_2ir_s takes code func, integer i1, integer i2, real r1 returns string
set ef_i1 = i1
set ef_i2 = i2
set ef_r1 = r1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_2is_s takes code func, integer i1, integer i2, string s1 returns string
set ef_i1 = i1
set ef_i2 = i2
set ef_s1 = s1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_i2r_s takes code func, integer i1, real r1, real r2 returns string
set ef_i1 = i1
set ef_r1 = r1
set ef_r2 = r2
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_irs_s takes code func, integer i1, real r1, string s1 returns string
set ef_i1 = i1
set ef_r1 = r1
set ef_s1 = s1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_i2s_s takes code func, integer i1, string s1, string s2 returns string
set ef_i1 = i1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_3r_s takes code func, real r1, real r2, real r3 returns string
set ef_r1 = r1
set ef_r2 = r2
set ef_r3 = r3
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_2rs_s takes code func, real r1, real r2, string s1 returns string
set ef_r1 = r1
set ef_r2 = r2
set ef_s1 = s1
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_r2s_s takes code func, real r1, string s1, string s2 returns string
set ef_r1 = r1
set ef_s1 = s1
set ef_s2 = s2
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_3s_s takes code func, string s1, string s2, string s3 returns string
set ef_s1 = s1
set ef_s2 = s2
set ef_s3 = s3
call execute_func(func)
return ef_ret_s
endfunction
function execute_func_init takes nothing returns nothing
call ForceAddPlayer(ef_force, Player(15))
endfunction
endlibrary
And yes, that's a decent number of lines (~633), so if in your map you are using .evalute/.execute
only on a few functions and they are somewhat short, you should probably stick to .evalute/.execute instead.