diff options
author | Lars Knoll <lars.knoll@digia.com> | 2012-11-24 22:07:02 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-25 10:20:25 +0100 |
commit | 87b31798170233b92f13ba4d39e0278fdf61e10e (patch) | |
tree | 8d2a106262de90fad6556985bb519f817641ccbd /qv4codegen.cpp | |
parent | 2bd3fa3fc27379a78e8cca0e66eda800729ed8c9 (diff) |
Support for the with statement
Add the with object (list) to the environment, and check properties
there if it's available.
Generate IR statements implementing with() support.
Add two new builtin methods to enter and leave a with scope.
Implement support for the builtin's in masm.
Make sure exception handling works across with scopes.
Change-Id: I8257a16cfccc91a1acedfd740ade711b016b33fd
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'qv4codegen.cpp')
-rw-r--r-- | qv4codegen.cpp | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/qv4codegen.cpp b/qv4codegen.cpp index a8e3c0b24c..33bb064996 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -665,7 +665,7 @@ void Codegen::variableDeclaration(VariableDeclaration *ast) if (! initializer) initializer = _block->CONST(IR::UndefinedType, 0); - if (! _env->parent) { + if (! _env->parent || _function->insideWith) { // it's global code. move(_block->NAME(ast->name.toString(), ast->identifierToken.startLine, ast->identifierToken.startColumn), initializer); } else { @@ -1113,7 +1113,7 @@ IR::Expr *Codegen::identifier(const QString &name, int line, int col) { int index = _env->findMember(name); - if (! _function->hasDirectEval && _env->parent) { + if (! _function->hasDirectEval && !_function->insideWith && _env->parent) { if (index != -1) { return _block->TEMP(index); } @@ -2137,9 +2137,26 @@ bool Codegen::visit(WhileStatement *ast) return false; } -bool Codegen::visit(WithStatement *) +bool Codegen::visit(WithStatement *ast) { - assert(!"with not implemented"); + IR::BasicBlock *withBlock = _function->newBasicBlock(); + + _block->JUMP(withBlock); + _block = withBlock; + int withObject = _block->newTemp(); + _block->MOVE(_block->TEMP(withObject), *expression(ast->expression)); + IR::ExprList *args = _function->New<IR::ExprList>(); + args->init(_block->TEMP(withObject)); + _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_with, 0, 0), args)); + ++_function->insideWith; + statement(ast->statement); + --_function->insideWith; + _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_with, 0, 0), 0)); + + IR::BasicBlock *next = _function->newBasicBlock(); + _block->JUMP(next); + _block = next; + return false; } |