Pliant forum message

Concerning release: 33
Subject: Bug
Title: In connection with arg_C
initial message posted by Knut Virow on 2000/03/17 21:42:42
#in debug level 2 (linux vers 33)

function fc2 s -> c
  arg Char s ; arg_C Char c
  c:= s
gvar Char c:="B"
console fc2:c eol

#results in

#B
#exception 11
#----------------------------------------------------------------
#processor stack content is:
#. len (Str) +4
#compile_text (List Module) +233
#pliant_load_module (Str Module Int Module) +940
#pliant internal startup function +2578
#???
#----------------------------------------------------------------                   

#whereas

function fc2 s -> c
  arg Char s ; arg_C Char c  
  c:= s                      # line 11
console fc2:"A" eol          # line 12

#leads to

#----------------------------------------------------------------
#pliant internal bug: unsatisfied assertion
#assertion is current!=null && current!=G.null_constant
#in file /pliant/pliant/install/../language/type/set/list.c at line 162
#  compile file:Func2.pli (internals) 12 1                                          
# [...]

Sorry for being not more specific. I found only this: Seems to be 
connected with arg_C (tested also arg but not the other arg_XXX)


BTW:
Is there any difference between "debug level 2" and "debug level n" n>2?


Thank you
 Knut Virow
answer posted by Patrice Ossona de Mendez on 2000/03/17 21:56:59
arg_C means that the result is a mapped constant, this means the result is
passed through a pointer.

So, you should do something like

module "/pliant/language/unsafe.pli" # for pointers
function fc2 s -> c
  arg Char s ; arg_C Char c
  c:> s # c maps to s

Actually, c:=s would mean a copy from s to the Char mapped by c 
(none, at the moment)

this way, you can write:

gvar Char x := "B"
fc2:x := "A"
console fc2:x eol # -> writes "A"

answer posted by Knut Virow on 2000/03/20 14:17:05

...mmm. I see. Nevertheless somthing like this is legal, or?


module "/pliant/language/unsafe.pli" # for pointers
function fc2 cin -> cout
  arg Char cin ; arg_C Char cout
  cout:= "A" # change the pointed char to A      #com1
  cout:> cin # point now to cin                  #com2
  cout:= "B" # change the new pointed char to B  #com3

gvar Char x:= "X"
gvar Char y:= "Y"
y:= fc2:x   
console x eol # -> writes "B"
console y eol # -> writes "B" too
# I assume: The call "y:= fc2:x" does
   1) y:="A" in com1
   2) x:="B" in com3 and 
   3) y:=x on the return from fc2

Please comment this.

Thanks
 Knut 
answer posted by Hubert Tonneau on 2000/03/20 15:10:57
> function fc2 cin -> cout
>   arg Char cin ; arg_C Char cout
>   cout:= "A" # change the pointed char to A      #com1
    ...

This is absolutely not valid: When you enter the function, 'cout' is not
defined, so is pointing to anywhere in the memory. As a result, the
first instruction in your function is poking a random byte in the memory.

'arg arg_R Char cout'  means that the function will return a pointer to
                       a character. The pointed object will be read only
                       for the caller.

'arg arg_RW Char cout' means that the function will return a pointer to
                       a character. The pointed object will be read write
                       for the caller.
                       The is basicaly the same as 'arg Pointer:Char cout'
                       where the caller would not be allowed to change
                       the pointer received on return.

'arg arg_C Char cout'  If the caller add read write access to the first
                       argument, then it will also have read write access
                       to the pointed object returned, and if not, then
                       it will have read only. So this is equivalent
                       to 'arg_R' or 'arg_RW' depending on the caller
                       access rights on the first argument.
                       This should be used for functions that return a
                       pointer to a part of the first argument (such a
                       function can be a function that returns a pointer
                       to a given field in a structure). If the caller
                       had read write access to the all object, then it
                       is consistent to provide it read write access on
                       the subpart pointed on return.

What you have to do when a function result is declared as 'arg_R' 'arg_RW'
or 'arg_C' is first set the pointer to something valid.
Now if you want your function to return a value, then just use 'arg' for
the result.
You are probably mistaken by your C++ knowledge: the Pliant way to pass
arguments is very different from C++ (mainly because we never want objects
to be copyed on return).
answer posted by Patrice Ossona de Mendez on 2000/03/20 18:01:50
Actually, it is not so far from C++ !

Something like

           function titi a -> b
              arg Int a; arg_C Int b
              ...

is something like the COUPLE of C++ functions :

           int & titi(int & a);

and 
           const int & titi (int a);

with the restriction that there is no implicit cast like int -> const int &

Hence, in C++, you would have written something like

           return *p; // where p is some pointer to some int

The same way, in pliant, you should write something like

           b :> x # where x is some persistent Int