【问题标题】:Is there anything like C++ static_assert for Haxe?有没有像 Haxe 的 C++ static_assert 之类的东西?
【发布时间】:2015-01-24 22:50:41
【问题描述】:

我想在 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 中进行编译时断言的最佳方法是什么?

下面我有一个宏,如果你只是将它传递给真/假(尽管我认为它应该不返回任何内容或 noop)。但我不确定如何使这项工作适用于“任何最终在编译时成为布尔值”的更一般情况。

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 { };
    }
}

【问题讨论】:

  • 你的宏和静态断言有什么关系?它会抛出一个错误,这将是运行时而不是编译时,对吧?
  • 不,这是编译时错误。
  • @Gama11 假设宏只在编译时进行评估,那么肯定也会发生抛出。
  • 嗯,有different kinds of macros。您的示例中的一个是表达式宏,但您可以从构建宏和初始化宏中调用 Context.fatalError() 来引发编译器错误。
  • 那个宏函数中的throw确实是编译时错误。要导致运行时抛出,它将是return macro throw ...

标签: haxe static-assert


【解决方案1】:

要评估Expr 并在编译时获取它的值,我们可以使用ExprTools.getValue。查看它的source,实际上它使用的技术类似于问题中发布的技术。

为了让它更加健壮,我们可以这样做 ExprTools.getValue(Context.getTypedExpr(Context.typeExpr(expr))) ,这样expr 中的所有内联变量甚至宏函数都将被解析。

要返回无操作,我们可以简单地return macro {};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多