[m-dev.] for review: duplicate arguments in `:- pragma c_code'

Simon Taylor stayl at cs.mu.OZ.AU
Fri Dec 10 12:04:22 AEDT 1999



Estimated hours taken: 1

compiler/make_hlds.m:
	Report errors if a variable occurs multiple times in the
	argument list of a `:- pragma c_code' declaration.

doc/reference_manual.texi:
	Document that variables should occur only once in a
	`:- pragma c_code' argument list.

tests/invalid/Mmakefile:
tests/invalid/pragma_c_code_dup_var.m:
tests/invalid/pragma_c_code_dup_var.err_exp:
	Test case.



Index: compiler/make_hlds.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/make_hlds.m,v
retrieving revision 1.319
diff -u -u -r1.319 make_hlds.m
--- make_hlds.m	1999/12/03 12:55:03	1.319
+++ make_hlds.m	1999/12/09 22:19:10
@@ -66,7 +66,7 @@
 :- import_module error_util.
 
 :- import_module string, char, int, set, bintree, map, multi_map, require.
-:- import_module term, varset, getopt, assoc_list, term_io.
+:- import_module bag, term, varset, getopt, assoc_list, term_io.
 
 parse_tree_to_hlds(module(Name, Items), MQInfo0, EqvMap, Module, 
 		UndefTypes, UndefModes) -->
@@ -3223,6 +3223,8 @@
 	% lookup some information we need from the pred_info and proc_info
 	%
 	{ pred_info_get_is_pred_or_func(PredInfo0, PredOrFunc) },
+	{ pred_info_module(PredInfo0, PredModule) },
+	{ pred_info_name(PredInfo0, PredName) },
 	{ pred_info_clauses_info(PredInfo0, Clauses0) },
 	{ pred_info_arg_types(PredInfo0, ArgTypes) },
 	{ pred_info_get_purity(PredInfo0, Purity) },
@@ -3264,7 +3266,8 @@
 	{ PragmaImpl = ordinary(C_Code, no) },
 	clauses_info_add_pragma_c_code(Clauses0, Purity, Attributes,
 		PredId, ProcId, VarSet, PragmaVars, ArgTypes, PragmaImpl,
-		Context, PredOrFunc, Arity, Clauses, Info0, Info),
+		Context, PredOrFunc, qualified(PredModule, PredName),
+		Arity, Clauses, Info0, Info),
 
 	%
 	% Store the clauses_info etc. back into the pred_info
@@ -3492,7 +3495,8 @@
 			clauses_info_add_pragma_c_code(Clauses0, Purity,
 				Attributes, PredId, ProcId, VarSet,
 				PVars, ArgTypes, PragmaImpl, Context,
-				PredOrFunc, Arity, Clauses, Info0, Info),
+				PredOrFunc, PredName, Arity,
+				Clauses, Info0, Info),
 			{ pred_info_set_clauses_info(PredInfo1, Clauses, 
 				PredInfo2) },
 			{ pred_info_set_goal_type(PredInfo2, pragmas, 
@@ -4485,48 +4489,94 @@
 :- pred clauses_info_add_pragma_c_code(clauses_info, purity,
 	pragma_c_code_attributes, pred_id, proc_id, prog_varset,
 	list(pragma_var), list(type), pragma_c_code_impl, prog_context,
-	pred_or_func, arity, clauses_info, qual_info,
+	pred_or_func, sym_name, arity, clauses_info, qual_info,
 	qual_info, io__state, io__state) is det.
 :- mode clauses_info_add_pragma_c_code(in, in, in, in, in, in, in, in, in, in,
-	in, in, out, in, out, di, uo) is det.
+	in, in, in, out, in, out, di, uo) is det.
 
 clauses_info_add_pragma_c_code(ClausesInfo0, Purity, Attributes, PredId,
 		ModeId, PVarSet, PVars, OrigArgTypes, PragmaImpl, Context,
-		PredOrFunc, Arity, ClausesInfo, Info0, Info) -->
+		PredOrFunc, PredName, Arity, ClausesInfo, Info0, Info) -->
 	{
 	ClausesInfo0 = clauses_info(VarSet0, VarTypes, VarTypes1,
 				 HeadVars, ClauseList, TI_VarMap, TCI_VarMap),
 	pragma_get_vars(PVars, Args0),
 	pragma_get_var_infos(PVars, ArgInfo),
 
+	%
+	% Check for arguments occurring multiple times.
+	%
+	bag__init(ArgBag0),
+	bag__insert_list(ArgBag0, Args0, ArgBag),
+	bag__to_assoc_list(ArgBag, ArgBagAL0),
+	list__filter(
+		(pred(Arg::in) is semidet :-
+			Arg = _ - Occurrences,
+			Occurrences > 1
+		), ArgBagAL0, ArgBagAL),
+	assoc_list__keys(ArgBagAL, MultipleArgs)
+	},
+
+	( { MultipleArgs = [_ | _] } ->
+		{ ClausesInfo = ClausesInfo0 },
+		{ Info = Info0 },
+		prog_out__write_context(Context),
+		io__write_string("In `:- pragma c_code' declaration for "),
+		{ adjust_func_arity(PredOrFunc, OrigArity, Arity) },
+		hlds_out__write_simple_call_id(
+			PredOrFunc - PredName/OrigArity),
+		io__write_string(":\n"),
+		prog_out__write_context(Context),
+		io__write_string("  error: "),
+		(
+			{ MultipleArgs = [MultipleArg] },
+			io__write_string("variable `"),
+			mercury_output_var(MultipleArg, PVarSet, no),
+			io__write_string("' occurs multiple times\n")
+		;
+			{ MultipleArgs = [_, _ | _] },
+			io__write_string("variables `"),
+			mercury_output_vars(MultipleArgs, PVarSet, no),
+			io__write_string(
+				"' occur multiple times\n")
+		),
+		prog_out__write_context(Context),
+		io__write_string("  in the argument list.\n"),
+		io__set_exit_status(1)
+	;
 		% merge the varsets of the proc and the new pragma_c_code
