1.4.25 • Published 8 months ago

nv-js-parse v1.4.25

Weekly downloads
-
License
ISC
Repository
-
Last release
8 months ago

nv-js-parse

  • nv-js-parse
  • wrap of @babel/parser
  • add some display/show/path/traverse methods , make it easy for manual-edit ast
  • nv-js-parse is slow, coz it insert some functions to original-babel-parser
  • and rebuild the path/traverse of babel
  • its for build cli-code-tools,NOT for creat-runtime

install

  • npm install nv-js-parse

usage

basic

const {tree,parse,unparse,pprint_ast} = require('nv-js-parse')

var code = `class T {
    #a = 1999
    get() {
      return this.#a
    }
}`

> var t = tree(code)
> t
 [program <Program> {"sourceType":"module","interpreter":null}] {}

  • astml is a simple syntax for manually writing ast
  • shape: %key <%type:String> %attr:Object %NL %listKey%index:Int <%type:String> %attr:Object %NL

       %type must be ast-node-type of estree/ts/flow/jsx
       %key AND %listKey  must be visitor/list-visitor of %type 

    > t.show_astml()
    program <Program> {"sourceType":"module","interpreter":null}
        body[0] <ClassDeclaration> {}
            id <Identifier> {"name":"T"}
            body <ClassBody> {}
                body[0] <ClassPrivateProperty> {"static":false}
                    key <PrivateName> {}
                        id <Identifier> {"name":"a"}
                    value <NumericLiteral> {"value":1999}
                body[1] <ClassMethod> {"generator":false,"async":false,"static":false,"computed":false,"kind":"method"}
                    key <Identifier> {"name":"get"}
                    body <BlockStatement> {}
                        body[0] <ReturnStatement> {}
                            argument <MemberExpression> {"computed":false}
                                object <ThisExpression> {}
                                property <PrivateName> {}
                                    id <Identifier> {"name":"a"}



        > t.show_code()
        class T {
          #a = 1999;

          get() {
            return this.#a;
          }

        }



        > t.get_all_ast_bracket_paths()
        [
          '',
          '["body"]["0"]',
          '["body"]["0"]["id"]',
          '["body"]["0"]["body"]',
          '["body"]["0"]["body"]["body"]["0"]',
          '["body"]["0"]["body"]["body"]["0"]["key"]',
          '["body"]["0"]["body"]["body"]["0"]["key"]["id"]',
          '["body"]["0"]["body"]["body"]["0"]["value"]',
          '["body"]["0"]["body"]["body"]["1"]',
          '["body"]["0"]["body"]["body"]["1"]["key"]',
          '["body"]["0"]["body"]["body"]["1"]["body"]',
          '["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]',
          '["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]',
          '["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["object"]',
          '["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["property"]',
          '["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["property"]["id"]'
        ]
        > t.ast["body"]["0"]["body"]["body"]["1"]["body"]["body"]["0"]["argument"]["property"]["id"]
        Node {
          type: 'Identifier',
          start: 67,
          end: 68,
          loc: SourceLocation {
            start: Position { line: 4, column: 23 },
            end: Position { line: 4, column: 24 },
            filename: undefined,
            identifierName: 'a'
          },
          name: 'a'
        }

const2let

  • for debug using
  • actually ,const is a runtime-check feature
    /*
    > function tst() {
    ...     const a;
        const a;
              ^

    Uncaught SyntaxError: Missing initializer in const declaration
    >     a=100
    100
    > }
    }
    ^

    */

    cd =`function tst() {
        const a;
        a=100
    }`


    > cd =`function tst() {
         const a;
        a=100
    }`
    'function tst() {\n    const a;\n    a=100\n}'
    >
    > const2let(cd)
    'function tst() {\n  let a;\n  a = 100;\n}'
    >

hoist_func_decl

  • stage0, func declaration hoist
  • not the final ,only hoist to first ance-block, not to function block

       var cd =`function A () {
             let x = 0
             console.log(tst())
             {
                console.log(tst())
                function tst() {return(x+1)}
             }
             function tst() {return(x)}
       }`
      s0 = split_var_decl(cd)
      s1 = split_var_declor(s0)
      s2 = hoist_var(s1)
      s3 = hoist_func_decl(s2)

     > console.log(s3)
     function A() {
       function tst() {
         return x;
       }

       let x;
       x = 0;
       console.log(tst());
       {
         function tst() {
           return x + 1;
         }

         console.log(tst());
       }
     }

fdecl2fexpr

  • must be used after hoist_func_decl
              var cd = `
                  function tst(u,v) {
                       let a=100;
                       function inner() {
                           var x;
                           function tst() {}
                       }
                  }
              `

            > console.log(fdecl2fexpr(cd))
            var tst = function tst(u, v) {
              let a = 100;

              var inner = function inner() {
                var x;

                var tst = function tst() {};
              };
            };

cdecl2cexpr

  • class declaration to class expression
     var cd = `
         class A {
             method() {
                 class B {}
                 class C {}
                 function tst() {
                     class D {}
                 }
             }
         }
     `


     > console.log(cdecl2cexpr(cd))
     let A = class A {
       method() {
         let B = class B {};
         let C = class C {};

         function tst() {
           let D = class D {};
         }
       }

     };

split_var_decl

  • for debug AND hoist using

const {split_var_decl} = require("nv-js-parse")
var code = `
    function tst() {
        let a,b=3,c;
        return(a+b+c)
}`


> console.log(split_var_decl(code))
function tst() {
  let a;
  let b = 3;
  let c;
  return a + b + c;
}

var code = `
    function tst() {
        let x,[{a,b},c]=[{a:666,b:777},3],y;
        return(a+b+c)
}`

> console.log(split_var_decl(code))
function tst() {
  let x;
  let [{
    a,
    b
  }, c] = [{
    a: 666,
    b: 777
  }, 3];
  let y;
  return a + b + c;
}

> tst()
1446
>


    >      var cd = `function tst() {
    ...          var a,b=8;
    ...          for(let i=0,j;i<3;i++,j++) {let {x,y}={}}
    ...          var c = a+b
    ...      }`
    > console.log(split_var_decl(cd))
    function tst() {
      var a;
      var b = 8;
      {                               //----------------
        let i = 0;
        let j;

        for (; i < 3; i++, j++) {
          let {
            x,
            y
          } = {};
        }
      }                             //------------------special handle of for AND forin AND forof
      var c = a + b;
    }

