[m-rev.] for review: mlds__function_body
Tyson Dowd
trd at cs.mu.OZ.AU
Fri Jul 13 01:32:31 AEST 2001
Hi,
===================================================================
Estimated hours taken: 0.75
Branches: main
Use a new mlds__function_body type to represent function bodies, as the old
usage of maybe/1 was error prone ("no" meant the function had been declared
using :- pragma external, not merely that the body was missing).
compiler/mlds.m:
Add mlds__function_body type.
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_optimize.m:
compiler/ml_tailcall.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_csharp.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
compiler/mlds_to_java.m:
compiler/mlds_to_mcpp.m:
Handle this change.
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.91
diff -u -r1.91 ml_code_gen.m
--- compiler/ml_code_gen.m 2001/07/11 13:52:34 1.91
+++ compiler/ml_code_gen.m 2001/07/12 14:50:48
@@ -1050,7 +1050,7 @@
% corresponding definition, making sure that the function
% is declared as `extern' rather than `static'.
%
- MaybeStatement = no,
+ FunctionBody = external,
ExtraDefns = []
;
% Set up the initial success continuation, if any.
@@ -1100,10 +1100,10 @@
MLDS_Decls = list__append(MLDS_LocalVars, MLDS_Decls0),
MLDS_Statement = ml_gen_block(MLDS_Decls, MLDS_Statements,
Context),
- MaybeStatement = yes(MLDS_Statement)
+ FunctionBody = defined_here(MLDS_Statement)
),
MLDS_ProcDefnBody = mlds__function(yes(proc(PredId, ProcId)),
- MLDS_Params, MaybeStatement).
+ MLDS_Params, FunctionBody).
% for model_det and model_semi procedures,
% figure out which output variables are returned by
Index: compiler/ml_code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_util.m,v
retrieving revision 1.41
diff -u -r1.41 ml_code_util.m
--- compiler/ml_code_util.m 2001/07/11 10:20:11 1.41
+++ compiler/ml_code_util.m 2001/07/12 14:50:49
@@ -921,7 +921,8 @@
%
{ DeclFlags = ml_gen_label_func_decl_flags },
{ MaybePredProcId = no },
- { FuncDefn = function(MaybePredProcId, FuncParams, yes(Statement)) },
+ { FuncDefn = function(MaybePredProcId, FuncParams,
+ defined_here(Statement)) },
{ Func = mlds__defn(FuncName, mlds__make_context(Context), DeclFlags,
FuncDefn) }.
@@ -1775,7 +1776,7 @@
{
Defn = mlds__defn(function(PredLabel, ProcId,
- yes(SeqNum), _), _, _, function(_, _, yes(_)))
+ yes(SeqNum), _), _, _, function(_, _, defined_here(_)))
->
% We call the proxy function.
QualProcLabel = qual(MLDS_Module, PredLabel - ProcId),
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.33
diff -u -r1.33 ml_elim_nested.m
--- compiler/ml_elim_nested.m 2001/07/11 12:45:18 1.33
+++ compiler/ml_elim_nested.m 2001/07/12 14:50:49
@@ -161,7 +161,8 @@
mlds__defn) = list(mlds__defn).
ml_elim_nested_defns(ModuleName, Globals, OuterVars, Defn0) = FlatDefns :-
Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
- ( DefnBody0 = mlds__function(PredProcId, Params, yes(FuncBody0)) ->
+ ( DefnBody0 = mlds__function(PredProcId, Params,
+ defined_here(FuncBody0)) ->
EnvName = ml_env_name(Name),
% XXX this should be optimized to generate
% EnvTypeName from just EnvName
@@ -265,7 +266,8 @@
HoistedDefns = HoistedDefns0
)
),
- DefnBody = mlds__function(PredProcId, Params, yes(FuncBody)),
+ DefnBody = mlds__function(PredProcId, Params,
+ defined_here(FuncBody)),
Defn = mlds__defn(Name, Context, Flags, DefnBody),
FlatDefns = list__append(HoistedDefns, [Defn])
;
@@ -387,7 +389,7 @@
Stmt = mlds__statement(block([], []), Context),
Ctor = mlds__function(no, func_params([], []),
- yes(Stmt)),
+ defined_here(Stmt)),
CtorFlags = init_decl_flags(public, per_instance, non_virtual,
overridable, modifiable, concrete),
@@ -486,7 +488,8 @@
ml_insert_init_env(TypeName, ModuleName, Globals, Defn0, Defn, Init0, Init) :-
Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
(
- DefnBody0 = mlds__function(PredProcId, Params, yes(FuncBody0)),
+ DefnBody0 = mlds__function(PredProcId, Params,
+ defined_here(FuncBody0)),
statement_contains_var(FuncBody0, qual(ModuleName,
mlds__var_name("env_ptr", no)))
->
@@ -499,7 +502,8 @@
Globals, EnvPtrDecl, InitEnvPtr),
FuncBody = mlds__statement(block([EnvPtrDecl],
[InitEnvPtr, FuncBody0]), Context),
- DefnBody = mlds__function(PredProcId, Params, yes(FuncBody)),
+ DefnBody = mlds__function(PredProcId, Params,
+ defined_here(FuncBody)),
Defn = mlds__defn(Name, Context, Flags, DefnBody),
Init = yes
;
@@ -671,6 +675,7 @@
%
% flatten_maybe_statement:
+% flatten_function_body:
% flatten_statements:
% flatten_statement:
% Recursively process the statement(s), calling fixup_var on every
@@ -679,6 +684,14 @@
% variables and nested functions).
%
+:- pred flatten_function_body(function_body, function_body,
+ elim_info, elim_info).
+:- mode flatten_function_body(in, out, in, out) is det.
+
+flatten_function_body(external, external) --> [].
+flatten_function_body(defined_here(Statement0), defined_here(Statement)) -->
+ flatten_statement(Statement0, Statement).
+
:- pred flatten_maybe_statement(maybe(mlds__statement), maybe(mlds__statement),
elim_info, elim_info).
:- mode flatten_maybe_statement(in, out, in, out) is det.
@@ -813,7 +826,7 @@
%
% recursively flatten the nested function
%
- flatten_maybe_statement(FuncBody0, FuncBody),
+ flatten_function_body(FuncBody0, FuncBody),
%
% mark the function as private / one_copy,
@@ -1188,6 +1201,7 @@
% defn_contains_defn:
% defn_body_contains_defn:
% maybe_statement_contains_defn:
+% function_body_contains_defn:
% statements_contains_defn:
% statement_contains_defn:
% Nondeterministically return all the definitions contained
@@ -1212,9 +1226,9 @@
:- mode defn_body_contains_defn(in, out) is nondet.
% defn_body_contains_defn(mlds__data(_Type, _Initializer), _Defn) :- fail.
-defn_body_contains_defn(mlds__function(_PredProcId, _Params, MaybeBody),
+defn_body_contains_defn(mlds__function(_PredProcId, _Params, FunctionBody),
Name) :-
- maybe_statement_contains_defn(MaybeBody, Name).
+ function_body_contains_defn(FunctionBody, Name).
defn_body_contains_defn(mlds__class(ClassDefn), Name) :-
ClassDefn = mlds__class_defn(_Kind, _Imports, _Inherits, _Implements,
CtorDefns, FieldDefns),
@@ -1236,6 +1250,13 @@
maybe_statement_contains_defn(yes(Statement), Defn) :-
statement_contains_defn(Statement, Defn).
+:- pred function_body_contains_defn(function_body, mlds__defn).
+:- mode function_body_contains_defn(in, out) is nondet.
+
+% function_body_contains_defn(external, _Defn) :- fail.
+function_body_contains_defn(defined_here(Statement), Defn) :-
+ statement_contains_defn(Statement, Defn).
+
:- pred statement_contains_defn(mlds__statement, mlds__defn).
:- mode statement_contains_defn(in, out) is nondet.
@@ -1315,7 +1336,7 @@
% defns_contains_var:
% defn_contains_var:
% defn_body_contains_var:
-% maybe_statement_contains_var:
+% function_body_contains_var:
% statements_contains_var:
% statement_contains_var:
% trail_op_contains_var:
@@ -1342,9 +1363,9 @@
defn_body_contains_var(mlds__data(_Type, Initializer), Name) :-
initializer_contains_var(Initializer, Name).
-defn_body_contains_var(mlds__function(_PredProcId, _Params, MaybeBody),
+defn_body_contains_var(mlds__function(_PredProcId, _Params, FunctionBody),
Name) :-
- maybe_statement_contains_var(MaybeBody, Name).
+ function_body_contains_var(FunctionBody, Name).
defn_body_contains_var(mlds__class(ClassDefn), Name) :-
ClassDefn = mlds__class_defn(_Kind, _Imports, _Inherits, _Implements,
CtorDefns, FieldDefns),
@@ -1357,6 +1378,13 @@
% maybe_statement_contains_var(no, _) :- fail.
maybe_statement_contains_var(yes(Statement), Name) :-
+ statement_contains_var(Statement, Name).
+
+:- pred function_body_contains_var(function_body, mlds__var).
+:- mode function_body_contains_var(in, in) is semidet.
+
+% function_body_contains_var(external, _) :- fail.
+function_body_contains_var(defined_here(Statement), Name) :-
statement_contains_var(Statement, Name).
:- pred statements_contains_var(mlds__statements, mlds__var).
Index: compiler/ml_optimize.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_optimize.m,v
retrieving revision 1.11
diff -u -r1.11 ml_optimize.m
--- compiler/ml_optimize.m 2001/07/09 15:55:04 1.11
+++ compiler/ml_optimize.m 2001/07/12 14:50:50
@@ -78,7 +78,7 @@
OptInfo = opt_info(Globals, ModuleName, Name, Params, Context),
FuncBody1 = optimize_func(OptInfo, FuncBody0),
- FuncBody = optimize_in_maybe_statement(OptInfo, FuncBody1),
+ FuncBody = optimize_in_function_body(OptInfo, FuncBody1),
DefnBody = mlds__function(PredProcId, Params, FuncBody),
Defn = mlds__defn(Name, Context, Flags, DefnBody)
@@ -99,6 +99,13 @@
Defn = mlds__defn(Name, Context, Flags, DefnBody)
).
+:- func optimize_in_function_body(opt_info, function_body) = function_body.
+
+optimize_in_function_body(_, external) = external.
+optimize_in_function_body(OptInfo, defined_here(Statement0)) =
+ defined_here(Statement) :-
+ Statement = optimize_in_statement(OptInfo, Statement0).
+
:- func optimize_in_maybe_statement(opt_info,
maybe(mlds__statement)) = maybe(mlds__statement).
@@ -290,16 +297,14 @@
).
%----------------------------------------------------------------------------
-
-:- func optimize_func(opt_info, maybe(mlds__statement))
- = maybe(mlds__statement).
-optimize_func(OptInfo, MaybeStatement) =
- maybe_apply(optimize_func_stmt(OptInfo), MaybeStatement).
+:- func optimize_func(opt_info, function_body) = function_body.
+optimize_func(_, external) = external.
+optimize_func(OptInfo, defined_here(Statement)) =
+ defined_here(optimize_func_stmt(OptInfo, Statement)).
-:- func optimize_func_stmt(opt_info,
- mlds__statement) = (mlds__statement).
+:- func optimize_func_stmt(opt_info, mlds__statement) = (mlds__statement).
optimize_func_stmt(OptInfo, mlds__statement(Stmt0, Context)) =
mlds__statement(Stmt, Context) :-
Index: compiler/ml_tailcall.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_tailcall.m,v
retrieving revision 1.9
diff -u -r1.9 ml_tailcall.m
--- compiler/ml_tailcall.m 2001/07/09 15:55:04 1.9
+++ compiler/ml_tailcall.m 2001/07/12 14:50:50
@@ -125,7 +125,7 @@
;
AtTail = no
),
- FuncBody = mark_tailcalls_in_maybe_statement(FuncBody0,
+ FuncBody = mark_tailcalls_in_function_body(FuncBody0,
AtTail, Locals),
DefnBody = mlds__function(PredProcId, Params, FuncBody),
Defn = mlds__defn(Name, Context, Flags, DefnBody)
@@ -143,6 +143,14 @@
DefnBody = mlds__class(ClassDefn),
Defn = mlds__defn(Name, Context, Flags, DefnBody)
).
+
+:- func mark_tailcalls_in_function_body(function_body, at_tail, locals)
+ = function_body.
+
+mark_tailcalls_in_function_body(external, _, _) = external.
+mark_tailcalls_in_function_body(defined_here(Statement0), AtTail, Locals) =
+ defined_here(Statement) :-
+ Statement = mark_tailcalls_in_statement(Statement0, AtTail, Locals).
:- func mark_tailcalls_in_maybe_statement(maybe(mlds__statement),
at_tail, locals) = maybe(mlds__statement).
Index: compiler/ml_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_util.m,v
retrieving revision 1.11
diff -u -r1.11 ml_util.m
--- compiler/ml_util.m 2001/06/22 09:14:34 1.11
+++ compiler/ml_util.m 2001/07/12 14:50:50
@@ -279,7 +279,7 @@
defn_contains_foreign_code(NativeTargetLang, Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
- Body = function(_, _, yes(FunctionBody)),
+ Body = function(_, _, defined_here(FunctionBody)),
statement_contains_statement(FunctionBody, Statement),
Statement = mlds__statement(Stmt, _),
(
@@ -291,7 +291,7 @@
defn_contains_outline_foreign_proc(ForeignLang, Defn) :-
Defn = mlds__defn(_Name, _Context, _Flags, Body),
- Body = function(_, _, yes(FunctionBody)),
+ Body = function(_, _, defined_here(FunctionBody)),
statement_contains_statement(FunctionBody, Statement),
Statement = mlds__statement(Stmt, _),
Stmt = atomic(outline_foreign_proc(ForeignLang, _, _)).
Index: compiler/mlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds.m,v
retrieving revision 1.61
diff -u -r1.61 mlds.m
--- compiler/mlds.m 2001/07/11 13:52:35 1.61
+++ compiler/mlds.m 2001/07/12 14:50:51
@@ -444,17 +444,21 @@
maybe(pred_proc_id), % identifies the original
% Mercury procedure, if any
mlds__func_params, % the arguments & return types
- maybe(mlds__statement) % the function body, or `no'
- % if the function is abstract
- % or if the function is defined
- % externally (i.e. the original
- % Mercury procedure was declared
- % `:- external').
+ mlds__function_body % the function body
+
)
% packages, classes, interfaces, structs, enums
; mlds__class(
mlds__class_defn
).
+
+ % It is possible for the function to be defined externally
+ % (i.e. the original Mercury procedure was declared `:- external').
+ % (If you want to generate an abstract body consider adding another
+ % alternative here).
+:- type mlds__function_body
+ ---> defined_here(mlds__statement)
+ ; external.
% Note that `one_copy' variables *must* have an initializer
% (the GCC back-end relies on this).
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.94
diff -u -r1.94 mlds_to_c.m
--- compiler/mlds_to_c.m 2001/07/10 14:49:14 1.94
+++ compiler/mlds_to_c.m 2001/07/12 14:50:52
@@ -1188,16 +1188,16 @@
).
:- pred mlds_output_func(indent, qualified_entity_name, mlds__context,
- func_params, maybe(statement), io__state, io__state).
+ func_params, function_body, io__state, io__state).
:- mode mlds_output_func(in, in, in, in, in, di, uo) is det.
-mlds_output_func(Indent, Name, Context, Signature, MaybeBody) -->
+mlds_output_func(Indent, Name, Context, Signature, FunctionBody) -->
mlds_output_func_decl(Indent, Name, Context, Signature),
(
- { MaybeBody = no },
+ { FunctionBody = external },
io__write_string(";\n")
;
- { MaybeBody = yes(Body) },
+ { FunctionBody = defined_here(Body) },
io__write_string("\n"),
mlds_indent(Context, Indent),
@@ -1803,7 +1803,7 @@
{ Name \= type(_, _) },
% Don't output "static" for functions that don't have a body.
% This can happen for Mercury procedures declared `:- external'
- { DefnBody \= mlds__function(_, _, no) }
+ { DefnBody \= mlds__function(_, _, external) }
->
io__write_string("static ")
;
Index: compiler/mlds_to_csharp.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_csharp.m,v
retrieving revision 1.9
diff -u -r1.9 mlds_to_csharp.m
--- compiler/mlds_to_csharp.m 2001/07/11 10:24:37 1.9
+++ compiler/mlds_to_csharp.m 2001/07/12 14:50:52
@@ -195,7 +195,7 @@
_Context, _DeclFlags, Entity)) -->
(
- { Entity = mlds__function(_, Params, yes(Statement)) },
+ { Entity = mlds__function(_, Params, defined_here(Statement)) },
{ has_foreign_languages(Statement, Langs) },
{ list__member(csharp, Langs) }
->
Index: compiler/mlds_to_gcc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_gcc.m,v
retrieving revision 1.44
diff -u -r1.44 mlds_to_gcc.m
--- compiler/mlds_to_gcc.m 2001/07/10 14:49:15 1.44
+++ compiler/mlds_to_gcc.m 2001/07/12 14:50:54
@@ -788,8 +788,8 @@
{ GlobalInfo = GlobalInfo0 ^ global_vars := GlobalVars }
;
{ DefnBody = mlds__function(_MaybePredProcId, Signature,
- MaybeBody) },
- gen_func(Name, Context, Flags, Signature, MaybeBody,
+ FunctionBody) },
+ gen_func(Name, Context, Flags, Signature, FunctionBody,
GlobalInfo0, GlobalInfo)
;
{ DefnBody = mlds__class(ClassDefn) },
@@ -1428,7 +1428,7 @@
%
:- pred gen_func(qualified_entity_name, mlds__context,
- mlds__decl_flags, func_params, maybe(statement),
+ mlds__decl_flags, func_params, function_body,
global_info, global_info, io__state, io__state).
:- mode gen_func(in, in, in, in, in, in, out, di, uo) is det.
@@ -1436,9 +1436,9 @@
GlobalInfo0, GlobalInfo) -->
{ GlobalInfo = GlobalInfo0 },
(
- { MaybeBody = no }
+ { MaybeBody = external }
;
- { MaybeBody = yes(Body) },
+ { MaybeBody = defined_here(Body) },
gcc__push_gc_context,
make_func_decl_for_defn(Name, Signature, GlobalInfo0,
FuncDecl, SymbolTable),
Index: compiler/mlds_to_il.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
retrieving revision 1.44
diff -u -r1.44 mlds_to_il.m
--- compiler/mlds_to_il.m 2001/07/11 13:10:18 1.44
+++ compiler/mlds_to_il.m 2001/07/12 14:51:14
@@ -265,13 +265,13 @@
= defn(Name, Context, Flags, Entity) :-
( Entity0 = data(Type, Initializer),
Entity = data(Type, rename_initializer(Initializer))
- ; Entity0 = function(MaybePredProcId, Params, MaybeStmt0),
- ( MaybeStmt0 = yes(Stmt),
- MaybeStmt = yes(rename_statement(Stmt))
- ; MaybeStmt0 = no,
- MaybeStmt = no
+ ; Entity0 = function(MaybePredProcId, Params, FunctionBody0),
+ ( FunctionBody0 = defined_here(Stmt),
+ FunctionBody = defined_here(rename_statement(Stmt))
+ ; FunctionBody0 = external,
+ FunctionBody = external
),
- Entity = function(MaybePredProcId, Params, MaybeStmt)
+ Entity = function(MaybePredProcId, Params, FunctionBody)
; Entity0 = class(_),
unexpected(this_file, "nested class")
).
@@ -833,9 +833,11 @@
il_info_get_next_block_id(BlockId),
% Generate the code of the statement.
- ( { MaybeStatement = yes(Statement) } ->
+ (
+ { MaybeStatement = defined_here(Statement) },
statement_to_il(Statement, InstrsTree1)
- ;
+ ;
+ { MaybeStatement = external },
% If there is no function body, generate
% forwarding code instead. This can happen with
% :- external
Index: compiler/mlds_to_java.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_java.m,v
retrieving revision 1.9
diff -u -r1.9 mlds_to_java.m
--- compiler/mlds_to_java.m 2001/07/09 15:55:07 1.9
+++ compiler/mlds_to_java.m 2001/07/12 14:51:15
@@ -423,7 +423,7 @@
Name0 = function(_Label0, ProcID, MaybeSeqNum, PredID),
Body0 = mlds__function(MaybeID, Params0,
MaybeStatements0),
- MaybeStatements0 = yes(Statements0),
+ MaybeStatements0 = defined_here(Statements0),
Statements0 = mlds__statement(
block(BlockDefns0, _BlockList0), _)
->
@@ -459,7 +459,8 @@
% Put it all together.
%
Params = mlds__func_params(Args, RetTypes),
- Body = mlds__function(MaybeID, Params, yes(Statements)),
+ Body = mlds__function(MaybeID, Params,
+ defined_here(Statements)),
Flags = ml_gen_special_member_decl_flags,
Defn = mlds__defn(Name, Context, Flags, Body)
;
@@ -977,16 +978,16 @@
).
:- pred output_func(indent, qualified_entity_name, mlds__context,
- func_params, maybe(statement), io__state, io__state).
+ func_params, function_body, io__state, io__state).
:- mode output_func(in, in, in, in, in, di, uo) is det.
output_func(Indent, Name, Context, Signature, MaybeBody) -->
output_func_decl(Indent, Name, Context, Signature),
(
- { MaybeBody = no },
+ { MaybeBody = external },
io__write_string(";\n")
;
- { MaybeBody = yes(Body) },
+ { MaybeBody = defined_here(Body) },
io__write_string("\n"),
indent_line(Context, Indent),
io__write_string("{\n"),
Index: compiler/mlds_to_mcpp.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_mcpp.m,v
retrieving revision 1.10
diff -u -r1.10 mlds_to_mcpp.m
--- compiler/mlds_to_mcpp.m 2001/07/11 10:24:37 1.10
+++ compiler/mlds_to_mcpp.m 2001/07/12 14:51:15
@@ -210,7 +210,8 @@
defn(function(PredLabel, ProcId, MaybeSeqNum, _PredId),
_Context, _DeclFlags, Entity)) -->
(
- { Entity = mlds__function(_, Params, yes(Statement)) },
+ { Entity = mlds__function(_, Params,
+ defined_here(Statement)) },
(
{ has_inline_target_code_statement(Statement) }
;
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.208
diff -u -r1.208 reference_manual.texi
--- doc/reference_manual.texi 2001/06/13 04:28:17 1.208
+++ doc/reference_manual.texi 2001/07/12 14:52:54
@@ -49,6 +49,7 @@
@author Peter Schachte
@author Simon Taylor
@author Chris Speirs
+ at author Tyson Speirs
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1995-2001 The University of Melbourne.
@@ -96,6 +97,8 @@
collections.
* Semantics:: Declarative and operational semantics of Mercury
programs.
+* Foreign language interface:: The foreign language interface allows
+ C code to be called from Mercury code.
* C interface:: The C interface allows C code to be called
from Mercury code, and vice versa.
* Impurity:: Users can write impure Mercury code.
@@ -4672,6 +4675,119 @@
For example, they may wish to provide semantics in which function
evaluation is lazy, rather than strict; semantics with a guaranteed
fair search rule; and so forth.
+
+ at node Foreign language interface
+ at chapter Foreign language interface
+
+ at menu
+* Calling foreign code from Mercury:: How to implement a Mercury predicate
+ or function as a call to foreign
+ lanugage code.
+ at end menu
+
+ at node Calling foreign code from Mercury
+ at section Calling foreign code from Mercury
+
+ at c we have no multi-language import mechanism at the moment.
+
+Mercury procedures can be implemented using fragments of foreign language
+code using @samp{pragma foreign_proc}.
+
+ at menu
+* pragma foreign_code:: Defining Mercury procedures using foreign code.
+ at end menu
+
+ at node pragma foreign_code
+ at subsection pragma foreign_code
+
+A declaration of the form
+
+ at example
+:- pragma foreign_proc("@var{Lang}", @var{Pred}(@var{Var1}::@var{Mode1}, @var{Var2}::@var{Mode2}, @dots{}),
+ @var{Attributes}, @var{Foreign_Code}).
+ at end example
+
+ at noindent
+or
+
+ at example
+:- pragma foreign_proc("@var{Lang}", @var{Func}(@var{Var1}::@var{Mode1}, @var{Var2}::@var{Mode2}, @dots{}) = (@var{Var}::@var{Mode}),
+ @var{Attributes}, @var{Foreign_Code}).
+ at end example
+
+ at noindent
+means that any calls to the specified mode of @var{Pred} or @var{Func}
+will result in execution of the foreign code given in @var{Foreign_Code}
+written in language @var{Lang}.
+The foreign code fragment may refer to the specified variables
+(@var{Var1}, @var{Var2}, @dots{}, and @var{Var})
+directly by name. These variables will have foreign language types
+corresponding to their Mercury types, as determined by language and
+implementation specific rules.
+It is an error for a variable to occur more than once in the argument list.
+
+Additional restrictions on the foreign language interface code
+depend on the foreign language, the backend target, and the implementation.
+For more information, including the list of supported foreign languages and
+the strings used to identify them, see the ``Foreign Language Interfaces''
+chapter of the Mercury User's Guide.
+
+If there is a @code{pragma foreign_proc} declaration for a
+mode of a predicate or function, then there must not be any clauses for that
+predicate or function, and there must be a @code{pragma foreign_proc}
+ at c or @code{pragma import}
+declaration for every mode of the predicate or function.
+
+For example, the following piece of code defines a Mercury function
+ at samp{sin/1} which calls the C function @samp{sin()} of the same name.
+
+ at example
+:- func sin(float) = float.
+:- pragma foreign_proc("C", sin(X::in) = (Sin::out),
+ [may_call_mercury],
+ "Sin = sin(X);").
+ at end example
+
+If the C code does not recursively invoke Mercury code,
+as in the above example, then you can use @samp{will_not_call_mercury}
+in place of @samp{may_call_mercury} in the declarations above.
+This allows the compiler to use a slightly more efficient calling convention.
+(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.)
+
+ at c XXX TYSE UP TO HERE
+ at c Move this to the User's Guide
+ at c
+The C code in a @code{pragma c_code} declaration
+for any procedure whose determinism indicates that it could fail
+must assign a truth value to the macro @samp{SUCCESS_INDICATOR}.
+For example:
+
+ at example
+:- pred string__contains_char(string, character).
+:- mode string__contains_char(in, in) is semidet.
+
+:- pragma c_code(string__contains_char(Str::in, Ch::in),
+ [will_not_call_mercury],
+ "SUCCESS_INDICATOR = (strchr(Str, Ch) != NULL);").
+ at end example
+
+ at code{SUCCESS_INDICATOR} should not be used other than as the target of
+an assignment.
+(For example, it may be @code{#define}d to a register, so you should not
+try to take its address.)
+Procedures whose determinism indicates that that they cannot fail
+should not access @code{SUCCESS_INDICATOR}.
+
+Arguments whose mode is input will have their values set by the
+Mercury implementation on entry to the C code. If the procedure
+succeeds, the C code must set the values of all output arguments
+before returning. If the procedure fails, the C code need only
+set @code{SUCCESS_INDICATOR} to false (zero).
+
+
+ at c -----------------------------------------------------------------------
+
@node C interface
@chapter C interface
--
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