changeset 1619:15e0c935c91b

Catching integer divisions by zero
author Adam Chlipala <adam@chlipala.net>
date Sat, 03 Dec 2011 09:44:07 -0500
parents 705cb41ac7d0
children 43f22a8f76cc
files lib/js/urweb.js src/cjr_print.sml src/jscomp.sml src/monoize.sml tests/div.ur
diffstat 5 files changed, 88 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/lib/js/urweb.js	Wed Nov 30 15:28:56 2011 -0500
+++ b/lib/js/urweb.js	Sat Dec 03 09:44:07 2011 -0500
@@ -19,9 +19,9 @@
 function minus(x, y) { return x - y; }
 function times(x, y) { return x * y; }
 function div(x, y) { return x / y; }
-function divInt(x, y) { var n = x / y; return n < 0 ? Math.ceil(n) : Math.floor(n); }
+function divInt(x, y) { if (y == 0) er("Division by zero"); var n = x / y; return n < 0 ? Math.ceil(n) : Math.floor(n); }
 function mod(x, y) { return x % y; }
-function modInt(x, y) { var n = x % y; return n < 0 ? Math.ceil(n) : Math.floor(n); }
+function modInt(x, y) { if (y == 0) er("Division by zero"); var n = x % y; return n < 0 ? Math.ceil(n) : Math.floor(n); }
 function lt(x, y) { return x < y; }
 function le(x, y) { return x <= y; }
 
--- a/src/cjr_print.sml	Wed Nov 30 15:28:56 2011 -0500
+++ b/src/cjr_print.sml	Sat Dec 03 09:44:07 2011 -0500
@@ -1655,7 +1655,7 @@
                           p_exp' true false env e1])
 
       | EBinop (s, e1, e2) =>
-        if Char.isAlpha (String.sub (s, size s - 1)) then
+        if s <> "fdiv" andalso Char.isAlpha (String.sub (s, size s - 1)) then
             box [string s,
                  string "(",
                  p_exp' false false env e1,
@@ -1663,10 +1663,48 @@
                  space,
                  p_exp' false false env e2,
                  string ")"]
+        else if s = "/" orelse s = "%" then
+            box [string "({",
+                 newline,
+                 string "uw_Basis_int",
+                 space,
+                 string "dividend",
+                 space,
+                 string "=",
+                 space,
+                 p_exp env e1,
+                 string ",",
+                 space,
+                 string "divisor",
+                 space,
+                 string "=",
+                 space,
+                 p_exp env e2,
+                 string ";",
+                 newline,
+                 string "if",
+                 space,
+                 string "(divisor",
+                 space,
+                 string "==",
+                 space,
+                 string "0)",
+                 newline,
+                 box [string "uw_error(ctx, FATAL, \"",
+                      string (ErrorMsg.spanToString loc),
+                      string ": division by zero\");",
+                      newline],
+                 string "dividend",
+                 space,
+                 string s,
+                 space,
+                 string "divisor;",
+                 newline,
+                 string "})"]
         else
             parenIf par (box [p_exp' true false env e1,
                               space,
-                              string s,
+                              string (if s = "fdiv" then "/" else s),
                               space,
                               p_exp' true false env e2])
 
--- a/src/jscomp.sml	Wed Nov 30 15:28:56 2011 -0500
+++ b/src/jscomp.sml	Sat Dec 03 09:44:07 2011 -0500
@@ -706,6 +706,8 @@
                                              | "*" => "times"
                                              | "/" => (case bi of Int => "divInt" | NotInt => "div")
                                              | "%" => (case bi of Int => "modInt" | NotInt => "mod")
+                                             | "fdiv" => "div"
+                                             | "fmod" => "mod"
                                              | "<" => "lt"
                                              | "<=" => "le"
                                              | "strcmp" => "strcmp"
--- a/src/monoize.sml	Wed Nov 30 15:28:56 2011 -0500
+++ b/src/monoize.sml	Sat Dec 03 09:44:07 2011 -0500
@@ -1031,7 +1031,7 @@
                        floatBin "+",
                        floatBin "-",
                        floatBin "*",
-                       floatBin "/",
+                       floatBin "fdiv",
                        floatBin "fmod")
             end
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/div.ur	Sat Dec 03 09:44:07 2011 -0500
@@ -0,0 +1,43 @@
+functor Make(M : sig
+                 type t
+                 val read_t : read t
+                 val show_t : show t
+                 val num_t : num t
+             end) = struct
+    fun calculate (n1, n2) = return <xml><body>
+      {[readError n1 / readError n2 : M.t]}<br/>
+      {[readError n1 % readError n2 : M.t]}<br/>
+    </body></xml>
+
+    fun main () =
+        s1 <- source "";
+        s2 <- source "";
+        s3 <- source "";
+        s4 <- source "";
+        return <xml><body>
+          <h1>Client-side</h1>
+
+          <ctextbox source={s1}/> / <ctextbox source={s2}/>
+          <button value="=" onclick={n1 <- get s1;
+                                     n2 <- get s2;
+                                     set s3 (show (readError n1 / readError n2 : M.t));
+                                     set s4 (show (readError n1 % readError n2 : M.t))}/>
+          <dyn signal={n <- signal s3; return (txt n)}/>,
+          <dyn signal={n <- signal s4; return (txt n)}/>
+
+          <h1>Server-side</h1>
+
+          <form>
+            <textbox{#1}/> / <textbox{#2}/>
+            <submit value="=" action={calculate}/>
+          </form>
+        </body></xml>
+end
+
+structure Int = Make(struct type t = int end)
+structure Float = Make(struct type t = float end)
+
+fun main () : transaction page = return <xml><body>
+  <li><a link={Int.main ()}>Int</a></li>
+  <li><a link={Float.main ()}>Float</a></li>
+</body></xml>