evalf / nutils

The nutils project
http://www.nutils.org/
MIT License
88 stars 48 forks source link

Evaluable to Python code compiler #859

Closed joostvanzwieten closed 3 months ago

joostvanzwieten commented 6 months ago

Previously Evaluables were evaluated by looping over all dependencies and calling Evaluable.evalf. For 1 + 2 + 3 (not simplified) this boils down to

serialized = [
    [Constant(1).evalf],
    [Constant(2).evalf],
    [Constant(3).evalf],
    [Add.evalf, 0, 1],
    [Add.evalf, 3, 2],
]
def eval():
    values = []
    for op, *args in serialized:
        values.append(op(*map(values.get, args)))
    return values[-1]

This PR replaces this mechanism by generating Python code via the new evaluable.compile() function, which produces:

c0 = 1
c1 = 2
c2 = 3
def eval():
    v3 = numpy.add(c0, c1)
    v4 = numpy.add(v3, c2)
    return v4

In addition, subtrees that are constant are cached for a second call, providing a slight performance improvement.

joostvanzwieten commented 3 months ago

I created commit 8159737 as a suggestion for making comments inline, simply by making them an argument of Assign. It's crude but effective, and I personally find the resulting code easier to follow.

I've replaced _pyast.Comment with _pyast.CommentBlock(comment, statements), which appends comment to the next line if the statements is a single line.