-	varset__merge_subst(VarSet0, PVarSet, VarSet1, Subst),
-	map__apply_to_list(Args0, Subst, TermArgs),
-	term__term_list_to_var_list(TermArgs, Args),
+		{
+		varset__merge_subst(VarSet0, PVarSet, VarSet1, Subst),
+		map__apply_to_list(Args0, Subst, TermArgs),
+		term__term_list_to_var_list(TermArgs, Args),
 
-		% build the pragma_c_code
-	goal_info_init(GoalInfo0),
-	goal_info_set_context(GoalInfo0, Context, GoalInfo1),
-	% Put the purity in the goal_info in case this c code is inlined
-	add_goal_info_purity_feature(GoalInfo1, Purity, GoalInfo),
-	HldsGoal0 = pragma_c_code(Attributes, PredId, ModeId, Args,
-		ArgInfo, OrigArgTypes, PragmaImpl) - GoalInfo
-	}, 
-		% Apply unifications with the head args.
-		% Since the set of head vars and the set vars in the
-		% pragma C code are disjoint, the unifications can be
-		% implemented as substitutions, and they will be.
-	insert_arg_unifications(HeadVars, TermArgs, Context,
-		head(PredOrFunc, Arity), yes, HldsGoal0, VarSet1,
-		HldsGoal1, VarSet2, Info0, Info),
-	{
-	map__init(Empty),
-	implicitly_quantify_clause_body(HeadVars, HldsGoal1, VarSet2, Empty,
-		HldsGoal, VarSet, _, _Warnings),
-	NewClause = clause([ModeId], HldsGoal, Context),
-	ClausesInfo =  clauses_info(VarSet, VarTypes, VarTypes1, HeadVars, 
-		[NewClause|ClauseList], TI_VarMap, TCI_VarMap)
-	}.
+			% build the pragma_c_code
+		goal_info_init(GoalInfo0),
+		goal_info_set_context(GoalInfo0, Context, GoalInfo1),
+		% Put the purity in the goal_info in case
+		% this c code is inlined
+		add_goal_info_purity_feature(GoalInfo1, Purity, GoalInfo),
+		HldsGoal0 = pragma_c_code(Attributes, PredId, ModeId, Args,
+			ArgInfo, OrigArgTypes, PragmaImpl) - GoalInfo
+		}, 
+			% Apply unifications with the head args.
+			% Since the set of head vars and the set vars in the
+			% pragma C code are disjoint, the unifications can be
+			% implemented as substitutions, and they will be.
+		insert_arg_unifications(HeadVars, TermArgs, Context,
+			head(PredOrFunc, Arity), yes, HldsGoal0, VarSet1,
+			HldsGoal1, VarSet2, Info0, Info),
+		{
+		map__init(Empty),
+		implicitly_quantify_clause_body(HeadVars, HldsGoal1,
+			VarSet2, Empty, HldsGoal, VarSet, _, _Warnings),
+		NewClause = clause([ModeId], HldsGoal, Context),
+		ClausesInfo =  clauses_info(VarSet, VarTypes, VarTypes1,
+			HeadVars, [NewClause|ClauseList],
+			TI_VarMap, TCI_VarMap)
+		}
+	).
+
 
 :- pred allocate_vars_for_saved_vars(list(string), list(pair(prog_var, string)),
 	prog_varset, prog_varset).
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/reference_manual.texi,v
retrieving revision 1.159
diff -u -u -r1.159 reference_manual.texi
--- reference_manual.texi	1999/11/25 08:21:16	1.159
+++ reference_manual.texi	1999/12/10 00:55:25
@@ -4054,7 +4054,8 @@
 (@var{Var1}, @var{Var2}, @dots{}, and @var{Var})
 directly by name.  These variables will have C types corresponding
 to their Mercury types, as determined by the rules specified in
