Pliant journal articles submission forum

Pliant journal articles submission forum

Pliant Pointers

Overview of Pliant pointer mechanism
Patch 0148U7U 
Patch section Release *
pointer6.pli 2001/03/24 12:49:40 17 modified lines browse review
pointer4.pli 2001/03/24 12:49:25 18 modified lines browse review
pointer1.pli 2001/03/24 12:49:08 5 modified lines browse review
pointer5.pli 2001/03/24 12:49:33 18 modified lines browse review
pointer2.pli 2001/03/24 12:49:15 27 modified lines browse review
pointer3.pli 2001/03/24 12:49:20 14 modified lines browse review
pointer.html 2001/03/24 12:48:54 324 modified lines browse review
pointer.page 2001/03/24 12:49:02 205 modified lines browse review
Browse patch files tree
Download the patch  Download as a ready to extract .tgz tarball
Message posted by pom on 2001/03/24 12:47:53
This is the first sections, more to come:

- function argument passing (arg_R, etc.)
  and indirect arguments for function call instructions

- Objects and links
  (oarg, lock, ref count, new, omap, Arrow, entry_type, entry_counter, entry_root
  build_instance, destroy_instance
  linkto, unlinkto
  (data_type, real_data_type)

- Creating new pointers
  'pliant star types', implicit casts, ...

- Database pointers (Data)
  :>, exists

- Usual bugs
  freed objects
  links on non objects
  arg vs oarg
  arg_C vs  arg Link:.. as return value
Message posted by pom on 2001/03/24 12:54:18


Introduction

Management of dynamically allocated objects and creation of linked structures are typical uses where addresses of objects in memory have to be handled.

Some languages (like the C++ programming language) have introduced pointers (which hold values that are the addresses of objects in memory) and references (which act as aliases). Pliant pointers act like references, but the refereed object may be changed, as with usual pointers.

Moreover, the same basic concept of object address actually adresses more than a single reality: adresses have to be handled in different context, like in

  • retrieving by reference arguments of a function,
  • linking datas together,
  • getting an absolute unique value refering an object in memory,
  • etc.
Thus, we shall look of all of these kind of situations, starting from the low-level functions and ending with the higher-level ones.


Manipulating Objects through their Addresses

  • Address
  • addressof
  • map
  • null
  • translate

Pliant introduces a specific data type to handle basic addresses of objects in memory, the Address data type.

The address of an object may be obtained by calling the addressof function on it; the reverse operation, which consists in mapping a memory address to an item with specified type is done by calling the map method:

Basic use of addressof and map calls.
module "/pliant/language/unsafe.pli"
gvar uInt i                   # is is an unsigned integer
gvar Address a:=addressof i   # a is its address
a map Int := -1               # 'brut force' cast !
console i eol                 # -> will show 4294967295

Notice that the module "/pliant/language/unsafe.pli" has to be linked to, as these kinds of calls are quite unsecure.

It is always allowed to map and address to an item of specified type, even if the address is null. Then, no problem will occur until you will try to actually access the item. Notice that the null address is actually the value of the null constant.

Computing an address from a base address and an offset corresponding to a given count of items of a given type is achieved by translate call:

Basic use of translate call.
module "/pliant/language/unsafe.pli"

# define some user data type Toto

type Toto
  field Int value
  field Str name
  field Str other_name
  field Float width

# create a Toto object and fill it

gvar Toto x
x:value := 1
x:name := "My sweet heart"
x:other_name := "Hi fox!"
x:width := 3.14

# address the fields of the Toto item
# from the address of the item itself

gvar Address add := addressof x # address of the first field of Toto item
add := add translate Int 1 # go one Int further, to the name field
console (add map Str) eol  # show the name field, "My sweet heart".
add := add translate Str 2 # go two Str further, to the width field
console (add map Float) eol     # show the width field, 3.14


Pliant Pointers (Basics)

  • pointerto
  • Pointer
  • 'pliant pointer types'
  • :>
  • exists

In Pliant, pointer are implicitely dereferenced, what means that a "Pointer to an item" roughly acts like the pointed item itself.

pointerto is a function which maps a type T into the type (Pointer T) (i.e. Pointer:T), building it if necessary. Thatfor, the function uses a global Relation named 'pliant pointer types' to know wether a Pointer type has already been created or not. The pointerto function is usually called through Pointer meta, which will only accept a constant type as its argument. Both will return a constant result in such a case, Pointer because it sets explicitely the constant flag in the access property of the result, and pointerto because of the constant evaluation mechanism of Pliant, which will discover that the result of calling pointerto on a constant arguments will give a constant result. To use the 'relaxed' version pointerto, you will have to link to module "/pliant/language/compiler.pli".

To make a pointer actuallay point to a data is done using :> operator. Once done, the data is handled through the pointer as if the pointer was the data itself (implicit cast):

Basic pointer manipulation.
module "/pliant/language/unsafe.pli"
module "/pliant/language/compiler.pli" # only needed by pointerto
gvar Int i := 23
gvar Int j := 45
gvar Pointer:Int p    # 'Pointer'-way to create a Pointer to an Int
gvar pointerto:Int q  # the same with 'pointerto' function

p :> i   # p points to i
q :> p   # q points to the data pointed by p !
p := 5   # is the same than i := 5
console q eol  # will print i, i.e. 5
q :> j   # q now points to j
q += p   # same as j += i
console q eol  # will print j, i.e. 50

A pointer may be set, in such a way that it points to an item at null address and this is actually the usual way to set the pointer as invalid. According to this convention, once may use the meta exists to test wether a pointer is valid or not.

Pointer manipulation (with validity test).
module "/pliant/language/unsafe.pli"

gvar Int i := 23   
gvar Pointer:Int p :> i

if exists:p # is p valid ?
  console "p refers to Int value " p eol # will be printed
else
  console "p is invalid" eol

p :> null map Int # p points to Int item at null address
                  # i.e. p is invalid

if exists:p # is p valid ?
  console "p refers to Int value " p eol
else
  console "p is invalid" eol             # will be printed


Pliant Pointers (Extended)

  • :>>
  • addressof
  • pointerto
  • is_pointer
  • unpointerto

It is possible to create a depth two pointer, that is a pointer to a pointer. Value modification may then take place at three levels:

  • value level, using := operator;
  • pointer level, using :> operator;
  • depth two pointer level, using :>> operator;
Accordingly, three address values may be retrieved from a depth 2 pointer (Pointer Pointer:Int p):
  • the value address, using simple form of addressof p
  • pointer address, using addressof Pointer:Int p
  • depth 2 pointer address, using addressof (Pointer Pointer:Int) p
This is shown in following example:

Multiple references and pointer address.
module "/pliant/language/unsafe.pli"

gvar Int i j
gvar Pointer:Int p q
gvar (Pointer Pointer:Int) pp qq

pp :>> p  # pp refers to the pointer p (depth 2)
pp :> i   # pp refers to i (same as p:>i, as pp refers to p at depth 2)
pp := 3   # same as p:=3, same as i:=3

var Address ad := addressof pp # same as addressof:p, same as addressof:i
ad map Int := 27 # same as i:=27

ad := addressof Pointer:Int pp # same as (addressof Pointer:Int p)
ad map Pointer:Int :> j  # same as pp :> j, same as p :> j

ad := addressof (Pointer Pointer:Int) pp # address of depth 2 pointer pp
ad map (Pointer Pointer:Int) :>> q  # same as pp :>> q

Pointer types may be dynamicaly handled, as mentioned above for the pointerto function. In order to get the dynamic functions, you shall link to the compiler module "/pliant/language/compiler.pli". Available function will allow you to create a pointer type (using pointerto), to test wether a type actually is a pointer type (using is_pointer  method) and to get the 'one depth less' value type (using unpointerto):

Multiple references and pointer address.
module "/pliant/language/unsafe.pli"
module "/pliant/language/compiler.pli"

gvar Pointer:Type T :> Int  # T points to type Int
# gvar pointerto:T x  would not work: pointerto:T is not constant!

if pointerto:T = Pointer:Int
  console "pointerto:T = Pointer:Int" eol # ok, =
T :> Float  # T points to type Int
if pointerto:T <> Pointer:Int
  console "now, pointerto:T <> Pointer:Int" eol # ok, <>

T :> pointerto:T  # T points to type Pointer:Float
if T:is_pointer   # T is a pointer ?
  T :> unpointerto:T  # go one depth less, back to Float type
  if T=Float
    console "I am back to Float" eol # ok, we're back.