[m-rev.] for review: il as a foreign language

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Jul 17 01:01:07 AEST 2001


You should describe `pragma foreign_decl' and `pragma foreign_code'.

On 16-Jul-2001, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> +++ doc/reference_manual.texi	2001/07/16 13:23:27
> @@ -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.

I suggest

* Foreign language interface:: Calling code written in other programming languages
		      from Mercury code.

> + 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
> +				       language code.

I suggest

* Calling foreign code from Mercury::  How to implement a Mercury predicate
				       or function as a call to code written in
				       a different programming language.

> +The syntax, documentation, behaviour and semantics of this chapter are
> +subject to change without notice.

s/of this chapter/of the constructs described in this chapter/

> + at node Calling foreign code from Mercury
> + at section Calling foreign code from Mercury
> +
> +Mercury procedures can be implemented using fragments of foreign language
> +code using @samp{pragma foreign_proc}.
> +
> + at menu
> +* pragma foreign_proc::         Defining Mercury procedures using foreign code.
> +* Foreign code attributes::   	Describing properties of foreign
> +				functions or code.

> + at end menu
> +
> + at node pragma foreign_proc
> + at subsection pragma foreign_proc
> +
> +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

I think the syntax there should be changed from "Lang" to 'Lang'.
The set of supported languages is an enumeration, not an arbitrary
string literal, so we should use enumeration-like syntax rather than
string literal syntax.

> + 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}.

That isn't true.  E.g. the "MC++" foreign procs in the std library
have no effect when compiling to C.

> +Additional restrictions on the foreign language interface code
> +depend on the foreign language, the backend target, and the implementation.

Different restrictions for different foreign languages are fine, but
implementations shouldn't be allowed to add arbitrary restrictions here.
If they are, then it would be impossible to write code that is portable
between different implementations.  That would be a bad thing.

Now, it may be unavoidable, but I'd like to see a detailed rationale
before including that in the language reference manual.

Also, I don't think the readers of the Mercury language reference manual will
know what you mean by "the backend target" here.  You'd need a more detailed
description.  It may be best to just leave that out; it's subsumed by
"the implementation".

(And by the way, if the word "backend" should remain, s/backend/back-end/.
I think the rule with these kinds of things is that
"backend" is a noun, "back-end" is an adjective.)

> +If there is a @code{pragma foreign_proc} declaration for any
> +mode of a predicate or function, then there must not be either a mode
> +specific clause, or a @code{pragma foreign_proc} 
> + at c or @code{pragma import} 
> +declaration for every mode of the predicate or function.

This sentence is very confusing.
Please rephrase it.

> +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.

Is this an example of the point in the preceding sentence?
That's what I first thought it would be.  Then I got confused because it wasn't.

I suggest you introduce it with something other than just "For example",
e.g. "Here's an example of code using `pragma foreign_proc'."
Or alternatively, you could put the example before the description
of the restrictions, so it follows directly after the description of
the syntax.

> + at node Foreign code attributes
> + at subsection Foreign code attributes
> +
> +As described above, @samp{pragma import} and @samp{pragma c_code}
> +declarations may include a list of attributes describing properties
> +of the given foreign function or code.

`pragma import' and `pragma c_code' haven't been mentioned yet.

> +All Mercury implementations must support the attributes listed below.
> +They may also support additional attributes.
> +
> +The attributes which must be supported by all implementations
> +are as follows:
> +
> + at table @asis
> +
> + at item @samp{may_call_mercury}/@samp{will_not_call_mercury}
> +This attribute declares whether or not execution inside this C code may
> +call back into Mercury or not.  The default, in case neither is specified,
> +is @samp{may_call_mercury}.  Specifying @samp{will_not_call_mercury}
> +may allow the compiler to generate more efficient code.
> +If you specify @samp{will_not_call_mercury},
> +but the C code @emph{does} invoke Mercury code, then the behaviour is
> +undefined.

The references to "C" here should be replaced with "the foreign language".

> + at item @samp{thread_safe}/@samp{not_thread_safe}
> +This attribute declares whether or not it is safe for multiple threads
> +to execute this C code concurrently.
> +The default, in case neither is specified, is @samp{not_thread_safe}.
> +If the C code is declared @samp{thread_safe}, then the Mercury implementation
> +is permitted to execute the code concurrently from multiple threads without
> +taking any special precautions.  If the C code is declared
> + at samp{not_thread_safe},
> +then the Mercury implementation must not invoke the code concurrently from
> +multiple threads.  If the Mercury implementation does use multithreading,
> +then it must take appropriate steps to prevent this.
> +(The experimental multithreaded version of the current
> +University of Melbourne Mercury implementation protects
> + at samp{not_thread_safe} code using a mutex:
> +C code that is not thread-safe has code inserted around it to obtain
> +and release a mutex.  All non-thread-safe C code shares a single mutex.)
> + at c XXX this can cause deadlocks if not_thread_safe C code calls
> + at c     Mercury which calls C
> + at end table

