Description
nonut (unsigned) integer values are stored correctly (%u prints the right bits), but every binary-operation path in handle_binary_operation except OP_MOD evaluates the operands as signed int. Comparisons, division, +, -, and * therefore give wrong answers for any nonut rizz value whose high bit is set (i.e. > INT_MAX). The is_unsigned modifier never reaches these nodes, so the value is treated as a negative signed int.
This is distinct from the already-fixed #25 (which was specifically nonut modulo).
Minimal reproduction code
skibidi main {
nonut rizz a = 3000000000;
edgy (a > 5) {
yapping("big");
} amogus {
yapping("small");
}
bussin 0;
}
Also, division:
skibidi main {
nonut rizz a = 3000000000;
nonut rizz b = 2;
yapping("%u", a / b); // expect 1500000000
bussin 0;
}
Expected behavior
- Comparison:
3000000000 > 5 is true → prints big.
- Division:
3000000000 / 2 → 1500000000.
Actual behavior
$ ./brainrot cmp.brainrot
small
$ ./brainrot div.brainrot
3647483648
3000000000 reinterpreted as signed int is -1294967296 (negative, so < 5); -1294967296 / 2 = -647483648, which as unsigned prints 3647483648.
Brainrot version / commit
19b9563
Operating system
Ubuntu on WSL2 (Linux 5.15)
Additional context
Root cause: ast.c, handle_binary_operation. promoted_type is only ever VAR_SHORT/VAR_INT/VAR_FLOAT/VAR_DOUBLE, and the VAR_INT arms for OP_LT/GT/LE/GE/EQ/NE, OP_DIVIDE, OP_PLUS/MINUS/TIMES operate on signed int. Only OP_MOD consults node->modifiers.is_unsigned — and the in-code comment in the OP_DIVIDE arm already notes that is_unsigned "is never set on these nodes as things stand," so even that handling is effectively dead. The fix needs to first propagate is_unsigned onto binary-op nodes, then add unsigned branches (using unsigned int arithmetic) to each arm.
Description
nonut(unsigned) integer values are stored correctly (%uprints the right bits), but every binary-operation path inhandle_binary_operationexceptOP_MODevaluates the operands as signedint. Comparisons, division,+,-, and*therefore give wrong answers for anynonut rizzvalue whose high bit is set (i.e.> INT_MAX). Theis_unsignedmodifier never reaches these nodes, so the value is treated as a negative signed int.This is distinct from the already-fixed #25 (which was specifically
nonutmodulo).Minimal reproduction code
Also, division:
Expected behavior
3000000000 > 5is true → printsbig.3000000000 / 2→1500000000.Actual behavior
3000000000reinterpreted as signedintis-1294967296(negative, so< 5);-1294967296 / 2 = -647483648, which as unsigned prints3647483648.Brainrot version / commit
19b9563
Operating system
Ubuntu on WSL2 (Linux 5.15)
Additional context
Root cause:
ast.c,handle_binary_operation.promoted_typeis only everVAR_SHORT/VAR_INT/VAR_FLOAT/VAR_DOUBLE, and theVAR_INTarms forOP_LT/GT/LE/GE/EQ/NE,OP_DIVIDE,OP_PLUS/MINUS/TIMESoperate on signedint. OnlyOP_MODconsultsnode->modifiers.is_unsigned— and the in-code comment in theOP_DIVIDEarm already notes thatis_unsigned"is never set on these nodes as things stand," so even that handling is effectively dead. The fix needs to first propagateis_unsignedonto binary-op nodes, then add unsigned branches (usingunsigned intarithmetic) to each arm.