split_var_declor

  • for debug AND hoist using
  • must be used after split_var_decl

      var cd = `
          function tst(u,v) {
              let x,e,ee;
              let [{a,b=e='EEEEE',...f},c=333,d,...g]=[{a:666,b:777},3];
              let [{aa,bb=ee='1111111',...ff},cc=333,dd,...gg]=[{aa:666,bb:777},3];
              let [] = [],[,] =[],[...args] = [1,2],{...D} = {1:2,3:4},[A] = [1,2],{B} = {B:2,3:4},[C=10] = [],{E=999} = {};
              return([u,v,x,a,b,e,f,c,d,g,aa,bb,ee,ff,cc,dd,gg,args,D,A,B,C,E])
          }
      `
      
      /*
      > eval(`(${cd})(100,500)`)
      [
        100,                500,
        undefined,          666,
        777,                undefined,
        {},                 3,
        undefined,          [],
        666,                777,
        undefined,          {},
        3,                  undefined,
        [],                 [ 1, 2 ],
        { '1': 2, '3': 4 }, 1,
        2,                  10,
        999
      ]
      >
      
      */
      s0 = split_var_decl(cd)
      console.log(s0)
      /*
      function tst(u, v) {
        let x;
        let e;
        let ee;
        let [{
          a,
          b = e = 'EEEEE',
          ...f
        }, c = 333, d, ...g] = [{
          a: 666,
          b: 777
        }, 3];
        let [{
          aa,
          bb = ee = '1111111',
          ...ff
        }, cc = 333, dd, ...gg] = [{
          aa: 666,
          bb: 777
        }, 3];
        let [] = [];
        let [,] = [];
        let [...args] = [1, 2];
        let { ...D
        } = {
          1: 2,
          3: 4
        };
        let [A] = [1, 2];
        let {
          B
        } = {
          B: 2,
          3: 4
        };
        let [C = 10] = [];
        let {
          E = 999
        } = {};
        return [u, v, x, a, b, e, f, c, d, g, aa, bb, ee, ff, cc, dd, gg, args, D, A, B, C, E];
      }
      
      */
      /*
      > eval(`(${s0})(100,500)`)
      [
        100,                500,
        undefined,          666,
        777,                undefined,
        {},                 3,
        undefined,          [],
        666,                777,
        undefined,          {},
        3,                  undefined,
        [],                 [ 1, 2 ],
        { '1': 2, '3': 4 }, 1,
        2,                  10,
        999
      ]
      >
      
      */
      s1 = split_var_declor(s0)
      console.log(s1)
      
      /*
      function tst(u, v) {
        let x;
        let e;
        let ee;
        let a;
        let b;
        let f;
        let c;
        let d;
        let g;
        [{
          a,
          b = e = 'EEEEE',
          ...f
        }, c = 333, d, ...g] = [{
          a: 666,
          b: 777
        }, 3];
        let aa;
        let bb;
        let ff;
        let cc;
        let dd;
        let gg;
        [{
          aa,
          bb = ee = '1111111',
          ...ff
        }, cc = 333, dd, ...gg] = [{
          aa: 666,
          bb: 777
        }, 3];
        [] = [];
        [,] = [];
        let args;
        [...args] = [1, 2];
        let D;
        ({ ...D
        } = {
          1: 2,
          3: 4
        });
        let A;
        [A] = [1, 2];
        let B;
        ({
          B
        } = {
          B: 2,
          3: 4
        });
        let C;
        [C = 10] = [];
        let E;
        ({
          E = 999
        } = {});
        return [u, v, x, a, b, e, f, c, d, g, aa, bb, ee, ff, cc, dd, gg, args, D, A, B, C, E];
      }
      
      */
      
      /*
      > eval(`(${s1})(100,500)`)
      [
        100,                500,
        undefined,          666,
        777,                undefined,
        {},                 3,
        undefined,          [],
        666,                777,
        undefined,          {},
        3,                  undefined,
        [],                 [ 1, 2 ],
        { '1': 2, '3': 4 }, 1,
        2,                  10,
        999
      ]
      >
      
      */



      var cd = `function tst() {for(let i=1,[x,y]=[888];i<3;i++) {}}`
      s0 = split_var_decl(cd)
      s1 = split_var_declor(s0)
      console.log(s1)

      /*
         function tst() {
           {
             let i;
             i = 1;
             let x;
             let y;
             [x, y] = [888];
         
             for (; i < 3; i++) {}
           }
         }
      */


      var cd = `function tst() {for(let i;i<3;i++) {}}`
      s0 = split_var_decl(cd)
      s1 = split_var_declor(s0)
      console.log(s1)

       /*
       function tst() {
         {
           let i;
       
           for (; i < 3; i++) {}
         }
       }
       */

     var cd = `
         async function tst() {
             let arr =[];
             let d = {};
             let g = (async function *(){})();
             for(let i=1,y;i<3;i++) {}
             for(let ele of arr) {}
             for(let k in d) {}
             for await (let  each of g) {}
         }
     `

      s0 = split_var_decl(cd)
      s1 = split_var_declor(s0)
      console.log(s1)
       /*
       async function tst() {
         let arr;
         arr = [];
         let d;
         d = {};
         let g;
       
         g = async function* () {}();
       
         {
           let i;
           i = 1;
           let y;
       
           for (; i < 3; i++) {}
         }
         {
           let ele;
       
           for (ele of arr) {}
         }
         {
           let k;
       
           for (k in d) {}
         }
         {
           let each;
       
           for await (each of g) {}
         }
       }
        */

hoist_var

  • must be used after split_var_decl -> split_var_declor
    const {
        split_var_decl,
        split_var_declor,
        tree,
        hoist_var,
    } = require("nv-js-parse")
    
              var cd = `
                  function tst(u,v) {
                      let x;
                      {
                          var y=888;
                          {
                              var [z,{w,r}] = [1,{w:2,r:3}];
                               let A;
                          }
                      }
                  }
              `
              
              s0 = split_var_decl(cd)
              s1 = split_var_declor(s0)
              s2 = hoist_var(s1)
    
    
    > console.log(s2)
    function tst(u, v) {
      let x;
      var y;
      var z;
      var w;
      var r;
      {
        y = 888;
        {
          [z, {
            w,
            r
          }] = [1, {
            w: 2,
            r: 3
          }];
          let A;
        }
      }
    }

rare special cases

    > var cd =`
    ... function tst() {
    ...   var a;
    ...   {
    .....     var a;
    .....     a = 13;
    .....   }
    ... }`
    >
    > hoist_var(cd)
    'function tst() {\n  var a;\n  var a;\n  {\n    a = 13;\n  }\n}'
    > console.log(hoist_var(cd))
    function tst() {
      var a;
      var a;
      {
        a = 13;
      }
    }






    var cd =`
    var tst;

    tst = function tst() {
      var a;
      {
        var a;
      }
    };
    `

    > var cd =`
    ... var tst;
    ...
    ... tst = function tst() {
    ...   var a;
    ...   {
    .....     var a;
    .....   }
    ... };
    ... `
    > console.log(hoist_var(cd))
    var tst;

    tst = function tst() {
      var a;
      var a;
      {}
    };
    >

merge_dupe_var_decl

  • must be used after hoist_var

    var cd = `
    function tst() {
      var a;
      var a;
      {
        a = 13;
      }
    }`

    merge_dupe_var_decl(cd)


    > console.log(merge_dupe_var_decl(cd))
    [
      ‍ [        id <Identifier> {"name":"tst"}] {},
      ‍ [                    id <Identifier> {"name":"a"}] {},
      ‍ [                    id <Identifier> {"name":"a"}] {},
      ‍ [                        left <Identifier> {"name":"a"}] {}
    ]
    function tst() {
      var a;
      {
        a = 13;
      }
    }

###when conflict with params-

var cd= `function tst(a) {
    var a;
    return(a)
}`


> console.log(merge_dupe_var_decl(cd))
function tst(a) {
  return a;
}

