[m-rev.] for review: mix mercury procs with foreign_proc procs
Tyson Dowd
trd at bacon.miscrit.be
Tue Jul 31 01:17:36 AEST 2001
Hi,
This should make it easier to avoid writing foreign_procs for all those
"hand-coded for speed" things in the library.
(I'm bootstrapping this at the moment, but I don't think there are any
problems left -- but I will know in a few hours).
===================================================================
Estimated hours taken: 16
Branches: main
Allow foreign_proc clauses to replace Mercury definitions.
Or alternately viewed, allow the compiler to fall back on Mercury
definitions of procedures if a suitable foreign_proc clause is unavailable.
(This is only possible with mode-specific Mercury procedures).
compiler/hlds_pred.m:
Add a field to clauses_info to record whether we have any
foreign_proc clauses.
compiler/make_hlds.m:
Record errors if we try to add a foreign_proc that will replace
a Mercury clause that is not mode-specific, or if we try to add
a non-mode specific Mercury clause that will replace a foreign
proc.
Otherwise, we allow a foreign_proc to replace mode-specific
Mercury clauses.
Set the goal type for potentially mixed mercury/foreign_proc
clauses as "clauses".
Add Mercury clauses only for modes not yet covered by
foreign_proc clauses. Checking this could be a performance
problem so we check the have_foreign_clauses boolean so
that we don't need to search all the clauses every time we add a
Mercury clause (only when there are foreign_clauses to search for).
Traverse clauses and decide upon our course of action (add
new foreign_proc clause, ignore new foreign_proc clause, replace
existing clause, split existing clause and add new clause)
all in one go.
compiler/clause_to_proc.m:
compiler/higher_order.m:
compiler/hlds_out.m:
compiler/polymorphism.m:
compiler/unify_proc.m:
Handle have_foreign_clauses field in clauses_info.
doc/reference_manual.texi:
doc/user_guide.texi:
Document the ability to mix mode-specific Mercury and
foreign_proc clauses.
Document the behaviour of the implementation when it comes to
specific backends (that is, the preferred foreign languages list).
Also a few fixes from fjh's review that didn't quite make it
into the review.
Index: compiler/clause_to_proc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/clause_to_proc.m,v
retrieving revision 1.30
diff -u -r1.30 clause_to_proc.m
--- compiler/clause_to_proc.m 2001/07/20 14:13:20 1.30
+++ compiler/clause_to_proc.m 2001/07/30 15:09:12
@@ -143,7 +143,7 @@
copy_clauses_to_proc(ProcId, ClausesInfo, Proc0, Proc) :-
ClausesInfo = clauses_info(VarSet, _, _, VarTypes, HeadVars, Clauses,
- TI_VarMap, TCI_VarMap),
+ TI_VarMap, TCI_VarMap, _),
select_matching_clauses(Clauses, ProcId, MatchingClauses),
get_clause_goals(MatchingClauses, GoalList),
( GoalList = [SingleGoal] ->
Index: compiler/higher_order.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/higher_order.m,v
retrieving revision 1.90
diff -u -r1.90 higher_order.m
--- compiler/higher_order.m 2001/07/13 12:15:50 1.90
+++ compiler/higher_order.m 2001/07/30 15:09:13
@@ -2500,7 +2500,7 @@
% hlds dumps if it's filled in.
ClausesInfo = clauses_info(EmptyVarSet, EmptyVarTypes,
EmptyTVarNameMap, EmptyVarTypes, [], [],
- EmptyTIMap, EmptyTCIMap),
+ EmptyTIMap, EmptyTCIMap, no),
pred_info_init(PredModule, SymName, Arity, ArgTVarSet, ExistQVars,
Types, true, Context, ClausesInfo, Status, MarkerList, GoalType,
PredOrFunc, ClassContext, EmptyProofs, Owner, NewPredInfo0),
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_out.m,v
retrieving revision 1.265
diff -u -r1.265 hlds_out.m
--- compiler/hlds_out.m 2001/07/24 10:47:13 1.265
+++ compiler/hlds_out.m 2001/07/30 15:09:15
@@ -792,7 +792,7 @@
[]
),
{ ClausesInfo = clauses_info(VarSet, _, _, VarTypes, HeadVars, Clauses,
- TypeInfoMap, TypeClassInfoMap) },
+ TypeInfoMap, TypeClassInfoMap, _) },
( { string__contains_char(Verbose, 'C') } ->
hlds_out__write_indent(Indent),
io__write_string("% pred id: "),
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.98
diff -u -r1.98 hlds_pred.m
--- compiler/hlds_pred.m 2001/07/20 14:13:29 1.98
+++ compiler/hlds_pred.m 2001/07/30 15:09:16
@@ -147,7 +147,10 @@
% fields are computed
% by polymorphism.m
clause_type_info_varmap :: type_info_varmap,
- clause_typeclass_info_varmap :: typeclass_info_varmap
+ clause_typeclass_info_varmap :: typeclass_info_varmap,
+ have_foreign_clauses :: bool
+ % do we have foreign
+ % language clauses?
).
:- type vartypes == map(prog_var, type).
@@ -969,8 +972,10 @@
% The empty list of clauses is a little white lie.
Clauses = [],
map__init(TVarNameMap),
+ HasForeignClauses = no,
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap,
- VarTypes, HeadVars, Clauses, TypeInfoMap, TypeClassInfoMap),
+ VarTypes, HeadVars, Clauses, TypeInfoMap, TypeClassInfoMap,
+ HasForeignClauses),
map__init(ClassProofs),
term__vars_list(Types, TVars),
list__delete_elems(TVars, ExistQVars, HeadTypeParams),
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.377
diff -u -r1.377 make_hlds.m
--- compiler/make_hlds.m 2001/07/23 12:22:05 1.377
+++ compiler/make_hlds.m 2001/07/30 15:09:19
@@ -985,8 +985,10 @@
map__init(TI_VarMap),
map__init(TCI_VarMap),
map__init(TVarNameMap),
+ HasForeignClauses = no,
Clauses = clauses_info(ArgVarSet, VarTypes0, TVarNameMap,
- VarTypes0, Args, [Clause], TI_VarMap, TCI_VarMap),
+ VarTypes0, Args, [Clause], TI_VarMap, TCI_VarMap,
+ HasForeignClauses),
pred_info_get_markers(PredInfo0, Markers),
map__init(Proofs),
@@ -2949,8 +2951,10 @@
map__init(TVarNameMap),
map__init(TI_VarMap),
map__init(TCI_VarMap),
+ HasForeignClauses = no,
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap, VarTypes,
- HeadVars, ClauseList, TI_VarMap, TCI_VarMap),
+ HeadVars, ClauseList, TI_VarMap, TCI_VarMap,
+ HasForeignClauses),
pred_info_set_clauses_info(PredInfo0, ClausesInfo, PredInfo).
%-----------------------------------------------------------------------------%
@@ -3579,15 +3583,20 @@
PredInfo1 = PredInfo0
},
(
- { pred_info_get_goal_type(PredInfo1, pragmas) }
- ->
+ { pred_info_get_goal_type(PredInfo1, pragmas) },
+ { get_mode_annotations(Args, _, empty, ModeAnnotations) },
+ { ModeAnnotations = empty ; ModeAnnotations = none }
+ ->
+ % If we have a pragma foreign_proc for this procedure
+ % already, and we are trying to add a non-mode specific
+ % Mercury clause
{ module_info_incr_errors(ModuleInfo1, ModuleInfo) },
prog_out__write_context(Context),
- io__write_string("Error: clause for "),
+ io__write_string("Error: non mode-specific clause for "),
hlds_out__write_simple_call_id(PredOrFunc, PredName/Arity),
io__write_string("\n"),
prog_out__write_context(Context),
- io__write_string(" with `:- pragma c_code' declaration preceding.\n"),
+ io__write_string(" with `:- pragma foreign_proc' declaration preceding.\n"),
{ Info = Info0 }
;
%
@@ -3869,8 +3878,10 @@
map__init(TVarNameMap),
map__init(TI_VarMap),
map__init(TCI_VarMap),
+ HasForeignClauses = no,
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap, VarTypes,
- HeadVars, [IntroducedClause], TI_VarMap, TCI_VarMap).
+ HeadVars, [IntroducedClause], TI_VarMap, TCI_VarMap,
+ HasForeignClauses).
% handle the arbitrary clauses syntax
produce_instance_method_clauses(clauses(InstanceClauses), PredOrFunc,
@@ -4161,20 +4172,23 @@
io__write_string(".\n"),
{ Info = Info0 }
;
- { pred_info_get_goal_type(PredInfo1, clauses) }
+ { pred_info_get_goal_type(PredInfo1, clauses) },
+ { pred_info_clauses_info(PredInfo1, CInfo) },
+ { clauses_info_clauses(CInfo, ClauseList) },
+ { list__member(clause([], _, mercury, _), ClauseList) }
+
->
{ module_info_incr_errors(ModuleInfo1, ModuleInfo) },
prog_out__write_context(Context),
- io__write_string("Error: `:- pragma foreign_code' (or `pragma c_code')\n"),
+ io__write_string("Error: `:- pragma foreign_proc' (or `pragma c_code')\n"),
prog_out__write_context(Context),
io__write_string("declaration for "),
hlds_out__write_simple_call_id(PredOrFunc, PredName/Arity),
io__write_string("\n"),
prog_out__write_context(Context),
- io__write_string(" with preceding clauses.\n"),
+ io__write_string(" with preceding non-mode specific clauses.\n"),
{ Info = Info0 }
;
-
% Don't add clauses for foreign languages other
% than the ones we can generate code for.
{ not list__member(PragmaForeignLanguage, BackendForeignLangs) }
@@ -4202,8 +4216,15 @@
ModuleInfo2, Info0, Info),
{ pred_info_set_clauses_info(PredInfo1, Clauses,
PredInfo2) },
- { pred_info_set_goal_type(PredInfo2, pragmas,
- PredInfo) },
+ % If we have already seen Mercury
+ % clauses for this, use Mercury clauses
+ % as an appoximation for the goal type.
+ { pred_info_get_goal_type(PredInfo2, clauses) ->
+ PredInfo = PredInfo2
+ ;
+ pred_info_set_goal_type(PredInfo2, pragmas,
+ PredInfo)
+ },
{ map__det_update(Preds0, PredId, PredInfo, Preds) },
{ predicate_table_set_preds(PredicateTable1, Preds,
PredicateTable) },
@@ -5143,8 +5164,9 @@
varset__init(VarSet),
map__init(TI_VarMap),
map__init(TCI_VarMap),
+ HasForeignClauses = no,
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap, VarTypes,
- HeadVars, [], TI_VarMap, TCI_VarMap).
+ HeadVars, [], TI_VarMap, TCI_VarMap, HasForeignClauses).
:- pred clauses_info_init(int::in, clauses_info::out) is det.
@@ -5155,8 +5177,10 @@
make_n_fresh_vars("HeadVar__", Arity, VarSet0, HeadVars, VarSet),
map__init(TI_VarMap),
map__init(TCI_VarMap),
+ HasForeignClauses = no,
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap,
- VarTypes, HeadVars, [], TI_VarMap, TCI_VarMap).
+ VarTypes, HeadVars, [], TI_VarMap, TCI_VarMap,
+ HasForeignClauses).
:- pred clauses_info_add_clause(clauses_info::in,
list(proc_id)::in, prog_varset::in, tvarset::in,
@@ -5167,13 +5191,13 @@
module_info::in, module_info::out, qual_info::in,
qual_info::out, io__state::di, io__state::uo) is det.
-clauses_info_add_clause(ClausesInfo0, ModeIds, CVarSet, TVarSet0,
+clauses_info_add_clause(ClausesInfo0, ModeIds0, CVarSet, TVarSet0,
Args, Body, Context, Status, PredOrFunc, Arity, IsAssertion,
Goal, VarSet, TVarSet, ClausesInfo, Warnings, Module0, Module,
Info0, Info) -->
{ ClausesInfo0 = clauses_info(VarSet0, ExplicitVarTypes0, TVarNameMap0,
InferredVarTypes, HeadVars, ClauseList0,
- TI_VarMap, TCI_VarMap) },
+ TI_VarMap, TCI_VarMap, HasForeignClauses) },
{ ClauseList0 = [] ->
% Create the mapping from type variable name, used to
% rename type variables occurring in explicit type
@@ -5209,17 +5233,46 @@
{ FoundError = no },
{ Goal = Goal0 },
+ % If we have foreign clauses, we should only
+ % add this clause for modes *not* covered by the
+ % foreign clauses.
+ { HasForeignClauses = yes ->
+ ForeignModeIds = list__condense(list__filter_map(
+ (func(C) = ProcIds is semidet :-
+ C = clause(ProcIds, _, ClauseLang, _),
+ not ClauseLang = mercury
+ ),
+ ClauseList0)),
+ ModeIds = list__delete_elems(ModeIds0, ForeignModeIds),
+ ( ModeIds = [] ->
+ ClauseList = ClauseList0
+ ;
+ % XXX we should avoid append - this gives O(N*N)
+ list__append(ClauseList0,
+ [clause(ModeIds, Goal, mercury,
+ Context)], ClauseList)
+ )
+ ;
% XXX we should avoid append - this gives O(N*N)
- { list__append(ClauseList0, [clause(ModeIds, Goal, mercury,
- Context)], ClauseList) },
+ list__append(ClauseList0, [clause(ModeIds0, Goal,
+ mercury, Context)], ClauseList)
+ },
{ qual_info_get_var_types(Info, ExplicitVarTypes) },
{ ClausesInfo = clauses_info(VarSet, ExplicitVarTypes,
TVarNameMap, InferredVarTypes, HeadVars,
- ClauseList, TI_VarMap, TCI_VarMap) }
+ ClauseList, TI_VarMap, TCI_VarMap,
+ HasForeignClauses) }
).
%-----------------------------------------------------------------------------
+:- type foreign_proc_action
+ ---> ignore
+ ; add
+ ; split_add(int, clause)
+ ; replace(int).
+
+
% Add the pragma_foreign_proc goal to the clauses_info for this procedure.
% To do so, we must also insert unifications between the variables in the
% pragma foreign_proc declaration and the head vars of the pred. Also
@@ -5239,85 +5292,88 @@
ModuleInfo, Info0, Info) -->
{ ClausesInfo0 = clauses_info(VarSet0, VarTypes, TVarNameMap,
- VarTypes1, HeadVars, ClauseList, TI_VarMap, TCI_VarMap) },
+ VarTypes1, HeadVars, ClauseList, TI_VarMap, TCI_VarMap,
+ _HasForeignClauses) },
% Find all the exising clauses for this mode, and
% extract their implementation language and clause number
% (that is, their index in the list).
{ foreign_language(Attributes0, NewLang) },
- { list__foldl2(
- (pred(C::in, Res0::in, Res::out, N0::in, N::out) is det :-
- (
- C = clause(ProcIds, _, ClauseLang, _),
- list__member(ProcId, ProcIds)
- ->
- Res = [ClauseLang - N0 | Res0],
- N = N0 + 1
- ;
- Res = Res0,
- N = N0 + 1
- )
- ), ClauseList, [], LangClauses, 1, _) },
globals__io_get_globals(Globals),
globals__io_get_target(Target),
- % Figure out what to do with this new clause.
- % We can either add it to the list of clauses, ignore it,
- % or replace the existing clause with it.
+
+ % We traverse the clauses, and decide which action to perform.
%
- % We create a closure called UpdateClauses which does the
- % appropriate action at the end of this predicate.
+ % If there are no clauses, we will simply add this clause.
%
- % In the rare case of multiple foreign language
- % implementations we might do some unnecessary work only
- % to ignore the new clause.
- {
- % no clauses -- add it
- LangClauses = [],
- UpdateClauses = (pred(NewCl::in, Cs::out) is det :-
- Cs = [NewCl|ClauseList])
- ;
- % was implemented in Mercury, do nothing
- % XXX if we want to make Mercury implementations a fallback
- % we should consider making this a replace instead of an
- % ignore.
- LangClauses = [mercury - _ | Rest],
- ( Rest = [] ->
- UpdateClauses = (pred(_NewCl::in, Cs::out) is det :-
- Cs = ClauseList)
- ;
- error("unexpected: multiple matches for foreign " ++
- "language clauses")
- )
+ % If there are matching foreign_proc clauses for this proc_id,
+ % we will either replace them or ignore the new clause
+ % (depending on the preference of the two foreign languages).
+ %
+ % If there is a matching Mercury clause for this proc_id, we
+ % will either
+ % - replace it if there is only one matching mode in its
+ % proc_id list.
+ % - remove the matching proc_id from its proc_id list,
+ % and add this clause as a new clause for this mode.
- ;
- LangClauses = [ForeignLang - ClauseNumber | Rest],
- ForeignLang = foreign_language(OldLang),
- ( Rest = [] ->
- PreferNewLang = foreign__prefer_foreign_language(
- Globals, Target, OldLang, NewLang),
+
+ { list__foldl2(
+ (pred(C::in, Action0::in, Action::out, N0::in, N::out) is det :-
+ C = clause(ProcIds, B, ClauseLang, D),
(
- % This language is preferred to the old
- % language, so we should replace it
- PreferNewLang = yes ->
- UpdateClauses =
- (pred(NewCl::in, Cs::out) is det :-
- list__replace_nth_det(ClauseList,
- ClauseNumber, NewCl, Cs))
+ ClauseLang = mercury,
+ ProcIds = [ProcId]
+ ->
+ Action = replace(N0)
;
- % Just ignore it.
- UpdateClauses =
- (pred(_NewCl::in, Cs::out) is det :-
- Cs = ClauseList)
- )
- ;
- error("unexpected: multiple matches for foreign " ++
- "language clauses")
+ ClauseLang = mercury,
+ list__delete_first(ProcIds, ProcId,
+ MercuryProcIds)
+ ->
+ NewMercuryClause = clause(
+ MercuryProcIds, B, ClauseLang, D),
+ Action = split_add(N0, NewMercuryClause)
+ ;
+ ClauseLang = foreign_language(OldLang),
+ list__member(ProcId, ProcIds)
+ ->
+ PreferNewLang =
+ foreign__prefer_foreign_language(
+ Globals, Target, OldLang,
+ NewLang),
+ % This language is preferred to the old
+ % language, so we should replace it
+ ( PreferNewLang = yes ->
+ Action = replace(N0)
+ ;
+ % Just ignore it.
+ Action = ignore
+ )
+ ;
+ Action = Action0
+ ),
+ N = N0 + 1
+ ), ClauseList, add, FinalAction, 1, _) },
+
+ { UpdateClauses = (pred(NewCl::in, Cs::out) is det :-
+ ( FinalAction = ignore,
+ Cs = ClauseList
+ ; FinalAction = add,
+ Cs = [NewCl|ClauseList]
+ ; FinalAction = replace(X),
+ list__replace_nth_det(ClauseList, X, NewCl, Cs)
+ ; FinalAction = split_add(X, Clause),
+ list__replace_nth_det(ClauseList, X, Clause, Cs1),
+ Cs = [NewCl|Cs1]
)
- },
-
+ ) },
+
+
+
globals__io_get_backend_foreign_languages(BackendForeignLanguages),
{
pragma_get_vars(PVars, Args0),
@@ -5409,9 +5465,10 @@
NewClause = clause([ProcId], HldsGoal,
foreign_language(NewLang), Context),
UpdateClauses(NewClause, NewClauseList),
+ HasForeignClauses = yes,
ClausesInfo = clauses_info(VarSet, VarTypes, TVarNameMap,
VarTypes1, HeadVars, NewClauseList,
- TI_VarMap, TCI_VarMap)
+ TI_VarMap, TCI_VarMap, HasForeignClauses)
}
).
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.215
diff -u -r1.215 polymorphism.m
--- compiler/polymorphism.m 2001/07/20 14:14:18 1.215
+++ compiler/polymorphism.m 2001/07/30 15:09:21
@@ -566,7 +566,8 @@
map__init(TVarNameMap), % This is only used while adding the clauses.
ClausesInfo = clauses_info(VarSet, ExplicitVarTypes, TVarNameMap,
VarTypes, HeadVars, Clauses,
- TypeInfoMap, TypeClassInfoMap).
+ TypeInfoMap, TypeClassInfoMap,
+ ClausesInfo0 ^ have_foreign_clauses).
:- pred polymorphism__process_clause(pred_info, list(prog_var), list(prog_var),
list(tvar), list(prog_var), list(prog_var),
Index: compiler/unify_proc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unify_proc.m,v
retrieving revision 1.94
diff -u -r1.94 unify_proc.m
--- compiler/unify_proc.m 2001/07/20 14:14:30 1.94
+++ compiler/unify_proc.m 2001/07/30 15:09:21
@@ -694,8 +694,10 @@
map__init(TVarNameMap),
map__init(TI_VarMap),
map__init(TCI_VarMap),
+ HasForeignClauses = yes,
ClauseInfo = clauses_info(VarSet, Types, TVarNameMap,
- Types, Args, Clauses, TI_VarMap, TCI_VarMap).
+ Types, Args, Clauses, TI_VarMap, TCI_VarMap,
+ HasForeignClauses).
:- pred unify_proc__generate_unify_clauses(hlds_type_body, prog_var, prog_var,
prog_context, list(clause), unify_proc_info, unify_proc_info).
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.212
diff -u -r1.212 reference_manual.texi
--- doc/reference_manual.texi 2001/07/25 15:49:53 1.212
+++ doc/reference_manual.texi 2001/07/30 15:09:26
@@ -4785,6 +4785,13 @@
(If you use this form, and the C code @emph{does} invoke Mercury code,
then the behaviour is undefined --- your program may misbehave or crash.)
+It is possible to provide both a Mercury definition, and
+a foreign_proc definition for a procedure.
+All such Mercury definitions must use mode-specific clauses (even if
+there is only a single mode for the predicate).
+Suitable foreign_proc definitions will be used first, but
+if no suitable foreign_proc definition is found, the Mercury definition
+will be used instead.
@node Foreign code attributes
@subsection Foreign code attributes
@@ -4910,6 +4917,8 @@
All Mercury implementations should support interfacing with C.
The set of other languages supported is implementation-defined.
+A suitable compiler or assembler for the foreign language
+must be available on the system.
The University of Melbourne Mercury implementation supports
interfacing with the following languages:
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.265
diff -u -r1.265 user_guide.texi
--- doc/user_guide.texi 2001/07/25 14:13:35 1.265
+++ doc/user_guide.texi 2001/07/30 15:09:30
@@ -5697,6 +5697,16 @@
@node Foreign language interface
@chapter Foreign language interface
+If the compiler generates code for a particular target for which
+there are multiple applicable foreign languages, it will choose the
+foreign languages according to a builtin ordering.
+
+If the language is not available for a particular backend, it will be
+ignored.
+
+Mercury clauses will be used if there are no suitable foreign_proc
+clauses for a particular procedure.
+
@table @asis
@item @samp{C}
@@ -5704,32 +5714,23 @@
or assembler.
Only available on backends that compile to C or assembler.
- at item @samp{Managed C++}
-Managed Extensions for C++ is a language based on C++ that
-provide support for writing .NET components, by adding extra
-keywords and syntax.
-
-This is the default foreign language on all backends which compile to IL.
-In the current implementation, this is only available on backends that
-compile to IL.
-Requires a Managed Extensions for C++ compiler installed.
-
-
@item @samp{C#}
Only available on backends that compile to IL.
-Requires a C# compiler installed.
-To use it pass mmc @samp{--use-foreign-language csharp} and
- at samp{--backend-foreign-language csharp}.
+This is the second preferred foreign language for IL code generation.
@item @samp{IL}
IL (or CIL) is the intermediate language of the .NET Common Language
Runtime.
+Only available on backends that compile to IL.
+This is the preferred foreign language for IL code generation.
-Use the string "IL" to set the foreign language to IL.
+ at item @samp{Managed C++}
+Managed Extensions for C++ is a language based on C++ that
+provide support for writing .NET components, by adding extra
+keywords and syntax.
Only available on backends that compile to IL.
-Requires an IL assembler installed.
-To use it pass mmc @samp{--use-foreign-language il} and
- at samp{--backend-foreign-language il}.
+This is the third preferred foreign language for IL code generation.
+
@end table
--------------------------------------------------------------------------
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