Commit graph

422 commits

Author SHA1 Message Date
Sei Lisa
4cbdbefe1b Fold again after applying distributibity or absortion.
Failure to do so was blocking some constant folding, like in:

if (a&1 || a&2 || a&4) -> if (a&(3|4))

Fixed. Now it correctly outputs if (a&7).
2017-10-17 23:28:14 +02:00
Sei Lisa
6c73ba95c2 Allow (x&r) && (x&s) && (x&t) to be collapsed into a single number.
This is an addendum to 3a849fe that allows more than two tests to be chained and optimized.
2017-10-17 23:26:13 +02:00
Sei Lisa
8d337467cb Fold the children of | as conditions when | is folded as condition. 2017-10-17 23:25:26 +02:00
Sei Lisa
a6a16c6e8f Fold ==0, ==1, ==-1 in general expressions, not just in conditions.
Also add a couple FIXMEs.
2017-10-17 02:38:08 +02:00
Sei Lisa
82081b2206 Fix crash when variables appear inside global lists.
Fixes #3.
2017-10-16 02:22:52 +02:00
Sei Lisa
cc96850f66 Fix bug where list elements of global declarations were removed.
CleanNode was too greedy, because children of global declarations (particularly lists) are not marked executable. Make a special case for them and don't recurse, since what matters is whether the declaration itself is executed. Its contents can't be cleaned up.
2017-10-16 02:22:40 +02:00
Sei Lisa
f77590df67 Fix sign of NaN*Indet and NaN/Indet.
In Python, NaN*Indet in any order returns the second operand, and NaN/Indet in any order returns the first operand. LSL consistently returns NaN in all cases.
2017-10-14 15:16:18 +02:00
Sei Lisa
0dc8629007 Raise ELSLInvalidType on invalid type passed to cond(). 2017-10-14 14:17:42 +02:00
Sei Lisa
a5ec12c9e9 Change (float)"NaN" to (-1e40*0) in output.
Solves both an inconsistency and the need to create a string.
2017-10-14 13:05:14 +02:00
Sei Lisa
6faa7816e6 Change ELSLInvalidType to ELSLTypeMismatch where appropriate.
The force type functions ff(), fi(), fs()... should normally trigger ELSLTypeMismatch when the input is not in the expected range of types, rather than ELSLInvalidType, which is reserved for the case where the type is not a valid LSL type.
2017-10-14 11:33:18 +02:00
Sei Lisa
3a849fe4b9 Optimize a common condition of (x & flag1) && (x & flag2)
It can't be done always: flag1 and flag2 must be nonzero powers of two. In that case, we can transform it to:

!~(x|~(flag1|flag2)) = !~(x|constant)

The -2147483648 case has trouble with the sign hack detector and I couldn't trigger it.
2017-10-13 02:59:32 +02:00
Sei Lisa
6ad2ef04d7 Add support for function calls in CompareTrees. 2017-10-13 00:30:47 +02:00
Sei Lisa
7ae7fa4396 Apply two optimizations to bitwise operations.
Based on basic Boolean algebra: distributive and absorption laws.
2017-10-12 22:48:43 +02:00
Sei Lisa
9e7a5d1cdf Change strategy for the checking of function input types.
Rather than assert that the types are correct, use the force type functions on the parameters:
ff, fk, fs, q2f, v2f, and the new fi, fl.

These functions have also been modified to ensure that the input type supports an implicit typecast to the target type and perform it, or emit ELSLInvalidType otherwise, rather than an assertion failure. fl in particular returns the original list if it isn't changed, or a copy if it is.

A couple bugs were found in testfuncs.py as a result, which have been fixed as well. A test has been added to ensure that the exception that caught these bugs remains in place.

The isxxxx functions are no longer necessary, so they are removed. Same goes for the painful cast handling process in foldconst, which was basically performing this task, and not necessarily well.

This approach is much more robust and should have been used since the beginning, but I didn't figure it out then.
2017-10-12 17:16:16 +02:00
Sei Lisa
41d2c68cf8 Add some more functions with predictable results.
Also minor reformatting forgotten in a previous commit.
2017-10-12 12:43:54 +02:00
Sei Lisa
1071941301 Implement accurate error reporting through #line directives.
Also simplify and fix the matching expression for #line (gcc inserts numeric flags at the end).

