0
0
Fork 1
mirror of https://git.savannah.gnu.org/git/emacs/org-mode.git synced 2024-08-20 14:19:00 +00:00

Moving nested evaluation from Tasks to Bugs

This commit is contained in:
Dan Davison 2009-07-21 15:48:14 -04:00
parent a58dd8e3af
commit ad7b17c393

View file

@ -208,152 +208,6 @@ would then be [[#sandbox][the sandbox]].
* Tasks [35/57]
** PROPOSED implement fully recursive evaluation machinery
The current parser / evaluator fails with greater levels of nested
function block calls (example below). If we want to overcome this I
think we'd have to redesign some of the evaluation
mechanism. Seeing as we are also facing issues like dealing with
default argument values, and seeing as we now know how we want the
library of babel to behave in addition to the source blocks, now
might be a good time to think about this. It would be nice to do
the full thing at some point, but otoh we may not consider it a
massive priority.
AIui, there are two stages: (i) construct a parse tree, and (ii)
evaluate it and return the value at the root. In the parse tree
each node represents an unevaluated value (either a literal value
or a reference). Node v may have descendent nodes, which represent
values upon which node v's evaluation depends. Once that tree is
constructed, then we evaluate the nodes from the tips towards the
root (a post-order traversal).
[This would also provide a solution for concatenating the STDOUTs
of called blocks, which is a [[*allow%20output%20mode%20to%20return%20stdout%20as%20value][task below]]; we concatenate them in
whatever order the traversal is done in.]
In addition to the variable references (i.e. daughter nodes), each
node would contain the information needed to evaluate that node
(e.g. lang body). Then we would pass a function postorder over the
tree which would call o-b-execute-src-block at each node, finally
returning the value at the root.
Fwiw I made a very tentative small start at stubbing this out in
org-babel-call.el in the 'evaluation' branch. And I've made a start
at sketching a parsing algorithm below.
*** discussion
I believe that this issue should be addressed as a bug rather than as
a point for new development. The code in [[file:lisp/org-babel-ref.el][org-babel-ref.el]] already
resolves variable references in a recursive manner which *should* work
in the same manner regardless of the depth of the number of nested
function calls. This recursive evaluation has the effect of
implicitly constructing the parse tree that your are thinking of
constructing explicitly.
Through using some of the commented out debugging statements in
[[file:lisp/org-babel-ref.el][org-babel-ref.el]] I have looked at what may be going wrong in the
current evaluation setup, and it seems that nested variables are being
set using the =:var= header argument, and these variables are being
overridden by the *default* variables which are being entered through
the new functional syntax (see the demonstration header below).
I believe that once this bug is fixed we should be back to fully
resolution of nested arguments. We should capture this functionality
in a test to ensure that we continue to test it as we move forward. I
can take a look at implementing this once I get a chance.
**** demonstration
After uncommenting the debugging statements located [[file:lisp/org-babel-ref.el::message%20format%20first%20second%20S%20S%20new%20refere%20new%20referent%20debugging][here]] and more
importantly [[file:lisp/org-babel-ref.el::message%20nested%20args%20S%20args%20debugging][here]], we can see that the current reference code does
evaluate the references correctly, and it uses the =:var= header
argument to set =a=8=, however the default variables specified using
the functional syntax in =adder(a=3, b=2)= is overriding this
specification.
#+srcname: adder(a=3, b=2)
#+begin_src python
a + b
#+end_src
#+resname: adder
: 5
#+srcname: after-adder(arg=adder(a=8))
#+begin_src python
arg
#+end_src
#+resname: after-adder
: 5
*** Parse tree algorithm
Seeing as we're just trying to parse a string like
f(a=1,b=g(c=2,d=3)) it shouldn't be too hard. But of course there
are 'proper' parsers written in elisp out there,
e.g. [[http://cedet.sourceforge.net/semantic.shtml][Semantic]]. Perhaps we can find what we need -- our syntax is
pretty much the same as python and R isn't it?
Or, a complete hack, but maybe it would be we easy to transform it
to XML and then parse that with some existing tool?
But if we're doing it ourselves, something very vaguely like this?
(I'm sure there're lots of problems with this)
#+srcname: org-babel-call-parse(call)
#+begin_src python
## we are currently reading a reference name: the name of the root function
whereami = "refname"
node = root = Node()
for c in call_string:
if c == '(':
varnum = 0
whereami = "varname" # now we're reading a variable name
if c == '=':
new = Node()
node.daughters = [node.daughters, new]
new.parent = node
node = new
whereami = "refname"
if c == ',':
whereami = "varname"
varnum += 1
elif c == ')':
node = node.parent
elif c == ' ':
pass
else:
if whereami = "varname":
node.varnames[varnum] += c
elif whereami = "refname":
node.name += c
#+end_src
*** Example that fails
#+srcname: adder(a=0, b=0)
#+begin_src python
a+b
#+end_src
#+srcname: one()
#+begin_src python :results silent
1
#+end_src
This works
#+srcname: level-one-nesting
#+begin_src python :var arg=adder(a=one(),b=one())
arg
#+end_src
But this doesn't
#+srcname: level-one-nesting
#+begin_src python :var arg=adder(a=adder(a=one(),b=one()),b=adder(a=one(),b=one()))
arg
#+end_src
** PROPOSED Default args
This would be good thing to address soon. I'm imagining that
e.g. here, the 'caller' block would return the answer 30. I believe