Next: , Previous: C data passing conventions, Up: Data passing conventions   [Contents]


14.3.2 C# data passing conventions

The Mercury primitive types are mapped to the following Common Language Infrastructure (CLI) and C# types:

Mercury typeCLI typeC# type
intSystem.Int32int
uintSystem.UInt32uint
floatSystem.Doubledouble
charSystem.Int32int
stringSystem.Stringstring

Note that the Mercury type char is mapped like int; not to the CLI type System.Char because that only holds 16-bit numeric values.

For the Mercury standard library type ‘bool.bool’, there is a corresponding C# type, mr_bool.Bool_0. C# code can refer to the boolean data constructors ‘yes’ and ‘no’, as mr_bool.YES and mr_bool.NO respectively.

For the Mercury standard library type ‘builtin.comparison_result’, there is a corresponding C# type, builtin.Comparison_result_0. C# code can refer to the data constructors of this type, ‘(<)’, ‘(=)’ and ‘(>)’, as builtin.COMPARE_LESS, builtin.COMPARE_EQUAL and builtin.COMPARE_GREATER respectively.

Mercury variables of a type for which there is a C# ‘pragma foreign_type’ declaration (see Using foreign types from Mercury) will be passed as the corresponding C# type. Both reference and value types are supported.

Mercury tuple types are passed as ‘object[]’ where the length of the array is the number of elements in the tuple.

Mercury variables whose type is a type variable will be passed as System.Object.

Mercury variables whose type is a Mercury discriminated union type will be passed as a CLI type whose type name is determined from the Mercury type name (ignoring any type parameters) followed by an underscore and then the type arity, expressed as a decimal integer. The first character of the type name will have its case inverted, and the name may be mangled to satisfy C# lexical rules.

For example, the following Mercury type corresponds to the C# class that follows (some implementation details elided):

:- type maybe(T)
    --->    yes(yes_field :: T)
    ;       no.

public static class Maybe_1 {
    public static class Yes_1 : Maybe_1 {
        public object yes_field;
        public Yes_1(object x) { … }
    }
    public static class No_0 : Maybe_1 {
        public No_0() { … }
    }
}

C# code generated by the Mercury compiler is placed in the ‘mercury’ namespace. Mercury module qualifiers are converted into a C# class name by concatenating the components with double underscore separators (‘__’). For example the Mercury type ‘foo.bar.baz/1’ will be passed as the C# type ‘mercury.foo__bar.Baz_1’.

Mercury array types are mapped to System.Array.

Mercury variables whose type is a Mercury equivalence type will be passed as the representation of the right hand side of the equivalence type.

This mapping is subject to change and you should try to avoid writing code that relies heavily upon a particular representation of Mercury terms.

Mercury arguments declared with input modes are passed by value to the C# function.

Arguments of type ‘io.state’ or ‘store.store(_)’ are not passed or returned at all. (The reason for this is that these types represent mutable state, and in C# modifications to mutable state are done via side effects, rather than argument passing.)

The handling of multiple output arguments is as follows.

If the Mercury procedure is deterministic and has no output arguments, then the return type of the C# function is ‘void’; if it has one output argument, then the return value of the function is that output argument.

If the Mercury procedure is deterministic and has two or more output arguments, then the return type of the C# function is ‘void’. At the position of each output argument, the C# function has an ‘out’ parameter.

If the Mercury procedure is semi-deterministic then the C# function returns a ‘bool’. A ‘true’ return value denotes success and ‘false’ denotes failure. Output arguments are handled in the same way as multiple outputs for deterministic procedures, using ‘out’ parameters. On failure the values of the ‘val’ fields are undefined.

Mercury lists can be manipulated by C# code using the following methods, which are defined by the Mercury implementation.

bool      list.is_empty(List_1 list)     // test if a list is empty
object    list.det_head(List_1 list)     // get the head of a list
List_1    list.det_tail(List_1 list)     // get the tail of a list
List_1    list.empty_list()              // create an empty list
List_1    list.cons(object head, List_1 tail)
                                         // construct a list with
                                         //  the given head and tail

Next: , Previous: C data passing conventions, Up: Data passing conventions   [Contents]