[m-rev.] diff: C# interface for .NET backend.

Tyson Dowd trd at cs.mu.OZ.AU
Wed May 2 09:01:44 AEST 2001


> >  :- pred ml_gen_nondet_pragma_c_code(code_model, pragma_foreign_proc_attributes,
> 
> Maybe you should change this to ml_gen_nondet_pragma_foreign_code to be
> consistent.

Done, I changed it to ml_gen_nondet_pragma_foreign_proc to be even more
accurate.

> > +	% For ordinary (not model_non) pragma foreign_code in C#,
> > +	% we generate a call to an out-of-line procedure that contains
> > +	% the user's code.
> > +
> What happens if you declare nondet pragma foreign_code in C#?

We now test for this and call sorry/2.

> > --- compiler/mlds.m	2001/02/28 15:59:18	1.49
> > +++ compiler/mlds.m	2001/04/30 13:50:33
> > @@ -1011,7 +1011,6 @@
> >  	;	mark_hp(mlds__lval)
> >  			% Tell the heap sub-system to store a marker
> >  			% (for later use in restore_hp/1 instructions)
> > -			% in the specified lval
> >  			%
> Why delete this line?

Oops, that I certainly didn't mean.

> > +	;	outline_target_code(
> > +				foreign_language,
> > +					% the foreign language of this code
> > +				list(mlds__lval),
> > +					% where to store return value(s)
> > +				string
> > +					% the user's foreign language code
> 
> What is the difference between the user's foreign language and the foreign
> language of this code?


foreign_language is one of the enumeration of the foreign_language type.
The user's foreign language code is the actual code fragment that the
programmer put inside the pragma.  

I've explained this a bit better now.

> > +:- import_module ilds, ilasm, il_peephole.
> > +:- import_module ml_util, ml_code_util.
> > +:- import_module mlds_to_c. /* to output C code for .cpp files */
> > +:- use_module llds. /* for user_c_code */
> > +
> > +:- import_module bool, int, map, string, list, assoc_list, term, std_util.
> > +:- import_module library, require, counter.
> > +
> > +:- import_module mlds_to_il.
> > +
> 
> I would imagine that the mlds_to_c import isn't needed.

Yes, and llds_out too.

> > +	% This section could very nearly be turned into a
> > +	% mlds_to_csharp module, which turns MLDS into managed C++.
> > +	% Note that it relies on quite a few predicates in mlds_to_il.
> > +	% XXX we should clean up the dependencies.
> > +	% XXX we don't output contexts for any of this.
> 
> Really that this section could almost be turned into a mlds_to_csharp
> module?

Ah, I can remove this comment now that I've done it.

And I now think the dependencies are OK, it's important to share the same
type conversions (turning MLDS types into IL types).

> > +	io__nl,
> > +	io__write_strings([
> > +		"// #using ""mercury_mcpp.dll""\n",
> > +		"// #using ""mercury_il.dll""\n",
> > +		"// #using """, ModuleNameStr, ".dll""\n",
> > +
> > +		% XXX We have to use the mercury namespace, as
> > +		% llds_out still generates some of the code used in the
> > +		% C sharp interface, and so it doesn't have "mercury::"
> > +		% namespace qualifiers.
> 
> . not :: qualifier.

True, but I think this might not be necessary for much longer anyway.
I've fixed the comment and removed the 3 lines above it that aren't
doing anything useful.

> > -	method_c_code	:: bool,		% method contains c_code
> > +	method_c_code	:: maybe(foreign_language),
> > +						% method contains foreign code
> >  		% method-wide attributes (static)
> >  	arguments 	:: arguments_map, 	% The arguments 
> >  	method_name	:: member_name,		% current method name
> > @@ -182,7 +185,7 @@
> >  
> Not sure that the *_c_code names are still appropiate, maybe switch to
> foreign.

Good point, I forgot to come back and do this.

> Otherwise the diff looks fine.


Here is the incremental diff:

diff -u compiler/ml_code_gen.m compiler/ml_code_gen.m
--- compiler/ml_code_gen.m
+++ compiler/ml_code_gen.m
@@ -773,7 +773,7 @@
 :- import_module arg_info, llds, llds_out. % XXX needed for pragma foreign code
 :- import_module export, foreign. % XXX needed for pragma foreign code
 :- import_module hlds_pred, hlds_data.
-:- import_module goal_util, type_util, mode_util, builtin_ops.
+:- import_module goal_util, type_util, mode_util, builtin_ops, error_util.
 :- import_module passes_aux, modules.
 :- import_module globals, options.
 
@@ -2024,7 +2024,7 @@
 		CodeModel, OuterContext, MLDS_Decls, MLDS_Statements) -->
         (
                 { PragmaImpl = ordinary(C_Code, _MaybeContext) },
-                ml_gen_ordinary_pragma_foreign_code(CodeModel, Attributes,
+                ml_gen_ordinary_pragma_foreign_proc(CodeModel, Attributes,
                         PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
                         C_Code, OuterContext, MLDS_Decls, MLDS_Statements)
         ;
@@ -2032,7 +2032,7 @@
                         LocalVarsDecls, LocalVarsContext,
 			FirstCode, FirstContext, LaterCode, LaterContext,
 			_Treatment, SharedCode, SharedContext) },
-                ml_gen_nondet_pragma_c_code(CodeModel, Attributes,
+                ml_gen_nondet_pragma_foreign_proc(CodeModel, Attributes,
                         PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
 			OuterContext, LocalVarsDecls, LocalVarsContext,
 			FirstCode, FirstContext, LaterCode, LaterContext,
@@ -2041,7 +2041,7 @@
 		{ PragmaImpl = import(Name, HandleReturn, Vars, _Context) },
 		{ C_Code = string__append_list([HandleReturn, " ",
 				Name, "(", Vars, ");"]) },
-                ml_gen_ordinary_pragma_foreign_code(CodeModel, Attributes,
+                ml_gen_ordinary_pragma_foreign_proc(CodeModel, Attributes,
                         PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
                         C_Code, OuterContext, MLDS_Decls, MLDS_Statements)
         ).
@@ -2056,13 +2056,14 @@
 %
 %
 
-:- pred ml_gen_nondet_pragma_c_code(code_model, pragma_foreign_proc_attributes,
+:- pred ml_gen_nondet_pragma_foreign_proc(code_model,
+		pragma_foreign_proc_attributes,
 		pred_id, proc_id, list(prog_var),
 		list(maybe(pair(string, mode))), list(prog_type), prog_context,
 		string, maybe(prog_context), string, maybe(prog_context),
 		string, maybe(prog_context), string, maybe(prog_context),
 		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
-:- mode ml_gen_nondet_pragma_c_code(in, in, in, in, in, in, in, in,
+:- mode ml_gen_nondet_pragma_foreign_proc(in, in, in, in, in, in, in, in,
 		in, in, in, in, in, in, in, in, out, out, in, out) is det.
 
 	% For model_non pragma c_code,
@@ -2116,11 +2117,18 @@
 	% gets inlined and optimized away.  Of course we also need to
 	% #undef it afterwards.
 	%		
-ml_gen_nondet_pragma_c_code(CodeModel, Attributes,
+ml_gen_nondet_pragma_foreign_proc(CodeModel, Attributes,
 		PredId, _ProcId, ArgVars, ArgDatas, OrigArgTypes, Context,
 		LocalVarsDecls, LocalVarsContext, FirstCode, FirstContext,
 		LaterCode, LaterContext, SharedCode, SharedContext,
 		MLDS_Decls, MLDS_Statements) -->
+
+	{ foreign_language(Attributes, Lang) },
+	( { Lang = csharp } ->
+		{ sorry(this_file, "nondet pragma foreign_proc for C#") }
+	;
+		[]
+	),
 	%
 	% Combine all the information about the each arg
 	%
@@ -2252,47 +2260,47 @@
 	]) },
 	{ MLDS_Decls = ConvDecls }.
 
-:- pred ml_gen_ordinary_pragma_foreign_code(code_model, 
+:- pred ml_gen_ordinary_pragma_foreign_proc(code_model, 
 		pragma_foreign_proc_attributes,
 		pred_id, proc_id, list(prog_var),
 		list(maybe(pair(string, mode))), list(prog_type),
 		string, prog_context,
 		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
-:- mode ml_gen_ordinary_pragma_foreign_code(in, in, in, in, in, in, 
+:- mode ml_gen_ordinary_pragma_foreign_proc(in, in, in, in, in, in, 
 		in, in, in, out, out, in, out) is det.
 
-ml_gen_ordinary_pragma_foreign_code(CodeModel, Attributes,
+ml_gen_ordinary_pragma_foreign_proc(CodeModel, Attributes,
 		PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
 		Foreign_Code, Context, MLDS_Decls, MLDS_Statements) -->
 	{ foreign_language(Attributes, Lang) },
 	( { Lang = c },
-		ml_gen_ordinary_pragma_c_code(CodeModel, Attributes,
+		ml_gen_ordinary_pragma_c_proc(CodeModel, Attributes,
 		PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
 		Foreign_Code, Context, MLDS_Decls, MLDS_Statements)
 	; { Lang = managed_cplusplus },
-		ml_gen_ordinary_pragma_c_code(CodeModel, Attributes,
+		ml_gen_ordinary_pragma_c_proc(CodeModel, Attributes,
 		PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
 		Foreign_Code, Context, MLDS_Decls, MLDS_Statements)
 	; { Lang = csharp },
-		ml_gen_ordinary_pragma_csharp_code(CodeModel, Attributes,
+		ml_gen_ordinary_pragma_csharp_proc(CodeModel, Attributes,
 		PredId, ProcId, ArgVars, ArgDatas, OrigArgTypes,
 		Foreign_Code, Context, MLDS_Decls, MLDS_Statements)
 	).
 
-:- pred ml_gen_ordinary_pragma_csharp_code(code_model, 
+:- pred ml_gen_ordinary_pragma_csharp_proc(code_model, 
 		pragma_foreign_proc_attributes,
 		pred_id, proc_id, list(prog_var),
 		list(maybe(pair(string, mode))), list(prog_type),
 		string, prog_context,
 		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
-:- mode ml_gen_ordinary_pragma_csharp_code(in, in, in, in, in, in, 
+:- mode ml_gen_ordinary_pragma_csharp_proc(in, in, in, in, in, in, 
 		in, in, in, out, out, in, out) is det.
 
 	% For ordinary (not model_non) pragma foreign_code in C#,
 	% we generate a call to an out-of-line procedure that contains
 	% the user's code.
 
-ml_gen_ordinary_pragma_csharp_code(_CodeModel, Attributes,
+ml_gen_ordinary_pragma_csharp_proc(_CodeModel, Attributes,
 		_PredId, _ProcId, _ArgVars, _ArgDatas, _OrigArgTypes,
 		ForeignCode, Context, MLDS_Decls, MLDS_Statements) -->
 	{ foreign_language(Attributes, ForeignLang) },
@@ -2309,19 +2317,19 @@
 	{ MLDS_Decls = [] }.
 
 
-:- pred ml_gen_ordinary_pragma_c_code(code_model, 
+:- pred ml_gen_ordinary_pragma_c_proc(code_model, 
 		pragma_foreign_proc_attributes,
 		pred_id, proc_id, list(prog_var),
 		list(maybe(pair(string, mode))), list(prog_type),
 		string, prog_context,
 		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
-:- mode ml_gen_ordinary_pragma_c_code(in, in, in, in, in, in, 
+:- mode ml_gen_ordinary_pragma_c_proc(in, in, in, in, in, in, 
 		in, in, in, out, out, in, out) is det.
 
-	% For ordinary (not model_non) pragma c_code,
+	% For ordinary (not model_non) pragma c_proc,
 	% we generate code of the following form:
 	%
-	% model_det pragma_c_code:
+	% model_det pragma_c_proc:
 	%
 	%	#define MR_PROC_LABEL <procedure name>
 	% 	<declaration of locals needed for boxing/unboxing>
@@ -2337,7 +2345,7 @@
 	%	}
 	%	#undef MR_PROC_LABEL
 	%		
-	% model_semi pragma_c_code:
+	% model_semi pragma_c_proc:
 	%
 	%	#define MR_PROC_LABEL <procedure name>
 	% 	<declaration of locals needed for boxing/unboxing>
@@ -2376,7 +2384,7 @@
 	% different for targets other than C, e.g. when compiling to
 	% Java.
 	%
-ml_gen_ordinary_pragma_c_code(CodeModel, Attributes,
+ml_gen_ordinary_pragma_c_proc(CodeModel, Attributes,
 		PredId, _ProcId, ArgVars, ArgDatas, OrigArgTypes,
 		C_Code, Context, MLDS_Decls, MLDS_Statements) -->
 	%
@@ -3085,6 +3093,9 @@
 			{ error("model_non disj in model_det disjunction") }
 		)
 	).
+
+:- func this_file = string.
+this_file = "mlds_to_c.m".
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
diff -u compiler/ml_util.m compiler/ml_util.m
--- compiler/ml_util.m
+++ compiler/ml_util.m
@@ -294,9 +294,7 @@
 	Body = function(_, _, yes(FunctionBody)),
 	statement_contains_statement(FunctionBody, Statement),
 	Statement = mlds__statement(Stmt, _),
-	( 
-		Stmt = atomic(outline_target_code(ForeignLang, _, _))
-	).
+	Stmt = atomic(outline_target_code(ForeignLang, _, _)).
 
 defn_is_type(Defn) :-
 	Defn = mlds__defn(Name, _Context, _Flags, _Body),
diff -u compiler/mlds.m compiler/mlds.m
--- compiler/mlds.m
+++ compiler/mlds.m
@@ -1011,6 +1011,7 @@
 	;	mark_hp(mlds__lval)
 			% Tell the heap sub-system to store a marker
 			% (for later use in restore_hp/1 instructions)
+			% in the specified lval.
 			%
 			% It's OK for the target to treat this as a no-op,
 			% and probably that is what most targets will do.
@@ -1044,11 +1045,13 @@
 			% statements.
 	;	outline_target_code(
 				foreign_language,
-					% the foreign language of this code
+					% the foreign language this code is
+					% written in.
 				list(mlds__lval),
 					% where to store return value(s)
 				string
 					% the user's foreign language code
+					% fragment
 		)
 			% Do whatever is specified by the string, which
 			% can be any piece of code in the specified
diff -u mlds_to_csharp.m mlds_to_csharp.m
--- mlds_to_csharp.m
+++ mlds_to_csharp.m
@@ -28,12 +28,11 @@
 :- import_module globals, options, passes_aux.
 :- import_module builtin_ops, c_util, modules, tree.
 :- import_module hlds_pred. % for `pred_proc_id'.
-:- import_module prog_data, prog_out, llds_out.
+:- import_module prog_data, prog_out.
 :- import_module rtti, type_util, error_util.
 
 :- import_module ilds, ilasm, il_peephole.
 :- import_module ml_util, ml_code_util.
-:- import_module mlds_to_c. /* to output C code for .cpp files */
 :- use_module llds. /* for user_c_code */
 
 :- import_module bool, int, map, string, list, assoc_list, term, std_util.
@@ -85,30 +84,20 @@
 
 %-----------------------------------------------------------------------------%
 
-	% This section could very nearly be turned into a
-	% mlds_to_csharp module, which turns MLDS into managed C++.
-	% Note that it relies on quite a few predicates in mlds_to_il.
-	% XXX we should clean up the dependencies.
 	% XXX we don't output contexts for any of this.
 :- pred generate_c_code(mlds, io__state, io__state).
 :- mode generate_c_code(in, di, uo) is det.
 generate_c_code(MLDS) -->
 
 	{ MLDS = mlds(ModuleName, ForeignCode, _Imports, Defns) },
-	{ prog_out__sym_name_to_string(ModuleName, ModuleNameStr) },
 	{ ClassName = mlds_module_name_to_class_name(
 		mercury_module_name_to_mlds(ModuleName)) },
 
 	io__nl,
 	io__write_strings([
-		"// #using ""mercury_mcpp.dll""\n",
-		"// #using ""mercury_il.dll""\n",
-		"// #using """, ModuleNameStr, ".dll""\n",
-
-		% XXX We have to use the mercury namespace, as
-		% llds_out still generates some of the code used in the
-		% C sharp interface, and so it doesn't have "mercury::"
-		% namespace qualifiers.
+		% XXX We may be able to drop the mercury namespace soon,
+		% as there doesn't appear to be any llds generated code in
+		% the C# code anymore.
 		"using mercury;\n",
 		"\n"]),
 
diff -u compiler/mlds_to_il.m compiler/mlds_to_il.m
--- compiler/mlds_to_il.m
+++ compiler/mlds_to_il.m
@@ -140,9 +140,8 @@
 
 :- import_module ilasm, il_peephole.
 :- import_module ml_util, ml_code_util, error_util.
-:- import_module mlds_to_c. /* to output C code for .cpp files */
 :- import_module ml_type_gen.
-:- use_module llds. /* for user_c_code */
+:- use_module llds. /* for user_foreign_code */
 
 :- import_module bool, int, map, string, set, list, assoc_list, term.
 :- import_module library, require, counter.
@@ -157,20 +156,20 @@
 	module_name 	:: mlds_module_name,	% the module name
 	assembly_name 	:: assembly_name,	% the assembly name
 	imports 	:: mlds__imports,	% the imports
-	file_c_code	:: set(foreign_language), % file foreign code
+	file_foreign_langs :: set(foreign_language), % file foreign code
 	il_data_rep	:: il_data_rep,		% data representation.
 		% class-wide attributes (all accumulate)
 	alloc_instrs	:: instr_tree,		% .cctor allocation instructions
 	init_instrs	:: instr_tree,		% .cctor init instructions
 	classdecls	:: list(classdecl),	% class methods and fields 
 	has_main	:: bool,		% class contains main
-	class_c_code	:: set(foreign_language),% class foreign code
+	class_foreign_langs :: set(foreign_language),% class foreign code
 		% method-wide attributes (accumulating)
 	locals 		:: locals_map,		% The current locals
 	instr_tree 	:: instr_tree,		% The instruction tree (unused)
 	label_counter 	:: counter,		% the label counter
 	block_counter 	:: counter,		% the block counter
-	method_c_code	:: maybe(foreign_language),
+	method_foreign_lang :: maybe(foreign_language),
 						% method contains foreign code
 		% method-wide attributes (static)
 	arguments 	:: arguments_map, 	% The arguments 
@@ -196,9 +195,9 @@
 
 		% Generate code for all the methods in this module.
 	list__foldl(generate_method_defn, Defns, Info0, Info1),
-	( Info1 ^ method_c_code = yes(SomeLang) ->
-		Info2 = Info1 ^ file_c_code :=
-			set__insert(Info1 ^ file_c_code, SomeLang)
+	( Info1 ^ method_foreign_lang = yes(SomeLang) ->
+		Info2 = Info1 ^ file_foreign_langs :=
+			set__insert(Info1 ^ file_foreign_langs, SomeLang)
 	;
 		Info2 = Info1
 	),
@@ -220,7 +219,7 @@
 		% assembly in a separate step during the build (using
 		% AL.EXE).  
 
-	Info3 ^ file_c_code = ForeignLangs,
+	Info3 ^ file_foreign_langs = ForeignLangs,
 	(
 		SymName = qualified(unqualified("mercury"), _)
 	->
@@ -229,7 +228,7 @@
 	;
 		ThisAssembly = [assembly(AssemblyName)],
 			% If not in the library, but we have C code,
-			% declare the __c_code module as an assembly we
+			% declare the foreign module as an assembly we
 			% reference
 		list__map(mangle_foreign_code_module(ModuleName),
 			set__to_sorted_list(ForeignLangs),
@@ -965,8 +964,8 @@
 atomic_statement_to_il(outline_target_code(Lang, ReturnLvals, _Code),
 		Instrs) --> 
 	il_info_get_module_name(ModuleName),
-	( no =^ method_c_code  ->
-		^ method_c_code := yes(Lang),
+	( no =^ method_foreign_lang  ->
+		^ method_foreign_lang := yes(Lang),
 		{ mangle_foreign_code_module(ModuleName, Lang,
 			OutlineLangModuleName) },
 		{ ClassName = mlds_module_name_to_class_name(
@@ -1013,9 +1012,9 @@
 
 atomic_statement_to_il(inline_target_code(_Lang, _Code), node(Instrs)) --> 
 	il_info_get_module_name(ModuleName),
-	( no =^ method_c_code  ->
+	( no =^ method_foreign_lang  ->
 			% XXX we hardcode managed C++ here
-		^ method_c_code := yes(managed_cplusplus),
+		^ method_foreign_lang := yes(managed_cplusplus),
 		{ mangle_dataname_module(no, ModuleName, NewModuleName) },
 		{ ClassName = mlds_module_name_to_class_name(NewModuleName) },
 		signature(_, RetType, Params) =^ signature, 
@@ -2758,11 +2757,11 @@
 
 il_info_new_method(ILArgs, ILSignature, MethodName) -->
 	=(Info),
-	( yes(SomeLang) =^ method_c_code ->
-		^ file_c_code := 
-			set__insert(Info ^ file_c_code, SomeLang),
-		^ class_c_code := 
-			set__insert(Info ^ class_c_code, SomeLang)
+	( yes(SomeLang) =^ method_foreign_lang ->
+		^ file_foreign_langs := 
+			set__insert(Info ^ file_foreign_langs, SomeLang),
+		^ class_foreign_langs := 
+			set__insert(Info ^ class_foreign_langs, SomeLang)
 	;
 		[]
 	),
@@ -2770,7 +2769,7 @@
 	^ instr_tree := empty,
 	^ label_counter := counter__init(1),
 	^ block_counter := counter__init(1),
-	^ method_c_code := no,
+	^ method_foreign_lang := no,
 	^ arguments := ILArgs,
 	^ method_name := MethodName,
 	^ signature := ILSignature.
diff -u mlds_to_mcpp.m mlds_to_mcpp.m
--- mlds_to_mcpp.m
+++ mlds_to_mcpp.m
@@ -81,11 +81,8 @@
 
 %-----------------------------------------------------------------------------%
 
-	% This section could very nearly be turned into a
-	% mlds_to_managed_cpp module, which turns MLDS into managed C++.
-	% Note that it relies on quite a few predicates in mlds_to_il.
-	% XXX we should clean up the dependencies.
-	% XXX we don't output contexts for any of this.
+	% XXX we don't output contexts correctly -- we need to write out the
+	% original context at the end of the user's MC++ code.
 :- pred generate_mcplusplus_code(mlds, io__state, io__state).
 :- mode generate_mcplusplus_code(in, di, uo) is det.
 generate_mcplusplus_code(MLDS) -->

-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
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