Haxe 有类似 C++ static_assert 的东西吗?
Is there anything like C++ static_assert for Haxe?
我想在 Haxe 中做编译时断言。做这样的事情会很好:
static inline var important_number = 42;
public function f():Void {
static_assert(important_number > 64, "important number is too small for this implementation!");
}
我的问题是:Haxe 宏是正确的路线吗,否则在 Haxe 中进行编译时断言的最佳方法是什么?
下面我有一个宏,只要你传递它就可以解决这个问题 true/false(尽管我认为它应该什么都不返回或没有返回)。但我不确定如何使这项工作适用于 "anything that eventually becomes a boolean at compile-time".
的更一般情况
class Assert {
/* Static assert */
macro static public function s(e:Expr, errorString:String):Expr {
switch(e.expr) {
case EConst(c):
switch(c) {
case CIdent("true"):
return e;
case CIdent("false"):
throw new Error(errorString, e.pos);
default:
throw new Error("I only accept true/false right now", e.pos);
}
default:
throw new Error("I only accept true/false right now", e.pos);
}
}
}
Assert.s(false, "yep, it's a compile time error");
Assert.s(true, "business as usual");
Assert.s(6 == 9, "i don't seem to work yet");
更新 1:
有#error 可用于一些简单的情况,例如:
#if ios
trace("it just works!");
#else
#error("you didn't implement this yet!");
#end
解决方案:
所以这就是我现在使用的,可能有一些注意事项,但它似乎适用于简单的静态断言:
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;
class Assert {
/* Static assert */
macro static public function s(expr:Expr, ?error:String):Expr {
if (error == null) {
error = "";
}
if (expr == null) {
throw new Error("Expression must be non-null", expr.pos);
}
var value = ExprTools.getValue(Context.getTypedExpr(Context.typeExpr(expr)));
if (value == null) {
throw new Error("Expression value is null", expr.pos);
}
else if (value != true && value != false) {
throw new Error("Expression does not evaluate to a boolean value", expr.pos);
}
else if(value == false) {
throw new Error("Assertion failure: " + ExprTools.toString(expr) + " " + "[ " + error + " ]", expr.pos);
}
return macro { };
}
}
要评估一个 Expr
并在编译时获取它的值,我们可以使用 ExprTools.getValue. Looking at its source,它实际上使用了一种类似于问题中发布的技术。
为了让它更健壮,我们可以做 ExprTools.getValue(Context.getTypedExpr(Context.typeExpr(expr)))
,这样 expr
中的所有内联变量甚至宏函数都将被解析。
为了返回一个空操作,我们可以简单地return macro {};
。
我想在 Haxe 中做编译时断言。做这样的事情会很好:
static inline var important_number = 42;
public function f():Void {
static_assert(important_number > 64, "important number is too small for this implementation!");
}
我的问题是:Haxe 宏是正确的路线吗,否则在 Haxe 中进行编译时断言的最佳方法是什么?
下面我有一个宏,只要你传递它就可以解决这个问题 true/false(尽管我认为它应该什么都不返回或没有返回)。但我不确定如何使这项工作适用于 "anything that eventually becomes a boolean at compile-time".
的更一般情况class Assert {
/* Static assert */
macro static public function s(e:Expr, errorString:String):Expr {
switch(e.expr) {
case EConst(c):
switch(c) {
case CIdent("true"):
return e;
case CIdent("false"):
throw new Error(errorString, e.pos);
default:
throw new Error("I only accept true/false right now", e.pos);
}
default:
throw new Error("I only accept true/false right now", e.pos);
}
}
}
Assert.s(false, "yep, it's a compile time error");
Assert.s(true, "business as usual");
Assert.s(6 == 9, "i don't seem to work yet");
更新 1:
有#error 可用于一些简单的情况,例如:
#if ios
trace("it just works!");
#else
#error("you didn't implement this yet!");
#end
解决方案:
所以这就是我现在使用的,可能有一些注意事项,但它似乎适用于简单的静态断言:
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;
class Assert {
/* Static assert */
macro static public function s(expr:Expr, ?error:String):Expr {
if (error == null) {
error = "";
}
if (expr == null) {
throw new Error("Expression must be non-null", expr.pos);
}
var value = ExprTools.getValue(Context.getTypedExpr(Context.typeExpr(expr)));
if (value == null) {
throw new Error("Expression value is null", expr.pos);
}
else if (value != true && value != false) {
throw new Error("Expression does not evaluate to a boolean value", expr.pos);
}
else if(value == false) {
throw new Error("Assertion failure: " + ExprTools.toString(expr) + " " + "[ " + error + " ]", expr.pos);
}
return macro { };
}
}
要评估一个 Expr
并在编译时获取它的值,我们可以使用 ExprTools.getValue. Looking at its source,它实际上使用了一种类似于问题中发布的技术。
为了让它更健壮,我们可以做 ExprTools.getValue(Context.getTypedExpr(Context.typeExpr(expr)))
,这样 expr
中的所有内联变量甚至宏函数都将被解析。
为了返回一个空操作,我们可以简单地return macro {};
。