diff --git a/artifacts/scripting/compiler/optimization.md b/artifacts/scripting/compiler/optimization.md index f241576a..3aa8a305 100644 --- a/artifacts/scripting/compiler/optimization.md +++ b/artifacts/scripting/compiler/optimization.md @@ -8,12 +8,12 @@ The executation speed of scripts is not typically important in an unmodded game, The sfall build of sslc supports a `-O` command line option to perform an optimization pass over the generated code. This isn't a magic make-my-code-go-faster bullet; most of what it does is very limited in scope. It's primary purpose was to strip out the procedures and variables which get automatically pulled into every script that includes **define.h**, whether you use them or not, and to do something about the additional variables that get created by `foreach` loops. -There are several levels of optimization available: +**There are several levels of optimization available:** - `-O1` - Basic, only removes unreferenced globals variables and procedures, code itself remains untouched. - `-O2` - Full, most code optimizations are on, but only those that were tested on complex scripts. - `-O3` - Experimental, provides most efficiency, but tend to break some complex code due to bugs. -The following optimizations are performed: +**The following optimizations are performed:** - constant expression folding: if an expression depends only on values which are known at compile time, then the expression is replaced by its result. ``` @@ -103,8 +103,8 @@ The following optimizations are performed: -> end ``` -- Mark functions with **pure** or **inline** where relevent. +- Mark functions with `pure` or `inline` where relevent. - * 'pure' is a hint to the optimizer that a procedure has no side effects. (i.e. there's no way to tell that it's been called aside from its return value.) Pure procedures cannot modify global variables, or call any other procedure that isn't itself pure. Functions marked with pure can only be used in expressions (i.e. you cannot use the `call ` syntax to call them.) If there are non-pure terms in an expression, it prevents that expression being considered for dead store removal. Where no such optimizations can be performed, or if optimization is disabled, marking a procedure with pure will have no effect on the compiled code. + * `pure` is a hint to the optimizer that a procedure has no side effects. (i.e. there's no way to tell that it's been called aside from its return value.) Pure procedures cannot modify global variables, or call any other procedure that isn't itself pure. Functions marked with pure can only be used in expressions (i.e. you cannot use the `call ` syntax to call them.) If there are non-pure terms in an expression, it prevents that expression being considered for dead store removal. Where no such optimizations can be performed, or if optimization is disabled, marking a procedure with pure will have no effect on the compiled code. - * 'inline' is an instruction to the compiler to replace calls to the marked procedure with a copy of the procedures code instead of having a seperate call. Inlined procedures cannot use the `return` command, cannot be predefined, and cannot be used as part of an expression. Inlining if a procedure is only going to be called once is always a win, but if there are multiple calls to a procedure you will end up bloating the size of the generated code. + * `inline` is an instruction to the compiler to replace calls to the marked procedure with a copy of the procedures code instead of having a seperate call. Inlined procedures cannot use the `return` command, cannot be predefined, and cannot be used as part of an expression. Inlining if a procedure is only going to be called once is always a win, but if there are multiple calls to a procedure you will end up bloating the size of the generated code. diff --git a/artifacts/scripting/compiler/sslc_readme.md b/artifacts/scripting/compiler/sslc_readme.md index 384245ba..eb7cb0e9 100644 --- a/artifacts/scripting/compiler/sslc_readme.md +++ b/artifacts/scripting/compiler/sslc_readme.md @@ -5,9 +5,9 @@ This is a modified copy of sslc, that has a few bugfixes from the original, that Unlike the original script compiler, this has not been compiled as a dos program. When using this in place of the original compile.exe but still using p.bat, you need to either get rid of the dos4gw.exe reference from p.bat or replace the original dos4gw.exe with the one in this archive. -If you use fallout script editor, you can extract `compile.exe` and `dos4gw.exe` to its `\binary` folder, or extract them somewhere else and change your preferences in FSE to point there. FSE doesn't seem to be able to tell when errors occur when using this compiler though, so I'd recommend either using sfall's script editor instead or compiling by hand if possible. +If you use Fallout Script Editor, you can extract `compile.exe` and `dos4gw.exe` to its `\binary` folder, or extract them somewhere else and change your preferences in FSE to point there. FSE doesn't seem to be able to tell when errors occur when using this compiler though, so I'd recommend either using sfall's script editor instead or compiling by hand if possible. -When compiling global or hook scripts for sfall 3.4 or below, you _must_ include the line `procedure start;` before any `#include`s that define procedures to avoid a few weird problems. (this is no longer required starting from 3.5) +When compiling global or hook scripts for sfall 3.4 or below, you _must_ include the line `procedure start;` before any `#include` files that define procedures to avoid a few weird problems. (this is no longer required starting from 3.5) This version of compiler was designed primarily for new sfall functions, but it can safely (and is recommended) to be used with non-sfall scripts as well, as long as you don't use any of the arrays syntax and any sfall scripting functions. @@ -23,7 +23,7 @@ The original unmodified sslc source is over here: [http://www.teamx.ru/site_arc/ -p preprocess source -P preprocess only (don't generate .int) -F write full file paths in "#line" directives --O optimize code (full, see optimization.md) +-O optimize code (full by default, see optimization.md) -O set specific level of optimization (0 - off, 1 - basic, 2 - full, 3 - experimental) -d print debug messages -D output an abstract syntax tree of the program @@ -119,7 +119,7 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by variable tile; tile := tile_num(dude_obj); ``` - __NOTE:__ if your expression starts with a constant (eg. `2 + 2`), enclose it in parentheses, otherwise compiler will be confused and give you errors. + __NOTE:__ If your expression starts with a constant (eg. `2 + 2`), enclose it in parentheses, otherwise compiler will be confused and give you errors. - Hexadecimal numerical constants: Simply prefix a number with `0x` to create a hexadecimal. The numbers 0 to 9 and A-F are allowed in the number. The number may not have a decimal point. - new: @@ -141,7 +141,7 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by a += 1; ``` -- `break` & `continue` statements: they work just like in most high-level languages. `break` jumps out of the loop. `continue` jumps right to the beginning of the next iteration (see `for` and `foreach` sections for additional details). +- `break` & `continue` statements: They work just like in most high-level languages. `break` jumps out of the loop. `continue` jumps right to the beginning of the next iteration (see `for` and `foreach` sections for additional details). - new: ``` while (i < N) begin @@ -220,7 +220,7 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by end ``` -- **(Does not work currently)** empty statements in blocks are allowed: This is just a convenience to save scripters a bit of memory. Some of the macros in the fallout headers include their own semicolons while others do not. With the original compiler you had to remember which was which, and if you got it wrong the script would not compile. Now it's always safe to include your own semicolon, even if the macro already had its own. For example, this would not compile with the original sslc, but will with the sfall edition: +- Empty statements in blocks are allowed: This is just a convenience to save scripters a bit of memory. Some of the macros in the Fallout headers include their own semicolons while others do not. With the original compiler you had to remember which was which, and if you got it wrong the script would not compile. Now it's always safe to include your own semicolon, even if the macro already had its own. For example, this would not compile with the original sslc, but will with the sfall edition: ``` #define my_macro diplay_msg("foo"); @@ -228,12 +228,9 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by my_macro; end ``` + __NOTE:__ **Does not work currently.** -- Procedure stringify operator `@`: designed to make callback-procedures a better option and allow for basic functional programming. Basically it replaces procedure names preceeded by `@` by a string constant. - Not many people know that since vanilla Fallout you can call procedures by "calling a variable" containing it's name as a string value. There was a couple of problems using this: - - optimizer wasn't aware that you are referencing a procedure, and could remove it, if you don't call it explicitly (can be solved by adding making procedure "critical") - - you couldn't see all references of a procedure from a Script Editor - - it was completely not obvious that you could do such a thing, it was a confusing syntax +- Procedure stringify operator `@`: Designed to make callback-procedures a better option and allow for basic functional programming. Basically it replaces procedure names preceeded by `@` by a string constant. - old: ``` callbackVar := "Node000"; @@ -244,8 +241,12 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by callbackVar := @Node000; callbackVar(); ``` + Not many people know that since vanilla Fallout you can call procedures by "calling a variable" containing it's name as a string value. There was a couple of problems using this: + - optimizer wasn't aware that you are referencing a procedure, and could remove it, if you don't call it explicitly (can be solved by adding making procedure `critical`) + - you couldn't see all references of a procedure from a Script Editor + - it was completely not obvious that you could do such a thing, it was a confusing syntax -- __*__ Arrays: In vanilla fallout arrays had to be constructed by reserving a block of global/map variables. Since sfall 2.7, specific array targeted functions have been available, but they are fairly messy and long winded to use. The compiler provides additional syntactic shorthand for accessing and setting array variables, as well as for array creation. When declaring an array variable, put a constant integer in []'s to give the number of elements in the array. (before sfall 3.4 you had to specify size in bytes for array elements, now it's not required, see **arrays.md** for more information) +- (*) **Arrays**: In vanilla Fallout, arrays had to be constructed by reserving a block of global/map variables. Since sfall 2.7, specific array targeted functions have been available, but they are fairly messy and long winded to use. The compiler provides additional syntactic shorthand for accessing and setting array variables, as well as for array creation. When declaring an array variable, put a constant integer in `[]`` to give the number of elements in the array. (before sfall 3.4 you had to specify size in bytes for array elements, now it's not required, see **arrays.md** for more information) - new: ``` procedure bingle begin @@ -266,7 +267,7 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by end ``` -- __*__ Array expressions: sometimes you need to construct an array of elements and you will probably want to do it in just one expression. This is now possible: +- (*) **Array expressions**: Sometimes you need to construct an array of elements and you will probably want to do it in just one expression. This is now possible: - new: ``` list := ["A", "B", "C", "D"]; @@ -281,12 +282,12 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by ``` Syntax specific for associative arrays is also available. (see **arrays.md** for full introduction to this type of arrays). -- __*__ Map array expressions: +- (*) **Map array expressions**: ``` map := {5: "five", 10: "ten", 15: "fifteen", 20: "twelve"}; ``` -- __*__ "dot" syntax to access elements of associative arrays. "dot" syntax allows to work with arrays like objects: +- (*) The dot `.` syntax to access elements of associative arrays and allow to work with arrays like objects: ``` trap.radius := 3; trap.tile := tile_num(dude_obj); @@ -295,10 +296,9 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by ``` collectionList[5].objectList[5].name += " foo"; ``` + __NOTE:__ When using incremental operators like `+=`, `*=`, `++`, `--` compiler will use additional temp variable to get an array at penultimate level in order to avoid making the same chain of `get_array` calls twice. - __NOTE:__ when using incremental operators like `+=`, `*=`, `++`, `--` compiler will use additional temp variable to get an array at penultimate level in order to avoid making the same chain of "get_array" calls twice. - -- __*__ `foreach` loops: A shorthand method of looping over all elements in an array. Syntax is `foreach ( in )`. +- (*) `foreach` loops: A shorthand method of looping over all elements in an array. Syntax is `foreach ( in )`. - new: ``` procedure bingle begin @@ -332,7 +332,7 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by If you want to add additional condition for continuing the loop, use syntax: `foreach ( in while )`. In this case loop will iterate over elements of an array until last element or until "while" expression is true (whatever comes first). - __NOTE:__ just like `for` loop, `continue` statement will respect increments of a hidden counter variable, so you can safely use it inside `foreach`. + __NOTE:__ Just like `for` loop, `continue` statement will respect increments of a hidden counter variable, so you can safely use it inside `foreach`. --- @@ -379,7 +379,7 @@ There are several changes in this version of sslc which may result in problems f - the basic optimization is now enabled by default when not specifying any optimization options - added `-m` option to define a macro named "macro" for conditional compilation - added `-I` option to specify an additional directory to search for include files -- unreferenced **critical** procedures and procedures with the names `Node998` and `Node999` are now removed by the optimizer +- unreferenced `critical` procedures and procedures with the names `Node998` and `Node999` are now removed by the optimizer **sfall 4.2:** - now it is possible to run preprocess or optimization passes in backward compatibility mode @@ -397,9 +397,9 @@ There are several changes in this version of sslc which may result in problems f **sfall 3.6:** - added Python-style ternary operator (conditional expression) - added `-s` short-circuit evalution option for `AND`, `OR` expressions -- int2ssl will detect and decompile conditional expressions and short-circuit logical operators -- added `-F` option to include full file paths in "#line" directives after preprocessing -- added `-D` option to write abstract syntax tree into .txt file +- **int2ssl** will detect and decompile conditional expressions and short-circuit logical operators +- added `-F` option to include full file paths in `#line` directives after preprocessing +- added `-D` option to write abstract syntax tree into `.txt` file - fixed compiler crash when number of arguments in procedure declaration does not match definition - fixed incorrect constant folding of `bwnot` operator - fixed more invalid results in constant folding @@ -407,8 +407,8 @@ There are several changes in this version of sslc which may result in problems f - implemented stringify procedure names using `@` operator, which is helpful to pass procedures around to call them from variables (it will properly handle references) - logic for procedures passed as arguments to scripting functions was moved from code generation to parsing stage - now it is possible to call user-defined procedures inside argument list of scripting functions, without compiler attempting to treat them as procedure references and probably fail (procedures will still be passed, but only to appropriate scripting functions at appropriate argument positions) -- int2ssl will now place empty parantheses after a call to user-defined procedure - this will distinct calls from passing procedures to some scripting functions (like `giq_option`) -- fixed **inline** procedure "calls" not working when optimization is enabled +- **int2ssl** will now place empty parantheses after a call to user-defined procedure - this will distinct calls from passing procedures to some scripting functions (like `giq_option`) +- fixed `inline` procedure "calls" not working when optimization is enabled - added column numbers to error/warning output - added code to simplify adding sfall opcodes into compiler (need to add code in 3 places, instead of 7 places for each opcode) - fixed bug when initializing variable with expression starting from a symbol @@ -417,7 +417,7 @@ There are several changes in this version of sslc which may result in problems f **sfall 3.5:** - completed namespace compression optimization with respect to imported/exported variables - changed `for` and `foreach` syntax to allow parentheses which are easier to read IMHO -- heavy code refactoring - split **parse.c** into several files, replaced all dirty workaround code in `lex()` (some syntax features) with parser-level equivalents +- heavy code refactoring - split "parse.c" into several files, replaced all dirty workaround code in "lex()" (some syntax features) with parser-level equivalents - added syntax to reference elements in multi-dimensional arrays (unlimited sequence of brackets `[]` and dots `.`) - added fully featured `break` and `continue` statements for loops - moved some optimizations (namely constant propagation and variable reuse) to "experimental" because they were breaking my scripts @@ -428,4 +428,4 @@ There are several changes in this version of sslc which may result in problems f - added array expressions for lists and maps - added `foreach (key: value in ...)` syntax for convenience - fixed crash bug in `for` loop parsing function -- added ability to access array elements with string keys using OOP-like dot ("`.`") syntax +- added ability to access array elements with string keys using OOP-like dot `.` syntax