Last active
June 21, 2016 21:33
-
-
Save nadako/561112bfdd7f5714e88412852aab70a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// register a build-macro that will be called | |
// for building fields for subclasses of this class | |
@:autoBuild(ComponentMacro.build()) | |
class Component { | |
// this function will be overriden in subclasses | |
public function registerCallbacks(updates:Array<Void->Void>) {} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import haxe.macro.Context; | |
import haxe.macro.Expr; | |
class ComponentMacro { | |
// this is a build macro function that returns an array | |
// of fields for the class being built | |
static function build():Array<Field> { | |
// get all the fields that are already there (e.g. defined by syntax in the source file) | |
var fields = Context.getBuildFields(); | |
// this is an array of expressions for the registerCallbacks function body | |
var registerExprs = new Array<Expr>(); | |
// iterate over defined fields to find the update function | |
for (field in fields) { | |
// this is an update function if it contains metadata named "update" | |
var isUpdateFunction = Lambda.exists(field.meta, function(m) return m.name == "update"); | |
// if it is - generate an expression that adds this method to the updates array | |
// and push this expression to the array of register function expressions | |
if (isUpdateFunction) { | |
var fieldName = field.name; | |
registerExprs.push(macro updates.push(this.$fieldName)); | |
} | |
} | |
// if we did found a function to register, add override of the registerCallbacks method | |
// to this class' fields | |
if (registerExprs.length > 0) { | |
fields.push({ | |
pos: Context.currentPos(), // whatever current position is, we don't really care | |
name: "registerCallbacks", // the function we're overriding is named like this, | |
access: [APublic, AOverride], // access specifiers: public override | |
kind: FFun({ // this is a function (not var or property) | |
args: [ | |
{ | |
name: "updates", // the function has one argument "updates" | |
type: macro : Array<Void->Void> // typed as Array<Void->Void>, just like in superclass | |
} | |
], | |
ret: null, // we don't care about return type (it will be inferred as Void anyway) | |
expr: macro $b{registerExprs} // the function body is a block of expressions we collected in registerExprs | |
}) | |
}); | |
} | |
// finally return the fields of our subclass | |
return fields; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyComponent extends Component { | |
public function new() {} | |
@update | |
function myCoolUpdate() { | |
trace("hello"); | |
} | |
} | |
class Main { | |
static function main() { | |
var updates = []; | |
var myComp = new MyComponent(); | |
myComp.registerCallbacks(updates); | |
for (update in updates) | |
update(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by Haxe 3.3.0 | |
(function () { "use strict"; | |
function $extend(from, fields) { | |
function Inherit() {} Inherit.prototype = from; var proto = new Inherit(); | |
for (var name in fields) proto[name] = fields[name]; | |
if( fields.toString !== Object.prototype.toString ) proto.toString = fields.toString; | |
return proto; | |
} | |
var Component = function() { }; | |
Component.prototype = { | |
registerCallbacks: function(updates) { | |
} | |
}; | |
var MyComponent = function() { | |
}; | |
MyComponent.__super__ = Component; | |
MyComponent.prototype = $extend(Component.prototype,{ | |
myCoolUpdate: function() { | |
console.log("hello"); | |
} | |
,registerCallbacks: function(updates) { | |
updates.push($bind(this,this.myCoolUpdate)); | |
} | |
}); | |
var Main = function() { }; | |
Main.main = function() { | |
var updates = []; | |
new MyComponent().registerCallbacks(updates); | |
var _g = 0; | |
while(_g < updates.length) { | |
var update = updates[_g]; | |
++_g; | |
update(); | |
} | |
}; | |
var $_, $fid = 0; | |
function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $fid++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; } | |
MyComponent.__meta__ = { fields : { myCoolUpdate : { update : null}}}; | |
Main.main(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment