Pass the ExecutionContext into the code generator
authorLars Knoll <lars.knoll@digia.com>
Sun, 2 Dec 2012 18:58:35 +0000 (10:58 -0800)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 3 Dec 2012 14:56:06 +0000 (15:56 +0100)
Use the contexts strict mode flag to correctly parse
eval code inside strict mode sections.
Add code to allow the code generator to throw syntax
errors.

Change-Id: I4e4258b0d0b88952f4d609ec51bbe8db9a1c66a9
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qmljs_objects.cpp
qv4codegen.cpp
qv4codegen_p.h
qv4ecmaobjects.cpp

index e0ebc67..e2cb5cf 100644 (file)
@@ -569,7 +569,7 @@ QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct
                 return 0;
             }
 
-            Codegen cg(ctx->engine->debugger);
+            Codegen cg(ctx);
             globalCode = cg(program, &module, mode);
             if (globalCode) {
                 // only generate other functions if global code generation succeeded.
index c9978ed..893bbb1 100644 (file)
@@ -49,6 +49,7 @@
 #include <QtCore/QStack>
 #include <private/qqmljsast_p.h>
 #include <qmljs_runtime.h>
+#include <qmljs_environment.h>
 #include <cmath>
 #include <iostream>
 #include <cassert>
@@ -206,6 +207,7 @@ protected:
     inline void enterEnvironment(Node *node)
     {
         Environment *e = _cg->newEnvironment(node, _env);
+        e->isStrict = _cg->_context->strictMode;
         _envStack.append(e);
         _env = e;
     }
@@ -248,8 +250,7 @@ protected:
                     || name == QLatin1String("public")
                     || name == QLatin1String("static")
                     || name == QLatin1String("yield")) {
-                // TODO: error!
-                qDebug("TODO: give a proper error message @%u:%u", loc.startLine, loc.startColumn);
+                _cg->throwSyntaxError(loc, "Unexpected strict mode reserved word");
             }
         }
     }
@@ -353,7 +354,7 @@ protected:
     QStack<Environment *> _envStack;
 };
 
-Codegen::Codegen(Debugging::Debugger *debugger)
+Codegen::Codegen(VM::ExecutionContext *context)
     : _module(0)
     , _function(0)
     , _block(0)
@@ -365,7 +366,8 @@ Codegen::Codegen(Debugging::Debugger *debugger)
     , _loop(0)
     , _labelledStatement(0)
     , _tryCleanup(0)
-    , _debugger(debugger)
+    , _context(context)
+    , _debugger(context->engine->debugger)
 {
 }
 
@@ -1021,7 +1023,7 @@ bool Codegen::visit(BinaryExpression *ast)
 
     case QSOperator::Assign:
         if (! (left->asTemp() || left->asName() || left->asSubscript() || left->asMember())) {
-            assert(!"syntax error");
+            throwSyntaxError(ast->lastSourceLocation(), "syntax error");
         }
 
         if (_expr.accept(nx)) {
@@ -1046,7 +1048,7 @@ bool Codegen::visit(BinaryExpression *ast)
     case QSOperator::InplaceURightShift:
     case QSOperator::InplaceXor: {
         if (! (left->asTemp() || left->asName() || left->asSubscript() || left->asMember())) {
-            assert(!"syntax error");
+            throwSyntaxError(ast->lastSourceLocation(), "syntax error");
         }
 
         if (_expr.accept(nx)) {
@@ -1730,7 +1732,7 @@ bool Codegen::visit(BreakStatement *ast)
                 return false;
             }
         }
-        assert(!"throw syntax error");
+        throwSyntaxError(ast->lastSourceLocation(), QString("Undefined label '") + ast->label.toString() + QString("'"));
     }
 
     return false;
@@ -1752,7 +1754,7 @@ bool Codegen::visit(ContinueStatement *ast)
                 return false;
             }
         }
-        assert(!"throw syntax error");
+        throwSyntaxError(ast->lastSourceLocation(), QString("Undefined label '") + ast->label.toString() + QString("'"));
     }
     return false;
 }
@@ -2264,3 +2266,13 @@ bool Codegen::visit(UiSourceElement *)
     assert(!"not implemented");
     return false;
 }
+
+void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail)
+{
+    VM::DiagnosticMessage *msg = new VM::DiagnosticMessage;
+    msg->offset = loc.begin();
+    msg->startLine = loc.startLine;
+    msg->startColumn = loc.startColumn;
+    msg->message = new VM::String(detail);
+    _context->throwSyntaxError(msg);
+}
index a75c872..f1dca06 100644 (file)
@@ -50,6 +50,10 @@ namespace AST {
 class UiParameterList;
 }
 
+namespace VM {
+struct ExecutionContext;
+}
+
 namespace Debugging {
 class Debugger;
 } // namespace Debugging
@@ -57,7 +61,7 @@ class Debugger;
 class Codegen: protected AST::Visitor
 {
 public:
-    Codegen(Debugging::Debugger *debugger);
+    Codegen(VM::ExecutionContext *ctx);
 
     enum Mode {
         GlobalCode,
@@ -329,6 +333,8 @@ protected:
     virtual bool visit(AST::UiScriptBinding *ast);
     virtual bool visit(AST::UiSourceElement *ast);
 
+    void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
+
 private:
     Result _expr;
     QString _property;
@@ -346,6 +352,7 @@ private:
     TryCleanup *_tryCleanup;
     QHash<AST::Node *, Environment *> _envMap;
     QHash<AST::FunctionExpression *, int> _functionMap;
+    VM::ExecutionContext *_context;
     Debugging::Debugger *_debugger;
 
     class ScanFunctions;
index 8edd43c..99375d2 100644 (file)
@@ -1892,7 +1892,7 @@ Value FunctionCtor::construct(ExecutionContext *ctx)
 
     IR::Module module;
 
-    Codegen cg(ctx->engine->debugger);
+    Codegen cg(ctx);
     IR::Function *irf = cg(fe, &module);
 
     EvalInstructionSelection *isel = ctx->engine->iselFactory->create(ctx->engine);