|
| 1 | +# New Rewriting Implementation |
| 2 | + |
| 3 | +Goal: **2nd rewriting implementation along the first** (for performance comparison) |
| 4 | + |
| 5 | +## Setup |
| 6 | + |
| 7 | +- find a name |
| 8 | +- copy the system |
| 9 | + - copy *reactive* folder (including *test*) -> copy only *test*? |
| 10 | + - strip obviously irrelevant files/folders |
| 11 | + - adjust *system config* |
| 12 | + - copy aliases |
| 13 | + - adapt rewriting settings (babel configs) |
| 14 | + - adapt rewritings (with parts are rewritten in what manner) |
| 15 | + - adjust import paths (non local ones) |
| 16 | + - replace directive `"enable aexpr";` -> `"ae";` |
| 17 | + - also in rewriting files (tests & plugins) |
| 18 | + - add preference *"rewriting or new"* |
| 19 | +- tests deaktivieren |
| 20 | + - remove all irrelevant tests |
| 21 | + - `const xxit = xit;` |
| 22 | + - go through each `xit`: do we want this behavior in the new implementation? |
| 23 | + - if not: remove else: replace `xit` with `xxit` |
| 24 | + - `it` -> `xit` |
| 25 | + - some `before`/`afterEach` might throw |
| 26 | + - which tests test all implementations? |
| 27 | + - find them, add the new implementation |
| 28 | + |
| 29 | +--> have **all tests passing** all the way until here |
| 30 | + |
| 31 | +## Actual Implementation |
| 32 | + |
| 33 | +### 1. Introduce EAM at body level |
| 34 | + |
| 35 | +insight: a first-class piece of behavior can run completely either in EAM or outside EAM. |
| 36 | + |
| 37 | +Thus, we can check if we are in EAM at the start of a FunctionBody, rather than on each member and variable access. Our initial function |
| 38 | + |
| 39 | +```javascript |
| 40 | +function foo() { |
| 41 | + obj.prop |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +has its body duplicated for each mode of operation: |
| 46 | + |
| 47 | +```javascript |
| 48 | +function foo() { |
| 49 | + if (self.__expressionAnalysisMode__) { |
| 50 | + _getMember(obj, "prop") |
| 51 | + } else { |
| 52 | + obj.prop |
| 53 | + } |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +thus, while analysing an expression, dependencies are still gathered, but outside the analysis, we only need to check one global boolean (which requires not only less redundant computation but also ). |
| 58 | + |
| 59 | +#### caveats |
| 60 | + |
| 61 | +1. arrow functionExpressions may need to be rewritten to have a block as body |
| 62 | +2. setters must be present in both |
| 63 | +3. the global `self` or `__expressionAnalysisMode__` might be shadowed, we have to take care of this case (initially skip this downside with a non-colliding import: ) |
| 64 | + |
| 65 | +#### downsides |
| 66 | + |
| 67 | +- space for src code increases exponentially with nesting of functions (we have to measure this impact, e.g. by transforming all of lively and compare) |
| 68 | + |
| 69 | +### 2. Localize Read/Write Accesses for Local Variables |
| 70 | + |
| 71 | +idea: instead of a central data structutr, keep refereces to aexprs for locals in the `_scope` objects. |
| 72 | + |
| 73 | +### 3. Localize Member Write Accesses (in favor of SourceCodeHooks) |
| 74 | + |
| 75 | +#### caveats |
| 76 | + |
| 77 | +1. `.length` (browser-dependent behavior for Arrays) and `obj[computedPropertyAccess]` still need to be using `setMember` |
| 78 | +2. other special hooks still need to be there (e.g. value hook or mutation hooks) |
| 79 | + |
| 80 | +### 4. Minimize tracking of local variables |
| 81 | + |
| 82 | +idea: local variables only need to be tracked, if |
| 83 | +- they leave their initial scope of declaration (= there is at least one read (#TODO: not sure if a read requires tracking) or write access to that variable in a different first-class functions' scope, i.e. it can be passed around) |
| 84 | +- they are not constant (there is a write operations somewhere for them) |
0 commit comments