[m-rev.] diff: switch over unary and binary ops in Java and C# code generators

Julien Fischer jfischer at opturion.com
Sun Feb 7 22:37:32 AEDT 2016


Switch over unary and binary ops in Java and C# code generators.

Fix more failing test cases in the non-C grades.

compiler/mlds_to_java.m:
compiler/mlds_to_cs.m:
     Always switch over unary and binary ops.  The existing code predates
     the addition of multi-arm switches to the language and was intended to
     the code duplication that would result in the absence of that feature.
     Since we now have multi-arm switches it is by far preferable to use
     a switch in these places.

     XXX for binary ops the above change replicates what the existing code
     did; I think it should actually abort in some cases.

     Fix spelling.

     Delete trailing whitespace.

compiler/java_util.m:
     Delete this module, it isn't used anymore.

compiler/ml_backend.m:
     Delete the include of the java_util module.

compiler/c_util.m:
     Update a comment.

tests/exceptions/Mmakefile:
     Fix the failure of 'test_uncaught_exception' in the java grade by
     filtering out the stack trace generated by the JVM.

tests/hard_coded/float_reg.exp4:
     Alternative expected output for this due to the way floats are
     printed.

tests/invalid_purity/purity.m:
tests/invalid_purity/purity.err_exp:
     Add C# and Java foreign_procs and updated the expected output.

tests/warnings/Mmakefile:
     Fix my previous change, which broke things in non-Erlang grades.

Julien.

diff --git a/compiler/c_util.m b/compiler/c_util.m
index 1e84b61..794d461 100644
--- a/compiler/c_util.m
+++ b/compiler/c_util.m
@@ -13,8 +13,6 @@
  % emitting C code.  Some of these routines are also useful with other languages
  % whose syntax is similar to C.
  %
-% NOTE: changes to this module may require changes to be made to java_util.m.
-%
  %-----------------------------------------------------------------------------%

  :- module backend_libs.c_util.
diff --git a/compiler/java_util.m b/compiler/java_util.m
deleted file mode 100644
index ce84860..0000000
--- a/compiler/java_util.m
+++ /dev/null
@@ -1,126 +0,0 @@
-%-----------------------------------------------------------------------------%
-% vim: ft=mercury ts=4 sw=4 et
-%-----------------------------------------------------------------------------%
-% Copyright (C) 2002-2006, 2010-2011 The University of Melbourne.
-% This file may only be copied under the terms of the GNU General
-% Public License - see the file COPYING in the Mercury distribution.
-%-----------------------------------------------------------------------------%
-%
-% File: java_util.m.
-% Main authors: juliensf, mjwybrow.
-%
-% This module defines utility routines that are used by the Java backend.
-% Much of the code below is similar to that in c_util.m; changes made to this
-% module may require changes to c_util.m.
-%
-%-----------------------------------------------------------------------------%
-
-:- module ml_backend.java_util.
-:- interface.
-
-:- import_module backend_libs.
-:- import_module backend_libs.builtin_ops.
-
-%-----------------------------------------------------------------------------%
-%
-% The following predicates all take as input an operator, check if it is an
-% operator of the specified kind, and if so, return the name of the
-% corresponding Java operator that can be used to implement it.
-%
-% XXX This scheme seems fundamentally incapable of providing a guarantee
-% that a piece of code that switches on binary_ops is a *complete* switch,
-% i.e. that it handles *all* binary operators.
-
-    % The operator returned will be either a prefix operator or function name.
-    % The operand needs to be placed in parentheses after the operator name.
-    %
-:- pred java_unary_prefix_op(unary_op::in, string::out) is det.
-
-    % The operator returned will be <, >, etc.; it can be used in the form:
-    % `<string_object>.CompareTo(<Arg1>, <Arg2>) <Op> 0'.
-    %
-:- pred java_string_compare_op(binary_op::in, string::out) is semidet.
-
-    % The operator returned will be +, *, etc.;
-    % the arguments should be floats and the result will be a float.
-    %
-:- pred java_float_op(binary_op::in, string::out) is semidet.
-
-    % The operator returned will be <, >, etc.;
-    % the arguments should be floats and the result will be a boolean.
-    %
-:- pred java_float_compare_op(binary_op::in, string::out) is semidet.
-
-    % The operator returned will be an infix operator.
-    % The arguments should be integer or booleans
-    % and the result will be an integer or a boolean.
-    %
-:- pred java_binary_infix_op(binary_op::in, string::out) is semidet.
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-:- implementation.
-
-%-----------------------------------------------------------------------------%
-
-    % Tags are not used in the Java back-end, as such, all of the tagging
-    % operators except for `tag' return no-ops. The `tag' case is handled
-    % separately in mlds_to_java__output_std_unop.
-    %
-java_unary_prefix_op(mktag,           "/* mktag */ ").
-java_unary_prefix_op(unmktag,         "/* unmktag */ ").
-java_unary_prefix_op(strip_tag,       "/* strip_tag */ ").
-java_unary_prefix_op(mkbody,          "/* mkbody */ ").
-java_unary_prefix_op(unmkbody,        "/* unmkbody */ ").
-java_unary_prefix_op(bitwise_complement,  "~").
-java_unary_prefix_op(logical_not,      "!").
-java_unary_prefix_op(tag, "").    % This case is never used.
-java_unary_prefix_op(hash_string,     "mercury.String.hash_1_f_0").
-java_unary_prefix_op(hash_string2,    "mercury.String.hash2_1_f_0").
-java_unary_prefix_op(hash_string3,    "mercury.String.hash3_1_f_0").
-java_unary_prefix_op(hash_string4,    "mercury.String.hash4_1_f_0").
-java_unary_prefix_op(hash_string5,    "mercury.String.hash5_1_f_0").
-java_unary_prefix_op(hash_string6,    "mercury.String.hash6_1_f_0").
-
-java_string_compare_op(str_eq, "==").
-java_string_compare_op(str_ne, "!=").
-java_string_compare_op(str_le, "<=").
-java_string_compare_op(str_ge, ">=").
-java_string_compare_op(str_lt, "<").
-java_string_compare_op(str_gt, ">").
-
-java_float_compare_op(float_eq, "==").
-java_float_compare_op(float_ne, "!=").
-java_float_compare_op(float_le, "<=").
-java_float_compare_op(float_ge, ">=").
-java_float_compare_op(float_lt, "<").
-java_float_compare_op(float_gt, ">").
-
-java_float_op(float_plus, "+").
-java_float_op(float_minus, "-").
-java_float_op(float_times, "*").
-java_float_op(float_divide, "/").
-
-java_binary_infix_op(int_add, "+").
-java_binary_infix_op(int_sub, "-").
-java_binary_infix_op(int_mul, "*").
-java_binary_infix_op(int_div, "/").
-java_binary_infix_op(int_mod, "%").
-java_binary_infix_op(unchecked_left_shift, "<<").
-java_binary_infix_op(unchecked_right_shift, ">>").
-java_binary_infix_op(bitwise_and, "&").
-java_binary_infix_op(bitwise_or, "|").
-java_binary_infix_op(bitwise_xor, "^").
-java_binary_infix_op(logical_and, "&&").
-java_binary_infix_op(logical_or, "||").
-java_binary_infix_op(eq, "==").
-java_binary_infix_op(ne, "!=").
-java_binary_infix_op(int_lt, "<").
-java_binary_infix_op(int_gt, ">").
-java_binary_infix_op(int_le, "<=").
-java_binary_infix_op(int_ge, ">=").
-
-%-----------------------------------------------------------------------------%
-:- end_module ml_backend.java_util.
-%-----------------------------------------------------------------------------%
diff --git a/compiler/ml_backend.m b/compiler/ml_backend.m
index 59a9565..17176d9 100644
--- a/compiler/ml_backend.m
+++ b/compiler/ml_backend.m
@@ -63,7 +63,6 @@

  % MLDS->Java back-end
  :- include_module mlds_to_java.
