Files
mercury/tests/hard_coded/bug383.m
Zoltan Somogyi d481a42f59 Give each op class (infix, prefix etc) its own slot.
library/ops.m:
    Instead of an op_table mapping a string to a list of one or more op_infos,
    make it map the string to a single structure, the op_infos, which has
    four slots, one each for infix, binary prefix, prefix and postfix
    op information. This allows parsers and unparsers to go directly to
    the kind of operator (e.g. infix or prefix) that they are interested in.

NEWS:
    Announce the change.

compiler/parse_tree_out_term.m:
library/mercury_term_parser.m:
library/pretty_printer.m:
library/stream.string_writer.m:
library/string.to_string.m:
samples/calculator2.m:
tests/hard_coded/bug383.m:
    Conform to the change. In several places, the new operator representation
    allows the replacement of loops with direct lookups, and the replacement
    of if-then-else chains with switches.

    Add reminders about keeping two predicates in sync.
2022-11-14 13:46:22 +11:00

192 lines
7.0 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
:- module bug383.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module int.
:- import_module list.
:- import_module mercury_term_parser.
:- import_module term_io.
:- import_module ops.
:- import_module pair.
:- import_module solutions.
:- import_module uint.
%---------------------------------------------------------------------------%
main(!IO) :-
read_term_with_op_table(cadmium_op_table, Res : read_term, !IO),
io.print_line(Res, !IO).
%---------------------------------------------------------------------------%
:- type cadmium_op_table
---> cadmium_op_table.
:- instance op_table(cadmium_op_table).
:- instance op_table(cadmium_op_table) where [
pred(lookup_infix_op/5) is lookup_cadmium_infix_op,
pred(lookup_prefix_op/4) is lookup_cadmium_prefix_op,
pred(lookup_binary_prefix_op/5) is lookup_cadmium_binary_prefix_op,
pred(lookup_postfix_op/4) is lookup_cadmium_postfix_op,
pred(is_op/2) is is_cadmium_op,
pred(lookup_op_infos/3) is lookup_cadmium_op_infos,
pred(lookup_operator_term/4) is lookup_cadmium_operator_term,
func(universal_priority/1) is cadmium_universal_priority,
func(loosest_op_priority/1) is cadmium_loosest_op_priority,
func(tightest_op_priority/1) is cadmium_tightest_op_priority,
func(comma_priority/1) is cadmium_comma_priority,
func(arg_priority/1) is cadmium_arg_priority
].
%---------------------------------------------------------------------------%
:- pred lookup_cadmium_op_infos(cadmium_op_table::in, string::in,
op_infos::out) is semidet.
lookup_cadmium_op_infos(_, Name, OpInfos) :-
cadmium_op_table(Name, OpInfos).
%---------------------------------------------------------------------------%
:- pred lookup_cadmium_infix_op(cadmium_op_table::in, string::in,
priority::out, arg_prio_gt_or_ge::out, arg_prio_gt_or_ge::out) is semidet.
lookup_cadmium_infix_op(_, Name, Priority, GtOrGeA, GtOrGeB) :-
cadmium_op_table(Name, OpInfos),
OpInfos ^ oi_infix = in(Priority, GtOrGeA, GtOrGeB).
%---------------------------------------------------------------------------%
:- pred lookup_cadmium_prefix_op(cadmium_op_table::in, string::in,
priority::out, arg_prio_gt_or_ge::out) is semidet.
lookup_cadmium_prefix_op(_, Name, Priority, GtOrGeA) :-
cadmium_op_table(Name, OpInfos),
OpInfos ^ oi_prefix = pre(Priority, GtOrGeA).
%---------------------------------------------------------------------------%
:- pred lookup_cadmium_binary_prefix_op(cadmium_op_table, string, priority,
arg_prio_gt_or_ge, arg_prio_gt_or_ge).
:- mode lookup_cadmium_binary_prefix_op(in, in, out, out, out) is semidet.
lookup_cadmium_binary_prefix_op(_, Name, Priority, GtOrGeA, GtOrGeB) :-
cadmium_op_table(Name, OpInfos),
OpInfos ^ oi_binary_prefix = bin_pre(Priority, GtOrGeA, GtOrGeB).
%---------------------------------------------------------------------------%
:- pred lookup_cadmium_postfix_op(cadmium_op_table::in, string::in,
priority::out, arg_prio_gt_or_ge::out) is semidet.
lookup_cadmium_postfix_op(_, Name, Priority, GtOrGeA) :-
cadmium_op_table(Name, OpInfos),
OpInfos ^ oi_postfix = post(Priority, GtOrGeA).
%---------------------------------------------------------------------------%
:- pred lookup_cadmium_operator_term(cadmium_op_table::in, priority::out,
arg_prio_gt_or_ge::out, arg_prio_gt_or_ge::out) is semidet.
lookup_cadmium_operator_term(_, prio(1400u), arg_ge, arg_gt) :-
semidet_true.
%---------------------------------------------------------------------------%
:- pred is_cadmium_op(cadmium_op_table::in, string::in) is semidet.
is_cadmium_op(_, Name) :-
cadmium_op_table(Name, _).
%---------------------------------------------------------------------------%
:- func cadmium_universal_priority(cadmium_op_table) = priority.
cadmium_universal_priority(_) = prio(0u).
:- func cadmium_loosest_op_priority(cadmium_op_table) = priority.
cadmium_loosest_op_priority(_) = prio(1u).
:- func cadmium_tightest_op_priority(cadmium_op_table) = priority.
cadmium_tightest_op_priority(_) = prio(1500u).
:- func cadmium_comma_priority(cadmium_op_table) = priority.
cadmium_comma_priority(_) = prio(195u).
:- func cadmium_arg_priority(cadmium_op_table) = priority.
cadmium_arg_priority(_) = prio(196u).
%---------------------------------------------------------------------------%
:- pred find_first(pred(T)::(pred(in) is semidet), list(T)::in, T::out)
is semidet.
find_first(Pred, [X | Xs], Y) :-
( if Pred(X) then
Y = X
else
find_first(Pred, Xs, Y)
).
%---------------------------------------------------------------------------%
:- pred cadmium_op_table(string::in, op_infos::out) is semidet.
cadmium_op_table(Op, OpInfos) :-
(
( Op = "+"
; Op = "-"
),
Infix = in(prio(1100u), arg_ge, arg_gt),
Prefix = pre(prio(1410u), arg_gt),
OpInfos = op_infos(Infix, no_bin_pre, Prefix, no_post)
;
( Op = "import", Prefix = pre(prio(100u), arg_ge)
; Op = "ruleset", Prefix = pre(prio(100u), arg_ge)
; Op = "transform", Prefix = pre(prio(100u), arg_ge)
),
OpInfos = op_infos(no_in, no_bin_pre, Prefix, no_post)
;
( Op = "<=>", Infix = in(prio(150u), arg_gt, arg_ge)
; Op = "|", Infix = in(prio(190u), arg_gt, arg_ge)
; Op = "\\", Infix = in(prio(190u), arg_ge, arg_gt)
; Op = ",", Infix = in(prio(195u), arg_gt, arg_ge)
; Op = "<->", Infix = in(prio(300u), arg_gt, arg_gt)
; Op = "->", Infix = in(prio(400u), arg_gt, arg_ge)
; Op = "<-", Infix = in(prio(400u), arg_gt, arg_ge)
; Op = "\\/", Infix = in(prio(500u), arg_ge, arg_gt)
; Op = "xor", Infix = in(prio(500u), arg_ge, arg_gt)
; Op = "/\\", Infix = in(prio(600u), arg_ge, arg_gt)
; Op = "<", Infix = in(prio(700u), arg_gt, arg_gt)
; Op = ">", Infix = in(prio(700u), arg_gt, arg_gt)
; Op = "<=", Infix = in(prio(700u), arg_gt, arg_ge)
; Op = ">=", Infix = in(prio(700u), arg_gt, arg_gt)
; Op = "=", Infix = in(prio(700u), arg_gt, arg_gt)
; Op = "!=", Infix = in(prio(700u), arg_gt, arg_gt)
; Op = ":=", Infix = in(prio(1430u), arg_gt, arg_gt)
; Op = "@", Infix = in(prio(1430u), arg_gt, arg_gt)
; Op = ".", Infix = in(prio(1490u), arg_ge, arg_gt)
),
OpInfos = op_infos(Infix, no_bin_pre, no_pre, no_post)
).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%