[m-rev.] for review: improvements for foreign_type

Simon Taylor stayl at cs.mu.OZ.AU
Mon Jul 1 02:39:05 AEST 2002


On 28-Jun-2002, Peter Ross <pro at missioncriticalit.com> wrote:
> On Fri, Jun 28, 2002 at 06:30:46PM +1000, Simon Taylor wrote:

Estimated hours taken: 10
Branches: main

Improvements for `:- pragma foreign_type'.
- Allow default Mercury definitions. The Mercury definition must define
  a discriminated union type. The constructors of the Mercury type are
  only visible in predicates which have implementations for all the
  foreign languages the type has implementations for. In all other
  predicates the type is treated as an abstract type (the check for
  this isn't quite right).
- Allow polymorphic foreign types.
- Don't require the `:- pragma foreign_type' for exported foreign types
  to be in the interface. We now only require that all definitions
  have the same visibility.

compiler/prog_data.m:
compiler/prog_io_pragma.m:
	Allow polymorphic foreign types.

compiler/prog_io.m:
	Export code to parse the type name in a type definition for
	use by prog_io_pragma.m.

compiler/make_hlds.m:
	Handle Mercury definitions for foreign types.

	Separate out the code to add constructors and special predicates
	to the HLDS into a separate pass. For foreign types, we don't know
	what to add until all type definitions have been seen.

	Use the C definition for foreign types with `--target asm'.

compiler/modules.m:
	Distinguish properly between `exported' and `exported_to_submodules'.
	Previously, if a module had sub-modules, all declarations,
	including those in the interface, had import_status
	`exported_to_submodules'. Now, the declarations in the
	interface have status `exported' or `abstract_exported'.
	This is needed to check that the visibility of all the
	definitions of a type is the same.

compiler/hlds_pred.m:
	Add a predicate status_is_exported_to_non_submodules, which
	fails if an item is local to the module and its sub-modules.