split_nonidlval_asgn_expr

  • must be used after split_var_declor
  • if the AssignmentExpression left(LVal) is NOT direct Identifier
  • (such as MemberExpression,ArrayPattern,ObjectPattern....)
  • it will split it to three part, see below

    var cd =`[z,{w,r}] = [1,{w:2,r:3}]`

    console.log(split_nonidlval_asgn_expr(cd))

    /*
        let ___swapper_b1cf8a9c_$AssignmentExpression___ = [1, {
          w: 2,
          r: 3
        }];

        [z, {
          w,
          r
        }] = ___swapper_b1cf8a9c_$AssignmentExpression___;


    */

          var cd = `
            function tst(u,v) {
                let x;
                {
                    var y=888;
                    {
                        var [z,{w,r}] = [1,{w:2,r:3}];
						var [u,{v},...X] = [10,{v:20}];
                        let A;
						var B=D=E=1111
                    }
                }
				var [z,{w,r}] = [10,{w:20,r:30}];
            }
        `
        
        s0 = split_var_decl(cd)
        s1 = split_var_declor(s0)
        s2 = hoist_var(s1)
        s3 = split_nonidlval_asgn_expr(s2)
		s4 = merge_dupe_var_decl(s3)
		console.log(s4)
		
    /*
    function tst(u, v) {
      var y;
      var z;
      var w;
      var r;
      var X;
      var B;
      let x;
      {
        y = 888;
        {
          let ___swapper_ec071153_$AssignmentExpression___ = [1, {
            w: 2,
            r: 3
          }];
          [z, {
            w,
            r
          }] = ___swapper_ec071153_$AssignmentExpression___;
          let ___swapper_fcc8fd5d_$AssignmentExpression___ = [10, {
            v: 20
          }];
          [u, {
            v
          }, ...X] = ___swapper_fcc8fd5d_$AssignmentExpression___;
          let A;
          B = D = E = 1111;
        }
      }
      let ___swapper_b72b9d99_$AssignmentExpression___ = [10, {
        w: 20,
        r: 30
      }];
      [z, {
        w,
        r
      }] = ___swapper_b72b9d99_$AssignmentExpression___;
    }
    */

var_to_let

  • must be used after merge_dupe_var_decl

      var cd = `
      function tst() {
        var a;
        var a;
        {
          a = 13;
        }
      }`
    
      var s0 = merge_dupe_var_decl(cd)
      var s1 = var2let(s0)
      > console.log(s1)
      function tst() {
        let a;
        {
          a = 13;
        }
      }

split_rtrn_stmt

  • move argument of return-statement out

const {split_rtrn_stmt} = require("nv-js-parse");


    var cd =`
    function tst(a,b,c) {
        function inner() {
            return(c*3)
        }
        return((a+b+inner()))
    }
    `
 
    console.log(split_rtrn_stmt(cd))




    function tst(a, b, c) {
      function inner() {
        let ___rslt_0296616b_$ReturnStatement___;

        ___rslt_0296616b_$ReturnStatement___ = c * 3;
        return ___rslt_0296616b_$ReturnStatement___;
      }

      let ___rslt_32b00b98_$ReturnStatement___;

      ___rslt_32b00b98_$ReturnStatement___ = a + b + inner();
      return ___rslt_32b00b98_$ReturnStatement___;
    }

split_thrw_stmt

    var src = `
    function tst() {
        throw(new Error("!!"));
        {
            throw a;
        }
    }
    `

    > console.log(x.split_thrw_stmt(src))
    function tst() {
      let ___rslt_2a23863e_$ThrowStatement___;

      ___rslt_2a23863e_$ThrowStatement___ = new Error("!!");
      throw ___rslt_2a23863e_$ThrowStatement___;
      {
        let ___rslt_91675550_$ThrowStatement___;

        ___rslt_91675550_$ThrowStatement___ = a;
        throw ___rslt_91675550_$ThrowStatement___;
      }
    }

ternery to if-else

    const {conexpr_to_ifelse} = require("nv-js-parse");

    var cd0 = `function tst(a,b,c,d,e) {return(a?b:c?d:e)}`;

    /*
    > function tst(a,b,c,d,e) {return(a?b:c?d:e)}
    > tst(true,false,true,'d','e')
    false
    >
    */

    console.log(conexpr_to_ifelse(cd0));

    /*
    function tst(a, b, c, d, e) {
      return (() => {
        if (a) {
          return b;
        } else {
          return (() => {
            if (c) {
              return d;
            } else {
              return e;
            }
          })();
        }
      })();
    }

    > tst(true,false,true,'d','e')
    false
    >

    */



    var cd1 = `function tst(a,b,c,d,e) {return((a?b:c)?d:e)}`;

    /*
    function tst(a,b,c,d,e) {return((a?b:c)?d:e)}
    > tst(true,false,true,'d','e')
    'e'
    >
    */

    console.log(conexpr_to_ifelse(cd1));

    /*
    function tst(a, b, c, d, e) {
      return (() => {
        if ((() => {
          if (a) {
            return b;
          } else {
            return c;
          }
        })()) {
          return d;
        } else {
          return e;
        }
      })();
    }

    > tst(true,false,true,'d','e')
    'e'
    >

    */

    var cd2 = `
        function tst(a,b,c,d,e) {
            let x = a?b:null
            function inner() {
                let y = a?(
                   c?d:e
                ):(
                   d?100:(e?200:300)
                )
            }
            return(inner())
        }
    `

    console.log(conexpr_to_ifelse(cd2));

    /*
    function tst(a, b, c, d, e) {
      let x = (() => {
        if (a) {
          return b;
        } else {
          return null;
        }
      })();

      function inner() {
        let y = (() => {
          if (a) {
            return (() => {
              if (c) {
                return d;
              } else {
                return e;
              }
            })();
          } else {
            return (() => {
              if (d) {
                return 100;
              } else {
                return (() => {
                  if (e) {
                    return 200;
                  } else {
                    return 300;
                  }
                })();
              }
            })();
          }
        })();
      }

      return inner();
    }
    */

tree

  • read-only

    const {tree} = require("nv-js-parse");
    
    
    var cd2 =`
        function outter() {
            let a ;
            function inner() {
                b
                a;
                {
                    a;
                }
            }
        }
    `
    
    var t = tree(cd2);
    var arr = t.$sdfs()
    var ids = arr.filter(r=>r.path.node.type==='Identifier')
    
    > ids.map(r=>r.path.node.name)
    [ 'outter', 'a', 'inner', 'b', 'a', 'a' ]
    >
    > ids[0].get_closure_scope_nd()
     [Program] {}
    >
    
    > ids[1].get_closure_scope_nd().show_code()
    
    > ids[1].get_ast().name
    'a'
    > ids[1].get_closure_scope_nd().show_code()
    function outter() {
      let a;
    
      function inner() {
        b;
        a;
        {
          a;
        }
      }
    }
    
    > ids[2].get_ast().name
    'inner'
    > ids[2].get_closure_scope_nd().show_code()
    function outter() {
      let a;
    
      function inner() {
        b;
        a;
        {
          a;
        }
      }
    }
    
    > ids[3].get_ast().name
    'b'
    > var top = ids[3].get_closure_scope_nd()
     [Program] {}
    >
    > top.path.scope.globals
    [Object: null prototype] {
      b: Node {
        type: 'Identifier',
        start: 80,
        end: 81,
        loc: SourceLocation {
          start: [Position],
          end: [Position],
          filename: undefined,
          identifierName: 'b'
        },
        name: 'b'
      }
    }
    >
    
    > ids[5].get_ast().name
    'a'
    >
    > ids[5].get_closure_scope_nd().show_code()
    function outter() {
      let a;
    
      function inner() {
        b;
        a;
        {
          a;
        }
      }
    }
    
    
    
    var cd3 = `
       function tst(A,B) {
           function inner() {
               return(A)
           }
       }
    `
    
    
    var t = tree(cd3);
    var arr = t.$sdfs()
    var ids = arr.filter(r=>r.path.node.type==='Identifier')
    ids.map(r=>r.path.node.name)
    [ 'tst', 'A', 'B', 'inner', 'A' ]
    
    > ids[1].get_closure_scope_nd().show_code()
    function tst(A, B) {
      function inner() {
        return A;
      }
    }
    undefined
    > ids[1].get_ast().name
    'A'
    > ids[1].get_closure_scope_nd().show_code()
    function tst(A, B) {
      function inner() {
        return A;
      }
    }
    > ids[4].get_ast().name
    'A'
    > ids[4].get_closure_scope_nd().show_code()
    function tst(A, B) {
      function inner() {
        return A;
      }
    }

