This page has been written by Hubert Tonneau, then enhanced by William Merriam.

In this document, I will call 'argument' an argument of a function which may also be the result of the function, and I will call 'true argument' an argument which is not the result.
Unlike C or C++, in which you have to define whether an argument is passed by value or by address, the Pliant semantic is that all arguments are passed by address, so you don't have to specify it. In reality, arguments that are read-only and atomic (may be stored in a register) are passed by value for efficiency, but you don't need to worry about it since it does not change the program behavior.

In pliant, you only specify what kind of operations your function wants to do on the argument. There are three access modes for an argument:
read-only The function reads the value of the argument but does not modify it.
read-write The function reads the value of the argument and modifies it.
write-only The function reads and writes the value of the argument, but the value of the argument when the function returns does not depend on its value at the time the function started. This means that the function can truly both read and write the argument, but from the semantic point of view, it only writes it.

Now for the result. You have to choose between:
by value result The result is returned as a value.
mapped result The result is returned as a pointer to existing data.

and also:
read-only result The calling function may only read the result.
read-write result The calling function may read and write the result.
consistent result The function has the same access rights on the result that it has on the first argument it passed to the function. This access right is generally used when the result maps a part of the first argument.

The calling conventions of Pliant are much more efficient than in C++. Let's take an example:

function three_times s -> sss
  arg Str s sss
  sss := s+s+s

and the C++ equivalent (assuming Str is a C++ string class):

Str three_times(const Str &s)
{
  return s+s+s ; 
}

The function returns a string which is the concatenation of three times the one it received in argument.


All the arguments of a function (including the result if there is one) must be typed using the 'arg' declaration.
arg the argument has default access mode:
if it's a true argument, then it is read-only
if it's the result, then it is write-only
arg_rw read-write argument
arg_w write-only argument (remember that it does not mean that the function cannot read the argument but rather that the final value of the argument does not depend on the initial value)
arg_R inside the function, the result is a mapped write-only argument.
outside the function (in the calling function), it will be only readable.
arg_RW inside the function, the result is a mapped write-only argument.
outside the function (in the calling function), it will be readable and writable.
arg_C inside the function, the result is a mapped write-only argument.
outside the function, it is consistent with the access right of the first argument. This means that if the caller had read-write access to the first argument it passed to the function, then it will get read-write access to the mapped result. On the other hand, if it had read-only access to the first argument it passed to the function, then it will get read-only access to the mapped result.
This is the right access mode for the result when it maps a part of the first argument.
oarg
oarg_rw
oarg_w
oarg_R
oarg_RW
oarg_C
Same as arg... declarations, but specifies that the argument must be a full object. added in release 33

Here are a few examples:

function factorial x -> f
  arg Int x f
  if x=0
    f := 1
  else 
    f := x * (factorial x-1)

Simple, isn't it ?

Second example, first version:

function first_char s -> c
  arg Str s ; arg_C Char c
  c :> s 0

This function returns the first character of the string which it receives as an argument. Note that we use ':>' instead of ':=' since we don't want to change the value of the object pointed to by 'c', but to make 'c' point to another address.

Second example, second version:

function first_char s -> c
  arg Str s ; arg Char c
  c := s 0

If we now use the new function in the following sequence:

var Str test := "abc"
var Char c1 := first_char test
console c1 eol

both functions will work fine and display "a".

But now, if we write:

var Str test := "abc"
first_char test := character 65
console test eol

only the first function work fine and display "Abc", while the second will return a compile error. The explanation is that the first version returns a pointer to the first character of the string, while the second returns a copy of it.
The attributes should appear at the end of the function prototype, before the function body
later This was just a prototype; the function will be defined later.
This attribute is useful when several functions call each other.
inline Forces the function to be expanded inline each time it is used.
generic This is a generic function.
For more details, see type definition introduction.
priority
has_side_effects
has_no_side_effect
can_share_result
indirect The last argument of the function must be an object of type Function.
When the indirect function is called, then the function passed as the last argument is called instead. The function to be called is expected to have a prototype compatible with the indirect one.
external_calling_convention The function must not use the compiler calling convention but rather the standard calling convention on the operating system.
This attribute is useful only when the address of the function must be passed as an argument to an external DLL or kernel function.
varargs_calling_convention The function must use the calling convention for C functions with a variable number of arguments.
external dll_name function_name_in_dll The function is implemented in an external DLL.
See examples in zlib.pli.
kernel_function function_number This is a Linux kernel function.
See various examples in linux.pli.
hidden_function The function cannot be called directly. Its address can be obtained using the function 'the_function'.
Casting related flags (for more details, read the introduction to Pliant casting mechanism):
implicit
extension
reduction
explicit