-:- include_module java_util.

  % MLDS->C# back-end.
  :- include_module mlds_to_cs.
diff --git a/compiler/mlds_to_cs.m b/compiler/mlds_to_cs.m
index c0a810b..02de846 100644
--- a/compiler/mlds_to_cs.m
+++ b/compiler/mlds_to_cs.m
@@ -62,7 +62,6 @@
  :- import_module mdbcomp.builtin_modules.
  :- import_module mdbcomp.prim_data.
  :- import_module mdbcomp.sym_name.
-:- use_module ml_backend.java_util.
  :- import_module ml_backend.ml_global_data.
  :- import_module ml_backend.ml_type_gen.   % for ml_gen_type_name
  :- import_module ml_backend.ml_util.
@@ -2707,7 +2706,7 @@ output_statements(Info, Indent, FuncInfo, [Statement | Statements],
          )
      else
          % Don't output any more statements from the current list since
-        % the preceeding statement cannot complete.
+        % the preceding statement cannot complete.
          ExitMethods = StmtExitMethods
      ).

@@ -3573,12 +3572,25 @@ csharp_builtin_type(Type, "int") :-
      % `tag', which always returns zero (a tag of zero means there's no tag).
      %
  output_std_unop(Info, UnaryOp, Expr, !IO) :-
-    ( if UnaryOp = tag then
+    (
+        UnaryOp = tag ,
          io.write_string("/* tag */  0", !IO)
-    else
-        % XXX C# is not Java
-        java_util.java_unary_prefix_op(UnaryOp, UnaryOpString),
-        io.write_string(UnaryOpString, !IO),
+    ;
+        ( UnaryOp = mktag,     UnaryOpStr = "/* mktag */ "
+        ; UnaryOp = unmktag,   UnaryOpStr = "/* unmktag */ "
+        ; UnaryOp = strip_tag, UnaryOpStr = "/* strip_tag */ "
+        ; UnaryOp = mkbody,    UnaryOpStr = "/* mkbody */ "
+        ; UnaryOp = unmkbody,   UnaryOpStr = "/* unmkbody */ "
+        ; UnaryOp = bitwise_complement, UnaryOpStr = "~"
+        ; UnaryOp = logical_not, UnaryOpStr = "!"
+        ; UnaryOp = hash_string,  UnaryOpStr = "mercury.String.hash_1_f_0"
+        ; UnaryOp = hash_string2, UnaryOpStr = "mercury.String.hash2_1_f_0"
+        ; UnaryOp = hash_string3, UnaryOpStr = "mercury.String.hash3_1_f_0"
+        ; UnaryOp = hash_string4, UnaryOpStr = "mercury.String.hash4_1_f_0"
+        ; UnaryOp = hash_string5, UnaryOpStr = "mercury.String.hash5_1_f_0"
+        ; UnaryOp = hash_string6, UnaryOpStr = "mercury.String.hash6_1_f_0"
+        ),
+        io.write_string(UnaryOpStr, !IO),
          io.write_string("(", !IO),
          output_rval(Info, Expr, !IO),
          io.write_string(")", !IO)
@@ -3588,41 +3600,85 @@ output_std_unop(Info, UnaryOp, Expr, !IO) :-
      mlds_rval::in, io::di, io::uo) is det.

  output_binop(Info, Op, X, Y, !IO) :-
-    % XXX This should be a single complete switch on Op.
-    ( if Op = array_index(_Type) then
+    (
+        Op = array_index(_Type),
          output_bracketed_rval(Info, X, !IO),
          io.write_string("[", !IO),
          output_rval(Info, Y, !IO),
          io.write_string("]", !IO)
-    % XXX C# is not Java
-    else if java_util.java_string_compare_op(Op, OpStr) then
-        ( if OpStr = "==" then
-            output_rval(Info, X, !IO),
-            io.write_string(".Equals(", !IO),
-            output_rval(Info, Y, !IO),
-            io.write_string(")", !IO)
-        else
-            io.write_string("(", !IO),
-            output_rval(Info, X, !IO),
-            io.write_string(".CompareOrdinal(", !IO),
-            output_rval(Info, Y, !IO),
-            io.write_string(") ", !IO),
-            io.write_string(OpStr, !IO),
-            io.write_string(" 0)", !IO)
-        )
-    else if Op = str_cmp then
+    ;
+        Op = str_eq,
+        output_rval(Info, X, !IO),
+        io.write_string(".Equals(", !IO),
+        output_rval(Info, Y, !IO),
+        io.write_string(")", !IO)
+    ;
+        ( Op = str_ne, OpStr = "!="
+        ; Op = str_lt, OpStr = "<"
+        ; Op = str_gt, OpStr = ">"
+        ; Op = str_le, OpStr = "<="
+        ; Op = str_ge, OpStr = ">="
+        ),
+        io.write_string("(", !IO),
+        output_rval(Info, X, !IO),
+        io.write_string(".CompareOrdinal(", !IO),
+        output_rval(Info, Y, !IO),
+        io.write_string(") ", !IO),
+        io.write_string(OpStr, !IO),
+        io.write_string(" 0)", !IO)
+    ;
+        Op = str_cmp,
          io.write_string("(", !IO),
          output_rval(Info, X, !IO),
          io.write_string(".CompareOrdinal(", !IO),
          output_rval(Info, Y, !IO),
          io.write_string("))", !IO)
-    else if Op = pointer_equal_conservative then
+    ;
+        Op = pointer_equal_conservative,
          io.write_string("System.Object.ReferenceEquals(", !IO),
          output_rval(Info, X, !IO),
          io.write_string(", ", !IO),
          output_rval(Info, Y, !IO),
          io.write_string(")", !IO)
-    else
+    ;
+        % XXX Should we abort for some of these?
+        ( Op = int_add
+        ; Op = int_sub
+        ; Op = int_mul
+        ; Op = int_div
+        ; Op = int_mod
+        ; Op = unchecked_left_shift
+        ; Op = unchecked_right_shift
+        ; Op = bitwise_and
+        ; Op = bitwise_or
+        ; Op = bitwise_xor
+        ; Op = logical_and
+        ; Op = logical_or
+        ; Op = eq
+        ; Op = ne
+        ; Op = body
+        ; Op = string_unsafe_index_code_unit
+        ; Op = offset_str_eq(_)
+        ; Op = int_lt
+        ; Op = int_gt
+        ; Op = int_le
+        ; Op = int_ge
+        ; Op = unsigned_le
+        ; Op = float_plus
+        ; Op = float_minus
+        ; Op = float_times
+        ; Op = float_divide
+        ; Op = float_eq
+        ; Op = float_ne
+        ; Op = float_lt
+        ; Op = float_gt
+        ; Op = float_le
+        ; Op = float_ge
+        ; Op = float_word_bits
+        ; Op = float_from_dword
+        ; Op = compound_eq
+        ; Op = compound_lt
+        ),
          io.write_string("(", !IO),
          output_rval(Info, X, !IO),
          io.write_string(" ", !IO),
@@ -3635,15 +3691,59 @@ output_binop(Info, Op, X, Y, !IO) :-
  :- pred output_binary_op(binary_op::in, io::di, io::uo) is det.

  output_binary_op(Op, !IO) :-
-    % XXX why are these separated into three predicates?
-    % XXX C# is not Java
-    ( if java_util.java_binary_infix_op(Op, OpStr) then
-        io.write_string(OpStr, !IO)
-    else if java_util.java_float_compare_op(Op, OpStr) then
-        io.write_string(OpStr, !IO)
-    else if java_util.java_float_op(Op, OpStr) then
+    (
+        ( Op = int_add, OpStr = "+"
+        ; Op = int_sub, OpStr = "-"
+        ; Op = int_mul, OpStr = "*"
+        ; Op = int_div, OpStr = "/"
+        ; Op = int_mod, OpStr = "%"
+        ; Op = unchecked_left_shift, OpStr = "<<"
+        ; Op = unchecked_right_shift, OpStr = ">>"
+        ; Op = bitwise_and, OpStr = "&"
+        ; Op = bitwise_or, OpStr = "|"
+        ; Op = bitwise_xor, OpStr = "^"
+        ; Op = logical_and, OpStr = "&&"
+        ; Op = logical_or, OpStr = "||"
+        ; Op = eq, OpStr = "=="
+        ; Op = ne, OpStr = "!="
+        ; Op = int_lt, OpStr = "<"
+        ; Op = int_gt, OpStr = ">"
+        ; Op = int_le, OpStr = "<="
+        ; Op = int_ge, OpStr = ">="
+
+
+        ; Op = float_eq, OpStr = "=="
+        ; Op = float_ne, OpStr = "!="
+        ; Op = float_le, OpStr = "<="
+        ; Op = float_ge, OpStr = ">="
+        ; Op = float_lt, OpStr = "<"
+        ; Op = float_gt, OpStr = ">"
+
+        ; Op = float_plus, OpStr = "+"
+        ; Op = float_minus, OpStr = "-"
+        ; Op = float_times, OpStr = "*"
+        ; Op = float_divide, OpStr = "/"
+        ),
          io.write_string(OpStr, !IO)
-    else
+    ;
+        ( Op = array_index(_)
+        ; Op = body
+        ; Op = float_from_dword
+        ; Op = float_word_bits
+        ; Op = offset_str_eq(_)
+        ; Op = str_cmp
+        ; Op = str_eq
+        ; Op = str_ge
+        ; Op = str_gt
+        ; Op = str_le
+        ; Op = str_lt
+        ; Op = str_ne
+        ; Op = string_unsafe_index_code_unit
+        ; Op = pointer_equal_conservative
+        ; Op = unsigned_le
+        ; Op = compound_eq
+        ; Op = compound_lt
+        ),
          unexpected($module, $pred, "invalid binary operator")
      ).

diff --git a/compiler/mlds_to_java.m b/compiler/mlds_to_java.m
index 0c1f573..93432a6 100644
--- a/compiler/mlds_to_java.m
+++ b/compiler/mlds_to_java.m
@@ -98,7 +98,6 @@
  :- import_module mdbcomp.
  :- import_module mdbcomp.prim_data.
  :- import_module mdbcomp.sym_name.
-:- import_module ml_backend.java_util.
  :- import_module ml_backend.ml_code_util.  % for ml_gen_local_var_decl_flags.
  :- import_module ml_backend.ml_global_data.
  :- import_module ml_backend.ml_type_gen.   % for ml_gen_type_name
@@ -4906,11 +4905,25 @@ java_builtin_type(Type, "int", "java.lang.Integer", "intValue") :-
      % means there's no tag).
      %
  output_std_unop(Info, UnaryOp, Expr, !IO) :-
-    ( if UnaryOp = tag then
+    (
+        UnaryOp = tag,
          io.write_string("/* tag */  0", !IO)
-    else
-        java_unary_prefix_op(UnaryOp, UnaryOpString),
-        io.write_string(UnaryOpString, !IO),
+    ;
+        ( UnaryOp = mktag,     UnaryOpStr = "/* mktag */ "
+        ; UnaryOp = unmktag,   UnaryOpStr = "/* unmktag */ "
+        ; UnaryOp = strip_tag, UnaryOpStr = "/* strip_tag */ "
+        ; UnaryOp = mkbody,    UnaryOpStr = "/* mkbody */ "
+        ; UnaryOp = unmkbody,   UnaryOpStr = "/* unmkbody */ "
+        ; UnaryOp = bitwise_complement, UnaryOpStr = "~"
+        ; UnaryOp = logical_not, UnaryOpStr = "!"
+        ; UnaryOp = hash_string,  UnaryOpStr = "mercury.String.hash_1_f_0"
+        ; UnaryOp = hash_string2, UnaryOpStr = "mercury.String.hash2_1_f_0"
+        ; UnaryOp = hash_string3, UnaryOpStr = "mercury.String.hash3_1_f_0"
+        ; UnaryOp = hash_string4, UnaryOpStr = "mercury.String.hash4_1_f_0"
+        ; UnaryOp = hash_string5, UnaryOpStr = "mercury.String.hash5_1_f_0"
+        ; UnaryOp = hash_string6, UnaryOpStr = "mercury.String.hash6_1_f_0"
+        ),
+        io.write_string(UnaryOpStr, !IO),
          io.write_string("(", !IO),
          output_rval(Info, Expr, !IO),
          io.write_string(")", !IO)
@@ -4920,55 +4933,102 @@ output_std_unop(Info, UnaryOp, Expr, !IO) :-
      mlds_rval::in, io::di, io::uo) is det.

  output_binop(Info, Op, X, Y, !IO) :-
-    % XXX This should be a single complete switch on Op.
-    ( if Op = array_index(_Type) then
+    (
+        Op = array_index(_Type),
          output_bracketed_rval(Info, X, !IO),
          io.write_string("[", !IO),
          output_rval(Info, Y, !IO),
          io.write_string("]", !IO)
-    else if java_string_compare_op(Op, OpStr) then
-        ( if OpStr = "==" then
-            output_rval(Info, X, !IO),
-            io.write_string(".equals(", !IO),
-            output_rval(Info, Y, !IO),
-            io.write_string(")", !IO)
-        else
-            io.write_string("(", !IO),
-            output_rval(Info, X, !IO),
-            io.write_string(".compareTo(", !IO),
-            output_rval(Info, Y, !IO),
-            io.write_string(") ", !IO),
-            io.write_string(OpStr, !IO),
-            io.write_string(" 0)", !IO)
-        )
-    else if Op = str_cmp then
-        io.write_string("(", !IO),
+    ;
+        Op = str_eq,
          output_rval(Info, X, !IO),
-        io.write_string(".compareTo(", !IO),
+        io.write_string(".equals(", !IO),
          output_rval(Info, Y, !IO),
-        io.write_string(")) ", !IO)
-    else if Op = pointer_equal_conservative then
+        io.write_string(")", !IO)
+    ;
+        ( Op = str_ne, OpStr = "!="
+        ; Op = str_lt, OpStr = "<"
+        ; Op = str_gt, OpStr = ">"
+        ; Op = str_le, OpStr = "<="
+        ; Op = str_ge, OpStr = ">="
+        ),
          io.write_string("(", !IO),
          output_rval(Info, X, !IO),
-        io.write_string(" == ", !IO),
+        io.write_string(".compareTo(", !IO),
          output_rval(Info, Y, !IO),
-        io.write_string(") ", !IO)
-    else if rval_is_enum_object(X) then
+        io.write_string(") ", !IO),
+        io.write_string(OpStr, !IO),
+        io.write_string(" 0)", !IO)
+    ;
+        Op = str_cmp,
          io.write_string("(", !IO),
          output_rval(Info, X, !IO),
-        io.write_string(".MR_value ", !IO),
-        output_binary_op(Op, !IO),
-        io.write_string(" ", !IO),
+        io.write_string(".compareTo(", !IO),
          output_rval(Info, Y, !IO),
-        io.write_string(".MR_value)", !IO)
-    else
+        io.write_string(")) ", !IO)
+    ;
+        Op = pointer_equal_conservative,
          io.write_string("(", !IO),
          output_rval(Info, X, !IO),
-        io.write_string(" ", !IO),
-        output_binary_op(Op, !IO),
-        io.write_string(" ", !IO),
+        io.write_string(" == ", !IO),
          output_rval(Info, Y, !IO),
-        io.write_string(")", !IO)
+        io.write_string(") ", !IO)
+    ;
+        % XXX Should we abort for some of these?
+        ( Op = int_add
+        ; Op = int_sub
+        ; Op = int_mul
+        ; Op = int_div
+        ; Op = int_mod
+        ; Op = unchecked_left_shift
+        ; Op = unchecked_right_shift
+        ; Op = bitwise_and
+        ; Op = bitwise_or
+        ; Op = bitwise_xor
+        ; Op = logical_and
+        ; Op = logical_or
+        ; Op = eq
+        ; Op = ne
+        ; Op = body
+        ; Op = string_unsafe_index_code_unit
+        ; Op = offset_str_eq(_)
+        ; Op = int_lt
+        ; Op = int_gt
+        ; Op = int_le
+        ; Op = int_ge
+        ; Op = unsigned_le
+        ; Op = float_plus
+        ; Op = float_minus
+        ; Op = float_times
+        ; Op = float_divide
+        ; Op = float_eq
+        ; Op = float_ne
+        ; Op = float_lt
+        ; Op = float_gt
+        ; Op = float_le
+        ; Op = float_ge
+        ; Op = float_word_bits
+        ; Op = float_from_dword
+        ; Op = compound_eq
+        ; Op = compound_lt
+        ),
+        ( if rval_is_enum_object(X) then
+            io.write_string("(", !IO),
+            output_rval(Info, X, !IO),
+            io.write_string(".MR_value ", !IO),
+            output_binary_op(Op, !IO),
+            io.write_string(" ", !IO),
+            output_rval(Info, Y, !IO),
+            io.write_string(".MR_value)", !IO)
+        else
+            io.write_string("(", !IO),
+            output_rval(Info, X, !IO),
+            io.write_string(" ", !IO),
+            output_binary_op(Op, !IO),
+            io.write_string(" ", !IO),
+            output_rval(Info, Y, !IO),
+            io.write_string(")", !IO)
+        )
      ).

      % Output an Rval and if the Rval is an enumeration object append the string
@@ -4996,14 +5056,59 @@ output_rval_maybe_with_enum(Info, Rval, !IO) :-
  :- pred output_binary_op(binary_op::in, io::di, io::uo) is det.

  output_binary_op(Op, !IO) :-
-    % XXX why are these separated into three predicates?
-    ( if java_binary_infix_op(Op, OpStr) then
-        io.write_string(OpStr, !IO)
-    else if java_float_compare_op(Op, OpStr) then
-        io.write_string(OpStr, !IO)
-    else if java_float_op(Op, OpStr) then
+    (
+        ( Op = int_add, OpStr = "+"
+        ; Op = int_sub, OpStr = "-"
+        ; Op = int_mul, OpStr = "*"
+        ; Op = int_div, OpStr = "/"
+        ; Op = int_mod, OpStr = "%"
+        ; Op = unchecked_left_shift, OpStr = "<<"
+        ; Op = unchecked_right_shift, OpStr = ">>"
+        ; Op = bitwise_and, OpStr = "&"
+        ; Op = bitwise_or, OpStr = "|"
+        ; Op = bitwise_xor, OpStr = "^"
+        ; Op = logical_and, OpStr = "&&"
+        ; Op = logical_or, OpStr = "||"
+        ; Op = eq, OpStr = "=="
+        ; Op = ne, OpStr = "!="
+        ; Op = int_lt, OpStr = "<"
+        ; Op = int_gt, OpStr = ">"
+        ; Op = int_le, OpStr = "<="
+        ; Op = int_ge, OpStr = ">="
+
+
+        ; Op = float_eq, OpStr = "=="
+        ; Op = float_ne, OpStr = "!="
+        ; Op = float_le, OpStr = "<="
+        ; Op = float_ge, OpStr = ">="
+        ; Op = float_lt, OpStr = "<"
+        ; Op = float_gt, OpStr = ">"
+
+        ; Op = float_plus, OpStr = "+"
+        ; Op = float_minus, OpStr = "-"
+        ; Op = float_times, OpStr = "*"
+        ; Op = float_divide, OpStr = "/"
+        ),
          io.write_string(OpStr, !IO)
-    else
+    ;
+        ( Op = array_index(_)
+        ; Op = body
+        ; Op = float_from_dword
+        ; Op = float_word_bits
+        ; Op = offset_str_eq(_)
+        ; Op = str_cmp
+        ; Op = str_eq
+        ; Op = str_ge
+        ; Op = str_gt
+        ; Op = str_le
+        ; Op = str_lt
+        ; Op = str_ne
+        ; Op = string_unsafe_index_code_unit
+        ; Op = pointer_equal_conservative
+        ; Op = unsigned_le
+        ; Op = compound_eq
+        ; Op = compound_lt
+        ),
          unexpected($module, $pred, "invalid binary operator")
      ).

@@ -5321,7 +5426,7 @@ init_java_out_info(ModuleInfo, SourceFileName, AddrOfMap) = Info :-
      module_info_get_globals(ModuleInfo, Globals),
      globals.lookup_bool_option(Globals, auto_comments, AutoComments),
      globals.lookup_bool_option(Globals, line_numbers, LineNumbers),
-    globals.lookup_bool_option(Globals, line_numbers_around_foreign_code, 
+    globals.lookup_bool_option(Globals, line_numbers_around_foreign_code,
          ForeignLineNumbers),
      module_info_get_name(ModuleInfo, ModuleName),
      MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
diff --git a/compiler/notes/compiler_design.html b/compiler/notes/compiler_design.html
index f73c5be..39c0bd8 100644
--- a/compiler/notes/compiler_design.html
+++ b/compiler/notes/compiler_design.html
@@ -2105,10 +2105,7 @@ and one generates C#.

  The MLDS->Java backend is broken into two submodules.
  <ul>
-<li>
-    mlds_to_java.m converts MLDS to Java and writes it to a .java file.
-<li>
-    java_util.m contains some utility routines.
+<li> mlds_to_java.m converts MLDS to Java and writes it to a .java file.
  </ul>

  After the Java code has been emitted, a Java compiler (normally javac)
diff --git a/tests/exceptions/Mmakefile b/tests/exceptions/Mmakefile
index 36432f6..5757b21 100644
--- a/tests/exceptions/Mmakefile
+++ b/tests/exceptions/Mmakefile
@@ -59,13 +59,15 @@ include Mercury.options
  # test_uncaught_exception is *supposed* to return an error exit status.
  # We also need to pipe the output through sed to avoid hard-coding
  # dependencies on particular line numbers in the standard library source code.
+# We also filter out the stack trace in the java grade in order to avoid
+# hard-coding dependencies on the Java runtime / generated code.
  test_uncaught_exception.out: test_uncaught_exception
  	if ./$< > $@.tmp 2>&1; then \
  		grep . $@.tmp; \
  		exit 1; \
  	else \
  		sed -e '/pred exception/s/exception.m:[0-9]*/exception.m:NNNN/g' \
-			< $@.tmp > $@ ; \
+			< $@.tmp | grep -v "jmercury\." > $@ ; \
  		rm -f $@.tmp; \
  	fi

diff --git a/tests/hard_coded/float_reg.exp4 b/tests/hard_coded/float_reg.exp4
new file mode 100644
index 0000000..369cba9
--- /dev/null
+++ b/tests/hard_coded/float_reg.exp4
@@ -0,0 +1,3 @@
+2.88E32
+1.0E32
+1.0E10
diff --git a/tests/invalid_purity/purity.err_exp b/tests/invalid_purity/purity.err_exp
index c34e052..4d1c06d 100644
--- a/tests/invalid_purity/purity.err_exp
+++ b/tests/invalid_purity/purity.err_exp
@@ -1,52 +1,52 @@
-purity.m:057: In predicate `w1'/0:
-purity.m:057:   warning: declared impure but actually pure.
-purity.m:061: In predicate `w2'/0:
-purity.m:061:   warning: declared semipure but actually pure.
-purity.m:065: In predicate `w3'/0:
-purity.m:065:   warning: declared impure but actually semipure.
-purity.m:069: In predicate `w4'/0:
-purity.m:069:   warning: unnecessary `promise_pure' pragma.
-purity.m:074: In predicate `w5'/0:
-purity.m:074:   error: declared impure but promised pure.
-purity.m:079: In predicate `w6'/0:
-purity.m:079:   error: declared semipure but promised pure.
-purity.m:087: In predicate `e1'/0:
-purity.m:087:   purity error: predicate is impure.
-purity.m:087:   It must be declared `impure' or promised pure.
-purity.m:091: In predicate `e2'/0:
-purity.m:091:   purity error: predicate is semipure.
-purity.m:091:   It must be declared `semipure' or promised pure.
-purity.m:095: In predicate `e3'/0:
-purity.m:095:   purity error: predicate is impure.
-purity.m:095:   It must be declared `impure' or promised semipure.
-purity.m:101: In call to impure predicate `purity.imp'/0:
-purity.m:101:   purity error: call must be preceded by `impure' indicator.
-purity.m:105: In call to semipure predicate `purity.semi'/0:
-purity.m:105:   purity error: call must be preceded by `semipure' indicator.
-purity.m:110: In clause for `e6':
-purity.m:110:   in argument 1 of call to predicate `purity.in'/1:
-purity.m:110:   mode error: variable `X' has instantiatedness `free',
-purity.m:110:   expected instantiatedness was `ground'.
-purity.m:110:   The goal could not be reordered, because it was followed by an
-purity.m:110:   impure goal.
-purity.m:111:   This is the location of the impure goal.
-purity.m:117: In clause for `e7':
-purity.m:117:   in argument 1 of call to predicate `purity.imp1'/1:
-purity.m:117:   mode error: variable `X' has instantiatedness `free',
-purity.m:117:   expected instantiatedness was `ground'.
-purity.m:117:   The goal could not be reordered, because it was impure.
-purity.m:120: In unification predicate for type `e8':
-purity.m:120:   purity error: predicate is impure.
-purity.m:120:   It must be pure.
-purity.m:132: In unification predicate for type `e9':
-purity.m:132:   purity error: predicate is semipure.
-purity.m:132:   It must be pure.
-purity.m:147: In call to impure predicate `purity.imp1'/1:
-purity.m:147:   purity error: call must be preceded by `impure' indicator.
-purity.m:147: Purity error in closure: closure body is impure, but closure was
-purity.m:147:   not declared impure.
-purity.m:153: In call to semipure predicate `purity.semi'/1:
-purity.m:153:   purity error: call must be preceded by `semipure' indicator.
-purity.m:153: Purity error in closure: closure body is semipure, but closure
-purity.m:153:   was not declared semipure.
+purity.m:115: In predicate `w1'/0:
+purity.m:115:   warning: declared impure but actually pure.
+purity.m:119: In predicate `w2'/0:
+purity.m:119:   warning: declared semipure but actually pure.
+purity.m:123: In predicate `w3'/0:
+purity.m:123:   warning: declared impure but actually semipure.
+purity.m:127: In predicate `w4'/0:
+purity.m:127:   warning: unnecessary `promise_pure' pragma.
+purity.m:132: In predicate `w5'/0:
+purity.m:132:   error: declared impure but promised pure.
+purity.m:137: In predicate `w6'/0:
+purity.m:137:   error: declared semipure but promised pure.
+purity.m:145: In predicate `e1'/0:
+purity.m:145:   purity error: predicate is impure.
+purity.m:145:   It must be declared `impure' or promised pure.
+purity.m:149: In predicate `e2'/0:
+purity.m:149:   purity error: predicate is semipure.
+purity.m:149:   It must be declared `semipure' or promised pure.
+purity.m:153: In predicate `e3'/0:
+purity.m:153:   purity error: predicate is impure.
+purity.m:153:   It must be declared `impure' or promised semipure.
+purity.m:159: In call to impure predicate `purity.imp'/0:
+purity.m:159:   purity error: call must be preceded by `impure' indicator.
+purity.m:163: In call to semipure predicate `purity.semi'/0:
+purity.m:163:   purity error: call must be preceded by `semipure' indicator.
+purity.m:168: In clause for `e6':
+purity.m:168:   in argument 1 of call to predicate `purity.in'/1:
+purity.m:168:   mode error: variable `X' has instantiatedness `free',
+purity.m:168:   expected instantiatedness was `ground'.
+purity.m:168:   The goal could not be reordered, because it was followed by an
+purity.m:168:   impure goal.
+purity.m:169:   This is the location of the impure goal.
+purity.m:175: In clause for `e7':
+purity.m:175:   in argument 1 of call to predicate `purity.imp1'/1:
+purity.m:175:   mode error: variable `X' has instantiatedness `free',
+purity.m:175:   expected instantiatedness was `ground'.
+purity.m:175:   The goal could not be reordered, because it was impure.
+purity.m:178: In unification predicate for type `e8':
+purity.m:178:   purity error: predicate is impure.
+purity.m:178:   It must be pure.
+purity.m:190: In unification predicate for type `e9':
+purity.m:190:   purity error: predicate is semipure.
+purity.m:190:   It must be pure.
+purity.m:205: In call to impure predicate `purity.imp1'/1:
+purity.m:205:   purity error: call must be preceded by `impure' indicator.
+purity.m:205: Purity error in closure: closure body is impure, but closure was
+purity.m:205:   not declared impure.
+purity.m:211: In call to semipure predicate `purity.semi'/1:
+purity.m:211:   purity error: call must be preceded by `semipure' indicator.
+purity.m:211: Purity error in closure: closure body is semipure, but closure
+purity.m:211:   was not declared semipure.
  For more information, recompile with `-E'.
