jsxer
jsxer copied to clipboard
Boolean expressions with parenthesis do not represent themselves properly in decompiler output.
For example:
ESTK Input:
(a || b && c) || !d
Decompiler output given the above compiled input:
((((a) || (b)) && (c)) || (!d))
which can be simplified to:
((a || b) && c) || ! d
Problems
- These two expressions are not algebraically equivalent.
- There are many redundant parenthesis.
Need someway of backtracking when dumping the ast as string. It's can be achieved using some contextual parsing and dumping.
Need someway of backtracking when dumping the ast as string. It's can be achieved using some contextual parsing and dumping.
I added code to #43. See what you think. I tested several different parenthesis configurations. It appears that Adobe's JavaScript interpreter parses logical expressions oddly. I'll expand on this later.
I did checked out some and wasn't satisfied about the results. gotta run some real test-cases to confirms. not having much time to focus on FOSS.
I studied the parsing of logical expressions with ExtendScript by making a script that generates a truth table and this was my conclusion...

Adobe ExtendScript seems not to honor operator precedence correctly for OR and AND.
Compiling
((((a) || (b)) && (c)) || (!d))
to jsxbin results in the same binary representation than
(a || b && c) || !d
Expecting standard algebraic precedence one would expect that these expressions are not the same. But in ExtendScript they are. You have to use
(a || (b && c)) || !d
to force a higher precedence for && in ExtendScript.
There are similar problems with bitwise operators
The decompilation process is correct - with some unneccessary parenthesis.
The decompilation process is correct - with some unnecessary parenthesis.
@sfeigl I deliberately added some unnecessary parenthesis to make any decompiled LogicalExpression
evaluate equivalently in more modern javascript engines[^1] (but it also makes the output more intuitive in my opinion). I tested it by making a script that generates a truth table and analyzing the output of different parenthesis configurations. I then implemented the parenthesis decompiler logic such that it may function equivalently on both ExtendScript and V8 runtimes.
[^1]: This is with the assumption that you did your analysis of the output with the linked pull request (#43), containing more refined parenthesis decompilation logic.
function ttbl(condition) {
var table = "";
for(var a = 0; a < 2; a++) {
for(var b = 0; b < 2; b++) {
for(var c = 0; c < 2; c++) {
for(var d = 0; d < 2; d++) {
table += a + " " + b + " " + c + " " + d + " = " + condition(a,b,c,d) + "\n";
}
}
}
}
alert(table);
}
// decompiler input before encoding to jsxbin
ttbl(function(a, b, c, d) {return a || b && c || d})
// JSXBIN encoded...
// @JSXBIN@[email protected]@MyBbyBn0ABJAnAEjzEjUjUjCjMBfRBNyBnAMAbyBn0ABZAnAUzCjcjcCUzChGhGDUCVzBjB
// EfAVzBjCFfBnnVzBjDGfCnnVzBjEHfDnnAEE40BhAF4B0AhAG4C0AhAH4D0AhAE0AzAICAff0DIByB
// the improved decompiler output... (truth table in V8 is now equivalent to that of the ExtendScript runtime, but
// the new expression is also functionally equivalent to the old one when ran in ES)
ttbl(function(a,b,c,d) {return (a || b) && c || d})
// The decompiler now produces output that forces order of operations equivalent to ES with modern interpreters like V8,
// and it manages to do it such that it does not affect the order of operations if evaluated in the ES runtime. Awesome! :)
@psyirius Circling back to this issue. What did you think of the results?