trueagi-io / hyperon-experimental

OpenCog Hyperon experimental version
https://wiki.opencog.org/w/Hyperon
MIT License
122 stars 43 forks source link

Fix returning values through variables as actual parameters #715

Closed vsbogd closed 3 weeks ago

vsbogd commented 3 weeks ago

When call is made using variable as an actual parameter the variables equality is kept in stack frame bindings to track the value of the variable. At the same time as formal argument variables are local they are not added into the Stack::vars set. Thus it is possible that variable equality is wiped when returning from the next nested call. And if after this call value is assigned to the formal argument variable this value will not be assigned to the actual argument variable.

In the following example:

(= (bar) (function (return ())))

(= (foo $b) (function
  ; fake internal call which wipes variables equalities
  (chain (eval (bar)) $_
  (unify $b value
    (return ())
    (return (Error () \"Unexpected error\")) ))))");

!(chain (eval (foo $a)) $_ $a)

calling (foo $a) adds variable equality { $a = $b } into bindings and $a is kept inside Stack::vars of the first frame because its value should be passed from the first chain's argument to the last one. After executing (chain (function (return ())) $_ bindings are being cleaned up and variable equality is removed from bindings. Thus when $b receives value it is not propagated to the $a

This fix replaces formal argument variables in a body of a called function by the actual argument value or variable. In the particular case above variable $b in (unify $b value (return ()) (return (Error () \"Unexpected error\")) ) is replaced by variable $a and value is assigned properly.