It still has many problems. It's O(n^2). It's calculated at every EParse, and EParse can be triggered and ignored while scanning vectors or globals. UniConvScript doesn't read #line at all, thus failing to report a meaningful input line. But at least it's a start.
2017-10-11 05:04:13 +02:00
Sei Lisa
4ba0518353 Report EParseReturnIsEmpty at return, EParseReturnShouldBeEmpty at expression.
Also change idpos to savepos, for consistency, and add note on why EParseReturnShouldBeEmpty is named like that.
2017-10-09 11:35:59 +02:00
Sei Lisa
4633c87a7c Report EParseUndefined at the identifier causing it.
It was being reported at the next token in some cases, due to needing to resolve the scope.
2017-10-05 18:51:53 +02:00
Sei Lisa
c544b51e37 Rewrite ReportError() and change EParse to report columns in chars.
ReportError() needed to account for terminal encodings that don't support the characters being printed. It was also reporting an inaccurate column number and its corresponding marker position, because the count was in bytes, not in characters, so that has been fixed.

Now EParse.__init__() calls a new function GetErrLineCol() that calculates the line and column corresponding to an error position.

The algorithm for finding the start of the line has also been changed in both ReportError() and EParse.__init__(); as a result, function fieldpos() has been removed.

The exception's lno and cno fields have been changed to be 1-based, rather than 0-based.

Thanks to @Jomik for the report. Fixes #5.
2017-10-05 18:50:45 +02:00
Sei Lisa
08c69eee0f Simplify a = a = b -> a = b 2017-09-22 16:14:50 +02:00
Sei Lisa
bdd42199eb Fix bug where assignments were treated as statements.
This caused e.g. b = a = a to raise an exception, when a = a was folded into a ';' which isn't an expression.
2017-09-22 16:04:44 +02:00
Sei Lisa
a0d4c77081 Minor cleanups; no functional changes.
lslcleanup: Variables renamed, order changed, comments added.

Other changes: remove semicolon at end of sentence, use self.Cast instead of creating a CAST node on the fly.
2017-09-22 15:42:42 +02:00
Sei Lisa
0a7e2a9e1d Optimize llDeleteSubList(expr, 0, -1) to [] if expr is SEF
It also applies to llListReplaceList with [] as replacement.
2017-09-15 23:13:59 +02:00
Sei Lisa
a6a08fe3f3 Implement transformation of lists into additions.
If the list in brackets is SEF:
  [a, b, ...]  ->  (list)a + b + ...
  ListExpr + [a, b, ...]  ->  ListExpr + a + b + ...
2017-09-15 22:30:22 +02:00
Sei Lisa
de29a9aa07 Fix for,while,if,do condition test during optimization.
That's exactly what 'cond' is for. Things like a loop with a constant zero vector condition should be recognized.

It was correct before just by chance, because FoldCond currently transforms a constant node into an integer node, but let's not rely on that.
2017-09-15 01:36:13 +02:00
Sei Lisa
b97b2a78e8 Fix return value for some detection functions.
When the index is good, on non-touch functions:
 - llDetectedTouchFace returns -1.
 - llDetectedTouchST and llDetectedTouchUV return TOUCH_INVALID_TEXCOORD.

We were returning 0 and ZERO_VECTOR respectively.
2017-08-30 19:23:38 +02:00
Sei Lisa
62eebb8bef Remove line no longer used from lsloptimizer.py. 2017-08-30 19:22:12 +02:00
Sei Lisa
2edd139a5c Fix copy/paste error in comment. 2017-08-25 20:45:24 +02:00
Sei Lisa
03c0e326c6 Remove "OK" from llDialog button list when it's the only element.
"OK" is the default; an empty list works just the same.
2017-08-25 20:35:24 +02:00
Sei Lisa
6738615360 Separate library function optimization into a different file.
No other functional changes. This required quite some reorganization affecting many files. As a side effect, PythonType2LSL and LSLType2Python aren't duplicate anymore.
2017-08-25 20:35:24 +02:00
Sei Lisa
36947b7b12 Rename lslfuncparams.py -> lslfuncopt.py
This is preparation work for splitting function optimization into a separate file, which will be the same that currently is lslfuncparams.py.
2017-08-25 20:35:24 +02:00
Sei Lisa
3ec460539e Implement the equivalent of GetObjectDetails for GPP/GLPP.
Removes the TODO item added in the last commit.
2017-08-25 20:35:24 +02:00
Sei Lisa
2a6e065c66 Optimize some llList2XXXX functions.
- Resolve for lists that aren't constants, but that are SEF, and reference a constant element, e.g. llList2String([llGetKey(), 5], 1) -> 5.
- Make it work with invalid conversions, if they are SEF.
- Simplify invalid conversions when the list argument is a llGetObjectDetails call and SEF.
- Simplify llList2String(llGetObjectDetails(id, [single_element]), 0) (or -1) to (string)llGetObjectDetails...; same with llList2Key and llList2Integer, converting it to (integer)((string)llGetObjectDetails...).
- Add TODO item to do it similarly for llGet[Link]PrimitiveParams.