diff --git a/tests/invalid_purity/purity.m b/tests/invalid_purity/purity.m
index 036d773..9ae8189 100644
--- a/tests/invalid_purity/purity.m
+++ b/tests/invalid_purity/purity.m
@@ -21,6 +21,20 @@
      ;
  ").

+:- pragma foreign_proc("Java",
+    imp,
+    [will_not_call_mercury],
+"
+    ;
+").
+
+:- pragma foreign_proc("C#",
+    imp,
+    [will_not_call_mercury],
+"
+    ;
+").
+
  :- semipure pred semi is semidet.
  :- pragma foreign_proc("C",
      semi,
@@ -29,6 +43,20 @@
      SUCCESS_INDICATOR = 0;
  ").

+:- pragma foreign_proc("Java",
+    semi,
+    [promise_semipure, will_not_call_mercury],
+"
+    SUCCESS_INDICATOR = false;
+").
+
+:- pragma foreign_proc("C#",
+    semi,
+    [promise_semipure, will_not_call_mercury],
+"
+    SUCCESS_INDICATOR = false;
+").
+
  :- pred in(foo).
  :- mode in(in) is semidet.
  in(a).
@@ -42,6 +70,22 @@ in(a).
      SUCCESS_INDICATOR = 0;
  ").

+:- pragma foreign_proc("Java",
+    semi(X::in),
+    [will_not_call_mercury, promise_semipure],
+"
+    /* X */
+    SUCCESS_INDICATOR = false;
+").
+
+:- pragma foreign_proc("C#",
+    semi(X::in),
+    [will_not_call_mercury, promise_semipure],
+"
+    /* X */
+    SUCCESS_INDICATOR = false;
+").
+
  :- impure pred imp1(foo).
  :- mode imp1(in) is semidet.
  :- pragma foreign_proc("C",
@@ -51,6 +95,20 @@ in(a).
      SUCCESS_INDICATOR = 0;
  ").

+:- pragma foreign_proc("Java",
+    imp1(_X::in),
+    [will_not_call_mercury],
+"
+    SUCCESS_INDICATOR = false;
+").
+
+:- pragma foreign_proc("C#",
+    imp1(_X::in),
+    [will_not_call_mercury],
+"
+    SUCCESS_INDICATOR = false;
+").
+
  %----------------------------------------------------------------
  %  Warnings.

diff --git a/tests/warnings/Mmakefile b/tests/warnings/Mmakefile
index 1f2c68b..66291ba 100644
--- a/tests/warnings/Mmakefile
+++ b/tests/warnings/Mmakefile
@@ -64,13 +64,10 @@ endif
  #     warn_return  (Erlang doesn't have return statements).
  #
  ifeq "$(filter erlang%,$(GRADE))" ""
-    NON_ERLANG_PROGS = \
-	warn_return
-else
-    NON_ERLANG_PROGS =
+    ERRORCHECK_PROGS += warn_return
  endif

-PROGS = $(COMPILE_PROGS) $(ERRORCHECK_PROGS) $(NON_ERLANG_PROGS) up_to_date
+PROGS = $(COMPILE_PROGS) $(ERRORCHECK_PROGS) up_to_date

  TESTS = $(sort $(PROGS))
  include $(TESTS_DIR)/Mmake.common



More information about the reviews mailing list