From 1d4fd3b2a98e5c9380980c6c1ce101a71d496cee Mon Sep 17 00:00:00 2001 From: shmyga Date: Sun, 21 Apr 2019 15:29:43 +0300 Subject: [PATCH] [dispatcher] add dispatcher macro --- demo/src/demo/Demo.hx | 34 +++++++- demo/src/demo/dispatch/DemoDispatcher.hx | 14 ++++ src/main/haxework/macro/DispatcherMacro.hx | 90 ++++++++++++++++++++++ src/main/haxework/parser/Parser.hx | 7 +- 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 demo/src/demo/dispatch/DemoDispatcher.hx create mode 100644 src/main/haxework/macro/DispatcherMacro.hx diff --git a/demo/src/demo/Demo.hx b/demo/src/demo/Demo.hx index acdf82c..12b4617 100644 --- a/demo/src/demo/Demo.hx +++ b/demo/src/demo/Demo.hx @@ -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) { 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); + } + } diff --git a/demo/src/demo/dispatch/DemoDispatcher.hx b/demo/src/demo/dispatch/DemoDispatcher.hx new file mode 100644 index 0000000..f6cbb7f --- /dev/null +++ b/demo/src/demo/dispatch/DemoDispatcher.hx @@ -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() {} +} diff --git a/src/main/haxework/macro/DispatcherMacro.hx b/src/main/haxework/macro/DispatcherMacro.hx new file mode 100644 index 0000000..0a57d94 --- /dev/null +++ b/src/main/haxework/macro/DispatcherMacro.hx @@ -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; + + public function new(classType:ClassType, fields:Array) { + this.classType = classType; + this.fields = fields; + } + + public function apply():Array { + var result:Array = 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 = 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; + } +} diff --git a/src/main/haxework/parser/Parser.hx b/src/main/haxework/parser/Parser.hx index faecc09..71c6616 100644 --- a/src/main/haxework/parser/Parser.hx +++ b/src/main/haxework/parser/Parser.hx @@ -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; }