@@ -652,22 +652,15 @@ const evaluate_map: EvaluateMap = {
652652  MemberExpression ( path )  { 
653653    const  { node,  scope,  ctx}  =  path ; 
654654    const  { object,  property,  computed}  =  node ; 
655-     if  ( types . isSuper ( node . object ) )  { 
656-       const  $var  =  scope . $find ( "this" ) ; 
657-       if  ( $var )  { 
658-         const  __this  =  $var . $get ( ) ; 
659-         if  ( ctx . SuperClass )  { 
660-           return  ctx . SuperClass . prototype [ ( < any > property ) . name ] . bind ( __this ) ; 
661-         }  else  { 
662-           throw  node ; 
663-         } 
664-       } 
665-     } 
666-     if  ( computed )  { 
667-       return  evaluate ( path . $child ( object ) ) [ evaluate ( path . $child ( property ) ) ] ; 
668-     }  else  { 
669-       return  evaluate ( path . $child ( object ) ) [ ( < types . Identifier > property ) . name ] ; 
670-     } 
655+ 
656+     const  propertyName : string  =  computed 
657+       ? evaluate ( path . $child ( property ) ) 
658+       : ( < types . Identifier > property ) . name ; 
659+ 
660+     const  obj  =  evaluate ( path . $child ( object ) ) ; 
661+     const  target  =  obj [ propertyName ] ; 
662+ 
663+     return  typeof  target  ===  "function"  ? target . bind ( obj )  : target ; 
671664  } , 
672665  AssignmentExpression ( path )  { 
673666    const  { node,  scope}  =  path ; 
@@ -781,10 +774,10 @@ const evaluate_map: EvaluateMap = {
781774      } 
782775    } ; 
783776
784-     Object . defineProperties ( func , { 
785-       length :{ value :node . params . length } , 
786-       name : { value :node . id  ? node . id . name  : "" } 
787-     } ) 
777+     Object . defineProperties ( func ,   { 
778+       length :  { value :  node . params . length } , 
779+       name : { value :  node . id  ? node . id . name  : "" } 
780+     } ) ; 
788781
789782    return  func ; 
790783  } , 
@@ -800,96 +793,75 @@ const evaluate_map: EvaluateMap = {
800793    return  path . node . value . raw ; 
801794  } , 
802795  ClassDeclaration ( path )  { 
796+     const  ClassConstructor  =  evaluate ( 
797+       path . $child ( path . node . body ,  path . scope . $child ( "block" ) ) 
798+     ) ; 
799+     path . scope . $const ( path . node . id . name ,  ClassConstructor ) ; 
800+   } , 
801+   ClassBody ( path )  { 
803802    const  { node,  scope}  =  path ; 
804-     const  constructor : types . ClassMethod  |  void =  < types . ClassMethod  |  void > node . body . body . find ( 
803+     const  constructor : types . ClassMethod  |  void =  < types . ClassMethod  |  void > node . body . find ( 
805804      n  =>  types . isClassMethod ( n )  &&  n . kind  ===  "constructor" 
806805    ) ; 
807-     const  methods : types . ClassMethod [ ]  =  < types . ClassMethod [ ] > node . body . body . filter ( 
806+     const  methods : types . ClassMethod [ ]  =  < types . ClassMethod [ ] > node . body . filter ( 
808807      n  =>  types . isClassMethod ( n )  &&  n . kind  !==  "constructor" 
809808    ) ; 
810-     const  properties : types . ClassProperty [ ]  =  < types . ClassProperty [ ] > node . body . body . filter ( 
809+     const  properties : types . ClassProperty [ ]  =  < types . ClassProperty [ ] > node . body . filter ( 
811810      n  =>  types . isClassProperty ( n ) 
812811    ) ; 
813812
814-     let  SuperClass ; 
815- 
816-     if  ( node . superClass )  { 
817-       const  superClassName : string  =  ( < any > node . superClass ) . name ; 
818-       const  $var  =  scope . $find ( superClassName ) ; 
819- 
820-       if  ( $var )  { 
821-         SuperClass  =  $var . $get ( ) ; 
822-       }  else  { 
823-         throw  new  ErrNotDefined ( superClassName ) ; 
824-       } 
825-     } 
813+     const  parentNode  =  ( < Path < types . ClassDeclaration > > path . parent ) . node ; 
826814
827815    const  Class  =  ( function ( SuperClass )  { 
828816      if  ( SuperClass )  { 
829817        _inherits ( Class ,  SuperClass ) ; 
830818      } 
819+ 
831820      function  Class ( ...args )  { 
832821        _classCallCheck ( this ,  Class ) ; 
833- 
834-         const  newScope  =  scope . $child ( "function" ) ; 
835- 
836-         // babel way to call super(); 
837-         const  __this  =  _possibleConstructorReturn ( 
838-           this , 
839-           ( ( < any > Class ) . __proto__  ||  Object . getPrototypeOf ( Class ) ) . apply ( 
840-             this , 
841-             args 
842-           ) 
843-         ) ; 
844- 
845-         newScope . $const ( "super" ,  this . __proto__ ) ; 
846- 
847-         // typescript way to call super() 
848-         // const __this = superClass ? superClass.apply(this, args) || this : this; 
849- 
850-         newScope . $const ( "this" ,  __this ) ; 
822+         const  classScope  =  scope . $child ( "function" ) ; 
823+         classScope . $var ( "this" ,  this ) ; 
851824
852825        // define class property 
853826        properties . forEach ( p  =>  { 
854-           __this [ p . key . name ]  =  evaluate ( path . $child ( p . value ,  newScope ) ) ; 
827+           this [ p . key . name ]  =  evaluate ( path . $child ( p . value ,  classScope ) ) ; 
855828        } ) ; 
856829
857830        if  ( constructor )  { 
858831          // defined the params 
859832          constructor . params . forEach ( ( p : types . LVal ,  i )  =>  { 
860833            if  ( types . isIdentifier ( p ) )  { 
861-               newScope . $const ( p . name ,  args [ i ] ) ; 
834+               classScope . $const ( p . name ,  args [ i ] ) ; 
862835            }  else  { 
863836              throw  new  Error ( "Invalid params" ) ; 
864837            } 
865838          } ) ; 
839+           constructor . body . body . forEach ( n  => 
840+             evaluate ( 
841+               path . $child ( n ,  classScope ,  { 
842+                 SuperClass, 
843+                 ClassConstructor : Class , 
844+                 ClassConstructorArguments : args , 
845+                 ClassEntity : this 
846+               } ) 
847+             ) 
848+           ) ; 
866849
867-           if  ( node . superClass )  { 
868-             // make sure super exist in first line 
869-             const  superCallExpression : types . ExpressionStatement  =  < types . ExpressionStatement > ( < any > constructor ) . body . body . shift ( ) ; 
870- 
871-             if  ( 
872-               ! types . isExpressionStatement ( superCallExpression )  || 
873-               ! types . isCallExpression ( superCallExpression . expression )  || 
874-               ! types . isSuper ( superCallExpression . expression . callee ) 
875-             )  { 
850+           if  ( parentNode . superClass )  { 
851+             // if not apply super in construtor 
852+             // FIXME: should define the var in private scope 
853+             if  ( ! scope . $find ( "@super" ) )  { 
876854              throw  ErrNoSuper ; 
877-             }  else  { 
878-               // TODO: run super 
879855            } 
880856          } 
881- 
882-           constructor . body . body . forEach ( n  => 
883-             evaluate ( path . $child ( n ,  newScope ,  { SuperClass} ) ) 
884-           ) ; 
885857        } 
886858
887-         return  __this ; 
859+         return  this ; 
888860      } 
889861
890862      // define class name 
891863      Object . defineProperties ( Class ,  { 
892-         name : { value : node . id . name } , 
864+         name : { value : parentNode . id . name } , 
893865        length : { value : constructor  ? constructor . params . length  : 0 } 
894866      } ) ; 
895867
@@ -907,7 +879,12 @@ const evaluate_map: EvaluateMap = {
907879            } ) ; 
908880
909881            const  result  =  evaluate ( 
910-               path . $child ( method . body ,  newScope ,  { SuperClass} ) 
882+               path . $child ( method . body ,  newScope ,  { 
883+                 SuperClass, 
884+                 ClassConstructor : Class , 
885+                 ClassMethodArguments : args , 
886+                 ClassEntity : this 
887+               } ) 
911888            ) ; 
912889            if  ( result  ===  RETURN_SINGAL )  { 
913890              return  result . result  ? result . result  : result ; 
@@ -934,17 +911,54 @@ const evaluate_map: EvaluateMap = {
934911      _createClass ( Class ,  _methods ) ; 
935912
936913      return  Class ; 
937-     } ) ( SuperClass ) ; 
914+     } ) ( 
915+       parentNode . superClass 
916+         ? ( ( )  =>  { 
917+             const  $var  =  scope . $find ( ( < any > parentNode . superClass ) . name ) ; 
918+             return  $var  ? $var . $get ( )  : null ; 
919+           } ) ( ) 
920+         : null 
921+     ) ; 
938922
939-     scope . $const ( node . id . name ,  Class ) ; 
923+     return  Class ; 
940924  } , 
941925  ClassMethod ( path )  { 
942926    return  evaluate ( path . $child ( path . node . body ) ) ; 
943927  } , 
944928  ClassExpression ( path )  { } , 
945929  Super ( path )  { 
946-     // FIXME: check it include in Class expression 
947-     return  function ( )  { } ; 
930+     const  { scope,  ctx}  =  path ; 
931+     const  { 
932+       SuperClass, 
933+       ClassConstructor, 
934+       ClassConstructorArguments, 
935+       ClassEntity
936+     }  =  ctx ; 
937+     const  ClassBodyPath  =  path . $findParent ( "ClassBody" ) ; 
938+     // make sure it include in ClassDeclaration 
939+     if  ( ! ClassBodyPath )  { 
940+       throw  new  Error ( "super() only can use in ClassDeclaration" ) ; 
941+     } 
942+     const  parentPath  =  path . parent ; 
943+     if  ( parentPath )  { 
944+       // super() 
945+       if  ( types . isCallExpression ( parentPath . node ) )  { 
946+         return  function  inherits ( ...args )  { 
947+           _possibleConstructorReturn ( 
948+             ClassEntity , 
949+             ( 
950+               ( < any > ClassConstructor ) . __proto__  || 
951+               Object . getPrototypeOf ( ClassConstructor ) 
952+             ) . apply ( ClassEntity ,  args ) 
953+           ) ; 
954+           ClassBodyPath . scope . $const ( "@super" ,  true ) ; 
955+         } . bind ( ClassEntity ) ; 
956+       }  else  if  ( types . isMemberExpression ( parentPath . node ) )  { 
957+         // super.eat() 
958+         // then return the superclass prototype 
959+         return  SuperClass . prototype ; 
960+       } 
961+     } 
948962  } , 
949963  SpreadElement ( path )  { 
950964    return  evaluate ( path . $child ( path . node . argument ) ) ; 
0 commit comments