binding

      var t = tree(`
           let P;
           function X([tst=666,{a,b}]){
               let uuu=y;
               class C {}
           }
           try{}catch({e}) { let vvv;}
           var D = { s(u,{v}){} }
           class U {}
           {let m;}
           for(let j=0;j<5;j++) {}
           for(let k in X) {}
           for(let ele of X) {}
      `)
      t.get_decl_ids().map(r=>r.get_sig_plstr())
      /*

      [
        'body-declarations-id',
        'body-id',
        'params-elements-left',
        'params-elements-properties-key',
        'params-elements-properties-key',
        'body-body-declarations-id',
        'body-body-id',
        'param-properties-key',
        'body-body-declarations-id',
        'body-declarations-id',
        'params',
        'params-properties-key',
        'body-id',
        'body-declarations-id',
        'init-declarations-id',
        'left-declarations-id',
        'left-declarations-id'
      ]
      */
      var fdecl = t.FunctionDeclaration()[0];

      /*
      > fdecl.show_code()
      function X([tst = 666, {
        a,
        b
      }]) {
        let uuu = y;

        class C {}
      }

      */

      > fdecl.get_binding_def_ids()
      {
        var: [],
        let: [
          ‍ [                    id <Identifier> {"name":"uuu"}] {}
        ],
        const: [],
        fdecl: [],
        cdecl: [
          ‍ [                id <Identifier> {"name":"C"}] {}
        ],
        params: [
          ‍ [                left <Identifier> {"name":"tst"}] {},
          ‍ [                    value <Identifier> {"name":"a"}] {},
          ‍ [                    value <Identifier> {"name":"b"}] {}
        ],
        global: [],
        catch_param: []
      }
      >


        var cd = `
        function tst() {
            let [{
                      a,
                      b = e = 'EEEEE',
                      ...f
                    }, 
                    c = 333, d, 
                    [A,B,C,{E,F}],
                    ...g
          ] =[];
        }
        `


        var t = tree(cd);
        var fdecl = t.$sdfs()[1]

        > fdecl.get_decl_ids().map(r=>r.ast.name)
        [
          'a', 'b', 'f', 'c',
          'd', 'A', 'B', 'C',
          'E', 'F', 'g'
        ]
        >


        function tst() {
            let [{
                      a,
                      b = e = 'EEEEE',               //identifier-e ast-path-sign not match
                      ...f
                    },
                    c = 333, d,
                    [A,B,C,{E,F}],
                    ...g
          ] =[{},undefined,undefined,[1,2,3,{}]];
        }

        /*
        > tst()
        > e
        'EEEEE'                   //e is global

        */

decl id type

  • for static trace using
    var cd = `
        function tst(a,{b}) {
            let c;
            {
               var d;
            }
            try{}catch(e){}
        }
        let _f1       = function (f) {}
        const _lambda = (g)=> {}
        class C {
            method(h,[j]) {}
            #method([k,{l}]){}
        }
        let O = {m(n){}}
        try{}catch({p}){}
        for(let i=0;i<5;i++) {}
        for(let {I}={I:0};i<5;i++) {}
        for(let ele of []) {}
        for(let [ELE] of [[1],[2]]) {}
        for(let k in {}) {}
        for(let {length} in [0,1,2,3,4,5,6,7,8,9,10]) {}              //this is a valid syntax
    `

    var t = tree(cd)

    > ids = t.get_decl_ids()
    [
      ‍ [        id <Identifier> {"name":"tst"}] {},
      ‍ [        params[0] <Identifier> {"name":"a"}] {},
      ‍ [                value <Identifier> {"name":"b"}] {},
      ‍ [                    id <Identifier> {"name":"c"}] {},
      ‍ [                        id <Identifier> {"name":"d"}] {},
      ‍ [                    param <Identifier> {"name":"e"}] {},
      ‍ [            id <Identifier> {"name":"_f1"}] {},
      ‍ [                params[0] <Identifier> {"name":"f"}] {},
      ‍ [            id <Identifier> {"name":"_lambda"}] {},
      ‍ [                params[0] <Identifier> {"name":"g"}] {},
      ‍ [        id <Identifier> {"name":"C"}] {},
      ‍ [                params[0] <Identifier> {"name":"h"}] {},
      ‍ [                    elements[0] <Identifier> {"name":"j"}] {},
      ‍ [                    elements[0] <Identifier> {"name":"k"}] {},
      ‍ [                            value <Identifier> {"name":"l"}] {},
      ‍ [            id <Identifier> {"name":"O"}] {},
      ‍ [                    params[0] <Identifier> {"name":"n"}] {},
      ‍ [                    value <Identifier> {"name":"p"}] {},
      ‍ [                id <Identifier> {"name":"i"}] {},
      ‍ [                        value <Identifier> {"name":"I"}] {},
      ‍ [                id <Identifier> {"name":"ele"}] {},
      ‍ [                    elements[0] <Identifier> {"name":"ELE"}] {},
      ‍ [                id <Identifier> {"name":"k"}] {},
      ‍ [                        value <Identifier> {"name":"length"}] {}
    ]
    >


    > ids[0].is_fdecl_id()
    true
    > ids[1].is_fdecl_param_id()
    true
    > ids[2].is_fdecl_param_id()
    true
    >
    > ids[3].is_let_decl_id()
    true
    >
    > ids[4].is_var_decl_id()
    true
    >
    > ids[5].is_catch_param_id()
    true
    >
    > ids[6].is_let_decl_id()
    true
    >
    > ids[7].is_fexpr_param_id()
    true
    >
    > ids[8].is_const_decl_id()
    true
    >
    > ids[9].is_arrow_param_id()
    true
    >
    > ids[10].is_cdecl_id()
    true
    >
    > ids[11].is_cls_method_param_id()
    true
    >
    > ids[12].is_cls_method_param_id()
    true
    >
    > ids[13].is_cls_priv_method_param_id()
    true
    >
    > ids[14].is_cls_priv_method_param_id()
    true
    >
    > ids[15].is_let_decl_id()
    true
    >
    > ids[16].is_obj_method_param_id()
    true
    >
    > ids[17].is_catch_param_id()
    true
    >
    > ids[18].is_for_init_id()
    true
    >
    > ids[19].is_for_init_id()
    true
    >
    > ids[20].is_forof_id()
    true
    > ids[21].is_forof_id()
    true
    > ids[22].is_forin_id()
    true
    > ids[23].is_forin_id()
    true
    >

