Repository: godot
Issue: Exponential Time Complexity with deeply nested function calls
Labels: bug,topic:gdscript,performance

### Godot version

3.3.3.stable.official

### System information

Fedora 31

### Issue description

Godot's GDScript engine rapidly becomes unusable if it has to parse deeply nested function calls (beyond 25 layers or so). That is, a line of GDScript line this

    foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(0))))))))))))))))))))))))

(assuming a function named `foo` is defined in the current scope) is enough to slow Godot down, and beyond a certain point, every additional function call nearly doubles the time it takes for Godot to load the file.

To get exact numbers, I defined a function called `foo`

    func foo(x):
        return x + 1

And, as the first test, I ran code like the following

    # CASE 1
    func _init():
        var a1 = foo(0)
        var a2 = foo(a1)
        ...
        var a20 = foo(a19)
        print(a20)

with varying numbers of local variables in the middle. Since `foo` is defined as `x + 1`, this simply prints the number of times we call `foo`. I benchmarked this by running it as a standalone script using Godot. As expected, the number of times we call `foo` does not greatly increase the total runtime of the program, and I can easily have an `_init` that introduces 2000 local variables as above and which runs in less than one second.

For the second test, I ran similar code but without the intermediate variables

    # CASE 2
    func _init():
        print(foo(foo(foo(...)))

varying the number of nested `foo` calls. This is identical to the above snippet, except that its all compressed to one line. Running in it an identical environment and varying the number of nested function calls produces the following graph, where the blue data points are the code with the local variables (Case 1) and the orange are the code with the nested calls in one line (Case 2).

![Screenshot from 2021-08-25 20-54-13](https://user-images.githubusercontent.com/8659281/130883508-43d0a93e-6627-4aaa-898e-92be18d49383.png)

This is a logarithmic plot, where the X axis varies from 1 to 27 function calls, and the Y axis indicates the number of seconds taken to run (averaged over eight runs, to eliminate variance from individual runs). Case 1 remains relatively constant in runtime, as would be expected, since the cost of an additional function call is negligible compared to the cost of starting the Godot process. On the other hand, Case 2 increases exponentially with every additional function call introduced. Beyond 26 calls, it takes over half a minute to even load the file. I suspect this is a parser issue, as loading the file in the Godot editor (without running the code at all) exhibits the same behavior.

This isn't an issue for hand-written code, generally, as human users should not be writing lines of code that long. But for automation scripts and code generators, individual lines of code can, in not uncommon circumstances, end up being quite deeply nested.

### Steps to reproduce

The attached Godot project contains a script. In that script, there is a single line of code which contains 175 nested function calls on one line. Attempt to open this script in the Godot editor. The editor will hang indefinitely, and the script will not open. Alternatively, try to run the scene from the Godot editor without opening it. Likewise, the runner will hang indefinitely. The intended behavior would be that the project open and run.

### Minimal reproduction project

[Foo.zip](https://github.com/godotengine/godot/files/7050758/Foo.zip)