Comment #10 on issue 4285 by little...@chromium.org: Sloppy function in block
https://code.google.com/p/v8/issues/detail?id=4285

At first, I was thinking that this didn't have to ship together with other block-scoped constructs (let and class). However, I came across test cases that look right, but don't work without this feature, like this:

function foo() {
  {
    let x = 1;
    function bar() {
      return x;
    }
    return bar;
  }
}

foo()() would give a ReferenceError without this bug fixed, so it seems pretty essential.

Whenever a FunctionDeclaration is parsed, currently an EmptyStatement is put in the AST. When functions are included in a block scope in sloppy mode, this may have to be replaced by an AssignmentExpression setting the var mode variable to the value of the function. However, the decision can't be made immediately when parsing the FunctionDeclaration because of the stipulation that the transformation isn't done when it would create an early error, as in the following case:

function f() {
  {
    function g() { }
  }
  let g;
}

There, an early error would be created by the var/let conflict if there were an outer level g var binding created. As far as I can tell, this is the only sort of early error which introducing the new function binding can cause. So the coding task is to take all the EmptyStatements created by function declarations and transform them into AssignmentExpressions *after* parsing the whole function and checking whether there is an outer-level let binding with the same name.

Looking at the code, I have a preliminary design:

Make a new AST node type called DelegateStatement. A DelegateStatement simply refers to a different statement, which can be overwritten. Each AstVisitor would have code to interpret a DelegateStatement as its underlying statement. When a sloppy-mode block-scoped function declaration is reached, it is treated as a let-mode binding (just like --harmony_sloppy_function), and the EmptyStatement is wrapped in a DelegateStatement.

Scopes are given a built-in hashtable mapping sloppy-mode block-scoped function names to lists of DelegateStatements which might need to be overwritten as AssignmentExpressions, which is constructed incrementally when parsing the inner FunctionDeclarations. When the end of the function is reached, for each function name in the table, if there is not a lexical binding of that name, in the outer scope of the function, then declare a var binding of that name, and replace the underlying statement of each DelegateStatement with the appropriate assignment.

An alternative:

Rather than introducing DelegateStatements and this hashtable, function declarations would be parsed as some sort of annotated EmptyStatement (possibly a different AstNode). Replacing these would be implemented as an AstVisitor traversal, with a new way to replace a statement with a block (currently not exposed directly). Or, maybe there could be some sort of crossreference table, though indexing could get out of sync with desugaring, and it could be difficult to figure out how to point to the parent block (since there are no upwards pointers in the AST). The logic will have to work across both blocks and CaseClauses. Any of these possibilities sounds pretty messy and difficult to get right.

WDYT?

--
You received this message because this project is configured to send all issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to