find escaped id

    var cd = `
        function tst(a) {
            let b=10,c={'key':X};
            a = b+c ;
            {
                let u = 5;
                a = a + u;
            }
            return(a)
        }
    `

    var t = tree(cd)
    var f = t.$fstch()

    > f.get_decl_ids()
    [
      ‍ [        params[0] <Identifier> {"name":"a"}] {},
      ‍ [                    id <Identifier> {"name":"b"}] {},
      ‍ [                    id <Identifier> {"name":"c"}] {},
      ‍ [                        id <Identifier> {"name":"u"}] {}          //后代block内的
    ]
    >

    > f.get_own_local_decl_ids()
    {
      var: [],
      let: [
        ‍ [                    id <Identifier> {"name":"b"}] {},
        ‍ [                    id <Identifier> {"name":"c"}] {}
      ],
      const: [],
      fdecl: [],
      cdecl: [],
      params: [
        ‍ [        params[0] <Identifier> {"name":"a"}] {}
      ],
      global: [],
      catch_param: []
    }
    >

    > f.get_own_local_escaped_decl_ids()
    [
      ‍ [        params[0] <Identifier> {"name":"a"}] {}            // 参数 a 被里层 block 使用
    ]
    >

    > f.get_own_local_noescaped_decl_ids()
    [
      ‍ [                    id <Identifier> {"name":"b"}] {},
      ‍ [                    id <Identifier> {"name":"c"}] {}
    ]
    >

    > f.get_nolocal_refed_ids()
    [
      ‍ [                            value <Identifier> {"name":"X"}] {}
    ]
    >




    > f.get_nodecl_notation_ids()
    [
      ‍ [                            value <Identifier> {"name":"X"}] {},
      ‍ [                    left <Identifier> {"name":"a"}] {},
      ‍ [                        left <Identifier> {"name":"b"}] {},
      ‍ [                        right <Identifier> {"name":"c"}] {},
      ‍ [                        left <Identifier> {"name":"a"}] {},             //<a> = a + u
      ‍ [                            left <Identifier> {"name":"a"}] {},         //  a = <a> + u
      ‍ [                            right <Identifier> {"name":"u"}] {},        // a = a + <u>
      ‍ [                argument <Identifier> {"name":"a"}] {}
    ]
    >
    > f.get_own_local_nodecl_ids()
    [
      ‍ [                    left <Identifier> {"name":"a"}] {},              //<a>=b+c
      ‍ [                        left <Identifier> {"name":"b"}] {},         //a=<b>+c
      ‍ [                        right <Identifier> {"name":"c"}] {},        //a=b+<c>
      ‍ [                argument <Identifier> {"name":"a"}] {}              //return(<a>)
    ]
    >

TAC format

  • used in a special js-runtime
  • normally useless

      > const {tree} = require("nv-js-parse")
      > var src =`ReactDOM.render(<App />, document.getElementById('root'));`
      > var t = tree(src,{plugins:["typescript","jsx"]})
    
      > t.$sdfs()
      [
        ‍ [program <Program> {"sourceType":"module","interpreter":null}] {},
        ‍ [    body[0] <ExpressionStatement> {}] {},
        ‍ [        expression <CallExpression> {}] {},
        ‍ [            callee <MemberExpression> {"computed":false}] {},
        ‍ [                object <Identifier> {"name":"ReactDOM"}] {},
        ‍ [                property <Identifier> {"name":"render"}] {},
        ‍ [            arguments[0] <JSXElement> {}] {},
        ‍ [                openingElement <JSXOpeningElement> {"selfClosing":true}] {},
        ‍ [                    name <JSXIdentifier> {"name":"App"}] {},
        ‍ [            arguments[1] <CallExpression> {}] {},
        ‍ [                callee <MemberExpression> {"computed":false}] {},
        ‍ [                    object <Identifier> {"name":"document"}] {},
        ‍ [                    property <Identifier> {"name":"getElementById"}] {},
        ‍ [                arguments[0] <StringLiteral> {"value":"root"}] {}
      ]
      >
    
      // K = listKey:AstString | Key:AstString
      // T = K@TYPE
      // Attr = Object
      // Ele  = [T,Attr?,Array<Ele>?]
      //
    
      > var tac = t.to_tac()
      > console.dir(tac,{depth:null})
      [
        'program@Program',{ sourceType: 'module', interpreter: null }, [
          'body@ExpressionStatement', [
            'expression@CallExpression', [
              'callee@MemberExpression',{ computed: false },[
                'object@Identifier',{ name: 'ReactDOM' },
                'property@Identifier',{ name: 'render' }
              ],
              'arguments@JSXElement',[
                'openingElement@JSXOpeningElement',{ selfClosing: true },[
                    'name@JSXIdentifier', { name: 'App' }
                 ]
              ],
              'arguments@CallExpression',[
                'callee@MemberExpression',{ computed: false },[
                  'object@Identifier',{ name: 'document' },
                  'property@Identifier',{ name: 'getElementById' }
                ],
                'arguments@StringLiteral',{ value: 'root' }
              ]
            ]
          ]
        ]
      ]

