Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asm.js type error: arguments to a comparison must both be signed, unsigned or doubles

I'm just learning the basics of asmjs, but I've got an error. I have no idea what did I wrong.

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

code:

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;
like image 746
don kaka Avatar asked Sep 08 '13 16:09

don kaka


1 Answers

There are a couple of different parts of the specification at play here. Let's work our way backwards from the error.

The error states: arguments to a comparison must both be signed, unsigned or doubles; int and int are given. Thus, the problem is with the following line of code:

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

If we look up the type semantics of the operator <, we get the following table:

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

This clearly reflects the wording of the error message; the < operator is only valid for comparisons between signed, unsigned, or double types. "But why?", you ask?

The description of the int type may give us a hint. Here's an excerpt:

The int type is the type of 32-bit integers where the signedness is not known. In asm.js, the type of a variable never has a known signedness. [...] However, this representation creates an overlap between signed and unsigned numbers that causes an ambiguity in determining which JavaScript number they represent. For example, the bit pattern 0xffffffff could represent 4294967295 or -1, depending on the signedness. For this reason, values of the int type are disallowed from escaping into external (non-asm.js) JavaScript code.

Thus, taking the comparison operation in isolation, ASM.js would have no way of knowing which of the two int values is less than the other, because it would not know the signedness of the integers.

So, why are the variables being resolved as type int?

Since you're declaring the variables inside of the function itself, we must refer to the following part of the spec:

The types of variable declarations are determined by their initializer. A variable initializer may be a floating-point literal, which is any numeric literal with the character . in their source, and has type double. Alternatively, an initializer may be an integer literal in the range [-231, 232), which has type int.

There we go. Since you're initializing the variables as var a=0, b=0;, that corresponds to the latter part of the spec, thus resolving to a type of int.


So how do we fix this? Well, we need a type cast to something that the < operator supports. The | operator can take two intish expressions, and return a signed, so that will suffice.

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

Note: The type diagram, together with the operator type rules are very useful when trying to debug type issues like this.

like image 167
voithos Avatar answered Oct 06 '22 01:10

voithos