Push a STMT_BLOCK for functions, avoiding having to do extremely fancy footwork for let declarations. This also simplifies the concept of being at the "top level" in a script.

git-svn-id: svn://10.0.0.236/branches/JS_1_7_ALPHA_BRANCH@199863 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mrbkap%gmail.com
2006-06-14 04:43:43 +00:00
parent 1ade79d950
commit db4d34f03c
2 changed files with 29 additions and 29 deletions

View File

@@ -142,9 +142,6 @@ struct JSTreeContext { /* tree context for semantic checks */
#define TREE_CONTEXT_FINISH(tc) \
((void)0)
#define TREE_CONTEXT_AT_TOP_LEVEL(tc) \
(!((tc)->flags & TCF_IN_FUNCTION) && !(tc)->topStmt)
/*
* Span-dependent instructions are jumps whose span (from the jump bytecode to
* the jump target) may require 2 or 4 bytes of immediate operand.

View File

@@ -691,6 +691,7 @@ FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun,
{
JSStackFrame *fp, frame;
JSObject *funobj;
JSStmtInfo stmtInfo;
uintN oldflags;
JSParseNode *pn;
@@ -707,11 +708,15 @@ FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun,
cx->fp = &frame;
}
js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
oldflags = tc->flags;
tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);
tc->flags |= TCF_IN_FUNCTION;
pn = Statements(cx, ts, tc);
js_PopStatement(tc);
/* Check for falling off the end of a function that returns a value. */
if (pn && JS_HAS_STRICT_OPTION(cx) && (tc->flags & TCF_RETURN_EXPR)) {
if (!CheckFinalReturn(cx, ts, pn))
@@ -1119,7 +1124,7 @@ Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
ts->flags |= TSF_OPERAND;
/* If compiling top-level statements, emit as we go to save space. */
if (TREE_CONTEXT_AT_TOP_LEVEL(tc) && (tc->flags & TCF_COMPILING)) {
if (!tc->topStmt && (tc->flags & TCF_COMPILING)) {
if (cx->fp->fun &&
JS_HAS_STRICT_OPTION(cx) &&
(tc->flags & TCF_RETURN_EXPR)) {
@@ -2888,45 +2893,43 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (!pn)
return NULL;
} else {
if (TREE_CONTEXT_AT_TOP_LEVEL(tc)) {
/*
* XXX This is a hard case that requires more work. In
* particular, in many cases, we're trying to emit code as we
* go. However, this means that we haven't necessarily
* finished processing all let declarations in the implicit
* top-level block when we emit a reference to one of them.
* For now, punt on this and pretend this is a var
* declaration.
*/
CURRENT_TOKEN(ts).type = TOK_VAR;
CURRENT_TOKEN(ts).t_op = JSOP_DEFVAR;
pn = Variables(cx, ts, tc);
if (!pn)
return NULL;
pn->pn_extra |= PNX_POPVAR;
break;
}
/* Set up the block object. */
stmt = FindBlockStatement(tc);
if (stmt && stmt->type == STMT_BLOCK_SCOPE) {
JS_ASSERT(stmt->blockObj);
obj = stmt->blockObj;
} else {
obj = js_NewBlockObject(cx);
if (!obj)
return NULL;
if (stmt) {
/* Convert the block statement into a scope statement. */
obj = js_NewBlockObject(cx);
if (!obj)
return NULL;
JS_ASSERT(stmt->type == STMT_BLOCK);
JS_ASSERT(stmt->downScope == NULL);
stmt->type = STMT_BLOCK_SCOPE;
stmt->downScope = tc->topScopeStmt;
tc->topScopeStmt = stmt;
obj->slots[JSSLOT_PARENT] =
OBJECT_TO_JSVAL(tc->blockChain);
tc->blockChain = stmt->blockObj = obj;
} else {
js_PushBlockScope(tc, &stmtInfo, obj, -1);
/*
* XXX This is a hard case that requires more work. In
* particular, in many cases, we're trying to emit code as
* we go. However, this means that we haven't necessarily
* finished processing all let declarations in the
* implicit top-level block when we emit a reference to
* one of them. For now, punt on this and pretend this is
* a var declaration.
*/
CURRENT_TOKEN(ts).type = TOK_VAR;
CURRENT_TOKEN(ts).t_op = JSOP_DEFVAR;
pn = Variables(cx, ts, tc);
if (!pn)
return NULL;
pn->pn_extra |= PNX_POPVAR;
break;
}
}