Only build function environments once.
Language currently create a new environment for each invocation.
This is not necessary, the function should just construct the environment when it is declared, save this environment, and then push and bind arguments on a copy of this environment when it is called.
createArgumentsBinding called in initFunction should just create placeholder bindings instead of binding the actual values.
Without additional logic, function declarations mess this up because they are inited before running code (unlike vars which just create empty bindings) and capture their unique local environment.
Function declarations in functions cannot capture the source environment of their parent, but need to capture the unique copy of it used for the invocation.
One solution may be the following binding initialization for functions:
- id
- args creation (empty bindings)
- fun decl binding creation (empty bindings)
- var decl bindings (empty bindings)
- arguments object (empty binding)
Then for each call (in forked env):
- Bind args to values
- Bind function delcs to values
- Bind arguments object to value.