Advertisement
Guest User

Untitled

a guest
Jan 11th, 2019
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.70 KB | None | 0 0
  1. package ftk.tools;
  2.  
  3. #if macro
  4. import haxe.macro.Context;
  5. import haxe.macro.Type;
  6. import haxe.macro.Expr;
  7. #else
  8. import ftk.db.Object;
  9. #end
  10.  
  11. /**
  12. * ...
  13. * @author
  14. */
  15.  
  16. enum EProp {
  17. ESimple( prop : String );
  18. EComplex( prop : String, props : Array<EProp> );
  19. }
  20.  
  21. class SerializeHelper {
  22. #if !macro
  23. public static inline function with<T:Object>( o : T, props : Array<EProp> ) : T {
  24. for ( eprop in props ){
  25. switch( eprop ){
  26. case ESimple( prop ) :
  27. if ( o.xfields.indexOf( prop ) == -1 ){
  28. o.xfields.push( prop );
  29. }
  30. case EComplex( prop, props ) :
  31. if ( o.xfields.indexOf( prop ) == -1 ){
  32. o.xfields.push( prop );
  33. }
  34. var v : Dynamic = Reflect.getProperty( o, prop );
  35. if ( Std.is( v, Array ) ){
  36. SerializeIterableHelper.with( (v:Array<T>), props );
  37. }else if ( Std.is( v, List ) ){
  38. SerializeIterableHelper.with( (v:List<T>), props );
  39. }else {
  40. SerializeHelper.with( (v:T), props );
  41. }
  42. }
  43. }
  44. return o;
  45. }
  46. #end
  47. }
  48.  
  49. class SerializeIterableHelper {
  50. #if !macro
  51. public static inline function with<T:Object>( it : Iterable<T>, props : Array<EProp> ) : Iterable<T>{
  52. for ( o in it ){
  53. SerializeHelper.with( o , props );
  54. }
  55. return it;
  56. }
  57. #end
  58. }
  59.  
  60. class MacroSerializeHelper{
  61. @:access( ftk.tools._MacroSerializeHelper.processWithCall )
  62. public static macro function mwith( expr : ExprOf<Object>, properties : Array<Expr> ) : Expr {
  63. return _MacroSerializeHelper.processWithCall( expr, properties );
  64. }
  65. }
  66.  
  67. class MacroSerializeIterableHelper{
  68. @:access( ftk.tools._MacroSerializeHelper.processWithCall )
  69. public static macro function mwith( expr : ExprOf<Iterable<Object>>, properties : Array<Expr> ) : Expr {
  70. return _MacroSerializeHelper.processWithCall( expr, properties );
  71. }
  72. }
  73.  
  74. class _MacroSerializeHelper {
  75.  
  76. #if macro
  77.  
  78. static function processWithCall( obj:Expr, properties:Array<Expr> ):Expr {
  79. var lines = process( obj, obj, properties, [macro var __obj = $obj] );
  80. lines.push( macro __obj );
  81. return macro @:pos(obj.pos) $b{lines};
  82. }
  83.  
  84. static function processObjects( iterable:Expr, typedIterable:Expr, properties:Array<Expr>, blockExpressions:Array<Expr> ):Array<Expr> {
  85. var ident = macro __obj;
  86. var typeExpr = macro $typedIterable.iterator().next();
  87. var lines = processObject( ident, typeExpr, properties, [] );
  88. var block = macro $b{lines};
  89. var loopExpr = macro for ($ident in $iterable) $block;
  90. blockExpressions.push( loopExpr );
  91. return blockExpressions;
  92. }
  93.  
  94. static function processObject( obj:Expr, typedExpr:Expr, properties:Array<Expr>, blockExpressions:Array<Expr> ):Array<Expr> {
  95. var fields = macro @:pos(obj.pos) $obj.xfields;
  96. function addField( propertyName:String ) {
  97. var expr = macro if ($fields.indexOf($v{propertyName})==-1) $fields.push( $v{propertyName} );
  98. var getterCall = macro $obj.$propertyName;
  99. blockExpressions.push( getterCall );
  100. blockExpressions.push( expr );
  101. }
  102. function removeField( propertyName:String ) {
  103. var expr = macro while ($fields.indexOf($v{propertyName})>-1) $fields.remove( $v{propertyName} );
  104. blockExpressions.push( expr );
  105. }
  106. for ( p in properties ) {
  107. switch p {
  108. case macro []:
  109. blockExpressions.push( macro $fields = [] );
  110. case macro $i{propertyName}:
  111. Context.typeof( macro @:pos(obj.pos) $typedExpr.$propertyName );
  112. addField( propertyName );
  113. case macro -$i{propertyName}:
  114. Context.typeof( macro @:pos(obj.pos) $typedExpr.$propertyName );
  115. removeField( propertyName );
  116. case macro $i{propertyName}=>$a{subProperties}:
  117. var property = macro @:pos(obj.pos) $obj.$propertyName;
  118. var typedProperty = macro @:pos(obj.pos) $typedExpr.$propertyName;
  119. addField( propertyName );
  120. process( property, typedProperty, subProperties, blockExpressions );
  121. case _:
  122. Context.fatalError( 'Could not understand property name ${ Std.string( p ) }', Context.currentPos() );
  123. }
  124. }
  125. return blockExpressions;
  126. }
  127.  
  128. static function process( expr:Expr, typedProp:Expr, properties:Array<Expr>, blockExpressions:Array<Expr> ):Array<Expr> {
  129. var exprType = Context.typeof( typedProp );
  130. var objectType = Context.typeof( macro new ftk.db.Object() );
  131. var iterableType = Context.typeof( macro { var it : Iterable<ftk.db.Object> = null; it; } );
  132.  
  133. if ( Context.unify(exprType, objectType) ) {
  134. return processObject( expr, typedProp, properties, blockExpressions );
  135. }
  136. else if ( Context.unify(exprType,iterableType) ) {
  137. return processObjects( expr, typedProp, properties, blockExpressions );
  138. }
  139. else {
  140. Context.fatalError( '${ Std.string( expr ) } is not a ftk.db.Object nor Iterable of', Context.currentPos() );
  141. return null;
  142. }
  143. }
  144. #end
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement