[dispatcher] add dispatcher macro

This commit is contained in:
2019-04-21 15:29:43 +03:00
parent 7c879ee159
commit 1d4fd3b2a9
4 changed files with 142 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
package demo;
import demo.dispatch.DemoDispatcher;
import haxework.net.JsonLoader;
import demo.popup.ColorPopup;
import haxework.App;
@@ -30,16 +31,28 @@ import haxework.log.TraceLogger;
}
}
class Demo extends App {
class Demo extends App implements DemoListener {
public static function main() {
L.push(new TraceLogger());
var app = new App();
var app = new Demo();
app.resources.image.put("logo", HaxeLogo.resolve());
Theme.setColor(0x33aa33);
app.start(new DemoView());
var dispatcher = new DemoDispatcher();
dispatcher.connect(app);
dispatcher.test1Change.emit();
dispatcher.test2Change.emit(1);
dispatcher.test3Change.emit(1, "test");
dispatcher.test4Change.emit(app);
dispatcher.disconnect(app);
dispatcher.test1Change.emit();
dispatcher.test2Change.emit(1);
dispatcher.test3Change.emit(1, "test");
dispatcher.test4Change.emit(app);
new JsonLoader().GET("http://umix.tv/channel/data2/renova.json")
.then(function(data:Array<Model>) {
app.resources.any.put("data", data);
@@ -47,4 +60,21 @@ class Demo extends App {
})
.catchError(function(error) trace(error));
}
public function test1():Void {
trace('test1');
}
public function test2(a:Int):Void {
trace('test2', a);
}
public function test3(a:Int, b:String):Void {
trace('test3', a, b);
}
public function test4(app: App):Void {
trace('test4', app);
}
}

View File

@@ -0,0 +1,14 @@
package demo.dispatch;
import haxework.App;
interface DemoListener {
public function test1():Void;
public function test2(a:Int):Void;
public function test3(a:Int, b:String):Void;
public function test4(app:App):Void;
}
@:dispatcher(DemoListener) class DemoDispatcher {
public function new() {}
}

View File

@@ -0,0 +1,90 @@
package haxework.macro;
import haxe.macro.TypeTools;
import haxe.macro.Context;
import haxe.macro.ExprTools;
import haxe.macro.Expr;
import haxe.macro.Type;
class DispatcherMacro {
private static inline var metaName:String = ':dispatcher';
public static function has(classType:ClassType):Bool {
return classType.meta.has(metaName);
}
private var classType:ClassType;
private var fields:Array<Field>;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
}
public function apply():Array<Field> {
var result:Array<Field> = fields.slice(0);
var typeName = ExprTools.toString(classType.meta.extract(metaName)[0].params[0]);
var type:ClassType = switch Context.getType(typeName) {
case TInst(t, _): t.get();
case _: null;
}
var fields = type.fields.get();
for (field in fields) {
var argsTypes:Array<Type> = switch field.type {
case TFun(args, _): args.map(function(arg) return arg.t);
case _ : [];
}
var signal = 'Signal${argsTypes.length}';
var type = TPath({
pack: ['haxework', 'signal'],
name: 'Signal',
sub: signal,
params: argsTypes.map(function(t) return TPType(TypeTools.toComplexType(t))),
});
result.push({
name: '${field.name}Change',
access: [APublic],
pos: Context.currentPos(),
kind: FProp('default', 'null', type, Context.parse('new haxework.signal.Signal.${signal}()', Context.currentPos())),
});
}
result.push({
name: 'connect',
access: [APublic],
pos: Context.currentPos(),
kind: FFun({
args: [{
name: 'listener',
type: TPath({
pack: type.pack,
name: type.name,
}),
}],
ret: null,
expr: macro $b{fields.map(function(field) {
return Context.parse('${field.name}Change.connect(listener.${field.name})', Context.currentPos());
})},
}),
});
result.push({
name: 'disconnect',
access: [APublic],
pos: Context.currentPos(),
kind: FFun({
args: [{
name: 'listener',
type: TPath({
pack: type.pack,
name: type.name,
}),
}],
ret: null,
expr: macro $b{fields.map(function(field) {
return Context.parse('${field.name}Change.disconnect(listener.${field.name})', Context.currentPos());
})},
}),
});
return result;
}
}

View File

@@ -3,11 +3,11 @@ package haxework.parser;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxework.macro.DispatcherMacro;
import haxework.macro.ProvideMacro;
import haxework.macro.ResourceMacro;
import haxework.macro.TemplateMacro;
class Parser {
private static function auto():Void {
@@ -46,6 +46,11 @@ class Parser {
var template = new TemplateMacro(ct, fields);
fields = template.apply();
}
if (DispatcherMacro.has(ct)) {
modify = true;
var dispatcher = new DispatcherMacro(ct, fields);
fields = dispatcher.apply();
}
return modify ? fields : null;
default: return null;
}