Skip to content

Instantly share code, notes, and snippets.

@nadako
Created May 5, 2014
Embed
What would you like to do?
OptionalField abstract
typedef House =
{
?numTennants:OptionalField<Int>
}
class Main
{
static function main()
{
var house:House = {};
var numTennants = house.numTennants.or(0);
}
}
(function () { "use strict";
var Main = function() { };
Main.main = function() {
var house = { };
var numTennants;
if(Object.prototype.hasOwnProperty.call(house,"numTennants")) numTennants = house.numTennants; else numTennants = 0;
};
Main.main();
})();
import haxe.macro.Context;
import haxe.macro.Expr;
abstract OptionalField<T>(T) from T
{
@:extern
public inline function extract():T return this;
public macro function exists(ethis:Expr):ExprOf<Bool>
{
return makeCheckExpr(ethis);
}
public macro function or(ethis:Expr, defaultValue:ExprOf<T>):ExprOf<T>
{
var check = makeCheckExpr(ethis);
return macro $check ? $ethis.extract() : $defaultValue;
}
#if macro
static function makeCheckExpr(ethis:Expr):ExprOf<Bool>
{
var typed = Context.typeExpr(ethis);
switch (typed.expr)
{
case TField(e, FAnon(_.get() => f)) if (f.meta.has(":optional")):
var eobj = Context.getTypedExpr(e);
return macro Reflect.hasField($eobj, $v{f.name});
default:
throw new Error("OptionalField type is only usable for optional structure fields", ethis.pos);
}
}
#end
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment