11

我只是在学习 asmjs 的基础知识,但我遇到了一个错误。我不知道我做错了什么。

TypeError: asm.js type error: arguments to a comparison must both be signed, unsigned or doubles; int and int are given

代码:

window.onload = (function(stdlib, foreign) {
    "use asm";

    var log = foreign.log;

    function main() {
        var a=0, b=0;

        a=10;
        b=20;

        if(a<b) {
            log(0.0);
        } else {
            log(1.0);
        }

        return;
    }

    return {main:main};
}(window, {log:console.log})).main;
4

2 回答 2

11

这里有几个不同的规范部分在起作用。让我们从错误中倒退。

错误状态:arguments to a comparison must both be signed, unsigned or doubles; int and int are given。因此,问题在于以下代码行:

    ...
    if(a < b) { // <- Here
        log(0.0);
    } else {
        log(1.0);
    }
    ...

如果我们查找operator 的类型语义<,我们会得到下表:

(signed, signed) → int ∧
(unsigned, unsigned) → int ∧
(double, double) → int

这清楚地反映了错误消息的措辞;该<运算符仅对有符号、无符号或双精度类型之间的比较有效。“但是为什么?”,你问?

类型描述int可能会给我们一个提示。这是一段摘录:

int 类型是符号未知的 32 位整数类型。在 asm.js 中,变量的类型从来没有已知的符号。[...] 但是,这种表示会在有符号和无符号数字之间产生重叠,从而导致在确定它们代表的 JavaScript 数字时产生歧义。例如,位模式 0xffffffff 可以表示 4294967295 或 -1,具体取决于符号。因此,不允许 int 类型的值转义到外部(非 asm.js)JavaScript 代码中。

因此,单独进行比较操作,ASM.js 将无法知道两个int值中的哪一个小于另一个,因为它不知道整数的符号。

那么,为什么变量被解析为 type int

由于您要在函数本身内部声明变量,因此我们必须参考规范的以下部分

变量声明的类型由它们的初始化器决定。变量初始值设定项可以是浮点文字,它是任何带有字符的数字文字。在他们的源代码中,并且类型为double。或者,初始值设定项可以是[-231, 232) 范围内的整数文字,其类型为int

我们去吧。由于您将变量初始化为var a=0, b=0;, 这对应于规范的后半部分,因此解析为int.


那么我们如何解决这个问题呢?好吧,我们需要一个类型转换为<运算符支持的东西。运算符可以采用|两个intish表达式,并返回 a signed,这样就足够了。

    if ((a|0) < (b|0)) {
        log(0.0);
    } else {
    ...

注意: 类型图以及运算符类型规则在尝试调试此类类型问题时非常有用。

于 2013-09-10T18:09:32.043 回答
3

正如错误消息所解释的,比较的参数必须是有符号的、无符号的或双精度的;这是RelationalExpression 验证运算符表所要求的。

但是,您的ab变量被分配了仅验证为的NumericLiterals ,编译器不知道它们是否已签名fixnum的类型。int

所以你需要用一个明确的表达式告诉它来验证它们的类型,它们要么是无符号的

if ( a>>>0 < b>>>0 )

或签名

if ( a|0 < b|0 ) // any of &, ^, <<, >> or ~~ should work
于 2013-09-10T18:04:04.717 回答