Newbie questions about Pliant

Newbie questions about Pliant

Implementing 'each' support for my object

My object doesn't store the elements but uses special C API to access them. I don't know how to handle memory allocation issues
Message posted by maybe Boris Reitman on 2003/12/12 06:59:09

I would like to get 'each' to work with my PerlHash object, which is like
Dictionary object, but represents a perl hash in the perl space.
The PerlHash object itself doesn't store any elements, but gets them 
with special C API.  I followed the implementation of the Dictionary object
and I see that the 'first' and 'next' methods of the dictionary object
return arg_C values, which ends up being a Pointer type.  I understand that
to signal the end of a list I must return a 'null' pointer.  For PerlHash,
I would like 'each' to browse through PerlScalar objects, so I figure 
I should return arg_C PerlScalar.  But it looks like that if I do 

  arg_C PerlScalar value
value is of type Pointer:PerlScalar, and the constructor 'build' for 
PerlScalar is never executed, so I actually need to point value somewhere, with 

  value :> existing_perlscalar_object

where do I get this PerlScalar object ?  Do I need to allocate it with 
new ?  In that case someone needs to clean it up, and I guess I need 
to use Link to do it.  But now I can no longer return Pointer:PerlScalar
but will return something like Pointer:Link:PerlScalar ? Or should I return 
Link:PerlScalar as an arg instead of arg_C ? Or should I overload operator <>
for PerlScalar and return 'arg PerlScalar' ?  The PerlScalar wraps perl SVs
in the same way that the Link object wraps Pliant objects.

Also, I don't understand why arg_C makes me return a Pointer.  Perhaps someone
can explain the allowed arg_* for return values with some examples.
Message posted by hubert.tonneau on 2003/12/12 09:50:39
Here is an 'each' implementation for 'XmlTree' data type that I use in the
Pliant browser to store XML tree.
Each 'XmlTree' has a list of sons, stored in a LISP like list (first son
is accessed through 'first', and next ones are successively accessed through
'next' filed)

You can use it as a fairly simple exemple, also it might be suboptimal as a
mater of code efficiency.

type XmlTree
  field Address buf
  field Pointer:XmlTree first
  field Pointer:XmlTree next
  field Float32 x0 y0 x1 y1

method t map_first p -> c
  arg XmlTree t ; arg_rw Pointer:XmlTree p ; arg CBool c
  p :> t first
  c := exists p

function map_next p -> c
  arg_rw Pointer:XmlTree p ; arg CBool c
  p :> p next
  c := exists p

meta each e
  if e:size=3 and e:0:is_pure_ident and (e:1 cast XmlTree) and e:2:ident="{}"
    var Link:Argument cursor :> e local_variable e:0 Pointer:XmlTree
    e:2 compile ?
    var Link:Argument some :> argument local CBool
    e suckup e:1
    e add (instruction (the_function '. map_first' XmlTree Pointer:XmlTree -> CBool) e:1:result cursor some)
    var Link:Instruction end :> instruction the_function:'do nothing'
    e add (instruction (the_function 'jump if not' CBool) some jump end)
    var Link:Instruction body :> instruction the_function:'do nothing'
    e add body
    e suckup e:2
    e add (instruction (the_function map_next Pointer:XmlTree -> CBool) cursor some)
    e add (instruction (the_function 'jump if' CBool) some jump body)
    e add end
    e set_void_result
Message posted by maybe pom on 2003/12/13 11:50:58
Concerning the result of a function:
upper cases in arg_... means "by pointer" (i.e. mapped result), 
lower case means "by value".
-> arg_R, arg_W, arg_RW and arg_C return pointers, while arg returns a value