<commit_before>package tink.reactive.signals.macros;

import haxe.macro.Expr;

using tink.macro.tools.MacroTools;
using tink.core.types.Outcome;

class SignalSugar {
	static var WHEN_NAMED = macro @when(NAME__data = EXPR__target) EXPR__handle;
	static var WHEN = macro @when(EXPR__target) EXPR__handle;
	static var WITH = macro @with(EXPR__target) EXPR__statements;
	static var ON = macro @on(EXPR__signal) EXPR__handle;
	
	static function getFuture(target:Expr, handle:Expr, ?name, ?pos) {
		if (name == null) 
			name = 'result';
		/*var t = (macro {
			var tmp = null;
			$target(function (d) tmp = d);
			tmp;
		}).finalize().typeof().sure().toComplex();*/
		return target.call(
			[handle.func([name.toArg()], false).asExpr(null, pos)],
			pos
		);
	}
	static function registerHandler(handle:Expr, signal:Expr) {
		signal = signal.withPrivateAccess();
		var t = signal.pos.makeBlankType();
		var ret =  
			if (signal.is(macro : tink.reactive.signals.Signal<$t>)) {
				var name = 'data';
				var t = (macro {
					var tmp = null;
					${signal}.on(function (d) tmp = d);
					tmp;
				}).finalize().typeof().sure().toComplex();
				switch (signal.typeof().sure()) {
					case TType(ref, params):
						if (ref.toString() == 'tink.reactive.signals.Named')
							name = params[0].getID().substr(1);
					default:
				}
				var func = handle.func([name.toArg(t)], false).asExpr();
				(macro $signal.on($func));
			}
			else macro $signal.on(function () $handle);
		return ret.finalize();
	}
	static public function on(e:Expr) 
		return
			switch (e.match(ON)) {
				case Success(match):
					match.exprs.signal.outerTransform(registerHandler.bind(match.exprs.handle));
				default: e;
			}	
			
	static public function with(e:Expr) 
		return
			switch (e.match(WITH)) {
				case Success(match):
					var target = match.exprs.target,
						statements = 
							switch (match.exprs.statements) {
								case { expr: EBlock(exprs) }: exprs;
								case e: [e]; 
							}
					for (s in statements) 						
						switch (s.match(ON)) {
							case Success(match):
								var signal = match.exprs.signal;
								switch (signal.expr) {
									case EConst(CIdent(name)): 
										signal.expr = 'tmp'.resolve().field(name).expr;
									case ECall({ expr: EConst(CIdent(name)) }, params):
										signal.expr = 'tmp'.resolve().field(name).call(params).expr;
									default:
								}
							default:
						}
					statements.unshift('tmp'.define(target, target.pos));
					statements.push('tmp'.resolve(target.pos));
					return statements.toBlock().finalize(e.pos);
				default: e;
			}		
	
	
	static public function when(e:Expr) {
		for (pattern in [WHEN_NAMED, WHEN])
			switch (e.match(pattern)) {
				case Success(match):
					return getFuture(match.exprs.target, match.exprs.handle, match.names.data, e.pos);
				default:
			}
		switch (e.expr) {
			//case EMeta( { name: 'when', params: [] }, { expr: ESwitch(over, cases, edef) } ):
			case ESwitch({ expr: EMeta( { name: 'when', params: [] }, over)}, cases, edef):
				var arg = String.tempName();
				return getFuture(
					over, 
					ESwitch(arg.resolve(over.pos), cases, edef).at(e.pos), 
					arg, 
					e.pos
				);
			default:
		}
		return e;
	}
	
}<commit_msg>Got rid of @when - sugar.<commit_after>package tink.reactive.signals.macros;

import haxe.macro.Expr;

using tink.macro.tools.MacroTools;
using tink.core.types.Outcome;

class SignalSugar {
	static var WITH = macro @with(EXPR__target) EXPR__statements;
	static var ON = macro @on(EXPR__signal) EXPR__handle;
	
	static function getFuture(target:Expr, handle:Expr, ?name, ?pos) {
		if (name == null) 
			name = 'result';
		/*var t = (macro {
			var tmp = null;
			$target(function (d) tmp = d);
			tmp;
		}).finalize().typeof().sure().toComplex();*/
		return target.call(
			[handle.func([name.toArg()], false).asExpr(null, pos)],
			pos
		);
	}
	static function registerHandler(handle:Expr, signal:Expr) {
		signal = signal.withPrivateAccess();
		var t = signal.pos.makeBlankType();
		var ret =  
			if (signal.is(macro : tink.reactive.signals.Signal<$t>)) {
				var name = 'data';
				var t = (macro {
					var tmp = null;
					${signal}.on(function (d) tmp = d);
					tmp;
				}).finalize().typeof().sure().toComplex();
				switch (signal.typeof().sure()) {
					case TType(ref, params):
						if (ref.toString() == 'tink.reactive.signals.Named')
							name = params[0].getID().substr(1);
					default:
				}
				var func = handle.func([name.toArg(t)], false).asExpr();
				(macro $signal.on($func));
			}
			else macro $signal.on(function () $handle);
		return ret.finalize();
	}
	static public function on(e:Expr) 
		return
			switch (e.match(ON)) {
				case Success(match):
					match.exprs.signal.outerTransform(registerHandler.bind(match.exprs.handle));
				default: e;
			}	
			
	static public function with(e:Expr) 
		return
			switch (e.match(WITH)) {
				case Success(match):
					var target = match.exprs.target,
						statements = 
							switch (match.exprs.statements) {
								case { expr: EBlock(exprs) }: exprs;
								case e: [e]; 
							}
					for (s in statements) 						
						switch (s.match(ON)) {
							case Success(match):
								var signal = match.exprs.signal;
								switch (signal.expr) {
									case EConst(CIdent(name)): 
										signal.expr = 'tmp'.resolve().field(name).expr;
									case ECall({ expr: EConst(CIdent(name)) }, params):
										signal.expr = 'tmp'.resolve().field(name).call(params).expr;
									default:
								}
							default:
						}
					statements.unshift('tmp'.define(target, target.pos));
					statements.push('tmp'.resolve(target.pos));
					return statements.toBlock().finalize(e.pos);
				default: e;
			}			
	
}
{'fraction_non_alphanumeric': 0.16023064826140138, 'fraction_numerical': 0.0006989341254586755, 'mean_word_length': 2.8728010825439783, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '5443570', 'n_tokens_mistral': 2530, 'n_tokens_neox': 1925, 'n_words': 411}