rplc_nodecl_undef_with_void0

    var code =`
    function tst() {
        let a = undefined;                          //============================>this undefined is right-hand  and on global,SHOULD-BE-REPLACED
        function inner() {
            let undefined = 999       //this undefined is left-hand and local #0
            return(undefined)          //this undefined is #0
        }
        console.log(1,inner())           //999
        function inner2() {
            function undefined () {     //this undefined is left-hand and local   #1
                return(undefined)       //this undefined is #1
            }
            return(undefined)          //this undefined is #1
        }
        console.log(2,inner2())           //[Function: undefined]
        function inner3() {
            let undefined =888;        //this undefined is left-hand and local #2
            let r = (()=> {
                return(undefined)      //this undefined is #2
            })();
            return(r)
        }
        console.log(3,inner3())                  //888
        /////
        function inner4() {
             try {
                 x = undefined ;   // ============================>this undefined is right-hand  and on global ,SHOULD-BE-REPLACED
                 throw(x)
             } catch(e){
                 return(e)
             }
        }
        console.log(4,inner4())    // undefined
        /////
        function inner5() {
           class undefined {
              m() {return(undefined)}                   //class undefined
           }
           t= new undefined()
           return(t)
        }
        console.log(5,inner5())   //undefined {}
        ////
        function inner6() {
           class C {
              undefined() {return(undefined)}            //global undefined coz classMethod
           }
           t= new C()
           return(t.undefined())
        }
        console.log(6,inner6())           //undefined
        /////
        function inner7() {
           let D= {
              undefined() {return(undefined)}            //global undefined coz ObjectMethod
           }
           return(D.undefined())
        }
        console.log(7,inner7())          //undefined
        /////
        function inner8() {
             function undefined() {
                 console.log('in fdecl',undefined)
                 return(undefined)                //function, coz FunctionDeclaration
             }
             console.log('in outter',undefined)
             return(undefined())
        }
        console.log(8,inner8())          //[Function: undefined]
        ////
        function inner9() {
             let _f = function undefined() {
                 console.log('A',undefined===_f)   //true
                 return(undefined)                //function coz FunctionExpression
             }
             console.log('B:',undefined===_f)    //false
             return(_f())
        }
        console.log(9,inner9())
    }
    `

    /*
    > tst()
    1 999
    2 [Function: undefined]
    3 888
    4 undefined
    5 undefined {}
    6 undefined
    7 undefined
    in outter [Function: undefined]
    in fdecl [Function: undefined]
    8 [Function: undefined]
    B: false
    A true
    9 [Function: undefined]
    undefined

    */

    console.log(rplc_nodecl_undef_with_void0(code))

    /*
    function tst() {
      let a = void 0; //============================>this undefined is right-hand  and on global,SHOULD-BE-REPLACED

      function inner() {
        let undefined = 999; //this undefined is left-hand and local #0

        return undefined; //this undefined is #0
      }

      console.log(1, inner()); //999

      function inner2() {
        function undefined() {
          //this undefined is left-hand and local   #1
          return undefined; //this undefined is #1
        }

        return undefined; //this undefined is #1
      }

      console.log(2, inner2()); //[Function: undefined]

      function inner3() {
        let undefined = 888; //this undefined is left-hand and local #2

        let r = (() => {
          return undefined; //this undefined is #2
        })();

        return r;
      }

      console.log(3, inner3()); //888
      /////

      function inner4() {
        try {
          x = void 0; // ============================>this undefined is right-hand  and on global ,SHOULD-BE-REPLACED

          throw x;
        } catch (e) {
          return e;
        }
      }

      console.log(4, inner4()); // undefined
      /////

      function inner5() {
        class undefined {
          m() {
            return undefined;
          } //class undefined


        }

        t = new undefined();
        return t;
      }

      console.log(5, inner5()); //undefined {}
      ////

      function inner6() {
        class C {
          undefined() {
            return void 0;
          } //global undefined coz classMethod


        }

        t = new C();
        return t.undefined();
      }

      console.log(6, inner6()); //undefined
      /////

      function inner7() {
        let D = {
          undefined() {
            return void 0;
          } //global undefined coz ObjectMethod


        };
        return D.undefined();
      }

      console.log(7, inner7()); //undefined
      /////

      function inner8() {
        function undefined() {
          console.log('in fdecl', undefined);
          return undefined; //function, coz FunctionDeclaration
        }

        console.log('in outter', undefined);
        return undefined();
      }

      console.log(8, inner8()); //[Function: undefined]
      ////

      function inner9() {
        let _f = function undefined() {
          console.log('A', undefined === _f); //true

          return undefined; //function coz FunctionExpression
        };

        console.log('B:', void 0 === _f); //false

        return _f();
      }

      console.log(9, inner9());
    }


    */

    /*
    > tst()
    1 999
    2 [Function: undefined]
    3 888
    4 undefined
    5 undefined {}
    6 undefined
    7 undefined
    in outter [Function: undefined]
    in fdecl [Function: undefined]
    8 [Function: undefined]
    B: false
    A true
    9 [Function: undefined]

    */

get funclike description

  • funclike: it is for convert a func/lambda/method to a single-param-function-without-any-lexical-binding
  • used in nvlang for fctx grammar
  • similiar to with , but NOT permit any lexical VarDeclaration
  • for tracing purpose

      {
        FunctionParent: [
          'FunctionDeclaration',
          'FunctionExpression',
          'ObjectMethod',
          'ArrowFunctionExpression',
          'ClassMethod',
          'ClassPrivateMethod'
        ]
      }

    var t = tree(`
        function tst(a,{b,c},...args) {
            let A;
            let B;
            let {x,y} = {};
        }
    `)

    /*
    > f.get_desc_of_funclike()
    [
      'tst',                                       //name
      'FunctionDeclaration',                       //ast-type
      { generator: false, async: false },          //attribs
      {
        A: null,
        B: null,
        x: null,
        y: null,
        a: null,
        b: null,
        c: null,
        args: []
      }                                            //---ctx after extract all params AND lexical-binding
    ]
    >
    */

signed-pl

  • find all declaration/def ids in a file, and generate a unique-path
  • it is used in nvlang for gproc grammar, which NOT permit any local variable