compiler/hlds_data.m:
compiler/*.m:
	Record whether a du type has foreign definitions as well.

	Also record whether uses of the type or its constructors
	need to be qualified (this is needed now that adding
	the constructors to the HLDS is a separate pass).

compiler/typecheck.m:
	Check that a predicate or function has foreign clauses before
	allowing the use of a constructor of a type which also has 
	foreign definitions.

compiler/hlds_pred.m:
compiler/make_hlds.m:
	Simplify the code to work out the goal_type for a predicate.

compiler/hlds_out.m:
	Don't abort on foreign types. 

	Print the goal type for each predicate.

compiler/error_util.m:
	Handle the case where the message being written is a
	continuation of an existing message, so the first line
	should be indented.

compiler/module_qual.m:
	Remove unnecessary processing of foreign types.

doc/reference_manual.tex:
	Document the change.

	Update the documentation for mixing Mercury and foreign clauses.
	The Mercury clauses no longer need to be mode-specific.

tests/hard_coded/Mmakefile:
tests/hard_coded/foreign_type2.{m,exp}:
tests/hard_coded/foreign_type.m:
tests/hard_coded/intermod_foreign_type.{m,exp}:
tests/hard_coded/intermod_foreign_type2.m:
tests/invalid/Mmakefile:
tests/invalid/foreign_type_2.{m,err_exp}:
tests/invalid/foreign_type_visibility.{m,err_exp}:
	Test cases.

tests/invalid/record_syntax.err_exp:
	Update expected output.


diff -u compiler/error_util.m compiler/error_util.m
--- compiler/error_util.m
+++ compiler/error_util.m
@@ -68,6 +68,8 @@
 	list(format_component)::in, io__state::di, io__state::uo) is det.
 
 	% Display the given error message, but indent the first line.
+	% This is useful when adding extra lines to an already
+	% displayed message.
 :- pred write_error_pieces_not_first_line(prog_context::in, int::in,
 	list(format_component)::in, io__state::di, io__state::uo) is det.
 
diff -u compiler/make_hlds.m compiler/make_hlds.m
--- compiler/make_hlds.m
+++ compiler/make_hlds.m
@@ -1968,7 +1968,7 @@
 					Status1) }
 			->
 				{ hlds_data__set_type_defn(TVarSet_2, Params_2,
-					NewBody, Status, OrigNeedQual,
+					NewBody, Status, NeedQual,
 					Context, T3) },
 				{ map__det_update(Types0,
 					TypeCtor, T3, Types) },
@@ -2035,17 +2035,23 @@
 		)
 	).
 
+	% check_foreign_type_visibility(OldStatus, NewDefnStatus).
+	%
+	% Check that the visibility of the new definition for
+	% a foreign type matches that of previous definitions.
 :- pred check_foreign_type_visibility(import_status::in,
 		import_status::in) is semidet.
 
-check_foreign_type_visibility(OldStatus, NewStatus) :-
+check_foreign_type_visibility(OldStatus, NewDefnStatus) :-
 	( OldStatus = abstract_exported  ->
-		status_is_exported_to_non_submodules(NewStatus, no)
+		% If OldStatus is abstract_exported, the previous
+		% definitions were local.
+		status_is_exported_to_non_submodules(NewDefnStatus, no)
 	; OldStatus = exported ->
-		NewStatus = exported
+		NewDefnStatus = exported
 	;
 		status_is_exported_to_non_submodules(OldStatus, no),
-		status_is_exported_to_non_submodules(NewStatus, no)
+		status_is_exported_to_non_submodules(NewDefnStatus, no)
 	).	
 
 	% Add the constructors and special preds for a type to the HLDS.
diff -u compiler/prog_data.m compiler/prog_data.m
--- compiler/prog_data.m
+++ compiler/prog_data.m
@@ -174,7 +174,8 @@
 
 	;	foreign_type(foreign_language_type, tvarset,
 			sym_name, list(type_param))
-			% ForeignType, TVarSet, MercuryType, MercuryTypeName
+			% ForeignType, TVarSet, MercuryTypeName,
+			% MercuryTypeParams
 
 	;	foreign_import_module(foreign_language, module_name)
 			% Equivalent to
diff -u compiler/typecheck.m compiler/typecheck.m
--- compiler/typecheck.m
+++ compiler/typecheck.m
@@ -4698,14 +4698,20 @@
 	% this point we've thrown away the clauses which we aren't using
 	% in the current compilation.
 	%
+	% The `.opt' files don't contain the foreign clauses from the source
+	% file that aren't used when compiling in the current grade, so we
+	% allow foreign type constructors in `opt_imported' predicates even
+	% if there are no foreign clauses. Errors will be caught when creating
+	% the `.opt' file.
+	%
 	(
 		Body ^ du_type_is_foreign_type = yes(_),
 		typecheck_info_get_predid(TypeCheckInfo, PredId),
 		typecheck_info_get_module_info(TypeCheckInfo, ModuleInfo),
 		module_info_pred_info(ModuleInfo, PredId, PredInfo),
-		\+ ( pred_info_get_goal_type(PredInfo, clauses_and_pragmas)
-		; code_util__compiler_generated(PredInfo)
-		)
+		\+ pred_info_get_goal_type(PredInfo, clauses_and_pragmas),
+		\+ code_util__compiler_generated(PredInfo),
+		\+ pred_info_import_status(PredInfo, opt_imported)
 	->
 		ConsTypeInfo = error(foreign_type_constructor(TypeCtor,
 				TypeDefn))
diff -u doc/reference_manual.texi doc/reference_manual.texi
--- doc/reference_manual.texi
+++ doc/reference_manual.texi
@@ -5227,7 +5227,7 @@
 language specific information below for details).  All definitions
 must have the same visibility.  A Mercury definition, which must define
 a discriminated union type, may also be given.  The constructors for the
-type will only be visible in clauses for for predicates or functions with
+type will only be visible in Mercury clauses for predicates or functions with
 @samp{pragma foreign_proc} clauses for all of the languages for which there
 are @samp{foreign_type} declarations for the type. 
 
diff -u tests/hard_coded/Mmakefile tests/hard_coded/Mmakefile
--- tests/hard_coded/Mmakefile
+++ tests/hard_coded/Mmakefile
@@ -82,6 +82,7 @@
 	impure_prune \
 	integer_test \
 	intermod_c_code \
+	intermod_foreign_type \
 	intermod_multimode_main \
 	intermod_pragma_clause \
 	intermod_type_qual \
@@ -254,6 +255,8 @@
 MCFLAGS-impure_foreign	=	--optimize-duplicate-calls
 MCFLAGS-intermod_c_code =	--intermodule-optimization
 MCFLAGS-intermod_c_code2 =	--intermodule-optimization
+MCFLAGS-intermod_foreign_type = --intermodule-optimization
+MCFLAGS-intermod_foreign_type2 = --intermodule-optimization
 MCFLAGS-intermod_pragma_clause = --intermodule-optimization
 MCFLAGS-intermod_type_qual =	--intermodule-optimization
 MCFLAGS-intermod_type_qual2 =	--intermodule-optimization
diff -u tests/hard_coded/foreign_type2.m tests/hard_coded/foreign_type2.m
--- tests/hard_coded/foreign_type2.m
+++ tests/hard_coded/foreign_type2.m
@@ -0,0 +1,78 @@
+% This modules tests selection of the Mercury definition for
+% types with both Mercury and foreign definitions,
+% It also tests field access functions for types with
+% both Mercury and foreign definitions.
Index: tests/hard_coded/intermod_foreign_type.exp
===================================================================
RCS file: tests/hard_coded/intermod_foreign_type.exp
diff -N tests/hard_coded/intermod_foreign_type.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/intermod_foreign_type.exp	28 Jun 2002 15:49:36 -0000
@@ -0,0 +1,3 @@
+X:4
+Y:5
+coord2(1, 2)
Index: tests/hard_coded/intermod_foreign_type.m
===================================================================
RCS file: tests/hard_coded/intermod_foreign_type.m
diff -N tests/hard_coded/intermod_foreign_type.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/intermod_foreign_type.m	28 Jun 2002 15:49:02 -0000
@@ -0,0 +1,30 @@
+:- module intermod_foreign_type.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module intermod_foreign_type2.
+:- import_module std_util.
+
+main -->
+	{ C = new(4, 5) },
+	io__write_string("X:"),
+	io__write_int(x(C)),
+	io__nl,
+	io__write_string("Y:"),
+	io__write_int(y(C)),
+	io__nl,
+	io__write(coord(1, 2)),
+	io__nl.
+
+:- type coord2
+	---> coord2(int, int).
+
+:- func coord(int, int) = coord2.
+
+coord(X, Y) = coord2(X, Y).
Index: tests/hard_coded/intermod_foreign_type2.m
===================================================================
RCS file: tests/hard_coded/intermod_foreign_type2.m
diff -N tests/hard_coded/intermod_foreign_type2.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/intermod_foreign_type2.m	28 Jun 2002 15:49:02 -0000
@@ -0,0 +1,58 @@
+:- module intermod_foreign_type2.
+
+:- interface.
+
+:- type coord.
+
+:- func new(int, int) = coord.
+
+:- func x(coord) = int.
+:- func y(coord) = int.
+
+%----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module std_util.
+
+% IL implementation
+:- pragma foreign_type(il, coord,
+	"class [foreign_type__csharp_code]coord").
+
+:- pragma foreign_decl("C#", "
+public class coord {
+	public int x;
+	public int y;
+}
+").
+
+:- pragma foreign_proc("C#", new(X::in, Y::in) = (C::out),
+	[will_not_call_mercury, promise_pure],
+"
+	C = new coord();
+	C.x = X;
+	C.y = Y;
+").
+
+:- pragma foreign_proc("C#", x(C::in) = (X::out),
+	[will_not_call_mercury, promise_pure],
+"
+	X = C.x;
+").
+
+:- pragma foreign_proc("C#", y(C::in) = (Y::out),
+	[will_not_call_mercury, promise_pure],
+"
+	Y = C.y;
+").
+
+%----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%
+
+% Mercury implementation
+:- type coord ---> coord(x :: int, y :: int).
+
+new(X, Y) = coord(X, Y).
+
+%----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list