Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -3842,16 +3842,25 @@ static VarType get_native_call_static_type(ASTNode *node)
return stdrot_type_to_vartype(entry->return_type.type);
}

/* An int-typed operand's value widened for a float/double operation --
through unsigned int for a nonut rizz (#371), so 3000000000 + 0.5 is
3000000000.5 rather than the signed reinterpretation. */
/* Preserve the integer operand's width before widening (#372), and its
unsigned interpretation for a nonut rizz (#371). */
static double int_operand_as_double(ASTNode *expr)
{
if (expression_is_long(expr))
return (double)evaluate_expression_long(expr);
int value = evaluate_expression_int(expr);
return expression_is_unsigned(expr) ? (double)(unsigned int)value
: (double)value;
}

static float int_operand_as_float(ASTNode *expr)
{
/* int64 -> double -> float can round twice at a float halfway point. */
if (expression_is_long(expr))
return (float)evaluate_expression_long(expr);
return (float)int_operand_as_double(expr);
}

void *handle_binary_operation(ASTNode *node)
{
if (!node || node->type != NODE_OPERATION)
Expand Down Expand Up @@ -3908,11 +3917,11 @@ void *handle_binary_operation(ASTNode *node)
right_value = SAFE_MALLOC(float);
*(float *)left_value =
(left_type == VAR_INT)
? (float)int_operand_as_double(node->data.op.left)
? int_operand_as_float(node->data.op.left)
: evaluate_expression_float(node->data.op.left);
*(float *)right_value =
(right_type == VAR_INT)
? (float)int_operand_as_double(node->data.op.right)
? int_operand_as_float(node->data.op.right)
: evaluate_expression_float(node->data.op.right);
break;

Expand Down Expand Up @@ -5309,6 +5318,12 @@ float evaluate_expression_float(ASTNode *node)
if (!node)
return 0.0f;

/* Integer expressions must be evaluated at their own width before
conversion. The type guard keeps mixed floating operations floating;
expression_is_long() excludes pointers and does not evaluate operands. */
if (get_expression_type(node) == VAR_INT && expression_is_long(node))
return (float)evaluate_expression_long(node);

switch (node->type)
{
case NODE_ARRAY_ACCESS:
Expand Down Expand Up @@ -5462,6 +5477,10 @@ double evaluate_expression_double(ASTNode *node)
if (!node)
return 0.0L;

/* As above, do not read a giga/thicc through a 32-bit value slot. */
if (get_expression_type(node) == VAR_INT && expression_is_long(node))
return (double)evaluate_expression_long(node);

switch (node->type)
{
case NODE_ARRAY_ACCESS:
Expand Down
49 changes: 49 additions & 0 deletions test_cases/wide_integer_float.brainrot
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
skibidi main {
giga rizz a = 5000000000;
thicc rizz b = 0 - 5000000000;
gigachad d = a;
chad f = a;
yapping("%.0f %.0f", d, f);
d = b;
f = b;
yapping("%.0f %.0f", d, f);

gigachad two_d = 2.0;
chad two_f = 2.0;
yapping("%.0f %.0f", a * two_d, two_d * a);
yapping("%.0f %.0f", b * two_f, two_f * b);
yapping("%.1f %.1f", a + 0.5, 0.5 + b);
yapping("%.1f %.1f", a / two_d, two_d - b);
yapping("%d %d %d %d", a > two_d, two_d < a, b < two_f, two_f > b);

d = a + 3;
f = b * 2;
yapping("%.0f %.0f", d, f);
d = 5000000000;
f = 5000000000;
yapping("%.0f %.0f", d, f);
d = -a;
f = -b;
yapping("%.0f %.0f", d, f);

thicc rizz zero = 0;
thicc rizz edge = 2147483648;
thicc rizz high = 4294967296;
yapping("%.0f %.0f %.0f", zero + two_d, edge + two_d, high + two_d);
thicc rizz minimum = 0 - 9223372036854775807 - 1;
d = minimum;
f = minimum;
yapping("%.0f %.0f", d, f);

🚽 Above a float halfway point: converting via double would round twice.
thicc rizz halfway = 4611686293305294849;
chad zero_f = 0.0;
f = halfway;
yapping("%.0f %.0f %.0f", f, halfway + zero_f, zero_f + halfway);

🚽 Retain the existing unsigned-32 conversion and mixed-fraction paths.
nonut rizz u = 3000000000;
yapping("%.1f %.1f", u + 0.5, 0.5 + u);
yapping("%.1f", (a + 0.5) + two_d);
bussin 0;
}
34 changes: 34 additions & 0 deletions test_cases/wide_integer_float_loads.brainrot
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
rizz next_factor(rizz *calls) {
*calls = *calls + 1;
bussin 2;
}

skibidi main {
rizz calls = 0;
thicc rizz values[2] = {5000000000, 6000000000};
thicc rizz *p = &values[0];
gigachad d = values[0];
chad f = values[1];
yapping("%.0f %.0f", d, f);
d = *p;
f = *(p + 1);
yapping("%.0f %.0f", d, f);

🚽 Integer expressions must be evaluated once, including their effects.
d = values[0] * next_factor(&calls);
f = next_factor(&calls) * values[0];
yapping("%.0f %.0f %d", d, f, calls);
d = (values[0] + next_factor(&calls)) + 0.5;
chad half = 0.5;
f = half * (values[0] * next_factor(&calls));
yapping("%.1f %.0f %d", d, f, calls);
rizz index = 0;
d = values[index++];
f = values[index++];
yapping("%.0f %.0f %d", d, f, index);
thicc rizz value = 5000000000;
d = value++;
gigachad after = ++value;
yapping("%.0f %.0f %lld", d, after, value);
bussin 0;
}
4 changes: 3 additions & 1 deletion tests/expected_results.json
Original file line number Diff line number Diff line change
Expand Up @@ -469,5 +469,7 @@
"array_decay_const_fail": "Error: Cannot modify const variable at line 37\nError: Cannot modify const variable at line 36\nError: Cannot modify const variable at line 35\nError: Cannot modify const variable at line 34\nError: Cannot modify const variable at line 33\nError: Cannot modify const variable at line 32\nError: Cannot modify const variable at line 31\nError: Cannot modify const variable at line 30\nError: Cannot modify const variable at line 29",
"pointer_width_consistency": "giga index: 20 30\ngiga arith: 20 30\nthicc index: 7000000000 5000000000 6000000000\nthicc arith: 7000000000 5000000000 6000000000\nthicc element: 8000000000\nthicc scalar: 9000000000",
"array_decay_local_return_fail": "Error: 'local_struct_field' returns an address inside local variable 'b', which is freed when the function returns -- make it `salty` (static), or have the caller pass the array in at line 31\nError: 'local_array_plus' returns an address inside local variable 'xs', which is freed when the function returns -- make it `salty` (static), or have the caller pass the array in at line 26\nError: 'local_array' returns an address inside local variable 'xs', which is freed when the function returns -- make it `salty` (static), or have the caller pass the array in at line 21",
"native_ptr_user_pointer_param": "inline: 41\nstored: 42"
"native_ptr_user_pointer_param": "inline: 41\nstored: 42",
"wide_integer_float": "5000000000 5000000000\n-5000000000 -5000000000\n10000000000 10000000000\n-10000000000 -10000000000\n5000000000.5 -4999999999.5\n2500000000.0 5000000002.0\n1 1 1 1\n5000000003 -10000000000\n5000000000 5000000000\n-5000000000 5000000000\n2 2147483650 4294967298\n-9223372036854775808 -9223372036854775808\n4611686568183201792 4611686568183201792 4611686568183201792\n3000000000.5 3000000000.5\n5000000002.5",
"wide_integer_float_loads": "5000000000 6000000000\n5000000000 6000000000\n10000000000 10000000000 2\n5000000002.5 5000000000 4\n5000000000 6000000000 2\n5000000000 5000000002 5000000002"
}
Loading