[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