forked from mirrors/org-mode
Moving nested evaluation from Tasks to Bugs
This commit is contained in:
parent
a58dd8e3af
commit
ad7b17c393
146
org-babel.org
146
org-babel.org
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue