1.1 --- a/jitcraft/Parser.cpp Wed Jul 04 19:39:00 2012 -0400
1.2 +++ b/jitcraft/Parser.cpp Wed Jul 04 19:54:53 2012 -0400
1.3 @@ -1,4 +1,5 @@
1.4 -/*
1.5 +/* vim: set ts=4 sw=4 tw=99 et:
1.6 + *
1.7 * Copyright (C) 2012 David Anderson
1.8 *
1.9 * This file is part of JITCraft.
1.10 @@ -440,10 +441,23 @@
1.11 if (!expect(TOK_RPAREN))
1.12 return NULL;
1.13
1.14 - Statement *body = localStatement();
1.15 + // Inside a loop, we force the creation of a scope object. Normally, we
1.16 + // will cull scopes if they have no variables. However inside a loop,
1.17 + // function calls that take references may compute a LIFO object, and to
1.18 + // avoid temporarily leaking many such objects, we ensure that a scope
1.19 + // is present so a LIFO slot can be allocated.
1.20 + if (!enterScope(Scope::BLOCK))
1.21 + return NULL;
1.22 +
1.23 + Statement *body;
1.24 + if (scanner_.peek() == TOK_LBRACE)
1.25 + body = block(scope_);
1.26 + else
1.27 + body = localStatement();
1.28 if (!body)
1.29 return NULL;
1.30
1.31 + scope_ = scope_->enclosing();
1.32 return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
1.33 }
1.34
1.35 @@ -453,10 +467,20 @@
1.36 SourcePosition pos = scanner_.begin();
1.37 scanner_.scan();
1.38
1.39 - Statement *body = block();
1.40 + // See the comment in ::while_() as to why we force a scope.
1.41 + if (!enterScope(Scope::BLOCK))
1.42 + return NULL;
1.43 +
1.44 + Statement *body;
1.45 + if (scanner_.peek() == TOK_LBRACE)
1.46 + body = block(scope_);
1.47 + else
1.48 + body = localStatement();
1.49 if (!body)
1.50 return NULL;
1.51
1.52 + scope_ = scope_->enclosing();
1.53 +
1.54 if (!expect(TOK_WHILE))
1.55 return NULL;
1.56
1.57 @@ -510,16 +534,26 @@
1.58 return NULL;
1.59 }
1.60
1.61 - Statement *body = localStatement();
1.62 + // See the comment in ::while_() as to why we force a scope.
1.63 + if (!enterScope(Scope::BLOCK))
1.64 + return NULL;
1.65 +
1.66 + Statement *body;
1.67 + if (scanner_.peek() == TOK_LBRACE)
1.68 + body = block(scope_);
1.69 + else
1.70 + body = localStatement();
1.71 if (!body)
1.72 return NULL;
1.73
1.74 - Scope *blockScope = NULL;
1.75 + scope_ = scope_->enclosing();
1.76 +
1.77 + Scope *declScope = NULL;
1.78 if (decl && decl->isVariableDeclaration()) {
1.79 - blockScope = scope_->unlinkIfEmpty();
1.80 + declScope = scope_->unlinkIfEmpty();
1.81 scope_ = scope_->enclosing();
1.82 }
1.83 - return new (pool_) ForStatement(pos, blockScope, decl, condition, update, body);
1.84 + return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
1.85 }
1.86
1.87 VariableDeclaration *
1.88 @@ -594,13 +628,13 @@
1.89 }
1.90
1.91 Statement *
1.92 -Parser::block()
1.93 +Parser::block(Scope *scope)
1.94 {
1.95 if (!expect(TOK_LBRACE))
1.96 return NULL;
1.97
1.98 SourcePosition pos = scanner_.begin();
1.99 - if (!enterScope(Scope::BLOCK))
1.100 + if (!scope && !enterScope(Scope::BLOCK))
1.101 return NULL;
1.102
1.103 StatementList *statements = new (pool_) StatementList();
1.104 @@ -611,10 +645,11 @@
1.105 statements->append(pool_, statement);
1.106 }
1.107
1.108 - Scope *blockScope = scope_->unlinkIfEmpty();
1.109 - BlockStatement *block = new (pool_) BlockStatement(pos, blockScope, statements);
1.110 -
1.111 - scope_ = scope_->enclosing();
1.112 + if (!scope) {
1.113 + scope = scope_->unlinkIfEmpty();
1.114 + scope_ = scope_->enclosing();
1.115 + }
1.116 + BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
1.117 return block;
1.118 }
1.119