Skip to content

Instantly share code, notes, and snippets.

@skial
Last active October 3, 2017 14:47
Show Gist options
  • Save skial/de6df6afe924b47d3a3e to your computer and use it in GitHub Desktop.
Save skial/de6df6afe924b47d3a3e to your computer and use it in GitHub Desktop.
Code exercise while my internet was down for the safe navigation operator from AS3 started by this Haxe mailing list thread https://groups.google.com/forum/#!topic/haxelang/Rrj9AUbXGuA using Haxe 3.2.0 (git build development @ 3a255a8).
-main Main
-js test.js
--next
## You need nodejs installed for this to work.
-cmd node test.js
package ;
import haxe.macro.*;
import haxe.macro.Expr.ComplexType;
using haxe.macro.ExprTools;
/**
* ...
* @author Skial Bainn
*/
class Builder {
public static var localVars:Array<Expr> = [];
public static function build() {
var cls = Context.getLocalClass().get();
var fields = Context.getBuildFields();
for (field in fields) switch (field.kind) {
case FFun(m) if (m.expr != null):
m.expr.iter( process );
case _:
}
return fields;
}
public static function process(expr:Expr) {
switch (expr) {
case macro var $id:$type:
localVars.push( expr );
case macro var $id:$type = $e:
localVars.push( expr );
case { expr:EBinop(OpBoolOr, e1, e2), pos:p } :
for (ee in [e1, e2]) inspect( ee, findLastType( expr ) );
case _:
expr.iter( process );
}
}
public static function inspect(expr:Expr, ctype:ComplexType) {
switch (expr) {
case { expr:EBinop(OpBoolOr, _, _), pos:_ }:
expr.iter( inspect.bind(_, ctype) );
case { expr:EConst(CIdent(ident)), pos:p } :
for (i in 0...localVars.length) switch (localVars[i]) {
case { expr:EVars([v = { name:n, type:t, expr:e } ]), pos:_ } :
if (n == ident) {
if (t == null) {
t = ctype;
}
if (!Context.unify(ComplexTypeTools.toType(t), Context.getType('Bool'))) {
v.type = macro :Main.N<$t>;
}
}
case _:
}
case _:
}
}
public static function findLastType(expr:Expr) {
var result = null;
switch (expr) {
case { expr:EConst(c), pos:_ } :
result = switch(c) {
case CInt(_): macro:Int;
case CFloat(_): macro:Float;
case CString(_): macro:String;
case CRegexp(_, _): macro:EReg;
case CIdent(i):
null;
}
case _:
expr.iter( function(e) result = findLastType(e) );
}
return result;
}
}
package ;
/**
* ...
* @author Skial Bainn
*/
@:build( Builder.build() )
class Main {
public static function main() new Main();
public function new() {
var a = null;
var b = null;
trace( a || b || 'woot' );
}
}
abstract N<T>(T) from T to T {
public inline function new(v:T) this = v;
@:to public inline function toBool():Bool return this != null;
@:op(A || B)
public static inline function or<T>(a:N<T>, b:N<T>) {
return (a:N<T>) ? a : b;
}
}
(function () { "use strict";
var console = (1,eval)('this').console || {log:function(){}};
var Main = function() {
var a = null;
var b = null;
console.log((function($this) {
var $r;
var a1;
if(a != null) a1 = a; else a1 = b;
$r = a1 != null?a1:"woot";
return $r;
}(this)));
};
Main.main = function() {
new Main();
};
var _Main = {};
_Main.N_Impl_ = {};
_Main.N_Impl_._new = function(v) {
return v;
};
_Main.N_Impl_.toBool = function(this1) {
return this1 != null;
};
_Main.N_Impl_.or = function(a,b) {
if(a != null) return a; else return b;
};
Main.main();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment