<commit_before>package bindx;

#if macro

import bindx.Error;
import haxe.macro.Expr;
import haxe.macro.MacroStringTools;
import haxe.macro.Type;
import haxe.macro.Context;
import haxe.macro.Printer;

using Lambda;
using StringTools;
using haxe.macro.Tools;

typedef FieldExpr = {
    var field:ClassField;
    var bindable:Bool;
    var e:Expr;
    @:optional var params:Array<Expr>;
}

typedef Chain = {
    var init:Array<Expr>;
    var bind:Array<Expr>;
    var unbind:Array<Expr>;
    var expr:Expr;
    var zeroName:String;
}
#end

@:access(bindx.BindMacros)
class BindExt {
    
    @:noUsing macro static public function expr(expr:Expr, listener:Expr):Expr {
        return internalBindExpr(expr, listener);
    }
    
    @:noUsing macro static public function exprTo(expr:Expr, target:Expr):Expr {
        var type = Context.typeof(expr).toComplexType();
        return internalBindExpr(expr, macro function (_, to:Null<$type>) $target = to);
    }
    
    @:noUsing macro static public function chain(expr:Expr, listener:Expr):Expr {
        return internalBindChain(expr, listener);
    }
    
    @:noUsing macro static public function chainTo(expr:Expr, target:Expr):Expr {
        var type = Context.typeof(expr).toComplexType();
        return internalBindChain(expr, macro function (_, to:Null<$type>) $target = to);
    }
    
    #if macro
    
    public static function internalBindChain(expr:Expr, listener:Expr):Expr {
        var zeroListener = listenerName(0, "");
        var chain = null;
        try { chain = warnPrepareChain(expr, macro $i{ zeroListener }); } catch (e:bindx.Error) e.contextError();
        
        return macro (function ($zeroListener):Void->Void
            $b { chain.init.concat(chain.bind).concat([macro return function ():Void $b { chain.unbind }]) }
        )($listener);
    }
    
    public static function internalBindExpr(expr:Expr, listener:Expr):Expr {
        var type = Context.typeof(expr).toComplexType();
        var listenerNameExpr = macro listener;
        var fieldListenerName = "fieldListener";
        var fieldListenerNameExpr = macro $i{fieldListenerName};
        var methodListenerName = "methodListener";
        var methodListenerNameExpr = macro $i{methodListenerName};
        var chain:Chain = { init:[], bind:[], unbind:[], expr:expr, zeroName:null };
        var binded:Map<String, {prebind:Expr, c:Chain}> = new Map();
        
        var prefix = 0;
        function findChain(expr:Expr) {
            var isChain;
            
            if (MacroStringTools.isFormatExpr(expr)) {<commit_msg>generics in BindExt<commit_after>package bindx;

#if macro

import bindx.Error;
import haxe.macro.Expr;
import haxe.macro.MacroStringTools;
import haxe.macro.Type;
import haxe.macro.Context;
import haxe.macro.Printer;

using Lambda;
using StringTools;
using haxe.macro.Tools;

typedef FieldExpr = {
    var field:ClassField;
    var bindable:Bool;
    var e:Expr;
    @:optional var params:Array<Expr>;
}

typedef Chain = {
    var init:Array<Expr>;
    var bind:Array<Expr>;
    var unbind:Array<Expr>;
    var expr:Expr;
    var zeroName:String;
}
#end

@:access(bindx.BindMacros)
class BindExt {
    
    @:noUsing macro static public function expr<T>(expr:ExprOf<T>, listener:ExprOf<Null<T>->Null<T>->Void>):ExprOf<Void->Void> {
        return internalBindExpr(expr, listener);
    }
    
    @:noUsing macro static public function exprTo<T>(expr:ExprOf<T>, target:ExprOf<T>):ExprOf<Void->Void> {
        var type = Context.typeof(expr).toComplexType();
        return internalBindExpr(expr, macro function (_, to:Null<$type>) $target = to);
    }
    
    @:noUsing macro static public function chain<T>(expr:ExprOf<T>, listener:ExprOf<Null<T>->Null<T>->Void>):ExprOf<Void->Void> {
        return internalBindChain(expr, listener);
    }
    
    @:noUsing macro static public function chainTo<T>(expr:ExprOf<T>, target:ExprOf<T>):ExprOf<Void->Void> {
        var type = Context.typeof(expr).toComplexType();
        return internalBindChain(expr, macro function (_, to:Null<$type>) $target = to);
    }
    
    #if macro
    
    public static function internalBindChain(expr:Expr, listener:Expr):Expr {
        var zeroListener = listenerName(0, "");
        var chain = null;
        try { chain = warnPrepareChain(expr, macro $i{ zeroListener }); } catch (e:bindx.Error) e.contextError();
        
        return macro (function ($zeroListener):Void->Void
            $b { chain.init.concat(chain.bind).concat([macro return function ():Void $b { chain.unbind }]) }
        )($listener);
    }
    
    public static function internalBindExpr(expr:Expr, listener:Expr):Expr {
        var type = Context.typeof(expr).toComplexType();
        var listenerNameExpr = macro listener;
        var fieldListenerName = "fieldListener";
        var fieldListenerNameExpr = macro $i{fieldListenerName};
        var methodListenerName = "methodListener";
        var methodListenerNameExpr = macro $i{methodListenerName};
        var chain:Chain = { init:[], bind:[], unbind:[], expr:expr, zeroName:null };
        var binded:Map<String, {prebind:Expr, c:Chain}> = new Map();
        
        var prefix = 0;
        function findChain(expr:Expr) {
            var isChain;
            
            if (MacroStringTools.isFormatExpr(expr)) {
{'fraction_non_alphanumeric': 0.1258452291510143, 'fraction_numerical': 0.0007513148009015778, 'mean_word_length': 3.249800478850758, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '77097', 'n_tokens_mistral': 1636, 'n_tokens_neox': 1617, 'n_words': 372}