Adds auxiliary functions to return a node or constant from a list in any of its forms, its length, and a constant for a node or constant.

Adds some utility members for LSL<->Python type conversion (one of them duplicated from lslparse.py).

Needs maintenance of the types returned by llGetObjectDetails.
2017-08-25 20:35:24 +02:00
Sei Lisa
906e76ea47 Format LIST nodes; don't add indent to CONST list in calc mode
LIST nodes will be pretty-printed with newlines between elements if they have 5 elements or more.

List constants won't be indented when in calc mode.
2017-08-25 20:35:24 +02:00
Sei Lisa
9a820a62d0 Simplify (type)sametype_expr -> sametype_expr. 2017-08-25 20:35:09 +02:00
Sei Lisa
2e09a3a986 Make some simplifications and keep PyFlakes happy. 2017-08-23 11:55:37 +02:00
Sei Lisa
ca3885c549 Expand conditions of types other than integer, string, key.
if(list!=[]) is always better than if(list), which compiles to if(!(list==[])).
if(float) can't be optimized, but it is equivalent to if(float!=0.0) which can. Same for vector, rotation.
2017-08-17 01:58:30 +02:00
Sei Lisa
a2e793df02 Parentheses around chained assignments are not necessary.
We follow the precedence and associativity rules, though.
2017-08-17 00:40:03 +02:00
Sei Lisa
2e29cc9131 Try to do better with the propagation of FoldCond.
Negation, specifically, didn't propagate to children. This might be redundant, though.
2017-08-16 22:02:11 +02:00
Sei Lisa
c5b5a8303c Add TODO item to lslrenamer. 2017-08-16 22:00:16 +02:00
Sei Lisa
6693022dfb Add !llStringLength(s) -> s == "" optimization. 2017-08-15 13:19:07 +02:00
Sei Lisa
0d76e09567 Propagate some SEF flags that we forgot 2017-08-15 13:19:07 +02:00
Sei Lisa
7c88acfe61 Fix type of != in llGetListLength substitution.
It was returning list instead of integer, causing inconsistencies in some comparisons depending on whether llGetListLength(L) or (L!=[]) was used.
2017-08-15 13:19:07 +02:00
Sei Lisa
fe574bb462 Bump copyright year.
'bout time.
2017-08-09 19:45:46 +02:00
Sei Lisa
e0fa1678a7 Optimize list addition when one list is known to have one element.
list + [element]  ->  list + element
list + (list)element  ->  list + element
[element] + list  ->  element + list
(list)element + list  ->  element + list
2017-08-09 16:41:36 +02:00
Sei Lisa
44e0db96d2 Optimize bool|1, bool&1 when possible.
a & 1 is always a, if a is boolean.

a | 1 is always 1, if a is boolean, but it can only be optimized out if a is side effect-free.
2017-08-02 01:40:48 +02:00
Sei Lisa
3f61e6f7bf Make IsBool smarter when finding whether an expression is boolean.
It was failing with a && b && c where a, b, c were known to be bools. It managed to simplify them to a & b & -c but that's not optimal.

Now it recurses on some operators that may return bool when used with bool operands: &, |, ^, * (in the case of &, it's bool if either operand is; for the rest, it's bool if both are). As a result, the above now simplifies to a & b & c, which is optimal.
2017-08-02 01:15:25 +02:00
Sei Lisa
61565470a2 New upstream version of builtins.txt, and minor code style changes. 2017-06-15 21:11:54 +02:00
Sei Lisa
b5994b79fe Optimize llDumpList2String(expr, "") to (string)expr.
It works on all VMs and it's always a gain, so it's not worth adding an option to deactivate it.
2017-05-31 14:39:42 +02:00
Sei Lisa
f1b05dd2ff Give more meaningful errors when break/continue parameter is wrong.
Adds a new EParseInvalidBrkContArg exception. Previously it raised EParseInvalidBreak or EParseInvalidCont, whose text was misleading for this type of error.
2017-04-29 13:47:45 +02:00