Skip to content

Instantly share code, notes, and snippets.

@romamik
Created February 15, 2017 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romamik/21d85e02ef7286df9a6f8ad1ed81eec7 to your computer and use it in GitHub Desktop.
Save romamik/21d85e02ef7286df9a6f8ad1ed81eec7 to your computer and use it in GitHub Desktop.
haxe null safety example
package;
import haxe.macro.Expr;
class Bar {
public var foo:Foo = null;
public function new() {}
}
class Foo {
public function new() {}
public var bar:Bar = new Bar();
public var mayBar:May<Bar> = null;
}
#if display @:forward #end // for ide completition
abstract May<T>(Null<T>) from(Null<T>) {
public inline function isSome():Bool return !isNull();
public inline function isNull():Bool return this == null;
public inline function unwrap(?pos:haxe.PosInfos):Null<T> return isNull() ? throw 'unwrap null $pos' : _unwrap();
public inline function _unwrap():Null<T> return this; // unsafe
@:op(a.b) static macro function resolve<T>(ethis:ExprOf<May<T>>, field:String) {
function setPos(pos:Position, expr:Expr) {
expr.pos = pos;
haxe.macro.ExprTools.iter(expr, function(e) setPos(pos, e));
return expr;
}
return setPos(haxe.macro.Context.currentPos(), macro {
var me = $ethis;
@:privateAccess May.fromMayOrNull(!me.isNull() ? me._unwrap().$field : null);
});
}
static inline function fromMayOrNull<T>(t:May<T>):May<T> return t; // used for type inference: T, May<T> or Null<T> ==> May<T>, to avoid May<May<T>>
}
class Main {
static function main() {
var may:May<Foo> = new Foo();
var t = may.bar.foo.bar.foo.bar;
$type(t);
trace(t);
trace(may.bar);
trace(may.mayBar);
may = null;
trace(may.bar);
trace(may.mayBar);
$type(may.bar.foo);
$type(may.mayBar);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment