summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adam@chlipala.net>2011-12-03 09:44:07 -0500
committerGravatar Adam Chlipala <adam@chlipala.net>2011-12-03 09:44:07 -0500
commit0f14aa67e5446391904c6a4d2ee7b4f00b803158 (patch)
tree55e7ce9758b2233896d59392e6b86614abab533a
parentfa906ca9e2e31d809221badd35ba1e93eaf3a8e5 (diff)
Catching integer divisions by zero
-rw-r--r--lib/js/urweb.js4
-rw-r--r--src/cjr_print.sml42
-rw-r--r--src/jscomp.sml2
-rw-r--r--src/monoize.sml2
-rw-r--r--tests/div.ur43
5 files changed, 88 insertions, 5 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
index d7bb7b6f..f05957a0 100644
--- a/lib/js/urweb.js
+++ b/lib/js/urweb.js
@@ -19,9 +19,9 @@ function plus(x, y) { return x + y; }
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; }
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index ddeb8ea5..2c4f7b36 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -1655,7 +1655,7 @@ fun p_exp' par tail env (e, loc) =
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 @@ fun p_exp' par tail env (e, loc) =
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])
diff --git a/src/jscomp.sml b/src/jscomp.sml
index 43c16cc3..3e475899 100644
--- a/src/jscomp.sml
+++ b/src/jscomp.sml
@@ -706,6 +706,8 @@ fun process file =
| "*" => "times"
| "/" => (case bi of Int => "divInt" | NotInt => "div")
| "%" => (case bi of Int => "modInt" | NotInt => "mod")
+ | "fdiv" => "div"
+ | "fmod" => "mod"
| "<" => "lt"
| "<=" => "le"
| "strcmp" => "strcmp"
diff --git a/src/monoize.sml b/src/monoize.sml
index 4a70c012..e4ed6562 100644
--- a/src/monoize.sml
+++ b/src/monoize.sml
@@ -1031,7 +1031,7 @@ fun monoExp (env, st, fm) (all as (e, loc)) =
floatBin "+",
floatBin "-",
floatBin "*",
- floatBin "/",
+ floatBin "fdiv",
floatBin "fmod")
end
diff --git a/tests/div.ur b/tests/div.ur
new file mode 100644
index 00000000..69a09275
--- /dev/null
+++ b/tests/div.ur
@@ -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>