[m-rev.] Re: for review: try goals
Peter Wang
novalazy at gmail.com
Thu Feb 19 16:04:23 AEDT 2009
Interdiff. Now it bootchecks.
--- gws_try_syntax,20090217,a.txt 2009-02-17 17:43:31.000000000 +1100
+++ gws_try_syntax,20090219,a.txt 2009-02-19 14:21:58.000000000 +1100
@@ -2,8 +2,7 @@
Add support for `try' goals, syntactic sugar on top of the exception handling
predicates in the standard library. The syntax is documented in the reference
-manual. Currently one of the proposed try parameters, io(!IO), is implemented,
-and the user must import the `exception' and `univ' modules explicitly.
+manual. Currently one of the proposed try parameters, io(!IO), is implemented.
Try goals are implemented by *two* source-to-source transformations, one at the
parse tree level, then a later one on the HLDS. The reason for this is given
@@ -36,6 +35,9 @@
compiler/mercury_compile.m:
Call the try_expand pass near the end of the front-end pass.
+compiler/module_imports.m:
+ Implicitly import `exception' if a `try' goal is seen.
+
compiler/det_analysis.m:
Conform to addition of try goals in HLDS. Make it not wrap a commit
scope around the intermediate try goal (as it might if there are no
@@ -62,7 +64,6 @@
compiler/mercury_to_mercury.m:
compiler/mode_util.m:
compiler/modes.m:
-compiler/module_imports.m:
compiler/module_qual.m:
compiler/ordering_mode_constraints.m:
compiler/polymorphism.m:
@@ -80,6 +81,12 @@
compiler/unused_imports.m:
Conform to changes in HLDS.
+compiler/il_peephole.m:
+compiler/il_asm.m:
+compiler/ilds.m:
+compiler/mlds_to_il.m:
+ Rename some symbols to avoid the new keywords.
+
library/exception.m:
Add two helper predicates for the try goal transformations.
@@ -103,6 +110,8 @@
tests/hard_coded/try_syntax_5.m:
tests/hard_coded/try_syntax_6.exp:
tests/hard_coded/try_syntax_6.m:
+tests/hard_coded/try_syntax_7.exp:
+tests/hard_coded/try_syntax_7.m:
tests/invalid/Mmakefile:
tests/invalid/try_bad_params.err_exp:
tests/invalid/try_bad_params.m:
@@ -110,6 +119,9 @@
tests/invalid/try_io_else.m:
Add test cases.
+tests/debugger/declarative/catch.m:
+ The module name is now a keyword so requires brackets.
+
tests/invalid/trace_goal_env.err_exp:
Update test case for fixed spelling for "parameter".
diff --git a/compiler/add_clause.m b/compiler/add_clause.m
index d51ef39..6e71498 100644
--- a/compiler/add_clause.m
+++ b/compiler/add_clause.m
@@ -1457,7 +1457,7 @@ transform_try_expr_with_io(IOStateVarUnrenamed,
IOStateVar, Goal0, Then0,
ResultIsSucceededUnify0 =
unify_expr(
ResultVarTerm,
- functor(atom("succeeded"), [NullTupleTerm], Context),
+ exception_functor("succeeded", NullTupleTerm, Context),
purity_pure
) - Context,
transform_goal(ResultIsSucceededUnify0, Renaming, ResultIsSucceededUnify,
@@ -1582,7 +1582,7 @@ transform_try_expr_without_io(Goal0, Then0,
MaybeElse0, Catches0,
ResultIsSucceededUnify0 =
unify_expr(
ResultVarTerm,
- functor(atom("succeeded"), [NullTupleTerm], Context),
+ exception_functor("succeeded", NullTupleTerm, Context),
purity_pure
) - Context,
(
@@ -1629,7 +1629,7 @@ make_exception_handling_disjunct(ResultVarTerm,
ExcpVarTerm, Catches,
ResultIsExceptionUnify =
unify_expr(
ResultVarTerm,
- functor(atom("exception"), [ExcpVarTerm], Context),
+ exception_functor("exception", ExcpVarTerm, Context),
purity_pure
) - Context,
make_catch_ite_chain(ResultVarTerm, ExcpVarTerm, Catches, MaybeCatchAny,
@@ -1654,20 +1654,21 @@ make_catch_ite_chain(ResultVarTerm,
ExcpVarTerm, Catches, MaybeCatchAny,
(
MaybeCatchAny = yes(catch_any_expr(CatchAnyVar, CatchAnyGoal)),
% With a catch_any part, end the if-then-else chain with:
- % CatchAnyVar = univ_value(Excp),
+ % CatchAnyVar = exc_univ_value(Excp),
% CatchAnyGoal
CatchAnyGoal = _ - Context,
GetUnivValue = unify_expr(
variable(CatchAnyVar, Context),
- functor(atom("univ_value"), [ExcpVarTerm], Context),
+ exception_functor("exc_univ_value", ExcpVarTerm, Context),
purity_pure) - Context,
Goal = conj_expr(GetUnivValue, CatchAnyGoal) - Context
;
MaybeCatchAny = no,
% Without a catch_any part, end the if-then-else chain
% by rethrowing the exception.
- Goal = call_expr(string_to_sym_name("exception.rethrow"),
- [ResultVarTerm], purity_pure) - get_term_context(ExcpVarTerm)
+ Rethrow = qualified(mercury_exception_module, "rethrow"),
+ Goal = call_expr(Rethrow, [ResultVarTerm], purity_pure)
+ - get_term_context(ExcpVarTerm)
)
).
@@ -1675,7 +1676,8 @@ make_catch_ite_chain(ResultVarTerm, ExcpVarTerm,
Catches, MaybeCatchAny,
goal::out) is det.
make_catch_pattern_unify_goal(CatchPatternTerm, ExcpVarTerm, Goal) :-
- GoalExpr = call_expr(string_to_sym_name("univ_to_type"),
+ GoalExpr = call_expr(
+ qualified(mercury_exception_module, "exc_univ_to_type"),
[ExcpVarTerm, CatchPatternTerm], purity_pure),
Goal = GoalExpr - get_term_context(CatchPatternTerm).
@@ -1684,6 +1686,12 @@ make_catch_pattern_unify_goal(CatchPatternTerm,
ExcpVarTerm, Goal) :-
magic_exception_result_sym_name =
qualified(mercury_exception_module, "magic_exception_result").
+:- func exception_functor(string, prog_term, term.context) = prog_term.
+
+exception_functor(Atom, Arg, Context) = Term :-
+ construct_qualified_term(qualified(mercury_exception_module, Atom),
+ [Arg], Context, Term).
+
%----------------------------------------------------------------------------%
:- func this_file = string.
diff --git a/compiler/hlds_goal.m b/compiler/hlds_goal.m
index 785775b..39c0cab 100644
--- a/compiler/hlds_goal.m
+++ b/compiler/hlds_goal.m
@@ -319,8 +319,8 @@
; top_level_atomic_goal
; nested_atomic_goal.
-:- type catch
- ---> catch(
+:- type catch_part
+ ---> catch_part(
catch_expr :: hlds_goal_expr,
catch_goal :: hlds_goal
).
diff --git a/compiler/il_peephole.m b/compiler/il_peephole.m
index 7eebe64..99d60bc 100644
--- a/compiler/il_peephole.m
+++ b/compiler/il_peephole.m
@@ -276,12 +276,12 @@ match(ldc(Type, Const), VerifyOnly, [stloc(Var)|
Instrs0], Instrs) :-
% Two patterns begin with start_scope.
-match(start_block(scope(Locals), Id), VerifyOnly, !Instrs) :-
+match(start_block(bt_scope(Locals), Id), VerifyOnly, !Instrs) :-
VerifyOnly = no,
- ( match_start_scope_1(start_block(scope(Locals), Id), !Instrs) ->
+ ( match_start_scope_1(start_block(bt_scope(Locals), Id), !Instrs) ->
true
;
- match_start_scope_2(start_block(scope(Locals), Id), !Instrs)
+ match_start_scope_2(start_block(bt_scope(Locals), Id), !Instrs)
).
% If this is a scope with a local variable that is stored to but not
@@ -296,7 +296,7 @@ match(start_block(scope(Locals), Id), VerifyOnly,
!Instrs) :-
%
:- pred match_start_scope_1(instr::in, instrs::in, instrs::out) is semidet.
-match_start_scope_1(start_block(scope(Locals), Id), Instrs0, Instrs) :-
+match_start_scope_1(start_block(bt_scope(Locals), Id), Instrs0, Instrs) :-
% Is this variable a local that is unused?
IsUnusedLocal = (pred(V::in) is semidet :-
% Var is in the locals
@@ -357,7 +357,7 @@ match_start_scope_1(start_block(scope(Locals),
Id), Instrs0, Instrs) :-
Comment = string.format(
"peephole: dup, stloc(%s) --> nothing (%s unused in scope)",
[s(VarName), s(VarName)]),
- Instrs = list.condense([[start_block(scope(Locals), Id)],
+ Instrs = list.condense([[start_block(bt_scope(Locals), Id)],
PreStlocInstrs,
Nops,
[comment(Comment)],
@@ -369,7 +369,7 @@ match_start_scope_1(start_block(scope(Locals),
Id), Instrs0, Instrs) :-
%
:- pred match_start_scope_2(instr::in, instrs::in, instrs::out) is semidet.
-match_start_scope_2(start_block(scope(Locals), Id), Instrs0, Instrs) :-
+match_start_scope_2(start_block(bt_scope(Locals), Id), Instrs0, Instrs) :-
no_handwritten_code(Instrs0, Id),
% The pattern.
@@ -391,7 +391,7 @@ match_start_scope_2(start_block(scope(Locals),
Id), Instrs0, Instrs) :-
[s(VarName)], CommentStr),
Comment = comment(CommentStr)
), UnusedLocals, Comments),
- Replacement = [start_block(scope(UsedLocals), Id)],
+ Replacement = [start_block(bt_scope(UsedLocals), Id)],
Instrs = list.condense([Comments, Replacement, Instrs0]).
@@ -402,7 +402,7 @@ match_start_scope_2(start_block(scope(Locals),
Id), Instrs0, Instrs) :-
% is incomplete. This procedure is not yet called from anywhere.
:- pred match4(instr::in, instrs::in, instrs::out) is semidet.
-match4(start_block(scope([]), _), Instrs0, Instrs) :-
+match4(start_block(bt_scope([]), _), Instrs0, Instrs) :-
Replacement = [],
Rest = Instrs0,
Instrs = list.append(Replacement, Rest).
@@ -591,16 +591,16 @@ can_call(unbox(_Type)) = no.
:- func equivalent_to_nop(instr) = bool.
equivalent_to_nop(comment(_)) = yes.
-equivalent_to_nop(start_block(scope(_), _)) = yes.
-equivalent_to_nop(end_block(scope(_), _)) = yes.
+equivalent_to_nop(start_block(bt_scope(_), _)) = yes.
+equivalent_to_nop(end_block(bt_scope(_), _)) = yes.
equivalent_to_nop(nop) = yes.
equivalent_to_nop(context(_, _)) = yes.
equivalent_to_nop(il_asm_code(_, _)) = no.
-equivalent_to_nop(start_block(try, _)) = no.
-equivalent_to_nop(end_block(try, _)) = no.
-equivalent_to_nop(start_block(catch(_), _)) = no.
-equivalent_to_nop(end_block(catch(_), _)) = no.
+equivalent_to_nop(start_block(bt_try, _)) = no.
+equivalent_to_nop(end_block(bt_try, _)) = no.
+equivalent_to_nop(start_block(bt_catch(_), _)) = no.
+equivalent_to_nop(end_block(bt_catch(_), _)) = no.
equivalent_to_nop(label(_Label)) = no.
equivalent_to_nop(call(_MethodRef)) = no.
equivalent_to_nop(calli(_Signature)) = no.
diff --git a/compiler/ilasm.m b/compiler/ilasm.m
index 0901c4a..a987a97 100644
--- a/compiler/ilasm.m
+++ b/compiler/ilasm.m
@@ -1013,13 +1013,13 @@ output_debug_instruction(Instr, !Info, !IO) :-
; Instr = context(_, _) ->
% Contexts are messy, let's ignore them for now.
true
- ; Instr = start_block(catch(ClassName), Id) ->
- output_instr(start_block(catch(ClassName), Id), !Info, !IO),
+ ; Instr = start_block(bt_catch(ClassName), Id) ->
+ output_instr(start_block(bt_catch(ClassName), Id), !Info, !IO),
io.write_string("\n", !IO),
io.write_string("\t", !IO),
output_trace_instr(Instr, !Info, !IO),
io.write_string("\n", !IO)
- ; Instr = start_block(scope(Locals), Id) ->
+ ; Instr = start_block(bt_scope(Locals), Id) ->
string.format("{\t// #%d", [i(Id)], S),
io.write_string(S, !IO),
io.nl(!IO),
@@ -1112,7 +1112,7 @@ output_instr(comment(Comment), !Info, !IO) :-
output_instr(label(Label), !Info, !IO) :-
output_label(Label, !IO),
io.write_string(":", !IO).
-output_instr(start_block(scope(Locals), Id), !Info, !IO) :-
+output_instr(start_block(bt_scope(Locals), Id), !Info, !IO) :-
io.write_string("{", !IO),
io.write_string("\t// #", !IO),
io.write_int(Id, !IO),
@@ -1124,26 +1124,26 @@ output_instr(start_block(scope(Locals), Id),
!Info, !IO) :-
ilasm.write_list(Locals, ",\n\t\t", output_local, !Info, !IO),
io.write_string("\n\t)\n", !IO)
).
-output_instr(start_block(try, Id), !Info, !IO) :-
+output_instr(start_block(bt_try, Id), !Info, !IO) :-
io.write_string(".try {", !IO),
io.write_string("\t// #", !IO),
io.write_int(Id, !IO).
-output_instr(start_block(catch(ClassName), Id), !Info, !IO) :-
+output_instr(start_block(bt_catch(ClassName), Id), !Info, !IO) :-
io.write_string("catch ", !IO),
output_class_name(ClassName, !Info, !IO),
io.write_string(" {", !IO),
io.write_string("\t// #", !IO),
io.write_int(Id, !IO).
-output_instr(end_block(scope(_), Id), !Info, !IO) :-
+output_instr(end_block(bt_scope(_), Id), !Info, !IO) :-
io.write_string("}", !IO),
io.write_string("\t// #", !IO),
io.write_int(Id, !IO).
-output_instr(end_block(catch(_), Id), !Info, !IO) :-
+output_instr(end_block(bt_catch(_), Id), !Info, !IO) :-
io.write_string("}", !IO),
io.write_string("\t// #", !IO),
io.write_int(Id, !IO),
io.write_string(" (catch block)", !IO).
-output_instr(end_block(try, Id), !Info, !IO) :-
+output_instr(end_block(bt_try, Id), !Info, !IO) :-
io.write_string("}", !IO),
io.write_string("\t// #", !IO),
io.write_int(Id, !IO),
diff --git a/compiler/ilds.m b/compiler/ilds.m
index c6945de..b3e5bba 100644
--- a/compiler/ilds.m
+++ b/compiler/ilds.m
@@ -269,10 +269,10 @@
% handwritten code, or can introduce try or catch code.
%
:- type blocktype
- ---> scope(locals)
+ ---> bt_scope(locals)
% scope just introduces a scope for local variables
- ; try
- ; catch(class_name).
+ ; bt_try
+ ; bt_catch(class_name).
% Each block has a unique identifier (mainly so you can tell which
% ones match up without counting them).
@@ -511,9 +511,9 @@ calculate_max_stack_2([I | Instrs], Current, Max) =
get_stack_difference(end_block(_, _)) = 0.
get_stack_difference(comment(_)) = 0.
-get_stack_difference(start_block(scope(_), _)) = 0.
-get_stack_difference(start_block(try, _)) = 0.
-get_stack_difference(start_block(catch(_), _)) = 1.
+get_stack_difference(start_block(bt_scope(_), _)) = 0.
+get_stack_difference(start_block(bt_try, _)) = 0.
+get_stack_difference(start_block(bt_catch(_), _)) = 1.
get_stack_difference(context(_, _)) = 0.
get_stack_difference(label(_Label)) = 0.
get_stack_difference(il_asm_code(_, _)) = 0.
diff --git a/compiler/mlds_to_il.m b/compiler/mlds_to_il.m
index d4d56ae..86f974d 100644
--- a/compiler/mlds_to_il.m
+++ b/compiler/mlds_to_il.m
@@ -1158,10 +1158,10 @@ generate_method(_, IsCons, mlds_defn(Name,
Context, Flags, Entity),
context_node(Context) ++
from_list(CtorInstrs) ++
context_node(Context) ++
- singleton(start_block(scope(Locals), BlockId)) ++
+ singleton(start_block(bt_scope(Locals), BlockId)) ++
InstrsTree1 ++
MaybeRet ++
- singleton(end_block(scope(Locals), BlockId)),
+ singleton(end_block(bt_scope(Locals), BlockId)),
% If this is main, add the entrypoint, set a flag, wrap the code
% in an exception handler and call the initialization instructions
@@ -1228,20 +1228,20 @@ generate_method(_, IsCons, mlds_defn(Name,
Context, Flags, Entity),
CatchAnyException =
from_list([
- start_block(catch(ExceptionClassName), OuterCatchBlockId),
+ start_block(bt_catch(ExceptionClassName), OuterCatchBlockId),
ldstr("\nUncaught system exception: \n"),
call(WriteString),
call(WriteObject),
ldc(int32, i(1)),
call(il_set_exit_code),
leave(label_target(DoneLabel)),
- end_block(catch(ExceptionClassName), OuterCatchBlockId)
+ end_block(bt_catch(ExceptionClassName), OuterCatchBlockId)
]),
% Code to catch Mercury exceptions.
CatchUserException =
from_list([
- start_block(catch(MercuryExceptionClassName),
+ start_block(bt_catch(MercuryExceptionClassName),
InnerCatchBlockId),
ldfld(FieldRef),
call(WriteUncaughtException),
@@ -1250,7 +1250,7 @@ generate_method(_, IsCons, mlds_defn(Name,
Context, Flags, Entity),
call(il_set_exit_code),
leave(label_target(DoneLabel)),
- end_block(catch(MercuryExceptionClassName),
+ end_block(bt_catch(MercuryExceptionClassName),
InnerCatchBlockId)
]),
@@ -1283,21 +1283,21 @@ generate_method(_, IsCons, mlds_defn(Name,
Context, Flags, Entity),
InstrsTree =
from_list([
% outer try block
- start_block(try, OuterTryBlockId),
+ start_block(bt_try, OuterTryBlockId),
% inner try block
- start_block(try, InnerTryBlockId)
+ start_block(bt_try, InnerTryBlockId)
]) ++
cord.map(RenameRets, InstrsTree2) ++
from_list([
leave(label_target(DoneLabel)),
- end_block(try, InnerTryBlockId)
+ end_block(bt_try, InnerTryBlockId)
]) ++
% inner catch block
CatchUserException ++
from_list([
leave(label_target(DoneLabel)),
- end_block(try, OuterTryBlockId)
+ end_block(bt_try, OuterTryBlockId)
]) ++
% outer catch block
CatchAnyException ++
@@ -1649,7 +1649,7 @@ statement_to_il(statement(BlockStmt, Context),
Instrs, !Info) :-
DataRep = !.Info ^ il_data_rep,
list.map((pred((K - V)::in, (K - W)::out) is det :-
W = mlds_type_to_ilds_type(DataRep, V)), Locals, ILLocals),
- Scope = scope(ILLocals),
+ Scope = bt_scope(ILLocals),
Instrs =
context_node(Context) ++
singleton(start_block(Scope, BlockId)) ++
@@ -1900,17 +1900,17 @@ statement_to_il(statement(TryCommitStmt,
Context), Instrs, !Info) :-
context_node(Context) ++
comment_node("try_commit/3") ++
- singleton(start_block(try, TryBlockId)) ++
+ singleton(start_block(bt_try, TryBlockId)) ++
GoalInstrsTree ++
singleton(leave(label_target(DoneLabel))) ++
- singleton(end_block(try, TryBlockId)) ++
+ singleton(end_block(bt_try, TryBlockId)) ++
- singleton(start_block(catch(ClassName), CatchBlockId)) ++
+ singleton(start_block(bt_catch(ClassName), CatchBlockId)) ++
comment_node("discard the exception object") ++
singleton(pop) ++
HandlerInstrsTree ++
singleton(leave(label_target(DoneLabel))) ++
- singleton(end_block(catch(ClassName), CatchBlockId)) ++
+ singleton(end_block(bt_catch(ClassName), CatchBlockId)) ++
singleton(label(DoneLabel)).
statement_to_il(statement(ComputedGotoStmt, Context), Instrs, !Info) :-
diff --git a/compiler/module_imports.m b/compiler/module_imports.m
index 463dea5..90b7e6d 100644
--- a/compiler/module_imports.m
+++ b/compiler/module_imports.m
@@ -437,7 +437,8 @@ add_implicit_imports(Items, Globals, !ImportDeps,
!UseDeps) :-
!:ImportDeps = [mercury_public_builtin_module | !.ImportDeps],
!:UseDeps = [mercury_private_builtin_module | !.UseDeps],
items_need_imports(Items, no, ItemsNeedTabling,
- no, ItemsNeedTablingStatistics, no, ItemsNeedSTM),
+ no, ItemsNeedTablingStatistics, no, ItemsNeedSTM,
+ no, ItemsNeedException),
% We should include mercury_table_builtin_module if the Items contain
% a tabling pragma, or if one of --use-minimal-model (either kind) and
% --trace-table-io is specified. In the former case, we may also need
@@ -479,6 +480,12 @@ add_implicit_imports(Items, Globals, !ImportDeps,
!UseDeps) :-
;
ItemsNeedSTM = no
),
+ (
+ ItemsNeedException = yes,
+ !:UseDeps = [mercury_exception_module | !.UseDeps]
+ ;
+ ItemsNeedException = no
+ ),
globals.lookup_bool_option(Globals, profile_deep, Deep),
(
Deep = yes,
@@ -527,12 +534,13 @@ add_implicit_imports(Items, Globals,
!ImportDeps, !UseDeps) :-
).
:- pred items_need_imports(list(item)::in,
- bool::in, bool::out, bool::in, bool::out, bool::in, bool::out) is det.
+ bool::in, bool::out, bool::in, bool::out, bool::in, bool::out,
+ bool::in, bool::out) is det.
items_need_imports([], !ItemsNeedTabling,
- !ItemsNeedTablingStatistics, !ItemsNeedSTM).
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM, !ItemsNeedException).
items_need_imports([Item | Items], !ItemsNeedTabling,
- !ItemsNeedTablingStatistics, !ItemsNeedSTM) :-
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM, !ItemsNeedException) :-
(
Item = item_pragma(ItemPragma),
ItemPragma = item_pragma_info(_, Pragma, _, _),
@@ -541,65 +549,78 @@ items_need_imports([Item | Items], !ItemsNeedTabling,
!:ItemsNeedTabling = yes,
(
MaybeAttributes = no,
- % We cannot be done yet. If !.ItemsNeedTablingStatistics and
- % !.ItemsNeedSTM were already both `yes', !.ItemsNeedTabling
- % would have been too, and we would have stopped before looking
- % at this item.
- items_need_imports(Items, !ItemsNeedTabling,
- !ItemsNeedTablingStatistics, !ItemsNeedSTM)
+ maybe_items_need_imports(Items, !ItemsNeedTabling,
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM,
+ !ItemsNeedException)
;
MaybeAttributes = yes(Attributes),
StatsAttr = Attributes ^ table_attr_statistics,
(
StatsAttr = table_gather_statistics,
!:ItemsNeedTablingStatistics = yes,
- (
- !.ItemsNeedSTM = yes
- % There is nothing left to search for; stop recursing.
- ;
- !.ItemsNeedSTM = no,
- items_need_imports(Items, !ItemsNeedTabling,
- !ItemsNeedTablingStatistics, !ItemsNeedSTM)
- )
+ maybe_items_need_imports(Items, !ItemsNeedTabling,
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM,
+ !ItemsNeedException)
;
StatsAttr = table_dont_gather_statistics
)
)
;
- Item = item_clause(ItemClause),
- Body = ItemClause ^ cl_body,
- goal_contains_stm_atomic(Body) = yes
+ Item = item_clause(ItemClause)
->
- !:ItemsNeedSTM = yes,
- (
- !.ItemsNeedTabling = yes,
- !.ItemsNeedTablingStatistics = yes
- ->
- % There is nothing left to search for; stop recursing.
- true
+ Body = ItemClause ^ cl_body,
+ goal_contains_stm_atomic_or_try(Body, ContainsAtomic, ContainsTry),
+ ( ContainsAtomic = yes ->
+ !:ItemsNeedSTM = yes,
+ !:ItemsNeedException = yes
+ ; ContainsTry = yes ->
+ !:ItemsNeedException = yes
;
- items_need_imports(Items, !ItemsNeedTabling,
- !ItemsNeedTablingStatistics, !ItemsNeedSTM)
- )
+ true
+ ),
+ maybe_items_need_imports(Items, !ItemsNeedTabling,
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM, !ItemsNeedException)
+ ;
+ items_need_imports(Items, !ItemsNeedTabling,
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM, !ItemsNeedException)
+ ).
+
+:- pred maybe_items_need_imports(list(item)::in,
+ bool::in, bool::out, bool::in, bool::out, bool::in, bool::out,
+ bool::in, bool::out) is det.
+
+maybe_items_need_imports(Items, !ItemsNeedTabling, !ItemsNeedTablingStatistics,
+ !ItemsNeedSTM, !ItemsNeedException) :-
+ (
+ !.ItemsNeedTabling = yes,
+ !.ItemsNeedTablingStatistics = yes,
+ !.ItemsNeedSTM = yes,
+ !.ItemsNeedException = yes
+ ->
+ % There is nothing left to search for; stop recursing.
+ true
;
items_need_imports(Items, !ItemsNeedTabling,
- !ItemsNeedTablingStatistics, !ItemsNeedSTM)
+ !ItemsNeedTablingStatistics, !ItemsNeedSTM, !ItemsNeedException)
).
-:- func goal_contains_stm_atomic(goal) = bool.
+:- pred goal_contains_stm_atomic_or_try(goal::in, bool::out, bool::out) is det.
-goal_contains_stm_atomic(GoalExpr - _Context) = ContainsAtomic :-
+goal_contains_stm_atomic_or_try(GoalExpr - _Context,
+ ContainsAtomic, ContainsTry) :-
(
( GoalExpr = true_expr
; GoalExpr = fail_expr
),
- ContainsAtomic = no
+ ContainsAtomic = no,
+ ContainsTry = no
;
( GoalExpr = conj_expr(SubGoalA, SubGoalB)
; GoalExpr = par_conj_expr(SubGoalA, SubGoalB)
; GoalExpr = disj_expr(SubGoalA, SubGoalB)
),
- ContainsAtomic = two_goals_contain_stm_atomic(SubGoalA, SubGoalB)
+ two_goals_contain_stm_atomic_or_try(SubGoalA, SubGoalB,
+ ContainsAtomic, ContainsTry)
;
( GoalExpr = some_expr(_, SubGoal)
; GoalExpr = all_expr(_, SubGoal)
@@ -612,52 +633,76 @@ goal_contains_stm_atomic(GoalExpr - _Context) =
ContainsAtomic :-
SubGoal)
; GoalExpr = trace_expr(_, _, _, _, SubGoal)
),
- ContainsAtomic = goal_contains_stm_atomic(SubGoal)
+ goal_contains_stm_atomic_or_try(SubGoal, ContainsAtomic, ContainsTry)
;
GoalExpr = try_expr(_, SubGoal, Then, MaybeElse, Catches, CatchAny),
ContainsAtomic = maybe_goals_contain_stm_atomic([
yes(SubGoal), yes(Then), MaybeElse,
maybe_catch_any_expr_goal(CatchAny) |
list.map(yes_catch_expr_goal, Catches)
- ])
+ ]),
+ ContainsTry = yes
;
( GoalExpr = implies_expr(SubGoalA, SubGoalB)
; GoalExpr = equivalent_expr(SubGoalA, SubGoalB)
),
- ContainsAtomic = two_goals_contain_stm_atomic(SubGoalA, SubGoalB)
+ two_goals_contain_stm_atomic_or_try(SubGoalA, SubGoalB,
+ ContainsAtomic, ContainsTry)
;
GoalExpr = not_expr(SubGoal),
- ContainsAtomic = goal_contains_stm_atomic(SubGoal)
+ goal_contains_stm_atomic_or_try(SubGoal, ContainsAtomic, ContainsTry)
;
GoalExpr = if_then_else_expr(_, _, Cond, Then, Else),
- ContainsAtomic = three_goals_contain_stm_atomic(Cond, Then, Else)
+ three_goals_contain_stm_atomic_or_try(Cond, Then, Else,
+ ContainsAtomic, ContainsTry)
;
GoalExpr = atomic_expr(_, _, _, _, _),
- ContainsAtomic = yes
+ ContainsAtomic = yes,
+ ContainsTry = no
;
( GoalExpr = event_expr(_, _)
; GoalExpr = call_expr(_, _, _)
; GoalExpr = unify_expr(_, _, _)
),
- ContainsAtomic = no
+ ContainsAtomic = no,
+ ContainsTry = no
).
-:- func two_goals_contain_stm_atomic(goal, goal) = bool.
+:- pred two_goals_contain_stm_atomic_or_try(goal::in, goal::in,
+ bool::out, bool::out) is det.
-two_goals_contain_stm_atomic(GoalA, GoalB) = ContainsAtomic :-
- ( goal_contains_stm_atomic(GoalA) = yes ->
- ContainsAtomic = yes
+two_goals_contain_stm_atomic_or_try(GoalA, GoalB,
+ ContainsAtomic, ContainsTry) :-
+ goal_contains_stm_atomic_or_try(GoalA, ContainsAtomicA, ContainsTryA),
+ (
+ ContainsAtomicA = yes,
+ ContainsTryA = yes
+ ->
+ ContainsAtomic = yes,
+ ContainsTry = yes
;
- ContainsAtomic = goal_contains_stm_atomic(GoalB)
+ goal_contains_stm_atomic_or_try(GoalB, ContainsAtomicB, ContainsTryB),
+ bool.or(ContainsAtomicA, ContainsAtomicB, ContainsAtomic),
+ bool.or(ContainsTryA, ContainsTryB, ContainsTry)
).
-:- func three_goals_contain_stm_atomic(goal, goal, goal) = bool.
+:- pred three_goals_contain_stm_atomic_or_try(goal::in, goal::in, goal::in,
+ bool::out, bool::out) is det.
-three_goals_contain_stm_atomic(GoalA, GoalB, GoalC) = ContainsAtomic :-
- ( goal_contains_stm_atomic(GoalA) = yes ->
- ContainsAtomic = yes
+three_goals_contain_stm_atomic_or_try(GoalA, GoalB, GoalC,
+ ContainsAtomic, ContainsTry) :-
+ two_goals_contain_stm_atomic_or_try(GoalA, GoalB,
+ ContainsAtomicAB, ContainsTryAB),
+ (
+ ContainsAtomicAB = yes,
+ ContainsTryAB = yes
+ ->
+ ContainsAtomic = yes,
+ ContainsTry = yes
;
- ContainsAtomic = two_goals_contain_stm_atomic(GoalB, GoalC)
+ goal_contains_stm_atomic_or_try(GoalC, ContainsAtomicC, ContainsTryC),
+ bool.or(ContainsAtomicAB, ContainsAtomicC, ContainsAtomic),
+ bool.or(ContainsTryAB, ContainsTryC, ContainsTry)
).
:- func maybe_goals_contain_stm_atomic(list(maybe(goal))) = bool.
@@ -666,7 +711,7 @@ maybe_goals_contain_stm_atomic([]) = no.
maybe_goals_contain_stm_atomic([MaybeGoal | MaybeGoals]) = ContainsAtomic :-
(
MaybeGoal = yes(Goal),
- goal_contains_stm_atomic(Goal) = yes
+ goal_contains_stm_atomic_or_try(Goal, yes, _)
->
ContainsAtomic = yes
;
diff --git a/compiler/try_expand.m b/compiler/try_expand.m
index 2831312..b2801bb 100644
--- a/compiler/try_expand.m
+++ b/compiler/try_expand.m
@@ -114,7 +114,9 @@
% OutputTuple = { <BoundVars> }
% ), TryResult),
% (
-% TryResult = succeeded({ <BoundVars> }),
+% TryResult = succeeded(TmpTupleVar),
+% inst_cast(TmpTupleVar, TupleVar),
+% TupleVar = { <BoundVars> },
% <Then>
% ;
% TryResult = failed,
@@ -131,7 +133,9 @@
% OutputTuple = { <BoundVars> }
% ), TryResult),
% (
-% TryResult = succeeded({ <BoundVars> }),
+% TryResult = succeeded(TmpTupleVar),
+% inst_cast(TmpTupleVar, TupleVar),
+% TupleVar = { <BoundVars> },
% <Then>
% ;
% TryResult = exception(Excp),
@@ -145,7 +149,9 @@
% OutputTuple = { <BoundVars> }
% ), TryResult, !IO),
% (
-% TryResult = succeeded({ <BoundVars> }),
+% TryResult = succeeded(TmpTupleVar),
+% inst_cast(TmpTupleVar, TupleVar),
+% TupleVar = { <BoundVars> },
% <Then>
% ;
% TryResult = exception(Excp),
@@ -155,23 +161,26 @@
% We have to rename an io.state variable in ExcpHandling so that the sequence
% begins with the output I/O state of the `try_io' call.
%
+% The inst casts preserve the known insts of the BoundVars, which were lost due
+% to the calls to try*.
+%
% The <ExcpHandling> parts can be passed through from the pre-transformation.
% If a `catch_any' is present the exception handling looks like this:
%
-% ( univ_to_type(Excp, <CatchPattern1>) ->
+% ( exc_univ_to_type(Excp, <CatchPattern1>) ->
% <CatchGoal1>
-% ; univ_to_type(Excp, <CatchPattern2>) ->
+% ; exc_univ_to_type(Excp, <CatchPattern2>) ->
% <CatchGoal2>
% ;
-% CatchAnyVar = univ_value(Excp),
+% CatchAnyVar = exc_univ_value(Excp),
% <CatchAnyGoal>
% )
%
% Otherwise, if `catch_any' is not present:
%
-% ( univ_to_type(Excp, <CatchPattern1>) ->
+% ( exc_univ_to_type(Excp, <CatchPattern1>) ->
% <CatchGoal1>
-% ; univ_to_type(Excp, <CatchPattern2>) ->
+% ; exc_univ_to_type(Excp, <CatchPattern2>) ->
% <CatchGoal2>
% ;
% rethrow(TryResult)
@@ -199,6 +208,7 @@
:- import_module check_hlds.det_analysis.
:- import_module check_hlds.det_report.
+:- import_module check_hlds.inst_util.
:- import_module check_hlds.modes.
:- import_module check_hlds.polymorphism.
:- import_module hlds.goal_util.
@@ -231,17 +241,25 @@
%-----------------------------------------------------------------------------%
expand_try_goals(!ModuleInfo, !IO) :-
- some [!Globals] (
- module_info_get_globals(!.ModuleInfo, !:Globals),
- disable_det_warnings(OptionsToRestore, !Globals),
- module_info_set_globals(!.Globals, !ModuleInfo),
-
- module_info_predids(PredIds, !ModuleInfo),
- list.foldl2(expand_try_goals_in_pred, PredIds, !ModuleInfo, !IO),
-
- module_info_get_globals(!.ModuleInfo, !:Globals),
- restore_det_warnings(OptionsToRestore, !Globals),
- module_info_set_globals(!.Globals, !ModuleInfo)
+ % The exception module is implicitly imported if any try goals were seen,
+ % so if the exception module is not imported then we know there are no try
+ % goals to be expanded.
+ module_info_get_imported_module_specifiers(!.ModuleInfo, ImportedModules),
+ ( set.contains(ImportedModules, mercury_exception_module) ->
+ some [!Globals] (
+ module_info_get_globals(!.ModuleInfo, !:Globals),
+ disable_det_warnings(OptionsToRestore, !Globals),
+ module_info_set_globals(!.Globals, !ModuleInfo),
+
+ module_info_predids(PredIds, !ModuleInfo),
+ list.foldl2(expand_try_goals_in_pred, PredIds, !ModuleInfo, !IO),
+
+ module_info_get_globals(!.ModuleInfo, !:Globals),
+ restore_det_warnings(OptionsToRestore, !Globals),
+ module_info_set_globals(!.Globals, !ModuleInfo)
+ )
+ ;
+ true
).
:- pred expand_try_goals_in_pred(pred_id::in,
@@ -478,18 +496,20 @@ expand_try_goal(Instmap, TryGoal, FinalGoal, !Info) :-
some [!ModuleInfo, !PredInfo, !ProcInfo, !VarTypes] (
!.Info = trys_info(!:ModuleInfo, !:PredInfo, !:ProcInfo, _),
expand_try_goal_2(MaybeIO, ResultVar, Goal1, Then1, MaybeElse1,
- ExcpHandling1, GoalOutputVarsSet, FinalGoal, !PredInfo, !ProcInfo,
- !ModuleInfo),
+ ExcpHandling1, InstmapAfterGoal, GoalOutputVarsSet, FinalGoal,
+ !PredInfo, !ProcInfo, !ModuleInfo),
!:Info = trys_info(!.ModuleInfo, !.PredInfo, !.ProcInfo, yes)
).
:- pred expand_try_goal_2(maybe(try_io_state_vars)::in, prog_var::in,
hlds_goal::in, hlds_goal::in, maybe(hlds_goal)::in, hlds_goal::in,
- set(prog_var)::in, hlds_goal::out, pred_info::in, pred_info::out,
- proc_info::in, proc_info::out, module_info::in, module_info::out) is det.
+ instmap::in, set(prog_var)::in, hlds_goal::out,
+ pred_info::in, pred_info::out, proc_info::in, proc_info::out,
+ module_info::in, module_info::out) is det.
expand_try_goal_2(MaybeIO, ResultVar, Goal1, Then1, MaybeElse1, ExcpHandling1,
- GoalOutputVarsSet, FinalGoal, !PredInfo, !ProcInfo, !ModuleInfo) :-
+ Instmap, GoalOutputVarsSet, FinalGoal,
+ !PredInfo, !ProcInfo, !ModuleInfo) :-
some [!VarTypes] (
% Get the type of the output tuple.
proc_info_get_vartypes(!.ProcInfo, !:VarTypes),
@@ -509,6 +529,8 @@ expand_try_goal_2(MaybeIO, ResultVar, Goal1,
Then1, MaybeElse1, ExcpHandling1,
make_try_lambda(Goal1, GoalOutputVarsSet, OutputTupleType, MaybeIO,
LambdaVar, AssignLambdaVar, !ProcInfo),
+ GoalPurity = goal_get_purity(Goal1),
+
(
MaybeIO = yes(try_io_state_vars(GoalInitialIOVar, GoalFinalIOVar)),
@@ -535,7 +557,7 @@ expand_try_goal_2(MaybeIO, ResultVar, Goal1,
Then1, MaybeElse1, ExcpHandling1,
proc_info_create_var_from_type(io_state_type, yes("TryIOOutput"),
TryIOOutputVar, !ProcInfo),
make_try_call("try_io", LambdaVar, ResultVar,
- [GoalInitialIOVar, TryIOOutputVar], OutputTupleType,
+ [GoalInitialIOVar, TryIOOutputVar], OutputTupleType, GoalPurity,
CallTryGoal, !PredInfo, !ProcInfo, !ModuleInfo),
create_pure_atomic_complicated_unification(GoalFinalIOVar,
@@ -548,7 +570,7 @@ expand_try_goal_2(MaybeIO, ResultVar, Goal1,
Then1, MaybeElse1, ExcpHandling1,
;
MaybeIO = no,
make_try_call("try", LambdaVar, ResultVar, [], OutputTupleType,
- CallTryGoal, !PredInfo, !ProcInfo, !ModuleInfo),
+ GoalPurity, CallTryGoal, !PredInfo, !ProcInfo, !ModuleInfo),
Then = Then1,
ExcpHandling = ExcpHandling1
),
@@ -556,13 +578,18 @@ expand_try_goal_2(MaybeIO, ResultVar, Goal1,
Then1, MaybeElse1, ExcpHandling1,
goal_info_init(GoalInfo),
% The `succeeded' case.
+ proc_info_create_var_from_type(OutputTupleType, yes("TmpOutputTuple"),
+ TmpTupleVar, !ProcInfo),
proc_info_create_var_from_type(OutputTupleType, yes("OutputTuple"),
TupleVar, !ProcInfo),
- deconstruct_functor(ResultVar, succeeded_cons_id, [TupleVar],
+ deconstruct_functor(ResultVar, succeeded_cons_id, [TmpTupleVar],
DeconstructSucceeded),
+ instmap_lookup_vars(Instmap, GoalOutputVars, TupleArgInsts),
+ make_output_tuple_inst_cast(TmpTupleVar, TupleVar, TupleArgInsts,
+ CastOutputTuple),
deconstruct_tuple(TupleVar, GoalOutputVars, DeconstructOutputs),
- conj_list_to_goal([DeconstructSucceeded, DeconstructOutputs, Then],
- GoalInfo, DeconstructsThen),
+ conj_list_to_goal([DeconstructSucceeded, CastOutputTuple,
+ DeconstructOutputs, Then], GoalInfo, DeconstructsThen),
SucceededCase = case(succeeded_cons_id, [], DeconstructsThen),
% The `exception' case.
@@ -804,12 +831,12 @@ detism_to_try_lambda_detism(detism_erroneous, detism_det).
detism_to_try_lambda_detism(detism_failure, detism_semi).
:- pred make_try_call(string::in, prog_var::in, prog_var::in,
- list(prog_var)::in, mer_type::in, hlds_goal::out,
+ list(prog_var)::in, mer_type::in, purity::in, hlds_goal::out,
pred_info::in, pred_info::out, proc_info::in, proc_info::out,
module_info::in, module_info::out) is det.
make_try_call(PredName, LambdaVar, ResultVar, ExtraArgs, OutputTupleType,
- OverallGoal, !PredInfo, !ProcInfo, !ModuleInfo) :-
+ GoalPurity, OverallGoal, !PredInfo, !ProcInfo, !ModuleInfo) :-
create_poly_info(!.ModuleInfo, !.PredInfo, !.ProcInfo, PolyInfo0),
polymorphism_make_type_info_var(OutputTupleType, term.context_init,
TypeInfoVar, MakeTypeInfoGoals, PolyInfo0, PolyInfo),
@@ -822,9 +849,24 @@ make_try_call(PredName, LambdaVar, ResultVar,
ExtraArgs, OutputTupleType,
InstMapSrc = [],
generate_simple_call(mercury_exception_module, PredName,
pf_predicate, Mode, detism_cc_multi, purity_pure, Args, Features,
- InstMapSrc, !.ModuleInfo, term.context_init, CallGoal),
+ InstMapSrc, !.ModuleInfo, term.context_init, CallGoal0),
goal_info_init(GoalInfo),
+
+ % The try* predicates are only implemented for pure lambdas. If the lambda
+ % is actually non-pure, retain that in the call to try* with a purity
+ % scope.
+ (
+ GoalPurity = purity_pure,
+ CallGoal = CallGoal0
+ ;
+ ( GoalPurity = purity_semipure
+ ; GoalPurity = purity_impure
+ ),
+ ScopeReason = promise_purity(dont_make_implicit_promises, GoalPurity),
+ CallGoal = hlds_goal(scope(ScopeReason, CallGoal0), GoalInfo)
+ ),
+
conj_list_to_goal(MakeTypeInfoGoals ++ [CallGoal], GoalInfo, OverallGoal).
:- pred make_unreachable_call(module_info::in, hlds_goal::out) is det.
@@ -834,6 +876,28 @@ make_unreachable_call(ModuleInfo, Goal) :-
pf_predicate, only_mode, detism_erroneous, purity_pure,
[], [], [], ModuleInfo, term.context_init, Goal).
+:- pred make_output_tuple_inst_cast(prog_var::in, prog_var::in,
+ list(mer_inst)::in, hlds_goal::out) is det.
+
+make_output_tuple_inst_cast(TmpTupleVar, TupleVar, TupleArgInsts,
+ CastOrUnify) :-
+ % If all the arguments have inst `ground' then a unification is enough.
+ (
+ list.member(ArgInst, TupleArgInsts),
+ ArgInst \= ground(_, none)
+ ->
+ TupleArity = list.length(TupleArgInsts),
+ TupleInst = bound(shared, [
+ bound_functor(cons(unqualified("{}"), TupleArity), TupleArgInsts)
+ ]),
+ generate_cast_with_insts(unsafe_type_inst_cast, TmpTupleVar, TupleVar,
+ ground_inst, TupleInst, term.context_init, CastOrUnify)
+ ;
+ create_pure_atomic_complicated_unification(TupleVar,
+ rhs_var(TmpTupleVar), term.context_init,
+ umc_implicit("try_expand"), [], CastOrUnify)
+ ).
+
%-----------------------------------------------------------------------------%
:- func succeeded_cons_id = cons_id.
diff --git a/doc/reference_manual.texi b/doc/reference_manual.texi
index 93ad1e6..0cb344f 100644
--- a/doc/reference_manual.texi
+++ b/doc/reference_manual.texi
...
diff --git a/library/exception.m b/library/exception.m
index 643fdff..99250ef 100644
--- a/library/exception.m
+++ b/library/exception.m
@@ -253,6 +253,16 @@
%
:- pred unreachable is erroneous.
+ % Forwarding predicates so we don't need to implicitly import `univ'
+ % in the implementation of `try' goals.
+ %
+:- pred exc_univ_to_type(univ, T).
+:- mode exc_univ_to_type(in, out) is semidet.
+:- mode exc_univ_to_type(out, in) is det.
+:- mode exc_univ_to_type(uo, di) is det.
+
+:- some [T] func exc_univ_value(univ) = T.
+
%-----------------------------------------------------------------------------%
:- implementation.
@@ -801,6 +811,11 @@ magic_exception_result(succeeded({})). % force cc_multi
unreachable :-
throw("unreachable code reached").
+exc_univ_to_type(Univ, Object) :-
+ univ.univ_to_type(Univ, Object).
+
+exc_univ_value(Univ) = univ.univ_value(Univ).
+
%-----------------------------------------------------------------------------%
:- pred throw_impl(univ::in) is erroneous.
diff --git a/tests/debugger/declarative/catch.m
b/tests/debugger/declarative/catch.m
index ae4c347..417f6ff 100644
--- a/tests/debugger/declarative/catch.m
+++ b/tests/debugger/declarative/catch.m
@@ -1,4 +1,4 @@
-:- module catch.
+:- module (catch).
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is cc_multi.
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 84cb72a..fb866e0 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -252,6 +252,7 @@ ORDINARY_PROGS= \
try_syntax_4 \
try_syntax_5 \
try_syntax_6 \
+ try_syntax_7 \
tuple_test \
type_ctor_desc \
type_ctor_desc_manip \
diff --git a/tests/hard_coded/try_syntax_1.m b/tests/hard_coded/try_syntax_1.m
index f5ff6e9..f6cae20 100644
--- a/tests/hard_coded/try_syntax_1.m
+++ b/tests/hard_coded/try_syntax_1.m
@@ -14,7 +14,6 @@
:- implementation.
:- import_module exception.
-:- import_module univ.
:- import_module string.
%-----------------------------------------------------------------------------%
diff --git a/tests/hard_coded/try_syntax_2.m b/tests/hard_coded/try_syntax_2.m
index 89e534f..3be82b4 100644
--- a/tests/hard_coded/try_syntax_2.m
+++ b/tests/hard_coded/try_syntax_2.m
@@ -14,7 +14,6 @@
:- implementation.
:- import_module exception.
-:- import_module univ.
:- import_module string.
%-----------------------------------------------------------------------------%
diff --git a/tests/hard_coded/try_syntax_3.m b/tests/hard_coded/try_syntax_3.m
index 59e424f..d6e4128 100644
--- a/tests/hard_coded/try_syntax_3.m
+++ b/tests/hard_coded/try_syntax_3.m
@@ -14,7 +14,6 @@
:- implementation.
:- import_module exception.
-:- import_module univ.
:- import_module string.
%-----------------------------------------------------------------------------%
diff --git a/tests/hard_coded/try_syntax_4.m b/tests/hard_coded/try_syntax_4.m
index 4a3170c..5beb159 100644
--- a/tests/hard_coded/try_syntax_4.m
+++ b/tests/hard_coded/try_syntax_4.m
@@ -14,7 +14,6 @@
:- implementation.
:- import_module exception.
-:- import_module univ.
:- import_module string.
%-----------------------------------------------------------------------------%
diff --git a/tests/hard_coded/try_syntax_5.m b/tests/hard_coded/try_syntax_5.m
index b1c665b..ca5f99f 100644
--- a/tests/hard_coded/try_syntax_5.m
+++ b/tests/hard_coded/try_syntax_5.m
@@ -15,7 +15,6 @@
:- implementation.
:- import_module exception.
-:- import_module univ.
%-----------------------------------------------------------------------------%
diff --git a/tests/hard_coded/try_syntax_6.m b/tests/hard_coded/try_syntax_6.m
index 60838e9..860453b 100644
--- a/tests/hard_coded/try_syntax_6.m
+++ b/tests/hard_coded/try_syntax_6.m
@@ -14,7 +14,6 @@
:- implementation.
:- import_module exception.
-:- import_module univ.
%-----------------------------------------------------------------------------%
diff --git a/tests/hard_coded/try_syntax_7.exp
b/tests/hard_coded/try_syntax_7.exp
new file mode 100644
index 0000000..68300b8
--- /dev/null
+++ b/tests/hard_coded/try_syntax_7.exp
@@ -0,0 +1 @@
+It works!
diff --git a/tests/hard_coded/try_syntax_7.m b/tests/hard_coded/try_syntax_7.m
new file mode 100644
index 0000000..4ac38ec
--- /dev/null
+++ b/tests/hard_coded/try_syntax_7.m
@@ -0,0 +1,35 @@
+%-----------------------------------------------------------------------------%
+% Check inst casts get added in try goal transformation.
+
+:- module try_syntax_7.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ (try [] (
+ X = 1,
+ Y = "hi"
+ )
+ then
+ % Without inst casts, X and Y would be `ground' here.
+ p(X, Y, !IO)
+ ).
+
+:- pred p(int::in(bound(1)), string::in(bound("hi")),
+ io::di, io::uo) is det.
+
+p(1, "hi", !IO) :-
+ io.write_string("It works!\n", !IO).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list