Likewise here.

> +Additional attributes which are supported by the Melbourne Mercury
> +compiler are as follows:
> +
> + at table @asis
> +
> + at item @samp{max_stack_size(Size)}
> +This attribute declares the maximum stack usage of a particular piece of
> +code.  The unit @samp{Size} is measured in depend upon foreign language
> +being used.  

s/The unit/The unit that/
s/depend/depends/

> +Currently this attribute is only used (and is in fact required) by the 
> + at samp{IL} foreign language interface, and is measured in units of stack
> +items.

> + at node Language specific bindings
> + at section Language specific bindings
> +
> +Note that these bindings are specific to the Melbourne Mercury compiler,
> +other compilers may choose to implement a different set of bindings.
> +
> + at table @asis
> +
> + at item @samp{C}
> +Use the string "C" to set the foreign language to C.
> +Default foreign language on all backends which compile to C.
> +Only available on backends that do compile to C.

The "Only available ..." sentence is false.
`pragma foreign_proc("C", ...)' works fine for the native-code back-end.

s/Default/This is the default/

You need to explain the concept of "default foreign language".
It might be better to put the documentation for that in the user guide.
I think this section should just say which foreign languages
supported, and what syntax you use for each language.

> + at item @samp{Managed C++}
> +Use the string "MC++" to set the foreign language to Managed C++.
> +Default foreign language on all backends which compile to IL.
> +Only available on backends that compile to IL.

Many readers won't know what "Managed C++" is, so you should explain,
e.g. "(also known as Microsoft C++ with managed extensions)".

s/Only available/In the current implementation, this is only available/
But again, I think the documentation about these implementation-specific
restrictions on which languages can be used for which back-end should
go in the user guide.

> +Requires a Managed Extensions for C++ compiler installed.

The analagous requirement is true for every foreign language.
It should be documented in the language-independent part of the
documentation.

> + at item @samp{C#}
> +Use the string "C#" to set the foreign language to C#.
> +Only available on backends that compile to IL.
> +Requires a C# compiler installed.
> +To use the pass mmc @samp{--use-foreign-language csharp} and
> + at samp{--backend-foreign-language csharp}.

"To use the pass" is not grammatically correct.

> + at item @samp{IL}
> +Use the string "IL" to set the foreign language to IL.

Many readers won't know what "IL" is, so you should explain further.

> + at node Interfacing with C#
> + at subsection Interfacing with C#
> +
> +Currently undocumented, sorry.
> +
> + at node Interfacing with Managed C++
> + at subsection Interfacing with Managed C++
> +
> +Currently undocumented, sorry.

You should add "@c XXX" to those two places.

> + at node Interfacing with IL
> + at subsection Interfacing with IL
> +
> +Variables can be accessed from IL by using ldloc (for input) 
> +stloc (for output).

s/stloc/and stloc/
s/for input/for input parameters/
s/for output/for output parameters/

> Do not use a ret instruction or tail.call
> instruction within the handwritten IL code.

So "tail.calli" is OK then? ;-)

You need to generalize this.

> +The IL code in a @code{pragma foreign_proc} declaration
> +for any procedure whose determinism indicates that it could fail
> +must assign a truth value to the local variable @samp{succeeded}.
> +For example:
> +
> + at example
> +:- pred same(int::in, int::in) is semidet.
> +:- pragma foreign_proc("il", same(X::in, Y::in), [max_stack_size(2)], "
> +	ldloc X
> +	ldloc Y
> +	ceq
> +	stloc succeeded
> +").
> + at end example

This is a bad design, IMHO.  It would be much better for the semidet
IL code to leave the truth value on the IL stack, and have the compiler
automatically generate the "stloc succeeded" instruction.

Apart from anything else, this would make it easier for peephole optimization
to optimize away the "stloc succeeded", "ldloc succeeded" pairs.
It's also nicer because it avoids hard-coding the magic name "succeeded".


Incidentally, it's generally a good idea to write the documentation and get it
reviewed before writing the code, because these kind of design issues often
come up when the documentation is reviewed.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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