- at ref{Passing data to and from C}.
+ at ref{Passing data to and from C}.  It is an error for a variable
+to occur more than once in the argument list.
 
 The C code fragment may declare local variables, but it should not
 declare any labels or static variables unless there is also a Mercury
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/tests/invalid/Mmakefile,v
retrieving revision 1.54
diff -u -u -r1.54 Mmakefile
--- Mmakefile	1999/12/03 17:33:37	1.54
+++ Mmakefile	1999/12/10 00:57:29
@@ -45,6 +45,7 @@
 	polymorphic_unification.m \
 	pragma_c_code_and_clauses1.m \
 	pragma_c_code_and_clauses2.m \
+	pragma_c_code_dup_var.m \
 	pragma_c_code_no_det.m \
 	predmode.m \
 	prog_io_erroneous.m \
Index: tests/invalid/pragma_c_code_dup_var.err_exp
===================================================================
RCS file: pragma_c_code_dup_var.err_exp
diff -N pragma_c_code_dup_var.err_exp
--- /dev/null	Fri Dec 10 11:30:05 1999
+++ pragma_c_code_dup_var.err_exp	Fri Dec 10 11:56:26 1999
@@ -0,0 +1,5 @@
+pragma_c_code_dup_var.m:019: In `:- pragma c_code' declaration for function `pragma_c_code_dup_var:bread_impl/6':
+pragma_c_code_dup_var.m:019:   error: variable `Buf' occurs multiple times
+pragma_c_code_dup_var.m:019:   in the argument list.
+pragma_c_code_dup_var.m:014: Error: no clauses for function `pragma_c_code_dup_var:bread_impl/7'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/pragma_c_code_dup_var.m
===================================================================
RCS file: pragma_c_code_dup_var.m
diff -N pragma_c_code_dup_var.m
--- /dev/null	Fri Dec 10 11:30:05 1999
+++ pragma_c_code_dup_var.m	Fri Dec 10 11:55:53 1999
@@ -0,0 +1,23 @@
+% Test errors for variables occurring multiple times in
+% a `:- pragma c_code' argument list.
+:- module pragma_c_code_dup_var.
+
+:- interface.
+
+:- import_module io.
+
+:- type buffer == string.
+:- type object == c_pointer.
+:- type unmarshalled(T) ---> unmarshalled(T).
+:- type signed_long_int ---> signed_short_int(c_pointer).
+
+:- func bread_impl(object, object, unmarshalled(buffer), unmarshalled(buffer), unmarshalled(signed_long_int), io__state, io__state) = unmarshalled(signed_long_int).
+:- mode bread_impl(in, out, in, out, in, di, uo) = out is det.
+
+:- implementation.
+
+:- pragma c_code(bread_impl(MC_Object0::in, MC_Object::out, Buf::in, Buf::out, Nbyte::in, MC_IO0::di, MC_IO::uo) = (Mc_returnval::out),
+		will_not_call_mercury, "
+	Mc_returnval = apache_gen__apache__request__bread(MC_Object0, &MC_Object, Buf, &Buf, Nbyte);
+	MC_IO = MC_IO0;
+").
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list