Pliant talk forum

Pliant talk forum

Discussion: lost links in meta compilation

It is quite hard to avoid lost links in meta when
handling expressions.
Here are some tricks, but explanations why it works would
be welcome!
Message posted by pom on 2002/04/03 12:57:35
The following code causes link lost:

meta '. insert' e
  if not e:size=3 or not (e:0 cast Expression) or not (e:1 cast Str)
    return
  e suckup e:0
  e suckup e:1
  var Link:Expression body :> duplicate e:2
  e add (instruction (the_function '. insert' Expression Str Expression) e:0:result e:1:result (argument mapped_constant Expression body))
  e set_void_result

but the following does not:

function externalize e
  arg_rw Expression e
  e:module :> e:module:external
  for (var Int i) 0 e:size-1
    externalize e:i

meta '. insert' e
  if not e:size=3 or not (e:0 cast Expression) or not (e:1 cast Str)
    return
  e suckup e:0
  e suckup e:1
  var Link:Expression body :> duplicate e:2
  externalize body
  e add (instruction (the_function '. insert' Expression Str Expression) e:0:result e:1:result (argument mapped_constant Expression body))
  e set_void_result

So, it seems that using internal module for insertion is dangerous.
However, it is necessary when compiling. So, to compile the previous expression
we need to reset the module correctly. For instance:

meta compile_here e
  if not e:size=1 or not (e:0 cast Expression)
    return
  e suckup e:0
  e add (instruction (the_function '. near_nothing' Expression) e:0:result)
  e add (instruction (the_function '. near' Expression Expression) e:0:result (argument mapped_constant Expression e))
  e add (instruction (the_function '. compile' Expression) e:0:result)
  e set_void_result

But this causes links to be lost!

This is "solved" the following way: duplicating e:0:result and introducing
a new expression near to e (one of these is not sufficient)

meta compile_here e
  if not e:size=1 or not (e:0 cast Expression)
    return
  e suckup e:0
  var Link:Expression e0 :> expression immediat void near e
  var Link:Argument expr :> argument indirect Expression (argument local Address) 0
  e add (instruction (the_function duplicate Expression -> Expression) e:0:result expr)
  e add (instruction (the_function '. near_nothing' Expression) expr)
  e add (instruction (the_function '. near' Expression Expression) expr (argument mapped_constant Expression e0))
  e add (instruction (the_function '. compile' Expression) expr)
  e set_void_result

Argh!!! I would like to understand...
Message posted by pom on 2002/04/03 13:24:43
For the second part, it is still a problem of module, the sequence
e:0:result near_nothing
e:0:result near e0
e:0:result compile
e:0:result near_nothing

avoids the duplication
Message posted by pom on 2002/04/03 13:31:14
The problem may me solved on working on modules:

# recursively set the module (equivalent to near)
method e set_module m
  arg_rw Expression e; arg Module m
  e module :> m
  for (var Int i) 0 e:size-1
    e:i set_module m

# insert (while linked duplicates of inserted value to null Module)
method e raw_insert id value
  arg_rw Expression e ; arg Str id ; arg Expression value
  var Int i := 0
  while i<e:size
    if e:i:is_pure_ident and e:i:ident=id and (addressof e:i:module)=null
      e:arguments 'size :=' e:size+1
      for (var Int j) e:size-2 i step -1
        e:arguments j+1 := e:arguments j
      e:arguments i := addressof duplicate:value
      e:i set_module (null map Module) # could be assumed ?
      i := i+2
    else
      e:i raw_insert id value
      i := i+1
# get the internal module
meta here e
  if e:size=0
    var Link:Argument a :> new Argument
    a locate Module argument_constant
    a constant := addressof e:module
    e set_result a access_read+access_write

##################################
# This allows to write things like:

gvar Expression my_expression :> expression immediat 'Insert here'

my_expression raw_insert "Insert here"
  expression immediat
    for (var Int j) 1 5
      console "yipee!" eol
my_expression remove "Insert here"
my_expression set_module here  # I want to compile in the internal module
my_expression compile
my_expression set_module (null map Module) # to unlink internal Module