> t.$sdfs().filter(nd=>nd.is_decl_id()).map(id=>id.get_id_plsign())
[
  'body-0-declarations-0-id:traverse',
  'body-1-declarations-0-id-properties-0-value:SimpleStack',
  'body-1-declarations-0-id-properties-1-value:DPGT',
  'body-1-declarations-0-id-properties-2-value:is_int',
  'body-1-declarations-0-id-properties-3-value:is_str',
  'body-2-declarations-0-id-properties-0-value:Root',
  'body-3-declarations-0-id:ary_clu',
  .....

for stmt to while

    var cd = `
    function tst() {
        for(let i=0;i<999;i++) {
            console.log(i);
            let b = i +666
        }
    }`


    console.log(for_stmt_to_while(cd))
    /*
    function tst() {
      {
        let i = 0;

        while (i < 999) {
          console.log(i);
          let b = i + 666;
          i++
        }
      }
    }

    */


    var cd = `
    async function tst() {
        let b;
        for(let i=0;i<999;i++) {
            await i;
            console.log(i);
            b = i +666;
            if(b>1500) {
                break
            }
        }
        return(b)
    }`

    console.log(for_stmt_to_while(cd))
    /*
    async function tst() {
      let b;
      {
        let i = 0;

        while (i < 999) {
          await i;
          console.log(i);
          b = i + 666;

          if (b > 1500) {
            break;
          }

          i++
        }
      }
      return b;
    }

    */

fmt-una-expr

  • wrap UnaryExpression in a SequenceExpression
  • normally useless

    > x.fmt_una_expr('!a')
    '!(0, a);'
    >


    > x.fmt_una_expr('!(typeof u.v)')
    '!(0, typeof (0, u.v));'
    >

replace update-expression WITH a closure

  • update-expr is boring to do static tracing

    var cd =`
    function tst(arr) {
        let v = 100;
        let d = {prop:100}
        arr = arr.forEach(
            nd => {
               v = v++;
               v = v--;
               v = ++v;
               --v;
               d.prop++;
               d.prop=++d.prop;
               d.prop--;
               d.prop=--d.prop;
            }
        )
        return([v,d])
    }
    `

    /*
    > tst([1,1,1])
    [ 100, { prop: 100 } ]
    >

    */

    console.log(rplc_updt_expr_with_closure(cd))


    /*
    function tst(arr) {
      let v = 100;
      let d = {
        prop: 100
      };
      arr = arr.forEach(nd => {
        v = (() => {
          let old_val = v;
          let new_val = old_val + 1;
          v = new_val;
          return old_val;                                    // v++  postfix-rtrn-old
        })();

        v = (() => {
          let old_val = v;
          let new_val = old_val - 1;
          v = new_val;
          return old_val;                                  //v--   postfix-rtrn-old
        })();

        v = (() => {
          let old_val = v;
          let new_val = old_val + 1;
          v = new_val;
          return new_val;                                 //++v  prefix-rtrn-new
        })();

        (() => {
          let old_val = v;
          let new_val = old_val - 1;
          v = new_val;
          return new_val;                                  //--v  prefix-rtrn-new
        })();

        (() => {
          let old_val = d.prop;
          let new_val = old_val + 1;
          d.prop = new_val;
          return old_val;
        })();

        d.prop = (() => {
          let old_val = d.prop;
          let new_val = old_val + 1;
          d.prop = new_val;
          return new_val;
        })();

        (() => {
          let old_val = d.prop;
          let new_val = old_val - 1;
          d.prop = new_val;
          return old_val;
        })();

        d.prop = (() => {
          let old_val = d.prop;
          let new_val = old_val - 1;
          d.prop = new_val;
          return new_val;
        })();
      });
      return [v, d];
    }

    */

    > tst([1,1,1])
    [ 100, { prop: 100 } ]
    >

get_completion_parent_nd

  • get the completion parent closure/block of
  • return/throw/break/continue

    var src = `
    function tst() {
        var m=0
        xx:while(m<3){
            console.log("here")
            i = 0;
            n = 0;
            while (i < 5) {
               i++;
               if (i === 3) {
                  continue xx;
               }
               n += i;
            }
            m=m+1
        }
        function inner() {
            for(let i=0;i<5;i++){
                break
                return(i)
            }
        }
    }
    `

    //return

    var t = tree(src);
    var rtrn_stmt = t.ReturnStatement()[0];
    > rtrn_stmt
     [69:                            body[1] <ReturnStatement> {}] {}
    >
    > var completion = rtrn_stmt.get_completion_parent_nd()

    > completion
     [54:            body[2] <FunctionDeclaration> {"generator":false,"async":false}] {}
    >
    > completion.show_code()
    function inner() {
      for (let i = 0; i < 5; i++) {
        break;
        return i;
      }
    }


    //break
    > var brk_stmt = t.BreakStatement()[0]

    > brk_stmt
     [68:                            body[0] <BreakStatement> {}] {}
    >
    > var completion = brk_stmt.get_completion_parent_nd()
    > completion
     [57:                    body[0] <ForStatement> {}] {}
    > completion.show_code()
    for (let i = 0; i < 5; i++) {
      break;
      return i;
    }


    //continue label

    > var conti_stmt = t.ContinueStatement()[0]
    undefined
    > conti_stmt
     [42:                                        body[0] <ContinueStatement> {}] {}
    >
    > var completion = conti_stmt.get_completion_parent_nd()
    undefined
    > completion
     [10:                body <WhileStatement> {}] {}
    >
    > completion.show_code()
    while (m < 3) {
      console.log("here");
      i = 0;
      n = 0;

      while (i < 5) {
        i++;

        if (i === 3) {
          continue xx;
        }

        n += i;
      }

      m = m + 1;
    }
    > completion.$parent()
     [8:            body[1] <LabeledStatement> {}] {}
    > completion.$parent().show_code()
    xx: while (m < 3) {
      console.log("here");
      i = 0;
      n = 0;

      while (i < 5) {
        i++;

        if (i === 3) {
          continue xx;
        }

        n += i;
      }

      m = m + 1;
    }

get_completion_check_points

  • find break/continue 's corresponding block/forin/forof/for/while/dowhile/switch
  • find return/throw 's corresponding func-decl/func-expr/cls-method/obj-method/arrow/cls-priv-method

    var src = `
    function tst() {
        while(true) {
            return(100)
        }
        try {
            return(200)
        } catch(e) {
             ()=> {
                 return('!!')
             }
        } finally {
        }
        {
           throw(400)
        }
    }`

    > var t = tree(src)
    > t.FunctionDeclaration()[0]
     [1:    body[0] <FunctionDeclaration> {"generator":false,"async":false}] {}
    > var fdecl = t.FunctionDeclaration()[0]
    > fdecl.get_rtrn_check_points()
    [
      ‍ [7:                    body[0] <ReturnStatement> {}] {},
      ‍ [11:                    body[0] <ReturnStatement> {}] {}
    ]
    > var rtrns = fdecl.get_rtrn_check_points()
    > rtrns
    [
      ‍ [7:                    body[0] <ReturnStatement> {}] {},
      ‍ [11:                    body[0] <ReturnStatement> {}] {}
    ]
    > rtrns.map(nd=>nd.show_code())
    return 100;
    return 200;

rm_sibs_after_completion

  • remove following-sibs of completion-node ,see below

    var src = `
    function tst() {
        try {
           let a = 1;
           return(a);
           let b = a*2;
           console.log(b)               //-----------------------------remove
        } catch(e) {
           LBL:for(let a in M) {
             while(true) {
                  if(x) {
                      break;
                      console.log(x)     //-----------------------------remove
                  } else if(y) {
                       continue LBL;
                       console.log(666)   //-----------------------------remove
                  } else {
                       switch(XX) {
                          case(0): {
                          }
                          case(1): {
                              break;
                              console.log(UUU)  //-----------------------------remove
                          }
                       }
                  }
             }
          }
        }
    }
    `

    console.log(x.rm_sibs_after_completion(src))


    /*
    function tst() {
      try {
        let a = 1;
        return a;
      } catch (e) {
        LBL: for (let a in M) {
          while (true) {
            if (x) {
              break;
            } else if (y) {
              continue LBL;
            } else {
              switch (XX) {
                case 0:
                  {}

                case 1:
                  {
                    break;
                  }
              }
            }
          }
        }
      }
    }

    */

tailize_try_catch_final

why

  • finalizer of try-statement is confusing
  • its write-order is at last, but its executing order is just before return/throw in try/catch
  • but the write-order of try/catch is BEFORE finalizer
  • I can NOT understand this
  • so transform the finalizer AND make it "reasonable"

example

    > function tst() {
    ...     try {
    .....         console.log(`before-return-in-try`)
                                                         //<====  #0
    .....         return(`i-am-returned`)
    .....     } finally {
    .....         console.log(`finalizer write after try-block`)
    .....     }
    ... }
    >
    > tst()
    before-return-in-try
    finalizer write after try-block   // 
    'i-am-returned'
    >
    >

step

    1. this will take the return-statement|throw-statement out from try-stmt-block|try-catch-handler
    1. convert 【return-statement|throw-statement in 1.】 to a 【if/esle block】
    1. convert try-stmt-finalizer to 【a block】
    1. delete the original try-stmt-finalizer
    1. put the 【if/esle block in 2.】 after 【converted-block-from-try-stmt-finalizer in 3.】
    1. generate a 【block-contain-return|throw】
    1. put the 【block-contain-return|throw in 6.】 at end

purpose

  • its purpose is to tailized rtrn/thrw of try-stmt AND transform the finalizer to its proper position
  • to make the write/read order same-as the execution-order
  • coz, the finally block is boring for static-tracing
  • hard to explain , just see the below examples,example is easy to understand

input

    var src =`
    function tst() {
        let a = 100;

            try {
                let a = (()=>{
                        try {
                                throw(1);
                                    console.log("unreachable")
                            } catch(e) {
                                return(e);
                                    console.log("unreachable")
                            } finally {
                                console.log('inner')
                            }
                    })();
                    if(a>0) {
                            return(a*2);
                            console.log("unreachable")
                    } else {
                        return(a*3)
                            console.log("unreachable")
                    }

            } catch ({e}) {
                console.log("unreachable")
            } finally {
                let arr = [a,a*2,a*3]
                console.log(arr)
            }

            let c = a*3;
            return(c)

    }
    `


    /*
    > tst()
    inner
    [ 100, 200, 300 ]
    2
    >

    */

output

   > console.log(x.tailize_try_catch_final(src))


    function tst() {
      let a = 100;
      //outer-try-catch-final
      {
        let ___τfinalización = [undefined, undefined];
        //outer-try-block
        {
          let a = (() => {
            //inner-  try-catch-final
            {
              let ___τfinalización = [undefined, undefined];
              //inner-try-block
              {
                ___τfinalización = [false, 1];
              }
              //inner-catch-handle
              if (___τfinalización[0] === false) {
                let ___τcatch_clause_value = ___τfinalización[1];
                {
                  let e = ___τcatch_clause_value;
                  ___τfinalización = [true, e];
                }
              } else {}
              //inner-final-block
              {
                console.log('inner');
              }
              //inner-tailized-completion-of-try-catch-final-stmt
              if (___τfinalización[0] === undefined) {} else if (___τfinalización[0] === true) {
                return ___τfinalización[1];
              } else {
                throw ___τfinalización[1];
              }
            }
          })();

          if (a > 0) {
            ___τfinalización = [true, a * 2];
          } else {
            ___τfinalización = [true, a * 3];
          }
        }

        //outer-catch-handle
        if (___τfinalización[0] === false) {
          let ___τcatch_clause_value = ___τfinalización[1];
          {
            let {
              e
            } = ___τcatch_clause_value;
            console.log("unreachable");
          }
        } else {}
        
        //outer-final-block
        {
          let arr = [a, a * 2, a * 3];
          console.log(arr);
        }

        //out-tailized-completion-of-try-catch-final-stmt
        if (___τfinalización[0] === undefined) {} else if (___τfinalización[0] === true) {
          return ___τfinalización[1];
        } else {
          throw ___τfinalización[1];
        }
      }
      let c = a * 3;
      return c;
    }


    /*
    > tst()
    inner
    [ 100, 200, 300 ]
    2
    >

    */

fmt-asgn-expr

  • must used after split_var_decl AND split_var_declor

 replace the below with a = a<op> b

      OP_TO_BINOP: {
        '+=': '+',
        '-=': '-',
        '/=': '/',
        '%=': '%',
        '*=': '*',
        '**=': '**',
        '&=': '&',
        '|=': '|',
        '>>=': '>>',
        '>>>=': '>>>',
        '<<=': '<<',
        '^=': '^',
        '||=': '||',
        '&&=': '&&',
        '??=': '??'
      },

  for example:
       a+=999
       will be replaced to 
          a = a + 999;

  this is for functionize-bin-operator, which will remove all bin-operator
  normally useless

    var  cd =`
        function tst() {
      
1.4.21

8 months ago

1.4.23

8 months ago

1.4.25

8 months ago

1.4.15

8 months ago

1.4.14

8 months ago

1.4.17

8 months ago

1.4.16

8 months ago

1.4.18

8 months ago

1.4.7

8 months ago

1.3.65

11 months ago

1.3.68

10 months ago

1.3.69

9 months ago

1.3.66

10 months ago

1.3.67

10 months ago

1.4.6

9 months ago

1.4.5

9 months ago

1.4.2

9 months ago

1.4.1

9 months ago

1.3.90

9 months ago

1.3.93

9 months ago

1.3.94

9 months ago

1.3.91

9 months ago

1.3.92

9 months ago

1.3.98

9 months ago

1.3.95

9 months ago

1.3.96

9 months ago

1.3.72

9 months ago

1.3.75

9 months ago

1.3.76

9 months ago

1.3.78

9 months ago

1.3.87

9 months ago

1.3.84

9 months ago

1.3.85

9 months ago

1.3.88

9 months ago

1.3.53

1 year ago

1.3.57

1 year ago

1.3.58

1 year ago

1.3.56

1 year ago

1.3.59

1 year ago

1.3.64

1 year ago

1.3.62

1 year ago

1.3.63

1 year ago

1.3.50

2 years ago

1.3.52

2 years ago

1.3.32

2 years ago

1.3.30

2 years ago

1.3.36

2 years ago

1.3.33

2 years ago

1.3.39

2 years ago

1.3.37

2 years ago

1.3.38

2 years ago

1.3.42

2 years ago

1.3.43

2 years ago

1.3.40

2 years ago

1.3.41

2 years ago

1.3.46

2 years ago

1.3.47

2 years ago

1.3.45

2 years ago

1.3.19

2 years ago

1.3.20

2 years ago

1.3.21

2 years ago

1.3.24

2 years ago

1.3.25

2 years ago

1.3.22

2 years ago

1.3.23

2 years ago

1.3.28

2 years ago

1.3.29

2 years ago

1.3.26

2 years ago

1.3.27

2 years ago

1.3.10

2 years ago

1.3.13

2 years ago

1.3.14

2 years ago

1.3.12

2 years ago

1.3.17

2 years ago

1.3.15

2 years ago

1.3.16

2 years ago

1.2.0

2 years ago

1.2.8

2 years ago

1.2.7

2 years ago

1.2.6

2 years ago

1.2.5

2 years ago

1.2.4

2 years ago

1.2.3

2 years ago

1.2.2

2 years ago

1.2.1

2 years ago

1.3.9

2 years ago

1.3.8

2 years ago

1.2.12

2 years ago

1.2.13

2 years ago

1.2.10

2 years ago

1.2.11

2 years ago

1.2.16

2 years ago

1.2.17

2 years ago

1.2.14

2 years ago

1.2.18

2 years ago

1.2.19

2 years ago

1.3.7

2 years ago

1.1.9

2 years ago

1.3.6

2 years ago

1.1.8

2 years ago

1.3.5

2 years ago

1.3.4

2 years ago

1.3.3

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.2.20

2 years ago

1.2.23

2 years ago

1.1.12

2 years ago

1.2.24

2 years ago

1.1.11

2 years ago

1.2.21

2 years ago

1.1.10

2 years ago

1.2.22

2 years ago

1.2.28

2 years ago

1.2.25

2 years ago

1.2.26

2 years ago

1.1.13

2 years ago

1.2.29

2 years ago

1.2.30

2 years ago

1.2.9

2 years ago

1.1.7

2 years ago

1.1.6

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.1.4

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

1.0.40

2 years ago

1.0.44

2 years ago

1.0.43

2 years ago

1.0.41

2 years ago

1.0.19

3 years ago

1.0.18

3 years ago

1.0.39

3 years ago

1.0.16

3 years ago

1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.21

3 years ago

1.0.20

3 years ago

1.0.25

3 years ago

1.0.24

3 years ago

1.0.23

3 years ago

1.0.28

3 years ago

1.0.33

3 years ago

1.0.11

3 years ago

1.0.32

3 years ago

1.0.30

3 years ago

1.0.37

3 years ago

1.0.15

3 years ago

1.0.36

3 years ago

1.0.14

3 years ago

1.0.13

3 years ago

1.0.12

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago