<\body> both allows the user to import functionality from C++ template languages and to export functions and classes back to C++. The syntax for importating and exporting functionality is as follows:>>> <\mmx-code> foreign cpp import import_body; foreign cpp export export_body; The import and export bodies essentially contain dictionaries between C++ names and names of various classes, functions and other variables or constants. In the case of foreign imports, it is usually necessary to specify options which should be passed to the compiler and to the linker, as well as some include statements or macro definitions which are necessary in order to compile the imported code. This can be done using the following keywords: <\indent> |||>>||<\cell> flags that should be passed to the C++ compiler >|>>||<\cell> flags that should be passed to the C++ linker >|>>||<\cell> C++ files that should be included in order to compile the imported code >|>>||<\cell> macro definitions which are necessary to compile the imported code >>>> A typical example of the use of these keywords occurs at the start of the file : <\mmx-code> foreign cpp import { \ \ cpp_flags \ \ \ "\0basix-config --cppflags\0"; \ \ cpp_libs \ \ \ \ "\0basix-config --libs\0"; \ \ cpp_include \ "basix/int.hpp"; \ \ cpp_preamble "#define int_literal(x) as_int (as_string (x))"; \ \ ... } The C++ compiler and linker flags are taken to be the results of the shell command which outputs the appropriate flags as a function of the user's environment. The header file contains various utility functions for machine integers which are imported into . The additional macro is also imported as the constructor of machine integers from literal integers. Inside the body of a >> statement, the C++ class can be imported into under the name using <\mmx-code> class My_Class == my_class; For instance, we may import the class as using <\mmx-code> class Integer == integer; Any imported class is required to provide the following standard routines:>>|>|>>>>>>>>> <\cpp-code> bool operator == (const my_class&, const my_class&); \ \ // equality predicate bool operator != (const my_class&, const my_class&); \ \ // inequality predicate bool exact_eq (const my_class&, const my_class&); \ \ // predicate for syntactic equality bool exact_neq (const my_class&, const my_class&); \ \ // predicate for syntactic equality bool hard_eq (const my_class&, const my_class&); \ \ // predicate for hard equality (of pointers for reference counted objects) bool hard_neq (const my_class&, const my_class&); \ \ // predicate for hard inequality (of pointers for reference counted objects) nat hash (const my_class&); \ \ // a hash code compatible with operator == nat exact_hash (const my_class&); \ \ // a hash code compatible with exact_eq nat hard_hash (const my_class&); \ \ // a hash code compatible with hard_eq syntactic flatten (const my_class&); \ \ // a flattener for objects of type my_class In practice, some of these routines can usually be derived from the others. In the file <\indent> one may find various macros to this effect, such as . In a similar way, a C++ container class param_1, ..., param_n\> can be imported as a container class with name using <\mmx-code> class My_Container (P_1: Cat_1, ..., P_n: Cat_n) == \ \ my_container (P_1, ..., P_n); The parameters of imported C++ containers are necessarily type parameters, and it is required to specify the types of these parameters, which are categories. For instance, in , the container class R\> of complex numbers is imported using <\mmx-code> class Complex (R: Ring) == complex R; In the case when the categories of the parameters are non trivial ( in the above example where is the category of the parameter ), it is necessary to specify a dictionary between the members of the category and their corresponding names in C++. Indeed, in the C++ implementation of an addition on complex numbers, we add the real and imaginary parts using the C++ operator. At some place, we have to specify that this C++ operator corresponds to the operator . This can be done by the category to C++:>> <\mmx-code> foreign cpp export { \ \ category Ring == { \ \ \ \ convert: Int -\ This == keyword constructor; \ \ \ \ prefix -: This -\ This == prefix -; \ \ \ \ infix +: (This, This) -\ This == infix +; \ \ \ \ infix -: (This, This) -\ This == infix -; \ \ \ \ infix *: (This, This) -\ This == infix *; \ \ } } This example illustrates the general syntax for the exportation of categories to C++: every field <\mmx-code> mmx_function: (S_1, ..., S_n) -\ D; in the definition of the category is replaced by a declaration <\mmx-code> mmx_function: (S_1, ..., S_n) -\ D == cpp_function; where is the C++ name corresponding to the function . Inside the body of a >> statement, one may import a \ C++ function or variable with name into under the name using the syntax <\mmx-code> mmx_name: Type == cpp_name; The type of the imported function or variable should be specified on the side. For instance, some of the basic operations on strings can be imported using <\mmx-code> foreign cpp import { \ \ prefix #: String -\ Int == N; \ \ postfix []: (String, Int, Int) -\ String == postfix (); \ \ infix *: (String, String) -\ String == infix *; \ \ infix \\: (String, String) -\ String == infix *; \ \ infix \\: (Alias String, String) -\ Alias String == infix \\; } The standard ports , and for input, output and errors are imported using <\mmx-code> foreign cpp import { \ \ mmin : Port == mmin; \ \ mmout: Port == mmout; \ \ mmerr: Port == mmerr; } Template functions can be imported from C++ into using the same syntax as for the importation of ordinary functions, by putting all declarations inside a > block. For instance, the following basic imported functions on vectors were extracted from : <\mmx-code> foreign cpp import { \ \ forall (C: Type) { \ \ \ \ prefix #: Vector C -\ Int == N; \ \ \ \ postfix []: (Vector C, Int) -\ C == postfix []; \ \ \ \ postfix []: (Alias Vector C, Int) -\ Alias C == postfix []; \ \ \ \ postfix []: (Vector C, Int, Int) -\ Vector C == range; \ \ \ \ reverse: Vector C -\ Vector C == reverse; \ \ \ \ infix \\: (Vector C, Vector C) -\ Vector C == append; \ \ } } Inside the block it is possible to impose additional constraints on the parameters using the > statement. For instance, we may extend the imported functions on vectors as follows: <\mmx-code> foreign cpp import { \ \ forall (C: Type) { \ \ \ \ prefix #: Vector C -\ Int == N; \ \ \ \ postfix []: (Vector C, Int) -\ C == postfix []; \ \ \ \ postfix []: (Alias Vector C, Int) -\ Alias C == postfix []; \ \ \ \ postfix []: (Vector C, Int, Int) -\ Vector C == range; \ \ \ \ reverse: Vector C -\ Vector C == reverse; \ \ \ \ infix \\: (Vector C, Vector C) -\ Vector C == append; \ \ \ \ \ \ \ \ assume (C: Abelian_Group) { \ \ \ \ \ \ prefix -: Vector C -\ Vector C == prefix -; \ \ \ \ \ \ infix +: (Vector C, Vector C) -\ Vector C == infix +; \ \ \ \ \ \ infix -: (Vector C, Vector C) -\ Vector C == infix -; \ \ \ \ } \ \ } } Here > stands for the following category: <\mmx-code> foreign cpp export { \ \ category Abelian_Group == { \ \ \ \ convert: Int -\ This == keyword constructor; \ \ \ \ prefix -: This -\ This == prefix -; \ \ \ \ infix +: (This, This) -\ This == infix +; \ \ \ \ infix -: (This, This) -\ This == infix -; \ \ } } Classes, functions and variables can be exported back to C++ using the same syntax as for importations. For instance, the class > from the can be exported together with some basic routines as follows>> <\mmx-code> foreign cpp export { \ \ class Point == point; \ \ point: (Double, Double) -\ Point == keyword constructor; \ \ postfix .x: Point -\ Double == get_x; \ \ postfix .y: Point -\ Double == get_y; } In order to use C++ template functions with as a parameter, the required operations from the category of that parameter should be exported to C++ as well. For instance, assume that we wish to use the operations and from the previous section on vectors of points. Then we first have to define the abelian group operations on : <\mmx-code> convert (i: Int): Point == point (as_double i, as_double i); prefix - (p: Point): Point == point (-p.x, -p.y); infix + (p: Point, q: Point): Point == point (p.x + q.x, p.y + q.y); infix - (p: Point, q: Point): Point == point (p.x - q.x, p.y - q.y); We next have to export these operations to C++, while making sure that the C++ names of the operations correspond to the exported names of the operations of the category : <\mmx-code> foreign cpp export { \ \ convert: Int -\ Point == keyword constructor; \ \ prefix -: Point -\ Point == prefix -; \ \ infix +: (Point, Point) -\ Point == infix +; \ \ infix -: (Point, Point) -\ Point == infix -; } <\remark> In the current implementation of the compiler, the mandatory operations ==>, , , , , , , , and >>>>>>>>>> of -compatible C++ types are exported to C++. For instance, assuming that the user redefined the default flattening routine for , this routine should be exported explicitly to C++ if we want vectors of points to be printed correctly. . If you don't have this file, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.>