When KoLmafia wants to execute an ASH script, it looks for an Interpreter pre-loaded with that script. If it finds one and neither the script nor any of its included scripts have changed since the Interpreter was created, it uses it. Otherwise, it makes a new Interpreter and parses the script into it.
Every time a script is executed, the Interpreter does the following:
- executes all the top-level commands in the script and included libraries
- executes the "main" function of the script, if any.
There are currently three exceptions to this:
- The forms of adventure() and adv1() that specify a filter function execute a single function in the context of the currently executing script. It will not execute the top-level commands.
- KoLmafiaASH.getScriptHTML() will execute a single function in the specified relay script. It will not execute the top-level commands. This function is never called.
- You can execute a single ASH function from the current "namespace". This will execute the top-level commands the first time the namespace file is executed, but not again unless it is reloaded.
Every other script - before battle scripts, recovery scripts, counter scripts, consult scripts - operates as described: execute top-level commands followed by "main".
What can go into top-level commands?
- global variables
- assignment statements
- arbitrary function calls or other ash constructs
Note that declaring a global variable implicitly assigns it an initial value, whether or not you specify one.
int a = 5;
assigns the value 5 to variable a.
int a;
assigns the value 0 to a. Similarly:
string [int] map;
map[ 1 ] = "one";
map[ 2 ] = "two"
assigns an empty map to variable "map" and then creates two mappings in it.
It seems to me that there are two kinds of global data that scripts want to use:
- Real variables
- Constant data, initialized by hand or via file_to_map, and never changed thereafter.
The former is like Java "static" data. The latter is like Java "static final" data.
I believe that we could allow that distinction for the use of ASH scripts, too: top-level commands are executed every time a script is executed, but the script could designate some of those commands as "final" to specify that they will be executed exactly once within a particular interpreter. The next time the script runs in the same interpreter, those declarations/assignments/function calls/whatever will be skipped.
Obviously, the programmer has to be careful deciding which commands should be "final"; most likely, only commands that initialize data that will really never change from execution to execution, although I can imagine scripts that "learn" over the course of multiple executions and want to augment or change their permanent data each time without having to write it out to disk and reload it.
I propose the following:
Thoughts?
Every time a script is executed, the Interpreter does the following:
- executes all the top-level commands in the script and included libraries
- executes the "main" function of the script, if any.
There are currently three exceptions to this:
- The forms of adventure() and adv1() that specify a filter function execute a single function in the context of the currently executing script. It will not execute the top-level commands.
- KoLmafiaASH.getScriptHTML() will execute a single function in the specified relay script. It will not execute the top-level commands. This function is never called.
- You can execute a single ASH function from the current "namespace". This will execute the top-level commands the first time the namespace file is executed, but not again unless it is reloaded.
Every other script - before battle scripts, recovery scripts, counter scripts, consult scripts - operates as described: execute top-level commands followed by "main".
What can go into top-level commands?
- global variables
- assignment statements
- arbitrary function calls or other ash constructs
Note that declaring a global variable implicitly assigns it an initial value, whether or not you specify one.
int a = 5;
assigns the value 5 to variable a.
int a;
assigns the value 0 to a. Similarly:
string [int] map;
map[ 1 ] = "one";
map[ 2 ] = "two"
assigns an empty map to variable "map" and then creates two mappings in it.
It seems to me that there are two kinds of global data that scripts want to use:
- Real variables
- Constant data, initialized by hand or via file_to_map, and never changed thereafter.
The former is like Java "static" data. The latter is like Java "static final" data.
I believe that we could allow that distinction for the use of ASH scripts, too: top-level commands are executed every time a script is executed, but the script could designate some of those commands as "final" to specify that they will be executed exactly once within a particular interpreter. The next time the script runs in the same interpreter, those declarations/assignments/function calls/whatever will be skipped.
Obviously, the programmer has to be careful deciding which commands should be "final"; most likely, only commands that initialize data that will really never change from execution to execution, although I can imagine scripts that "learn" over the course of multiple executions and want to augment or change their permanent data each time without having to write it out to disk and reload it.
I propose the following:
Code:
// The following will be executed every time the script executes:
int level = my_level();
string path = my_path();
// The following will be executed the first time a script executes in a session:
final
{
string [int] map;
map[ 1 ] = "one";
map[ 2 ] = "two";
string [int] map2;
file_to_map( "bigfile.txt", map2 );
}
Thoughts?
Last edited: