Author: jonathan
Date: Thu Aug  7 07:50:04 2008
New Revision: 30092

Modified:
   trunk/languages/perl6/src/builtins/op.pir

Log:
[rakudo] Make various arithmetic operations return an Int when they are 
performed on Ints. However, to get the right semantics, we must also add some 
logic to do upgrades when needed, which is also in this patch. Resolves 
RT#56944 and RT##56748.

Modified: trunk/languages/perl6/src/builtins/op.pir
==============================================================================
--- trunk/languages/perl6/src/builtins/op.pir   (original)
+++ trunk/languages/perl6/src/builtins/op.pir   Thu Aug  7 07:50:04 2008
@@ -12,6 +12,21 @@
 
 .namespace []
 
+## This is used by integer computations, to upgrade the answer and return a
+## Num if we overflow. We may want to return something like a BigInt in the
+## future, but we don't have that yet and this gives something closer to the
+## correct semantics than not upgrading an Int at all.
+.sub '!upgrade_to_num_if_needed'
+    .param num test
+    if test > 2147483647.0 goto upgrade
+    if test < -2147483648.0 goto upgrade
+    $I0 = test
+    .return ($I0)
+  upgrade:
+    .return (test)
+.end
+
+
 ## autoincrement
 .sub 'postfix:++' :multi(_)
     .param pmc a
@@ -51,6 +66,14 @@
 .end
 
 
+.sub 'infix:**' :multi(Integer,Integer)
+    .param num base
+    .param num exp
+    $N0 = pow base, exp
+    .return '!upgrade_to_num_if_needed'($N0)
+.end
+
+
 ## symbolic unary
 .sub 'prefix:!' :multi(_)
     .param pmc a
@@ -124,6 +147,14 @@
 .end
 
 
+.sub 'infix:*' :multi(Integer,Integer)
+    .param num a
+    .param num b
+    $N0 = a * b
+    .return '!upgrade_to_num_if_needed'($N0)
+.end
+
+
 .sub 'infix:/' :multi(_,_)
     .param num a
     .param num b
@@ -132,6 +163,19 @@
 .end
 
 
+.sub 'infix:/' :multi(Integer,Integer)
+    .param num a
+    .param num b
+    $N0 = a / b
+    $I0 = floor $N0
+    $N1 = $N0 - $I0
+    if $N1 != 0 goto upgrade
+    .return '!upgrade_to_num_if_needed'($N0)
+  upgrade:
+    .return ($N0)
+.end
+
+
 .sub 'infix:%' :multi(_,_)
     .param num a
     .param num b
@@ -140,6 +184,14 @@
 .end
 
 
+.sub 'infix:%' :multi(Integer,Integer)
+    .param num a
+    .param num b
+    $N0 = mod a, b
+    .return '!upgrade_to_num_if_needed'($N0)
+.end
+
+
 .sub 'infix:x' :multi(_,_)
     .param string str
     .param int count
@@ -211,6 +263,14 @@
 .end
 
 
+.sub 'infix:+' :multi(Integer,Integer)
+    .param num a
+    .param num b
+    $N0 = a + b
+    .return '!upgrade_to_num_if_needed'($N0)
+.end
+
+
 .sub 'infix:-' :multi(_,_)
     .param num a
     .param num b
@@ -219,6 +279,14 @@
 .end
 
 
+.sub 'infix:-' :multi(Integer,Integer)
+    .param num a
+    .param num b
+    $N0 = a - b
+    .return '!upgrade_to_num_if_needed'($N0)
+.end
+
+
 .sub 'infix:~' :multi(_,_)
     .param string a
     .param string b

Reply via email to