Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ftk.tools;
- #if macro
- import haxe.macro.Context;
- import haxe.macro.Type;
- import haxe.macro.Expr;
- #else
- import ftk.db.Object;
- #end
- /**
- * ...
- * @author
- */
- enum EProp {
- ESimple( prop : String );
- EComplex( prop : String, props : Array<EProp> );
- }
- class SerializeHelper {
- #if !macro
- public static inline function with<T:Object>( o : T, props : Array<EProp> ) : T {
- for ( eprop in props ){
- switch( eprop ){
- case ESimple( prop ) :
- if ( o.xfields.indexOf( prop ) == -1 ){
- o.xfields.push( prop );
- }
- case EComplex( prop, props ) :
- if ( o.xfields.indexOf( prop ) == -1 ){
- o.xfields.push( prop );
- }
- var v : Dynamic = Reflect.getProperty( o, prop );
- if ( Std.is( v, Array ) ){
- SerializeIterableHelper.with( (v:Array<T>), props );
- }else if ( Std.is( v, List ) ){
- SerializeIterableHelper.with( (v:List<T>), props );
- }else {
- SerializeHelper.with( (v:T), props );
- }
- }
- }
- return o;
- }
- #end
- }
- class SerializeIterableHelper {
- #if !macro
- public static inline function with<T:Object>( it : Iterable<T>, props : Array<EProp> ) : Iterable<T>{
- for ( o in it ){
- SerializeHelper.with( o , props );
- }
- return it;
- }
- #end
- }
- class MacroSerializeHelper{
- @:access( ftk.tools._MacroSerializeHelper.processWithCall )
- public static macro function mwith( expr : ExprOf<Object>, properties : Array<Expr> ) : Expr {
- return _MacroSerializeHelper.processWithCall( expr, properties );
- }
- }
- class MacroSerializeIterableHelper{
- @:access( ftk.tools._MacroSerializeHelper.processWithCall )
- public static macro function mwith( expr : ExprOf<Iterable<Object>>, properties : Array<Expr> ) : Expr {
- return _MacroSerializeHelper.processWithCall( expr, properties );
- }
- }
- class _MacroSerializeHelper {
- #if macro
- static function processWithCall( obj:Expr, properties:Array<Expr> ):Expr {
- var lines = process( obj, obj, properties, [macro var __obj = $obj] );
- lines.push( macro __obj );
- return macro @:pos(obj.pos) $b{lines};
- }
- static function processObjects( iterable:Expr, typedIterable:Expr, properties:Array<Expr>, blockExpressions:Array<Expr> ):Array<Expr> {
- var ident = macro __obj;
- var typeExpr = macro $typedIterable.iterator().next();
- var lines = processObject( ident, typeExpr, properties, [] );
- var block = macro $b{lines};
- var loopExpr = macro for ($ident in $iterable) $block;
- blockExpressions.push( loopExpr );
- return blockExpressions;
- }
- static function processObject( obj:Expr, typedExpr:Expr, properties:Array<Expr>, blockExpressions:Array<Expr> ):Array<Expr> {
- var fields = macro @:pos(obj.pos) $obj.xfields;
- function addField( propertyName:String ) {
- var expr = macro if ($fields.indexOf($v{propertyName})==-1) $fields.push( $v{propertyName} );
- var getterCall = macro $obj.$propertyName;
- blockExpressions.push( getterCall );
- blockExpressions.push( expr );
- }
- function removeField( propertyName:String ) {
- var expr = macro while ($fields.indexOf($v{propertyName})>-1) $fields.remove( $v{propertyName} );
- blockExpressions.push( expr );
- }
- for ( p in properties ) {
- switch p {
- case macro []:
- blockExpressions.push( macro $fields = [] );
- case macro $i{propertyName}:
- Context.typeof( macro @:pos(obj.pos) $typedExpr.$propertyName );
- addField( propertyName );
- case macro -$i{propertyName}:
- Context.typeof( macro @:pos(obj.pos) $typedExpr.$propertyName );
- removeField( propertyName );
- case macro $i{propertyName}=>$a{subProperties}:
- var property = macro @:pos(obj.pos) $obj.$propertyName;
- var typedProperty = macro @:pos(obj.pos) $typedExpr.$propertyName;
- addField( propertyName );
- process( property, typedProperty, subProperties, blockExpressions );
- case _:
- Context.fatalError( 'Could not understand property name ${ Std.string( p ) }', Context.currentPos() );
- }
- }
- return blockExpressions;
- }
- static function process( expr:Expr, typedProp:Expr, properties:Array<Expr>, blockExpressions:Array<Expr> ):Array<Expr> {
- var exprType = Context.typeof( typedProp );
- var objectType = Context.typeof( macro new ftk.db.Object() );
- var iterableType = Context.typeof( macro { var it : Iterable<ftk.db.Object> = null; it; } );
- if ( Context.unify(exprType, objectType) ) {
- return processObject( expr, typedProp, properties, blockExpressions );
- }
- else if ( Context.unify(exprType,iterableType) ) {
- return processObjects( expr, typedProp, properties, blockExpressions );
- }
- else {
- Context.fatalError( '${ Std.string( expr ) } is not a ftk.db.Object nor Iterable of', Context.currentPos() );
- return null;
- }
- }
- #end
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement