diff options
Diffstat (limited to 'src/qml')
117 files changed, 5098 insertions, 7260 deletions
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h index 63fd4b0dac..0be6ca96ea 100644 --- a/src/qml/animations/qabstractanimationjob_p.h +++ b/src/qml/animations/qabstractanimationjob_p.h @@ -56,6 +56,8 @@ #include <QtCore/private/qabstractanimation_p.h> #include <vector> +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class QAnimationGroupJob; diff --git a/src/qml/animations/qanimationgroupjob_p.h b/src/qml/animations/qanimationgroupjob_p.h index fb567dc019..b01b2f3b36 100644 --- a/src/qml/animations/qanimationgroupjob_p.h +++ b/src/qml/animations/qanimationgroupjob_p.h @@ -54,6 +54,8 @@ #include "private/qabstractanimationjob_p.h" #include <QtCore/qdebug.h> +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class Q_QML_PRIVATE_EXPORT QAnimationGroupJob : public QAbstractAnimationJob diff --git a/src/qml/animations/qanimationjobutil_p.h b/src/qml/animations/qanimationjobutil_p.h index 0bb9e83b2d..e3d6fe9178 100644 --- a/src/qml/animations/qanimationjobutil_p.h +++ b/src/qml/animations/qanimationjobutil_p.h @@ -51,6 +51,8 @@ // We mean it. // +QT_REQUIRE_CONFIG(qml_animation); + #define RETURN_IF_DELETED(func) \ { \ bool *prevWasDeleted = m_wasDeleted; \ diff --git a/src/qml/animations/qcontinuinganimationgroupjob_p.h b/src/qml/animations/qcontinuinganimationgroupjob_p.h index baf4ff1ae5..c67b8d39ad 100644 --- a/src/qml/animations/qcontinuinganimationgroupjob_p.h +++ b/src/qml/animations/qcontinuinganimationgroupjob_p.h @@ -53,6 +53,8 @@ #include "private/qanimationgroupjob_p.h" +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class Q_QML_PRIVATE_EXPORT QContinuingAnimationGroupJob : public QAnimationGroupJob diff --git a/src/qml/animations/qparallelanimationgroupjob_p.h b/src/qml/animations/qparallelanimationgroupjob_p.h index 67ba626247..0265fe3274 100644 --- a/src/qml/animations/qparallelanimationgroupjob_p.h +++ b/src/qml/animations/qparallelanimationgroupjob_p.h @@ -53,6 +53,8 @@ #include "private/qanimationgroupjob_p.h" +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class Q_QML_PRIVATE_EXPORT QParallelAnimationGroupJob : public QAnimationGroupJob diff --git a/src/qml/animations/qpauseanimationjob_p.h b/src/qml/animations/qpauseanimationjob_p.h index d0e8d57fc7..6c9bbf0dab 100644 --- a/src/qml/animations/qpauseanimationjob_p.h +++ b/src/qml/animations/qpauseanimationjob_p.h @@ -53,6 +53,8 @@ #include <private/qanimationgroupjob_p.h> +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class Q_QML_PRIVATE_EXPORT QPauseAnimationJob : public QAbstractAnimationJob diff --git a/src/qml/animations/qsequentialanimationgroupjob_p.h b/src/qml/animations/qsequentialanimationgroupjob_p.h index 800f0c3b90..13f9806be1 100644 --- a/src/qml/animations/qsequentialanimationgroupjob_p.h +++ b/src/qml/animations/qsequentialanimationgroupjob_p.h @@ -53,6 +53,8 @@ #include <private/qanimationgroupjob_p.h> +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class QPauseAnimationJob; diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 4a1b27d7aa..9de27a2588 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -96,23 +96,24 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, cons declarationsOverride = nullptr; } -QString Object::sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation) +QString IRBuilder::sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation) { QSet<int> functionNames; - for (Function *f = functions->first; f; f = f->next) { - QQmlJS::AST::FunctionDeclaration *function = f->functionDeclaration; - Q_ASSERT(function); - *errorLocation = function->identifierToken; + for (auto functionit = obj->functionsBegin(); functionit != obj->functionsEnd(); ++functionit) { + Function *f = functionit.ptr; + errorLocation->startLine = f->location.line; + errorLocation->startColumn = f->location.column; if (functionNames.contains(f->nameIndex)) return tr("Duplicate method name"); functionNames.insert(f->nameIndex); - for (QmlIR::Signal *s = qmlSignals->first; s; s = s->next) { + for (auto signalit = obj->signalsBegin(); signalit != obj->signalsEnd(); ++signalit) { + QmlIR::Signal *s = signalit.ptr; if (s->nameIndex == f->nameIndex) return tr("Duplicate method name"); } - const QString name = function->name.toString(); + const QString name = stringAt(f->nameIndex); if (name.at(0).isUpper()) return tr("Method names cannot begin with an upper case letter"); if (illegalNames.contains(name)) @@ -601,7 +602,7 @@ bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qu return false; QQmlJS::AST::SourceLocation loc; - QString error = obj->sanityCheckFunctionNames(illegalNames, &loc); + QString error = sanityCheckFunctionNames(obj, illegalNames, &loc); if (!error.isEmpty()) { recordError(loc, error); return false; @@ -976,21 +977,21 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node) const int index = _object->functionsAndExpressions->append(foe); Function *f = New<Function>(); - f->functionDeclaration = funDecl; QQmlJS::AST::SourceLocation loc = funDecl->identifierToken; f->location.line = loc.startLine; f->location.column = loc.startColumn; f->index = index; f->nameIndex = registerString(funDecl->name.toString()); - int formalsCount = 0; - for (QQmlJS::AST::FormalParameterList *it = funDecl->formals; it; it = it->next) - ++formalsCount; + const QStringList formals = funDecl->formals->formals(); + int formalsCount = formals.size(); f->formals.allocate(pool, formalsCount); int i = 0; - for (QQmlJS::AST::FormalParameterList *it = funDecl->formals; it; it = it->next, ++i) - f->formals[i] = registerString(it->name.toString()); + for (const QString &arg : formals) { + f->formals[i] = registerString(arg); + ++i; + } _object->appendFunction(f); } else { @@ -1824,6 +1825,9 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil } scan.leaveEnvironment(); + if (hasError) + return QVector<int>(); + _context = nullptr; for (int i = 0; i < functions.count(); ++i) { @@ -1841,10 +1845,10 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil else name = QStringLiteral("%qml-expression-entry"); - QQmlJS::AST::SourceElements *body; - if (function) - body = function->body ? function->body->elements : nullptr; - else { + QQmlJS::AST::StatementList *body; + if (function) { + body = function->body; + } else { // Synthesize source elements. QQmlJS::MemoryPool *pool = jsEngine->pool(); @@ -1854,8 +1858,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil QQmlJS::AST::ExpressionNode *expr = node->expressionCast(); stmt = new (pool) QQmlJS::AST::ExpressionStatement(expr); } - QQmlJS::AST::SourceElement *element = new (pool) QQmlJS::AST::StatementSourceElement(stmt); - body = new (pool) QQmlJS::AST::SourceElements(element); + body = new (pool) QQmlJS::AST::StatementList(stmt); body = body->finish(); } @@ -1869,7 +1872,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil return runtimeFunctionIndices; } -int JSCodeGen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::SourceElements *body) +int JSCodeGen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::StatementList *body) { int qmlContextTemp = -1; int importedScriptsTemp = -1; @@ -2430,8 +2433,6 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO } } - QQmlJS::Engine *jsParserEngine = &output->jsParserEngine; - const quint32_le *functionIdx = serializedObject->functionOffsetTable(); for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) { QmlIR::Function *f = pool->New<QmlIR::Function>(); @@ -2442,26 +2443,10 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO f->location = compiledFunction->location; f->nameIndex = compiledFunction->nameIndex; - QQmlJS::AST::FormalParameterList *paramList = nullptr; - const quint32_le *formalNameIdx = compiledFunction->formalsTable(); - for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx) { - const QString formal = unit->stringAt(*formalNameIdx); - QStringRef paramNameRef = jsParserEngine->newStringRef(formal); - - if (paramList) - paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, paramNameRef); - else - paramList = new (pool) QQmlJS::AST::FormalParameterList(paramNameRef); - } - - if (paramList) - paramList = paramList->finish(); - const QString name = unit->stringAt(compiledFunction->nameIndex); - f->functionDeclaration = new(pool) QQmlJS::AST::FunctionDeclaration(jsParserEngine->newStringRef(name), paramList, /*body*/nullptr); f->formals.allocate(pool, int(compiledFunction->nFormals)); - formalNameIdx = compiledFunction->formalsTable(); + const quint32_le *formalNameIdx = compiledFunction->formalsTable(); for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx) f->formals[i] = *formalNameIdx; diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index c2cf18e3c4..14f59dd7e8 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -57,7 +57,6 @@ #include <private/qqmljsmemorypool_p.h> #include <private/qv4codegen_p.h> #include <private/qv4compiler_p.h> -#include <private/qqmljslexer_p.h> #include <QTextStream> #include <QCoreApplication> @@ -325,7 +324,6 @@ struct Alias : public QV4::CompiledData::Alias struct Function { - QQmlJS::AST::FunctionDeclaration *functionDeclaration; QV4::CompiledData::Location location; int nameIndex; quint32 index; // index in parsedQML::functions @@ -400,8 +398,6 @@ public: void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation()); - QString sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation); - QString appendEnum(Enum *enumeration); QString appendSignal(Signal *signal); QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation); @@ -548,6 +544,8 @@ public: static bool isStatementNodeScript(QQmlJS::AST::Statement *statement); static bool isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement); + QString sanityCheckFunctionNames(Object *obj, const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation); + QList<QQmlJS::DiagnosticMessage> errors; QSet<QString> illegalNames; @@ -623,7 +621,7 @@ struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen int defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, - AST::SourceElements *body) override; + AST::StatementList *body) override; protected: void beginFunctionBodyHook() override; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a896745b3f..34c2c3ffc9 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -466,10 +466,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio for (const QString ¶m : qAsConst(parameters)) { QStringRef paramNameRef = compiler->newStringRef(param); - if (paramList) - paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, paramNameRef); - else - paramList = new (pool) QQmlJS::AST::FormalParameterList(paramNameRef); + QQmlJS::AST::BindingElement *b = new (pool) QQmlJS::AST::BindingElement(paramNameRef, nullptr); + paramList = new (pool) QQmlJS::AST::FormalParameterList(paramList, b); } if (paramList) @@ -490,11 +488,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } if (!functionDeclaration) { QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(foe->node); - QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement); - QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement); - elements = elements->finish(); - - QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements); + QQmlJS::AST::StatementList *body = new (pool) QQmlJS::AST::StatementList(statement); + body = body->finish(); functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body); functionDeclaration->lbraceToken = functionDeclaration->functionToken diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index e69f2cd310..9bd9d82e0d 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -181,6 +181,12 @@ public: return addJumpInstruction(data); } + Q_REQUIRED_RESULT Jump jumpNotUndefined() + { + Instruction::JumpNotUndefined data; + return addJumpInstruction(data); + } + void jumpStrictEqual(const StackSlot &lhs, const Label &target) { Instruction::CmpStrictEqual cmp; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 8ada1d505e..f7617c66de 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -58,6 +58,8 @@ #include <cmath> #include <iostream> +static const bool disable_lookups = false; + #ifdef CONST #undef CONST #endif @@ -120,7 +122,10 @@ void Codegen::generateFromProgram(const QString &fileName, ScanFunctions scan(this, sourceCode, mode); scan(node); - defineFunction(QStringLiteral("%entry"), node, nullptr, node->elements); + if (hasError) + return; + + defineFunction(QStringLiteral("%entry"), node, nullptr, node->statements); } void Codegen::enterContext(Node *node) @@ -337,45 +342,10 @@ Codegen::Reference Codegen::expression(ExpressionNode *ast) return r.result(); } -Codegen::Result Codegen::sourceElement(SourceElement *ast) -{ - Result r(nx); - if (ast) { - qSwap(_expr, r); - accept(ast); - qSwap(_expr, r); - } - return r; -} - -void Codegen::functionBody(FunctionBody *ast) -{ - if (ast) - sourceElements(ast->elements); -} - void Codegen::program(Program *ast) { if (ast) { - sourceElements(ast->elements); - } -} - -void Codegen::sourceElements(SourceElements *ast) -{ - bool _requiresReturnValue = false; - qSwap(_requiresReturnValue, requiresReturnValue); - for (SourceElements *it = ast; it; it = it->next) { - if (!it->next) - qSwap(_requiresReturnValue, requiresReturnValue); - sourceElement(it->element); - if (hasError) - return; - if (StatementSourceElement *sse = AST::cast<StatementSourceElement *>(it->element)) { - if (AST::cast<ThrowStatement *>(sse->statement) || - AST::cast<ReturnStatement *>(sse->statement)) - return; - } + statementList(ast->statements); } } @@ -389,7 +359,10 @@ void Codegen::statementList(StatementList *ast) it->next->statement->kind == Statement::Kind_ContinueStatement || it->next->statement->kind == Statement::Kind_ReturnStatement) requiresReturnValue = _requiresReturnValue; - statement(it->statement); + if (FunctionDeclaration *decl = cast<FunctionDeclaration *>(it->statement)) + statement(decl); + else + statement(static_cast<Statement *>(it->statement)); requiresReturnValue = false; if (it->statement->kind == Statement::Kind_ThrowStatement || it->statement->kind == Statement::Kind_BreakStatement || @@ -424,6 +397,67 @@ void Codegen::variableDeclarationList(VariableDeclarationList *ast) } } +void Codegen::initializeAndDestructureBindingElement(AST::BindingElement *e, const Codegen::Reference &baseRef) +{ + RegisterScope scope(this); + Reference varToStore = e->name.isNull() ? Reference::fromStackSlot(this, bytecodeGenerator->newRegister()) : referenceForName(e->name, true); + if (e->initializer && baseRef == varToStore) { + baseRef.loadInAccumulator(); + BytecodeGenerator::Jump jump = bytecodeGenerator->jumpNotUndefined(); + expression(e->initializer).loadInAccumulator(); + varToStore.storeConsumeAccumulator(); + jump.link(); + } else if (e->initializer) { + baseRef.loadInAccumulator(); + BytecodeGenerator::Jump jump = bytecodeGenerator->jumpNotUndefined(); + expression(e->initializer).loadInAccumulator(); + jump.link(); + varToStore.storeConsumeAccumulator(); + } else if (baseRef != varToStore) { + baseRef.loadInAccumulator(); + varToStore.storeConsumeAccumulator(); + } + if (BindingElementList *l = e->elementList()) { + destructureElementList(varToStore, l); + } else if (BindingPropertyList *p = e->propertyList()) { + destructurePropertyList(varToStore, p); + } +} + +void Codegen::destructurePropertyList(const Codegen::Reference &object, BindingPropertyList *bindingList) +{ + RegisterScope scope(this); + + for (BindingPropertyList *p = bindingList; p; p = p->next) { + RegisterScope scope(this); + QString propertyName = p->propertyName->asString(); + Reference property = Reference::fromMember(object, propertyName); + initializeAndDestructureBindingElement(p->binding, property); + } +} + +void Codegen::destructureElementList(const Codegen::Reference &array, BindingElementList *bindingList) +{ + RegisterScope scope(this); + + int index = 0; + for (BindingElementList *p = bindingList; p; p = p->next) { + for (Elision *elision = p->elision; elision; elision = elision->next) + ++index; + + RegisterScope scope(this); + + Reference idx = Reference::fromConst(this, Encode(index)); + Reference property = Reference::fromSubscript(array, idx); + BindingElement *e = p->bindingElement(); + if (e) + initializeAndDestructureBindingElement(e, property); + else { + throwSyntaxError(bindingList->firstSourceLocation(), QString::fromLatin1("Support for rest elements in binding arrays not implemented!")); + } + } +} + bool Codegen::visit(ArgumentList *) { @@ -485,19 +519,13 @@ bool Codegen::visit(FormalParameterList *) return false; } -bool Codegen::visit(FunctionBody *) -{ - Q_UNREACHABLE(); - return false; -} - bool Codegen::visit(Program *) { Q_UNREACHABLE(); return false; } -bool Codegen::visit(PropertyAssignmentList *) +bool Codegen::visit(PropertyDefinitionList *) { Q_UNREACHABLE(); return false; @@ -515,12 +543,6 @@ bool Codegen::visit(PropertyGetterSetter *) return false; } -bool Codegen::visit(SourceElements *) -{ - Q_UNREACHABLE(); - return false; -} - bool Codegen::visit(StatementList *) { Q_UNREACHABLE(); @@ -1279,6 +1301,12 @@ bool Codegen::visit(CallExpression *ast) if (hasError) return false; + handleCall(base, calldata); + return false; +} + +void Codegen::handleCall(Reference &base, Arguments calldata) +{ //### Do we really need all these call instructions? can's we load the callee in a temp? if (base.type == Reference::QmlScopeObject) { Instruction::CallScopeObjectProperty call; @@ -1295,7 +1323,7 @@ bool Codegen::visit(CallExpression *ast) call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else if (base.type == Reference::Member) { - if (useFastLookups) { + if (!disable_lookups && useFastLookups) { Instruction::CallPropertyLookup call; call.base = base.propertyBase.stackSlot(); call.lookupIndex = registerGetterLookup(base.propertyNameIndex); @@ -1323,7 +1351,7 @@ bool Codegen::visit(CallExpression *ast) call.argc = calldata.argc; call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); - } else if (useFastLookups && base.global) { + } else if (!disable_lookups && useFastLookups && base.global) { Instruction::CallGlobalLookup call; call.index = registerGlobalGetterLookup(base.nameAsIndex()); call.argc = calldata.argc; @@ -1346,7 +1374,6 @@ bool Codegen::visit(CallExpression *ast) } _expr.setResult(Reference::fromAccumulator(this)); - return false; } Codegen::Arguments Codegen::pushArgs(ArgumentList *args) @@ -1378,6 +1405,30 @@ Codegen::Arguments Codegen::pushArgs(ArgumentList *args) return { argc, calldata }; } +Codegen::Arguments Codegen::pushTemplateArgs(TemplateLiteral *args) +{ + int argc = 0; + for (TemplateLiteral *it = args; it; it = it->next) + ++argc; + + if (!argc) + return { 0, 0 }; + + int calldata = bytecodeGenerator->newRegisterArray(argc); + + argc = 0; + for (TemplateLiteral *it = args; it && it->expression; it = it->next) { + RegisterScope scope(this); + Reference e = expression(it->expression); + if (hasError) + break; + (void) e.storeOnStack(calldata + argc); + ++argc; + } + + return { argc, calldata }; +} + bool Codegen::visit(ConditionalExpression *ast) { if (hasError) @@ -1490,6 +1541,86 @@ bool Codegen::visit(FieldMemberExpression *ast) return false; } +bool Codegen::visit(TaggedTemplate *ast) +{ + if (hasError) + return false; + + RegisterScope scope(this); + + Reference base = expression(ast->base); + if (hasError) + return false; + switch (base.type) { + case Reference::Member: + case Reference::Subscript: + base = base.asLValue(); + break; + case Reference::Name: + break; + default: + base = base.storeOnStack(); + break; + } + + int arrayTemp = createTemplateArray(ast->templateLiteral); + Q_UNUSED(arrayTemp); + auto calldata = pushTemplateArgs(ast->templateLiteral); + if (hasError) + return false; + ++calldata.argc; + Q_ASSERT(calldata.argv == arrayTemp + 1); + --calldata.argv; + + handleCall(base, calldata); + return false; + + + return false; +} + +int Codegen::createTemplateArray(TemplateLiteral *t) +{ + int arrayTemp = bytecodeGenerator->newRegister(); + + RegisterScope scope(this); + + int argc = 0; + int args = -1; + auto push = [this, &argc, &args](const QStringRef &arg) { + int temp = bytecodeGenerator->newRegister(); + if (args == -1) + args = temp; + Instruction::LoadRuntimeString instr; + instr.stringId = registerString(arg.toString()); + bytecodeGenerator->addInstruction(instr); + Instruction::StoreReg store; + store.reg = temp; + bytecodeGenerator->addInstruction(store); + + ++argc; + }; + + for (TemplateLiteral *it = t; it; it = it->next) + push(it->value); + + if (args == -1) { + Q_ASSERT(argc == 0); + args = 0; + } + + Instruction::DefineArray call; + call.argc = argc; + call.args = Moth::StackSlot::createRegister(args); + bytecodeGenerator->addInstruction(call); + + Instruction::StoreReg store; + store.reg = arrayTemp; + bytecodeGenerator->addInstruction(store); + + return arrayTemp; +} + bool Codegen::visit(FunctionExpression *ast) { if (hasError) @@ -1497,7 +1628,7 @@ bool Codegen::visit(FunctionExpression *ast) RegisterScope scope(this); - int function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : nullptr); + int function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body); loadClosure(function); _expr.setResult(Reference::fromAccumulator(this)); return false; @@ -1705,7 +1836,7 @@ bool Codegen::visit(ObjectLiteral *ast) RegisterScope scope(this); - for (PropertyAssignmentList *it = ast->properties; it; it = it->next) { + for (PropertyDefinitionList *it = ast->properties; it; it = it->next) { QString name = it->assignment->name->asString(); if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) { Reference value = expression(nv->value); @@ -1721,7 +1852,7 @@ bool Codegen::visit(ObjectLiteral *ast) v.rvalue = value.storeOnStack(); } else if (PropertyGetterSetter *gs = AST::cast<AST::PropertyGetterSetter *>(it->assignment)) { - const int function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : nullptr); + const int function = defineFunction(name, gs, gs->formals, gs->functionBody); ObjectPropertyValue &v = valueMap[name]; if (v.rvalue.isValid() || (gs->type == PropertyGetterSetter::Getter && v.hasGetter()) || @@ -1933,6 +2064,49 @@ bool Codegen::visit(StringLiteral *ast) return false; } +bool Codegen::visit(TemplateLiteral *ast) +{ + if (hasError) + return false; + + Instruction::LoadRuntimeString instr; + instr.stringId = registerString(ast->value.toString()); + bytecodeGenerator->addInstruction(instr); + + if (ast->expression) { + RegisterScope scope(this); + int temp = bytecodeGenerator->newRegister(); + Instruction::StoreReg store; + store.reg = temp; + bytecodeGenerator->addInstruction(store); + + Reference expr = expression(ast->expression); + + if (ast->next) { + int temp2 = bytecodeGenerator->newRegister(); + expr.storeOnStack(temp2); + visit(ast->next); + + Instruction::Add instr; + instr.lhs = temp2; + bytecodeGenerator->addInstruction(instr); + } else { + expr.loadInAccumulator(); + } + + Instruction::Add instr; + instr.lhs = temp; + bytecodeGenerator->addInstruction(instr); + } + + auto r = Reference::fromAccumulator(this); + r.isReadonly = true; + + _expr.setResult(r); + return false; + +} + bool Codegen::visit(ThisExpression *) { if (hasError) @@ -2024,7 +2198,7 @@ bool Codegen::visit(FunctionDeclaration * ast) RegisterScope scope(this); if (_context->compilationMode == QmlBinding) - Reference::fromName(this, ast->name.toString()).loadInAccumulator(); + referenceForName(ast->name.toString(), true).loadInAccumulator(); _expr.accept(nx); return false; } @@ -2038,14 +2212,7 @@ static bool endsWithReturn(Node *node) if (AST::cast<ThrowStatement *>(node)) return true; if (Program *p = AST::cast<Program *>(node)) - return endsWithReturn(p->elements); - if (SourceElements *se = AST::cast<SourceElements *>(node)) { - while (se->next) - se = se->next; - return endsWithReturn(se->element); - } - if (StatementSourceElement *sse = AST::cast<StatementSourceElement *>(node)) - return endsWithReturn(sse->statement); + return endsWithReturn(p->statements); if (StatementList *sl = AST::cast<StatementList *>(node)) { while (sl->next) sl = sl->next; @@ -2060,10 +2227,8 @@ static bool endsWithReturn(Node *node) int Codegen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, - AST::SourceElements *body) + AST::StatementList *body) { - Q_UNUSED(formals); - enterContext(ast); if (_context->functionIndex >= 0) @@ -2151,7 +2316,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, for (const Context::Member &member : qAsConst(_context->members)) { if (member.function) { const int function = defineFunction(member.function->name.toString(), member.function, member.function->formals, - member.function->body ? member.function->body->elements : nullptr); + member.function->body); loadClosure(function); if (! _context->parent) { Reference::fromName(this, member.function->name.toString()).storeConsumeAccumulator(); @@ -2164,7 +2329,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, } } if (_context->usesArgumentsObject == Context::ArgumentsObjectUsed) { - if (_context->isStrict) { + if (_context->isStrict || !formals->isSimpleParameterList()) { Instruction::CreateUnmappedArgumentsObject setup; bytecodeGenerator->addInstruction(setup); } else { @@ -2179,9 +2344,28 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, bytecodeGenerator->addInstruction(convert); } + int argc = 0; + while (formals) { + if (AST::BindingRestElement *r = formals->bindingRestElement()) { + Q_ASSERT(!formals->next); + Instruction::CreateRestParameter rest; + rest.argIndex = argc; + bytecodeGenerator->addInstruction(rest); + Reference f = referenceForName(r->name.toString(), true); + f.storeConsumeAccumulator(); + } else if (BindingElement *e = formals->bindingElement()) { + Reference arg = referenceForName(e->name, true); + initializeAndDestructureBindingElement(e, arg); + } else { + Q_UNREACHABLE(); + } + formals = formals->next; + ++argc; + } + beginFunctionBodyHook(); - sourceElements(body); + statementList(body); if (hasError || !endsWithReturn(body)) { bytecodeGenerator->setLocation(ast->lastSourceLocation()); @@ -2215,24 +2399,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, return leaveContext(); } -bool Codegen::visit(FunctionSourceElement *ast) -{ - if (hasError) - return false; - - statement(ast->declaration); - return false; -} - -bool Codegen::visit(StatementSourceElement *ast) -{ - if (hasError) - return false; - - statement(ast->statement); - return false; -} - bool Codegen::visit(Block *ast) { if (hasError) @@ -3306,7 +3472,7 @@ void Codegen::Reference::storeAccumulator() const } } return; case Member: - if (codegen->useFastLookups) { + if (!disable_lookups && codegen->useFastLookups) { Instruction::SetLookup store; store.base = propertyBase.stackSlot(); store.index = codegen->registerSetterLookup(propertyNameIndex); @@ -3422,7 +3588,7 @@ QT_WARNING_POP return; } } - if (codegen->useFastLookups && global) { + if (!disable_lookups && codegen->useFastLookups && global) { Instruction::LoadGlobalLookup load; load.index = codegen->registerGlobalGetterLookup(nameAsIndex()); codegen->bytecodeGenerator->addInstruction(load); @@ -3433,7 +3599,7 @@ QT_WARNING_POP } return; case Member: - if (codegen->useFastLookups) { + if (!disable_lookups && codegen->useFastLookups) { if (propertyBase.isAccumulator()) { Instruction::GetLookupA load; load.index = codegen->registerGetterLookup(propertyNameIndex); diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index d51dc29517..5ff0aa5c30 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -197,6 +197,8 @@ public: Reference &operator =(const Reference &other); bool operator==(const Reference &other) const; + bool operator!=(const Reference &other) const + { return !(*this == other); } bool isValid() const { return type != Invalid; } bool loadTriggersSideEffect() const { @@ -493,7 +495,7 @@ protected: // Returns index in _module->functions virtual int defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, - AST::SourceElements *body); + AST::StatementList *body); void statement(AST::Statement *ast); void statement(AST::ExpressionNode *ast); @@ -501,17 +503,18 @@ protected: const BytecodeGenerator::Label *iffalse, bool trueBlockFollowsCondition); Reference expression(AST::ExpressionNode *ast); - Result sourceElement(AST::SourceElement *ast); void accept(AST::Node *node); - void functionBody(AST::FunctionBody *ast); void program(AST::Program *ast); - void sourceElements(AST::SourceElements *ast); void statementList(AST::StatementList *ast); void variableDeclaration(AST::VariableDeclaration *ast); void variableDeclarationList(AST::VariableDeclarationList *ast); + void initializeAndDestructureBindingElement(AST::BindingElement *e, const Reference &baseRef); + void destructurePropertyList(const Reference &object, AST::BindingPropertyList *bindingList); + void destructureElementList(const Reference &array, AST::BindingElementList *bindingList); + Reference referenceForName(const QString &name, bool lhs); void loadClosure(int index); @@ -531,12 +534,10 @@ protected: bool visit(AST::Elision *ast) override; bool visit(AST::Finally *ast) override; bool visit(AST::FormalParameterList *ast) override; - bool visit(AST::FunctionBody *ast) override; bool visit(AST::Program *ast) override; bool visit(AST::PropertyNameAndValue *ast) override; - bool visit(AST::PropertyAssignmentList *ast) override; + bool visit(AST::PropertyDefinitionList *ast) override; bool visit(AST::PropertyGetterSetter *ast) override; - bool visit(AST::SourceElements *ast) override; bool visit(AST::StatementList *ast) override; bool visit(AST::UiArrayMemberList *ast) override; bool visit(AST::UiImport *ast) override; @@ -561,6 +562,7 @@ protected: bool visit(AST::DeleteExpression *ast) override; bool visit(AST::FalseLiteral *ast) override; bool visit(AST::FieldMemberExpression *ast) override; + bool visit(AST::TaggedTemplate *ast) override; bool visit(AST::FunctionExpression *ast) override; bool visit(AST::IdentifierExpression *ast) override; bool visit(AST::NestedExpression *ast) override; @@ -576,6 +578,7 @@ protected: bool visit(AST::PreIncrementExpression *ast) override; bool visit(AST::RegExpLiteral *ast) override; bool visit(AST::StringLiteral *ast) override; + bool visit(AST::TemplateLiteral *ast) override; bool visit(AST::ThisExpression *ast) override; bool visit(AST::TildeExpression *ast) override; bool visit(AST::TrueLiteral *ast) override; @@ -585,10 +588,6 @@ protected: bool visit(AST::VoidExpression *ast) override; bool visit(AST::FunctionDeclaration *ast) override; - // source elements - bool visit(AST::FunctionSourceElement *ast) override; - bool visit(AST::StatementSourceElement *ast) override; - // statements bool visit(AST::Block *ast) override; bool visit(AST::BreakStatement *ast) override; @@ -633,6 +632,10 @@ public: Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right); struct Arguments { int argc; int argv; }; Arguments pushArgs(AST::ArgumentList *args); + void handleCall(Reference &base, Arguments calldata); + + Arguments pushTemplateArgs(AST::TemplateLiteral *args); + int createTemplateArray(AST::TemplateLiteral *t); void setUseFastLookups(bool b) { useFastLookups = b; } diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 8dcc068a06..a17ee43446 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -96,8 +96,9 @@ static QString cacheFilePath(const QUrl &url) #endif CompilationUnit::CompilationUnit(const Unit *unitData) - : data(unitData) -{} +{ + data = unitData; +} #ifndef V4_BOOTSTRAP CompilationUnit::~CompilationUnit() @@ -157,15 +158,15 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) } if (data->jsClassTableSize) { - runtimeClasses = (QV4::InternalClass**)malloc(data->jsClassTableSize * sizeof(QV4::InternalClass*)); + runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); + // memset the regexps to 0 in case a GC run happens while we're within the loop below + memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); for (uint i = 0; i < data->jsClassTableSize; ++i) { int memberCount = 0; const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount); - QV4::InternalClass *klass = engine->internalClasses[QV4::ExecutionEngine::Class_Object]; + runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object); for (int j = 0; j < memberCount; ++j, ++member) - klass = klass->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); - - runtimeClasses[i] = klass; + runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); } } @@ -244,13 +245,28 @@ void CompilationUnit::unlink() void CompilationUnit::markObjects(QV4::MarkStack *markStack) { - for (uint i = 0; i < data->stringTableSize; ++i) - if (runtimeStrings[i]) - runtimeStrings[i]->mark(markStack); + if (runtimeStrings) { + for (uint i = 0; i < data->stringTableSize; ++i) + if (runtimeStrings[i]) + runtimeStrings[i]->mark(markStack); + } if (runtimeRegularExpressions) { for (uint i = 0; i < data->regexpTableSize; ++i) runtimeRegularExpressions[i].mark(markStack); } + if (runtimeClasses) { + for (uint i = 0; i < data->jsClassTableSize; ++i) + if (runtimeClasses[i]) + runtimeClasses[i]->mark(markStack); + } + for (QV4::Function *f : qAsConst(runtimeFunctions)) + if (f && f->internalClass) + f->internalClass->mark(markStack); + + if (runtimeLookups) { + for (uint i = 0; i < data->lookupTableSize; ++i) + runtimeLookups[i].markObjects(markStack); + } } IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex) @@ -476,8 +492,9 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) QQmlJS::AST::FormalParameterList *parameters = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node)->formals; changedSignalParameters << parameters; - for (; parameters; parameters = parameters->next) - stringTable.registerString(parameters->name.toString()); + const QStringList formals = parameters->formals(); + for (const QString &arg : formals) + stringTable.registerString(arg); } } @@ -500,11 +517,11 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) function->formalsOffset = signalParameterNameTableOffset - jsUnit->functionOffsetTable()[functionIndex]; - for (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i); - parameters; parameters = parameters->next) { - signalParameterNameTable.append(stringTable.getStringId(parameters->name.toString())); - function->nFormals = function->nFormals + 1; - } + const QStringList formals = changedSignalParameters.at(i)->formals(); + for (const QString &arg : formals) + signalParameterNameTable.append(stringTable.getStringId(arg)); + + function->nFormals = formals.size(); // Hack to ensure an activation is created. function->flags |= QV4::CompiledData::Function::HasCatchOrWith | QV4::CompiledData::Function::HasDirectEval; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 1df9d6794f..66707456cd 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -881,6 +881,8 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnitBase QV4::Heap::String **runtimeStrings = nullptr; // Array const Value* constants = nullptr; QV4::Value *runtimeRegularExpressions = nullptr; + const Unit *data = nullptr; + QV4::Heap::InternalClass **runtimeClasses = nullptr; }; Q_STATIC_ASSERT(std::is_standard_layout<CompilationUnitBase>::value); @@ -915,8 +917,6 @@ public: return refCount.load(); } - const Unit *data = nullptr; - // Called only when building QML, when we build the header for JS first and append QML data QV4::CompiledData::Unit *createUnitData(QmlIR::Document *irDocument); @@ -943,7 +943,6 @@ public: } QV4::Lookup *runtimeLookups = nullptr; - QV4::InternalClass **runtimeClasses = nullptr; QVector<QV4::Function *> runtimeFunctions; mutable QQmlNullableValue<QUrl> m_url; mutable QQmlNullableValue<QUrl> m_finalUrl; diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 455a76c729..fef2b56055 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -263,9 +263,8 @@ struct Context { return true; if (type != FunctionDefinition) { - for (QQmlJS::AST::FormalParameterList *it = formals; it; it = it->next) - if (it->name == name) - return (scope == QQmlJS::AST::VariableDeclaration::FunctionScope); + if (formals->containsName(name)) + return (scope == QQmlJS::AST::VariableDeclaration::FunctionScope); } MemberMap::iterator it = members.find(name); if (it != members.end()) { diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index 84ee452332..3f7211b95e 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -95,25 +95,23 @@ void ScanFunctions::leaveEnvironment() _context = _contextStack.isEmpty() ? 0 : _contextStack.top(); } -void ScanFunctions::checkDirectivePrologue(SourceElements *ast) +void ScanFunctions::checkDirectivePrologue(StatementList *ast) { - for (SourceElements *it = ast; it; it = it->next) { - if (StatementSourceElement *stmt = cast<StatementSourceElement *>(it->element)) { - if (ExpressionStatement *expr = cast<ExpressionStatement *>(stmt->statement)) { - if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) { - // Use the source code, because the StringLiteral's - // value might have escape sequences in it, which is not - // allowed. - if (strLit->literalToken.length < 2) - continue; - QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2); - if (str == QLatin1String("use strict")) { - _context->isStrict = true; - } else { - // TODO: give a warning. - } + for (StatementList *it = ast; it; it = it->next) { + if (ExpressionStatement *expr = cast<ExpressionStatement *>(it->statement)) { + if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) { + // Use the source code, because the StringLiteral's + // value might have escape sequences in it, which is not + // allowed. + if (strLit->literalToken.length < 2) continue; + QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2); + if (str == QLatin1String("use strict")) { + _context->isStrict = true; + } else { + // TODO: give a warning. } + continue; } } @@ -138,20 +136,10 @@ void ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc) } } -bool ScanFunctions::formalsContainName(AST::FormalParameterList *parameters, const QString &name) -{ - while (parameters) { - if (parameters->name == name) - return true; - parameters = parameters->next; - } - return false; -} - bool ScanFunctions::visit(Program *ast) { enterEnvironment(ast, defaultProgramMode); - checkDirectivePrologue(ast->elements); + checkDirectivePrologue(ast->statements); return true; } @@ -237,7 +225,8 @@ bool ScanFunctions::visit(ExpressionStatement *ast) if (!_allowFuncDecls) _cg->throwSyntaxError(expr->functionToken, QStringLiteral("conditional function or closure declaration")); - enterFunction(expr, /*enterName*/ true); + if (!enterFunction(expr, /*enterName*/ true)) + return false; Node::accept(expr->formals, this); Node::accept(expr->body, this); leaveEnvironment(); @@ -253,15 +242,25 @@ bool ScanFunctions::visit(ExpressionStatement *ast) bool ScanFunctions::visit(FunctionExpression *ast) { - enterFunction(ast, /*enterName*/ false); + return enterFunction(ast, /*enterName*/ false); +} + +bool ScanFunctions::visit(TemplateLiteral *ast) +{ + while (ast) { + if (ast->expression) + Node::accept(ast->expression, this); + ast = ast->next; + } return true; + } -void ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName) +bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName) { if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments"))) _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode")); - enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr); + return enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr); } void ScanFunctions::endVisit(FunctionExpression *) @@ -272,7 +271,7 @@ void ScanFunctions::endVisit(FunctionExpression *) bool ScanFunctions::visit(ObjectLiteral *ast) { int argc = 0; - for (PropertyAssignmentList *it = ast->properties; it; it = it->next) { + for (PropertyDefinitionList *it = ast->properties; it; it = it->next) { QString key = it->assignment->name->asString(); if (QV4::String::toArrayIndex(key) != UINT_MAX) ++argc; @@ -290,8 +289,7 @@ bool ScanFunctions::visit(ObjectLiteral *ast) bool ScanFunctions::visit(PropertyGetterSetter *ast) { TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true); - enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr); - return true; + return enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr); } void ScanFunctions::endVisit(PropertyGetterSetter *) @@ -301,8 +299,7 @@ void ScanFunctions::endVisit(PropertyGetterSetter *) bool ScanFunctions::visit(FunctionDeclaration *ast) { - enterFunction(ast, /*enterName*/ true); - return true; + return enterFunction(ast, /*enterName*/ true); } void ScanFunctions::endVisit(FunctionDeclaration *) @@ -391,7 +388,7 @@ bool ScanFunctions::visit(Block *ast) { return false; } -void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr) +bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, FunctionExpression *expr) { Context *outerContext = _context; enterEnvironment(ast, FunctionCode); @@ -402,47 +399,48 @@ void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete if (expr) { if (!outerContext->addLocalVar(name, Context::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr)) { _cg->throwSyntaxError(ast->firstSourceLocation(), QStringLiteral("Identifier %1 has already been declared").arg(name)); - return; + return false; } } if (name == QLatin1String("arguments")) outerContext->usesArgumentsObject = Context::ArgumentsObjectNotUsed; } - if (formalsContainName(formals, QStringLiteral("arguments"))) + if (formals->containsName(QStringLiteral("arguments"))) _context->usesArgumentsObject = Context::ArgumentsObjectNotUsed; - if (!name.isEmpty() && !formalsContainName(formals, name)) + if (!name.isEmpty() && !formals->containsName(name)) _context->addLocalVar(name, Context::ThisFunctionName, QQmlJS::AST::VariableDeclaration::FunctionScope); _context->formals = formals; if (body && !_context->isStrict) - checkDirectivePrologue(body->elements); - - for (FormalParameterList *it = formals; it; it = it->next) { - QString arg = it->name.toString(); - int duplicateIndex = _context->arguments.indexOf(arg); - if (duplicateIndex != -1) { - if (_context->isStrict) { - _cg->throwSyntaxError(it->identifierToken, QStringLiteral("Duplicate parameter name '%1' is not allowed in strict mode").arg(arg)); - return; - } else { - // change the name of the earlier argument to enforce the specified lookup semantics - QString modified = arg; - while (_context->arguments.contains(modified)) - modified += QString(0xfffe); - _context->arguments[duplicateIndex] = modified; + checkDirectivePrologue(body); + + bool isSimpleParameterList = formals->isSimpleParameterList(); + + _context->arguments = formals->formals(); + + const QStringList boundNames = formals->boundNames(); + for (int i = 0; i < boundNames.size(); ++i) { + const QString &arg = boundNames.at(i); + if (_context->isStrict || !isSimpleParameterList) { + bool duplicate = (boundNames.indexOf(arg, i + 1) != -1); + if (duplicate) { + _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("Duplicate parameter name '%1' is not allowed.").arg(arg)); + return false; } } if (_context->isStrict) { if (arg == QLatin1String("eval") || arg == QLatin1String("arguments")) { - _cg->throwSyntaxError(it->identifierToken, QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg)); - return; + _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg)); + return false; } } - _context->arguments += arg; + if (!_context->arguments.contains(arg)) + _context->addLocalVar(arg, Context::VariableDefinition, QQmlJS::AST::VariableDeclaration::FunctionScope); } + return true; } void ScanFunctions::calcEscapingVariables() diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index 87b7210879..cf79da2203 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -95,10 +95,9 @@ protected: using Visitor::visit; using Visitor::endVisit; - void checkDirectivePrologue(AST::SourceElements *ast); + void checkDirectivePrologue(AST::StatementList *ast); void checkName(const QStringRef &name, const AST::SourceLocation &loc); - bool formalsContainName(AST::FormalParameterList *parameters, const QString &name); bool visit(AST::Program *ast) override; void endVisit(AST::Program *) override; @@ -110,8 +109,9 @@ protected: bool visit(AST::IdentifierExpression *ast) override; bool visit(AST::ExpressionStatement *ast) override; bool visit(AST::FunctionExpression *ast) override; + bool visit(AST::TemplateLiteral *ast) override; - void enterFunction(AST::FunctionExpression *ast, bool enterName); + bool enterFunction(AST::FunctionExpression *ast, bool enterName); void endVisit(AST::FunctionExpression *) override; @@ -136,7 +136,7 @@ protected: bool visit(AST::Block *ast) override; protected: - void enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::FunctionBody *body, AST::FunctionExpression *expr); + bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, AST::FunctionExpression *expr); void calcEscapingVariables(); // fields: diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 450fa50528..3a9cecdae0 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -454,6 +454,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject) MOTH_END_INSTR(CreateUnmappedArgumentsObject) + MOTH_BEGIN_INSTR(CreateRestParameter) + d << argIndex; + MOTH_END_INSTR(CreateRestParameter) + MOTH_BEGIN_INSTR(ConvertThisToObject) MOTH_END_INSTR(ConvertThisToObject) @@ -473,6 +477,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << ABSOLUTE_OFFSET(); MOTH_END_INSTR(JumpFalse) + MOTH_BEGIN_INSTR(JumpNotUndefined) + d << ABSOLUTE_OFFSET(); + MOTH_END_INSTR(JumpNotUndefined) + MOTH_BEGIN_INSTR(CmpEqNull) MOTH_END_INSTR(CmpEqNull) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 7dd639c94c..8ce72f4942 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -128,11 +128,13 @@ QT_BEGIN_NAMESPACE #define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 4, internalClassId, arrayValueCount, arrayGetterSetterCountAndFlags, args) #define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0) #define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0) +#define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex) #define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0) #define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv) #define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset) #define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset) #define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset) +#define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset) #define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0) #define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0) #define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs) @@ -244,11 +246,13 @@ QT_BEGIN_NAMESPACE F(DefineObjectLiteral) \ F(CreateMappedArgumentsObject) \ F(CreateUnmappedArgumentsObject) \ + F(CreateRestParameter) \ F(ConvertThisToObject) \ F(Construct) \ F(Jump) \ F(JumpTrue) \ F(JumpFalse) \ + F(JumpNotUndefined) \ F(CmpEqNull) \ F(CmpNeNull) \ F(CmpEqInt) \ diff --git a/src/qml/configure.json b/src/qml/configure.json index 681cecea99..7d67db8b2c 100644 --- a/src/qml/configure.json +++ b/src/qml/configure.json @@ -40,6 +40,47 @@ ], "output": [ "privateFeature" ] }, + "qml-devtools": { + "label": "QML Development Tools", + "purpose": "Provides the QmlDevtools library and various utilities.", + "section": "QML", + "output": [ "privateFeature" ] + }, + "qml-sequence-object": { + "label": "QML sequence object", + "purpose": "Supports mapping sequence types into QML.", + "section": "QML", + "output": [ "privateFeature" ] + }, + "qml-list-model": { + "label": "QML list model", + "purpose": "Provides the ListModel QML type.", + "section": "QML", + "output": [ "privateFeature" ] + }, + "qml-xml-http-request": { + "label": "QML XML http request", + "purpose": "Provides support for sending XML http requests.", + "section": "QML", + "condition": [ + "features.xmlstreamreader", + "features.qml-network" + ], + "output": [ "privateFeature" ] + }, + "qml-locale": { + "label": "QML Locale", + "purpose": "Provides support for locales in QML.", + "section": "QML", + "output": [ "privateFeature" ] + }, + "qml-animation": { + "label": "QML Animations", + "purpose": "Provides support for animations and timers in QML.", + "section": "QML", + "condition": "features.animation", + "output": [ "privateFeature" ] + }, "qml-delegate-model": { "label": "QML delegate model", "purpose": "Provides the DelegateModel QML type.", @@ -54,6 +95,10 @@ "entries": [ "qml-network", "qml-debug", + "qml-sequence-object", + "qml-list-model", + "qml-xml-http-request", + "qml-locale", "qml-delegate-model" ] } diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h index c63e694c7e..f39f8fccd2 100644 --- a/src/qml/debugger/qqmlabstractprofileradapter_p.h +++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h @@ -73,13 +73,13 @@ public: ~QQmlAbstractProfilerAdapter() override {} void setService(QQmlProfilerService *new_service) { service = new_service; } - virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) = 0; + virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0; void startProfiling(quint64 features); void stopProfiling(); - void reportData(bool trackLocations) { emit dataRequested(trackLocations); } + void reportData() { emit dataRequested(); } void stopWaiting() { waiting = false; } void startWaiting() { waiting = true; } @@ -96,7 +96,7 @@ signals: void profilingDisabled(); void profilingDisabledWhileWaiting(); - void dataRequested(bool trackLocations); + void dataRequested(); void referenceTimeKnown(const QElapsedTimer &timer); protected: diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp index 8c0bd73822..da0b14dd85 100644 --- a/src/qml/debugger/qqmlprofiler.cpp +++ b/src/qml/debugger/qqmlprofiler.cpp @@ -59,19 +59,18 @@ void QQmlProfiler::startProfiling(quint64 features) void QQmlProfiler::stopProfiling() { featuresEnabled = false; - reportData(true); + reportData(); m_locations.clear(); } -void QQmlProfiler::reportData(bool trackLocations) +void QQmlProfiler::reportData() { LocationHash resolved; resolved.reserve(m_locations.size()); for (auto it = m_locations.begin(), end = m_locations.end(); it != end; ++it) { - if (!trackLocations || !it->sent) { + if (!it->sent) { resolved.insert(it.key(), it.value()); - if (trackLocations) - it->sent = true; + it->sent = true; } } diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 287c53ea05..d01e2bc429 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -383,7 +383,7 @@ public: void startProfiling(quint64 features); void stopProfiling(); - void reportData(bool trackLocations); + void reportData(); void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index c3e16c4093..890d9d03a1 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -701,6 +701,12 @@ struct PlatformAssembler64 : PlatformAssemblerCommon PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();}); } + void jumpNotUndefined(int offset) + { + auto jump = branch64(NotEqual, AccumulatorRegister, TrustedImm64(0)); + patches.push_back({ jump, offset }); + } + void toBoolean(std::function<void(RegisterID)> continuation) { urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister); @@ -1136,6 +1142,14 @@ struct PlatformAssembler32 : PlatformAssemblerCommon push(TrustedImm32(v)); } + void jumpNotUndefined(int offset) + { + move(AccumulatorRegisterTag, ScratchRegister); + or32(AccumulatorRegisterValue, ScratchRegister); + auto jump = branch32(NotEqual, ScratchRegister, TrustedImm32(0)); + patches.push_back({ jump, offset }); + } + void toBoolean(std::function<void(RegisterID)> continuation) { urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerConvertible_Shift - 32), @@ -1982,6 +1996,11 @@ void Assembler::jumpFalse(int offset) }); } +void Assembler::jumpNotUndefined(int offset) +{ + pasm()->jumpNotUndefined(offset); +} + void Assembler::jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset) { pasm()->jumpStrictEqualStackSlotInt(lhs, rhs, offset); diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 37d4232a17..a98761c6ab 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -140,6 +140,7 @@ public: void jump(int offset); void jumpTrue(int offset); void jumpFalse(int offset); + void jumpNotUndefined(int offset); void jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset); void jumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset); diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp index bc46c0ca1d..b2dde4fca2 100644 --- a/src/qml/jit/qv4jit.cpp +++ b/src/qml/jit/qv4jit.cpp @@ -781,6 +781,14 @@ void BaselineJIT::generate_CreateUnmappedArgumentsObject() Assembler::ResultInAccumulator); } +void BaselineJIT::generate_CreateRestParameter(int argIndex) +{ + as->prepareCallWithArgCount(2); + as->passInt32AsArg(argIndex, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_createRestParameter, Assembler::ResultInAccumulator); +} + static void convertThisToObjectHelper(ExecutionEngine *engine, Value *t) { if (!t->isObject()) { @@ -816,6 +824,7 @@ void BaselineJIT::generate_Construct(int func, int argc, int argv) void BaselineJIT::generate_Jump(int offset) { as->jump(instructionOffset() + offset); } void BaselineJIT::generate_JumpTrue(int offset) { as->jumpTrue(instructionOffset() + offset); } void BaselineJIT::generate_JumpFalse(int offset) { as->jumpFalse(instructionOffset() + offset); } +void BaselineJIT::generate_JumpNotUndefined(int offset) { as->jumpNotUndefined(instructionOffset() + offset); } void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); } void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); } @@ -1172,6 +1181,9 @@ void BaselineJIT::collectLabelsInBytecode() MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject) MOTH_END_INSTR(CreateUnmappedArgumentsObject) + MOTH_BEGIN_INSTR(CreateRestParameter) + MOTH_END_INSTR(CreateRestParameter) + MOTH_BEGIN_INSTR(ConvertThisToObject) MOTH_END_INSTR(ConvertThisToObject) @@ -1190,6 +1202,10 @@ void BaselineJIT::collectLabelsInBytecode() addLabel(code - start + offset); MOTH_END_INSTR(JumpFalse) + MOTH_BEGIN_INSTR(JumpNotUndefined) + addLabel(code - start + offset); + MOTH_END_INSTR(JumpUndefined) + MOTH_BEGIN_INSTR(CmpEqNull) MOTH_END_INSTR(CmpEqNull) diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h index 5aebf78a8d..9ff2d99191 100644 --- a/src/qml/jit/qv4jit_p.h +++ b/src/qml/jit/qv4jit_p.h @@ -192,11 +192,13 @@ public: int args) override; void generate_CreateMappedArgumentsObject() override; void generate_CreateUnmappedArgumentsObject() override; + void generate_CreateRestParameter(int argIndex) override; void generate_ConvertThisToObject() override; void generate_Construct(int func, int argc, int argv) override; void generate_Jump(int offset) override; void generate_JumpTrue(int offset) override; void generate_JumpFalse(int offset) override; + void generate_JumpNotUndefined(int offset) override; void generate_CmpEqNull() override; void generate_CmpNeNull() override; void generate_CmpEqInt(int lhs) override; diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index c483af638b..924de14bc7 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -304,9 +304,9 @@ QJSEngine::QJSEngine() QJSEngine::QJSEngine(QObject *parent) : QObject(*new QJSEnginePrivate, parent) - , m_v4Engine(new QV4::ExecutionEngine) + , m_v4Engine(new QV4::ExecutionEngine(this)) { - m_v4Engine->v8Engine = new QV8Engine(this, m_v4Engine); + m_v4Engine->v8Engine = new QV8Engine(m_v4Engine); checkForApplicationInstance(); QJSEnginePrivate::addToDebugServer(this); @@ -317,9 +317,9 @@ QJSEngine::QJSEngine(QObject *parent) */ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent) : QObject(dd, parent) - , m_v4Engine(new QV4::ExecutionEngine) + , m_v4Engine(new QV4::ExecutionEngine(this)) { - m_v4Engine->v8Engine = new QV8Engine(this, m_v4Engine); + m_v4Engine->v8Engine = new QV8Engine(m_v4Engine); checkForApplicationInstance(); } diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index 4bc877bd9d..1ec00cc744 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -36,7 +36,6 @@ SOURCES += \ $$PWD/qv4runtimecodegen.cpp \ $$PWD/qv4serialize.cpp \ $$PWD/qv4script.cpp \ - $$PWD/qv4sequenceobject.cpp \ $$PWD/qv4include.cpp \ $$PWD/qv4qobjectwrapper.cpp \ $$PWD/qv4arraybuffer.cpp \ @@ -89,7 +88,6 @@ HEADERS += \ $$PWD/qv4script_p.h \ $$PWD/qv4scopedvalue_p.h \ $$PWD/qv4executableallocator_p.h \ - $$PWD/qv4sequenceobject_p.h \ $$PWD/qv4include_p.h \ $$PWD/qv4qobjectwrapper_p.h \ $$PWD/qv4profiling_p.h \ @@ -98,6 +96,14 @@ HEADERS += \ $$PWD/qv4dataview_p.h \ $$PWD/qv4vme_moth_p.h +qtConfig(qml-sequence-object) { + HEADERS += \ + $$PWD/qv4sequenceobject_p.h + + SOURCES += \ + $$PWD/qv4sequenceobject.cpp +} + } diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index ac281f555a..d163bbaf88 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -142,7 +142,7 @@ struct ArgumentsObject: Object { bool fullyCreated() const { return d()->fullyCreated; } static bool isNonStrictArgumentsObject(Managed *m) { - return m->d()->vtable() == staticVTable(); + return m->vtable() == staticVTable(); } bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs); diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index b2573b4491..613c3b2b50 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -117,7 +117,7 @@ DECLARE_HEAP_OBJECT(ArrayData, Base) { bool isSparse() const { return type == Sparse; } - const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); } + const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); } inline ReturnedValue get(uint i) const { return vtable()->get(this, i); diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 512bfa06d8..ccc1653c36 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -55,23 +55,8 @@ QT_BEGIN_NAMESPACE -class QObject; -class QQmlContextData; - namespace QV4 { -namespace CompiledData { -struct CompilationUnitBase; -struct Function; -} - -struct Function; -struct Identifier; -struct CallContext; -struct CatchContext; -struct QmlContext; -struct QQmlContextWrapper; - struct CallData { enum Offsets { @@ -113,8 +98,6 @@ Q_STATIC_ASSERT(offsetof(CallData, args) == 5*sizeof(Value)); namespace Heap { -struct QmlContext; - #define ExecutionContextMembers(class, Member) \ Member(class, Pointer, ExecutionContext *, outer) \ Member(class, Pointer, Object *, activation) @@ -137,6 +120,10 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) { type = t; } + const VTable *vtable() const { + return internalClass->vtable; + } + quint32 type : 8; quint32 nArgs : 24; #if QT_POINTER_SIZE == 8 @@ -242,6 +229,7 @@ struct Q_QML_EXPORT CallContext : public ExecutionContext struct CatchContext : public ExecutionContext { V4_MANAGED(CatchContext, ExecutionContext) + V4_INTERNALCLASS(CatchContext) }; inline CallContext *ExecutionContext::asCallContext() diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index d894d909ff..78b83e4a87 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -69,7 +69,7 @@ ReturnedValue DataViewCtor::callAsConstructor(const FunctionObject *f, const Val if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength) return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range")); - Scoped<DataView> a(scope, scope.engine->memoryManager->allocObject<DataView>()); + Scoped<DataView> a(scope, scope.engine->memoryManager->allocate<DataView>()); a->d()->buffer.set(scope.engine, buffer->d()); a->d()->byteLength = byteLength; a->d()->byteOffset = byteOffset; diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 2b9a580288..0750d3bc75 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -101,7 +101,7 @@ struct DateObject: Object { template<> inline const DateObject *Value::as() const { - return isManaged() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr; + return isManaged() && m()->internalClass->vtable->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr; } struct DateCtor: FunctionObject diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 5521633db7..dc9a37b406 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -63,7 +63,11 @@ #include "qv4debugging_p.h" #include "qv4profiling_p.h" #include "qv4executableallocator_p.h" + +#if QT_CONFIG(qml_sequence_object) #include "qv4sequenceobject_p.h" +#endif + #include "qv4qobjectwrapper_p.h" #include "qv4memberdata_p.h" #include "qv4arraybuffer_p.h" @@ -76,7 +80,9 @@ #include <private/qqmlvaluetype_p.h> #include <private/qqmllistwrapper_p.h> #include <private/qqmllist_p.h> +#if QT_CONFIG(qml_locale) #include <private/qqmllocale_p.h> +#endif #include <QtCore/QTextStream> #include <QDateTime> @@ -110,7 +116,7 @@ ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const #ifdef V4_BOOTSTRAP QJSEngine *ExecutionEngine::jsEngine() const { - return v8Engine->publicEngine(); + return publicEngine; } QQmlEngine *ExecutionEngine::qmlEngine() const @@ -121,7 +127,7 @@ QQmlEngine *ExecutionEngine::qmlEngine() const qint32 ExecutionEngine::maxCallDepth = -1; -ExecutionEngine::ExecutionEngine() +ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) : executableAllocator(new QV4::ExecutableAllocator) , regExpAllocator(new QV4::ExecutableAllocator) , bumperPointerAllocator(new WTF::BumpPointerAllocator) @@ -129,6 +135,7 @@ ExecutionEngine::ExecutionEngine() , gcStack(new WTF::PageAllocation) , globalCode(nullptr) , v8Engine(nullptr) + , publicEngine(jsEngine) , argumentsAccessors(nullptr) , nArgumentsAccessors(0) , m_engineId(engineSerial.fetchAndAddOrdered(1)) @@ -192,16 +199,18 @@ ExecutionEngine::ExecutionEngine() identifierTable = new IdentifierTable(this); - classPool = new InternalClassPool; + memset(classes, 0, sizeof(classes)); + classes[Class_Empty] = memoryManager->allocIC<InternalClass>(); + classes[Class_Empty]->init(this); - internalClasses[Class_Empty] = new (classPool) InternalClass(this); - internalClasses[Class_String] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::String::staticVTable()); - internalClasses[Class_MemberData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::MemberData::staticVTable()); - internalClasses[Class_SimpleArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable()); - internalClasses[Class_SparseArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable()); - internalClasses[Class_ExecutionContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable()); - internalClasses[Class_QmlContext] = internalClasses[EngineBase::Class_ExecutionContext]->changeVTable(QV4::QmlContext::staticVTable()); - internalClasses[Class_CallContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::CallContext::staticVTable()); + classes[Class_String] = classes[Class_Empty]->changeVTable(QV4::String::staticVTable()); + classes[Class_MemberData] = classes[Class_Empty]->changeVTable(QV4::MemberData::staticVTable()); + classes[Class_SimpleArrayData] = classes[Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable()); + classes[Class_SparseArrayData] = classes[Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable()); + classes[Class_ExecutionContext] = classes[Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable()); + classes[Class_CallContext] = classes[Class_Empty]->changeVTable(QV4::CallContext::staticVTable()); + classes[Class_CatchContext] = classes[Class_Empty]->changeVTable(QV4::CatchContext::staticVTable()); + classes[Class_QmlContext] = classes[Class_Empty]->changeVTable(QV4::QmlContext::staticVTable()); jsStrings[String_Empty] = newIdentifier(QString()); jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined")); @@ -240,26 +249,29 @@ ExecutionEngine::ExecutionEngine() jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer")); jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex")); - InternalClass *ic = internalClasses[Class_Empty]->changeVTable(QV4::Object::staticVTable()); - jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic); - internalClasses[Class_Object] = ic->changePrototype(objectPrototype()->d()); - internalClasses[EngineBase::Class_QmlContextWrapper] = internalClasses[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable()); + Scope scope(this); + Scoped<InternalClass> ic(scope); + ic = classes[Class_Empty]->changeVTable(QV4::Object::staticVTable()); + jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic->d()); + classes[Class_Object] = ic->changePrototype(objectPrototype()->d()); + classes[EngineBase::Class_QmlContextWrapper] = classes[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable()); ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype()); - Q_ASSERT(ic->prototype); + Q_ASSERT(ic->d()->prototype); ic = ic->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable); - Q_ASSERT(ic->prototype); - jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(ic, objectPrototype()); - internalClasses[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d()); - jsObjects[PropertyListProto] = memoryManager->allocObject<PropertyListPrototype>(); + Q_ASSERT(ic->d()->prototype); + jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(ic->d()); + classes[Class_ArrayObject] = ic->changePrototype(arrayPrototype()->d()); + jsObjects[PropertyListProto] = memoryManager->allocate<PropertyListPrototype>(); - InternalClass *argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype()); + Scoped<InternalClass> argsClass(scope); + argsClass = newInternalClass(ArgumentsObject::staticVTable(), objectPrototype()); argsClass = argsClass->addMember(id_length(), Attr_NotEnumerable); - internalClasses[EngineBase::Class_ArgumentsObject] = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable); + classes[Class_ArgumentsObject] = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable); argsClass = newInternalClass(StrictArgumentsObject::staticVTable(), objectPrototype()); argsClass = argsClass->addMember(id_length(), Attr_NotEnumerable); argsClass = argsClass->addMember(id_callee(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - internalClasses[EngineBase::Class_StrictArgumentsObject] = argsClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + classes[Class_StrictArgumentsObject] = argsClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); *static_cast<Value *>(globalObject) = newObject(); Q_ASSERT(globalObject->d()->vtable()); @@ -267,34 +279,33 @@ ExecutionEngine::ExecutionEngine() ic = newInternalClass(QV4::StringObject::staticVTable(), objectPrototype()); ic = ic->addMember(id_length(), Attr_ReadOnly); - jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic); - internalClasses[Class_StringObject] = ic->changePrototype(stringPrototype()->d()); - Q_ASSERT(internalClasses[EngineBase::Class_StringObject]->find(id_length()) == Heap::StringObject::LengthPropertyIndex); + jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(ic->d()); + classes[Class_StringObject] = ic->changePrototype(stringPrototype()->d()); + Q_ASSERT(classes[Class_StringObject]->find(id_length()) == Heap::StringObject::LengthPropertyIndex); - jsObjects[NumberProto] = memoryManager->allocObject<NumberPrototype>(); - jsObjects[BooleanProto] = memoryManager->allocObject<BooleanPrototype>(); - jsObjects[DateProto] = memoryManager->allocObject<DatePrototype>(); + jsObjects[NumberProto] = memoryManager->allocate<NumberPrototype>(); + jsObjects[BooleanProto] = memoryManager->allocate<BooleanPrototype>(); + jsObjects[DateProto] = memoryManager->allocate<DatePrototype>(); uint index; ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype()); ic = ic->addMember(id_prototype(), Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); - jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic, objectPrototype()); + jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic->d()); ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype()); ic = ic->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); - internalClasses[EngineBase::Class_FunctionObject] = ic; + classes[Class_FunctionObject] = ic->d(); ic = ic->addMember(id_name(), Attr_ReadOnly, &index); Q_ASSERT(index == Heap::ScriptFunction::Index_Name); ic = ic->changeVTable(ScriptFunction::staticVTable()); - internalClasses[EngineBase::Class_ScriptFunction] = ic->addMember(id_length(), Attr_ReadOnly, &index); + classes[Class_ScriptFunction] = ic->addMember(id_length(), Attr_ReadOnly, &index); Q_ASSERT(index == Heap::ScriptFunction::Index_Length); - internalClasses[EngineBase::Class_ObjectProto] = internalClasses[Class_Object]->addMember(id_constructor(), Attr_NotEnumerable, &index); + classes[Class_ObjectProto] = classes[Class_Object]->addMember(id_constructor(), Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor); - Scope scope(this); ScopedString str(scope); - internalClasses[Class_RegExp] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::RegExp::staticVTable()); + classes[Class_RegExp] = classes[Class_Empty]->changeVTable(QV4::RegExp::staticVTable()); ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype()); ic = ic->addMember(id_lastIndex(), Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == RegExpObject::Index_LastIndex); @@ -306,12 +317,12 @@ ExecutionEngine::ExecutionEngine() Q_ASSERT(index == RegExpObject::Index_IgnoreCase); ic = ic->addMember((str = newIdentifier(QStringLiteral("multiline"))), Attr_ReadOnly, &index); Q_ASSERT(index == RegExpObject::Index_Multiline); - jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(ic, objectPrototype()); - internalClasses[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d()); + jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(ic->d()); + classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d()); - ic = internalClasses[Class_ArrayObject]->addMember(id_index(), Attr_Data, &index); + ic = classes[Class_ArrayObject]->addMember(id_index(), Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayIndex); - internalClasses[EngineBase::Class_RegExpExecArray] = ic->addMember(id_input(), Attr_Data, &index); + classes[Class_RegExpExecArray] = ic->addMember(id_input(), Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayInput); ic = newInternalClass(ErrorObject::staticVTable(), nullptr); @@ -320,51 +331,54 @@ ExecutionEngine::ExecutionEngine() ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName"))), Attr_Data|Attr_NotEnumerable, &index); Q_ASSERT(index == ErrorObject::Index_FileName); ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber"))), Attr_Data|Attr_NotEnumerable, &index); - internalClasses[EngineBase::Class_ErrorObject] = ic; + classes[Class_ErrorObject] = ic->d(); Q_ASSERT(index == ErrorObject::Index_LineNumber); - internalClasses[EngineBase::Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index); + classes[Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index); Q_ASSERT(index == ErrorObject::Index_Message); ic = newInternalClass(ErrorObject::staticVTable(), objectPrototype()); ic = ic->addMember(id_constructor(), Attr_Data|Attr_NotEnumerable, &index); Q_ASSERT(index == ErrorPrototype::Index_Constructor); ic = ic->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index); Q_ASSERT(index == ErrorPrototype::Index_Message); - internalClasses[EngineBase::Class_ErrorProto] = ic->addMember(id_name(), Attr_Data|Attr_NotEnumerable, &index); + classes[Class_ErrorProto] = ic->addMember(id_name(), Attr_Data|Attr_NotEnumerable, &index); Q_ASSERT(index == ErrorPrototype::Index_Name); jsObjects[GetStack_Function] = FunctionObject::createBuiltinFunction(rootContext(), str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack); getStackFunction()->defineReadonlyProperty(id_length(), Primitive::fromInt32(0)); - jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto], objectPrototype()); - jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype()); - jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype()); - jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype()); - jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype()); - jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype()); - jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto]->changePrototype(errorPrototype()->d()), errorPrototype()); + jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(classes[Class_ErrorProto]); + ic = classes[Class_ErrorProto]->changePrototype(errorPrototype()->d()); + jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(ic->d()); + jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(ic->d()); + jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(ic->d()); + jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(ic->d()); + jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(ic->d()); + jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(ic->d()); - jsObjects[VariantProto] = memoryManager->allocObject<VariantPrototype>(); + jsObjects[VariantProto] = memoryManager->allocate<VariantPrototype>(); Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d()); +#if QT_CONFIG(qml_sequence_object) ic = newInternalClass(SequencePrototype::staticVTable(), SequencePrototype::defaultPrototype(this)); - jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(ic, SequencePrototype::defaultPrototype(this))); + jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(ic->d())); +#endif ExecutionContext *global = rootContext(); - jsObjects[Object_Ctor] = memoryManager->allocObject<ObjectCtor>(global); - jsObjects[String_Ctor] = memoryManager->allocObject<StringCtor>(global); - jsObjects[Number_Ctor] = memoryManager->allocObject<NumberCtor>(global); - jsObjects[Boolean_Ctor] = memoryManager->allocObject<BooleanCtor>(global); - jsObjects[Array_Ctor] = memoryManager->allocObject<ArrayCtor>(global); - jsObjects[Function_Ctor] = memoryManager->allocObject<FunctionCtor>(global); - jsObjects[Date_Ctor] = memoryManager->allocObject<DateCtor>(global); - jsObjects[RegExp_Ctor] = memoryManager->allocObject<RegExpCtor>(global); - jsObjects[Error_Ctor] = memoryManager->allocObject<ErrorCtor>(global); - jsObjects[EvalError_Ctor] = memoryManager->allocObject<EvalErrorCtor>(global); - jsObjects[RangeError_Ctor] = memoryManager->allocObject<RangeErrorCtor>(global); - jsObjects[ReferenceError_Ctor] = memoryManager->allocObject<ReferenceErrorCtor>(global); - jsObjects[SyntaxError_Ctor] = memoryManager->allocObject<SyntaxErrorCtor>(global); - jsObjects[TypeError_Ctor] = memoryManager->allocObject<TypeErrorCtor>(global); - jsObjects[URIError_Ctor] = memoryManager->allocObject<URIErrorCtor>(global); + jsObjects[Object_Ctor] = memoryManager->allocate<ObjectCtor>(global); + jsObjects[String_Ctor] = memoryManager->allocate<StringCtor>(global); + jsObjects[Number_Ctor] = memoryManager->allocate<NumberCtor>(global); + jsObjects[Boolean_Ctor] = memoryManager->allocate<BooleanCtor>(global); + jsObjects[Array_Ctor] = memoryManager->allocate<ArrayCtor>(global); + jsObjects[Function_Ctor] = memoryManager->allocate<FunctionCtor>(global); + jsObjects[Date_Ctor] = memoryManager->allocate<DateCtor>(global); + jsObjects[RegExp_Ctor] = memoryManager->allocate<RegExpCtor>(global); + jsObjects[Error_Ctor] = memoryManager->allocate<ErrorCtor>(global); + jsObjects[EvalError_Ctor] = memoryManager->allocate<EvalErrorCtor>(global); + jsObjects[RangeError_Ctor] = memoryManager->allocate<RangeErrorCtor>(global); + jsObjects[ReferenceError_Ctor] = memoryManager->allocate<ReferenceErrorCtor>(global); + jsObjects[SyntaxError_Ctor] = memoryManager->allocate<SyntaxErrorCtor>(global); + jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(global); + jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global); static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor()); static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor()); @@ -382,26 +396,27 @@ ExecutionEngine::ExecutionEngine() static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor()); static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor()); static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor()); - static_cast<VariantPrototype *>(variantPrototype())->init(); - sequencePrototype()->cast<SequencePrototype>()->init(); +#if QT_CONFIG(qml_sequence_object) + sequencePrototype()->cast<SequencePrototype>()->init(); +#endif // typed arrays - jsObjects[ArrayBuffer_Ctor] = memoryManager->allocObject<ArrayBufferCtor>(global); - jsObjects[ArrayBufferProto] = memoryManager->allocObject<ArrayBufferPrototype>(); + jsObjects[ArrayBuffer_Ctor] = memoryManager->allocate<ArrayBufferCtor>(global); + jsObjects[ArrayBufferProto] = memoryManager->allocate<ArrayBufferPrototype>(); static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor()); - jsObjects[DataView_Ctor] = memoryManager->allocObject<DataViewCtor>(global); - jsObjects[DataViewProto] = memoryManager->allocObject<DataViewPrototype>(); + jsObjects[DataView_Ctor] = memoryManager->allocate<DataViewCtor>(global); + jsObjects[DataViewProto] = memoryManager->allocate<DataViewPrototype>(); static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor()); jsObjects[ValueTypeProto] = (Heap::Base *) nullptr; jsObjects[SignalHandlerProto] = (Heap::Base *) nullptr; for (int i = 0; i < Heap::TypedArray::NTypes; ++i) { - static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocObject<TypedArrayCtor>(global, Heap::TypedArray::Type(i)); - static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocObject<TypedArrayPrototype>(Heap::TypedArray::Type(i)); + static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(global, Heap::TypedArray::Type(i)); + static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i)); typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>())); } @@ -433,15 +448,15 @@ ExecutionEngine::ExecutionEngine() for (int i = 0; i < Heap::TypedArray::NTypes; ++i) globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]); ScopedObject o(scope); - globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocObject<MathObject>())); - globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocObject<JsonObject>())); + globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocate<MathObject>())); + globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocate<JsonObject>())); globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue()); globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN())); globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY)); - jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global); + jsObjects[Eval_Function] = memoryManager->allocate<EvalFunction>(global); globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction()); // ES6: 20.1.2.12 & 20.1.2.13: @@ -487,8 +502,6 @@ ExecutionEngine::~ExecutionEngine() while (!compilationUnits.isEmpty()) (*compilationUnits.begin())->unlink(); - internalClasses[Class_Empty]->destroy(); - delete classPool; delete bumperPointerAllocator; delete regExpCache; delete regExpAllocator; @@ -524,24 +537,28 @@ void ExecutionEngine::initRootContext() jsObjects[IntegerNull] = Encode((int)0); } -InternalClass *ExecutionEngine::newClass(const InternalClass &other) +Heap::InternalClass *ExecutionEngine::newClass(Heap::InternalClass *other) { - return new (classPool) InternalClass(other); + Heap::InternalClass *ic = memoryManager->allocIC<InternalClass>(); + ic->init(other); + return ic; } -InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype) +Heap::InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype) { - return internalClasses[EngineBase::Class_Empty]->changeVTable(vtable)->changePrototype(prototype ? prototype->d() : nullptr); + Scope scope(this); + Scoped<InternalClass> ic(scope, internalClasses(Class_Empty)->changeVTable(vtable)); + return ic->changePrototype(prototype ? prototype->d() : nullptr); } Heap::Object *ExecutionEngine::newObject() { - return memoryManager->allocObject<Object>(); + return memoryManager->allocate<Object>(); } -Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype) +Heap::Object *ExecutionEngine::newObject(Heap::InternalClass *internalClass) { - return memoryManager->allocObject<Object>(internalClass, prototype); + return memoryManager->allocObject<Object>(internalClass); } Heap::String *ExecutionEngine::newString(const QString &s) @@ -557,23 +574,23 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text) Heap::Object *ExecutionEngine::newStringObject(const String *string) { - return memoryManager->allocObject<StringObject>(string); + return memoryManager->allocate<StringObject>(string); } Heap::Object *ExecutionEngine::newNumberObject(double value) { - return memoryManager->allocObject<NumberObject>(value); + return memoryManager->allocate<NumberObject>(value); } Heap::Object *ExecutionEngine::newBooleanObject(bool b) { - return memoryManager->allocObject<BooleanObject>(b); + return memoryManager->allocate<BooleanObject>(b); } Heap::ArrayObject *ExecutionEngine::newArrayObject(int count) { Scope scope(this); - ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>()); + ScopedArrayObject object(scope, memoryManager->allocate<ArrayObject>()); if (count) { if (count < 0x1000) @@ -586,7 +603,7 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(int count) Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int length) { Scope scope(this); - ScopedArrayObject a(scope, memoryManager->allocObject<ArrayObject>()); + ScopedArrayObject a(scope, memoryManager->allocate<ArrayObject>()); if (length) { size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value); @@ -613,45 +630,41 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int leng Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list) { - Scope scope(this); - ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(list)); - return object->d(); + return memoryManager->allocate<ArrayObject>(list); } -Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *internalClass, Object *prototype) +Heap::ArrayObject *ExecutionEngine::newArrayObject(Heap::InternalClass *internalClass) { - Scope scope(this); - ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(internalClass, prototype)); - return object->d(); + return memoryManager->allocObject<ArrayObject>(internalClass); } Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array) { - return memoryManager->allocObject<ArrayBuffer>(array); + return memoryManager->allocate<ArrayBuffer>(array); } Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(size_t length) { - return memoryManager->allocObject<ArrayBuffer>(length); + return memoryManager->allocate<ArrayBuffer>(length); } Heap::DateObject *ExecutionEngine::newDateObject(const Value &value) { - return memoryManager->allocObject<DateObject>(value); + return memoryManager->allocate<DateObject>(value); } Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt) { Scope scope(this); - Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(dt)); + Scoped<DateObject> object(scope, memoryManager->allocate<DateObject>(dt)); return object->d(); } Heap::DateObject *ExecutionEngine::newDateObjectFromTime(const QTime &t) { Scope scope(this); - Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(t)); + Scoped<DateObject> object(scope, memoryManager->allocate<DateObject>(t)); return object->d(); } @@ -668,12 +681,12 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re) { - return memoryManager->allocObject<RegExpObject>(re); + return memoryManager->allocate<RegExpObject>(re); } Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re) { - return memoryManager->allocObject<RegExpObject>(re); + return memoryManager->allocate<RegExpObject>(re); } Heap::Object *ExecutionEngine::newErrorObject(const Value &value) @@ -720,13 +733,13 @@ Heap::Object *ExecutionEngine::newURIErrorObject(const Value &message) Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v) { - return memoryManager->allocObject<VariantObject>(v); + return memoryManager->allocate<VariantObject>(v); } Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o) { Scope scope(this); - ScopedObject obj(scope, memoryManager->allocObject<ForEachIteratorObject>(o)); + ScopedObject obj(scope, memoryManager->allocate<ForEachIteratorObject>(o)); return obj->d(); } @@ -894,8 +907,8 @@ void ExecutionEngine::requireArgumentsAccessors(int n) } ExecutionContext *global = rootContext(); for (int i = oldSize; i < nArgumentsAccessors; ++i) { - argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocObject<ArgumentsGetterFunction>(global, i)); - argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocObject<ArgumentsSetterFunction>(global, i)); + argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocate<ArgumentsGetterFunction>(global, i)); + argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocate<ArgumentsSetterFunction>(global, i)); } } } @@ -912,7 +925,9 @@ void ExecutionEngine::markObjects(MarkStack *markStack) setter->mark(markStack); } - classPool->markObjects(markStack); + for (int i = 0; i < NClasses; ++i) + if (classes[i]) + classes[i]->mark(markStack); markStack->drain(); for (auto compilationUnit: compilationUnits) { @@ -1056,12 +1071,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError() error.setColumn(frame.column); } QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception); - if (!!errorObj && errorObj->asSyntaxError()) { - QV4::ScopedString m(scope, newString(QStringLiteral("message"))); - QV4::ScopedValue v(scope, errorObj->get(m)); - error.setDescription(v->toQStringNoThrow()); - } else - error.setDescription(exception->toQStringNoThrow()); + error.setDescription(exception->toQStringNoThrow()); return error; } @@ -1120,8 +1130,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return v->toVariant(); } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) { return l->toVariant(); - } else if (object->isListType()) +#if QT_CONFIG(qml_sequence_object) + } else if (object->isListType()) { return QV4::SequencePrototype::toVariant(object); +#endif + } } if (value.as<ArrayObject>()) { @@ -1144,10 +1157,12 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return QVariant::fromValue(QV4::JsonObject::toJsonArray(a)); } +#if QT_CONFIG(qml_sequence_object) bool succeeded = false; QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded); if (succeeded) return retn; +#endif } if (value.isUndefined()) @@ -1167,8 +1182,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return str.at(0); return str; } +#if QT_CONFIG(qml_locale) if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>()) return *ld->d()->locale; +#endif if (const QV4::DateObject *d = value.as<DateObject>()) return d->toQDateTime(); if (const ArrayBuffer *d = value.as<ArrayBuffer>()) @@ -1324,6 +1341,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr))); case QMetaType::QObjectStar: return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr)); +#if QT_CONFIG(qml_sequence_object) case QMetaType::QStringList: { bool succeeded = false; @@ -1333,6 +1351,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) return retn->asReturnedValue(); return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(ptr))); } +#endif case QMetaType::QVariantList: return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr)); case QMetaType::QVariantMap: @@ -1343,8 +1362,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(ptr)); case QMetaType::QJsonArray: return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(ptr)); +#if QT_CONFIG(qml_locale) case QMetaType::QLocale: return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr)); +#endif default: break; } @@ -1384,10 +1405,12 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) if (objOk) return QV4::QObjectWrapper::wrap(this, obj); +#if QT_CONFIG(qml_sequence_object) bool succeeded = false; QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(this, variant, &succeeded)); if (succeeded) return retn->asReturnedValue(); +#endif if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type)) return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index c7fb743088..4316967484 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -88,8 +88,6 @@ struct CompilationUnit; } struct Function; -struct InternalClass; -struct InternalClassPool; struct Q_QML_EXPORT CppStackFrame { CppStackFrame *parent; @@ -153,10 +151,11 @@ public: QJSEngine *jsEngine() const; QQmlEngine *qmlEngine() const; #else // !V4_BOOTSTRAP - QJSEngine *jsEngine() const { return v8Engine->publicEngine(); } + QJSEngine *jsEngine() const { return publicEngine; } QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; } #endif // V4_BOOTSTRAP QV8Engine *v8Engine; + QJSEngine *publicEngine; enum JSObjects { RootContext, @@ -178,7 +177,9 @@ public: TypeErrorProto, URIErrorProto, VariantProto, +#if QT_CONFIG(qml_sequence_object) SequenceProto, +#endif ArrayBufferProto, DataViewProto, ValueTypeProto, @@ -247,7 +248,9 @@ public: Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); } Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); } Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); } +#if QT_CONFIG(qml_sequence_object) Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); } +#endif Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); } Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); } @@ -256,7 +259,6 @@ public: Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); } Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); } - InternalClassPool *classPool; EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); } FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); } FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); } @@ -372,9 +374,9 @@ public: const bool m_canAllocateExecutableMemory; #endif - int internalClassIdCount = 0; + quintptr protoIdCount = 1; - ExecutionEngine(); + ExecutionEngine(QJSEngine *jsEngine = nullptr); ~ExecutionEngine(); #if !QT_CONFIG(qml_debug) @@ -396,12 +398,13 @@ public: return static_cast<ExecutionContext *>(¤tStackFrame->jsFrame->context); } - int newInternalClassId() { return ++internalClassIdCount; } + // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast + quintptr newProtoId() { return (protoIdCount += 2); } - InternalClass *newInternalClass(const VTable *vtable, Object *prototype); + Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype); Heap::Object *newObject(); - Heap::Object *newObject(InternalClass *internalClass, Object *prototype); + Heap::Object *newObject(Heap::InternalClass *internalClass); Heap::String *newString(const QString &s = QString()); Heap::String *newIdentifier(const QString &text); @@ -413,7 +416,7 @@ public: Heap::ArrayObject *newArrayObject(int count = 0); Heap::ArrayObject *newArrayObject(const Value *values, int length); Heap::ArrayObject *newArrayObject(const QStringList &list); - Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype); + Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic); Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array); Heap::ArrayBuffer *newArrayBuffer(size_t length); @@ -453,7 +456,7 @@ public: void initRootContext(); - InternalClass *newClass(const InternalClass &other); + Heap::InternalClass *newClass(Heap::InternalClass *other); StackTrace exceptionStackTrace; diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h index 59fb4a564a..b7f6b8d3cd 100644 --- a/src/qml/jsruntime/qv4enginebase_p.h +++ b/src/qml/jsruntime/qv4enginebase_p.h @@ -88,7 +88,7 @@ struct Q_QML_EXPORT EngineBase { // Exception handling Value *exceptionValue = nullptr; - enum { + enum InternalClassType { Class_Empty, Class_String, Class_MemberData, @@ -96,6 +96,8 @@ struct Q_QML_EXPORT EngineBase { Class_SparseArrayData, Class_ExecutionContext, Class_CallContext, + Class_CatchContext, + Class_QmlContext, Class_Object, Class_ArrayObject, Class_FunctionObject, @@ -111,10 +113,10 @@ struct Q_QML_EXPORT EngineBase { Class_ErrorObjectWithMessage, Class_ErrorProto, Class_QmlContextWrapper, - Class_QmlContext, NClasses }; - InternalClass *internalClasses[NClasses]; + Heap::InternalClass *classes[NClasses]; + Heap::InternalClass *internalClasses(InternalClassType icType) { return classes[icType]; } }; #if defined(Q_CC_MSVC) || defined(Q_CC_GNU) #pragma pack(pop) diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 90e158ba37..56eb98b6b6 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -47,10 +47,6 @@ #include "qv4string_p.h" #include <private/qv4mm_p.h> -#include <private/qqmljsengine_p.h> -#include <private/qqmljslexer_p.h> -#include <private/qqmljsparser_p.h> -#include <private/qqmljsast_p.h> #include <qv4codegen_p.h> #ifndef Q_OS_WIN @@ -74,7 +70,7 @@ void Heap::ErrorObject::init() Scope scope(internalClass->engine); Scoped<QV4::ErrorObject> e(scope, this); - if (internalClass == scope.engine->internalClasses[EngineBase::Class_ErrorProto]) + if (internalClass == scope.engine->internalClasses(EngineBase::Class_ErrorProto)) return; setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d()); diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 6b578e8c38..44b88f0d31 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -180,7 +180,7 @@ struct ErrorObject: Object { template<> inline const ErrorObject *Value::as() const { - return isManaged() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : nullptr; + return isManaged() && m()->internalClass->vtable->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : nullptr; } struct EvalErrorObject: ErrorObject { @@ -328,25 +328,26 @@ inline SyntaxErrorObject *ErrorObject::asSyntaxError() template <typename T> Heap::Object *ErrorObject::create(ExecutionEngine *e, const Value &message) { - InternalClass *ic = e->internalClasses[message.isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage]; - ic = ic->changePrototype(T::defaultPrototype(e)->d()); - return e->memoryManager->allocObject<T>(ic, T::defaultPrototype(e), message); + EngineBase::InternalClassType klass = message.isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage; + Scope scope(e); + Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d())); + return e->memoryManager->allocObject<T>(ic->d(), message); } template <typename T> Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message) { Scope scope(e); ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue()); - InternalClass *ic = e->internalClasses[v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage]; - ic = ic->changePrototype(T::defaultPrototype(e)->d()); - return e->memoryManager->allocObject<T>(ic, T::defaultPrototype(e), v); + EngineBase::InternalClassType klass = v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage; + Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d())); + return e->memoryManager->allocObject<T>(ic->d(), v); } template <typename T> Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column) { Scope scope(e); ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue()); - InternalClass *ic = e->internalClasses[v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage]; - ic = ic->changePrototype(T::defaultPrototype(e)->d()); - return e->memoryManager->allocObject<T>(ic, T::defaultPrototype(e), v, filename, line, column); + EngineBase::InternalClassType klass = v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage; + Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d())); + return e->memoryManager->allocObject<T>(ic->d(), v, filename, line, column); } diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 83e861138b..493147e99b 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -61,18 +61,18 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, , codeRef(nullptr) , hasQmlDependencies(function->hasQmlDependencies()) { - Q_UNUSED(engine); - - internalClass = engine->internalClasses[EngineBase::Class_CallContext]; + Scope scope(engine); + Scoped<InternalClass> ic(scope, engine->internalClasses(EngineBase::Class_CallContext)); // first locals const quint32_le *localsIndices = compiledFunction->localsTable(); for (quint32 i = 0; i < compiledFunction->nLocals; ++i) - internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); + ic = ic->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); const quint32_le *formalsIndices = compiledFunction->formalsTable(); for (quint32 i = 0; i < compiledFunction->nFormals; ++i) - internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[formalsIndices[i]]), Attr_NotConfigurable); + ic = ic->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[formalsIndices[i]]), Attr_NotConfigurable); + internalClass = ic->d(); nFormals = compiledFunction->nFormals; } @@ -110,7 +110,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr } - internalClass = engine->internalClasses[EngineBase::Class_CallContext]; + internalClass = engine->internalClasses(EngineBase::Class_CallContext); Scope scope(engine); ScopedString arg(scope); diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 59a94e5dde..c8dbcec51d 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -81,7 +81,7 @@ struct Q_QML_EXPORT Function { JSC::MacroAssemblerCodeRef *codeRef; // first nArguments names in internalClass are the actual arguments - InternalClass *internalClass; + Heap::InternalClass *internalClass; uint nFormals; int interpreterCallCount = 0; bool hasQmlDependencies; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index dc8ee550d5..390e0d5161 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -146,8 +146,8 @@ void FunctionObject::init(String *n, bool createProto) Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()) == Heap::FunctionObject::Index_Prototype); if (createProto) { - ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses[EngineBase::Class_ObjectProto], s.engine->objectPrototype())); - Q_ASSERT(s.engine->internalClasses[EngineBase::Class_ObjectProto]->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor); + ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto))); + Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor); proto->setProperty(Heap::FunctionObject::Index_ProtoConstructor, d()); setProperty(Heap::FunctionObject::Index_Prototype, proto); } else { @@ -175,7 +175,7 @@ ReturnedValue FunctionObject::call(const FunctionObject *, const Value *, const Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function) { - return scope->engine()->memoryManager->allocObject<ScriptFunction>(scope, function); + return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function); } bool FunctionObject::isBinding() const @@ -240,6 +240,9 @@ ReturnedValue FunctionCtor::callAsConstructor(const FunctionObject *f, const Val RuntimeCodegen cg(scope.engine, &jsGenerator, false); cg.generateFromFunctionExpression(QString(), function, fe, &module); + if (scope.hasException()) + return Encode::undefined(); + QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = cg.generateCompilationUnit(); Function *vmf = compilationUnit->linkToEngine(scope.engine); @@ -389,8 +392,7 @@ ReturnedValue ScriptFunction::callAsConstructor(const FunctionObject *fo, const const ScriptFunction *f = static_cast<const ScriptFunction *>(fo); Scope scope(v4); - InternalClass *ic = f->classForConstructor(); - ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic)); + ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(f->classForConstructor())); ReturnedValue result = Moth::VME::exec(fo, thisObject, argv, argc); @@ -432,19 +434,19 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function } } -InternalClass *ScriptFunction::classForConstructor() const +Heap::InternalClass *ScriptFunction::classForConstructor() const { const Object *o = d()->protoProperty(); - InternalClass *ic = d()->cachedClassForConstructor; - if (ic && ic->prototype == o->d()) - return ic; + if (d()->cachedClassForConstructor && d()->cachedClassForConstructor->prototype == o->d()) + return d()->cachedClassForConstructor; - ic = engine()->internalClasses[EngineBase::Class_Object]; + Scope scope(engine()); + Scoped<InternalClass> ic(scope, engine()->internalClasses(EngineBase::Class_Object)); if (o) ic = ic->changePrototype(o->d()); - d()->cachedClassForConstructor = ic; + d()->cachedClassForConstructor.set(scope.engine, ic->d()); - return ic; + return ic->d(); } DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 32e71a175b..bd5b756aed 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -111,14 +111,16 @@ struct IndexedBuiltinFunction : FunctionObject { uint index; }; -struct ScriptFunction : FunctionObject { +#define ScriptFunctionMembers(class, Member) \ + Member(class, Pointer, InternalClass *, cachedClassForConstructor) + +DECLARE_HEAP_OBJECT(ScriptFunction, FunctionObject) { + DECLARE_MARKOBJECTS(ScriptFunction) enum { Index_Name = FunctionObject::Index_Prototype + 1, Index_Length }; void init(QV4::ExecutionContext *scope, Function *function); - - QV4::InternalClass *cachedClassForConstructor; }; #define BoundFunctionMembers(class, Member) \ @@ -169,7 +171,7 @@ struct Q_QML_EXPORT FunctionObject: Object { static Heap::FunctionObject *createBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)) { - return scope->engine()->memoryManager->allocObject<FunctionObject>(scope, name, code); + return scope->engine()->memoryManager->allocate<FunctionObject>(scope, name, code); } bool strictMode() const { return d()->function ? d()->function->isStrict() : false; } @@ -181,7 +183,7 @@ struct Q_QML_EXPORT FunctionObject: Object { template<> inline const FunctionObject *Value::as() const { - return isManaged() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : nullptr; + return isManaged() && m()->internalClass->vtable->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : nullptr; } @@ -227,7 +229,7 @@ struct ScriptFunction : FunctionObject { static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc); static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); - InternalClass *classForConstructor() const; + Heap::InternalClass *classForConstructor() const; }; @@ -236,7 +238,7 @@ struct BoundFunction: FunctionObject { static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs) { - return scope->engine()->memoryManager->allocObject<BoundFunction>(scope, target, boundThis, boundArgs); + return scope->engine()->memoryManager->allocate<BoundFunction>(scope, target, boundThis, boundArgs); } Heap::FunctionObject *target() const { return d()->target; } diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 9b13d4e341..9cc63a98c5 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -166,7 +166,9 @@ namespace Heap { struct ExecutionContext; struct CallContext; + struct QmlContext; struct ScriptFunction; + struct InternalClass; struct BooleanObject; struct NumberObject; @@ -196,6 +198,7 @@ struct ObjectPrototype; struct ObjectIterator; struct ExecutionContext; struct CallContext; +struct QmlContext; struct ScriptFunction; struct InternalClass; struct Property; diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 9da854e7d7..4c7eb7b185 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE -using namespace QV4; +namespace QV4 { static const uchar prime_deltas[] = { 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, @@ -74,24 +74,8 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) // fill up to max 50% bool grow = (d->alloc <= d->size*2); - if (classSize < d->size || grow) { - PropertyHashData *dd = new PropertyHashData(grow ? d->numBits + 1 : d->numBits); - for (int i = 0; i < d->alloc; ++i) { - const Entry &e = d->entries[i]; - if (!e.identifier || e.index >= static_cast<unsigned>(classSize)) - continue; - uint idx = e.identifier->hashValue % dd->alloc; - while (dd->entries[idx].identifier) { - ++idx; - idx %= dd->alloc; - } - dd->entries[idx] = e; - } - dd->size = classSize; - Q_ASSERT(d->refCount > 1); - --d->refCount; - d = dd; - } + if (classSize < d->size || grow) + detach(grow, classSize); uint idx = entry.identifier->hashValue % d->alloc; while (d->entries[idx].identifier) { @@ -102,38 +86,125 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) ++d->size; } +int PropertyHash::removeIdentifier(Identifier *identifier, int classSize) +{ + int val = -1; + PropertyHashData *dd = new PropertyHashData(d->numBits); + for (int i = 0; i < d->alloc; ++i) { + const Entry &e = d->entries[i]; + if (!e.identifier || e.index >= static_cast<unsigned>(classSize)) + continue; + if (e.identifier == identifier) { + val = e.index; + continue; + } + uint idx = e.identifier->hashValue % dd->alloc; + while (dd->entries[idx].identifier) { + ++idx; + idx %= dd->alloc; + } + dd->entries[idx] = e; + } + dd->size = classSize; + if (!--d->refCount) + delete d; + d = dd; -InternalClass::InternalClass(ExecutionEngine *engine) - : engine(engine) - , vtable(nullptr) - , prototype(nullptr) - , m_sealed(nullptr) - , m_frozen(nullptr) - , size(0) - , extensible(true) + Q_ASSERT(val != -1); + return val; +} + +void PropertyHash::detach(bool grow, int classSize) { - id = engine->newInternalClassId(); -} - - -InternalClass::InternalClass(const QV4::InternalClass &other) - : QQmlJS::Managed() - , engine(other.engine) - , vtable(other.vtable) - , prototype(other.prototype) - , propertyTable(other.propertyTable) - , nameMap(other.nameMap) - , propertyData(other.propertyData) - , m_sealed(nullptr) - , m_frozen(nullptr) - , size(other.size) - , extensible(other.extensible) - , isUsedAsProto(other.isUsedAsProto) + if (d->refCount == 1 && !grow) + return; + + PropertyHashData *dd = new PropertyHashData(grow ? d->numBits + 1 : d->numBits); + for (int i = 0; i < d->alloc; ++i) { + const Entry &e = d->entries[i]; + if (!e.identifier || e.index >= static_cast<unsigned>(classSize)) + continue; + uint idx = e.identifier->hashValue % dd->alloc; + while (dd->entries[idx].identifier) { + ++idx; + idx %= dd->alloc; + } + dd->entries[idx] = e; + } + dd->size = classSize; + if (!--d->refCount) + delete d; + d = dd; +} + +namespace Heap { + +void InternalClass::init(ExecutionEngine *engine) +{ + Base::init(); + new (&propertyTable) PropertyHash(); + new (&nameMap) SharedInternalClassData<Identifier *>(); + new (&propertyData) SharedInternalClassData<PropertyAttributes>(); + new (&transitions) std::vector<Transition>(); + + this->engine = engine; + vtable = QV4::InternalClass::staticVTable(); +// prototype = nullptr; +// parent = nullptr; +// size = 0; + extensible = true; + isFrozen = false; + isSealed = false; + isUsedAsProto = false; + protoId = engine->newProtoId(); + + // Also internal classes need an internal class pointer. Simply make it point to itself + internalClass.set(engine, this); +} + + +void InternalClass::init(Heap::InternalClass *other) +{ + Base::init(); + Q_ASSERT(!other->isFrozen); + new (&propertyTable) PropertyHash(other->propertyTable); + new (&nameMap) SharedInternalClassData<Identifier *>(other->nameMap); + new (&propertyData) SharedInternalClassData<PropertyAttributes>(other->propertyData); + new (&transitions) std::vector<Transition>(); + + engine = other->engine; + vtable = other->vtable; + prototype = other->prototype; + parent = other; + size = other->size; + extensible = other->extensible; + isSealed = other->isSealed; + isFrozen = other->isFrozen; + isUsedAsProto = other->isUsedAsProto; + protoId = engine->newProtoId(); + + internalClass.set(engine, other->internalClass); +} + +void InternalClass::destroy() { - id = engine->newInternalClassId(); +#ifndef QT_NO_DEBUG + for (const auto &t : transitions) { + Q_ASSERT(!t.lookup || !t.lookup->isMarked()); + } +#endif + if (parent && parent->engine && parent->isMarked()) + parent->removeChildEntry(this); + + propertyTable.~PropertyHash(); + nameMap.~SharedInternalClassData<Identifier *>(); + propertyData.~SharedInternalClassData<PropertyAttributes>(); + transitions.~vector<Transition>(); + engine = nullptr; + Base::destroy(); } -static void insertHoleIntoPropertyData(Object *object, int idx) +static void insertHoleIntoPropertyData(QV4::Object *object, int idx) { Heap::Object *o = object->d(); ExecutionEngine *v4 = o->internalClass->engine; @@ -142,7 +213,7 @@ static void insertHoleIntoPropertyData(Object *object, int idx) o->setProperty(v4, i, *o->propertyData(i - 1)); } -static void removeFromPropertyData(Object *object, int idx, bool accessor = false) +static void removeFromPropertyData(QV4::Object *object, int idx, bool accessor = false) { Heap::Object *o = object->d(); ExecutionEngine *v4 = o->internalClass->engine; @@ -154,20 +225,22 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals o->setProperty(v4, size + 1, Primitive::undefinedValue()); } -void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index) +void InternalClass::changeMember(QV4::Object *object, QV4::String *string, PropertyAttributes data, uint *index) { uint idx; - InternalClass *oldClass = object->internalClass(); - InternalClass *newClass = oldClass->changeMember(string->identifier(), data, &idx); + Heap::InternalClass *oldClass = object->internalClass(); + Heap::InternalClass *newClass = oldClass->changeMember(string->identifier(), data, &idx); if (index) *index = idx; + uint oldSize = oldClass->size; object->setInternalClass(newClass); - if (newClass->size > oldClass->size) { - Q_ASSERT(newClass->size == oldClass->size + 1); + // don't use oldClass anymore, it could be GC'ed + if (newClass->size > oldSize) { + Q_ASSERT(newClass->size == oldSize + 1); insertHoleIntoPropertyData(object, idx); - } else if (newClass->size < oldClass->size) { - Q_ASSERT(newClass->size == oldClass->size - 1); + } else if (newClass->size < oldSize) { + Q_ASSERT(newClass->size == oldSize - 1); removeFromPropertyData(object, idx + 1); } } @@ -183,7 +256,16 @@ InternalClassTransition &InternalClass::lookupOrInsertTransition(const InternalC } } -InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttributes data, uint *index) +static void addDummyEntry(InternalClass *newClass, PropertyHash::Entry e) +{ + // add a dummy entry, since we need two entries for accessors + newClass->propertyTable.addEntry(e, newClass->size); + newClass->nameMap.add(newClass->size, nullptr); + newClass->propertyData.add(newClass->size, PropertyAttributes()); + ++newClass->size; +} + +Heap::InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttributes data, uint *index) { data.resolve(); uint idx = find(identifier); @@ -193,7 +275,7 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri *index = idx; if (data == propertyData.at(idx)) - return this; + return static_cast<Heap::InternalClass *>(this); Transition temp = { { identifier }, nullptr, (int)data.flags() }; Transition &t = lookupOrInsertTransition(temp); @@ -201,14 +283,34 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri return t.lookup; // create a new class and add it to the tree - InternalClass *newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); - newClass = newClass->changePrototype(prototype); - for (uint i = 0; i < size; ++i) { - if (i == idx) { - newClass = newClass->addMember(nameMap.at(i), data); - } else if (!propertyData.at(i).isEmpty()) { - newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + Heap::InternalClass *newClass = engine->newClass(this); + if (data.isAccessor() != propertyData.at(idx).isAccessor()) { + // this changes the layout of the class, so we need to rebuild the data + newClass->propertyTable = PropertyHash(); + newClass->nameMap = SharedInternalClassData<Identifier *>(); + newClass->propertyData = SharedInternalClassData<PropertyAttributes>(); + newClass->size = 0; + for (uint i = 0; i < size; ++i) { + Identifier *identifier = nameMap.at(i); + PropertyHash::Entry e = { identifier, newClass->size }; + if (!identifier) + e.identifier = nameMap.at(i - 1); + newClass->propertyTable.addEntry(e, newClass->size); + newClass->nameMap.add(newClass->size, identifier); + if (i == idx) { + newClass->propertyData.add(newClass->size, data); + ++newClass->size; + if (data.isAccessor()) + addDummyEntry(newClass, e); + else + ++i; + } else { + newClass->propertyData.add(newClass->size, propertyData.at(i)); + ++newClass->size; + } } + } else { + newClass->propertyData.set(idx, data); } t.lookup = newClass; @@ -216,8 +318,10 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri return newClass; } -InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto) +Heap::InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto) { + Scope scope(engine); + ScopedValue protectThis(scope, this); if (proto) proto->setUsedAsProto(); Q_ASSERT(prototype != proto); @@ -231,25 +335,15 @@ InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto) return t.lookup; // create a new class and add it to the tree - InternalClass *newClass; - if (!size && !prototype) { - newClass = engine->newClass(*this); - newClass->prototype = proto; - } else { - newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); - newClass = newClass->changePrototype(proto); - for (uint i = 0; i < size; ++i) { - if (!propertyData.at(i).isEmpty()) - newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); - } - } + Heap::InternalClass *newClass = engine->newClass(this); + newClass->prototype = proto; t.lookup = newClass; return newClass; } -InternalClass *InternalClass::changeVTableImpl(const VTable *vt) +Heap::InternalClass *InternalClass::changeVTableImpl(const VTable *vt) { Q_ASSERT(vtable != vt); @@ -261,18 +355,8 @@ InternalClass *InternalClass::changeVTableImpl(const VTable *vt) return t.lookup; // create a new class and add it to the tree - InternalClass *newClass; - if (this == engine->internalClasses[EngineBase::Class_Empty]) { - newClass = engine->newClass(*this); - newClass->vtable = vt; - } else { - newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vt); - newClass = newClass->changePrototype(prototype); - for (uint i = 0; i < size; ++i) { - if (!propertyData.at(i).isEmpty()) - newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); - } - } + Heap::InternalClass *newClass = engine->newClass(this); + newClass->vtable = vt; t.lookup = newClass; Q_ASSERT(t.lookup); @@ -280,7 +364,7 @@ InternalClass *InternalClass::changeVTableImpl(const VTable *vt) return newClass; } -InternalClass *InternalClass::nonExtensible() +Heap::InternalClass *InternalClass::nonExtensible() { if (!extensible) return this; @@ -290,7 +374,7 @@ InternalClass *InternalClass::nonExtensible() if (t.lookup) return t.lookup; - InternalClass *newClass = engine->newClass(*this); + Heap::InternalClass *newClass = engine->newClass(this); newClass->extensible = false; t.lookup = newClass; @@ -298,7 +382,7 @@ InternalClass *InternalClass::nonExtensible() return newClass; } -void InternalClass::addMember(Object *object, String *string, PropertyAttributes data, uint *index) +void InternalClass::addMember(QV4::Object *object, QV4::String *string, PropertyAttributes data, uint *index) { data.resolve(); object->internalClass()->engine->identifierTable->identifier(string); @@ -308,20 +392,20 @@ void InternalClass::addMember(Object *object, String *string, PropertyAttributes } uint idx; - InternalClass *newClass = object->internalClass()->addMemberImpl(string->identifier(), data, &idx); + Heap::InternalClass *newClass = object->internalClass()->addMemberImpl(string->identifier(), data, &idx); if (index) *index = idx; object->setInternalClass(newClass); } -InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index) +Heap::InternalClass *InternalClass::addMember(QV4::String *string, PropertyAttributes data, uint *index) { engine->identifierTable->identifier(string); return addMember(string->identifier(), data, index); } -InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttributes data, uint *index) +Heap::InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttributes data, uint *index) { data.resolve(); @@ -331,7 +415,7 @@ InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttribut return addMemberImpl(identifier, data, index); } -InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index) +Heap::InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index) { Transition temp = { { identifier }, nullptr, (int)data.flags() }; Transition &t = lookupOrInsertTransition(temp); @@ -343,62 +427,59 @@ InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttr return t.lookup; // create a new class and add it to the tree - InternalClass *newClass = engine->newClass(*this); + Heap::InternalClass *newClass = engine->newClass(this); PropertyHash::Entry e = { identifier, newClass->size }; newClass->propertyTable.addEntry(e, newClass->size); newClass->nameMap.add(newClass->size, identifier); newClass->propertyData.add(newClass->size, data); ++newClass->size; - if (data.isAccessor()) { - // add a dummy entry, since we need two entries for accessors - newClass->propertyTable.addEntry(e, newClass->size); - newClass->nameMap.add(newClass->size, 0); - newClass->propertyData.add(newClass->size, PropertyAttributes()); - ++newClass->size; - } + if (data.isAccessor()) + addDummyEntry(newClass, e); t.lookup = newClass; Q_ASSERT(t.lookup); return newClass; } -void InternalClass::removeMember(Object *object, Identifier *id) +void InternalClass::removeChildEntry(InternalClass *child) +{ + Q_ASSERT(engine); + for (auto &t : transitions) { + if (t.lookup == child) { + t.lookup = nullptr; + return; + } + } + Q_UNREACHABLE(); + +} + +void InternalClass::removeMember(QV4::Object *object, Identifier *identifier) { - InternalClass *oldClass = object->internalClass(); - uint propIdx = oldClass->propertyTable.lookup(id); - Q_ASSERT(propIdx < oldClass->size); + Heap::InternalClass *oldClass = object->internalClass(); + Q_ASSERT(oldClass->propertyTable.lookup(identifier) < oldClass->size); - Transition temp = { { id }, nullptr, -1 }; + Transition temp = { { identifier }, nullptr, Transition::RemoveMember }; Transition &t = object->internalClass()->lookupOrInsertTransition(temp); - bool accessor = oldClass->propertyData.at(propIdx).isAccessor(); - - if (t.lookup) { - object->setInternalClass(t.lookup); - } else { + if (!t.lookup) { // create a new class and add it to the tree - InternalClass *newClass = oldClass->engine->internalClasses[EngineBase::Class_Empty]->changeVTable(oldClass->vtable); - newClass = newClass->changePrototype(oldClass->prototype); - for (uint i = 0; i < oldClass->size; ++i) { - if (i == propIdx) - continue; - if (!oldClass->propertyData.at(i).isEmpty()) - newClass = newClass->addMember(oldClass->nameMap.at(i), oldClass->propertyData.at(i)); - } - object->setInternalClass(newClass); + Heap::InternalClass *newClass = oldClass->engine->newClass(oldClass); + // simply make the entry inaccessible + int idx = newClass->propertyTable.removeIdentifier(identifier, oldClass->size); + newClass->nameMap.set(idx, nullptr); + newClass->propertyData.set(idx, PropertyAttributes()); + t.lookup = newClass; + Q_ASSERT(t.lookup); } + object->setInternalClass(t.lookup); - Q_ASSERT(object->internalClass()->size == oldClass->size - (accessor ? 2 : 1)); - - // remove the entry in the property data - removeFromPropertyData(object, propIdx, accessor); - - t.lookup = object->internalClass(); - Q_ASSERT(t.lookup); + // we didn't remove the data slot, just made it inaccessible + Q_ASSERT(object->internalClass()->size == oldClass->size); } -uint InternalClass::find(const String *string) +uint InternalClass::find(const QV4::String *string) { engine->identifierTable->identifier(string); const Identifier *id = string->d()->identifier; @@ -410,42 +491,104 @@ uint InternalClass::find(const String *string) return UINT_MAX; } -InternalClass *InternalClass::sealed() +Heap::InternalClass *InternalClass::sealed() { - if (m_sealed) - return m_sealed; + if (isSealed) + return this; + + bool alreadySealed = !extensible; + for (uint i = 0; i < size; ++i) { + PropertyAttributes attrs = propertyData.at(i); + if (attrs.isEmpty()) + continue; + if (attrs.isConfigurable()) { + alreadySealed = false; + break; + } + } + + if (alreadySealed) { + isSealed = true; + return this; + } + + Transition temp = { { nullptr }, nullptr, InternalClassTransition::Sealed }; + Transition &t = lookupOrInsertTransition(temp); + + if (t.lookup) { + Q_ASSERT(t.lookup && t.lookup->isSealed); + return t.lookup; + } + + Heap::InternalClass *s = engine->newClass(this); - m_sealed = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); - m_sealed = m_sealed->changePrototype(prototype); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); if (attrs.isEmpty()) continue; attrs.setConfigurable(false); - m_sealed = m_sealed->addMember(nameMap.at(i), attrs); + s->propertyData.set(i, attrs); } - m_sealed = m_sealed->nonExtensible(); + s->extensible = false; + s->isSealed = true; - m_sealed->m_sealed = m_sealed; - return m_sealed; + t.lookup = s; + return s; } -InternalClass *InternalClass::frozen() +Heap::InternalClass *InternalClass::frozen() { - if (m_frozen) - return m_frozen; + if (isFrozen) + return this; + + bool alreadyFrozen = !extensible; + for (uint i = 0; i < size; ++i) { + PropertyAttributes attrs = propertyData.at(i); + if (attrs.isEmpty()) + continue; + if ((attrs.isData() && attrs.isWritable()) || attrs.isConfigurable()) { + alreadyFrozen = false; + break; + } + } + + if (alreadyFrozen) { + isSealed = true; + isFrozen = true; + return this; + } + + Transition temp = { { nullptr }, nullptr, InternalClassTransition::Frozen }; + Transition &t = lookupOrInsertTransition(temp); + + if (t.lookup) { + Q_ASSERT(t.lookup && t.lookup->isSealed && t.lookup->isFrozen); + return t.lookup; + } + + Heap::InternalClass *f = engine->newClass(this); - m_frozen = propertiesFrozen(); - m_frozen = m_frozen->nonExtensible(); + for (uint i = 0; i < size; ++i) { + PropertyAttributes attrs = propertyData.at(i); + if (attrs.isEmpty()) + continue; + if (attrs.isData()) + attrs.setWritable(false); + attrs.setConfigurable(false); + f->propertyData.set(i, attrs); + } + f->extensible = false; + f->isSealed = true; + f->isFrozen = true; - m_frozen->m_frozen = m_frozen; - m_frozen->m_sealed = m_frozen; - return m_frozen; + t.lookup = f; + return f; } -InternalClass *InternalClass::propertiesFrozen() const +Heap::InternalClass *InternalClass::propertiesFrozen() const { - InternalClass *frozen = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); + Scope scope(engine); + Scoped<QV4::InternalClass> frozen(scope, engine->internalClasses(EngineBase::Class_Empty)->changeVTable(vtable)); frozen = frozen->changePrototype(prototype); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); @@ -455,10 +598,10 @@ InternalClass *InternalClass::propertiesFrozen() const attrs.setConfigurable(false); frozen = frozen->addMember(nameMap.at(i), attrs); } - return frozen; + return frozen->d(); } -InternalClass *InternalClass::asProtoClass() +Heap::InternalClass *InternalClass::asProtoClass() { if (isUsedAsProto) return this; @@ -468,7 +611,7 @@ InternalClass *InternalClass::asProtoClass() if (t.lookup) return t.lookup; - InternalClass *newClass = engine->newClass(*this); + Heap::InternalClass *newClass = engine->newClass(this); newClass->isUsedAsProto = true; t.lookup = newClass; @@ -476,88 +619,37 @@ InternalClass *InternalClass::asProtoClass() return newClass; } -void InternalClass::destroy() +static void updateProtoUsage(Heap::Object *o, Heap::InternalClass *ic) { - std::vector<InternalClass *> destroyStack; - destroyStack.reserve(64); - destroyStack.push_back(this); - - while (!destroyStack.empty()) { - InternalClass *next = destroyStack.back(); - destroyStack.pop_back(); - if (!next->engine) - continue; - next->engine = nullptr; - next->propertyTable.~PropertyHash(); - next->nameMap.~SharedInternalClassData<Identifier *>(); - next->propertyData.~SharedInternalClassData<PropertyAttributes>(); - if (next->m_sealed) - destroyStack.push_back(next->m_sealed); - if (next->m_frozen) - destroyStack.push_back(next->m_frozen); - - for (size_t i = 0; i < next->transitions.size(); ++i) { - Q_ASSERT(next->transitions.at(i).lookup); - destroyStack.push_back(next->transitions.at(i).lookup); - } - - next->transitions.~vector<Transition>(); + if (ic->prototype == o) + ic->protoId = ic->engine->newProtoId(); + for (auto &t : ic->transitions) { + if (t.lookup) + updateProtoUsage(o, t.lookup); } } + void InternalClass::updateProtoUsage(Heap::Object *o) { Q_ASSERT(isUsedAsProto); - InternalClass *ic = engine->internalClasses[EngineBase::Class_Empty]; + Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_Empty); Q_ASSERT(!ic->prototype); - // only need to go two levels into the IC hierarchy, as prototype changes - // can only happen there - for (auto &t : ic->transitions) { - Q_ASSERT(t.lookup); - if (t.flags == InternalClassTransition::VTableChange) { - InternalClass *ic2 = t.lookup; - for (auto &t2 : ic2->transitions) { - if (t2.flags == InternalClassTransition::PrototypeChange && - t2.lookup->prototype == o) - ic2->updateInternalClassIdRecursive(); - } - } else if (t.flags == InternalClassTransition::PrototypeChange && t.lookup->prototype == o) { - ic->updateInternalClassIdRecursive(); - } - } + Heap::updateProtoUsage(o, ic); } -void InternalClass::updateInternalClassIdRecursive() +void InternalClass::markObjects(Heap::Base *b, MarkStack *stack) { - id = engine->newInternalClassId(); - for (auto &t : transitions) { - Q_ASSERT(t.lookup); - t.lookup->updateInternalClassIdRecursive(); - } + Heap::InternalClass *ic = static_cast<Heap::InternalClass *>(b); + if (ic->prototype) + ic->prototype->mark(stack); + if (ic->parent) + ic->parent->mark(stack); } +} - -void InternalClassPool::markObjects(MarkStack *markStack) -{ - InternalClass *ic = markStack->engine->internalClasses[EngineBase::Class_Empty]; - Q_ASSERT(!ic->prototype); - - // only need to go two levels into the IC hierarchy, as prototype changes - // can only happen there - for (auto &t : ic->transitions) { - Q_ASSERT(t.lookup); - if (t.flags == InternalClassTransition::VTableChange) { - InternalClass *ic2 = t.lookup; - for (auto &t2 : ic2->transitions) { - if (t2.flags == InternalClassTransition::PrototypeChange) - t2.lookup->prototype->mark(markStack); - } - } else if (t.flags == InternalClassTransition::PrototypeChange) { - t.lookup->prototype->mark(markStack); - } - } } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index b689272006..0b6f088bd3 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -53,8 +53,8 @@ #include "qv4global_p.h" #include <QHash> -#include <private/qqmljsmemorypool_p.h> #include <private/qv4identifier_p.h> +#include <private/qv4heap_p.h> QT_BEGIN_NAMESPACE @@ -79,12 +79,12 @@ struct PropertyHash inline PropertyHash(); inline PropertyHash(const PropertyHash &other); inline ~PropertyHash(); + PropertyHash &operator=(const PropertyHash &other); void addEntry(const Entry &entry, int classSize); uint lookup(const Identifier *identifier) const; - -private: - PropertyHash &operator=(const PropertyHash &other); + int removeIdentifier(Identifier *identifier, int classSize); + void detach(bool grow, int classSize); }; struct PropertyHashData @@ -118,6 +118,17 @@ inline PropertyHash::~PropertyHash() delete d; } +inline PropertyHash &PropertyHash::operator=(const PropertyHash &other) +{ + ++other.d->refCount; + if (!--d->refCount) + delete d; + d = other.d; + return *this; +} + + + inline uint PropertyHash::lookup(const Identifier *identifier) const { Q_ASSERT(d->entries); @@ -163,6 +174,13 @@ struct SharedInternalClassData { if (!--d->refcount) delete d; } + SharedInternalClassData &operator=(const SharedInternalClassData &other) { + ++other.d->refcount; + if (!--d->refcount) + delete d; + d = other.d; + return *this; + } void add(uint pos, T value) { if (pos < d->size) { @@ -214,9 +232,6 @@ struct SharedInternalClassData { Q_ASSERT(i < d->size); return d->data[i]; } - -private: - SharedInternalClassData &operator=(const SharedInternalClassData &other); }; struct InternalClassTransition @@ -226,14 +241,17 @@ struct InternalClassTransition const VTable *vtable; Heap::Object *prototype; }; - InternalClass *lookup; + Heap::InternalClass *lookup; int flags; enum { // range 0-0xff is reserved for attribute changes NotExtensible = 0x100, VTableChange = 0x200, PrototypeChange = 0x201, - ProtoClass = 0x202 + ProtoClass = 0x202, + Sealed = 0x203, + Frozen = 0x204, + RemoveMember = -1 }; bool operator==(const InternalClassTransition &other) const @@ -243,11 +261,14 @@ struct InternalClassTransition { return id < other.id || (id == other.id && flags < other.flags); } }; -struct InternalClass : public QQmlJS::Managed { - int id = 0; // unique across the engine, gets changed also when proto chain changes +namespace Heap { + +struct InternalClass : Base { ExecutionEngine *engine; const VTable *vtable; + quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes Heap::Object *prototype; + InternalClass *parent; PropertyHash propertyTable; // id to valueIndex SharedInternalClassData<Identifier *> nameMap; @@ -257,32 +278,25 @@ struct InternalClass : public QQmlJS::Managed { std::vector<Transition> transitions; InternalClassTransition &lookupOrInsertTransition(const InternalClassTransition &t); - InternalClass *m_sealed; - InternalClass *m_frozen; - uint size; bool extensible; - bool isUsedAsProto = false; + bool isSealed; + bool isFrozen; + bool isUsedAsProto; + + void init(ExecutionEngine *engine); + void init(InternalClass *other); + void destroy(); Q_REQUIRED_RESULT InternalClass *nonExtensible(); - Q_REQUIRED_RESULT InternalClass *changeVTable(const VTable *vt) { - if (vtable == vt) - return this; - return changeVTableImpl(vt); - } - Q_REQUIRED_RESULT InternalClass *changePrototype(Heap::Object *proto) { - if (prototype == proto) - return this; - return changePrototypeImpl(proto); - } - static void addMember(Object *object, String *string, PropertyAttributes data, uint *index); - Q_REQUIRED_RESULT InternalClass *addMember(String *string, PropertyAttributes data, uint *index = nullptr); + static void addMember(QV4::Object *object, QV4::String *string, PropertyAttributes data, uint *index); + Q_REQUIRED_RESULT InternalClass *addMember(QV4::String *string, PropertyAttributes data, uint *index = nullptr); Q_REQUIRED_RESULT InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = nullptr); Q_REQUIRED_RESULT InternalClass *changeMember(Identifier *identifier, PropertyAttributes data, uint *index = nullptr); - static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = nullptr); - static void removeMember(Object *object, Identifier *id); - uint find(const String *string); + static void changeMember(QV4::Object *object, QV4::String *string, PropertyAttributes data, uint *index = nullptr); + static void removeMember(QV4::Object *object, Identifier *identifier); + uint find(const QV4::String *string); uint find(const Identifier *id) { uint index = propertyTable.lookup(id); @@ -298,24 +312,37 @@ struct InternalClass : public QQmlJS::Managed { Q_REQUIRED_RESULT InternalClass *asProtoClass(); - void destroy(); + Q_REQUIRED_RESULT InternalClass *changeVTable(const VTable *vt) { + if (vtable == vt) + return this; + return changeVTableImpl(vt); + } + Q_REQUIRED_RESULT InternalClass *changePrototype(Heap::Object *proto) { + if (prototype == proto) + return this; + return changePrototypeImpl(proto); + } void updateProtoUsage(Heap::Object *o); + static void markObjects(Heap::Base *ic, MarkStack *stack); + private: Q_QML_EXPORT InternalClass *changeVTableImpl(const VTable *vt); Q_QML_EXPORT InternalClass *changePrototypeImpl(Heap::Object *proto); InternalClass *addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index); - void updateInternalClassIdRecursive(); + + void removeChildEntry(InternalClass *child); friend struct ExecutionEngine; - InternalClass(ExecutionEngine *engine); - InternalClass(const InternalClass &other); }; -struct InternalClassPool : public QQmlJS::MemoryPool +inline +void Base::markObjects(Base *b, MarkStack *stack) { - void markObjects(MarkStack *markStack); -}; + b->internalClass->mark(stack); +} + +} } diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 52ab03cd94..fdf3d7685d 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -92,7 +92,7 @@ ReturnedValue Lookup::resolveGetter(ExecutionEngine *engine, const Object *objec return getter(this, engine, *object); } - protoLookup.icIdentifier = obj->internalClass->id; + protoLookup.protoId = obj->internalClass->protoId; resolveProtoGetter(name, obj->prototype()); return getter(this, engine, *object); } @@ -126,7 +126,7 @@ ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Valu } Identifier *name = engine->identifierTable->identifier(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); - protoLookup.icIdentifier = primitiveLookup.proto->internalClass->id; + protoLookup.protoId = primitiveLookup.proto->internalClass->protoId; resolveProtoGetter(name, primitiveLookup.proto); if (getter == getterProto) @@ -140,7 +140,7 @@ ReturnedValue Lookup::resolveGlobalGetter(ExecutionEngine *engine) { Object *o = engine->globalObject; Identifier *name = engine->identifierTable->identifier(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); - protoLookup.icIdentifier = o->internalClass()->id; + protoLookup.protoId = o->internalClass()->protoId; resolveProtoGetter(name, o->d()); if (getter == getterProto) @@ -188,16 +188,16 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const return result; } if (first.getter == getterProto && second.getter == getterProto) { - l->protoLookupTwoClasses.icIdentifier = first.protoLookup.icIdentifier; - l->protoLookupTwoClasses.icIdentifier2 = second.protoLookup.icIdentifier; + l->protoLookupTwoClasses.protoId = first.protoLookup.protoId; + l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId; l->protoLookupTwoClasses.data = first.protoLookup.data; l->protoLookupTwoClasses.data2 = second.protoLookup.data; l->getter = getterProtoTwoClasses; return result; } if (first.getter == getterProtoAccessor && second.getter == getterProtoAccessor) { - l->protoLookupTwoClasses.icIdentifier = first.protoLookup.icIdentifier; - l->protoLookupTwoClasses.icIdentifier2 = second.protoLookup.icIdentifier; + l->protoLookupTwoClasses.protoId = first.protoLookup.protoId; + l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId; l->protoLookupTwoClasses.data = first.protoLookup.data; l->protoLookupTwoClasses.data2 = second.protoLookup.data; l->getter = getterProtoAccessorTwoClasses; @@ -250,7 +250,7 @@ ReturnedValue Lookup::getterProto(Lookup *l, ExecutionEngine *engine, const Valu // the internal class won't match Heap::Object *o = static_cast<Heap::Object *>(object.heapObject()); if (o) { - if (l->protoLookup.icIdentifier == o->internalClass->id) + if (l->protoLookup.protoId == o->internalClass->protoId) return l->protoLookup.data->asReturnedValue(); } return getterTwoClasses(l, engine, object); @@ -307,9 +307,9 @@ ReturnedValue Lookup::getterProtoTwoClasses(Lookup *l, ExecutionEngine *engine, // the internal class won't match Heap::Object *o = static_cast<Heap::Object *>(object.heapObject()); if (o) { - if (l->protoLookupTwoClasses.icIdentifier == o->internalClass->id) + if (l->protoLookupTwoClasses.protoId == o->internalClass->protoId) return l->protoLookupTwoClasses.data->asReturnedValue(); - if (l->protoLookupTwoClasses.icIdentifier2 == o->internalClass->id) + if (l->protoLookupTwoClasses.protoId2 == o->internalClass->protoId) return l->protoLookupTwoClasses.data2->asReturnedValue(); return getterFallback(l, engine, object); } @@ -340,14 +340,13 @@ ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, co // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Heap::Object *o = static_cast<Heap::Object *>(object.heapObject()); - if (o && l->protoLookup.icIdentifier == o->internalClass->id) { + if (o && l->protoLookup.protoId == o->internalClass->protoId) { const Value *getter = l->protoLookup.data; if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); } - l->getter = getterTwoClasses; return getterTwoClasses(l, engine, object); } @@ -358,9 +357,9 @@ ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine * Heap::Object *o = static_cast<Heap::Object *>(object.heapObject()); if (o) { const Value *getter = nullptr; - if (l->protoLookupTwoClasses.icIdentifier == o->internalClass->id) + if (l->protoLookupTwoClasses.protoId == o->internalClass->protoId) getter = l->protoLookupTwoClasses.data; - else if (l->protoLookupTwoClasses.icIdentifier2 == o->internalClass->id) + else if (l->protoLookupTwoClasses.protoId2 == o->internalClass->protoId) getter = l->protoLookupTwoClasses.data2; if (getter) { if (!getter->isFunctionObject()) // ### catch at resolve time @@ -377,7 +376,7 @@ ReturnedValue Lookup::primitiveGetterProto(Lookup *l, ExecutionEngine *engine, c { if (object.type() == l->primitiveLookup.type) { Heap::Object *o = l->primitiveLookup.proto; - if (l->primitiveLookup.icIdentifier == o->internalClass->id) + if (l->primitiveLookup.protoId == o->internalClass->protoId) return l->primitiveLookup.data->asReturnedValue(); } l->getter = getterGeneric; @@ -388,7 +387,7 @@ ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine { if (object.type() == l->primitiveLookup.type) { Heap::Object *o = l->primitiveLookup.proto; - if (l->primitiveLookup.icIdentifier == o->internalClass->id) { + if (l->primitiveLookup.protoId == o->internalClass->protoId) { const Value *getter = l->primitiveLookup.data; if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); @@ -417,7 +416,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine) { Heap::Object *o = engine->globalObject->d(); - if (l->protoLookup.icIdentifier == o->internalClass->id) + if (l->protoLookup.protoId == o->internalClass->protoId) return l->protoLookup.data->asReturnedValue(); l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, engine); @@ -426,7 +425,7 @@ ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine) { Heap::Object *o = engine->globalObject->d(); - if (l->protoLookup.icIdentifier == o->internalClass->id) { + if (l->protoLookup.protoId == o->internalClass->protoId) { const Value *getter = l->protoLookup.data; if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); @@ -442,7 +441,7 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value Scope scope(engine); ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); - InternalClass *c = object->internalClass(); + Heap::InternalClass *c = object->internalClass(); uint idx = c->find(name); if (idx != UINT_MAX) { if (object->isArrayObject() && idx == Heap::ArrayObject::LengthPropertyIndex) { @@ -460,7 +459,7 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value return setter(this, engine, *object, value); } - insertionLookup.icIdentifier = c->id; + insertionLookup.protoId = c->protoId; if (!object->put(name, value)) { setter = Lookup::setterFallback; return false; @@ -574,7 +573,7 @@ bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c bool Lookup::setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { Object *o = static_cast<Object *>(object.managed()); - if (o && o->internalClass()->id == l->insertionLookup.icIdentifier) { + if (o && o->internalClass()->protoId == l->insertionLookup.protoId) { o->setInternalClass(l->insertionLookup.newClass); o->d()->setProperty(engine, l->insertionLookup.offset, value); return true; diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 5f507733fd..49eb66d1fb 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct Lookup { - enum { Size = 4 }; union { ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object); ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine); @@ -73,35 +72,43 @@ struct Lookup { }; union { struct { - InternalClass *ic; + Heap::Base *h1; + Heap::Base *h2; + quintptr unused; + quintptr unused2; + } markDef; + struct { + Heap::InternalClass *ic; + quintptr _unused; int offset; } objectLookup; struct { + quintptr protoId; + quintptr _unused; const Value *data; - int icIdentifier; } protoLookup; struct { - InternalClass *ic; - InternalClass *ic2; + Heap::InternalClass *ic; + Heap::InternalClass *ic2; int offset; int offset2; } objectLookupTwoClasses; struct { + quintptr protoId; + quintptr protoId2; const Value *data; const Value *data2; - int icIdentifier; - int icIdentifier2; } protoLookupTwoClasses; struct { // Make sure the next two values are in sync with protoLookup - const Value *data; - int icIdentifier; - unsigned type; + quintptr protoId; Heap::Object *proto; + const Value *data; + quintptr type; } primitiveLookup; struct { - InternalClass *newClass; - int icIdentifier; + Heap::InternalClass *newClass; + quintptr protoId; int offset; } insertionLookup; }; @@ -144,6 +151,17 @@ struct Lookup { static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + + void markObjects(MarkStack *stack) { + if (markDef.h1 && !(reinterpret_cast<quintptr>(markDef.h1) & 1)) + markDef.h1->mark(stack); + if (markDef.h2 && !(reinterpret_cast<quintptr>(markDef.h2) & 1)) + markDef.h2->mark(stack); + } + + void clear() { + memset(&markDef, 0, sizeof(markDef)); + } }; Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value); diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index b50e5f0355..c3def2f949 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -63,11 +63,13 @@ const VTable Managed::static_vtbl = isEqualTo }; +DEFINE_MANAGED_VTABLE(InternalClass); + QString Managed::className() const { const char *s = nullptr; - switch (Type(d()->vtable()->type)) { + switch (Type(vtable()->type)) { case Type_Invalid: case Type_String: return QString(); @@ -114,6 +116,9 @@ QString Managed::className() const case Type_ForeachIteratorObject: s = "__ForeachIterator"; break; + case Type_InternalClass: + s = "__InternalClass"; + break; case Type_RegExp: s = "__RegExp"; break; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 092c61b81c..b35788a711 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -92,14 +92,14 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} QV4::Heap::DataClass *dptr = d_unchecked(); \ dptr->_checkIsInitialized(); \ return dptr; \ - } \ - Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value); + } #define V4_MANAGED(DataClass, superClass) \ private: \ DataClass() Q_DECL_EQ_DELETE; \ Q_DISABLE_COPY(DataClass) \ - V4_MANAGED_ITSELF(DataClass, superClass) + V4_MANAGED_ITSELF(DataClass, superClass) \ + Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value); #define Q_MANAGED_TYPE(type) \ public: \ @@ -154,8 +154,8 @@ const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF #define V4_INTERNALCLASS(c) \ - static QV4::InternalClass *defaultInternalClass(QV4::EngineBase *e) \ - { return e->internalClasses[QV4::EngineBase::Class_##c]; } + static Heap::InternalClass *defaultInternalClass(QV4::EngineBase *e) \ + { return e->internalClasses(QV4::EngineBase::Class_##c); } struct Q_QML_PRIVATE_EXPORT Managed : Value { @@ -193,6 +193,7 @@ public: Type_MathObject, Type_ExecutionContext, + Type_InternalClass, Type_ForeachIteratorObject, Type_RegExp, @@ -200,18 +201,19 @@ public: }; Q_MANAGED_TYPE(Invalid) - InternalClass *internalClass() const { return d()->internalClass; } + Heap::InternalClass *internalClass() const { return d()->internalClass; } + const VTable *vtable() const { return d()->internalClass->vtable; } inline ExecutionEngine *engine() const { return internalClass()->engine; } - bool isListType() const { return d()->vtable()->type == Type_QmlSequence; } + bool isListType() const { return d()->internalClass->vtable->type == Type_QmlSequence; } - bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; } - bool isStringObject() const { return d()->vtable()->type == Type_StringObject; } + bool isArrayObject() const { return d()->internalClass->vtable->type == Type_ArrayObject; } + bool isStringObject() const { return d()->internalClass->vtable->type == Type_StringObject; } QString className() const; bool isEqualTo(const Managed *other) const - { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); } + { return d()->internalClass->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); } static bool isEqualTo(Managed *m, Managed *other); @@ -254,6 +256,32 @@ inline const Object *Value::as() const { return objectValue(); } + +struct InternalClass : Managed +{ + V4_MANAGED_ITSELF(InternalClass, Managed) + Q_MANAGED_TYPE(InternalClass) + V4_INTERNALCLASS(Empty) + V4_NEEDS_DESTROY + + Q_REQUIRED_RESULT Heap::InternalClass *changeVTable(const VTable *vt) { + return d()->changeVTable(vt); + } + Q_REQUIRED_RESULT Heap::InternalClass *changePrototype(Heap::Object *proto) { + return d()->changePrototype(proto); + } + Q_REQUIRED_RESULT Heap::InternalClass *addMember(QV4::String *string, PropertyAttributes data, uint *index = 0) { + return d()->addMember(string, data, index); + } + Q_REQUIRED_RESULT Heap::InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = 0) { + return d()->addMember(identifier, data, index); + } + + void operator =(Heap::InternalClass *ic) { + Value::operator=(ic); + } +}; + } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index bcbe475c2c..170ad9f556 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -57,9 +57,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(Object); -void Object::setInternalClass(InternalClass *ic) +void Object::setInternalClass(Heap::InternalClass *ic) { - d()->internalClass = ic; + d()->internalClass.set(engine(), ic); if (ic->isUsedAsProto) ic->updateProtoUsage(d()); Q_ASSERT(ic && ic->vtable); @@ -89,7 +89,7 @@ void Object::setProperty(uint index, const Property *p) void Heap::Object::setUsedAsProto() { - internalClass = internalClass->asProtoClass(); + internalClass.set(internalClass->engine, internalClass->asProtoClass()); } bool Object::setPrototype(Object *proto) @@ -121,7 +121,7 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property bool Object::putValue(uint memberIndex, const Value &value) { - QV4::InternalClass *ic = internalClass(); + Heap::InternalClass *ic = internalClass(); if (ic->engine->hasException) return false; @@ -228,6 +228,7 @@ void Object::defineReadonlyConfigurableProperty(String *name, const Value &value void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack) { + Base::markObjects(b, stack); Object *o = static_cast<Object *>(b); if (o->memberData) o->memberData->mark(stack); @@ -248,7 +249,7 @@ void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack) void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes) { uint idx; - InternalClass::addMember(this, s, attributes, &idx); + Heap::InternalClass::addMember(this, s, attributes, &idx); if (attributes.isAccessor()) { setProperty(idx + GetterOffset, p->value); @@ -776,7 +777,7 @@ bool Object::internalDeleteProperty(String *name) uint memberIdx = internalClass()->find(name->identifier()); if (memberIdx != UINT_MAX) { if (internalClass()->propertyData[memberIdx].isConfigurable()) { - InternalClass::removeMember(this, name->identifier()); + Heap::InternalClass::removeMember(this, name->identifier()); return true; } return false; @@ -832,7 +833,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const } if (attrs.hasWritable() && !attrs.isWritable()) { cattrs.setWritable(false); - InternalClass::changeMember(this, engine->id_length(), cattrs); + Heap::InternalClass::changeMember(this, engine->id_length(), cattrs); } if (!succeeded) return false; @@ -980,7 +981,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String * current->merge(cattrs, p, attrs); if (member) { - InternalClass::changeMember(this, member, cattrs); + Heap::InternalClass::changeMember(this, member, cattrs); setProperty(index, current); } else { setArrayAttributes(index, cattrs); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 1731ae3c76..79ffef47ba 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -74,6 +74,10 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) { static void markObjects(Heap::Base *base, MarkStack *stack); void init() { Base::init(); } + const VTable *vtable() const { + return internalClass->vtable; + } + const Value *inlinePropertyDataWithOffset(uint indexWithOffset) const { Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < vtable()->inlinePropertyOffset + vtable()->nInlineProperties); return reinterpret_cast<const Value *>(this) + indexWithOffset; @@ -218,7 +222,7 @@ struct Q_QML_EXPORT Object: Managed { SetterOffset = 1 }; - void setInternalClass(InternalClass *ic); + void setInternalClass(Heap::InternalClass *ic); const Value *propertyData(uint index) const { return d()->propertyData(index); } @@ -551,7 +555,7 @@ inline void Object::arraySet(uint index, const Value &value) template<> inline const ArrayObject *Value::as() const { - return isManaged() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : nullptr; + return isManaged() && m()->internalClass->vtable->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : nullptr; } #ifndef V4_BOOTSTRAP diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index 5fd200efc1..b337243204 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -78,7 +78,7 @@ Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine( void Profiler::stopProfiling() { featuresEnabled = 0; - reportData(true); + reportData(); m_sentLocations.clear(); } @@ -89,7 +89,7 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2) (call1.m_end == call2.m_end && call1.m_function < call2.m_function))); } -void Profiler::reportData(bool trackLocations) +void Profiler::reportData() { std::sort(m_data.begin(), m_data.end()); QVector<FunctionCallProperties> properties; @@ -100,12 +100,11 @@ void Profiler::reportData(bool trackLocations) properties.append(call.properties()); Function *function = call.function(); SentMarker &marker = m_sentLocations[reinterpret_cast<quintptr>(function)]; - if (!trackLocations || !marker.isValid()) { + if (!marker.isValid()) { FunctionLocation &location = locations[properties.constLast().id]; if (!location.isValid()) location = call.resolveLocation(); - if (trackLocations) - marker.setFunction(function); + marker.setFunction(function); } } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index e8c154e4e7..8461384e9a 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -251,7 +251,7 @@ public: void stopProfiling(); void startProfiling(quint64 features); - void reportData(bool trackLocations); + void reportData(); void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 040f060476..1de5720d03 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -312,7 +312,7 @@ Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, cons context->isInternal = true; context->isJSContext = true; - Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)nullptr)); + Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, (QObject*)nullptr)); qml->d()->isNullWrapper = true; qml->setReadOnly(false); @@ -330,7 +330,7 @@ Heap::QmlContext *QmlContext::create(ExecutionContext *parent, QQmlContextData * { Scope scope(parent); - Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, scopeObject)); + Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, scopeObject)); Heap::QmlContext *c = scope.engine->memoryManager->alloc<QmlContext>(parent, qml); Q_ASSERT(c->vtable() == staticVTable()); return c; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 816c259b9b..157de0e96e 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -56,7 +56,11 @@ #include <private/qv4functionobject_p.h> #include <private/qv4runtime_p.h> #include <private/qv4variantobject_p.h> + +#if QT_CONFIG(qml_sequence_object) #include <private/qv4sequenceobject_p.h> +#endif + #include <private/qv4objectproto_p.h> #include <private/qv4jsonobject_p.h> #include <private/qv4regexpobject_p.h> @@ -181,11 +185,13 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType())) return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, property.propType()); } else { +#if QT_CONFIG(qml_sequence_object) // see if it's a sequence type bool succeeded = false; QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType(), object, property.coreIndex(), &succeeded)); if (succeeded) return retn->asReturnedValue(); +#endif } if (property.propType() == QMetaType::UnknownType) { @@ -242,7 +248,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje return QV4::QObjectMethod::create(global, object, property->coreIndex()); } else if (property->isSignalHandler()) { QmlSignalHandler::initProto(engine); - return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue(); + return engine->memoryManager->allocate<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue(); } else { ExecutionContext *global = engine->rootContext(); return QV4::QObjectMethod::create(global, object, property->coreIndex()); @@ -684,7 +690,7 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) return result; } } - return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue(); + return (engine->memoryManager->allocate<QV4::QObjectWrapper>(object))->asReturnedValue(); } QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty) @@ -1619,6 +1625,7 @@ void CallArgument::initAsType(int callType) } } +#if QT_CONFIG(qml_sequence_object) template <class T, class M> void CallArgument::fromContainerValue(const QV4::Object *object, int callType, M CallArgument::*member, bool &queryEngine) { @@ -1631,6 +1638,7 @@ void CallArgument::fromContainerValue(const QV4::Object *object, int callType, M } } } +#endif void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const QV4::Value &value) { @@ -1713,6 +1721,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q type = callType; } else if (callType == QMetaType::Void) { *qvariantPtr = QVariant(); +#if QT_CONFIG(qml_sequence_object) } else if (callType == qMetaTypeId<std::vector<int>>() || callType == qMetaTypeId<std::vector<qreal>>() || callType == qMetaTypeId<std::vector<bool>>() @@ -1740,6 +1749,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q stdVectorQModelIndexPtr = nullptr; fromContainerValue<std::vector<QModelIndex>>(object, callType, &CallArgument::stdVectorQModelIndexPtr, queryEngine); } +#endif } else { queryEngine = true; } @@ -1833,7 +1843,7 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine) ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index) { Scope valueScope(scope); - Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope)); + Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocate<QObjectMethod>(scope)); method->d()->setObject(object); if (QQmlData *ddata = QQmlData::get(object)) @@ -1846,7 +1856,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index) { Scope valueScope(scope); - Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope)); + Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocate<QObjectMethod>(scope)); method->d()->setPropertyCache(valueType->d()->propertyCache()); method->d()->index = index; method->d()->valueTypeWrapper.set(valueScope.engine, valueType->d()); @@ -2019,7 +2029,7 @@ void Heap::QMetaObjectWrapper::ensureConstructorsCache() { ReturnedValue QMetaObjectWrapper::create(ExecutionEngine *engine, const QMetaObject* metaObject) { QV4::Scope scope(engine); - Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocObject<QV4::QMetaObjectWrapper>(metaObject)->asReturnedValue()); + Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocate<QV4::QMetaObjectWrapper>(metaObject)->asReturnedValue()); mo->init(engine); return mo->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 000e2c3a7e..0b1979dfcc 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -45,10 +45,6 @@ #include "qv4scopedvalue_p.h" #include "qv4jscall_p.h" -#include <private/qqmljsengine_p.h> -#include <private/qqmljslexer_p.h> -#include <private/qqmljsparser_p.h> -#include <private/qqmljsast_p.h> #include "private/qlocale_tools_p.h" #include <QtCore/QDebug> @@ -387,7 +383,7 @@ ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value } // fill in result data - ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses[EngineBase::Class_RegExpExecArray], scope.engine->arrayPrototype())); + ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses(EngineBase::Class_RegExpExecArray))); int len = r->value()->captureCount(); array->arrayReserve(len); ScopedValue v(scope); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 0211ad1011..b14395b507 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -617,7 +617,7 @@ ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value & uint idx = 0; if (index.asArrayIndex(idx)) { if (Heap::Base *b = object.heapObject()) { - if (b->vtable()->isObject) { + if (b->internalClass->vtable->isObject) { Heap::Object *o = static_cast<Heap::Object *>(b); if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>(); @@ -661,7 +661,7 @@ bool Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, uint idx = 0; if (index.asArrayIndex(idx)) { if (Heap::Base *b = object.heapObject()) { - if (b->vtable()->isObject) { + if (b->internalClass->vtable->isObject) { Heap::Object *o = static_cast<Heap::Object *>(b); if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>(); @@ -1217,8 +1217,8 @@ ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *value ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) { Scope scope(engine); - QV4::InternalClass *klass = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeClasses[classId]; - ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype())); + Scoped<InternalClass> klass(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]); + ScopedObject o(scope, engine->newObject(klass->d())); { bool needSparseArray = arrayGetterSetterCountAndFlags >> 30; @@ -1226,7 +1226,7 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4:: o->initSparseArray(); } - for (uint i = 0; i < klass->size; ++i) + for (uint i = 0; i < klass->d()->size; ++i) o->setProperty(i, *args++); if (arrayValueCount > 0) { @@ -1259,16 +1259,26 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4:: QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine) { Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext); - QV4::InternalClass *ic = engine->internalClasses[EngineBase::Class_ArgumentsObject]; - return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), engine->currentStackFrame)->asReturnedValue(); + Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_ArgumentsObject); + return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue(); } QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine *engine) { - QV4::InternalClass *ic = engine->internalClasses[EngineBase::Class_StrictArgumentsObject]; - return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->objectPrototype(), engine->currentStackFrame)->asReturnedValue(); + Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_StrictArgumentsObject); + return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue(); } +QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, int argIndex) +{ + const Value *values = engine->currentStackFrame->originalArguments + argIndex; + int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex; + if (nValues <= 0) + return engine->newArrayObject(0)->asReturnedValue(); + return engine->newArrayObject(values, nValues)->asReturnedValue(); +} + + ReturnedValue Runtime::method_loadQmlContext(NoThrowEngine *engine) { Heap::QmlContext *ctx = engine->qmlContext(); diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 91232256a9..9bdb41b19e 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -134,6 +134,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { F(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)) \ F(ReturnedValue, createMappedArgumentsObject, (ExecutionEngine *engine)) \ F(ReturnedValue, createUnmappedArgumentsObject, (ExecutionEngine *engine)) \ + F(ReturnedValue, createRestParameter, (ExecutionEngine *engine, int argIndex)) \ \ /* literals */ \ F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \ diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp index fe18ddf9ed..93ca666c53 100644 --- a/src/qml/jsruntime/qv4runtimecodegen.cpp +++ b/src/qml/jsruntime/qv4runtimecodegen.cpp @@ -58,7 +58,10 @@ void RuntimeCodegen::generateFromFunctionExpression(const QString &fileName, scan(ast); scan.leaveEnvironment(); - int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : nullptr); + if (hasError) + return; + + int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body); _module->rootContext = _module->functions.at(index); } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 7d29d0b517..c0dce2df0d 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -691,7 +691,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId) #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(object, propertyIndex)); \ + QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QQml##ElementTypeName##List>(object, propertyIndex)); \ return obj.asReturnedValue(); \ } else @@ -709,7 +709,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s #define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(v.value<SequenceType >())); \ + QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QQml##ElementTypeName##List>(v.value<SequenceType >())); \ return obj.asReturnedValue(); \ } else diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index e9bef2f604..eab1ffb5d7 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -59,6 +59,8 @@ #include "qv4context_p.h" #include "qv4string_p.h" +QT_REQUIRE_CONFIG(qml_sequence_object); + QT_BEGIN_NAMESPACE namespace QV4 { diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index 14def49d0a..31b51cbfe3 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -40,13 +40,17 @@ #include "qv4serialize_p.h" #include <private/qv8engine_p.h> +#if QT_CONFIG(qml_list_model) #include <private/qqmllistmodel_p.h> #include <private/qqmllistmodelworkeragent_p.h> +#endif #include <private/qv4value_p.h> #include <private/qv4dateobject_p.h> #include <private/qv4regexpobject_p.h> +#if QT_CONFIG(qml_sequence_object) #include <private/qv4sequenceobject_p.h> +#endif #include <private/qv4objectproto_p.h> #include <private/qv4qobjectwrapper_p.h> @@ -82,8 +86,12 @@ enum Type { WorkerNumber, WorkerDate, WorkerRegexp, +#if QT_CONFIG(qml_list_model) WorkerListModel, +#endif +#if QT_CONFIG(qml_sequence_object) WorkerSequence +#endif }; static inline quint32 valueheader(Type type, quint32 size = 0) @@ -228,6 +236,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) { // XXX TODO: Generalize passing objects between the main thread and worker scripts so // that others can trivially plug in their elements. +#if QT_CONFIG(qml_list_model) QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object()); if (lm && lm->agent()) { QQmlListModelWorkerAgent *agent = lm->agent(); @@ -236,9 +245,13 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine push(data, (void *)agent); return; } +#else + Q_UNUSED(qobjectWrapper); +#endif // No other QObject's are allowed to be sent push(data, valueheader(WorkerUndefined)); } else if (const Object *o = v.as<Object>()) { +#if QT_CONFIG(qml_sequence_object) if (o->isListType()) { // valid sequence. we generate a length (sequence length + 1 for the sequence type) uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32(); @@ -256,6 +269,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine return; } +#endif // regular object QV4::ScopedValue val(scope, v); @@ -353,6 +367,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) data += ALIGN(length * sizeof(quint16)); return Encode(engine->newRegExpObject(pattern, flags)); } +#if QT_CONFIG(qml_list_model) case WorkerListModel: { void *ptr = popPtr(data); @@ -369,6 +384,8 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) agent->setEngine(engine); return rv->asReturnedValue(); } +#endif +#if QT_CONFIG(qml_sequence_object) case WorkerSequence: { ScopedValue value(scope); @@ -387,6 +404,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded); return QV4::SequencePrototype::fromVariant(engine, seqVariant, &succeeded); } +#endif } Q_ASSERT(!"Unreachable"); return QV4::Encode::undefined(); diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 447992ebec..57832a0068 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -54,6 +54,7 @@ using namespace QV4; void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack) { + Base::markObjects(that, markStack); String *s = static_cast<String *>(that); if (s->subtype < StringType_Complex) return; @@ -76,7 +77,7 @@ bool String::isEqualTo(Managed *t, Managed *o) if (t == o) return true; - if (!o->d()->vtable()->isString) + if (!o->vtable()->isString) return false; return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o)); diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 5466cc274d..72c4057b20 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -76,6 +76,10 @@ struct Q_QML_PRIVATE_EXPORT String : Base { }; #ifndef V4_BOOTSTRAP + const VTable *vtable() const { + return internalClass->vtable; + } + void init(const QString &text); void destroy(); void simplifyString() const; @@ -282,7 +286,7 @@ struct ComplexString : String { template<> inline const String *Value::as() const { - return isManaged() && m()->vtable()->isString ? static_cast<const String *>(this) : nullptr; + return isManaged() && m()->internalClass->vtable->isString ? static_cast<const String *>(this) : nullptr; } template<> diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index ea1532b8ce..ea931abd1c 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -351,9 +351,9 @@ void Heap::TypedArray::init(Type t) Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t) { - QV4::InternalClass *ic = e->internalClasses[EngineBase::Class_Empty]->changeVTable(staticVTable()); - ic = ic->changePrototype(e->typedArrayPrototype[t].d()); - return e->memoryManager->allocObject<TypedArray>(ic, e->typedArrayPrototype + t, t); + Scope scope(e); + Scoped<InternalClass> ic(scope, e->newInternalClass(staticVTable(), e->typedArrayPrototype + t)); + return e->memoryManager->allocObject<TypedArray>(ic->d(), t); } ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty) diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index 0d4711df3c..c558c27521 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -84,7 +84,7 @@ bool Value::toBooleanImpl(Value val) #ifdef V4_BOOTSTRAP Q_UNIMPLEMENTED(); #else - if (b->vtable()->isString) + if (b->internalClass->vtable->isString) return static_cast<Heap::String *>(b)->length() > 0; #endif return true; diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index a5ee6b5373..42c0370138 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -56,6 +56,7 @@ #include <QtCore/QString> #include "qv4global_p.h" #include <private/qv4heap_p.h> +#include <private/qv4internalclass_p.h> #include <private/qnumeric_p.h> @@ -428,11 +429,11 @@ public: if (!isManaged()) return nullptr; - Q_ASSERT(m()->vtable()); + Q_ASSERT(m()->internalClass->vtable); #if !defined(QT_NO_QOBJECT_CHECK) static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this)); #endif - const VTable *vt = m()->vtable(); + const VTable *vt = m()->internalClass->vtable; while (vt) { if (vt == T::staticVTable()) return static_cast<const T *>(this); @@ -500,18 +501,18 @@ inline void Value::mark(MarkStack *markStack) inline bool Value::isString() const { Heap::Base *b = heapObject(); - return b && b->vtable()->isString; + return b && b->internalClass->vtable->isString; } inline bool Value::isObject() const { Heap::Base *b = heapObject(); - return b && b->vtable()->isObject; + return b && b->internalClass->vtable->isObject; } inline bool Value::isFunctionObject() const { Heap::Base *b = heapObject(); - return b && b->vtable()->isFunctionObject; + return b && b->internalClass->vtable->isFunctionObject; } inline bool Value::isPrimitive() const diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index e73365e9b1..fae917dbb5 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -397,13 +397,13 @@ static bool compareEqual(Value lhs, Value rhs) Heap::Base *r = rhs.m(); Q_ASSERT(l); Q_ASSERT(r); - if (l->vtable()->isString == r->vtable()->isString) + if (l->internalClass->vtable->isString == r->internalClass->vtable->isString) return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs)); - if (l->vtable()->isString) { + if (l->internalClass->vtable->isString) { rhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT)); break; } else { - Q_ASSERT(r->vtable()->isString); + Q_ASSERT(r->internalClass->vtable->isString); lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); break; } @@ -418,7 +418,7 @@ static bool compareEqual(Value lhs, Value rhs) rhs = Primitive::fromDouble(rhs.int_32()); // fall through default: // double - if (lhs.m()->vtable()->isString) + if (lhs.m()->internalClass->vtable->isString) return RuntimeHelpers::toNumber(lhs) == rhs.doubleValue(); else lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); @@ -462,7 +462,7 @@ static bool compareEqualInt(Value &accumulator, Value lhs, int rhs) case Value::QT_ManagedOrUndefined2: case Value::QT_ManagedOrUndefined3: // LHS: Managed - if (lhs.m()->vtable()->isString) + if (lhs.m()->internalClass->vtable->isString) return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs; accumulator = lhs; lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT)); @@ -981,6 +981,10 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, acc = Runtime::method_createUnmappedArgumentsObject(engine); MOTH_END_INSTR(CreateUnmappedArgumentsObject) + MOTH_BEGIN_INSTR(CreateRestParameter) + acc = Runtime::method_createRestParameter(engine, argIndex); + MOTH_END_INSTR(CreateRestParameter) + MOTH_BEGIN_INSTR(ConvertThisToObject) Value *t = &stack[CallData::This]; if (!t->isObject()) { @@ -1023,6 +1027,11 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, } MOTH_END_INSTR(JumpFalse) + MOTH_BEGIN_INSTR(JumpNotUndefined) + if (Q_LIKELY(acc != QV4::Encode::undefined())) + code += offset; + MOTH_END_INSTR(JumpNotUndefined) + MOTH_BEGIN_INSTR(CmpEqNull) acc = Encode(ACC.isNullOrUndefined()); MOTH_END_INSTR(CmpEqNull) diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index 53933cd090..f327388355 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -54,7 +54,6 @@ #include <private/qv4global_p.h> #include <private/qv4mmdefs_p.h> #include <private/qv4writebarrier_p.h> -#include <private/qv4internalclass_p.h> #include <QSharedPointer> // To check if Heap::Base::init is called (meaning, all subclasses did their init and called their @@ -65,8 +64,6 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct InternalClass; - struct VTable { const VTable * const parent; @@ -88,17 +85,41 @@ struct VTable namespace Heap { +template <typename T, size_t o> +struct Pointer { + static Q_CONSTEXPR size_t offset = o; + T operator->() const { return get(); } + operator T () const { return get(); } + + Base *base(); + + void set(EngineBase *e, T newVal) { + WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Base *>(newVal)); + } + + T get() const { return reinterpret_cast<T>(ptr); } + + template <typename Type> + Type *cast() { return static_cast<Type *>(ptr); } + + Base *heapObject() const { return ptr; } + +private: + Base *ptr; +}; +typedef Pointer<char *, 0> V4PointerCheck; +Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value); + struct Q_QML_EXPORT Base { void *operator new(size_t) = delete; - static void markObjects(Heap::Base *, MarkStack *) {} + static void markObjects(Base *, MarkStack *); - InternalClass *internalClass; + Pointer<InternalClass *, 0> internalClass; inline ReturnedValue asReturnedValue() const; inline void mark(QV4::MarkStack *markStack); - const VTable *vtable() const { return internalClass->vtable; } inline bool isMarked() const { const HeapItem *h = reinterpret_cast<const HeapItem *>(this); Chunk *c = h->chunk(); @@ -125,13 +146,9 @@ struct Q_QML_EXPORT Base { return Chunk::testBit(c->objectBitmap, h - c->realBase()); } - inline void markChildren(MarkStack *markStack) { - vtable()->markObjects(this, markStack); - } - void *operator new(size_t, Managed *m) { return m; } - void *operator new(size_t, Heap::Base *m) { return m; } - void operator delete(void *, Heap::Base *) {} + void *operator new(size_t, Base *m) { return m; } + void operator delete(void *, Base *) {} void init() { _setInitialized(); } void destroy() { _setDestroyed(); } @@ -178,10 +195,8 @@ Q_STATIC_ASSERT(std::is_standard_layout<Base>::value); Q_STATIC_ASSERT(offsetof(Base, internalClass) == 0); Q_STATIC_ASSERT(sizeof(Base) == QT_POINTER_SIZE); -} - inline -void Heap::Base::mark(QV4::MarkStack *markStack) +void Base::mark(QV4::MarkStack *markStack) { Q_ASSERT(inUse()); const HeapItem *h = reinterpret_cast<const HeapItem *>(this); @@ -196,36 +211,12 @@ void Heap::Base::mark(QV4::MarkStack *markStack) } } -namespace Heap { - -template <typename T, size_t o> -struct Pointer { - static Q_CONSTEXPR size_t offset = o; - T operator->() const { return get(); } - operator T () const { return get(); } - - Heap::Base *base() { - Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base)); - Q_ASSERT(base->inUse()); - return base; - } - - void set(EngineBase *e, T newVal) { - WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal)); - } - - T get() const { return reinterpret_cast<T>(ptr); } - - template <typename Type> - Type *cast() { return static_cast<Type *>(ptr); } - - Heap::Base *heapObject() const { return ptr; } - -private: - Heap::Base *ptr; -}; -typedef Pointer<char *, 0> V4PointerCheck; -Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value); +template<typename T, size_t o> +Base *Pointer<T, o>::base() { + Base *base = reinterpret_cast<Base *>(this) - (offset/sizeof(Base *)); + Q_ASSERT(base->inUse()); + return base; +} } diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 4e83abebdf..06313c3d30 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -335,7 +335,7 @@ bool Chunk::sweep(ExecutionEngine *engine) HeapItem *itemToFree = o + index; Heap::Base *b = *itemToFree; - const VTable *v = b->vtable(); + const VTable *v = b->internalClass->vtable; // if (Q_UNLIKELY(classCountPtr)) // classCountPtr(v->className); if (v->destroy) { @@ -389,8 +389,8 @@ void Chunk::freeAll(ExecutionEngine *engine) HeapItem *itemToFree = o + index; Heap::Base *b = *itemToFree; - if (b->vtable()->destroy) { - b->vtable()->destroy(b); + if (b->internalClass->vtable->destroy) { + b->internalClass->vtable->destroy(b); b->_checkIsDestroyed(); } #ifdef V4_USE_HEAPTRACK @@ -643,8 +643,9 @@ void BlockAllocator::sweep() void BlockAllocator::freeAll() { - for (auto c : chunks) { + for (auto c : chunks) c->freeAll(engine); + for (auto c : chunks) { Q_V4_PROFILE_DEALLOC(engine, Chunk::DataSize, Profiling::HeapPage); chunkAllocator->free(c); } @@ -691,7 +692,7 @@ static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocato { HeapItem *itemToFree = c.chunk->first(); Heap::Base *b = *itemToFree; - const VTable *v = b->vtable(); + const VTable *v = b->internalClass->vtable; if (Q_UNLIKELY(classCountPtr)) classCountPtr(v->className); @@ -758,6 +759,7 @@ MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) , chunkAllocator(new ChunkAllocator) , blockAllocator(chunkAllocator, engine) + , icAllocator(chunkAllocator, engine) , hugeItemAllocator(chunkAllocator, engine) , m_persistentValues(new PersistentValueStorage(engine)) , m_weakValues(new PersistentValueStorage(engine)) @@ -884,7 +886,7 @@ Heap::Object *MemoryManager::allocObjectWithMemberData(const QV4::VTable *vtable Chunk::clearBit(c->extendsBitmap, index); } o->memberData.set(engine, m); - m->internalClass = engine->internalClasses[EngineBase::Class_MemberData]; + m->internalClass.set(engine, engine->internalClasses(EngineBase::Class_MemberData)); Q_ASSERT(o->memberData->internalClass); m->values.alloc = static_cast<uint>((memberSize - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value)); m->values.size = o->memberData->values.alloc; @@ -911,7 +913,7 @@ void MarkStack::drain() Heap::Base *h = pop(); ++markStackSize; Q_ASSERT(h); // at this point we should only have Heap::Base objects in this area on the stack. If not, weird things might happen. - h->markChildren(this); + h->internalClass->vtable->markObjects(h, this); } } @@ -1017,8 +1019,11 @@ void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPt } } - blockAllocator.sweep(); - hugeItemAllocator.sweep(classCountPtr); + if (!lastSweep) { + blockAllocator.sweep(/*classCountPtr*/); + hugeItemAllocator.sweep(classCountPtr); + icAllocator.sweep(/*classCountPtr*/); + } } bool MemoryManager::shouldRunGC() const @@ -1167,6 +1172,7 @@ void MemoryManager::runGC() // reset all black bits blockAllocator.resetBlackBits(); hugeItemAllocator.resetBlackBits(); + icAllocator.resetBlackBits(); } size_t MemoryManager::getUsedMem() const @@ -1193,6 +1199,7 @@ MemoryManager::~MemoryManager() sweep(/*lastSweep*/true); blockAllocator.freeAll(); hugeItemAllocator.freeAll(); + icAllocator.freeAll(); delete m_weakValues; #ifdef V4_USE_VALGRIND diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 40670bcdc7..d61655c38a 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -160,224 +160,98 @@ public: { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); } template<typename ManagedType> - inline typename ManagedType::Data *allocManaged(std::size_t size) + inline typename ManagedType::Data *allocManaged(std::size_t size, Heap::InternalClass *ic) { Q_STATIC_ASSERT(std::is_trivial< typename ManagedType::Data >::value); size = align(size); - Heap::Base *o = allocData(size); - InternalClass *ic = ManagedType::defaultInternalClass(engine); - ic = ic->changeVTable(ManagedType::staticVTable()); - o->internalClass = ic; - Q_ASSERT(o->internalClass && o->internalClass->vtable); - return static_cast<typename ManagedType::Data *>(o); + typename ManagedType::Data *d = static_cast<typename ManagedType::Data *>(allocData(size)); + d->internalClass.set(engine, ic); + Q_ASSERT(d->internalClass && d->internalClass->vtable); + Q_ASSERT(ic->vtable == ManagedType::staticVTable()); + return d; } template<typename ManagedType> inline typename ManagedType::Data *allocManaged(std::size_t size, InternalClass *ic) { - Q_STATIC_ASSERT(std::is_trivial< typename ManagedType::Data >::value); - size = align(size); - Heap::Base *o = allocData(size); - o->internalClass = ic; - Q_ASSERT(o->internalClass && o->internalClass->vtable); - Q_ASSERT(ic->vtable == ManagedType::staticVTable()); - return static_cast<typename ManagedType::Data *>(o); + return allocManaged<ManagedType>(size, ic->d()); + } + + template<typename ManagedType> + inline typename ManagedType::Data *allocManaged(std::size_t size) + { + Scope scope(engine); + Scoped<InternalClass> ic(scope, ManagedType::defaultInternalClass(engine)); + return allocManaged<ManagedType>(size, ic); } template <typename ObjectType> - typename ObjectType::Data *allocateObject(InternalClass *ic) + typename ObjectType::Data *allocateObject(Heap::InternalClass *ic) { Heap::Object *o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->size); - o->internalClass = ic; - Q_ASSERT(o->internalClass && o->internalClass->vtable); - Q_ASSERT(ic->vtable == ObjectType::staticVTable()); + o->internalClass.set(engine, ic); + Q_ASSERT(o->internalClass.get() && o->vtable()); + Q_ASSERT(o->vtable() == ObjectType::staticVTable()); return static_cast<typename ObjectType::Data *>(o); } template <typename ObjectType> + typename ObjectType::Data *allocateObject(InternalClass *ic) + { + return allocateObject<ObjectType>(ic->d()); + } + + template <typename ObjectType> typename ObjectType::Data *allocateObject() { - InternalClass *ic = ObjectType::defaultInternalClass(engine); + Scope scope(engine); + Scoped<InternalClass> ic(scope, ObjectType::defaultInternalClass(engine)); ic = ic->changeVTable(ObjectType::staticVTable()); ic = ic->changePrototype(ObjectType::defaultPrototype(engine)->d()); - Heap::Object *o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->size); - o->internalClass = ic; - Q_ASSERT(o->internalClass && o->internalClass->vtable); - Q_ASSERT(o->internalClass->prototype == ObjectType::defaultPrototype(engine)->d()); - return static_cast<typename ObjectType::Data *>(o); + return allocateObject<ObjectType>(ic); } template <typename ManagedType, typename Arg1> typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) { typename ManagedType::Data *o = reinterpret_cast<typename ManagedType::Data *>(allocString(unmanagedSize)); - o->internalClass = ManagedType::defaultInternalClass(engine); + o->internalClass.set(engine, ManagedType::defaultInternalClass(engine)); Q_ASSERT(o->internalClass && o->internalClass->vtable); o->init(arg1); return o; } - template <typename ObjectType> - typename ObjectType::Data *allocObject(InternalClass *ic) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - t->d_unchecked()->init(); - return t->d(); - } - - template <typename ObjectType> - typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr)); - Q_UNUSED(prototype); - t->d_unchecked()->init(); - return t->d(); - } - - template <typename ObjectType, typename Arg1> - typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr)); - Q_UNUSED(prototype); - t->d_unchecked()->init(arg1); - return t->d(); - } - - template <typename ObjectType, typename Arg1, typename Arg2> - typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr)); - Q_UNUSED(prototype); - t->d_unchecked()->init(arg1, arg2); - return t->d(); - } - - template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3> - typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3) + template <typename ObjectType, typename... Args> + typename ObjectType::Data *allocObject(Heap::InternalClass *ic, Args... args) { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr)); - Q_UNUSED(prototype); - t->d_unchecked()->init(arg1, arg2, arg3); - return t->d(); + typename ObjectType::Data *d = allocateObject<ObjectType>(ic); + d->init(args...); + return d; } - template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> - typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + template <typename ObjectType, typename... Args> + typename ObjectType::Data *allocObject(InternalClass *ic, Args... args) { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - Q_ASSERT(t->internalClass()->prototype == (prototype ? prototype->d() : nullptr)); - Q_UNUSED(prototype); - t->d_unchecked()->init(arg1, arg2, arg3, arg4); - return t->d(); + typename ObjectType::Data *d = allocateObject<ObjectType>(ic); + d->init(args...); + return d; } - template <typename ObjectType> - typename ObjectType::Data *allocObject() + template <typename ObjectType, typename... Args> + typename ObjectType::Data *allocate(Args... args) { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - t->d_unchecked()->init(); + t->d_unchecked()->init(args...); return t->d(); } - template <typename ObjectType, typename Arg1> - typename ObjectType::Data *allocObject(Arg1 arg1) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - t->d_unchecked()->init(arg1); - return t->d(); - } - - template <typename ObjectType, typename Arg1, typename Arg2> - typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - t->d_unchecked()->init(arg1, arg2); - return t->d(); - } - - template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3> - typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - t->d_unchecked()->init(arg1, arg2, arg3); - return t->d(); - } - - template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> - typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) - { - Scope scope(engine); - Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - t->d_unchecked()->init(arg1, arg2, arg3, arg4); - return t->d(); - } - - - template <typename ManagedType> - typename ManagedType::Data *alloc() - { - Scope scope(engine); - Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - t->d_unchecked()->init(); - return t->d(); - } - - template <typename ManagedType, typename Arg1> - typename ManagedType::Data *alloc(Arg1 arg1) + template <typename ManagedType, typename... Args> + typename ManagedType::Data *alloc(Args... args) { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - t->d_unchecked()->init(arg1); - return t->d(); - } - - template <typename ManagedType, typename Arg1, typename Arg2> - typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2) - { - Scope scope(engine); - Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - t->d_unchecked()->init(arg1, arg2); - return t->d(); - } - - template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3> - typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { - Scope scope(engine); - Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - t->d_unchecked()->init(arg1, arg2, arg3); - return t->d(); - } - - template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> - typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) - { - Scope scope(engine); - Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - t->d_unchecked()->init(arg1, arg2, arg3, arg4); - return t->d(); - } - - template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> - typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) - { - Scope scope(engine); - Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5); + t->d_unchecked()->init(args...); return t->d(); } @@ -392,6 +266,14 @@ public: // called when a JS object grows itself. Specifically: Heap::String::append void changeUnmanagedHeapSizeUsage(qptrdiff delta) { unmanagedHeapSize += delta; } + template<typename ManagedType> + typename ManagedType::Data *allocIC() + { + size_t size = align(sizeof(typename ManagedType::Data)); + Heap::Base *b = *icAllocator.allocate(size, true); + return static_cast<typename ManagedType::Data *>(b); + } + protected: /// expects size to be aligned Heap::Base *allocString(std::size_t unmanagedSize); @@ -409,6 +291,7 @@ public: QV4::ExecutionEngine *engine; ChunkAllocator *chunkAllocator; BlockAllocator blockAllocator; + BlockAllocator icAllocator; HugeItemAllocator hugeItemAllocator; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; diff --git a/src/qml/parser/parser.pri b/src/qml/parser/parser.pri index e5b8ae2749..dcdde4f81c 100644 --- a/src/qml/parser/parser.pri +++ b/src/qml/parser/parser.pri @@ -3,20 +3,22 @@ HEADERS += \ $$PWD/qqmljsastfwd_p.h \ $$PWD/qqmljsastvisitor_p.h \ $$PWD/qqmljsengine_p.h \ - $$PWD/qqmljsgrammar_p.h \ $$PWD/qqmljslexer_p.h \ $$PWD/qqmljsmemorypool_p.h \ - $$PWD/qqmljsparser_p.h \ $$PWD/qqmljsglobal_p.h \ $$PWD/qqmljskeywords_p.h \ + $$PWD/qqmljsengine_p.h \ + $$PWD/qqmljsglobal_p.h SOURCES += \ $$PWD/qqmljsast.cpp \ $$PWD/qqmljsastvisitor.cpp \ $$PWD/qqmljsengine_p.cpp \ - $$PWD/qqmljsgrammar.cpp \ $$PWD/qqmljslexer.cpp \ - $$PWD/qqmljsparser.cpp \ -OTHER_FILES += \ - $$PWD/qqmljs.g +CONFIG += qlalr +QLALRSOURCES = $$PWD/qqmljs.g +QMAKE_QLALRFLAGS = --no-debug --qt + +# make sure we install the headers generated by qlalr +private_headers.CONFIG += no_check_exist diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index d2d947e55c..fe8e744264 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -40,8 +40,7 @@ %parser QQmlJSGrammar %decl qqmljsparser_p.h %impl qqmljsparser.cpp -%expect 5 -%expect-rr 2 +%expect 1 %token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" %token T_BREAK "break" T_CASE "case" T_CATCH "catch" @@ -64,7 +63,7 @@ %token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" %token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" %token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" -%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal" +%token T_STAR_STAR "**" T_STAR_EQ "*=" T_STRING_LITERAL "string literal" %token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly" %token T_SWITCH "switch" T_THIS "this" T_THROW "throw" %token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" @@ -77,14 +76,29 @@ %token T_MULTILINE_STRING_LITERAL "multiline string literal" %token T_COMMENT "comment" %token T_COMPATIBILITY_SEMICOLON +%token T_ARROW "=>" %token T_ENUM "enum" +%token T_ELLIPSIS "..." +%token T_YIELD "yield" +%token T_SUPER "super" +%token T_CLASS "class" +%token T_EXTENDS "extends" +%token T_STATIC "static" +%token T_EXPORT "export" +%token T_FROM "from" + +--- template strings +%token T_NO_SUBSTITUTION_TEMPLATE"(no subst template)" +%token T_TEMPLATE_HEAD "(template head)" +%token T_TEMPLATE_MIDDLE "(template middle)" +%token T_TEMPLATE_TAIL "(template tail)" --- context keywords. %token T_PUBLIC "public" %token T_IMPORT "import" %token T_PRAGMA "pragma" %token T_AS "as" -%token T_ON "on" +%token T_OF "of" %token T_GET "get" %token T_SET "set" @@ -95,11 +109,16 @@ %token T_FEED_UI_OBJECT_MEMBER %token T_FEED_JS_STATEMENT %token T_FEED_JS_EXPRESSION -%token T_FEED_JS_SOURCE_ELEMENT -%token T_FEED_JS_PROGRAM +%token T_FEED_JS_SCRIPT +%token T_FEED_JS_MODULE -%nonassoc SHIFT_THERE -%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET +--- Lookahead handling +%token T_FORCE_DECLARATION "(force decl)" +%token T_FORCE_BLOCK "(force block)" +%token T_FOR_LOOKAHEAD_OK "(for lookahead ok)" + +--%left T_PLUS T_MINUS +%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_YIELD T_OF T_STATIC T_FROM %nonassoc REDUCE_HERE %start TopLevel @@ -143,10 +162,10 @@ ** ****************************************************************************/ -#include "qqmljsengine_p.h" -#include "qqmljslexer_p.h" -#include "qqmljsast_p.h" -#include "qqmljsmemorypool_p.h" +#include <private/qqmljsengine_p.h> +#include <private/qqmljslexer_p.h> +#include <private/qqmljsast_p.h> +#include <private/qqmljsmemorypool_p.h> #include <QtCore/qdebug.h> #include <QtCore/qcoreapplication.h> @@ -221,10 +240,10 @@ #ifndef QQMLJSPARSER_P_H #define QQMLJSPARSER_P_H -#include "qqmljsglobal_p.h" -#include "qqmljsgrammar_p.h" -#include "qqmljsast_p.h" -#include "qqmljsengine_p.h" +#include <private/qqmljsglobal_p.h> +#include <private/qqmljsgrammar_p.h> +#include <private/qqmljsast_p.h> +#include <private/qqmljsengine_p.h> #include <QtCore/qlist.h> #include <QtCore/qstring.h> @@ -250,21 +269,23 @@ public: AST::ElementList *ElementList; AST::Elision *Elision; AST::ExpressionNode *Expression; + AST::TemplateLiteral *Template; AST::Finally *Finally; AST::FormalParameterList *FormalParameterList; - AST::FunctionBody *FunctionBody; AST::FunctionDeclaration *FunctionDeclaration; AST::Node *Node; AST::PropertyName *PropertyName; - AST::PropertyAssignment *PropertyAssignment; - AST::PropertyAssignmentList *PropertyAssignmentList; - AST::SourceElement *SourceElement; - AST::SourceElements *SourceElements; + AST::PropertyDefinition *PropertyDefinition; + AST::PropertyDefinitionList *PropertyDefinitionList; AST::Statement *Statement; AST::StatementList *StatementList; AST::Block *Block; AST::VariableDeclaration *VariableDeclaration; AST::VariableDeclarationList *VariableDeclarationList; + AST::BindingPattern *BindingPattern; + AST::BindingElement *BindingElement; + AST::BindingPropertyList *BindingPropertyList; + AST::BindingElementList *BindingElementList; AST::UiProgram *UiProgram; AST::UiHeaderItemList *UiHeaderItemList; @@ -290,12 +311,13 @@ public: ~Parser(); // parse a UI program - bool parse() { return parse(T_FEED_UI_PROGRAM); } + bool parse() { ++functionNestingLevel; bool r = parse(T_FEED_UI_PROGRAM); --functionNestingLevel; return r; } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } - bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } - bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } - bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } + bool parseUiObjectMember() { ++functionNestingLevel; bool r = parse(T_FEED_UI_OBJECT_MEMBER); --functionNestingLevel; return r; } + bool parseProgram() { return parse(T_FEED_JS_SCRIPT); } + bool parseScript() { return parse(T_FEED_JS_SCRIPT); } + bool parseModule() { return parse(T_FEED_JS_MODULE); } AST::UiProgram *ast() const { return AST::cast<AST::UiProgram *>(program); } @@ -366,20 +388,27 @@ protected: AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); AST::UiQualifiedPragmaId *reparseAsQualifiedPragmaId(AST::ExpressionNode *expr); + void pushToken(int token); + int lookaheadToken(Lexer *lexer); + + void syntaxError(const AST::SourceLocation &location, const char *message) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location, QLatin1String(message))); + } + protected: Engine *driver; MemoryPool *pool; - int tos; - int stack_size; - Value *sym_stack; - int *state_stack; - AST::SourceLocation *location_stack; - QStringRef *string_stack; + int tos = 0; + int stack_size = 0; + Value *sym_stack = nullptr; + int *state_stack = nullptr; + AST::SourceLocation *location_stack = nullptr; + QStringRef *string_stack = nullptr; - AST::Node *program; + AST::Node *program = nullptr; - // error recovery - enum { TOKEN_BUFFER_SIZE = 3 }; + // error recovery and lookahead handling + enum { TOKEN_BUFFER_SIZE = 5 }; struct SavedToken { int token; @@ -388,14 +417,17 @@ protected: QStringRef spell; }; - double yylval; + int yytoken = -1; + double yylval = 0.; QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; - SavedToken *first_token; - SavedToken *last_token; + SavedToken *first_token = nullptr; + SavedToken *last_token = nullptr; + + int functionNestingLevel = 0; QList<DiagnosticMessage> diagnostic_messages; }; @@ -424,6 +456,8 @@ protected: // qlalr --no-debug --no-lines --qt qqmljs.g // +#define UNIMPLEMENTED syntaxError(loc(1), "Unimplemented"); return false + using namespace QQmlJS; QT_QML_BEGIN_NAMESPACE @@ -443,17 +477,7 @@ void Parser::reallocateStack() Parser::Parser(Engine *engine): driver(engine), - pool(engine->pool()), - tos(0), - stack_size(0), - sym_stack(0), - state_stack(0), - location_stack(0), - string_stack(0), - program(0), - yylval(0), - first_token(0), - last_token(0) + pool(engine->pool()) { } @@ -517,17 +541,38 @@ AST::UiQualifiedPragmaId *Parser::reparseAsQualifiedPragmaId(AST::ExpressionNode return 0; } +void Parser::pushToken(int token) +{ + last_token->token = yytoken; + last_token->dval = yylval; + last_token->spell = yytokenspell; + last_token->loc = yylloc; + ++last_token; + yytoken = token; +} + +int Parser::lookaheadToken(Lexer *lexer) +{ + if (yytoken < 0) { + yytoken = lexer->lex(); + yylval = lexer->tokenValue(); + yytokenspell = lexer->tokenSpell(); + yylloc = location(lexer); + } + return yytoken; +} + bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; - int yytoken = -1; + yytoken = -1; int action = 0; token_buffer[0].token = startToken; first_token = &token_buffer[0]; - if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) { + if (startToken == T_FEED_JS_SCRIPT && !lexer->qmlMode()) { Directives ignoreDirectives; Directives *directives = driver->directives(); if (!directives) @@ -570,9 +615,15 @@ bool Parser::parse(int startToken) yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; + if (first_token == last_token) + first_token = last_token = &token_buffer[0]; } } +#ifdef PARSER_DEBUG + qDebug() << " current token" << yytoken << (yytoken >= 0 ? spell[yytoken] : "(null)"); +#endif + action = t_action(action, yytoken); if (action > 0) { if (action != ACCEPT_STATE) { @@ -588,6 +639,10 @@ bool Parser::parse(int startToken) const int r = -action - 1; tos -= rhs[r]; +#ifdef PARSER_DEBUG + qDebug() << " reducing through rule " << r; +#endif + switch (r) { ./ @@ -595,2571 +650,2976 @@ bool Parser::parse(int startToken) -- Declarative UI -------------------------------------------------------------------------------------------------------- -TopLevel: T_FEED_UI_PROGRAM UiProgram ; +TopLevel: T_FEED_UI_PROGRAM UiProgram; /. -case $rule_number: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; + } break; ./ -TopLevel: T_FEED_JS_STATEMENT Statement ; +TopLevel: T_FEED_JS_STATEMENT Statement; /. -case $rule_number: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; + } break; ./ -TopLevel: T_FEED_JS_EXPRESSION Expression ; +TopLevel: T_FEED_JS_EXPRESSION Expression; /. -case $rule_number: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; + } break; ./ -TopLevel: T_FEED_JS_SOURCE_ELEMENT SourceElement ; +TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember; /. -case $rule_number: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; + } break; ./ -TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ; +TopLevel: T_FEED_JS_SCRIPT Script; /. -case $rule_number: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; + } break; ./ -TopLevel: T_FEED_JS_PROGRAM Program ; +TopLevel: T_FEED_JS_MODULE Module; /. -case $rule_number: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; + } break; ./ + UiProgram: UiHeaderItemListOpt UiRootMember; /. -case $rule_number: { - sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiHeaderItemList, - sym(2).UiObjectMemberList->finish()); -} break; + case $rule_number: { + sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiHeaderItemList, sym(2).UiObjectMemberList->finish()); + } break; ./ -UiHeaderItemListOpt: Empty ; -UiHeaderItemListOpt: UiHeaderItemList ; +UiHeaderItemListOpt: Empty; +UiHeaderItemListOpt: UiHeaderItemList; /. -case $rule_number: { - sym(1).Node = sym(1).UiHeaderItemList->finish(); -} break; + case $rule_number: { + sym(1).Node = sym(1).UiHeaderItemList->finish(); + } break; ./ -UiHeaderItemList: UiPragma ; +UiHeaderItemList: UiPragma; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiPragma); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiPragma); + } break; ./ -UiHeaderItemList: UiImport ; +UiHeaderItemList: UiImport; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiImport); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiImport); + } break; ./ -UiHeaderItemList: UiHeaderItemList UiPragma ; +UiHeaderItemList: UiHeaderItemList UiPragma; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiPragma); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiPragma); + } break; ./ -UiHeaderItemList: UiHeaderItemList UiImport ; +UiHeaderItemList: UiHeaderItemList UiImport; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiImport); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiImport); + } break; ./ -PragmaId: MemberExpression ; +PragmaId: MemberExpression; -ImportId: MemberExpression ; +ImportId: MemberExpression; -UiPragma: UiPragmaHead T_AUTOMATIC_SEMICOLON ; -UiPragma: UiPragmaHead T_SEMICOLON ; +UiPragma: UiPragmaHead T_AUTOMATIC_SEMICOLON; +UiPragma: UiPragmaHead T_SEMICOLON; /. -case $rule_number: { - sym(1).UiPragma->semicolonToken = loc(2); -} break; + case $rule_number: { + sym(1).UiPragma->semicolonToken = loc(2); + } break; ./ -UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ; -UiImport: UiImportHead T_SEMICOLON ; +UiImport: UiImportHead T_AUTOMATIC_SEMICOLON; +UiImport: UiImportHead T_SEMICOLON; /. -case $rule_number: { - sym(1).UiImport->semicolonToken = loc(2); -} break; + case $rule_number: { + sym(1).UiImport->semicolonToken = loc(2); + } break; ./ -UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ; -UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ; +UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON; +UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON; /. -case $rule_number: { - sym(1).UiImport->versionToken = loc(2); - sym(1).UiImport->semicolonToken = loc(3); -} break; + case $rule_number: { + sym(1).UiImport->versionToken = loc(2); + sym(1).UiImport->semicolonToken = loc(3); + } break; ./ -UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; -UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ; +UiImport: UiImportHead T_NUMERIC_LITERAL T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON; +UiImport: UiImportHead T_NUMERIC_LITERAL T_AS QmlIdentifier T_SEMICOLON; /. -case $rule_number: { - sym(1).UiImport->versionToken = loc(2); - sym(1).UiImport->asToken = loc(3); - sym(1).UiImport->importIdToken = loc(4); - sym(1).UiImport->importId = stringRef(4); - sym(1).UiImport->semicolonToken = loc(5); -} break; + case $rule_number: { + sym(1).UiImport->versionToken = loc(2); + sym(1).UiImport->asToken = loc(3); + sym(1).UiImport->importIdToken = loc(4); + sym(1).UiImport->importId = stringRef(4); + sym(1).UiImport->semicolonToken = loc(5); + } break; ./ -UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; -UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ; +UiImport: UiImportHead T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON; +UiImport: UiImportHead T_AS QmlIdentifier T_SEMICOLON; /. -case $rule_number: { - sym(1).UiImport->asToken = loc(2); - sym(1).UiImport->importIdToken = loc(3); - sym(1).UiImport->importId = stringRef(3); - sym(1).UiImport->semicolonToken = loc(4); -} break; + case $rule_number: { + sym(1).UiImport->asToken = loc(2); + sym(1).UiImport->importIdToken = loc(3); + sym(1).UiImport->importId = stringRef(3); + sym(1).UiImport->semicolonToken = loc(4); + } break; ./ -UiPragmaHead: T_PRAGMA PragmaId ; +UiPragmaHead: T_PRAGMA PragmaId; /. -case $rule_number: { - AST::UiPragma *node = 0; + case $rule_number: { + AST::UiPragma *node = 0; - if (AST::UiQualifiedPragmaId *qualifiedId = reparseAsQualifiedPragmaId(sym(2).Expression)) { - node = new (pool) AST::UiPragma(qualifiedId); - } + if (AST::UiQualifiedPragmaId *qualifiedId = reparseAsQualifiedPragmaId(sym(2).Expression)) + node = new (pool) AST::UiPragma(qualifiedId); - sym(1).Node = node; + sym(1).Node = node; - if (node) { - node->pragmaToken = loc(1); - } else { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), - QLatin1String("Expected a qualified name id"))); + if (node) { + node->pragmaToken = loc(1); + } else { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id"))); - return false; // ### remove me - } -} break; + return false; // ### remove me + } + } break; ./ -UiImportHead: T_IMPORT ImportId ; +UiImportHead: T_IMPORT ImportId; /. -case $rule_number: { - AST::UiImport *node = 0; - - if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { - node = new (pool) AST::UiImport(importIdLiteral->value); - node->fileNameToken = loc(2); - } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { - node = new (pool) AST::UiImport(qualifiedId); - node->fileNameToken = loc(2); - } + case $rule_number: { + AST::UiImport *node = 0; - sym(1).Node = node; + if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { + node = new (pool) AST::UiImport(importIdLiteral->value); + node->fileNameToken = loc(2); + } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { + node = new (pool) AST::UiImport(qualifiedId); + node->fileNameToken = loc(2); + } - if (node) { - node->importToken = loc(1); - } else { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), - QLatin1String("Expected a qualified name id or a string literal"))); + sym(1).Node = node; - return false; // ### remove me - } -} break; + if (node) { + node->importToken = loc(1); + } else { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id or a string literal"))); + + return false; // ### remove me + } + } break; ./ Empty: ; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -UiRootMember: UiObjectDefinition ; +UiRootMember: UiObjectDefinition; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); + } break; ./ -UiObjectMemberList: UiObjectMember ; +UiObjectMemberList: UiObjectMember; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); + } break; ./ -UiObjectMemberList: UiObjectMemberList UiObjectMember ; +UiObjectMemberList: UiObjectMemberList UiObjectMember; /. -case $rule_number: { - AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( - sym(1).UiObjectMemberList, sym(2).UiObjectMember); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList(sym(1).UiObjectMemberList, sym(2).UiObjectMember); + sym(1).Node = node; + } break; ./ -UiArrayMemberList: UiObjectDefinition ; +UiArrayMemberList: UiObjectDefinition; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); + } break; ./ -UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; +UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition; /. -case $rule_number: { - AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( - sym(1).UiArrayMemberList, sym(3).UiObjectMember); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList(sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -UiObjectInitializer: T_LBRACE T_RBRACE ; +UiObjectInitializer: T_LBRACE T_RBRACE; /. -case $rule_number: { - AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); - node->lbraceToken = loc(1); - node->rbraceToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); + node->lbraceToken = loc(1); + node->rbraceToken = loc(2); + sym(1).Node = node; + } break; ./ -UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; +UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE; /. -case $rule_number: { - AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; + } break; ./ -UiObjectDefinition: UiQualifiedId UiObjectInitializer ; +UiObjectDefinition: UiQualifiedId UiObjectInitializer; /. -case $rule_number: { - AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, - sym(2).UiObjectInitializer); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); + sym(1).Node = node; + } break; ./ -UiObjectMember: UiObjectDefinition ; +UiObjectMember: UiObjectDefinition; -UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; +UiObjectMember: UiQualifiedId T_COLON ExpressionStatementLookahead T_LBRACKET UiArrayMemberList T_RBRACKET; /. -case $rule_number: { - AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( - sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); - node->colonToken = loc(2); - node->lbracketToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding(sym(1).UiQualifiedId, sym(5).UiArrayMemberList->finish()); + node->colonToken = loc(2); + node->lbracketToken = loc(4); + node->rbracketToken = loc(6); + sym(1).Node = node; + } break; ./ -UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ; +UiObjectMember: UiQualifiedId T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer; /. -case $rule_number: { - AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( - sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( + sym(1).UiQualifiedId, sym(4).UiQualifiedId, sym(5).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; + } break; ./ -UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer ; +UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer; /. -case $rule_number: { - AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( - sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - node->hasOnToken = true; - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( + sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + node->hasOnToken = true; + sym(1).Node = node; + } break; ./ -UiScriptStatement: Block ; -UiScriptStatement: EmptyStatement ; -UiScriptStatement: ExpressionStatement ; -UiScriptStatement: IfStatement ; -UiScriptStatement: WithStatement ; -UiScriptStatement: SwitchStatement ; -UiScriptStatement: TryStatement ; -UiObjectMember: UiQualifiedId T_COLON UiScriptStatement ; +UiObjectLiteral: T_LBRACE ExpressionStatementLookahead UiPropertyDefinitionList T_RBRACE; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiObjectLiteral: T_LBRACE ExpressionStatementLookahead UiPropertyDefinitionList T_COMMA T_RBRACE; /. -case $rule_number: -{ - AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( - sym(1).UiQualifiedId, sym(3).Statement); - node->colonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ObjectLiteral *l = new (pool) AST::ObjectLiteral(sym(3).PropertyDefinitionList->finish()); + l->lbraceToken = loc(1); + l->rbraceToken = loc(4); + AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(l); + sym(1).Node = node; + } break; ./ -UiPropertyType: T_VAR ; -/. -case $rule_number: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ -UiPropertyType: T_RESERVED_WORD ; +UiScriptStatement: ExpressionStatementLookahead T_FORCE_DECLARATION ExpressionStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead T_FORCE_BLOCK Block; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead T_FORCE_BLOCK UiObjectLiteral; /. -case $rule_number: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(3).Node; + } break; ./ -UiPropertyType: T_IDENTIFIER ; -/. -case $rule_number: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; -./ -UiPropertyType: UiPropertyType T_DOT T_IDENTIFIER ; +UiScriptStatement: ExpressionStatementLookahead EmptyStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead ExpressionStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead IfStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead WithStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead SwitchStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +UiScriptStatement: ExpressionStatementLookahead TryStatement; /. -case $rule_number: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(sym(1).UiQualifiedId, stringRef(3)); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + } break; ./ -UiParameterListOpt: ; +UiObjectMember: UiQualifiedId T_COLON UiScriptStatement; /. -case $rule_number: { - sym(1).Node = 0; -} break; +case $rule_number: +{ + AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding(sym(1).UiQualifiedId, sym(3).Statement); + node->colonToken = loc(2); + sym(1).Node = node; + } break; ./ -UiParameterListOpt: UiParameterList ; +UiPropertyType: T_VAR; /. -case $rule_number: { - sym(1).Node = sym(1).UiParameterList->finish (); -} break; + case $rule_number: { + AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -UiParameterList: UiPropertyType JsIdentifier ; +UiPropertyType: T_RESERVED_WORD; /. -case $rule_number: { - AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiQualifiedId->finish(), stringRef(2)); - node->propertyTypeToken = loc(1); - node->identifierToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ; +UiPropertyType: T_IDENTIFIER; /. -case $rule_number: { - AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(3).UiQualifiedId->finish(), stringRef(4)); - node->propertyTypeToken = loc(3); - node->commaToken = loc(2); - node->identifierToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ; +UiPropertyType: UiPropertyType T_DOT T_IDENTIFIER; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); - node->type = AST::UiPublicMember::Signal; - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(2); - node->parameters = sym(4).UiParameterList; - node->semicolonToken = loc(6); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(sym(1).UiQualifiedId, stringRef(3)); + node->identifierToken = loc(3); + sym(1).Node = node; + } break; ./ -UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ; +UiParameterListOpt: ; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); - node->type = AST::UiPublicMember::Signal; - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ; +UiParameterListOpt: UiParameterList; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); - node->typeModifier = stringRef(2); - node->propertyToken = loc(1); - node->typeModifierToken = loc(2); - node->typeToken = loc(4); - node->identifierToken = loc(6); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(1).UiParameterList->finish(); + } break; ./ -UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; +UiParameterList: UiPropertyType QmlIdentifier; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->semicolonToken = loc(4); - sym(1).Node = node; -} break; -./ + case $rule_number: { + AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiQualifiedId->finish(), stringRef(2)); + node->propertyTypeToken = loc(1); + node->identifierToken = loc(2); + sym(1).Node = node; + } break; +./ -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; +UiParameterList: UiParameterList T_COMMA UiPropertyType QmlIdentifier; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->semicolonToken = loc(5); - sym(1).Node = node; -} break; -./ - -UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_AUTOMATIC_SEMICOLON ; -UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ; + case $rule_number: { + AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(3).UiQualifiedId->finish(), stringRef(4)); + node->propertyTypeToken = loc(3); + node->commaToken = loc(2); + node->identifierToken = loc(4); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON; +UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7)); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->typeModifier = stringRef(3); - node->propertyToken = loc(2); - node->typeModifierToken = loc(2); - node->typeToken = loc(4); - node->identifierToken = loc(7); - node->semicolonToken = loc(8); - sym(1).Node = node; -} break; -./ + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(2); + node->parameters = sym(4).UiParameterList; + node->semicolonToken = loc(6); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON; +UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON; +UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); + node->typeModifier = stringRef(2); + node->propertyToken = loc(1); + node->typeModifierToken = loc(2); + node->typeToken = loc(4); + node->identifierToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON; +UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; + } break; +./ -UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; -/. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3), - sym(5).Statement); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->colonToken = loc(4); - sym(1).Node = node; -} break; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON; +UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7)); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->typeModifier = stringRef(3); + node->propertyToken = loc(2); + node->typeModifierToken = loc(2); + node->typeToken = loc(4); + node->identifierToken = loc(7); + node->semicolonToken = loc(8); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3), sym(5).Statement); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->colonToken = loc(4); + sym(1).Node = node; + } break; +./ + +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement; +/. + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + sym(1).Node = node; + } break; ./ -UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), - sym(6).Statement); - node->isReadonlyMember = true; - node->readonlyToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->colonToken = loc(5); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), sym(6).Statement); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + sym(1).Node = node; + } break; ./ -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; +UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), - sym(6).Statement); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->colonToken = loc(5); - sym(1).Node = node; -} break; -./ + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); + node->typeModifier = stringRef(2); + node->propertyToken = loc(1); + node->typeModifierToken = loc(2); + node->typeToken = loc(4); + node->identifierToken = loc(6); + node->semicolonToken = loc(7); // insert a fake ';' before ':' -UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; -/. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); - node->typeModifier = stringRef(2); - node->propertyToken = loc(1); - node->typeModifierToken = loc(2); - node->typeToken = loc(4); - node->identifierToken = loc(6); - node->semicolonToken = loc(7); // insert a fake ';' before ':' - - AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); - propertyName->identifierToken = loc(6); - propertyName->next = 0; - - AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( - propertyName, sym(9).UiArrayMemberList->finish()); - binding->colonToken = loc(7); - binding->lbracketToken = loc(8); - binding->rbracketToken = loc(10); - - node->binding = binding; + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); + propertyName->identifierToken = loc(6); + propertyName->next = 0; - sym(1).Node = node; -} break; + AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding(propertyName, sym(9).UiArrayMemberList->finish()); + binding->colonToken = loc(7); + binding->lbracketToken = loc(8); + binding->rbracketToken = loc(10); + + node->binding = binding; + + sym(1).Node = node; + } break; ./ -UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; +UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->semicolonToken = loc(4); // insert a fake ';' before ':' + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->semicolonToken = loc(4); // insert a fake ';' before ':' - AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); - propertyName->identifierToken = loc(3); - propertyName->next = 0; + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); + propertyName->identifierToken = loc(3); + propertyName->next = 0; - AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( - propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); - binding->colonToken = loc(4); + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( + propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); + binding->colonToken = loc(4); - node->binding = binding; + node->binding = binding; - sym(1).Node = node; -} break; + sym(1).Node = node; + } break; ./ -UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON ExpressionStatementLookahead UiQualifiedId UiObjectInitializer; /. -case $rule_number: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); - node->isReadonlyMember = true; - node->readonlyToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->semicolonToken = loc(5); // insert a fake ';' before ':' + case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); // insert a fake ';' before ':' - AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); - propertyName->identifierToken = loc(4); - propertyName->next = 0; + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); + propertyName->identifierToken = loc(4); + propertyName->next = 0; - AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( - propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); - binding->colonToken = loc(5); + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( + propertyName, sym(7).UiQualifiedId, sym(8).UiObjectInitializer); + binding->colonToken = loc(5); - node->binding = binding; + node->binding = binding; - sym(1).Node = node; -} break; + sym(1).Node = node; + } break; ./ -UiObjectMember: FunctionDeclaration ; +UiObjectMember: FunctionDeclaration; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); + } break; ./ -UiObjectMember: VariableStatement ; +UiObjectMember: VariableStatement; /. -case $rule_number: { - sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); + } break; +./ + +UiQualifiedId: MemberExpression; +/. + case $rule_number: { + if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, + QLatin1String("Ignored annotation"))); + + sym(1).Expression = mem->base; + } + + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { + sym(1).UiQualifiedId = qualifiedId; + } else { + sym(1).UiQualifiedId = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id"))); + + return false; // ### recover + } + } break; ./ UiObjectMember: T_ENUM T_IDENTIFIER T_LBRACE EnumMemberList T_RBRACE; /. -case $rule_number: { - AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish()); - enumDeclaration->enumToken = loc(1); - enumDeclaration->rbraceToken = loc(5); - sym(1).Node = enumDeclaration; - break; -} + case $rule_number: { + AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish()); + enumDeclaration->enumToken = loc(1); + enumDeclaration->rbraceToken = loc(5); + sym(1).Node = enumDeclaration; + break; + } ./ EnumMemberList: T_IDENTIFIER; /. -case $rule_number: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1)); - node->memberToken = loc(1); - sym(1).Node = node; - break; -} + case $rule_number: { + AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1)); + node->memberToken = loc(1); + sym(1).Node = node; + break; + } ./ EnumMemberList: T_IDENTIFIER T_EQ T_NUMERIC_LITERAL; /. -case $rule_number: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1), sym(3).dval); - node->memberToken = loc(1); - node->valueToken = loc(3); - sym(1).Node = node; - break; -} + case $rule_number: { + AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1), sym(3).dval); + node->memberToken = loc(1); + node->valueToken = loc(3); + sym(1).Node = node; + break; + } ./ EnumMemberList: EnumMemberList T_COMMA T_IDENTIFIER; /. -case $rule_number: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3)); - node->memberToken = loc(3); - sym(1).Node = node; - break; -} + case $rule_number: { + AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3)); + node->memberToken = loc(3); + sym(1).Node = node; + break; + } ./ EnumMemberList: EnumMemberList T_COMMA T_IDENTIFIER T_EQ T_NUMERIC_LITERAL; /. -case $rule_number: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3), sym(5).dval); - node->memberToken = loc(3); - node->valueToken = loc(5); - sym(1).Node = node; - break; -} + case $rule_number: { + AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3), sym(5).dval); + node->memberToken = loc(3); + node->valueToken = loc(5); + sym(1).Node = node; + break; + } ./ -JsIdentifier: T_IDENTIFIER; +QmlIdentifier: T_IDENTIFIER; +QmlIdentifier: T_PROPERTY; +QmlIdentifier: T_SIGNAL; +QmlIdentifier: T_READONLY; +QmlIdentifier: T_ON; +QmlIdentifier: T_GET; +QmlIdentifier: T_SET; +QmlIdentifier: T_FROM; +QmlIdentifier: T_OF; -JsIdentifier: T_PROPERTY ; -JsIdentifier: T_SIGNAL ; -JsIdentifier: T_READONLY ; -JsIdentifier: T_ON ; -JsIdentifier: T_GET ; -JsIdentifier: T_SET ; +JsIdentifier: T_IDENTIFIER; +JsIdentifier: T_PROPERTY; +JsIdentifier: T_SIGNAL; +JsIdentifier: T_READONLY; +JsIdentifier: T_ON; +JsIdentifier: T_GET; +JsIdentifier: T_SET; +JsIdentifier: T_FROM; +JsIdentifier: T_STATIC; +JsIdentifier: T_OF; + +IdentifierReference: JsIdentifier; +BindingIdentifier: IdentifierReference; -------------------------------------------------------------------------------------------------------- -- Expressions -------------------------------------------------------------------------------------------------------- -PrimaryExpression: T_THIS ; +PrimaryExpression: T_THIS; /. -case $rule_number: { - AST::ThisExpression *node = new (pool) AST::ThisExpression(); - node->thisToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ThisExpression *node = new (pool) AST::ThisExpression(); + node->thisToken = loc(1); + sym(1).Node = node; + } break; ./ -PrimaryExpression: JsIdentifier ; +PrimaryExpression: IdentifierReference; /. -case $rule_number: { - AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_NULL ; +PrimaryExpression: Literal; +PrimaryExpression: ArrayLiteral; +PrimaryExpression: ObjectLiteral; +PrimaryExpression: FunctionExpression; +PrimaryExpression: ClassExpression; +PrimaryExpression: GeneratorExpression; +PrimaryExpression: RegularExpressionLiteral; +PrimaryExpression: TemplateLiteral; + +PrimaryExpression: CoverParenthesizedExpressionAndArrowParameterList; + +-- ### Further restricted parsing of the CoverParenthesizedExpressionAndArrowParameterList to the one rule below when this is parsed as a primary expression! +CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN Expression_In T_RPAREN; /. -case $rule_number: { - AST::NullExpression *node = new (pool) AST::NullExpression(); - node->nullToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); + node->lparenToken = loc(1); + node->rparenToken = loc(3); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_TRUE ; +CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN T_RPAREN; +CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN T_ELLIPSIS BindingIdentifier T_RPAREN; +CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN T_ELLIPSIS BindingPattern T_RPAREN; +CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN Expression_In T_COMMA T_ELLIPSIS BindingIdentifier T_RPAREN; +CoverParenthesizedExpressionAndArrowParameterList: T_LPAREN Expression_In T_COMMA T_ELLIPSIS BindingPattern T_RPAREN; + +Literal: T_NULL; /. -case $rule_number: { - AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); - node->trueToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::NullExpression *node = new (pool) AST::NullExpression(); + node->nullToken = loc(1); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_FALSE ; +Literal: T_TRUE; /. -case $rule_number: { - AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); - node->falseToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); + node->trueToken = loc(1); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_NUMERIC_LITERAL ; +Literal: T_FALSE; /. -case $rule_number: { - AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); + node->falseToken = loc(1); + sym(1).Node = node; + } break; +./ + +Literal: T_NUMERIC_LITERAL; +/. + case $rule_number: { + AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); + node->literalToken = loc(1); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_MULTILINE_STRING_LITERAL ; -/.case $rule_number:./ +Literal: T_MULTILINE_STRING_LITERAL; +/. case $rule_number: Q_FALLTHROUGH(); ./ -PrimaryExpression: T_STRING_LITERAL ; +Literal: T_STRING_LITERAL; /. -case $rule_number: { - AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); - node->literalToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); + node->literalToken = loc(1); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_DIVIDE_ ; +RegularExpressionLiteral: T_DIVIDE_; /: #define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number :/ /. -case $rule_number: { - bool rx = lexer->scanRegExp(Lexer::NoPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; // ### remove me - } - - loc(1).length = lexer->tokenLength(); - yylloc = loc(1); // adjust the location of the current token - - AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( - driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); - node->literalToken = loc(1); - sym(1).Node = node; -} break; +{ + Lexer::RegExpBodyPrefix prefix; + case $rule_number: + prefix = Lexer::NoPrefix; + goto scan_regexp; ./ -PrimaryExpression: T_DIVIDE_EQ ; +RegularExpressionLiteral: T_DIVIDE_EQ; /: #define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number :/ /. -case $rule_number: { - bool rx = lexer->scanRegExp(Lexer::EqualPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; - } + case $rule_number: + prefix = Lexer::EqualPrefix; + goto scan_regexp; - loc(1).length = lexer->tokenLength(); - yylloc = loc(1); // adjust the location of the current token + scan_regexp: { + bool rx = lexer->scanRegExp(prefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; + } - AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( - driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); - node->literalToken = loc(1); - sym(1).Node = node; -} break; + loc(1).length = lexer->tokenLength(); + yylloc = loc(1); // adjust the location of the current token + + AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral(driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); + node->literalToken = loc(1); + sym(1).Node = node; + } break; +} ./ -PrimaryExpression: T_LBRACKET T_RBRACKET ; + +ArrayLiteral: T_LBRACKET ElisionOpt T_RBRACKET; /. -case $rule_number: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); - node->lbracketToken = loc(1); - node->rbracketToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; +ArrayLiteral: T_LBRACKET ElementList T_RBRACKET; /. -case $rule_number: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; +ArrayLiteral: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET; /. -case $rule_number: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish(), sym(4).Elision); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; +ElementList: AssignmentExpression_In; /. -case $rule_number: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), - (AST::Elision *) 0); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::ElementList(nullptr, sym(1).Expression); + } break; ./ -PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; +ElementList: Elision AssignmentExpression_In; /. -case $rule_number: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), - sym(4).Elision->finish()); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); + } break; ./ --- PrimaryExpression: T_LBRACE T_RBRACE ; --- /. --- case $rule_number: { --- sym(1).Node = new (pool) AST::ObjectLiteral(); --- } break; --- ./ +ElementList: ElisionOpt SpreadElement; -PrimaryExpression: T_LBRACE PropertyAssignmentListOpt T_RBRACE ; +ElementList: ElementList T_COMMA ElisionOpt AssignmentExpression_In; /. -case $rule_number: { - AST::ObjectLiteral *node = 0; - if (sym(2).Node) - node = new (pool) AST::ObjectLiteral( - sym(2).PropertyAssignmentList->finish ()); - else - node = new (pool) AST::ObjectLiteral(); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision, sym(4).Expression); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -PrimaryExpression: T_LBRACE PropertyAssignmentList T_COMMA T_RBRACE ; -/. -case $rule_number: { - AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( - sym(2).PropertyAssignmentList->finish ()); - node->lbraceToken = loc(1); - node->rbraceToken = loc(4); - sym(1).Node = node; -} break; -./ +ElementList: ElementList T_COMMA ElisionOpt SpreadElement; -PrimaryExpression: T_LPAREN Expression T_RPAREN ; +Elision: T_COMMA; /. -case $rule_number: { - AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); - node->lparenToken = loc(1); - node->rparenToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::Elision *node = new (pool) AST::Elision(); + node->commaToken = loc(1); + sym(1).Node = node; + } break; ./ - -UiQualifiedId: MemberExpression ; +Elision: Elision T_COMMA; /. -case $rule_number: { - if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, - QLatin1String("Ignored annotation"))); - - sym(1).Expression = mem->base; - } - - if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { - sym(1).UiQualifiedId = qualifiedId; - } else { - sym(1).UiQualifiedId = 0; - - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), - QLatin1String("Expected a qualified name id"))); - - return false; // ### recover - } -} break; + case $rule_number: { + AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -ElementList: AssignmentExpression ; +ElisionOpt: ; /. -case $rule_number: { - sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -ElementList: Elision AssignmentExpression ; +ElisionOpt: Elision; /. -case $rule_number: { - sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); -} break; + case $rule_number: { + sym(1).Node = sym(1).Elision->finish(); + } break; ./ -ElementList: ElementList T_COMMA AssignmentExpression ; +SpreadElement: T_ELLIPSIS AssignmentExpression; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +ObjectLiteral: T_LBRACE T_RBRACE; /. -case $rule_number: { - AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, - (AST::Elision *) 0, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral(); + node->lbraceToken = loc(1); + node->rbraceToken = loc(2); + sym(1).Node = node; + } break; ./ -ElementList: ElementList T_COMMA Elision AssignmentExpression ; +ObjectLiteral: T_LBRACE PropertyDefinitionList T_RBRACE; /. -case $rule_number: { - AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), - sym(4).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral(sym(2).PropertyDefinitionList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; + } break; ./ -Elision: T_COMMA ; +ObjectLiteral: T_LBRACE PropertyDefinitionList T_COMMA T_RBRACE; /. -case $rule_number: { - AST::Elision *node = new (pool) AST::Elision(); - node->commaToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral(sym(2).PropertyDefinitionList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(4); + sym(1).Node = node; + } break; ./ -Elision: Elision T_COMMA ; + +UiPropertyDefinitionList: UiPropertyDefinition; +/. case $rule_number: Q_FALLTHROUGH(); ./ +PropertyDefinitionList: PropertyDefinition; /. -case $rule_number: { - AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::PropertyDefinitionList(sym(1).PropertyDefinition); + } break; ./ -PropertyAssignment: PropertyName T_COLON AssignmentExpression ; +UiPropertyDefinitionList: UiPropertyDefinitionList T_COMMA UiPropertyDefinition; +/. case $rule_number: Q_FALLTHROUGH(); ./ +PropertyDefinitionList: PropertyDefinitionList T_COMMA PropertyDefinition; /. -case $rule_number: { - AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue( - sym(1).PropertyName, sym(3).Expression); - node->colonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PropertyDefinitionList *node = new (pool) AST::PropertyDefinitionList(sym(1).PropertyDefinitionList, sym(3).PropertyDefinition); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -PropertyAssignment: T_GET PropertyName T_LPAREN T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +PropertyDefinition: IdentifierReference; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +PropertyDefinition: CoverInitializedName; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +UiPropertyDefinition: UiPropertyName T_COLON AssignmentExpression_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +PropertyDefinition: PropertyName T_COLON AssignmentExpression_In; /. -case $rule_number: { - AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( - sym(2).PropertyName, sym(6).FunctionBody); - node->getSetToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(4); - node->lbraceToken = loc(5); - node->rbraceToken = loc(7); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue(sym(1).PropertyName, sym(3).Expression); + node->colonToken = loc(2); + sym(1).Node = node; + } break; ./ -PropertyAssignment: T_SET PropertyName T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +PropertyDefinition: MethodDefinition; + +PropertyName: LiteralPropertyName; +PropertyName: ComputedPropertyName; + +LiteralPropertyName: IdentifierName; /. -case $rule_number: { - AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( - sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody); - node->getSetToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; + case $rule_number: { + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); + node->propertyNameToken = loc(1); + sym(1).Node = node; + } break; ./ -PropertyAssignmentList: PropertyAssignment ; +UiPropertyName: T_STRING_LITERAL; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LiteralPropertyName: T_STRING_LITERAL; /. -case $rule_number: { - sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment); -} break; + case $rule_number: { + AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); + node->propertyNameToken = loc(1); + sym(1).Node = node; + } break; ./ -PropertyAssignmentList: PropertyAssignmentList T_COMMA PropertyAssignment ; +UiPropertyName: T_NUMERIC_LITERAL; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LiteralPropertyName: T_NUMERIC_LITERAL; /. -case $rule_number: { - AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList( - sym(1).PropertyAssignmentList, sym(3).PropertyAssignment); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); + node->propertyNameToken = loc(1); + sym(1).Node = node; + } break; ./ -PropertyName: JsIdentifier %prec SHIFT_THERE ; +IdentifierName: IdentifierReference; +IdentifierName: ReservedIdentifier; + +ReservedIdentifier: T_BREAK; +ReservedIdentifier: T_CASE; +ReservedIdentifier: T_CATCH; +ReservedIdentifier: T_CONTINUE; +ReservedIdentifier: T_DEFAULT; +ReservedIdentifier: T_DELETE; +ReservedIdentifier: T_DO; +ReservedIdentifier: T_ELSE; +ReservedIdentifier: T_ENUM; +ReservedIdentifier: T_FALSE; +ReservedIdentifier: T_FINALLY; +ReservedIdentifier: T_FOR; +ReservedIdentifier: T_FUNCTION; +ReservedIdentifier: T_IF; +ReservedIdentifier: T_IN; +ReservedIdentifier: T_INSTANCEOF; +ReservedIdentifier: T_NEW; +ReservedIdentifier: T_NULL; +ReservedIdentifier: T_RETURN; +ReservedIdentifier: T_SWITCH; +ReservedIdentifier: T_THIS; +ReservedIdentifier: T_THROW; +ReservedIdentifier: T_TRUE; +ReservedIdentifier: T_TRY; +ReservedIdentifier: T_TYPEOF; +ReservedIdentifier: T_VAR; +ReservedIdentifier: T_VOID; +ReservedIdentifier: T_WHILE; +ReservedIdentifier: T_CONST; +ReservedIdentifier: T_LET; +ReservedIdentifier: T_DEBUGGER; +ReservedIdentifier: T_RESERVED_WORD; +ReservedIdentifier: T_SUPER; +ReservedIdentifier: T_WITH; +ReservedIdentifier: T_CLASS; +ReservedIdentifier: T_EXTENDS; +ReservedIdentifier: T_EXPORT; + +ComputedPropertyName: T_LBRACKET AssignmentExpression_In T_RBRACKET; +/. case $rule_number: { UNIMPLEMENTED; } ./ + + +CoverInitializedName: IdentifierReference Initializer_In; + +Initializer: T_EQ AssignmentExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Initializer_In: T_EQ AssignmentExpression_In; /. case $rule_number: { - AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; + sym(1) = sym(2); } break; ./ -PropertyName: T_STRING_LITERAL ; + +InitializerOpt: ; +/. case $rule_number: Q_FALLTHROUGH(); ./ +InitializerOpt_In: ; /. -case $rule_number: { - AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -PropertyName: T_NUMERIC_LITERAL ; +InitializerOpt: Initializer; +InitializerOpt_In: Initializer_In; + +TemplateLiteral: T_NO_SUBSTITUTION_TEMPLATE; +/. case $rule_number: Q_FALLTHROUGH(); ./ + +TemplateSpans: T_TEMPLATE_TAIL; /. -case $rule_number: { - AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::TemplateLiteral *node = new (pool) AST::TemplateLiteral(stringRef(1), nullptr); + node->literalToken = loc(1); + sym(1).Node = node; + } break; ./ -PropertyName: ReservedIdentifier ; +TemplateSpans: T_TEMPLATE_MIDDLE Expression TemplateSpans; +/. case $rule_number: Q_FALLTHROUGH(); ./ + +TemplateLiteral: T_TEMPLATE_HEAD Expression TemplateSpans; /. -case $rule_number: { - AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::TemplateLiteral *node = new (pool) AST::TemplateLiteral(stringRef(1), sym(2).Expression); + node->next = sym(3).Template; + node->literalToken = loc(1); + sym(1).Node = node; + } break; ./ -ReservedIdentifier: T_BREAK ; -ReservedIdentifier: T_CASE ; -ReservedIdentifier: T_CATCH ; -ReservedIdentifier: T_CONTINUE ; -ReservedIdentifier: T_DEFAULT ; -ReservedIdentifier: T_DELETE ; -ReservedIdentifier: T_DO ; -ReservedIdentifier: T_ELSE ; -ReservedIdentifier: T_ENUM ; -ReservedIdentifier: T_FALSE ; -ReservedIdentifier: T_FINALLY ; -ReservedIdentifier: T_FOR ; -ReservedIdentifier: T_FUNCTION ; -ReservedIdentifier: T_IF ; -ReservedIdentifier: T_IN ; -ReservedIdentifier: T_INSTANCEOF ; -ReservedIdentifier: T_NEW ; -ReservedIdentifier: T_NULL ; -ReservedIdentifier: T_RETURN ; -ReservedIdentifier: T_SWITCH ; -ReservedIdentifier: T_THIS ; -ReservedIdentifier: T_THROW ; -ReservedIdentifier: T_TRUE ; -ReservedIdentifier: T_TRY ; -ReservedIdentifier: T_TYPEOF ; -ReservedIdentifier: T_VAR ; -ReservedIdentifier: T_VOID ; -ReservedIdentifier: T_WHILE ; -ReservedIdentifier: T_CONST ; -ReservedIdentifier: T_LET ; -ReservedIdentifier: T_DEBUGGER ; -ReservedIdentifier: T_RESERVED_WORD ; -ReservedIdentifier: T_WITH ; - -PropertyIdentifier: JsIdentifier ; -PropertyIdentifier: ReservedIdentifier ; - -MemberExpression: PrimaryExpression ; -MemberExpression: FunctionExpression ; - -MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; + +MemberExpression: PrimaryExpression; + +MemberExpression: MemberExpression T_LBRACKET Expression_In T_RBRACKET; /. -case $rule_number: { - AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; + } break; ./ -MemberExpression: MemberExpression T_DOT PropertyIdentifier ; +MemberExpression: MemberExpression T_DOT IdentifierName; /. -case $rule_number: { - AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; + } break; ./ -MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; +MemberExpression: SuperProperty; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +MemberExpression: MetaProperty; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +MemberExpression: T_NEW MemberExpression T_LPAREN Arguments T_RPAREN; /. -case $rule_number: { - AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); - node->newToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - sym(1).Node = node; -} break; + case $rule_number: { + AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); + node->newToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + sym(1).Node = node; + } break; ./ -NewExpression: MemberExpression ; +SuperProperty: T_SUPER T_LBRACKET Expression_In T_RBRACKET; -NewExpression: T_NEW NewExpression ; +SuperProperty: T_SUPER T_DOT IdentifierName; + +MetaProperty: NewTarget; + +NewTarget: T_NEW T_DOT T_IDENTIFIER; -- ### the identifier has to be "target"; + +NewExpression: MemberExpression; + +NewExpression: T_NEW NewExpression; /. -case $rule_number: { + case $rule_number: { AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; -} break; + } break; ./ -CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; + +CallExpression: CallExpression TemplateLiteral; +/. case $rule_number: Q_FALLTHROUGH(); ./ +MemberExpression: MemberExpression TemplateLiteral; /. -case $rule_number: { - AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::TaggedTemplate *node = new (pool) AST::TaggedTemplate(sym(1).Expression, sym(2).Template); + sym(1).Node = node; + } break; ./ -CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; +CallExpression: MemberExpression T_LPAREN Arguments T_RPAREN; /. -case $rule_number: { - AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; ./ -CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; +CallExpression: SuperCall; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +CallExpression: CallExpression T_LPAREN Arguments T_RPAREN; /. -case $rule_number: { - AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; ./ -CallExpression: CallExpression T_DOT PropertyIdentifier ; +CallExpression: CallExpression T_LBRACKET Expression_In T_RBRACKET; /. -case $rule_number: { - AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; + } break; ./ -ArgumentListOpt: ; +CallExpression: CallExpression T_DOT IdentifierName; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; + } break; ./ -ArgumentListOpt: ArgumentList ; +SuperCall: T_SUPER T_LPAREN Arguments T_RPAREN; + +Arguments: ; /. -case $rule_number: { - sym(1).Node = sym(1).ArgumentList->finish(); -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -ArgumentList: AssignmentExpression ; +Arguments: ArgumentList; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Arguments: ArgumentList T_COMMA; /. -case $rule_number: { - sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); -} break; + case $rule_number: { + sym(1).Node = sym(1).ArgumentList->finish(); + } break; ./ -ArgumentList: ArgumentList T_COMMA AssignmentExpression ; +ArgumentList: AssignmentExpression_In; /. -case $rule_number: { - AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); + } break; ./ -LeftHandSideExpression: NewExpression ; -LeftHandSideExpression: CallExpression ; -PostfixExpression: LeftHandSideExpression ; +ArgumentList: T_ELLIPSIS AssignmentExpression_In; +/. case $rule_number: { UNIMPLEMENTED; } ./ -PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; +ArgumentList: ArgumentList T_COMMA AssignmentExpression_In; /. -case $rule_number: { - AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); - node->incrementToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; +ArgumentList: ArgumentList T_COMMA T_ELLIPSIS AssignmentExpression_In; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +LeftHandSideExpression: NewExpression; +LeftHandSideExpression: CallExpression; + +UpdateExpression: LeftHandSideExpression; + +UpdateExpression: LeftHandSideExpression T_PLUS_PLUS; /. -case $rule_number: { - AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); - node->decrementToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); + node->incrementToken = loc(2); + sym(1).Node = node; + } break; ./ -UnaryExpression: PostfixExpression ; +UpdateExpression: LeftHandSideExpression T_MINUS_MINUS; +/. + case $rule_number: { + AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); + node->decrementToken = loc(2); + sym(1).Node = node; + } break; +./ -UnaryExpression: T_DELETE UnaryExpression ; +UpdateExpression: T_PLUS_PLUS UnaryExpression; /. -case $rule_number: { - AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); - node->deleteToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); + node->incrementToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_VOID UnaryExpression ; +UpdateExpression: T_MINUS_MINUS UnaryExpression; /. -case $rule_number: { - AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); - node->voidToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); + node->decrementToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_TYPEOF UnaryExpression ; +UnaryExpression: UpdateExpression; + +UnaryExpression: T_DELETE UnaryExpression; /. -case $rule_number: { - AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); - node->typeofToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); + node->deleteToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_PLUS_PLUS UnaryExpression ; +UnaryExpression: T_VOID UnaryExpression; /. -case $rule_number: { - AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); - node->incrementToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); + node->voidToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_MINUS_MINUS UnaryExpression ; +UnaryExpression: T_TYPEOF UnaryExpression; /. -case $rule_number: { - AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); - node->decrementToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); + node->typeofToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_PLUS UnaryExpression ; +UnaryExpression: T_PLUS UnaryExpression; /. -case $rule_number: { - AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); - node->plusToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); + node->plusToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_MINUS UnaryExpression ; +UnaryExpression: T_MINUS UnaryExpression; /. -case $rule_number: { - AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); - node->minusToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); + node->minusToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_TILDE UnaryExpression ; +UnaryExpression: T_TILDE UnaryExpression; /. -case $rule_number: { - AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); - node->tildeToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); + node->tildeToken = loc(1); + sym(1).Node = node; + } break; ./ -UnaryExpression: T_NOT UnaryExpression ; +UnaryExpression: T_NOT UnaryExpression; /. -case $rule_number: { - AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); - node->notToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); + node->notToken = loc(1); + sym(1).Node = node; + } break; ./ -MultiplicativeExpression: UnaryExpression ; +ExponentiationExpression: UnaryExpression; -MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; +ExponentiationExpression: UpdateExpression T_STAR_STAR ExponentiationExpression; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +MultiplicativeExpression: ExponentiationExpression; + +MultiplicativeExpression: MultiplicativeExpression MultiplicativeOperator ExponentiationExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Mul, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; +MultiplicativeOperator: T_STAR; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Div, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Mul; + } break; ./ -MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; +MultiplicativeOperator: T_DIVIDE_; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Mod, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Div; + } break; +./ + +MultiplicativeOperator: T_REMAINDER; +/. + case $rule_number: { + sym(1).ival = QSOperator::Mod; + } break; ./ -AdditiveExpression: MultiplicativeExpression ; +AdditiveExpression: MultiplicativeExpression; -AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; +AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Add, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; +AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Sub, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -ShiftExpression: AdditiveExpression ; +ShiftExpression: AdditiveExpression; -ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; +ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::LShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; +ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::RShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; +ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::URShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -RelationalExpression: ShiftExpression ; +RelationalExpression_In: ShiftExpression; +RelationalExpression: ShiftExpression; -RelationalExpression: RelationalExpression T_LT ShiftExpression ; +RelationalExpression_In: RelationalExpression_In RelationalOperator ShiftExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +RelationalExpression: RelationalExpression RelationalOperator ShiftExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -RelationalExpression: RelationalExpression T_GT ShiftExpression ; +RelationalOperator: T_LT; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Lt; + } break; ./ - -RelationalExpression: RelationalExpression T_LE ShiftExpression ; +RelationalOperator: T_GT; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Gt; + } break; ./ - -RelationalExpression: RelationalExpression T_GE ShiftExpression ; +RelationalOperator: T_LE; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Le; + } break; ./ - -RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; +RelationalOperator: T_GE; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Ge; + } break; +./ +RelationalOperator: T_INSTANCEOF; +/. + case $rule_number: { + sym(1).ival = QSOperator::InstanceOf; + } break; ./ -RelationalExpression: RelationalExpression T_IN ShiftExpression ; +RelationalExpression_In: RelationalExpression_In T_IN ShiftExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::In, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -RelationalExpressionNotIn: ShiftExpression ; +EqualityExpression_In: RelationalExpression_In; +EqualityExpression: RelationalExpression; -RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; +EqualityExpression_In: EqualityExpression_In EqualityOperator RelationalExpression_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +EqualityExpression: EqualityExpression EqualityOperator RelationalExpression; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; +EqualityOperator: T_EQ_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::Equal; + } break; ./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; +EqualityOperator: T_NOT_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::NotEqual; + } break; ./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; +EqualityOperator: T_EQ_EQ_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::StrictEqual; + } break; ./ - -RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; +EqualityOperator: T_NOT_EQ_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::StrictNotEqual; + } break; ./ -EqualityExpression: RelationalExpression ; -EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; +BitwiseANDExpression: EqualityExpression; +XitwiseANDExpression_In: EqualityExpression_In; + +BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +XitwiseANDExpression_In: XitwiseANDExpression_In T_AND EqualityExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; + +BitwiseXORExpression: BitwiseANDExpression; +BitwiseXORExpression_In: XitwiseANDExpression_In; + +BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +BitwiseXORExpression_In: BitwiseXORExpression_In T_XOR XitwiseANDExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; +BitwiseORExpression: BitwiseXORExpression; +BitwiseORExpression_In: BitwiseXORExpression_In; + +BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +BitwiseORExpression_In: BitwiseORExpression_In T_OR BitwiseXORExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; +LogicalANDExpression: BitwiseORExpression; +LogicalANDExpression_In: BitwiseORExpression_In; + +LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LogicalANDExpression_In: LogicalANDExpression_In T_AND_AND BitwiseORExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -EqualityExpressionNotIn: RelationalExpressionNotIn ; +LogicalORExpression: LogicalANDExpression; +LogicalORExpression_In: LogicalANDExpression_In; -EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; +LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LogicalORExpression_In: LogicalORExpression_In T_OR_OR LogicalANDExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; + +ConditionalExpression: LogicalORExpression; +ConditionalExpression_In: LogicalORExpression_In; + +ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +ConditionalExpression_In: LogicalORExpression_In T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; + } break; ./ -EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; +AssignmentExpression: ConditionalExpression; +AssignmentExpression_In: ConditionalExpression_In; + +AssignmentExpression: YieldExpression; +AssignmentExpression_In: YieldExpression_In; + +AssignmentExpression: ArrowFunction; +AssignmentExpression_In: ArrowFunction_In; + +-- ### Use AssignmentPattern in some cases for LHSexpression +AssignmentExpression: LeftHandSideExpression T_EQ AssignmentExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +AssignmentExpression_In: LeftHandSideExpression T_EQ AssignmentExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Assign, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; +AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +AssignmentExpression_In: LeftHandSideExpression AssignmentOperator AssignmentExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; ./ -BitwiseANDExpression: EqualityExpression ; - -BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; +AssignmentOperator: T_STAR_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceMul; + } break; ./ -BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; - -BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; +AssignmentOperator: T_DIVIDE_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceDiv; + } break; ./ -BitwiseXORExpression: BitwiseANDExpression ; - -BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; +AssignmentOperator: T_REMAINDER_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceMod; + } break; ./ -BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; - -BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; +AssignmentOperator: T_PLUS_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceAdd; + } break; ./ -BitwiseORExpression: BitwiseXORExpression ; - -BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; +AssignmentOperator: T_MINUS_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceSub; + } break; ./ -BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; - -BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; +AssignmentOperator: T_LT_LT_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceLeftShift; + } break; ./ -LogicalANDExpression: BitwiseORExpression ; - -LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; +AssignmentOperator: T_GT_GT_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceRightShift; + } break; ./ -LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; +AssignmentOperator: T_GT_GT_GT_EQ; +/. + case $rule_number: { + sym(1).ival = QSOperator::InplaceURightShift; + } break; +./ -LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; +AssignmentOperator: T_AND_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceAnd; + } break; ./ -LogicalORExpression: LogicalANDExpression ; +AssignmentOperator: T_XOR_EQ; +/. + case $rule_number: { + sym(1).ival = QSOperator::InplaceXor; + } break; +./ -LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; +AssignmentOperator: T_OR_EQ; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).ival = QSOperator::InplaceOr; + } break; ./ -LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; +Expression: AssignmentExpression; +Expression_In: AssignmentExpression_In; -LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; +Expression: Expression T_COMMA AssignmentExpression; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Expression_In: Expression_In T_COMMA AssignmentExpression_In; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -ConditionalExpression: LogicalORExpression ; - -ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; +ExpressionOpt: ; +/. case $rule_number: Q_FALLTHROUGH(); ./ +ExpressionOpt_In: ; /. -case $rule_number: { - AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -ConditionalExpressionNotIn: LogicalORExpressionNotIn ; +ExpressionOpt: Expression; +ExpressionOpt_In: Expression_In; + +-- Statements -ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; +Statement: ExpressionStatementLookahead T_FORCE_BLOCK BlockStatement; /. -case $rule_number: { - AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(3).Node; + } break; ./ -AssignmentExpression: ConditionalExpression ; - -AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; +Statement: ExpressionStatementLookahead VariableStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead EmptyStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead ExpressionStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead IfStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead BreakableStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead ContinueStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead BreakStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead ReturnStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead WithStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead LabelledStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead ThrowStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead TryStatement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +Statement: ExpressionStatementLookahead DebuggerStatement; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(2).Node; + } break; ./ -AssignmentExpressionNotIn: ConditionalExpressionNotIn ; +Declaration: HoistableDeclaration; +Declaration: ClassDeclaration; +Declaration: LexicalDeclaration_In; + +HoistableDeclaration: FunctionDeclaration; +HoistableDeclaration: GeneratorDeclaration; -AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; +HoistableDeclaration_Default: FunctionDeclaration_Default; +HoistableDeclaration_Default: GeneratorDeclaration_Default; + +BreakableStatement: IterationStatement; +BreakableStatement: SwitchStatement; + +BlockStatement: Block; + +Block: T_LBRACE StatementListOpt T_RBRACE; /. -case $rule_number: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::Block *node = new (pool) AST::Block(sym(2).StatementList); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; + } break; ./ -AssignmentOperator: T_EQ ; +StatementList: StatementListItem; + +StatementList: StatementList StatementListItem; /. -case $rule_number: { - sym(1).ival = QSOperator::Assign; -} break; + case $rule_number: { + sym(1).StatementList = sym(1).StatementList->append(sym(2).StatementList); + } break; ./ -AssignmentOperator: T_STAR_EQ ; +StatementListItem: Statement; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceMul; -} break; + case $rule_number: { + sym(1).StatementList = new (pool) AST::StatementList(sym(1).Statement); + } break; ./ -AssignmentOperator: T_DIVIDE_EQ ; +StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration T_AUTOMATIC_SEMICOLON; +StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration T_SEMICOLON; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceDiv; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::StatementList(sym(3).FunctionDeclaration); + } break; ./ -AssignmentOperator: T_REMAINDER_EQ ; +StatementListOpt: ; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceMod; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -AssignmentOperator: T_PLUS_EQ ; +StatementListOpt: StatementList; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceAdd; -} break; + case $rule_number: { + sym(1).Node = sym(1).StatementList->finish(); + } break; ./ -AssignmentOperator: T_MINUS_EQ ; +LetOrConst: T_LET; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceSub; -} break; + case $rule_number: { + sym(1).ival = AST::VariableDeclaration::BlockScope; + } break; ./ - -AssignmentOperator: T_LT_LT_EQ ; +LetOrConst: T_CONST; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceLeftShift; -} break; + case $rule_number: { + sym(1).ival = AST::VariableDeclaration::ReadOnlyBlockScope; + } break; ./ -AssignmentOperator: T_GT_GT_EQ ; +Var: T_VAR; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceRightShift; -} break; + case $rule_number: { + sym(1).ival = AST::VariableDeclaration::FunctionScope; + } break; ./ -AssignmentOperator: T_GT_GT_GT_EQ ; +LexicalDeclaration: LetOrConst BindingList; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LexicalDeclaration_In: LetOrConst BindingList_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VarDeclaration: Var VariableDeclarationList; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VarDeclaration_In: Var VariableDeclarationList_In; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceURightShift; -} break; + case $rule_number: { + AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::VariableScope(sym(1).ival); + AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s)); + node->declarationKindToken = loc(1); + sym(1).Node = node; + } break; ./ -AssignmentOperator: T_AND_EQ ; +VariableStatement: VarDeclaration_In T_AUTOMATIC_SEMICOLON; +VariableStatement: VarDeclaration_In T_SEMICOLON; + +BindingList: LexicalBinding_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +BindingList_In: LexicalBinding_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclarationList: VariableDeclaration; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclarationList_In: VariableDeclaration_In; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceAnd; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); + } break; ./ -AssignmentOperator: T_XOR_EQ ; +BindingList: BindingList T_COMMA LexicalBinding; +/. case $rule_number: Q_FALLTHROUGH(); ./ +BindingList_In: BindingList_In T_COMMA LexicalBinding_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclarationList_In: VariableDeclarationList_In T_COMMA VariableDeclaration_In; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceXor; -} break; + case $rule_number: { + AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + node->commaToken = loc(2); + sym(1).Node = node; + } break; ./ -AssignmentOperator: T_OR_EQ ; +LexicalBinding: BindingIdentifier InitializerOpt; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LexicalBinding_In: BindingIdentifier InitializerOpt_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclaration: BindingIdentifier InitializerOpt; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclaration_In: BindingIdentifier InitializerOpt_In; /. -case $rule_number: { - sym(1).ival = QSOperator::InplaceOr; -} break; + case $rule_number: { + AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; + AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -Expression: AssignmentExpression ; +LexicalBinding: BindingPattern Initializer; +/. case $rule_number: Q_FALLTHROUGH(); ./ +LexicalBinding_In: BindingPattern Initializer_In; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclaration: BindingPattern InitializerOpt; +/. case $rule_number: Q_FALLTHROUGH(); ./ +VariableDeclaration_In: BindingPattern Initializer_In; +/. case $rule_number: { UNIMPLEMENTED; } ./ -Expression: Expression T_COMMA AssignmentExpression ; +BindingPattern: T_LBRACE ObjectBindingPattern T_RBRACE; /. -case $rule_number: { - AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + auto *node = new (pool) AST::ObjectBindingPattern(sym(2).BindingPropertyList); + node->first = loc(1); + node->last = loc(3); + sym(1).Node = node; + } break; ./ -ExpressionOpt: ; +BindingPattern: T_LBRACKET ArrayBindingPattern T_RBRACKET; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + auto *node = new (pool) AST::ArrayBindingPattern(sym(2).BindingElementList); + node->first = loc(1); + node->last = loc(3); + sym(1).Node = node; + } break; ./ -ExpressionOpt: Expression ; - -ExpressionNotIn: AssignmentExpressionNotIn ; - -ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; +ObjectBindingPattern: ; /. -case $rule_number: { - AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -ExpressionNotInOpt: ; +ObjectBindingPattern: BindingPropertyList; +/. case $rule_number: ./ +ObjectBindingPattern: BindingPropertyList T_COMMA; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + sym(1).Node = sym(1).BindingPropertyList->finish(); + } break; ./ -ExpressionNotInOpt: ExpressionNotIn ; - -Statement: Block ; -Statement: VariableStatement ; -Statement: EmptyStatement ; -Statement: ExpressionStatement ; -Statement: IfStatement ; -Statement: IterationStatement ; -Statement: ContinueStatement ; -Statement: BreakStatement ; -Statement: ReturnStatement ; -Statement: WithStatement ; -Statement: LabelledStatement ; -Statement: SwitchStatement ; -Statement: ThrowStatement ; -Statement: TryStatement ; -Statement: DebuggerStatement ; - - -Block: T_LBRACE StatementListOpt T_RBRACE ; +ArrayBindingPattern: ElisionOpt BindingRestElementOpt; /. -case $rule_number: { - AST::Block *node = new (pool) AST::Block(sym(2).StatementList); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + if (sym(3).Elision || sym(4).Node) { + auto *l = new (pool) AST::BindingElementList(sym(1).Elision, sym(2).Node); + sym(1).Node = l->finish(); + } else { + sym(1).Node = nullptr; + } + } break; ./ -StatementList: Statement ; +ArrayBindingPattern: BindingElementList; /. -case $rule_number: { - sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); -} break; + case $rule_number: { + sym(1).Node = sym(1).BindingElementList->finish(); + } break; ./ -StatementList: StatementList Statement ; +ArrayBindingPattern: BindingElementList T_COMMA ElisionOpt BindingRestElementOpt; /. -case $rule_number: { - sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); -} break; + case $rule_number: { + if (sym(3).Elision || sym(4).Node) { + auto *l = new (pool) AST::BindingElementList(sym(3).Elision, sym(4).Node); + l = sym(1).BindingElementList->append(l); + sym(1).Node = l; + } + sym(1).Node = sym(1).BindingElementList->finish(); + } break; ./ -StatementListOpt: ; +BindingPropertyList: BindingProperty; + +BindingPropertyList: BindingPropertyList T_COMMA BindingProperty; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + sym(1).Node = sym(1).BindingPropertyList->append(sym(3).BindingPropertyList); + } break; ./ -StatementListOpt: StatementList ; +BindingElementList: BindingElisionElement; + +BindingElementList: BindingElementList T_COMMA BindingElisionElement; /. -case $rule_number: { - sym(1).Node = sym(1).StatementList->finish (); -} break; + case $rule_number: { + sym(1).BindingElementList->append(sym(3).BindingElementList); + } break; ./ -VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; +BindingElisionElement: ElisionOpt BindingElement; /. -case $rule_number: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - if (sym(1).ival == T_LET) - s = AST::VariableDeclaration::BlockScope; - else if (sym(1).ival == T_CONST) - s = AST::VariableDeclaration::ReadOnlyBlockScope; - - AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s)); - node->declarationKindToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::BindingElementList(sym(1).Elision, sym(2).BindingElement); + } break; ./ -VariableDeclarationKind: T_LET ; + +BindingProperty: BindingIdentifier InitializerOpt_In; /. -case $rule_number: { - sym(1).ival = T_LET; -} break; + case $rule_number: { + AST::StringLiteralPropertyName *name = new (pool) AST::StringLiteralPropertyName(stringRef(1)); + AST::BindingElement *e = new (pool) AST::BindingElement(stringRef(1), sym(2).Expression); + AST::BindingPropertyList *node = new (pool) AST::BindingPropertyList(name, e); + sym(1).Node = node; + } break; ./ -VariableDeclarationKind: T_CONST ; +BindingProperty: PropertyName T_COLON BindingElement; /. -case $rule_number: { - sym(1).ival = T_CONST; -} break; + case $rule_number: { + AST::BindingPropertyList *node = new (pool) AST::BindingPropertyList(sym(1).PropertyName, sym(3).BindingElement); + sym(1).Node = node; + } break; ./ -VariableDeclarationKind: T_VAR ; +BindingElement: BindingIdentifier InitializerOpt_In; /. -case $rule_number: { - sym(1).ival = T_VAR; -} break; + case $rule_number: { + AST::BindingElement *node = new (pool) AST::BindingElement(stringRef(1), sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -VariableDeclarationList: VariableDeclaration ; +BindingElement: BindingPattern InitializerOpt_In; /. -case $rule_number: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); -} break; + case $rule_number: { + AST::BindingElement *node = new (pool) AST::BindingElement(sym(1).BindingPattern, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; + } break; ./ -VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; +BindingRestElement: T_ELLIPSIS BindingIdentifier; /. -case $rule_number: { - AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( - sym(1).VariableDeclarationList, sym(3).VariableDeclaration); - node->commaToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BindingRestElement *node = new (pool) AST::BindingRestElement(stringRef(2)); + node->identifierToken = loc(2); + sym(1).Node = node; + } break; ./ -VariableDeclarationListNotIn: VariableDeclarationNotIn ; +BindingRestElement: T_ELLIPSIS BindingPattern; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +BindingRestElementOpt: ; /. -case $rule_number: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; +BindingRestElementOpt: BindingRestElement; + + +EmptyStatement: T_SEMICOLON; /. -case $rule_number: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); -} break; + case $rule_number: { + AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); + node->semicolonToken = loc(1); + sym(1).Node = node; + } break; ./ -VariableDeclaration: JsIdentifier InitialiserOpt ; +-- Spec says it should have a "[lookahead ∉ { {, function, class, let [ }]" before the Expression statement. +-- This is implemented with the rule below that is run before any statement and inserts a T_EXPRESSION_STATEMENT_OK +-- token if it's ok to parse as an expression statement. +ExpressionStatementLookahead: ; +/: +#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE $rule_number +:/ /. -case $rule_number: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + int token = lookaheadToken(lexer); + if (token == T_LBRACE) + pushToken(T_FORCE_BLOCK); + else if (token == T_FUNCTION || token == T_CLASS || token == T_LET || token == T_CONST) + pushToken(T_FORCE_DECLARATION); + } break; +./ + +ExpressionStatement: Expression_In T_AUTOMATIC_SEMICOLON; +ExpressionStatement: Expression_In T_SEMICOLON; +/. + case $rule_number: { + AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; + } break; ./ - -VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; + +IfStatement: T_IF T_LPAREN Expression_In T_RPAREN Statement T_ELSE Statement; +/. + case $rule_number: { + AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->elseToken = loc(6); + sym(1).Node = node; + } break; +./ + +IfStatement: T_IF T_LPAREN Expression_In T_RPAREN Statement; /. -case $rule_number: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; +./ + + +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_AUTOMATIC_SEMICOLON; +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_COMPATIBILITY_SEMICOLON; -- for JSC/V8 compatibility +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_SEMICOLON; +/. + case $rule_number: { + AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); + node->doToken = loc(1); + node->whileToken = loc(3); + node->lparenToken = loc(4); + node->rparenToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; + } break; ./ -Initialiser: T_EQ AssignmentExpression ; +IterationStatement: T_WHILE T_LPAREN Expression_In T_RPAREN Statement; /. -case $rule_number: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; + case $rule_number: { + AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); + node->whileToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; ./ -InitialiserOpt: ; +IterationStatement: T_FOR T_LPAREN ExpressionOpt T_SEMICOLON ExpressionOpt_In T_SEMICOLON ExpressionOpt_In T_RPAREN Statement; -- [lookahead != { let [ }] /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->firstSemicolonToken = loc(4); + node->secondSemicolonToken = loc(6); + node->rparenToken = loc(8); + sym(1).Node = node; + } break; ./ -InitialiserOpt: Initialiser ; +IterationStatement: T_FOR T_LPAREN VarDeclaration T_SEMICOLON ExpressionOpt_In T_SEMICOLON ExpressionOpt_In T_RPAREN Statement; +/. case $rule_number: Q_FALLTHROUGH(); ./ +IterationStatement: T_FOR T_LPAREN LexicalDeclaration T_SEMICOLON ExpressionOpt_In T_SEMICOLON ExpressionOpt_In T_RPAREN Statement; +/. + case $rule_number: { + // ### get rid of the static_cast! + AST::LocalForStatement *node = new (pool) AST::LocalForStatement( + static_cast<AST::VariableStatement *>(sym(3).Node)->declarations, sym(5).Expression, + sym(7).Expression, sym(9).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->firstSemicolonToken = loc(4); + node->secondSemicolonToken = loc(6); + node->rparenToken = loc(8); + sym(1).Node = node; + } break; +./ -InitialiserNotIn: T_EQ AssignmentExpressionNotIn ; +IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression_In T_RPAREN Statement; /. -case $rule_number: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; + case $rule_number: { + AST::ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->inToken = loc(4); + node->rparenToken = loc(6); + sym(1).Node = node; + } break; ./ -InitialiserNotInOpt: ; +IterationStatement: T_FOR T_LPAREN ForDeclaration T_IN Expression_In T_RPAREN Statement; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement(sym(3).VariableDeclaration, sym(5).Expression, sym(7).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->inToken = loc(4); + node->rparenToken = loc(6); + sym(1).Node = node; + } break; ./ -InitialiserNotInOpt: InitialiserNotIn ; -EmptyStatement: T_SEMICOLON ; +IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_OF AssignmentExpression_In T_RPAREN Statement; -- [lookahead ≠let] +/. case $rule_number: { UNIMPLEMENTED; } ./ +IterationStatement: T_FOR T_LPAREN ForDeclaration T_OF Expression_In T_RPAREN Statement; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +ForDeclaration: LetOrConst ForBinding; +/. case $rule_number: Q_FALLTHROUGH(); ./ +ForDeclaration: Var ForBinding; /. -case $rule_number: { - AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); - node->semicolonToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::VariableScope(sym(1).ival); + auto *node = new (pool) AST::VariableDeclaration(stringRef(2), nullptr, s); + node->identifierToken = loc(2); + sym(1).Node = node; + } break; ./ - -ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ExpressionStatement: Expression T_SEMICOLON ; + +ForBinding: BindingIdentifier; + +ForBinding: BindingPattern; +/. case $rule_number: UNIMPLEMENTED; ./ + +ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON; +ContinueStatement: T_CONTINUE T_SEMICOLON; /. -case $rule_number: { - AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); + node->continueToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; + } break; ./ -IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; +ContinueStatement: T_CONTINUE IdentifierReference T_AUTOMATIC_SEMICOLON; +ContinueStatement: T_CONTINUE IdentifierReference T_SEMICOLON; /. -case $rule_number: { - AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - node->elseToken = loc(6); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); + node->continueToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; + } break; ./ - -IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; + +BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON; +BreakStatement: T_BREAK T_SEMICOLON; /. -case $rule_number: { - AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); + node->breakToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; + } break; ./ - -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_COMPATIBILITY_SEMICOLON ; -- for JSC/V8 compatibility -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; +BreakStatement: T_BREAK IdentifierReference T_AUTOMATIC_SEMICOLON; +BreakStatement: T_BREAK IdentifierReference T_SEMICOLON; /. -case $rule_number: { - AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); - node->doToken = loc(1); - node->whileToken = loc(3); - node->lparenToken = loc(4); - node->rparenToken = loc(6); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; + case $rule_number: { + AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); + node->breakToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; + } break; ./ -IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; +ReturnStatement: T_RETURN ExpressionOpt_In T_AUTOMATIC_SEMICOLON; +ReturnStatement: T_RETURN ExpressionOpt_In T_SEMICOLON; /. -case $rule_number: { - AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); - node->whileToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + if (!functionNestingLevel) { + syntaxError(loc(1), "Return statement not allowed outside of Function declaration."); + return false; + } + AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); + node->returnToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; + } break; ./ -IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; +WithStatement: T_WITH T_LPAREN Expression_In T_RPAREN Statement; /. -case $rule_number: { - AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, - sym(5).Expression, sym(7).Expression, sym(9).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->firstSemicolonToken = loc(4); - node->secondSemicolonToken = loc(6); - node->rparenToken = loc(8); - sym(1).Node = node; -} break; + case $rule_number: { + AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); + node->withToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; ./ -IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; +SwitchStatement: T_SWITCH T_LPAREN Expression_In T_RPAREN CaseBlock; /. -case $rule_number: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - AST::LocalForStatement *node = new (pool) AST::LocalForStatement( - sym(4).VariableDeclarationList->finish(s), sym(6).Expression, - sym(8).Expression, sym(10).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->firstSemicolonToken = loc(5); - node->secondSemicolonToken = loc(7); - node->rparenToken = loc(9); - sym(1).Node = node; -} break; + case $rule_number: { + AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); + node->switchToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; ./ -IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; +CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE; /. -case $rule_number: { - AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, - sym(5).Expression, sym(7).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->inToken = loc(4); - node->rparenToken = loc(6); - sym(1).Node = node; -} break; + case $rule_number: { + AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; + } break; ./ -IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; +CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE; /. -case $rule_number: { - AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( - sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->inToken = loc(5); - node->rparenToken = loc(7); - sym(1).Node = node; -} break; + case $rule_number: { + AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(5); + sym(1).Node = node; + } break; ./ -ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ContinueStatement: T_CONTINUE T_SEMICOLON ; +CaseClauses: CaseClause; /. -case $rule_number: { - AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); - node->continueToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); + } break; ./ -ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; +CaseClauses: CaseClauses CaseClause; /. -case $rule_number: { - AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); - node->continueToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); + } break; ./ -BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -BreakStatement: T_BREAK T_SEMICOLON ; +CaseClausesOpt: ; /. -case $rule_number: { - AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); - node->breakToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; +CaseClausesOpt: CaseClauses; /. -case $rule_number: { - AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); - node->breakToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(1).CaseClauses->finish(); + } break; ./ -ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; +CaseClause: T_CASE Expression_In T_COLON StatementListOpt; /. -case $rule_number: { - AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); - node->returnToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); + node->caseToken = loc(1); + node->colonToken = loc(3); + sym(1).Node = node; + } break; ./ -WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; +DefaultClause: T_DEFAULT T_COLON StatementListOpt; /. -case $rule_number: { - AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); - node->withToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); + node->defaultToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; + } break; ./ -SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; +LabelledStatement: IdentifierReference T_COLON LabelledItem; /. -case $rule_number: { - AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); - node->switchToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; + } break; ./ -CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; +LabelledItem: Statement; + +LabelledItem: ExpressionStatementLookahead T_FORCE_DECLARATION FunctionDeclaration; /. -case $rule_number: { - AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + syntaxError(loc(3), "FunctionDeclarations are not allowed after a label."); + return false; + } break; ./ -CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; +ThrowStatement: T_THROW Expression_In T_AUTOMATIC_SEMICOLON; +ThrowStatement: T_THROW Expression_In T_SEMICOLON; /. -case $rule_number: { - AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(5); - sym(1).Node = node; -} break; + case $rule_number: { + AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); + node->throwToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; + } break; ./ -CaseClauses: CaseClause ; +TryStatement: T_TRY Block Catch; /. -case $rule_number: { - sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); -} break; + case $rule_number: { + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); + node->tryToken = loc(1); + sym(1).Node = node; + } break; ./ -CaseClauses: CaseClauses CaseClause ; +TryStatement: T_TRY Block Finally; /. -case $rule_number: { - sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); -} break; + case $rule_number: { + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); + node->tryToken = loc(1); + sym(1).Node = node; + } break; ./ -CaseClausesOpt: ; +TryStatement: T_TRY Block Catch Finally; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); + node->tryToken = loc(1); + sym(1).Node = node; + } break; ./ -CaseClausesOpt: CaseClauses ; +Catch: T_CATCH T_LPAREN CatchParameter T_RPAREN Block; /. -case $rule_number: { - sym(1).Node = sym(1).CaseClauses->finish (); -} break; + case $rule_number: { + AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); + node->catchToken = loc(1); + node->lparenToken = loc(2); + node->identifierToken = loc(3); + node->rparenToken = loc(4); + sym(1).Node = node; + } break; ./ -CaseClause: T_CASE Expression T_COLON StatementListOpt ; +Finally: T_FINALLY Block; /. -case $rule_number: { - AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); - node->caseToken = loc(1); - node->colonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::Finally *node = new (pool) AST::Finally(sym(2).Block); + node->finallyToken = loc(1); + sym(1).Node = node; + } break; ./ -DefaultClause: T_DEFAULT T_COLON StatementListOpt ; +CatchParameter: BindingIdentifier; +CatchParameter: BindingPattern; + +DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON; -- automatic semicolon +DebuggerStatement: T_DEBUGGER T_SEMICOLON; /. -case $rule_number: { - AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); - node->defaultToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); + node->debuggerToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; + } break; ./ -LabelledStatement: JsIdentifier T_COLON Statement ; +-- tell the parser to prefer function declarations to function expressions. +-- That is, the `Function' symbol is used to mark the start of a function +-- declaration. +-- This is still required for parsing QML, where MemberExpression and FunctionDeclaration would +-- otherwise conflict. +Function: T_FUNCTION %prec REDUCE_HERE; + +FunctionDeclaration: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. -case $rule_number: { - AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); - node->identifierToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList); + node->functionToken = loc(1); + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; + } break; ./ -ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -ThrowStatement: T_THROW Expression T_SEMICOLON ; + +FunctionDeclaration_Default: FunctionDeclaration; +FunctionDeclaration_Default: T_FUNCTION T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. -case $rule_number: { - AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); - node->throwToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList); + node->functionToken = loc(1); + node->identifierToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->lbraceToken = loc(5); + node->rbraceToken = loc(7); + sym(1).Node = node; + } break; ./ -TryStatement: T_TRY Block Catch ; +FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. -case $rule_number: { - AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); - node->tryToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList); + node->functionToken = loc(1); + if (! stringRef(2).isNull()) + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; + } break; ./ -TryStatement: T_TRY Block Finally ; +FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. -case $rule_number: { - AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList); + node->functionToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->lbraceToken = loc(5); + node->rbraceToken = loc(7); + sym(1).Node = node; + } break; ./ -TryStatement: T_TRY Block Catch Finally ; +StrictFormalParameters: FormalParameters; + +FormalParameters: ; /. -case $rule_number: { - AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; +FormalParameters: FormalParameterList; /. -case $rule_number: { - AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); - node->catchToken = loc(1); - node->lparenToken = loc(2); - node->identifierToken = loc(3); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; + case $rule_number: { + sym(1).Node = sym(1).FormalParameterList->finish(); + } break; ./ -Finally: T_FINALLY Block ; +FormalsList: BindingElement; +/. case $rule_number: ./ + +FormalParameterList: BindingRestElement; /. -case $rule_number: { - AST::Finally *node = new (pool) AST::Finally(sym(2).Block); - node->finallyToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FormalParameterList *node = new (pool) AST::FormalParameterList(nullptr, sym(1).Node); + sym(1).Node = node; + } break; ./ -DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon -DebuggerStatement: T_DEBUGGER T_SEMICOLON ; +FormalParameterList: FormalsList; + +FormalParameterList: FormalsList T_COMMA BindingRestElement; +/. case $rule_number: ./ + +FormalsList: FormalsList T_COMMA BindingElement; /. -case $rule_number: { - AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); - node->debuggerToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; + case $rule_number: { + AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, sym(3).Node); + sym(1).Node = node; + } break; ./ --- tell the parser to prefer function declarations to function expressions. --- That is, the `Function' symbol is used to mark the start of a function --- declaration. -Function: T_FUNCTION %prec REDUCE_HERE ; +FormalParameter: BindingElement; -FunctionDeclaration: Function JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +FunctionLBrace: T_LBRACE; /. -case $rule_number: { - AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; + case $rule_number: { + ++functionNestingLevel; + } break; ./ -FunctionExpression: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +FunctionRBrace: T_RBRACE; /. -case $rule_number: { - AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - if (! stringRef(2).isNull()) - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; + case $rule_number: { + --functionNestingLevel; + } break; ./ -FunctionExpression: T_FUNCTION T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; + +FunctionBody: FunctionStatementList; +FunctionStatementList: StatementListOpt; + +ArrowFunction: ArrowParameters T_ARROW ConciseBody; +/. case $rule_number: { UNIMPLEMENTED; } ./ +ArrowFunction_In: ArrowParameters T_ARROW ConciseBody_In; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +ArrowParameters: BindingIdentifier; + +ArrowParameters: CoverParenthesizedExpressionAndArrowParameterList; + +-- ### CoverParenthesizedExpressionAndArrowParameterList for ArrowParameters refined to: +-- ArrowFormalParameters[Yield]: (StrictFormalParameters[?Yield]) + +ConciseBodyLookahead: ; +/: +#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE $rule_number +:/ /. -case $rule_number: { - AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody); - node->functionToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - node->lbraceToken = loc(5); - node->rbraceToken = loc(7); - sym(1).Node = node; -} break; + case $rule_number: { + if (lookaheadToken(lexer) == T_LBRACE) + pushToken(T_FORCE_BLOCK); + } break; ./ -FormalParameterList: JsIdentifier ; +ConciseBody: ConciseBodyLookahead AssignmentExpression; -- [lookahead ≠{] +ConciseBody_In: ConciseBodyLookahead AssignmentExpression_In; -- [lookahead ≠{] +ConciseBody: ConciseBodyLookahead T_FORCE_BLOCK FunctionLBrace FunctionBody FunctionRBrace; +ConciseBody_In: ConciseBodyLookahead T_FORCE_BLOCK FunctionLBrace FunctionBody FunctionRBrace; + +MethodDefinition: PropertyName T_LPAREN StrictFormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +MethodDefinition: GeneratorMethod; + +MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. -case $rule_number: { - AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter(sym(2).PropertyName, sym(6).StatementList); + node->getSetToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(4); + node->lbraceToken = loc(5); + node->rbraceToken = loc(7); + sym(1).Node = node; + } break; ./ -FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; +MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN FunctionLBrace FunctionBody FunctionRBrace; /. -case $rule_number: { - AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); - node->commaToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; + case $rule_number: { + AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( + sym(2).PropertyName, sym(4).FormalParameterList, sym(7).StatementList); + node->getSetToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; + } break; ./ -FormalParameterListOpt: ; + +PropertySetParameterList: FormalParameter; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + AST::FormalParameterList *node = (new (pool) AST::FormalParameterList(nullptr, sym(1).Node))->finish(); + sym(1).Node = node; + } break; ./ -FormalParameterListOpt: FormalParameterList ; +GeneratorLBrace: T_LBRACE; /. -case $rule_number: { - sym(1).Node = sym(1).FormalParameterList->finish (); -} break; + case $rule_number: { + ++functionNestingLevel; + lexer->enterGeneratorBody(); + } break; ./ -FunctionBodyOpt: ; +GeneratorRBrace: T_RBRACE; /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + --functionNestingLevel; + lexer->leaveGeneratorBody(); + } break; ./ -FunctionBodyOpt: FunctionBody ; +GeneratorMethod: T_STAR PropertyName T_LPAREN StrictFormalParameters T_RPAREN GeneratorLBrace GeneratorBody GeneratorRBrace; +/. case $rule_number: { UNIMPLEMENTED; } ./ -FunctionBody: SourceElements ; -/. -case $rule_number: { - sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); -} break; -./ +GeneratorDeclaration: T_FUNCTION T_STAR BindingIdentifier T_LPAREN FormalParameters T_RPAREN GeneratorLBrace GeneratorBody GeneratorRBrace; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +GeneratorDeclaration_Default: GeneratorDeclaration; +GeneratorDeclaration_Default: T_FUNCTION T_STAR T_LPAREN FormalParameters T_RPAREN GeneratorLBrace GeneratorBody GeneratorRBrace; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +GeneratorExpression: T_FUNCTION T_STAR BindingIdentifier T_LPAREN FormalParameters T_RPAREN GeneratorLBrace GeneratorBody GeneratorRBrace; +/. case $rule_number: { UNIMPLEMENTED; } ./ +GeneratorExpression: T_FUNCTION T_STAR T_LPAREN FormalParameters T_RPAREN GeneratorLBrace GeneratorBody GeneratorRBrace; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +GeneratorBody: FunctionBody; -Program: Empty ; +YieldExpression: T_YIELD T_STAR AssignmentExpression; +YieldExpression_In: T_YIELD T_STAR AssignmentExpression_In; +YieldExpression: T_YIELD AssignmentExpression; +YieldExpression_In: T_YIELD AssignmentExpression_In; -Program: SourceElements ; + +ClassDeclaration: T_CLASS BindingIdentifier ClassTail; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +ClassDeclaration_Default: ClassDeclaration; +ClassDeclaration_Default: T_CLASS ClassTail; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +ClassExpression: T_CLASS BindingIdentifier ClassTail; + +ClassExpression: T_CLASS ClassTail; + +ClassLBrace: T_LBRACE; /. -case $rule_number: { - sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); -} break; + case $rule_number: { + lexer->setStaticIsKeyword(true); + } break; ./ -SourceElements: SourceElement ; +ClassRBrace: T_RBRACE; +/. case $rule_number: ./ +ClassStaticQualifier: T_STATIC; /. -case $rule_number: { - sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); -} break; + case $rule_number: { + lexer->setStaticIsKeyword(false); + } break; ./ -SourceElements: SourceElements SourceElement ; +ClassTail: ClassLBrace ClassBodyOpt ClassRBrace; +ClassTail: ClassHeritage ClassLBrace ClassBodyOpt ClassRBrace; + +ClassHeritage: T_EXTENDS LeftHandSideExpression; + +ClassBody: ClassElementList; + +ClassBodyOpt: ; + +ClassBodyOpt: ClassBody; + +ClassElementList: ClassElement; +ClassElementList: ClassElementList ClassElement; + +ClassElement: MethodDefinition; + +ClassElement: ClassStaticQualifier MethodDefinition; /. -case $rule_number: { - sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); -} break; + case $rule_number: { + lexer->setStaticIsKeyword(true); + } break; ./ -SourceElement: Statement ; +ClassElement: T_SEMICOLON; + +-- Scripts and Modules + +Script: ; /. -case $rule_number: { - sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); -} break; + case $rule_number: { + sym(1).Node = nullptr; + } break; ./ -SourceElement: FunctionDeclaration ; +Script: ScriptBody; + +ScriptBody: StatementList; /. -case $rule_number: { - sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); -} break; + case $rule_number: { + sym(1).Node = new (pool) AST::Program(sym(1).StatementList->finish()); + } break; ./ -PropertyAssignmentListOpt: ; +Module: ModuleBodyOpt; +/. case $rule_number: { UNIMPLEMENTED; } ./ + +ModuleBody: ModuleItemList; + +ModuleBodyOpt: ; +ModuleBodyOpt: ModuleBody; + +ModuleItemList: ModuleItem; +ModuleItemList: ModuleItemList ModuleItem; + +ModuleItem: ImportDeclaration T_AUTOMATIC_SEMICOLON; +ModuleItem: ImportDeclaration T_SEMICOLON; +ModuleItem: ExportDeclaration T_AUTOMATIC_SEMICOLON; +ModuleItem: ExportDeclaration T_SEMICOLON; +ModuleItem: StatementListItem; + +ImportDeclaration: T_IMPORT ImportClause FromClause; +ImportDeclaration: T_IMPORT ModuleSpecifier; + +ImportClause: ImportedDefaultBinding; +ImportClause: NameSpaceImport; +ImportClause: NamedImports; +ImportClause: ImportedDefaultBinding T_COMMA NameSpaceImport; +ImportClause: ImportedDefaultBinding T_COMMA NamedImports; + +ImportedDefaultBinding: ImportedBinding; + +NameSpaceImport: T_STAR T_AS ImportedBinding; + +NamedImports: T_LBRACE T_RBRACE; +NamedImports: T_LBRACE ImportsList T_RBRACE; +NamedImports: T_LBRACE ImportsList T_COMMA T_RBRACE; + +FromClause: T_FROM ModuleSpecifier; + +ImportsList: ImportSpecifier; +ImportsList: ImportsList T_COMMA ImportSpecifier; + +ImportSpecifier: ImportedBinding; +ImportSpecifier: IdentifierName T_AS ImportedBinding; + +ModuleSpecifier: T_STRING_LITERAL; + +ImportedBinding: BindingIdentifier; + +ExportDeclarationLookahead: ; +/: +#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE $rule_number +:/ /. -case $rule_number: { - sym(1).Node = 0; -} break; + case $rule_number: { + int token = lookaheadToken(lexer); + if (token == T_FUNCTION || token == T_CLASS) + pushToken(T_FORCE_DECLARATION); + } break; ./ -PropertyAssignmentListOpt: PropertyAssignmentList ; +ExportDeclaration: T_EXPORT T_STAR FromClause; +ExportDeclaration: T_EXPORT ExportClause FromClause; +ExportDeclaration: T_EXPORT ExportClause; +ExportDeclaration: T_EXPORT VariableStatement; +ExportDeclaration: T_EXPORT Declaration; +ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead T_FORCE_DECLARATION HoistableDeclaration_Default; +ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead T_FORCE_DECLARATION ClassDeclaration_Default; +ExportDeclaration: T_EXPORT T_DEFAULT ExportDeclarationLookahead AssignmentExpression_In; -- [lookahead ∉ { function, class }] + +ExportClause: T_LBRACE T_RBRACE; +ExportClause: T_LBRACE ExportsList T_RBRACE; +ExportClause: T_LBRACE ExportsList T_COMMA T_RBRACE; + +ExportsList: ExportSpecifier; +ExportsList: ExportsList T_COMMA ExportSpecifier; + +ExportSpecifier: IdentifierName; +ExportSpecifier: IdentifierName T_AS IdentifierName; + +-- Old top level code /. + // ------------ end of switch statement } // switch action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); } // if @@ -3260,8 +3720,7 @@ PropertyAssignmentListOpt: PropertyAssignmentList ; for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || - tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || - tk == T_FEED_JS_SOURCE_ELEMENT) + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) continue; int a = t_action(errorState, tk); diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 34657a7d48..f78e48e66a 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -155,6 +155,16 @@ void StringLiteral::accept0(Visitor *visitor) visitor->endVisit(this); } +void TemplateLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + if (next) + accept(next, visitor); + } + + visitor->endVisit(this); +} + void NumericLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { @@ -232,10 +242,10 @@ void PropertyGetterSetter::accept0(Visitor *visitor) visitor->endVisit(this); } -void PropertyAssignmentList::accept0(Visitor *visitor) +void PropertyDefinitionList::accept0(Visitor *visitor) { if (visitor->visit(this)) { - for (PropertyAssignmentList *it = this; it; it = it->next) { + for (PropertyDefinitionList *it = this; it; it = it->next) { accept(it->assignment, visitor); } } @@ -752,57 +762,71 @@ void FunctionExpression::accept0(Visitor *visitor) visitor->endVisit(this); } -void FormalParameterList::accept0(Visitor *visitor) +QStringList FormalParameterList::formals() const { - if (visitor->visit(this)) { - // ### + QStringList formals; + int i = 0; + for (const FormalParameterList *it = this; it; it = it->next) { + QString name; + if (QQmlJS::AST::BindingElement *b = it->bindingElement()) { + name = b->name; + } else if (QQmlJS::AST::BindingRestElement *r = it->bindingRestElement()) { + name = r->name.toString(); + } + int duplicateIndex = formals.indexOf(name); + if (duplicateIndex >= 0) { + // change the name of the earlier argument to enforce the lookup semantics from the spec + formals[duplicateIndex] += QLatin1String("#") + QString::number(i); + } + formals += name; + ++i; } - - visitor->endVisit(this); + return formals; } -void FunctionBody::accept0(Visitor *visitor) +QStringList FormalParameterList::boundNames() const { - if (visitor->visit(this)) { - accept(elements, visitor); + QStringList names; + for (const FormalParameterList *it = this; it; it = it->next) { + if (QQmlJS::AST::BindingElement *b = it->bindingElement()) { + b->boundNames(&names); + } else if (QQmlJS::AST::BindingRestElement *r = it->bindingRestElement()) { + names += r->name.toString(); + } } - - visitor->endVisit(this); + return names; } -void Program::accept0(Visitor *visitor) +void FormalParameterList::accept0(Visitor *visitor) { if (visitor->visit(this)) { - accept(elements, visitor); + // ### } visitor->endVisit(this); } -void SourceElements::accept0(Visitor *visitor) +FormalParameterList *FormalParameterList::finish() { - if (visitor->visit(this)) { - for (SourceElements *it = this; it; it = it->next) { - accept(it->element, visitor); - } - } - - visitor->endVisit(this); -} + FormalParameterList *front = next; + next = nullptr; -void FunctionSourceElement::accept0(Visitor *visitor) -{ - if (visitor->visit(this)) { - accept(declaration, visitor); + int i = 0; + for (const FormalParameterList *it = this; it; it = it->next) { + QString name; + if (QQmlJS::AST::BindingElement *b = it->bindingElement()) { + if (b->name.isEmpty()) + name = QLatin1String("arg#") + QString::number(i); + } + ++i; } - - visitor->endVisit(this); + return front; } -void StatementSourceElement::accept0(Visitor *visitor) +void Program::accept0(Visitor *visitor) { if (visitor->visit(this)) { - accept(statement, visitor); + accept(statements, visitor); } visitor->endVisit(this); @@ -984,6 +1008,93 @@ void UiEnumMemberList::accept0(Visitor *visitor) visitor->endVisit(this); } +void TaggedTemplate::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(templateLiteral, visitor); + } + + visitor->endVisit(this); +} + +void BindingRestElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void BindingElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(initializer, visitor); + } + + visitor->endVisit(this); +} + +void BindingElement::boundNames(QStringList *names) +{ + if (binding) { + if (BindingElementList *e = elementList()) + e->boundNames(names); + else if (BindingPropertyList *p = propertyList()) + p->boundNames(names); + } else + names->append(name); +} + +void BindingElementList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void BindingElementList::boundNames(QStringList *names) +{ + for (BindingElementList *it = this; it; it = it->next) { + if (BindingElement *e = it->bindingElement()) + e->boundNames(names); + else if (BindingRestElement *r = it->bindingRestElement()) + names->append(r->name.toString()); + } +} + +void BindingPropertyList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void BindingPropertyList::boundNames(QStringList *names) +{ + for (BindingPropertyList *it = this; it; it = it->next) + it->binding->boundNames(names); +} + +void ObjectBindingPattern::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(properties, visitor); + } + + visitor->endVisit(this); +} + +void ArrayBindingPattern::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(elements, visitor); + } + + visitor->endVisit(this); +} + } } // namespace QQmlJS::AST QT_QML_END_NAMESPACE diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index ed3c83badf..6c8a5c7af6 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -156,7 +156,6 @@ public: Kind_FunctionBody, Kind_FunctionDeclaration, Kind_FunctionExpression, - Kind_FunctionSourceElement, Kind_IdentifierExpression, Kind_IdentifierPropertyName, Kind_IfStatement, @@ -175,19 +174,18 @@ public: Kind_PreDecrementExpression, Kind_PreIncrementExpression, Kind_Program, - Kind_PropertyAssignmentList, + Kind_PropertyDefinitionList, Kind_PropertyGetterSetter, Kind_PropertyName, Kind_PropertyNameAndValue, Kind_RegExpLiteral, Kind_ReturnStatement, - Kind_SourceElement, - Kind_SourceElements, Kind_StatementList, - Kind_StatementSourceElement, Kind_StringLiteral, Kind_StringLiteralPropertyName, Kind_SwitchStatement, + Kind_TemplateLiteral, + Kind_TaggedTemplate, Kind_ThisExpression, Kind_ThrowStatement, Kind_TildeExpression, @@ -203,6 +201,12 @@ public: Kind_WhileStatement, Kind_WithStatement, Kind_NestedExpression, + Kind_ArrayBindingPattern, + Kind_ObjectBindingPattern, + Kind_BindingElement, + Kind_BindingElementList, + Kind_BindingPropertyList, + Kind_BindingRestElement, Kind_UiArrayBinding, Kind_UiImport, @@ -428,6 +432,29 @@ public: SourceLocation literalToken; }; +class QML_PARSER_EXPORT TemplateLiteral : public ExpressionNode +{ +public: + QQMLJS_DECLARE_AST_NODE(TemplateLiteral) + + TemplateLiteral(const QStringRef &str, ExpressionNode *e) + : value(str), expression(e), next(nullptr) + { kind = K; } + + SourceLocation firstSourceLocation() const override + { return literalToken; } + + SourceLocation lastSourceLocation() const override + { return next ? next->lastSourceLocation() : (expression ? expression->lastSourceLocation() : literalToken); } + + void accept0(Visitor *visitor) override; + + QStringRef value; + ExpressionNode *expression; + TemplateLiteral *next; + SourceLocation literalToken; +}; + class QML_PARSER_EXPORT RegExpLiteral: public ExpressionNode { public: @@ -491,7 +518,7 @@ public: ObjectLiteral() { kind = K; } - ObjectLiteral(PropertyAssignmentList *plist): + ObjectLiteral(PropertyDefinitionList *plist): properties (plist) { kind = K; } void accept0(Visitor *visitor) override; @@ -503,7 +530,7 @@ public: { return rbraceToken; } // attributes - PropertyAssignmentList *properties = nullptr; + PropertyDefinitionList *properties = nullptr; SourceLocation lbraceToken; SourceLocation rbraceToken; }; @@ -609,27 +636,34 @@ public: SourceLocation propertyNameToken; }; -class QML_PARSER_EXPORT PropertyAssignment: public Node +class QML_PARSER_EXPORT PropertyDefinition: public Node { public: - PropertyAssignment(PropertyName *n) + PropertyDefinition(PropertyName *n) : name(n) {} + + SourceLocation firstSourceLocation() const override + { return name->firstSourceLocation(); } + + SourceLocation lastSourceLocation() const override + { return name->lastSourceLocation(); } + // attributes PropertyName *name; }; -class QML_PARSER_EXPORT PropertyAssignmentList: public Node +class QML_PARSER_EXPORT PropertyDefinitionList: public Node { public: - QQMLJS_DECLARE_AST_NODE(PropertyAssignmentList) + QQMLJS_DECLARE_AST_NODE(PropertyDefinitionList) - PropertyAssignmentList(PropertyAssignment *assignment) + PropertyDefinitionList(PropertyDefinition *assignment) : assignment(assignment) , next(this) { kind = K; } - PropertyAssignmentList(PropertyAssignmentList *previous, PropertyAssignment *assignment) + PropertyDefinitionList(PropertyDefinitionList *previous, PropertyDefinition *assignment) : assignment(assignment) { kind = K; @@ -637,9 +671,9 @@ public: previous->next = this; } - inline PropertyAssignmentList *finish () + inline PropertyDefinitionList *finish () { - PropertyAssignmentList *front = next; + PropertyDefinitionList *front = next; next = nullptr; return front; } @@ -653,18 +687,18 @@ public: { return next ? next->lastSourceLocation() : assignment->lastSourceLocation(); } // attributes - PropertyAssignment *assignment; - PropertyAssignmentList *next; + PropertyDefinition *assignment; + PropertyDefinitionList *next; SourceLocation commaToken; }; -class QML_PARSER_EXPORT PropertyNameAndValue: public PropertyAssignment +class QML_PARSER_EXPORT PropertyNameAndValue: public PropertyDefinition { public: QQMLJS_DECLARE_AST_NODE(PropertyNameAndValue) PropertyNameAndValue(PropertyName *n, ExpressionNode *v) - : PropertyAssignment(n), value(v) + : PropertyDefinition(n), value(v) { kind = K; } void accept0(Visitor *visitor) override; @@ -681,7 +715,7 @@ public: SourceLocation commaToken; }; -class QML_PARSER_EXPORT PropertyGetterSetter: public PropertyAssignment +class QML_PARSER_EXPORT PropertyGetterSetter: public PropertyDefinition { public: QQMLJS_DECLARE_AST_NODE(PropertyGetterSetter) @@ -691,12 +725,12 @@ public: Setter }; - PropertyGetterSetter(PropertyName *n, FunctionBody *b) - : PropertyAssignment(n), type(Getter), formals(nullptr), functionBody (b) + PropertyGetterSetter(PropertyName *n, StatementList *b) + : PropertyDefinition(n), type(Getter), formals(nullptr), functionBody(b) { kind = K; } - PropertyGetterSetter(PropertyName *n, FormalParameterList *f, FunctionBody *b) - : PropertyAssignment(n), type(Setter), formals(f), functionBody (b) + PropertyGetterSetter(PropertyName *n, FormalParameterList *f, StatementList *b) + : PropertyDefinition(n), type(Setter), formals(f), functionBody(b) { kind = K; } void accept0(Visitor *visitor) override; @@ -714,7 +748,7 @@ public: FormalParameterList *formals; SourceLocation rparenToken; SourceLocation lbraceToken; - FunctionBody *functionBody; + StatementList *functionBody; SourceLocation rbraceToken; }; @@ -814,6 +848,28 @@ public: SourceLocation identifierToken; }; +class QML_PARSER_EXPORT TaggedTemplate : public ExpressionNode +{ +public: + QQMLJS_DECLARE_AST_NODE(TaggedTemplate) + + TaggedTemplate(ExpressionNode *b, TemplateLiteral *t) + : base (b), templateLiteral(t) + { kind = K; } + + void accept0(Visitor *visitor) override; + + SourceLocation firstSourceLocation() const override + { return base->firstSourceLocation(); } + + SourceLocation lastSourceLocation() const override + { return templateLiteral->lastSourceLocation(); } + + // attributes + ExpressionNode *base; + TemplateLiteral *templateLiteral; +}; + class QML_PARSER_EXPORT NewMemberExpression: public ExpressionNode { public: @@ -1257,22 +1313,21 @@ class QML_PARSER_EXPORT StatementList: public Node public: QQMLJS_DECLARE_AST_NODE(StatementList) - StatementList(Statement *stmt): - statement (stmt), next (this) - { kind = K; } + // ### This should be a Statement, but FunctionDeclaration currently doesn't inherit it. + StatementList(Node *stmt) + : statement(stmt), next (this) + { kind = K; } - StatementList(StatementList *previous, Statement *stmt): - statement (stmt) - { - kind = K; - next = previous->next; - previous->next = this; + StatementList *append(StatementList *n) { + n->next = next; + next = n; + return n; } void accept0(Visitor *visitor) override; SourceLocation firstSourceLocation() const override - { return statement->firstSourceLocation(); } + { return statement ? statement->firstSourceLocation() : statement->firstSourceLocation(); } SourceLocation lastSourceLocation() const override { return next ? next->lastSourceLocation() : statement->lastSourceLocation(); } @@ -1285,33 +1340,10 @@ public: } // attributes - Statement *statement; + Node *statement = nullptr; StatementList *next; }; -class QML_PARSER_EXPORT VariableStatement: public Statement -{ -public: - QQMLJS_DECLARE_AST_NODE(VariableStatement) - - VariableStatement(VariableDeclarationList *vlist): - declarations (vlist) - { kind = K; } - - void accept0(Visitor *visitor) override; - - SourceLocation firstSourceLocation() const override - { return declarationKindToken; } - - SourceLocation lastSourceLocation() const override - { return semicolonToken; } - -// attributes - VariableDeclarationList *declarations; - SourceLocation declarationKindToken; - SourceLocation semicolonToken; -}; - class QML_PARSER_EXPORT VariableDeclaration: public Node { public: @@ -1390,6 +1422,28 @@ public: SourceLocation commaToken; }; +class QML_PARSER_EXPORT VariableStatement: public Statement +{ +public: + QQMLJS_DECLARE_AST_NODE(VariableStatement) + + VariableStatement(VariableDeclarationList *vlist): + declarations (vlist) + { kind = K; } + + void accept0(Visitor *visitor) override; + + SourceLocation firstSourceLocation() const override + { return declarationKindToken; } + + SourceLocation lastSourceLocation() const override + { return declarations->lastSourceLocation(); } + +// attributes + VariableDeclarationList *declarations; + SourceLocation declarationKindToken; +}; + class QML_PARSER_EXPORT EmptyStatement: public Statement { public: @@ -1423,7 +1477,7 @@ public: { return expression->firstSourceLocation(); } SourceLocation lastSourceLocation() const override - { return semicolonToken; } + { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; @@ -1993,7 +2047,7 @@ class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode public: QQMLJS_DECLARE_AST_NODE(FunctionExpression) - FunctionExpression(const QStringRef &n, FormalParameterList *f, FunctionBody *b): + FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b): name (n), formals (f), body (b) { kind = K; } @@ -2008,7 +2062,7 @@ public: // attributes QStringRef name; FormalParameterList *formals; - FunctionBody *body; + StatementList *body; SourceLocation functionToken; SourceLocation identifierToken; SourceLocation lparenToken; @@ -2017,185 +2071,301 @@ public: SourceLocation rbraceToken; }; -class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression +class QML_PARSER_EXPORT BindingRestElement : public Node { public: - QQMLJS_DECLARE_AST_NODE(FunctionDeclaration) + QQMLJS_DECLARE_AST_NODE(BindingRestElement) - FunctionDeclaration(const QStringRef &n, FormalParameterList *f, FunctionBody *b): - FunctionExpression(n, f, b) - { kind = K; } + BindingRestElement(const QStringRef &n) + : name(n) + { kind = K; } void accept0(Visitor *visitor) override; + + SourceLocation firstSourceLocation() const override + { return identifierToken; } + + SourceLocation lastSourceLocation() const override + { return identifierToken; } + +// attributes + SourceLocation identifierToken; + QStringRef name; }; -class QML_PARSER_EXPORT FormalParameterList: public Node +class QML_PARSER_EXPORT BindingPattern : public Node { public: - QQMLJS_DECLARE_AST_NODE(FormalParameterList) - FormalParameterList(const QStringRef &n): - name (n), next (this) - { kind = K; } + SourceLocation firstSourceLocation() const override + { return first; } - FormalParameterList(FormalParameterList *previous, const QStringRef &n): - name (n) - { - kind = K; - next = previous->next; - previous->next = this; - } + SourceLocation lastSourceLocation() const override + { return last; } - void accept0(Visitor *visitor) override; + SourceLocation first; + SourceLocation last; +}; - SourceLocation firstSourceLocation() const override - { return identifierToken; } +class QML_PARSER_EXPORT ObjectBindingPattern : public BindingPattern +{ +public: + QQMLJS_DECLARE_AST_NODE(ObjectBindingPattern) - SourceLocation lastSourceLocation() const override - { return next ? next->lastSourceLocation() : identifierToken; } + ObjectBindingPattern(BindingPropertyList *p) + : properties(p) + { kind = K; } - inline FormalParameterList *finish () - { - FormalParameterList *front = next; - next = nullptr; - return front; - } + void accept0(Visitor *visitor) override; -// attributes - QStringRef name; - FormalParameterList *next; - SourceLocation commaToken; - SourceLocation identifierToken; + BindingPropertyList *properties; }; -class QML_PARSER_EXPORT SourceElement: public Node +class QML_PARSER_EXPORT ArrayBindingPattern : public BindingPattern { public: - QQMLJS_DECLARE_AST_NODE(SourceElement) + QQMLJS_DECLARE_AST_NODE(ArrayBindingPattern) - inline SourceElement() - { kind = K; } + ArrayBindingPattern(BindingElementList *e) + : elements(e) + { kind = K; } + + void accept0(Visitor *visitor) override; + + BindingElementList *elements; }; -class QML_PARSER_EXPORT SourceElements: public Node +class QML_PARSER_EXPORT BindingElement : public Node { public: - QQMLJS_DECLARE_AST_NODE(SourceElements) + QQMLJS_DECLARE_AST_NODE(BindingElement) - SourceElements(SourceElement *elt): - element (elt), next (this) - { kind = K; } + BindingElement(const QStringRef &n, ExpressionNode *i = nullptr) + : name(n.toString()), initializer(i) + { kind = K; } - SourceElements(SourceElements *previous, SourceElement *elt): - element (elt) - { - kind = K; - next = previous->next; - previous->next = this; - } + BindingElement(BindingPattern *binding, ExpressionNode *i = nullptr) + : binding(binding), initializer(i) + { kind = K; } void accept0(Visitor *visitor) override; SourceLocation firstSourceLocation() const override - { return element->firstSourceLocation(); } + { return identifierToken; } SourceLocation lastSourceLocation() const override - { return next ? next->lastSourceLocation() : element->lastSourceLocation(); } + { return initializer ? initializer->lastSourceLocation() : (binding ? binding->lastSourceLocation() : identifierToken); } - inline SourceElements *finish () - { - SourceElements *front = next; - next = nullptr; - return front; + BindingElementList *elementList() const { + ArrayBindingPattern *p = cast<ArrayBindingPattern *>(binding); + return p ? p->elements : nullptr; + } + BindingPropertyList *propertyList() const { + ObjectBindingPattern *p = cast<ObjectBindingPattern *>(binding); + return p ? p->properties : nullptr; } + void boundNames(QStringList *names); + // attributes - SourceElement *element; - SourceElements *next; + SourceLocation identifierToken; + BindingPattern *binding = nullptr; + QString name; + ExpressionNode *initializer = nullptr; }; -class QML_PARSER_EXPORT FunctionBody: public Node +class QML_PARSER_EXPORT BindingElementList : public Node { public: - QQMLJS_DECLARE_AST_NODE(FunctionBody) + QQMLJS_DECLARE_AST_NODE(BindingElementList) - FunctionBody(SourceElements *elts): - elements (elts) - { kind = K; } + BindingElementList(Elision *e, Node *p) + : elision(e), param(p), next(this) + { kind = K; } + + BindingElementList *append(BindingElementList *n) { + n->next = next; + next = n; + return n; + } + + inline BindingElementList *finish () + { + BindingElementList *front = next; + next = 0; + return front; + } + + BindingRestElement *bindingRestElement() const { + return cast<BindingRestElement *>(param); + } + + BindingElement *bindingElement() const { + return cast<BindingElement *>(param); + } void accept0(Visitor *visitor) override; + void boundNames(QStringList *names); + SourceLocation firstSourceLocation() const override - { return elements ? elements->firstSourceLocation() : SourceLocation(); } + { return elision ? elision->firstSourceLocation() : param->firstSourceLocation(); } SourceLocation lastSourceLocation() const override - { return elements ? elements->lastSourceLocation() : SourceLocation(); } + { return next ? next->lastSourceLocation() : (param ? param->lastSourceLocation() : elision->lastSourceLocation()); } -// attributes - SourceElements *elements; + Elision *elision = nullptr; + Node *param = nullptr; + BindingElementList *next; }; -class QML_PARSER_EXPORT Program: public Node +class QML_PARSER_EXPORT BindingPropertyList : public Node { public: - QQMLJS_DECLARE_AST_NODE(Program) + QQMLJS_DECLARE_AST_NODE(BindingPropertyList) - Program(SourceElements *elts): - elements (elts) - { kind = K; } + BindingPropertyList(PropertyName *n, BindingElement *e) + : propertyName(n), binding(e), next(this) + { kind = K; } void accept0(Visitor *visitor) override; + void boundNames(QStringList *names); + + BindingPropertyList *append(BindingPropertyList *n) { + n->next = next; + next = n; + return n; + } + + inline BindingPropertyList *finish () + { + BindingPropertyList *front = next; + next = 0; + return front; + } + SourceLocation firstSourceLocation() const override - { return elements ? elements->firstSourceLocation() : SourceLocation(); } + { return propertyName->firstSourceLocation(); } SourceLocation lastSourceLocation() const override - { return elements ? elements->lastSourceLocation() : SourceLocation(); } + { return next ? next->lastSourceLocation() : binding->lastSourceLocation(); } -// attributes - SourceElements *elements; + PropertyName *propertyName; + BindingElement *binding; + BindingPropertyList *next; }; -class QML_PARSER_EXPORT FunctionSourceElement: public SourceElement +class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression { public: - QQMLJS_DECLARE_AST_NODE(FunctionSourceElement) + QQMLJS_DECLARE_AST_NODE(FunctionDeclaration) - FunctionSourceElement(FunctionDeclaration *f): - declaration (f) + FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b): + FunctionExpression(n, f, b) { kind = K; } void accept0(Visitor *visitor) override; +}; + +class QML_PARSER_EXPORT FormalParameterList: public Node +{ +public: + QQMLJS_DECLARE_AST_NODE(FormalParameterList) + + FormalParameterList(FormalParameterList *previous, Node *p) + : param(p) + { + kind = K; + if (previous) { + next = previous->next; + previous->next = this; + } else { + next = this; + } + } + + FormalParameterList *append(FormalParameterList *n) { + n->next = next; + next = n; + return n; + } + + BindingRestElement *bindingRestElement() const { + return cast<BindingRestElement *>(param); + } + + BindingElement *bindingElement() const { + return cast<BindingElement *>(param); + } + + bool isSimpleParameterList() + { + AST::FormalParameterList *formals = this; + while (formals) { + if (formals->bindingRestElement()) + return false; + BindingElement *e = formals->bindingElement(); + Q_ASSERT(e); + if (e->initializer || e->binding) + return false; + formals = formals->next; + } + return true; + } + + bool containsName(const QString &name) const { + for (const FormalParameterList *it = this; it; it = it->next) { + if (QQmlJS::AST::BindingElement *b = it->bindingElement()) { + // ### handle binding patterns + if (b->name == name) + return true; + } else if (QQmlJS::AST::BindingRestElement *r = it->bindingRestElement()) { + if (r->name == name) + return true; + } + } + return false; + } + + QStringList formals() const; + + QStringList boundNames() const; + + void accept0(Visitor *visitor) override; SourceLocation firstSourceLocation() const override - { return declaration->firstSourceLocation(); } + { return param->firstSourceLocation(); } SourceLocation lastSourceLocation() const override - { return declaration->lastSourceLocation(); } + { return next ? next->lastSourceLocation() : param->lastSourceLocation(); } + + FormalParameterList *finish(); // attributes - FunctionDeclaration *declaration; + Node *param = nullptr; + FormalParameterList *next; }; -class QML_PARSER_EXPORT StatementSourceElement: public SourceElement +class QML_PARSER_EXPORT Program: public Node { public: - QQMLJS_DECLARE_AST_NODE(StatementSourceElement) + QQMLJS_DECLARE_AST_NODE(Program) - StatementSourceElement(Statement *stmt): - statement (stmt) - { kind = K; } + Program(StatementList *statements) + : statements(statements) + { kind = K; } void accept0(Visitor *visitor) override; SourceLocation firstSourceLocation() const override - { return statement->firstSourceLocation(); } + { return statements ? statements->firstSourceLocation() : SourceLocation(); } SourceLocation lastSourceLocation() const override - { return statement->lastSourceLocation(); } + { return statements ? statements->lastSourceLocation() : SourceLocation(); } // attributes - Statement *statement; + StatementList *statements; }; class QML_PARSER_EXPORT DebuggerStatement: public Statement diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h index 140a757e51..89245f4884 100644 --- a/src/qml/parser/qqmljsastfwd_p.h +++ b/src/qml/parser/qqmljsastfwd_p.h @@ -91,12 +91,13 @@ class TrueLiteral; class FalseLiteral; class NumericLiteral; class StringLiteral; +class TemplateLiteral; class RegExpLiteral; class ArrayLiteral; class ObjectLiteral; class ElementList; class Elision; -class PropertyAssignmentList; +class PropertyDefinitionList; class PropertyGetterSetter; class PropertyNameAndValue; class PropertyName; @@ -105,6 +106,7 @@ class StringLiteralPropertyName; class NumericLiteralPropertyName; class ArrayMemberExpression; class FieldMemberExpression; +class TaggedTemplate; class NewMemberExpression; class NewExpression; class CallExpression; @@ -154,14 +156,17 @@ class Finally; class FunctionDeclaration; class FunctionExpression; class FormalParameterList; -class FunctionBody; class Program; -class SourceElements; -class SourceElement; -class FunctionSourceElement; -class StatementSourceElement; class DebuggerStatement; class NestedExpression; +class BindingPattern; +class ArrayBindingPattern; +class ObjectBindingPattern; +class BindingElement; +class BindingElementList; +class BindingPropertyList; +class BindingElement; +class BindingRestElement; // ui elements class UiProgram; diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h index 13218f0e98..1c11ee9c02 100644 --- a/src/qml/parser/qqmljsastvisitor_p.h +++ b/src/qml/parser/qqmljsastvisitor_p.h @@ -125,6 +125,9 @@ public: virtual bool visit(StringLiteral *) { return true; } virtual void endVisit(StringLiteral *) {} + virtual bool visit(TemplateLiteral *) { return true; } + virtual void endVisit(TemplateLiteral *) {} + virtual bool visit(NumericLiteral *) { return true; } virtual void endVisit(NumericLiteral *) {} @@ -143,8 +146,8 @@ public: virtual bool visit(Elision *) { return true; } virtual void endVisit(Elision *) {} - virtual bool visit(PropertyAssignmentList *) { return true; } - virtual void endVisit(PropertyAssignmentList *) {} + virtual bool visit(PropertyDefinitionList *) { return true; } + virtual void endVisit(PropertyDefinitionList *) {} virtual bool visit(PropertyNameAndValue *) { return true; } virtual void endVisit(PropertyNameAndValue *) {} @@ -170,6 +173,9 @@ public: virtual bool visit(FieldMemberExpression *) { return true; } virtual void endVisit(FieldMemberExpression *) {} + virtual bool visit(TaggedTemplate *) { return true; } + virtual void endVisit(TaggedTemplate *) {} + virtual bool visit(NewMemberExpression *) { return true; } virtual void endVisit(NewMemberExpression *) {} @@ -314,23 +320,29 @@ public: virtual bool visit(FunctionExpression *) { return true; } virtual void endVisit(FunctionExpression *) {} - virtual bool visit(FormalParameterList *) { return true; } - virtual void endVisit(FormalParameterList *) {} + virtual bool visit(ObjectBindingPattern *) { return true; } + virtual void endVisit(ObjectBindingPattern *) {} - virtual bool visit(FunctionBody *) { return true; } - virtual void endVisit(FunctionBody *) {} + virtual bool visit(ArrayBindingPattern *) { return true; } + virtual void endVisit(ArrayBindingPattern *) {} - virtual bool visit(Program *) { return true; } - virtual void endVisit(Program *) {} + virtual bool visit(BindingElement *) { return true; } + virtual void endVisit(BindingElement *) {} - virtual bool visit(SourceElements *) { return true; } - virtual void endVisit(SourceElements *) {} + virtual bool visit(BindingElementList *) { return true; } + virtual void endVisit(BindingElementList *) {} - virtual bool visit(FunctionSourceElement *) { return true; } - virtual void endVisit(FunctionSourceElement *) {} + virtual bool visit(BindingPropertyList *) { return true; } + virtual void endVisit(BindingPropertyList *) {} - virtual bool visit(StatementSourceElement *) { return true; } - virtual void endVisit(StatementSourceElement *) {} + virtual bool visit(BindingRestElement *) { return true; } + virtual void endVisit(BindingRestElement *) {} + + virtual bool visit(FormalParameterList *) { return true; } + virtual void endVisit(FormalParameterList *) {} + + virtual bool visit(Program *) { return true; } + virtual void endVisit(Program *) {} virtual bool visit(DebuggerStatement *) { return true; } virtual void endVisit(DebuggerStatement *) {} diff --git a/src/qml/parser/qqmljsengine_p.cpp b/src/qml/parser/qqmljsengine_p.cpp index b4f0debf85..97ce6ebea3 100644 --- a/src/qml/parser/qqmljsengine_p.cpp +++ b/src/qml/parser/qqmljsengine_p.cpp @@ -112,13 +112,6 @@ double integerFromString(const char *buf, int size, int radix) return result; } -double integerFromString(const QString &str, int radix) -{ - QByteArray ba = QStringRef(&str).trimmed().toLatin1(); - return integerFromString(ba.constData(), ba.size(), radix); -} - - Engine::Engine() : _lexer(nullptr), _directives(nullptr) { } diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h index af26bac0ff..1de907d296 100644 --- a/src/qml/parser/qqmljsengine_p.h +++ b/src/qml/parser/qqmljsengine_p.h @@ -63,9 +63,35 @@ QT_QML_BEGIN_NAMESPACE namespace QQmlJS { class Lexer; -class Directives; class MemoryPool; +class QML_PARSER_EXPORT Directives { +public: + virtual ~Directives() {} + + virtual void pragmaLibrary() + { + } + + virtual void importFile(const QString &jsfile, const QString &module, int line, int column) + { + Q_UNUSED(jsfile); + Q_UNUSED(module); + Q_UNUSED(line); + Q_UNUSED(column); + } + + virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column) + { + Q_UNUSED(uri); + Q_UNUSED(version); + Q_UNUSED(module); + Q_UNUSED(line); + Q_UNUSED(column); + } +}; + + class QML_PARSER_EXPORT DiagnosticMessage { public: diff --git a/src/qml/parser/qqmljsgrammar.cpp b/src/qml/parser/qqmljsgrammar.cpp deleted file mode 100644 index 2aaeb385e3..0000000000 --- a/src/qml/parser/qqmljsgrammar.cpp +++ /dev/null @@ -1,1167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// This file was generated by qlalr - DO NOT EDIT! -#include "qqmljsgrammar_p.h" - -QT_BEGIN_NAMESPACE - -const char *const QQmlJSGrammar::spell [] = { - "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue", - "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", - "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", - "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", - "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=", - "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", - ")", ";", nullptr, "*", "*=", "string literal", "property", "signal", "readonly", "switch", - "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", - "^=", "null", "true", "false", "const", "let", "debugger", "reserved word", "multiline string literal", "comment", - nullptr, "enum", "public", "import", "pragma", "as", "on", "get", "set", nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr -}; - -const short QQmlJSGrammar::lhs [] = { - 108, 108, 108, 108, 108, 108, 109, 115, 115, 118, - 118, 118, 118, 121, 123, 119, 119, 120, 120, 120, - 120, 120, 120, 120, 120, 124, 125, 117, 116, 128, - 128, 129, 129, 130, 130, 127, 113, 113, 113, 113, - 132, 132, 132, 132, 132, 132, 132, 113, 140, 140, - 140, 140, 141, 141, 142, 142, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 145, 145, 145, - 145, 126, 126, 126, 126, 126, 126, 126, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 131, 148, 148, 148, - 148, 147, 147, 152, 152, 152, 150, 150, 153, 153, - 153, 153, 156, 156, 156, 156, 156, 156, 156, 156, - 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, - 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, - 156, 156, 156, 156, 156, 157, 157, 122, 122, 122, - 122, 122, 160, 160, 161, 161, 161, 161, 159, 159, - 162, 162, 163, 163, 164, 164, 164, 165, 165, 165, - 165, 165, 165, 165, 165, 165, 165, 166, 166, 166, - 166, 167, 167, 167, 168, 168, 168, 168, 169, 169, - 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, - 170, 171, 171, 171, 171, 171, 172, 172, 172, 172, - 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, - 177, 178, 178, 179, 179, 180, 180, 181, 181, 182, - 182, 183, 183, 184, 184, 151, 151, 185, 185, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 111, 111, 187, 187, 188, 188, 189, 189, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 133, 198, 198, 197, 197, 144, - 144, 199, 199, 199, 200, 200, 202, 202, 201, 203, - 206, 204, 204, 207, 205, 205, 134, 135, 135, 136, - 136, 190, 190, 190, 190, 190, 190, 190, 190, 191, - 191, 191, 191, 192, 192, 192, 192, 193, 193, 137, - 138, 208, 208, 211, 211, 209, 209, 212, 210, 194, - 195, 195, 139, 139, 139, 213, 214, 196, 196, 215, - 143, 158, 158, 216, 216, 155, 155, 154, 154, 217, - 114, 114, 218, 218, 112, 112, 149, 149, 219 -}; - -const short QQmlJSGrammar::rhs [] = { - 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, - 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, - 3, 5, 5, 4, 4, 2, 2, 0, 1, 1, - 2, 1, 3, 2, 3, 2, 1, 5, 4, 4, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, - 1, 3, 0, 1, 2, 4, 6, 6, 3, 3, - 7, 7, 4, 4, 5, 5, 8, 8, 5, 6, - 6, 10, 6, 7, 1, 1, 5, 1, 3, 3, - 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 3, 4, 5, 3, 4, 3, 1, 1, 2, 3, - 4, 1, 2, 3, 7, 8, 1, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, - 3, 5, 1, 2, 4, 4, 4, 3, 0, 1, - 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, - 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, - 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, - 3, 1, 3, 3, 3, 3, 1, 3, 3, 3, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 5, 1, 5, 1, 3, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 1, 2, 0, 1, 3, - 3, 1, 1, 1, 1, 3, 1, 3, 2, 2, - 2, 0, 1, 2, 0, 1, 1, 2, 2, 7, - 5, 7, 7, 7, 5, 9, 10, 7, 8, 2, - 2, 3, 3, 2, 2, 3, 3, 3, 3, 5, - 5, 3, 5, 1, 2, 0, 1, 4, 3, 3, - 3, 3, 3, 3, 4, 5, 2, 2, 2, 1, - 8, 8, 7, 1, 3, 0, 1, 0, 1, 1, - 1, 1, 1, 2, 1, 1, 0, 1, 2 -}; - -const short QQmlJSGrammar::action_default [] = { - 0, 0, 28, 0, 0, 0, 28, 0, 195, 262, - 226, 234, 230, 174, 246, 222, 3, 159, 90, 175, - 238, 242, 163, 192, 173, 178, 158, 212, 199, 0, - 97, 98, 93, 0, 87, 82, 367, 0, 0, 0, - 0, 95, 0, 0, 91, 94, 86, 0, 0, 83, - 85, 88, 84, 96, 89, 0, 92, 0, 0, 188, - 0, 0, 175, 194, 177, 176, 0, 0, 0, 190, - 191, 189, 193, 0, 223, 0, 0, 0, 0, 213, - 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, - 197, 198, 196, 201, 205, 204, 202, 200, 215, 214, - 216, 0, 231, 0, 227, 0, 0, 169, 156, 168, - 157, 123, 124, 125, 151, 126, 153, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 152, - 139, 140, 154, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 155, 0, 0, 167, 263, 170, 0, - 171, 0, 172, 166, 0, 259, 252, 250, 257, 258, - 256, 255, 261, 254, 253, 251, 260, 247, 0, 235, - 0, 0, 239, 0, 0, 243, 0, 0, 169, 161, - 0, 160, 0, 165, 179, 0, 356, 356, 357, 0, - 354, 0, 355, 0, 358, 270, 277, 276, 284, 272, - 0, 273, 0, 359, 0, 366, 274, 275, 90, 280, - 278, 363, 360, 365, 281, 0, 293, 0, 0, 0, - 0, 350, 0, 367, 292, 264, 307, 0, 0, 0, - 294, 0, 0, 282, 283, 0, 271, 279, 308, 309, - 0, 356, 0, 0, 358, 0, 351, 352, 0, 340, - 364, 0, 324, 325, 326, 327, 0, 320, 321, 322, - 323, 348, 349, 0, 0, 0, 0, 0, 312, 313, - 314, 268, 266, 228, 236, 232, 248, 224, 269, 0, - 175, 240, 244, 217, 206, 0, 0, 225, 0, 0, - 0, 0, 218, 0, 0, 0, 0, 0, 210, 208, - 211, 209, 207, 220, 219, 221, 0, 233, 0, 229, - 0, 267, 175, 0, 249, 264, 265, 0, 264, 0, - 0, 316, 0, 0, 0, 318, 0, 237, 0, 0, - 241, 0, 0, 245, 305, 0, 297, 306, 300, 0, - 304, 0, 264, 298, 0, 264, 0, 0, 317, 0, - 0, 0, 319, 0, 0, 0, 311, 0, 310, 90, - 117, 368, 0, 0, 122, 286, 289, 0, 123, 293, - 126, 153, 128, 129, 93, 134, 135, 87, 136, 292, - 139, 91, 94, 264, 88, 96, 142, 89, 144, 92, - 146, 147, 294, 149, 150, 155, 0, 119, 118, 121, - 105, 120, 104, 0, 114, 287, 285, 0, 0, 0, - 358, 0, 115, 163, 164, 169, 0, 162, 0, 328, - 329, 0, 356, 0, 0, 358, 0, 116, 0, 0, - 0, 331, 336, 334, 337, 0, 0, 335, 336, 0, - 332, 0, 333, 288, 339, 0, 288, 338, 0, 341, - 342, 0, 288, 343, 344, 0, 0, 345, 0, 0, - 0, 346, 347, 181, 180, 0, 0, 0, 315, 0, - 0, 0, 330, 302, 295, 0, 303, 299, 0, 301, - 290, 0, 291, 296, 0, 0, 358, 0, 353, 108, - 0, 0, 112, 99, 0, 101, 110, 0, 102, 111, - 113, 103, 109, 100, 0, 106, 185, 183, 187, 184, - 182, 186, 361, 6, 362, 4, 2, 75, 107, 0, - 0, 0, 83, 85, 84, 37, 5, 0, 76, 0, - 51, 50, 49, 0, 0, 51, 0, 0, 0, 52, - 0, 67, 68, 0, 65, 0, 66, 41, 42, 43, - 44, 46, 47, 71, 45, 0, 0, 0, 78, 0, - 77, 80, 0, 81, 0, 79, 0, 51, 0, 0, - 0, 0, 0, 61, 0, 62, 0, 0, 32, 0, - 0, 72, 33, 0, 36, 34, 30, 0, 35, 31, - 0, 63, 0, 64, 163, 0, 69, 73, 0, 0, - 0, 0, 163, 288, 0, 70, 90, 123, 293, 126, - 153, 128, 129, 93, 134, 135, 136, 292, 139, 91, - 94, 264, 96, 142, 89, 144, 92, 146, 147, 294, - 149, 150, 155, 74, 0, 59, 53, 60, 54, 0, - 0, 0, 0, 56, 0, 57, 58, 55, 0, 0, - 0, 0, 48, 0, 38, 39, 0, 40, 8, 0, - 0, 9, 0, 11, 0, 10, 0, 1, 27, 15, - 14, 26, 13, 12, 29, 7, 0, 18, 0, 19, - 0, 24, 25, 0, 20, 21, 0, 22, 23, 16, - 17, 369 -}; - -const short QQmlJSGrammar::goto_default [] = { - 7, 667, 213, 200, 211, 526, 513, 662, 675, 512, - 661, 665, 663, 671, 22, 668, 666, 664, 18, 525, - 587, 577, 584, 579, 553, 195, 199, 201, 206, 237, - 214, 234, 568, 639, 638, 205, 236, 557, 26, 491, - 490, 362, 361, 9, 360, 363, 204, 484, 364, 109, - 17, 149, 24, 13, 148, 19, 25, 59, 23, 8, - 28, 27, 283, 15, 277, 10, 273, 12, 275, 11, - 274, 20, 281, 21, 282, 14, 276, 272, 313, 418, - 278, 279, 207, 197, 196, 210, 209, 233, 198, 367, - 366, 235, 475, 474, 335, 336, 477, 338, 476, 337, - 431, 435, 438, 434, 433, 453, 454, 202, 188, 203, - 212, 0 -}; - -const short QQmlJSGrammar::action_index [] = { - 350, 1528, 3041, 3041, 2937, 1235, 115, 105, 239, -108, - 102, 93, 95, 205, -108, 422, 110, -108, -108, 727, - 92, 118, 265, 256, -108, -108, -108, 507, 247, 1528, - -108, -108, -108, 665, -108, -108, 2729, 1826, 1528, 1528, - 1528, -108, 1041, 1528, -108, -108, -108, 1528, 1528, -108, - -108, -108, -108, -108, -108, 1528, -108, 1528, 1528, -108, - 1528, 1528, 174, 221, -108, -108, 1528, 1528, 1528, -108, - -108, -108, 177, 1528, 422, 1528, 1528, 1528, 1528, 411, - 1528, 1528, 1528, 1528, 1528, 1528, 211, 1528, 1528, 1528, - 142, 148, 154, 217, 223, 226, 227, 231, 507, 385, - 395, 1528, 57, 1528, 83, 2521, 1528, 1528, -108, -108, - -108, -108, -108, -108, -108, -108, -108, -108, -108, -108, - -108, -108, -108, -108, -108, -108, -108, -108, -108, -108, - -108, -108, -108, -108, -108, -108, -108, -108, -108, -108, - -108, -108, -108, -108, 179, 1528, -108, -108, 77, 36, - -108, 1528, -108, -108, 1528, -108, -108, -108, -108, -108, - -108, -108, -108, -108, -108, -108, -108, -108, 1528, 56, - 1528, 1528, 80, 74, 1528, -108, 2521, 1528, 1528, -108, - 125, -108, 55, -108, -108, 53, 410, 418, 72, 52, - -108, 392, -108, 46, 3041, -108, -108, -108, -108, -108, - 273, -108, 396, -108, 44, -108, -108, -108, 76, -108, - -108, -108, 3041, -108, -108, 744, -108, 589, 98, 2937, - 91, 90, 88, 3249, -108, 1528, -108, 86, 1528, 81, - -108, 75, 73, -108, -108, 586, -108, -108, -108, -108, - 71, 491, 69, 65, 3041, 64, -108, -108, 2937, -108, - -108, 139, -108, -108, -108, -108, 134, -108, -108, -108, - -108, -108, -108, 63, 66, 1528, 147, 264, -108, -108, - -108, 1726, -108, 87, 68, 70, -108, 334, 82, 78, - 796, 89, 121, 349, 318, 469, 1528, 330, 1528, 1528, - 1528, 1528, 359, 1528, 1528, 1528, 1528, 1528, 284, 289, - 303, 306, 313, 365, 369, 375, 1528, 58, 1528, 85, - 1528, -108, 849, 1528, -108, 1528, 79, 59, 1528, 61, - 2937, -108, 1528, 146, 2937, -108, 1528, 62, 1528, 1528, - 106, 99, 1528, -108, 96, 176, 171, -108, -108, 1528, - -108, 407, 1528, -108, 97, 1528, -52, 2937, -108, 1528, - 120, 2937, -108, 1528, 123, 2937, 101, 2937, -108, 116, - -108, 84, 45, 0, -108, -108, 2937, -39, 641, -3, - 652, 156, 1528, 2937, -7, -11, 567, 2625, -21, 5, - 945, 2, 94, 1629, 2625, -1, -26, 6, 1528, 10, - -15, 1528, 14, 1528, -25, -12, 2833, -108, -108, -108, - -108, -108, -108, 1528, -108, -108, -108, -14, -58, -13, - 3041, -36, -108, 287, -108, 1528, -46, -108, 153, -108, - -108, -31, 586, -57, -32, 3041, 11, -108, 1528, 168, - 29, -108, 47, -108, 48, 169, 1528, -108, 49, 50, - -108, 9, -108, 2937, -108, 136, 2937, -108, 275, -108, - -108, 126, 2937, 35, -108, 33, 37, -108, 466, -4, - 38, -108, -108, -108, -108, 1528, 130, 2937, -108, 1528, - 117, 2937, -108, 34, -108, 296, -108, -108, 1528, -108, - -108, 404, -108, -108, 12, 40, 3041, 13, -108, -108, - 155, 1926, -108, -108, 2026, -108, -108, 2126, -108, -108, - -108, -108, -108, -108, 144, -108, -108, -108, -108, -108, - -108, -108, -108, -108, 3041, -108, -108, -108, 132, -27, - 15, 1137, 218, -23, 17, -108, -108, 196, -108, 242, - 8, -108, -108, 579, 237, -108, 127, 18, 415, -108, - 103, -108, -108, 236, -108, 2223, -108, -108, -108, -108, - -108, -108, -108, -108, -108, 27, 21, 137, 31, 20, - -108, 23, -5, -108, -9, -108, 332, -10, 571, 201, - 195, 586, 225, -108, 7, -108, 1137, 165, -108, 4, - 1137, -108, -108, 1333, -108, -108, -108, 1431, -108, -108, - 184, -108, 2223, -108, 331, 3, -108, -108, 202, 531, - 26, 2417, 327, 3145, 1, -108, 25, 629, 24, 649, - 124, 1528, 2937, 22, -6, 514, -8, 19, 1041, 16, - 94, 1629, 28, 42, 67, 1528, 60, 43, 1528, 54, - 1528, 41, 39, -108, 234, -108, 228, -108, 51, -2, - 564, 233, 575, -108, 100, -108, -108, -108, 2320, 1137, - 1826, 32, -108, 122, -108, -108, 30, -108, -108, 1137, - 1137, 104, 903, -108, 308, -108, 108, -108, -108, 133, - 119, -108, -108, -108, -108, -108, 451, -108, 164, -108, - 161, -108, -108, 458, -108, -108, 151, -108, -108, -108, - -108, -108, - - -112, 18, 86, 97, 69, 316, 7, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -64, - -112, -112, -112, -112, -112, -112, -112, -112, -112, 66, - -112, -112, -112, -17, -112, -112, -10, -36, 3, 90, - 95, -112, 149, 74, -112, -112, -112, 67, 13, -112, - -112, -112, -112, -112, -112, 178, -112, 181, 185, -112, - 189, 190, -112, -112, -112, -112, 198, 208, 212, -112, - -112, -112, -112, 209, -112, 201, 164, 111, 113, -112, - 116, 130, 131, 132, 134, 142, -112, 118, 124, 144, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, 154, -112, 155, -112, 268, 28, -8, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, 42, -112, -112, -112, -112, - -112, 47, -112, -112, 50, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, 159, -112, - 158, 56, -112, -112, 57, -112, 362, 60, 157, -112, - -112, -112, -112, -112, -112, -112, 20, 151, -112, -112, - -112, 25, -112, -112, 30, -112, -112, -112, -112, -112, - -112, -112, 31, -112, -112, -112, -112, -112, -112, -112, - -112, -112, 233, -112, -112, 34, -112, 35, -112, 225, - -112, 36, -112, 216, -112, 55, -112, -112, 53, 39, - -112, -112, -112, -112, -112, 19, -112, -112, -112, -112, - -112, 94, -112, -112, 92, -112, -112, -112, 117, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, 33, -112, -112, -112, -112, - -112, 88, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, 51, 220, -112, 227, 235, - 236, 244, -112, 21, 17, 102, 91, 89, -112, -112, - -112, -112, -112, -112, -112, -112, 211, -112, 247, -112, - 257, -112, -112, 264, -112, 75, -112, -112, 103, -112, - 112, -112, 29, -112, 73, -112, 263, -112, 255, 254, - -112, -112, 245, -112, -112, -112, -112, -112, -112, 248, - -112, 65, 105, -112, -112, 99, -112, 162, -112, 37, - -112, 115, -112, 44, -112, 135, -112, 137, -112, -112, - -112, -112, -112, -112, -112, -112, 138, -112, 24, -112, - 26, -112, 104, 140, -112, -112, 32, 64, -112, -112, - 174, -112, -112, 48, 87, -112, -112, -112, 54, -112, - 40, 71, -112, 150, -112, -112, 197, -112, -112, -112, - -112, -112, -112, 12, -112, -112, -112, -112, -112, -112, - 206, -112, -112, -112, -112, 207, -112, -112, -112, -112, - -112, -112, 231, -112, -112, 239, -112, -112, 43, -112, - -112, -112, -112, -112, -59, -112, 38, -112, -62, -112, - -112, -112, -112, 258, -112, -112, 259, -112, -112, -112, - -112, -112, 163, -72, -112, -112, 41, -112, 62, -112, - 61, -112, -112, -112, -112, 59, -112, 193, -112, 58, - -112, 204, -112, -112, -112, -112, -112, -112, 52, -112, - -112, 175, -112, -112, -112, -112, 186, -112, -112, -112, - -112, 49, -112, -112, 173, -112, -112, 45, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, 213, -112, -112, -112, -112, -112, - -112, 46, -112, -112, -112, -112, -112, -112, -112, 27, - -112, -112, -112, -18, -9, -112, -112, -112, 15, -112, - -112, -112, -112, -112, -112, 331, -112, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -112, -112, 11, -6, - -112, 10, -112, -112, -112, -112, 156, -112, -112, -112, - 240, -112, -112, 330, -112, -112, -112, 332, -112, -112, - -112, -112, 376, -112, -112, 8, -112, -112, -7, 76, - -112, 358, -112, 228, 5, -112, -112, 6, -112, 4, - -112, 79, 221, -112, -112, 2, -112, -112, 174, -112, - -112, 16, -112, -112, -112, 14, -112, -16, 70, -112, - 63, -112, -112, -112, -112, -112, -30, -112, -112, -112, - -15, -28, -13, -112, -112, -112, -112, -112, 460, 93, - 307, -12, -112, -112, -112, -112, -11, -112, -112, -2, - -1, 85, 84, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, -112, -112, -112, -3, -112, -112, -112, - -112, -112, -112, 0, -112, -112, -112, -112, -112, -112, - -112, -112 -}; - -const short QQmlJSGrammar::action_info [] = { - -132, 425, 409, 424, -151, 422, -120, 403, 347, -140, - 428, 465, -152, -143, 417, 353, 406, -145, 452, 412, - 410, -148, 408, -140, 469, 271, -152, 569, 353, -132, - 271, -151, 248, 601, 583, -120, 583, 583, 565, 529, - 562, 576, 563, 598, 555, 534, 634, 539, 564, 561, - 558, 478, 436, 436, 436, 456, 460, 443, 644, 641, - 556, -148, 432, 583, 442, 583, 427, -145, 488, 458, - 452, 452, 485, 486, -143, 469, 452, 465, 428, 194, - 191, 174, 168, 248, 73, 151, 286, 145, 286, 187, - 310, 326, 396, 0, 168, 0, 153, 0, 244, 247, - 402, -121, 265, 73, 101, 691, 332, 241, 326, 469, - 306, 465, 193, 339, 452, 183, 306, 357, 145, 246, - 318, 320, 428, 248, 353, 145, 186, 271, 145, 243, - 580, 145, 455, 145, 176, 0, 103, 308, 145, 315, - 264, 101, 537, 446, 145, 559, 456, 176, 176, 308, - 0, 538, 145, 177, 145, 145, 0, 0, 345, 262, - 261, 646, 645, 494, 542, 541, 177, 177, 170, 690, - 689, 328, 171, 580, 103, 329, 145, 471, 654, 439, - 351, 181, 60, 355, 341, 262, 261, 145, 60, 66, - 467, 592, 560, 61, 60, 260, 259, 659, 660, 61, - 255, 254, 349, 648, 505, 61, 324, 267, 659, 660, - 537, 495, 688, 687, 420, 419, 64, 262, 261, 571, - 105, 581, 682, 681, 440, 685, 684, 65, 430, 583, - 535, 535, 574, 66, 67, 146, 87, 342, 88, 106, - 68, 107, 87, 545, 88, 593, 591, 567, 87, 89, - 88, 87, 87, 88, 88, 89, 87, 535, 88, 683, - 0, 89, 535, 0, 89, 89, 535, 0, 66, 89, - 636, 530, 87, 0, 88, 0, 532, 532, 67, 60, - 176, 145, 0, 145, 68, 89, 575, 573, 531, 531, - 61, 0, 649, 532, 0, 637, 635, 546, 544, 177, - 0, 178, 176, 532, 481, 531, 0, 0, 532, 87, - 0, 88, 532, 67, 87, 531, 88, 532, 0, 68, - 531, 177, 89, 415, 531, 270, 268, 89, 87, 531, - 88, 87, 0, 88, 239, 238, 450, 449, 87, 0, - 88, 89, 176, 87, 89, 88, 176, 176, 288, 289, - 0, 89, 288, 289, 269, 678, 89, 482, 480, 0, - -107, 177, 0, 178, -107, 177, 177, 178, 415, 679, - 677, 0, 293, 294, 0, 290, 291, 0, 0, 290, - 291, 295, 293, 294, 296, 0, 297, 0, 293, 294, - 0, 295, 293, 294, 296, 0, 297, 295, 293, 294, - 296, 295, 297, 676, 296, 0, 297, 295, 80, 81, - 296, 0, 297, 0, 0, 0, 82, 83, 80, 81, - 84, 35, 85, 0, 0, 35, 82, 83, 0, 0, - 84, 0, 85, 35, 80, 81, 35, 0, 0, 35, - 75, 76, 82, 83, 35, 0, 84, 35, 85, 0, - 6, 5, 4, 1, 3, 2, 0, 0, 49, 52, - 50, 0, 49, 52, 50, 0, 0, 77, 78, 0, - 49, 52, 50, 49, 52, 50, 49, 52, 50, 0, - 35, 49, 52, 50, 49, 52, 50, 35, 46, 34, - 51, 0, 46, 34, 51, 35, 0, 0, 35, 0, - 46, 34, 51, 46, 34, 51, 46, 34, 51, 0, - 0, 46, 34, 51, 46, 34, 51, 49, 52, 50, - 35, 0, 0, 0, 49, 52, 50, 0, 0, 0, - 80, 81, 49, 52, 50, 49, 52, 50, 82, 83, - 0, 0, 84, 35, 85, 0, 537, 46, 34, 51, - 186, 0, 0, 0, 46, 34, 51, 49, 52, 50, - 35, 0, 46, 34, 51, 46, 34, 51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 537, - 49, 52, 50, 0, 0, 0, 537, 46, 34, 51, - 537, 0, 0, 35, 537, 0, 35, 49, 52, 50, - 35, 0, 0, 186, 35, 0, 0, 0, 35, 0, - 46, 34, 51, 0, 0, 35, 0, 0, 35, 0, - 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 49, 52, 50, 49, 52, 50, 0, 49, 52, 50, - 0, 49, 52, 50, 0, 49, 52, 50, 0, 0, - 258, 257, 49, 52, 50, 49, 52, 50, 35, 0, - 46, 34, 51, 46, 34, 51, 0, 46, 34, 51, - 35, 46, 34, 51, 0, 46, 34, 51, 35, 0, - 0, 35, 46, 34, 51, 46, 34, 51, 0, 0, - 253, 252, 0, 0, 35, 49, 52, 50, 0, 0, - 0, 186, 253, 252, 0, 0, 0, 49, 52, 50, - 258, 257, 0, 258, 257, 49, 52, 50, 49, 52, - 50, 0, 0, 0, 0, 46, 34, 51, 0, 0, - 155, 49, 52, 50, 0, 0, 0, 46, 34, 51, - 156, 0, 0, 0, 157, 46, 34, 51, 46, 34, - 51, 0, 0, 158, 0, 159, 0, 0, 0, 0, - 0, 46, 34, 51, 0, 0, 160, 0, 161, 64, - 0, 0, 0, 35, 0, 0, 162, 0, 0, 163, - 65, 0, 0, 0, 0, 164, 0, 0, 0, 0, - 0, 165, 0, 0, 0, 0, 0, 0, 0, 155, - 0, 0, 0, 0, 0, 253, 252, 166, 0, 156, - 49, 52, 50, 157, 0, 0, 0, 0, 0, 0, - 0, 0, 158, 0, 159, 0, 0, 322, 0, 0, - 0, 0, 0, 0, 0, 160, 0, 161, 64, 0, - 46, 34, 51, 0, 0, 162, 0, 0, 163, 65, - 0, 0, 155, 0, 164, 0, 0, 0, 0, 0, - 165, 0, 156, 0, 0, 0, 157, 0, 0, 0, - 0, 0, 0, 0, 0, 158, 166, 159, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, - 161, 64, 0, 0, 0, 0, 0, 0, 162, 0, - 0, 163, 65, 0, 0, 0, 0, 164, 0, 0, - 0, 0, 0, 165, 0, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 166, - 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, - 0, 0, 0, 0, 0, 0, 521, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 33, 53, 49, - 52, 50, 0, 54, 35, 0, 0, 0, 36, 37, - 0, 38, 0, 0, 44, 56, 32, 0, 42, 0, - 0, 41, 45, 0, 0, 0, 0, 0, 0, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 49, 52, 50, 0, 54, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 44, 56, 32, 0, - 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, - 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, - 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, - 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, - 0, 0, 0, 0, 42, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 53, 49, 52, 50, - 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 44, 56, 32, 0, 0, 0, 0, 41, - 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, - 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, - 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, - 36, 37, 0, 38, 0, 0, 0, 0, 0, 0, - 521, 0, 0, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 53, 49, 52, 50, 0, 54, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 44, 56, - 32, 0, 0, 0, 0, 41, 0, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 519, 0, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, - 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, - 0, 38, 0, 0, 0, 0, 0, 0, 521, 0, - 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 522, 524, 523, 0, 54, 0, 0, 0, 0, - 230, 0, 0, 0, 0, 0, 44, 56, 32, 216, - 224, 0, 0, 41, 0, 0, 520, 0, 0, 0, - 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 519, 0, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 221, 0, 0, 0, 0, - 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, - 0, 0, 0, 0, 0, 0, 521, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 585, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 53, 522, - 524, 523, 0, 54, 0, 0, 0, 0, 230, 0, - 0, 0, 0, 0, 44, 56, 32, 216, 224, 0, - 0, 41, 0, 0, 520, 0, 0, 0, 0, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 519, 0, 30, 31, 0, 0, 0, 0, 0, - 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, - 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, - 0, 0, 0, 0, 521, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 588, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 53, 522, 524, 523, - 0, 54, 0, 0, 0, 0, 230, 0, 0, 0, - 0, 0, 44, 56, 32, 216, 224, 0, 0, 41, - 0, 0, 520, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, - 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, - 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, - 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, - 55, 0, 57, 0, 58, 0, 0, 0, 0, 44, - 56, 32, 0, 0, 0, 0, 41, 0, 0, 0, - 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -141, 0, 0, 0, - 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, - 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, - 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, - 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, - 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, - 0, 55, 0, 57, 0, 58, 0, 0, 0, 0, - 44, 56, 32, 0, 0, 0, 0, 41, 0, 0, - 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 285, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 492, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 493, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 500, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 503, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 492, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 498, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 500, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 501, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, - 0, 0, 35, 222, 0, 0, 223, 37, 0, 38, - 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, - 45, 0, 0, 0, 47, 0, 48, 0, 0, 0, - 0, 0, 0, 0, 226, 0, 0, 0, 53, 49, - 52, 50, 227, 54, 0, 55, 229, 57, 0, 58, - 0, 232, 0, 0, 44, 56, 32, 0, 0, 0, - 0, 41, 0, 0, 0, 0, 0, 0, 0, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, - 222, 0, 0, 603, 650, 0, 38, 0, 0, 0, - 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, - 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, - 0, 226, 0, 0, 0, 53, 49, 52, 50, 227, - 54, 0, 55, 229, 57, 0, 58, 0, 232, 0, - 0, 44, 56, 32, 0, 0, 0, 0, 41, 0, - 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, - 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, - 0, 0, 0, 0, 0, 0, 35, 222, 0, 0, - 603, 37, 0, 38, 0, 0, 0, 39, 0, 40, - 42, 43, 0, 0, 45, 0, 0, 0, 47, 0, - 48, 0, 0, 0, 0, 0, 0, 0, 226, 0, - 0, 0, 53, 49, 52, 50, 227, 54, 0, 55, - 229, 57, 0, 58, 0, 232, 0, 0, 44, 56, - 32, 0, 0, 0, 0, 41, 0, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 111, 112, 113, 0, 0, - 115, 117, 118, 0, 0, 119, 0, 120, 0, 0, - 0, 123, 124, 125, 0, 0, 0, 0, 0, 0, - 35, 126, 127, 128, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 130, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 133, 0, 0, 0, 0, 0, 0, 49, 52, 50, - 134, 135, 136, 0, 138, 139, 140, 141, 142, 143, - 0, 0, 131, 137, 122, 114, 129, 116, 132, 0, - 0, 0, 121, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, - 112, 113, 0, 0, 115, 117, 118, 0, 0, 119, - 0, 120, 0, 0, 0, 123, 124, 125, 0, 0, - 0, 0, 0, 0, 35, 126, 127, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 130, 0, - 0, 0, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 133, 0, 0, 0, 0, 0, - 401, 49, 52, 50, 134, 135, 136, 0, 138, 139, - 140, 141, 142, 143, 0, 0, 131, 137, 122, 114, - 129, 116, 132, 0, 0, 0, 121, 0, 0, 0, - 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 111, 112, 113, 0, 0, 115, 117, - 118, 0, 0, 119, 0, 120, 0, 0, 0, 123, - 124, 125, 0, 0, 0, 0, 0, 0, 35, 126, - 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 130, 0, 0, 0, 399, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 133, 0, - 0, 0, 0, 0, 401, 49, 52, 50, 134, 135, - 136, 0, 138, 139, 140, 141, 142, 143, 0, 0, - 131, 137, 122, 114, 129, 116, 132, 0, 0, 0, - 121, 0, 0, 0, 0, 46, 377, 384, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 111, 112, 113, - 0, 0, 115, 117, 118, 0, 0, 119, 0, 120, - 0, 0, 0, 123, 124, 125, 0, 0, 0, 0, - 0, 0, 35, 126, 127, 128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, - 399, 0, 0, 0, 0, 0, 0, 0, 400, 0, - 0, 0, 133, 0, 0, 0, 0, 0, 401, 49, - 52, 50, 134, 135, 136, 0, 138, 139, 140, 141, - 142, 143, 0, 0, 131, 137, 122, 114, 129, 116, - 132, 0, 0, 0, 121, 0, 0, 0, 0, 46, - 377, 384, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 215, 0, 0, 0, 0, 217, 0, 29, 30, - 31, 219, 0, 0, 0, 0, 0, 0, 220, 33, - 0, 0, 0, 0, 0, 0, 35, 222, 0, 0, - 223, 37, 0, 38, 0, 0, 0, 39, 0, 40, - 42, 43, 0, 0, 45, 0, 0, 0, 47, 0, - 48, 0, 0, 0, 0, 0, 225, 0, 226, 0, - 0, 0, 53, 49, 52, 50, 227, 54, 228, 55, - 229, 57, 230, 58, 231, 232, 0, 0, 44, 56, - 32, 216, 224, 218, 0, 41, 0, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, - 217, 0, 29, 30, 31, 219, 0, 0, 0, 0, - 0, 0, 220, 221, 0, 0, 0, 0, 0, 0, - 35, 222, 0, 0, 223, 37, 0, 38, 0, 0, - 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, - 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, - 225, 0, 226, 0, 0, 0, 53, 49, 52, 50, - 227, 54, 228, 55, 229, 57, 230, 58, 231, 232, - 0, 0, 44, 56, 32, 216, 224, 218, 0, 41, - 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, - 112, 113, 0, 0, 609, 117, 611, 30, 31, 612, - 0, 120, 0, 0, 0, 123, 614, 615, 0, 0, - 0, 0, 0, 0, 35, 616, 127, 128, 223, 37, - 0, 38, 0, 0, 0, 39, 0, 40, 618, 43, - 0, 0, 620, 0, 0, 0, 47, 0, 48, 0, - 0, 0, 0, 0, 621, 0, 226, 0, 0, 0, - 622, 49, 52, 50, 623, 624, 625, 55, 627, 628, - 629, 630, 631, 632, 0, 0, 619, 626, 613, 608, - 617, 610, 132, 41, 0, 0, 121, 0, 0, 0, - 0, 46, 377, 384, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 112, 113, 0, 0, 370, 117, - 372, 30, 31, 373, 0, 120, 0, 0, 0, 123, - 375, 376, 0, 0, 0, 0, 0, 0, 35, 378, - 127, 128, 223, 37, 0, 38, 0, 0, 0, 39, - 0, 40, 380, 43, 0, 0, 382, 0, 0, 0, - 47, 0, 48, 0, -288, 0, 0, 0, 383, 0, - 226, 0, 0, 0, 385, 49, 52, 50, 386, 387, - 388, 55, 390, 391, 392, 393, 394, 395, 0, 0, - 381, 389, 374, 369, 379, 371, 132, 41, 0, 0, - 121, 0, 0, 0, 0, 46, 377, 384, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - - 543, 185, 640, 647, 642, 643, 504, 489, 397, 451, - 655, 657, 669, 670, 154, 680, 658, 448, 686, 316, - 185, 16, 256, 536, 251, 599, 570, 633, 572, 590, - 597, 144, 323, 540, 457, 150, 266, 473, 190, 441, - 350, 445, 251, 192, 256, 437, 429, 354, 208, 240, - 185, 316, 251, 256, 185, 404, 448, 448, 316, 533, - 566, 470, 466, 180, 451, 451, 462, 0, 62, 334, - 510, 516, 62, 0, 0, 325, 62, 299, 316, 0, - 459, 298, 397, 334, 0, 147, 461, 208, 499, 0, - 152, 208, 502, 167, 600, 479, 673, 672, 518, 173, - 175, 515, 316, 674, 208, 397, 316, 518, 316, 407, - 208, 0, 190, 0, 321, 208, 656, 352, 62, 249, - 464, 62, 62, 184, 509, 62, 62, 463, 463, 62, - 208, 508, 421, 208, 62, 208, 184, 356, 245, 358, - 405, 242, 263, 280, 62, 62, 62, 506, 284, 302, - 62, 301, 507, 208, 317, 208, 208, 62, 208, 62, - 343, 184, 300, 413, 348, 365, 62, 0, 62, 190, - 518, 62, 99, 62, 100, 578, 86, 90, 346, 62, - 208, 208, 319, 91, 344, 62, 62, 62, 413, 62, - 93, 94, 95, 473, 96, 468, 514, 62, 189, 62, - 150, 414, 97, 92, 208, 62, 472, 464, 182, 62, - 62, 208, 497, 62, 62, 397, 496, 250, 365, 62, - 104, 102, 208, 263, 208, 98, 414, 263, 169, 172, - 365, 208, 487, 62, 359, 511, 62, 250, 463, 208, - 62, 398, 464, 208, 62, 62, 606, 63, 72, 190, - 150, 208, 411, 62, 518, 69, 62, 208, 416, 582, - 365, 365, 79, 62, 62, 70, 62, 62, 483, 71, - 0, 284, 74, 0, 0, 62, 208, 208, 423, 307, - 284, 0, 62, 0, 287, 426, 108, 284, 0, 292, - 62, 62, 0, 0, 0, 284, 284, 303, 304, 62, - 312, 0, 62, 312, 284, 284, 305, 284, 284, 312, - 62, 0, 312, 309, 284, 284, 110, 284, 62, 312, - 0, 594, 333, 284, 284, 340, 578, 330, 653, 0, - 518, 331, 0, 327, 311, 586, 0, 589, 0, 527, - 0, 314, 0, 0, 518, 0, 518, 444, 447, 0, - 489, 517, 528, 527, 0, 527, 547, 548, 549, 550, - 554, 551, 552, 0, 0, 517, 528, 517, 528, 0, - 0, 0, 602, 0, 0, 0, 0, 0, 0, 0, - 108, 604, 605, 547, 548, 549, 550, 554, 551, 552, - 594, 0, 0, 0, 0, 0, 0, 0, 0, 595, - 596, 547, 548, 549, 550, 554, 551, 552, 0, 0, - 110, 179, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 602, 0, 0, 0, 0, 0, - 0, 0, 0, 651, 652, 547, 548, 549, 550, 554, - 551, 552, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 -}; - -const short QQmlJSGrammar::action_check [] = { - 7, 33, 60, 60, 7, 36, 7, 7, 60, 7, - 36, 36, 7, 7, 60, 36, 55, 7, 33, 55, - 33, 7, 36, 7, 36, 36, 7, 37, 36, 7, - 36, 7, 7, 7, 33, 7, 33, 33, 47, 66, - 17, 34, 47, 66, 29, 37, 29, 29, 17, 29, - 29, 17, 5, 5, 5, 20, 60, 7, 60, 8, - 33, 7, 33, 33, 55, 33, 55, 7, 55, 36, - 33, 33, 60, 33, 7, 36, 33, 36, 36, 33, - 8, 7, 2, 7, 1, 8, 1, 8, 1, 36, - 8, 2, 8, -1, 2, -1, 60, -1, 33, 55, - 55, 7, 36, 1, 48, 0, 7, 36, 2, 36, - 48, 36, 60, 17, 33, 60, 48, 16, 8, 55, - 61, 60, 36, 7, 36, 8, 36, 36, 8, 60, - 8, 8, 6, 8, 15, -1, 79, 79, 8, 61, - 77, 48, 15, 7, 8, 8, 20, 15, 15, 79, - -1, 24, 8, 34, 8, 8, -1, -1, 61, 61, - 62, 61, 62, 8, 61, 62, 34, 34, 50, 61, - 62, 50, 54, 8, 79, 54, 8, 60, 56, 10, - 60, 56, 40, 60, 8, 61, 62, 8, 40, 12, - 60, 7, 55, 51, 40, 61, 62, 93, 94, 51, - 61, 62, 31, 7, 60, 51, 60, 60, 93, 94, - 15, 56, 61, 62, 61, 62, 42, 61, 62, 24, - 15, 56, 61, 62, 55, 61, 62, 53, 60, 33, - 29, 29, 7, 12, 57, 56, 25, 61, 27, 34, - 63, 36, 25, 7, 27, 61, 62, 29, 25, 38, - 27, 25, 25, 27, 27, 38, 25, 29, 27, 95, - -1, 38, 29, -1, 38, 38, 29, -1, 12, 38, - 36, 29, 25, -1, 27, -1, 75, 75, 57, 40, - 15, 8, -1, 8, 63, 38, 61, 62, 87, 87, - 51, -1, 96, 75, -1, 61, 62, 61, 62, 34, - -1, 36, 15, 75, 8, 87, -1, -1, 75, 25, - -1, 27, 75, 57, 25, 87, 27, 75, -1, 63, - 87, 34, 38, 36, 87, 61, 62, 38, 25, 87, - 27, 25, -1, 27, 61, 62, 61, 62, 25, -1, - 27, 38, 15, 25, 38, 27, 15, 15, 18, 19, - -1, 38, 18, 19, 90, 47, 38, 61, 62, -1, - 33, 34, -1, 36, 33, 34, 34, 36, 36, 61, - 62, -1, 23, 24, -1, 45, 46, -1, -1, 45, - 46, 32, 23, 24, 35, -1, 37, -1, 23, 24, - -1, 32, 23, 24, 35, -1, 37, 32, 23, 24, - 35, 32, 37, 95, 35, -1, 37, 32, 23, 24, - 35, -1, 37, -1, -1, -1, 31, 32, 23, 24, - 35, 29, 37, -1, -1, 29, 31, 32, -1, -1, - 35, -1, 37, 29, 23, 24, 29, -1, -1, 29, - 18, 19, 31, 32, 29, -1, 35, 29, 37, -1, - 100, 101, 102, 103, 104, 105, -1, -1, 66, 67, - 68, -1, 66, 67, 68, -1, -1, 45, 46, -1, - 66, 67, 68, 66, 67, 68, 66, 67, 68, -1, - 29, 66, 67, 68, 66, 67, 68, 29, 96, 97, - 98, -1, 96, 97, 98, 29, -1, -1, 29, -1, - 96, 97, 98, 96, 97, 98, 96, 97, 98, -1, - -1, 96, 97, 98, 96, 97, 98, 66, 67, 68, - 29, -1, -1, -1, 66, 67, 68, -1, -1, -1, - 23, 24, 66, 67, 68, 66, 67, 68, 31, 32, - -1, -1, 35, 29, 37, -1, 15, 96, 97, 98, - 36, -1, -1, -1, 96, 97, 98, 66, 67, 68, - 29, -1, 96, 97, 98, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, - 66, 67, 68, -1, -1, -1, 15, 96, 97, 98, - 15, -1, -1, 29, 15, -1, 29, 66, 67, 68, - 29, -1, -1, 36, 29, -1, -1, -1, 29, -1, - 96, 97, 98, -1, -1, 29, -1, -1, 29, -1, - -1, -1, -1, -1, -1, -1, -1, 96, 97, 98, - 66, 67, 68, 66, 67, 68, -1, 66, 67, 68, - -1, 66, 67, 68, -1, 66, 67, 68, -1, -1, - 61, 62, 66, 67, 68, 66, 67, 68, 29, -1, - 96, 97, 98, 96, 97, 98, -1, 96, 97, 98, - 29, 96, 97, 98, -1, 96, 97, 98, 29, -1, - -1, 29, 96, 97, 98, 96, 97, 98, -1, -1, - 61, 62, -1, -1, 29, 66, 67, 68, -1, -1, - -1, 36, 61, 62, -1, -1, -1, 66, 67, 68, - 61, 62, -1, 61, 62, 66, 67, 68, 66, 67, - 68, -1, -1, -1, -1, 96, 97, 98, -1, -1, - 3, 66, 67, 68, -1, -1, -1, 96, 97, 98, - 13, -1, -1, -1, 17, 96, 97, 98, 96, 97, - 98, -1, -1, 26, -1, 28, -1, -1, -1, -1, - -1, 96, 97, 98, -1, -1, 39, -1, 41, 42, - -1, -1, -1, 29, -1, -1, 49, -1, -1, 52, - 53, -1, -1, -1, -1, 58, -1, -1, -1, -1, - -1, 64, -1, -1, -1, -1, -1, -1, -1, 3, - -1, -1, -1, -1, -1, 61, 62, 80, -1, 13, - 66, 67, 68, 17, -1, -1, -1, -1, -1, -1, - -1, -1, 26, -1, 28, -1, -1, 31, -1, -1, - -1, -1, -1, -1, -1, 39, -1, 41, 42, -1, - 96, 97, 98, -1, -1, 49, -1, -1, 52, 53, - -1, -1, 3, -1, 58, -1, -1, -1, -1, -1, - 64, -1, 13, -1, -1, -1, 17, -1, -1, -1, - -1, -1, -1, -1, -1, 26, 80, 28, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, - 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, - -1, 52, 53, -1, -1, -1, -1, 58, -1, -1, - -1, -1, -1, 64, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, 80, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, 65, 66, - 67, 68, -1, 70, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, 81, 82, 83, -1, 43, -1, - -1, 88, 47, -1, -1, -1, -1, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, -1, 88, -1, -1, -1, -1, -1, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, - -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, - 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, - -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 81, 82, 83, -1, -1, -1, -1, 88, - -1, -1, -1, -1, -1, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, - 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, - 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, -1, 88, -1, -1, -1, -1, - -1, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, - -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, - 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, - 85, -1, -1, 88, -1, -1, 91, -1, -1, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, - -1, -1, -1, -1, 81, 82, 83, 84, 85, -1, - -1, 88, -1, -1, 91, -1, -1, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, - -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, - 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, - -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, - -1, -1, 81, 82, 83, 84, 85, -1, -1, 88, - -1, -1, 91, -1, -1, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, -1, 88, -1, -1, -1, - -1, -1, -1, -1, 96, 97, 98, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, - 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, - -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, - 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, - -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, - 81, 82, 83, -1, -1, -1, -1, 88, -1, -1, - -1, -1, -1, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, 75, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, - -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, - -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, - 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, - -1, 78, -1, -1, 81, 82, 83, -1, -1, -1, - -1, 88, -1, -1, -1, -1, -1, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, - -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, - 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, - -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, - 70, -1, 72, 73, 74, -1, 76, -1, 78, -1, - -1, 81, 82, 83, -1, -1, -1, -1, 88, -1, - -1, -1, -1, -1, -1, -1, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, - 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, - 83, -1, -1, -1, -1, 88, -1, -1, -1, -1, - -1, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, - 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, - -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, - 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 59, -1, -1, -1, -1, -1, -1, 66, 67, 68, - 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, - -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, - -1, -1, 91, -1, -1, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, - 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, - -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, - -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, - -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, - 65, 66, 67, 68, 69, 70, 71, -1, 73, 74, - 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, - 85, 86, 87, -1, -1, -1, 91, -1, -1, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, - 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, - 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, - 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, - -1, -1, -1, -1, 65, 66, 67, 68, 69, 70, - 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, - 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, - 91, -1, -1, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, - -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, - -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, - -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, - -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, - 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, - 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, - 87, -1, -1, -1, 91, -1, -1, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, - 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, - -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, - 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, - 83, 84, 85, 86, -1, 88, -1, -1, -1, -1, - -1, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, - 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, - -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, - 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, - -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, - -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, - 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - -1, -1, 81, 82, 83, 84, 85, 86, -1, 88, - -1, -1, -1, -1, -1, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, - 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, - -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, - -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, - 85, 86, 87, 88, -1, -1, 91, -1, -1, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, - 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, - 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, - 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, - -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, - 51, -1, 53, -1, 55, -1, -1, -1, 59, -1, - 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, - 81, 82, 83, 84, 85, 86, 87, 88, -1, -1, - 91, -1, -1, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - - 18, 18, 32, 18, 32, 18, 3, 43, 18, 25, - 22, 22, 14, 14, 78, 18, 9, 3, 18, 3, - 18, 3, 18, 32, 18, 32, 32, 22, 18, 18, - 22, 3, 3, 18, 106, 43, 3, 18, 18, 101, - 3, 3, 18, 18, 18, 104, 3, 3, 18, 18, - 18, 3, 18, 18, 18, 43, 3, 3, 3, 32, - 14, 3, 3, 3, 25, 25, 25, -1, 55, 18, - 57, 2, 55, -1, -1, 2, 55, 60, 3, -1, - 18, 60, 18, 18, -1, 43, 25, 18, 43, -1, - 43, 18, 43, 43, 18, 43, 11, 12, 14, 43, - 43, 4, 3, 19, 18, 18, 3, 14, 3, 45, - 18, -1, 18, -1, 2, 18, 23, 2, 55, 2, - 57, 55, 55, 57, 57, 55, 55, 57, 57, 55, - 18, 57, 45, 18, 55, 18, 57, 2, 46, 2, - 2, 47, 2, 55, 55, 55, 55, 57, 60, 60, - 55, 60, 57, 18, 79, 18, 18, 55, 18, 55, - 95, 57, 60, 14, 2, 2, 55, -1, 55, 18, - 14, 55, 61, 55, 61, 19, 60, 59, 79, 55, - 18, 18, 79, 59, 79, 55, 55, 55, 14, 55, - 60, 60, 60, 18, 60, 2, 110, 55, 47, 55, - 43, 52, 60, 59, 18, 55, 2, 57, 51, 55, - 55, 18, 39, 55, 55, 18, 43, 4, 2, 55, - 65, 67, 18, 2, 18, 61, 52, 2, 69, 71, - 2, 18, 46, 55, 18, 57, 55, 4, 57, 18, - 55, 44, 57, 18, 55, 55, 18, 58, 58, 18, - 43, 18, 46, 55, 14, 57, 55, 18, 51, 19, - 2, 2, 61, 55, 55, 57, 55, 55, 93, 57, - -1, 60, 63, -1, -1, 55, 18, 18, 47, 68, - 60, -1, 55, -1, 64, 46, 18, 60, -1, 62, - 55, 55, -1, -1, -1, 60, 60, 62, 62, 55, - 55, -1, 55, 55, 60, 60, 62, 60, 60, 55, - 55, -1, 55, 66, 60, 60, 48, 60, 55, 55, - -1, 14, 77, 60, 60, 77, 19, 72, 21, -1, - 14, 77, -1, 70, 77, 5, -1, 5, -1, 23, - -1, 77, -1, -1, 14, -1, 14, 89, 89, -1, - 43, 35, 36, 23, -1, 23, 25, 26, 27, 28, - 29, 30, 31, -1, -1, 35, 36, 35, 36, -1, - -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, - 18, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 14, -1, -1, -1, -1, -1, -1, -1, -1, 23, - 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, - 48, 49, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, - -1, -1, -1, 23, 24, 25, 26, 27, 28, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1 -}; - -QT_END_NAMESPACE diff --git a/src/qml/parser/qqmljsgrammar_p.h b/src/qml/parser/qqmljsgrammar_p.h deleted file mode 100644 index 9d028f2191..0000000000 --- a/src/qml/parser/qqmljsgrammar_p.h +++ /dev/null @@ -1,215 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// This file was generated by qlalr - DO NOT EDIT! -#ifndef QQMLJSGRAMMAR_P_H -#define QQMLJSGRAMMAR_P_H - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class QQmlJSGrammar -{ -public: - enum VariousConstants { - EOF_SYMBOL = 0, - REDUCE_HERE = 107, - SHIFT_THERE = 106, - T_AND = 1, - T_AND_AND = 2, - T_AND_EQ = 3, - T_AS = 95, - T_AUTOMATIC_SEMICOLON = 62, - T_BREAK = 4, - T_CASE = 5, - T_CATCH = 6, - T_COLON = 7, - T_COMMA = 8, - T_COMMENT = 89, - T_COMPATIBILITY_SEMICOLON = 90, - T_CONST = 84, - T_CONTINUE = 9, - T_DEBUGGER = 86, - T_DEFAULT = 10, - T_DELETE = 11, - T_DIVIDE_ = 12, - T_DIVIDE_EQ = 13, - T_DO = 14, - T_DOT = 15, - T_ELSE = 16, - T_ENUM = 91, - T_EQ = 17, - T_EQ_EQ = 18, - T_EQ_EQ_EQ = 19, - T_ERROR = 99, - T_FALSE = 83, - T_FEED_JS_EXPRESSION = 103, - T_FEED_JS_PROGRAM = 105, - T_FEED_JS_SOURCE_ELEMENT = 104, - T_FEED_JS_STATEMENT = 102, - T_FEED_UI_OBJECT_MEMBER = 101, - T_FEED_UI_PROGRAM = 100, - T_FINALLY = 20, - T_FOR = 21, - T_FUNCTION = 22, - T_GE = 23, - T_GET = 97, - T_GT = 24, - T_GT_GT = 25, - T_GT_GT_EQ = 26, - T_GT_GT_GT = 27, - T_GT_GT_GT_EQ = 28, - T_IDENTIFIER = 29, - T_IF = 30, - T_IMPORT = 93, - T_IN = 31, - T_INSTANCEOF = 32, - T_LBRACE = 33, - T_LBRACKET = 34, - T_LE = 35, - T_LET = 85, - T_LPAREN = 36, - T_LT = 37, - T_LT_LT = 38, - T_LT_LT_EQ = 39, - T_MINUS = 40, - T_MINUS_EQ = 41, - T_MINUS_MINUS = 42, - T_MULTILINE_STRING_LITERAL = 88, - T_NEW = 43, - T_NOT = 44, - T_NOT_EQ = 45, - T_NOT_EQ_EQ = 46, - T_NULL = 81, - T_NUMERIC_LITERAL = 47, - T_ON = 96, - T_OR = 48, - T_OR_EQ = 49, - T_OR_OR = 50, - T_PLUS = 51, - T_PLUS_EQ = 52, - T_PLUS_PLUS = 53, - T_PRAGMA = 94, - T_PROPERTY = 66, - T_PUBLIC = 92, - T_QUESTION = 54, - T_RBRACE = 55, - T_RBRACKET = 56, - T_READONLY = 68, - T_REMAINDER = 57, - T_REMAINDER_EQ = 58, - T_RESERVED_WORD = 87, - T_RETURN = 59, - T_RPAREN = 60, - T_SEMICOLON = 61, - T_SET = 98, - T_SIGNAL = 67, - T_STAR = 63, - T_STAR_EQ = 64, - T_STRING_LITERAL = 65, - T_SWITCH = 69, - T_THIS = 70, - T_THROW = 71, - T_TILDE = 72, - T_TRUE = 82, - T_TRY = 73, - T_TYPEOF = 74, - T_VAR = 75, - T_VOID = 76, - T_WHILE = 77, - T_WITH = 78, - T_XOR = 79, - T_XOR_EQ = 80, - - ACCEPT_STATE = 691, - RULE_COUNT = 369, - STATE_COUNT = 692, - TERMINAL_COUNT = 108, - NON_TERMINAL_COUNT = 112, - - GOTO_INDEX_OFFSET = 692, - GOTO_INFO_OFFSET = 3357, - GOTO_CHECK_OFFSET = 3357 - }; - - static const char *const spell[]; - static const short lhs[]; - static const short rhs[]; - static const short goto_default[]; - static const short action_default[]; - static const short action_index[]; - static const short action_info[]; - static const short action_check[]; - - static inline int nt_action (int state, int nt) - { - const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; - if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) - return goto_default [nt]; - - return action_info [GOTO_INFO_OFFSET + yyn]; - } - - static inline int t_action (int state, int token) - { - const int yyn = action_index [state] + token; - - if (yyn < 0 || action_check [yyn] != token) - return - action_default [state]; - - return action_info [yyn]; - } -}; - - -QT_END_NAMESPACE -#endif // QQMLJSGRAMMAR_P_H - diff --git a/src/qml/parser/qqmljskeywords_p.h b/src/qml/parser/qqmljskeywords_p.h index 20daf545a9..9cc47469e5 100644 --- a/src/qml/parser/qqmljskeywords_p.h +++ b/src/qml/parser/qqmljskeywords_p.h @@ -57,10 +57,10 @@ QT_QML_BEGIN_NAMESPACE namespace QQmlJS { -static inline int classify2(const QChar *s, bool qmlMode) { +static inline int classify2(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'a') { if (s[1].unicode() == 's') { - return qmlMode ? Lexer::T_AS : Lexer::T_IDENTIFIER; + return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_AS : Lexer::T_IDENTIFIER; } } else if (s[0].unicode() == 'd') { @@ -76,15 +76,15 @@ static inline int classify2(const QChar *s, bool qmlMode) { return Lexer::T_IN; } } - else if (qmlMode && s[0].unicode() == 'o') { + else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'o') { if (s[1].unicode() == 'n') { - return qmlMode ? Lexer::T_ON : Lexer::T_IDENTIFIER; + return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_ON : Lexer::T_IDENTIFIER; } } return Lexer::T_IDENTIFIER; } -static inline int classify3(const QChar *s, bool qmlMode) { +static inline int classify3(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'f') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'r') { @@ -102,7 +102,7 @@ static inline int classify3(const QChar *s, bool qmlMode) { else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'n') { if (s[2].unicode() == 't') { - return qmlMode ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER); } } } @@ -144,12 +144,12 @@ static inline int classify3(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify4(const QChar *s, bool qmlMode) { +static inline int classify4(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'y') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { - return qmlMode ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER); } } } @@ -165,7 +165,7 @@ static inline int classify4(const QChar *s, bool qmlMode) { else if (s[1].unicode() == 'h') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'r') { - return qmlMode ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER); } } } @@ -181,7 +181,16 @@ static inline int classify4(const QChar *s, bool qmlMode) { else if (s[1].unicode() == 'n') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'm') { - return qmlMode ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD); + } + } + } + } + else if (s[0].unicode() == 'f') { + if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'o') { + if (s[3].unicode() == 'm') { + return int(Lexer::T_FROM); } } } @@ -190,7 +199,7 @@ static inline int classify4(const QChar *s, bool qmlMode) { if (s[1].unicode() == 'o') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'o') { - return qmlMode ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER); } } } @@ -199,7 +208,7 @@ static inline int classify4(const QChar *s, bool qmlMode) { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'g') { - return qmlMode ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER); } } } @@ -250,7 +259,7 @@ static inline int classify4(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify5(const QChar *s, bool qmlMode) { +static inline int classify5(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'e') { @@ -305,7 +314,7 @@ static inline int classify5(const QChar *s, bool qmlMode) { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'l') { - return qmlMode ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER); } } } @@ -314,7 +323,7 @@ static inline int classify5(const QChar *s, bool qmlMode) { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 't') { - return qmlMode ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER); } } } @@ -325,7 +334,7 @@ static inline int classify5(const QChar *s, bool qmlMode) { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'r') { if (s[4].unicode() == 't') { - return qmlMode ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER); } } } @@ -334,7 +343,7 @@ static inline int classify5(const QChar *s, bool qmlMode) { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'r') { - return qmlMode ? int(Lexer::T_SUPER) : int(Lexer::T_RESERVED_WORD); + return int(Lexer::T_SUPER); } } } @@ -362,10 +371,21 @@ static inline int classify5(const QChar *s, bool qmlMode) { } } } + else if (s[0].unicode() == 'y') { + if (s[1].unicode() == 'i') { + if (s[2].unicode() == 'e') { + if (s[3].unicode() == 'l') { + if (s[4].unicode() == 'd') { + return (parseModeFlags & Lexer::YieldIsKeyword) ? Lexer::T_YIELD : Lexer::T_IDENTIFIER; + } + } + } + } + } return Lexer::T_IDENTIFIER; } -static inline int classify6(const QChar *s, bool qmlMode) { +static inline int classify6(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'l') { @@ -383,7 +403,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 'b') { if (s[4].unicode() == 'l') { if (s[5].unicode() == 'e') { - return qmlMode ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER); } } } @@ -409,7 +429,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 't') { - return qmlMode ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD); } } } @@ -422,7 +442,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 'i') { if (s[4].unicode() == 'v') { if (s[5].unicode() == 'e') { - return qmlMode ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER); } } } @@ -435,7 +455,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'c') { - return qmlMode ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER; + return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER; } } } @@ -446,7 +466,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 'g') { if (s[4].unicode() == 'm') { if (s[5].unicode() == 'a') { - return qmlMode ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER; + return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER; } } } @@ -467,7 +487,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { } } else if (s[0].unicode() == 's') { - if (qmlMode && s[1].unicode() == 'i') { + if ((parseModeFlags & Lexer::QmlMode) && s[1].unicode() == 'i') { if (s[2].unicode() == 'g') { if (s[3].unicode() == 'n') { if (s[4].unicode() == 'a') { @@ -483,7 +503,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 't') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'c') { - return qmlMode ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::StaticIsKeyword) ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER); } } } @@ -507,7 +527,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'w') { if (s[5].unicode() == 's') { - return qmlMode ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER); } } } @@ -528,7 +548,7 @@ static inline int classify6(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify7(const QChar *s, bool qmlMode) { +static inline int classify7(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'o') { @@ -536,7 +556,7 @@ static inline int classify7(const QChar *s, bool qmlMode) { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'a') { if (s[6].unicode() == 'n') { - return qmlMode ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER); } } } @@ -596,7 +616,7 @@ static inline int classify7(const QChar *s, bool qmlMode) { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'g') { if (s[6].unicode() == 'e') { - return qmlMode ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER); } } } @@ -609,7 +629,7 @@ static inline int classify7(const QChar *s, bool qmlMode) { if (s[4].unicode() == 'a') { if (s[5].unicode() == 't') { if (s[6].unicode() == 'e') { - return qmlMode ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER); } } } @@ -620,7 +640,7 @@ static inline int classify7(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify8(const QChar *s, bool qmlMode) { +static inline int classify8(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'a') { if (s[1].unicode() == 'b') { if (s[2].unicode() == 's') { @@ -629,7 +649,7 @@ static inline int classify8(const QChar *s, bool qmlMode) { if (s[5].unicode() == 'a') { if (s[6].unicode() == 'c') { if (s[7].unicode() == 't') { - return qmlMode ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER); } } } @@ -689,7 +709,7 @@ static inline int classify8(const QChar *s, bool qmlMode) { } } } - else if (qmlMode && s[0].unicode() == 'p') { + else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'p') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'p') { @@ -706,7 +726,7 @@ static inline int classify8(const QChar *s, bool qmlMode) { } } } - else if (qmlMode && s[0].unicode() == 'r') { + else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'r') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'd') { @@ -731,7 +751,7 @@ static inline int classify8(const QChar *s, bool qmlMode) { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'l') { if (s[7].unicode() == 'e') { - return qmlMode ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER); } } } @@ -743,7 +763,7 @@ static inline int classify8(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify9(const QChar *s, bool qmlMode) { +static inline int classify9(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'i') { if (s[1].unicode() == 'n') { if (s[2].unicode() == 't') { @@ -753,7 +773,7 @@ static inline int classify9(const QChar *s, bool qmlMode) { if (s[6].unicode() == 'a') { if (s[7].unicode() == 'c') { if (s[8].unicode() == 'e') { - return qmlMode ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER); } } } @@ -772,7 +792,7 @@ static inline int classify9(const QChar *s, bool qmlMode) { if (s[6].unicode() == 't') { if (s[7].unicode() == 'e') { if (s[8].unicode() == 'd') { - return qmlMode ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER); } } } @@ -791,7 +811,7 @@ static inline int classify9(const QChar *s, bool qmlMode) { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 't') { - return qmlMode ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER); } } } @@ -804,7 +824,7 @@ static inline int classify9(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify10(const QChar *s, bool qmlMode) { +static inline int classify10(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 'i') { if (s[1].unicode() == 'm') { if (s[2].unicode() == 'p') { @@ -815,7 +835,7 @@ static inline int classify10(const QChar *s, bool qmlMode) { if (s[7].unicode() == 'n') { if (s[8].unicode() == 't') { if (s[9].unicode() == 's') { - return qmlMode ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER); } } } @@ -848,7 +868,7 @@ static inline int classify10(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -static inline int classify12(const QChar *s, bool qmlMode) { +static inline int classify12(const QChar *s, int parseModeFlags) { if (s[0].unicode() == 's') { if (s[1].unicode() == 'y') { if (s[2].unicode() == 'n') { @@ -861,7 +881,7 @@ static inline int classify12(const QChar *s, bool qmlMode) { if (s[9].unicode() == 'z') { if (s[10].unicode() == 'e') { if (s[11].unicode() == 'd') { - return qmlMode ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER); + return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER); } } } @@ -877,18 +897,18 @@ static inline int classify12(const QChar *s, bool qmlMode) { return Lexer::T_IDENTIFIER; } -int Lexer::classify(const QChar *s, int n, bool qmlMode) { +int Lexer::classify(const QChar *s, int n, int parseModeFlags) { switch (n) { - case 2: return classify2(s, qmlMode); - case 3: return classify3(s, qmlMode); - case 4: return classify4(s, qmlMode); - case 5: return classify5(s, qmlMode); - case 6: return classify6(s, qmlMode); - case 7: return classify7(s, qmlMode); - case 8: return classify8(s, qmlMode); - case 9: return classify9(s, qmlMode); - case 10: return classify10(s, qmlMode); - case 12: return classify12(s, qmlMode); + case 2: return classify2(s, parseModeFlags); + case 3: return classify3(s, parseModeFlags); + case 4: return classify4(s, parseModeFlags); + case 5: return classify5(s, parseModeFlags); + case 6: return classify6(s, parseModeFlags); + case 7: return classify7(s, parseModeFlags); + case 8: return classify8(s, parseModeFlags); + case 9: return classify9(s, parseModeFlags); + case 10: return classify10(s, parseModeFlags); + case 12: return classify12(s, parseModeFlags); default: return Lexer::T_IDENTIFIER; } // switch } diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp index aab9025a08..1165183483 100644 --- a/src/qml/parser/qqmljslexer.cpp +++ b/src/qml/parser/qqmljslexer.cpp @@ -77,22 +77,15 @@ static inline QChar convertHex(QChar c1, QChar c2) return QChar((convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); } -static inline QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4) -{ - return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()), - (convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); -} - Lexer::Lexer(Engine *engine) : _engine(engine) , _codePtr(nullptr) , _endPtr(nullptr) - , _lastLinePtr(nullptr) - , _tokenLinePtr(nullptr) , _tokenStartPtr(nullptr) , _char(QLatin1Char('\n')) , _errorCode(NoError) , _currentLineNumber(0) + , _currentColumnNumber(0) , _tokenValue(0) , _parenthesesState(IgnoreParentheses) , _parenthesesCount(0) @@ -101,6 +94,7 @@ Lexer::Lexer(Engine *engine) , _tokenKind(0) , _tokenLength(0) , _tokenLine(0) + , _tokenColumn(0) , _validTokenText(false) , _prohibitAutomaticSemicolon(false) , _restrictedKeyword(false) @@ -137,14 +131,13 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode) _codePtr = code.unicode(); _endPtr = _codePtr + code.length(); - _lastLinePtr = _codePtr; - _tokenLinePtr = _codePtr; _tokenStartPtr = _codePtr; _char = QLatin1Char('\n'); _errorCode = NoError; _currentLineNumber = lineno; + _currentColumnNumber = 0; _tokenValue = 0; // parentheses state @@ -156,6 +149,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode) _patternFlags = 0; _tokenLength = 0; _tokenLine = lineno; + _tokenColumn = 0; _validTokenText = false; _prohibitAutomaticSemicolon = false; @@ -172,9 +166,10 @@ void Lexer::scanChar() if (sequenceLength == 2) _char = *_codePtr++; - if (unsigned sequenceLength = isLineTerminatorSequence()) { - _lastLinePtr = _codePtr + sequenceLength - 1; // points to the first character after the newline + ++_currentColumnNumber; + if (isLineTerminator()) { ++_currentLineNumber; + _currentColumnNumber = 0; } } @@ -222,12 +217,32 @@ inline bool isBinop(int tok) return false; } } + +int hexDigit(QChar c) +{ + if (c >= QLatin1Char('0') && c <= QLatin1Char('9')) + return c.unicode() - '0'; + if (c >= QLatin1Char('a') && c <= QLatin1Char('f')) + return c.unicode() - 'a' + 10; + if (c >= QLatin1Char('A') && c <= QLatin1Char('F')) + return c.unicode() - 'A' + 10; + return -1; +} + +int octalDigit(QChar c) +{ + if (c >= QLatin1Char('0') && c <= QLatin1Char('7')) + return c.unicode() - '0'; + return -1; +} + } // anonymous namespace int Lexer::lex() { const int previousTokenKind = _tokenKind; + again: _tokenSpell = QStringRef(); _tokenKind = scanToken(); _tokenLength = _codePtr - _tokenStartPtr - 1; @@ -239,6 +254,9 @@ int Lexer::lex() // update the flags switch (_tokenKind) { case T_LBRACE: + if (_bracesCount > 0) + ++_bracesCount; + Q_FALLTHROUGH(); case T_SEMICOLON: case T_QUESTION: case T_COLON: @@ -269,6 +287,11 @@ int Lexer::lex() case T_THROW: _restrictedKeyword = true; break; + case T_RBRACE: + if (_bracesCount > 0) + --_bracesCount; + if (_bracesCount == 0) + goto again; } // switch // update the parentheses state @@ -295,39 +318,57 @@ int Lexer::lex() return _tokenKind; } -bool Lexer::isUnicodeEscapeSequence(const QChar *chars) -{ - if (isHexDigit(chars[0]) && isHexDigit(chars[1]) && isHexDigit(chars[2]) && isHexDigit(chars[3])) - return true; - - return false; -} - -QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok) +uint Lexer::decodeUnicodeEscapeCharacter(bool *ok) { - if (_char == QLatin1Char('u') && isUnicodeEscapeSequence(&_codePtr[0])) { - scanChar(); // skip u + Q_ASSERT(_char == QLatin1Char('u')); + scanChar(); // skip u + if (_codePtr + 4 <= _endPtr && isHexDigit(_char)) { + uint codePoint = 0; + for (int i = 0; i < 4; ++i) { + int digit = hexDigit(_char); + if (digit < 0) + goto error; + codePoint *= 16; + codePoint += digit; + scanChar(); + } - const QChar c1 = _char; - scanChar(); + *ok = true; + return codePoint; + } else if (_codePtr < _endPtr && _char == QLatin1Char('{')) { + scanChar(); // skip '{' + uint codePoint = 0; + if (!isHexDigit(_char)) + // need at least one hex digit + goto error; - const QChar c2 = _char; - scanChar(); + while (_codePtr <= _endPtr) { + int digit = hexDigit(_char); + if (digit < 0) + break; + codePoint *= 16; + codePoint += digit; + if (codePoint > 0x10ffff) + goto error; + scanChar(); + } - const QChar c3 = _char; - scanChar(); + if (_char != QLatin1Char('}')) + goto error; - const QChar c4 = _char; - scanChar(); + scanChar(); // skip '}' - if (ok) - *ok = true; - return convertUnicode(c1, c2, c3, c4); + *ok = true; + return codePoint; } + error: + _errorCode = IllegalUnicodeEscapeSequence; + _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence"); + *ok = false; - return QChar(); + return 0; } QChar Lexer::decodeHexEscapeCharacter(bool *ok) @@ -351,15 +392,15 @@ QChar Lexer::decodeHexEscapeCharacter(bool *ok) return QChar(); } -static inline bool isIdentifierStart(QChar ch) +static inline bool isIdentifierStart(uint ch) { // fast path for ascii - if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || - (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || + if ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || ch == '$' || ch == '_') return true; - switch (ch.category()) { + switch (QChar::category(ch)) { case QChar::Number_Letter: case QChar::Letter_Uppercase: case QChar::Letter_Lowercase: @@ -373,17 +414,17 @@ static inline bool isIdentifierStart(QChar ch) return false; } -static bool isIdentifierPart(QChar ch) +static bool isIdentifierPart(uint ch) { // fast path for ascii - if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || - (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || - (ch.unicode() >= '0' && ch.unicode() <= '9') || + if ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || ch == '$' || ch == '_' || - ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */) + ch == 0x200c /* ZWNJ */ || ch == 0x200d /* ZWJ */) return true; - switch (ch.category()) { + switch (QChar::category(ch)) { case QChar::Mark_NonSpacing: case QChar::Mark_SpacingCombining: @@ -412,19 +453,23 @@ int Lexer::scanToken() return tk; } + if (_bracesCount == 0) { + // we're inside a Template string + return scanString(TemplateContinuation); + } + + _terminator = false; again: _validTokenText = false; - _tokenLinePtr = _lastLinePtr; while (_char.isSpace()) { - if (unsigned sequenceLength = isLineTerminatorSequence()) { - _tokenLinePtr = _codePtr + sequenceLength - 1; - + if (isLineTerminator()) { if (_restrictedKeyword) { // automatic semicolon insertion _tokenLine = _currentLineNumber; + _tokenColumn = _currentColumnNumber; _tokenStartPtr = _codePtr - 1; return T_SEMICOLON; } else { @@ -438,6 +483,7 @@ again: _tokenStartPtr = _codePtr - 1; _tokenLine = _currentLineNumber; + _tokenColumn = _currentColumnNumber; if (_codePtr > _endPtr) return EOF_SYMBOL; @@ -501,6 +547,9 @@ again: return T_EQ_EQ_EQ; } return T_EQ_EQ; + } else if (_char == QLatin1Char('>')) { + scanChar(); + return T_ARROW; } return T_EQ; @@ -557,50 +606,18 @@ again: return T_DIVIDE_; case '.': - if (_char.isDigit()) { - QVarLengthArray<char,32> chars; - - chars.append(ch.unicode()); // append the `.' - - while (_char.isDigit()) { - chars.append(_char.unicode()); + if (isDecimalDigit(_char.unicode())) + return scanNumber(ch); + if (_char == QLatin1Char('.')) { + scanChar(); + if (_char == QLatin1Char('.')) { scanChar(); - } - - if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { - if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && - _codePtr[1].isDigit())) { - - chars.append(_char.unicode()); - scanChar(); // consume `e' - - if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { - chars.append(_char.unicode()); - scanChar(); // consume the sign - } - - while (_char.isDigit()) { - chars.append(_char.unicode()); - scanChar(); - } - } - } - - chars.append('\0'); - - const char *begin = chars.constData(); - const char *end = nullptr; - bool ok = false; - - _tokenValue = qstrtod(begin, &end, &ok); - - if (end - begin != chars.size() - 1) { - _errorCode = IllegalExponentIndicator; - _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal syntax for exponential number"); + return T_ELLIPSIS; + } else { + _errorCode = IllegalCharacter; + _errorMessage = QCoreApplication::translate("QQmlParser", "Unexpected token '.'"); return T_ERROR; } - - return T_NUMERIC_LITERAL; } return T_DOT; @@ -642,6 +659,9 @@ again: if (_char == QLatin1Char('=')) { scanChar(); return T_STAR_EQ; + } else if (_char == QLatin1Char('*')) { + scanChar(); + return T_STAR_STAR; } return T_STAR; @@ -676,141 +696,12 @@ again: } return T_NOT; + case '`': + _outerTemplateBraceCount.push(_bracesCount); + Q_FALLTHROUGH(); case '\'': - case '"': { - const QChar quote = ch; - bool multilineStringLiteral = false; - - const QChar *startCode = _codePtr; - - if (_engine) { - while (_codePtr <= _endPtr) { - if (isLineTerminator()) { - if (qmlMode()) - break; - _errorCode = IllegalCharacter; - _errorMessage = QCoreApplication::translate("QQmlParser", "Stray newline in string literal"); - return T_ERROR; - } else if (_char == QLatin1Char('\\')) { - break; - } else if (_char == quote) { - _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); - scanChar(); - - return T_STRING_LITERAL; - } - scanChar(); - } - } - - _validTokenText = true; - _tokenText.resize(0); - startCode--; - while (startCode != _codePtr - 1) - _tokenText += *startCode++; - - while (_codePtr <= _endPtr) { - if (unsigned sequenceLength = isLineTerminatorSequence()) { - multilineStringLiteral = true; - _tokenText += _char; - if (sequenceLength == 2) - _tokenText += *_codePtr; - scanChar(); - } else if (_char == quote) { - scanChar(); - - if (_engine) - _tokenSpell = _engine->newStringRef(_tokenText); - - return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL; - } else if (_char == QLatin1Char('\\')) { - scanChar(); - if (_codePtr > _endPtr) { - _errorCode = IllegalEscapeSequence; - _errorMessage = QCoreApplication::translate("QQmlParser", "End of file reached at escape sequence"); - return T_ERROR; - } - - QChar u; - - switch (_char.unicode()) { - // unicode escape sequence - case 'u': { - bool ok = false; - u = decodeUnicodeEscapeCharacter(&ok); - if (! ok) { - _errorCode = IllegalUnicodeEscapeSequence; - _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence"); - return T_ERROR; - } - } break; - - // hex escape sequence - case 'x': { - bool ok = false; - u = decodeHexEscapeCharacter(&ok); - if (!ok) { - _errorCode = IllegalHexadecimalEscapeSequence; - _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal hexadecimal escape sequence"); - return T_ERROR; - } - } break; - - // single character escape sequence - case '\\': u = QLatin1Char('\\'); scanChar(); break; - case '\'': u = QLatin1Char('\''); scanChar(); break; - case '\"': u = QLatin1Char('\"'); scanChar(); break; - case 'b': u = QLatin1Char('\b'); scanChar(); break; - case 'f': u = QLatin1Char('\f'); scanChar(); break; - case 'n': u = QLatin1Char('\n'); scanChar(); break; - case 'r': u = QLatin1Char('\r'); scanChar(); break; - case 't': u = QLatin1Char('\t'); scanChar(); break; - case 'v': u = QLatin1Char('\v'); scanChar(); break; - - case '0': - if (! _codePtr->isDigit()) { - scanChar(); - u = QLatin1Char('\0'); - break; - } - Q_FALLTHROUGH(); - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - _errorCode = IllegalEscapeSequence; - _errorMessage = QCoreApplication::translate("QQmlParser", "Octal escape sequences are not allowed"); - return T_ERROR; - - case '\r': - case '\n': - case 0x2028u: - case 0x2029u: - scanChar(); - continue; - - default: - // non escape character - u = _char; - scanChar(); - } - - _tokenText += u; - } else { - _tokenText += _char; - scanChar(); - } - } - - _errorCode = UnclosedStringLiteral; - _errorMessage = QCoreApplication::translate("QQmlParser", "Unclosed string at end of line"); - return T_ERROR; - } + case '"': + return scanString(ScanStringMode(ch.unicode())); case '0': case '1': case '2': @@ -824,28 +715,36 @@ again: return scanNumber(ch); default: { - QChar c = ch; + uint c = ch.unicode(); bool identifierWithEscapeChars = false; - if (c == QLatin1Char('\\') && _char == QLatin1Char('u')) { + if (QChar::isHighSurrogate(c) && QChar::isLowSurrogate(_char.unicode())) { + c = QChar::surrogateToUcs4(ushort(c), _char.unicode()); + scanChar(); + } else if (c == '\\' && _char == QLatin1Char('u')) { identifierWithEscapeChars = true; bool ok = false; c = decodeUnicodeEscapeCharacter(&ok); - if (! ok) { - _errorCode = IllegalUnicodeEscapeSequence; - _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence"); + if (!ok) return T_ERROR; - } } if (isIdentifierStart(c)) { if (identifierWithEscapeChars) { _tokenText.resize(0); - _tokenText += c; + if (QChar::requiresSurrogates(c)) { + _tokenText += QChar(QChar::highSurrogate(c)); + _tokenText += QChar(QChar::lowSurrogate(c)); + } else { + _tokenText += QChar(c); + } _validTokenText = true; } - while (true) { - c = _char; - if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) { - if (! identifierWithEscapeChars) { + while (_codePtr <= _endPtr) { + c = _char.unicode(); + if (QChar::isHighSurrogate(c) && QChar::isLowSurrogate(_codePtr->unicode())) { + scanChar(); + c = QChar::surrogateToUcs4(ushort(c), _char.unicode()); + } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) { + if (!identifierWithEscapeChars) { identifierWithEscapeChars = true; _tokenText.resize(0); _tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1); @@ -855,38 +754,52 @@ again: scanChar(); // skip '\\' bool ok = false; c = decodeUnicodeEscapeCharacter(&ok); - if (! ok) { - _errorCode = IllegalUnicodeEscapeSequence; - _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence"); + if (!ok) return T_ERROR; - } - if (isIdentifierPart(c)) - _tokenText += c; - continue; - } else if (isIdentifierPart(c)) { - if (identifierWithEscapeChars) - _tokenText += c; - scanChar(); + if (!isIdentifierPart(c)) + break; + + if (identifierWithEscapeChars) { + if (QChar::requiresSurrogates(c)) { + _tokenText += QChar(QChar::highSurrogate(c)); + _tokenText += QChar(QChar::lowSurrogate(c)); + } else { + _tokenText += QChar(c); + } + } continue; } - _tokenLength = _codePtr - _tokenStartPtr - 1; + if (!isIdentifierPart(c)) + break; - int kind = T_IDENTIFIER; + if (identifierWithEscapeChars) { + if (QChar::requiresSurrogates(c)) { + _tokenText += QChar(QChar::highSurrogate(c)); + _tokenText += QChar(QChar::lowSurrogate(c)); + } else { + _tokenText += QChar(c); + } + } + scanChar(); + } - if (! identifierWithEscapeChars) - kind = classify(_tokenStartPtr, _tokenLength, _qmlMode); + _tokenLength = _codePtr - _tokenStartPtr - 1; - if (_engine) { - if (kind == T_IDENTIFIER && identifierWithEscapeChars) - _tokenSpell = _engine->newStringRef(_tokenText); - else - _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength); - } + int kind = T_IDENTIFIER; - return kind; + if (!identifierWithEscapeChars) + kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags()); + + if (_engine) { + if (kind == T_IDENTIFIER && identifierWithEscapeChars) + _tokenSpell = _engine->newStringRef(_tokenText); + else + _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength); } + + return kind; } } @@ -896,93 +809,278 @@ again: return T_ERROR; } -int Lexer::scanNumber(QChar ch) +int Lexer::scanString(ScanStringMode mode) { - if (ch != QLatin1Char('0')) { - QVarLengthArray<char, 64> buf; - buf += ch.toLatin1(); - - QChar n = _char; - const QChar *code = _codePtr; - while (n.isDigit()) { - buf += n.toLatin1(); - n = *code++; - } + QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode); + bool multilineStringLiteral = false; + + const QChar *startCode = _codePtr; - if (n != QLatin1Char('.') && n != QLatin1Char('e') && n != QLatin1Char('E')) { - if (code != _codePtr) { - _codePtr = code - 1; + if (_engine) { + while (_codePtr <= _endPtr) { + if (isLineTerminator()) { + if (qmlMode()) + break; + _errorCode = IllegalCharacter; + _errorMessage = QCoreApplication::translate("QQmlParser", "Stray newline in string literal"); + return T_ERROR; + } else if (_char == QLatin1Char('\\')) { + break; + } else if (_char == '$' && quote == QLatin1Char('`')) { + break; + } else if (_char == quote) { + _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); scanChar(); + + if (quote == QLatin1Char('`')) + _bracesCount = _outerTemplateBraceCount.pop(); + + if (mode == TemplateHead) + return T_NO_SUBSTITUTION_TEMPLATE; + else if (mode == TemplateContinuation) + return T_TEMPLATE_TAIL; + else + return T_STRING_LITERAL; } - buf.append('\0'); - _tokenValue = strtod(buf.constData(), nullptr); - return T_NUMERIC_LITERAL; + scanChar(); } - } else if (_char.isDigit() && !qmlMode()) { - _errorCode = IllegalCharacter; - _errorMessage = QCoreApplication::translate("QQmlParser", "Decimal numbers can't start with '0'"); - return T_ERROR; } - QVarLengthArray<char,32> chars; - chars.append(ch.unicode()); + _validTokenText = true; + _tokenText.resize(0); + startCode--; + while (startCode != _codePtr - 1) + _tokenText += *startCode++; + + while (_codePtr <= _endPtr) { + if (unsigned sequenceLength = isLineTerminatorSequence()) { + multilineStringLiteral = true; + _tokenText += _char; + if (sequenceLength == 2) + _tokenText += *_codePtr; + scanChar(); + } else if (_char == mode) { + scanChar(); - if (ch == QLatin1Char('0') && (_char == QLatin1Char('x') || _char == QLatin1Char('X'))) { - ch = _char; // remember the x or X to use it in the error message below. + if (_engine) + _tokenSpell = _engine->newStringRef(_tokenText); - // parse hex integer literal - chars.append(_char.unicode()); - scanChar(); // consume `x' + if (quote == QLatin1Char('`')) + _bracesCount = _outerTemplateBraceCount.pop(); - while (isHexDigit(_char)) { - chars.append(_char.unicode()); + if (mode == TemplateContinuation) + return T_TEMPLATE_TAIL; + else if (mode == TemplateHead) + return T_NO_SUBSTITUTION_TEMPLATE; + + return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL; + } else if (quote == QLatin1Char('`') && _char == QLatin1Char('$') && *_codePtr == '{') { + scanChar(); + scanChar(); + _bracesCount = 1; + if (_engine) + _tokenSpell = _engine->newStringRef(_tokenText); + + return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE); + } else if (_char == QLatin1Char('\\')) { + scanChar(); + if (_codePtr > _endPtr) { + _errorCode = IllegalEscapeSequence; + _errorMessage = QCoreApplication::translate("QQmlParser", "End of file reached at escape sequence"); + return T_ERROR; + } + + QChar u; + + switch (_char.unicode()) { + // unicode escape sequence + case 'u': { + bool ok = false; + uint codePoint = decodeUnicodeEscapeCharacter(&ok); + if (!ok) + return T_ERROR; + if (QChar::requiresSurrogates(codePoint)) { + // need to use a surrogate pair + _tokenText += QChar(QChar::highSurrogate(codePoint)); + u = QChar::lowSurrogate(codePoint); + } else { + u = codePoint; + } + } break; + + // hex escape sequence + case 'x': { + bool ok = false; + u = decodeHexEscapeCharacter(&ok); + if (!ok) { + _errorCode = IllegalHexadecimalEscapeSequence; + _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal hexadecimal escape sequence"); + return T_ERROR; + } + } break; + + // single character escape sequence + case '\\': u = QLatin1Char('\\'); scanChar(); break; + case '\'': u = QLatin1Char('\''); scanChar(); break; + case '\"': u = QLatin1Char('\"'); scanChar(); break; + case 'b': u = QLatin1Char('\b'); scanChar(); break; + case 'f': u = QLatin1Char('\f'); scanChar(); break; + case 'n': u = QLatin1Char('\n'); scanChar(); break; + case 'r': u = QLatin1Char('\r'); scanChar(); break; + case 't': u = QLatin1Char('\t'); scanChar(); break; + case 'v': u = QLatin1Char('\v'); scanChar(); break; + + case '0': + if (! _codePtr->isDigit()) { + scanChar(); + u = QLatin1Char('\0'); + break; + } + Q_FALLTHROUGH(); + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + _errorCode = IllegalEscapeSequence; + _errorMessage = QCoreApplication::translate("QQmlParser", "Octal escape sequences are not allowed"); + return T_ERROR; + + case '\r': + case '\n': + case 0x2028u: + case 0x2029u: + scanChar(); + continue; + + default: + // non escape character + u = _char; + scanChar(); + } + + _tokenText += u; + } else { + _tokenText += _char; scanChar(); } + } - if (chars.size() < 3) { - _errorCode = IllegalHexNumber; - _errorMessage = QCoreApplication::translate("QQmlParser", "At least one hexadecimal digit is required after '0%1'").arg(ch); + _errorCode = UnclosedStringLiteral; + _errorMessage = QCoreApplication::translate("QQmlParser", "Unclosed string at end of line"); + return T_ERROR; +} + +int Lexer::scanNumber(QChar ch) +{ + if (ch == QLatin1Char('0')) { + if (_char == QLatin1Char('x') || _char == QLatin1Char('X')) { + ch = _char; // remember the x or X to use it in the error message below. + + // parse hex integer literal + scanChar(); // consume 'x' + + if (!isHexDigit(_char)) { + _errorCode = IllegalNumber; + _errorMessage = QCoreApplication::translate("QQmlParser", "At least one hexadecimal digit is required after '0%1'").arg(ch); + return T_ERROR; + } + + double d = 0.; + while (1) { + int digit = ::hexDigit(_char); + if (digit < 0) + break; + d *= 16; + d += digit; + scanChar(); + } + + _tokenValue = d; + return T_NUMERIC_LITERAL; + } else if (_char == QLatin1Char('o') || _char == QLatin1Char('O')) { + ch = _char; // remember the o or O to use it in the error message below. + + // parse octal integer literal + scanChar(); // consume 'o' + + if (!isOctalDigit(_char.unicode())) { + _errorCode = IllegalNumber; + _errorMessage = QCoreApplication::translate("QQmlParser", "At least one octal digit is required after '0%1'").arg(ch); + return T_ERROR; + } + + double d = 0.; + while (1) { + int digit = ::octalDigit(_char); + if (digit < 0) + break; + d *= 8; + d += digit; + scanChar(); + } + + _tokenValue = d; + return T_NUMERIC_LITERAL; + } else if (_char == QLatin1Char('b') || _char == QLatin1Char('B')) { + ch = _char; // remember the b or B to use it in the error message below. + + // parse binary integer literal + scanChar(); // consume 'b' + + if (_char.unicode() != '0' && _char.unicode() != '1') { + _errorCode = IllegalNumber; + _errorMessage = QCoreApplication::translate("QQmlParser", "At least one binary digit is required after '0%1'").arg(ch); + return T_ERROR; + } + + double d = 0.; + while (1) { + int digit = 0; + if (_char.unicode() == '1') + digit = 1; + else if (_char.unicode() != '0') + break; + d *= 2; + d += digit; + scanChar(); + } + + _tokenValue = d; + return T_NUMERIC_LITERAL; + } else if (_char.isDigit() && !qmlMode()) { + _errorCode = IllegalCharacter; + _errorMessage = QCoreApplication::translate("QQmlParser", "Decimal numbers can't start with '0'"); return T_ERROR; } - - _tokenValue = integerFromString(chars.constData(), chars.size(), 16); - return T_NUMERIC_LITERAL; } // decimal integer literal - while (_char.isDigit()) { - chars.append(_char.unicode()); - scanChar(); // consume the digit - } - - if (_char == QLatin1Char('.')) { - chars.append(_char.unicode()); - scanChar(); // consume `.' + QVarLengthArray<char,32> chars; + chars.append(ch.unicode()); + if (ch != QLatin1Char('.')) { while (_char.isDigit()) { chars.append(_char.unicode()); - scanChar(); + scanChar(); // consume the digit } - if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { - if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && - _codePtr[1].isDigit())) { - - chars.append(_char.unicode()); - scanChar(); // consume `e' + if (_char == QLatin1Char('.')) { + chars.append(_char.unicode()); + scanChar(); // consume `.' + } + } - if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { - chars.append(_char.unicode()); - scanChar(); // consume the sign - } + while (_char.isDigit()) { + chars.append(_char.unicode()); + scanChar(); + } - while (_char.isDigit()) { - chars.append(_char.unicode()); - scanChar(); - } - } - } - } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { @@ -1001,12 +1099,6 @@ int Lexer::scanNumber(QChar ch) } } - if (chars.length() == 1) { - // if we ended up with a single digit, then it was a '0' - _tokenValue = 0; - return T_NUMERIC_LITERAL; - } - chars.append('\0'); const char *begin = chars.constData(); @@ -1174,16 +1266,6 @@ bool Lexer::isOctalDigit(ushort c) return (c >= '0' && c <= '7'); } -int Lexer::tokenEndLine() const -{ - return _currentLineNumber; -} - -int Lexer::tokenEndColumn() const -{ - return _codePtr - _lastLinePtr; -} - QString Lexer::tokenText() const { if (_validTokenText) diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h index 11d8081713..a6ac8cb354 100644 --- a/src/qml/parser/qqmljslexer_p.h +++ b/src/qml/parser/qqmljslexer_p.h @@ -51,10 +51,11 @@ // We mean it. // -#include "qqmljsglobal_p.h" -#include "qqmljsgrammar_p.h" +#include <private/qqmljsglobal_p.h> +#include <private/qqmljsgrammar_p.h> #include <QtCore/qstring.h> +#include <QtCore/qstack.h> QT_QML_BEGIN_NAMESPACE @@ -62,32 +63,7 @@ namespace QQmlJS { class Engine; class DiagnosticMessage; - -class QML_PARSER_EXPORT Directives { -public: - virtual ~Directives() {} - - virtual void pragmaLibrary() - { - } - - virtual void importFile(const QString &jsfile, const QString &module, int line, int column) - { - Q_UNUSED(jsfile); - Q_UNUSED(module); - Q_UNUSED(line); - Q_UNUSED(column); - } - - virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column) - { - Q_UNUSED(uri); - Q_UNUSED(version); - Q_UNUSED(module); - Q_UNUSED(line); - Q_UNUSED(column); - } -}; +class Directives; class QML_PARSER_EXPORT Lexer: public QQmlJSGrammar { @@ -97,10 +73,7 @@ public: T_BOOLEAN = T_RESERVED_WORD, T_BYTE = T_RESERVED_WORD, T_CHAR = T_RESERVED_WORD, - T_CLASS = T_RESERVED_WORD, T_DOUBLE = T_RESERVED_WORD, - T_EXPORT = T_RESERVED_WORD, - T_EXTENDS = T_RESERVED_WORD, T_FINAL = T_RESERVED_WORD, T_FLOAT = T_RESERVED_WORD, T_GOTO = T_RESERVED_WORD, @@ -113,8 +86,6 @@ public: T_PRIVATE = T_RESERVED_WORD, T_PROTECTED = T_RESERVED_WORD, T_SHORT = T_RESERVED_WORD, - T_STATIC = T_RESERVED_WORD, - T_SUPER = T_RESERVED_WORD, T_SYNCHRONIZED = T_RESERVED_WORD, T_THROWS = T_RESERVED_WORD, T_TRANSIENT = T_RESERVED_WORD, @@ -124,7 +95,7 @@ public: enum Error { NoError, IllegalCharacter, - IllegalHexNumber, + IllegalNumber, UnclosedStringLiteral, IllegalEscapeSequence, IllegalUnicodeEscapeSequence, @@ -145,10 +116,29 @@ public: RegExp_Multiline = 0x04 }; + enum ParseModeFlags { + QmlMode = 0x1, + YieldIsKeyword = 0x2, + StaticIsKeyword = 0x4 + }; + public: Lexer(Engine *engine); + int parseModeFlags() const { + int flags = 0; + if (qmlMode()) + flags |= QmlMode|StaticIsKeyword; + if (yieldIsKeyWord()) + flags |= YieldIsKeyword; + if (_staticIsKeyword) + flags |= StaticIsKeyword; + return flags; + } + bool qmlMode() const; + bool yieldIsKeyWord() const { return _generatorLevel != 0; } + void setStaticIsKeyword(bool b) { _staticIsKeyword = b; } QString code() const; void setCode(const QString &code, int lineno, bool qmlMode = true); @@ -166,10 +156,7 @@ public: int tokenLength() const { return _tokenLength; } int tokenStartLine() const { return _tokenLine; } - int tokenStartColumn() const { return _tokenStartPtr - _tokenLinePtr + 1; } - - int tokenEndLine() const; - int tokenEndColumn() const; + int tokenStartColumn() const { return _tokenColumn; } inline QStringRef tokenSpell() const { return _tokenSpell; } double tokenValue() const { return _tokenValue; } @@ -188,13 +175,23 @@ public: BalancedParentheses }; + void enterGeneratorBody() { ++_generatorLevel; } + void leaveGeneratorBody() { --_generatorLevel; } + protected: - int classify(const QChar *s, int n, bool qmlMode); + static int classify(const QChar *s, int n, int parseModeFlags); private: inline void scanChar(); int scanToken(); int scanNumber(QChar ch); + enum ScanStringMode { + SingleQuote = '\'', + DoubleQuote = '"', + TemplateHead = '`', + TemplateContinuation = 0 + }; + int scanString(ScanStringMode mode); bool isLineTerminator() const; unsigned isLineTerminatorSequence() const; @@ -202,10 +199,9 @@ private: static bool isDecimalDigit(ushort c); static bool isHexDigit(QChar c); static bool isOctalDigit(ushort c); - static bool isUnicodeEscapeSequence(const QChar *chars); void syncProhibitAutomaticSemicolon(); - QChar decodeUnicodeEscapeCharacter(bool *ok); + uint decodeUnicodeEscapeCharacter(bool *ok); QChar decodeHexEscapeCharacter(bool *ok); private: @@ -218,26 +214,30 @@ private: const QChar *_codePtr; const QChar *_endPtr; - const QChar *_lastLinePtr; - const QChar *_tokenLinePtr; const QChar *_tokenStartPtr; QChar _char; Error _errorCode; int _currentLineNumber; + int _currentColumnNumber; double _tokenValue; // parentheses state ParenthesesState _parenthesesState; int _parenthesesCount; + // template string stack + QStack<int> _outerTemplateBraceCount; + int _bracesCount = -1; + int _stackToken; int _patternFlags; int _tokenKind; int _tokenLength; int _tokenLine; + int _tokenColumn; bool _validTokenText; bool _prohibitAutomaticSemicolon; @@ -246,6 +246,8 @@ private: bool _followsClosingBrace; bool _delimited; bool _qmlMode; + int _generatorLevel = 0; + bool _staticIsKeyword = false; }; } // end of namespace QQmlJS diff --git a/src/qml/parser/qqmljsparser.cpp b/src/qml/parser/qqmljsparser.cpp deleted file mode 100644 index 24b04b02f9..0000000000 --- a/src/qml/parser/qqmljsparser.cpp +++ /dev/null @@ -1,2010 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qqmljsengine_p.h" -#include "qqmljslexer_p.h" -#include "qqmljsast_p.h" -#include "qqmljsmemorypool_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qcoreapplication.h> - -#include <string.h> - - - -#include "qqmljsparser_p.h" - -#include <QtCore/qvarlengtharray.h> - -// -// W A R N I N G -// ------------- -// -// This file is automatically generated from qqmljs.g. -// Changes should be made to that file, not here. Any change to this file will -// be lost! -// -// To regenerate this file, run: -// qlalr --no-debug --no-lines --qt qqmljs.g -// - -using namespace QQmlJS; - -QT_QML_BEGIN_NAMESPACE - -void Parser::reallocateStack() -{ - if (! stack_size) - stack_size = 128; - else - stack_size <<= 1; - - sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value))); - state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int))); - location_stack = reinterpret_cast<AST::SourceLocation*> (realloc(location_stack, stack_size * sizeof(AST::SourceLocation))); - string_stack = reinterpret_cast<QStringRef*> (realloc(static_cast<void *>(string_stack), stack_size * sizeof(QStringRef))); -} - -Parser::Parser(Engine *engine): - driver(engine), - pool(engine->pool()), - tos(0), - stack_size(0), - sym_stack(nullptr), - state_stack(nullptr), - location_stack(nullptr), - string_stack(nullptr), - program(nullptr), - yylval(0), - first_token(nullptr), - last_token(nullptr) -{ -} - -Parser::~Parser() -{ - if (stack_size) { - free(sym_stack); - free(state_stack); - free(location_stack); - free(string_stack); - } -} - -static inline AST::SourceLocation location(Lexer *lexer) -{ - AST::SourceLocation loc; - loc.offset = lexer->tokenOffset(); - loc.length = lexer->tokenLength(); - loc.startLine = lexer->tokenStartLine(); - loc.startColumn = lexer->tokenStartColumn(); - return loc; -} - -AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) -{ - QVarLengthArray<QStringRef, 4> nameIds; - QVarLengthArray<AST::SourceLocation, 4> locations; - - AST::ExpressionNode *it = expr; - while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { - nameIds.append(m->name); - locations.append(m->identifierToken); - it = m->base; - } - - if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { - AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name); - q->identifierToken = idExpr->identifierToken; - - AST::UiQualifiedId *currentId = q; - for (int i = nameIds.size() - 1; i != -1; --i) { - currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); - currentId->identifierToken = locations[i]; - } - - return currentId->finish(); - } - - return nullptr; -} - -AST::UiQualifiedPragmaId *Parser::reparseAsQualifiedPragmaId(AST::ExpressionNode *expr) -{ - if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) { - AST::UiQualifiedPragmaId *q = new (pool) AST::UiQualifiedPragmaId(idExpr->name); - q->identifierToken = idExpr->identifierToken; - - return q->finish(); - } - - return nullptr; -} - - -bool Parser::parse(int startToken) -{ - Lexer *lexer = driver->lexer(); - bool hadErrors = false; - int yytoken = -1; - int action = 0; - - token_buffer[0].token = startToken; - first_token = &token_buffer[0]; - if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) { - Directives ignoreDirectives; - Directives *directives = driver->directives(); - if (!directives) - directives = &ignoreDirectives; - DiagnosticMessage error; - if (!lexer->scanDirectives(directives, &error)) { - diagnostic_messages.append(error); - return false; - } - token_buffer[1].token = lexer->tokenKind(); - token_buffer[1].dval = lexer->tokenValue(); - token_buffer[1].loc = location(lexer); - token_buffer[1].spell = lexer->tokenSpell(); - last_token = &token_buffer[2]; - } else { - last_token = &token_buffer[1]; - } - - tos = -1; - program = nullptr; - - do { - if (++tos == stack_size) - reallocateStack(); - - state_stack[tos] = action; - - _Lcheck_token: - if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { - yyprevlloc = yylloc; - - if (first_token == last_token) { - yytoken = lexer->lex(); - yylval = lexer->tokenValue(); - yytokenspell = lexer->tokenSpell(); - yylloc = location(lexer); - } else { - yytoken = first_token->token; - yylval = first_token->dval; - yytokenspell = first_token->spell; - yylloc = first_token->loc; - ++first_token; - } - } - - action = t_action(action, yytoken); - if (action > 0) { - if (action != ACCEPT_STATE) { - yytoken = -1; - sym(1).dval = yylval; - stringRef(1) = yytokenspell; - loc(1) = yylloc; - } else { - --tos; - return ! hadErrors; - } - } else if (action < 0) { - const int r = -action - 1; - tos -= rhs[r]; - - switch (r) { - -case 0: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; - -case 1: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; - -case 2: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; - -case 3: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; - -case 4: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; - -case 5: { - sym(1).Node = sym(2).Node; - program = sym(1).Node; -} break; - -case 6: { - sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiHeaderItemList, - sym(2).UiObjectMemberList->finish()); -} break; - -case 8: { - sym(1).Node = sym(1).UiHeaderItemList->finish(); -} break; - -case 9: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiPragma); -} break; - -case 10: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiImport); -} break; - -case 11: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiPragma); -} break; - -case 12: { - sym(1).Node = new (pool) AST::UiHeaderItemList(sym(1).UiHeaderItemList, sym(2).UiImport); -} break; - -case 16: { - sym(1).UiPragma->semicolonToken = loc(2); -} break; - -case 18: { - sym(1).UiImport->semicolonToken = loc(2); -} break; - -case 20: { - sym(1).UiImport->versionToken = loc(2); - sym(1).UiImport->semicolonToken = loc(3); -} break; - -case 22: { - sym(1).UiImport->versionToken = loc(2); - sym(1).UiImport->asToken = loc(3); - sym(1).UiImport->importIdToken = loc(4); - sym(1).UiImport->importId = stringRef(4); - sym(1).UiImport->semicolonToken = loc(5); -} break; - -case 24: { - sym(1).UiImport->asToken = loc(2); - sym(1).UiImport->importIdToken = loc(3); - sym(1).UiImport->importId = stringRef(3); - sym(1).UiImport->semicolonToken = loc(4); -} break; - -case 25: { - AST::UiPragma *node = nullptr; - - if (AST::UiQualifiedPragmaId *qualifiedId = reparseAsQualifiedPragmaId(sym(2).Expression)) { - node = new (pool) AST::UiPragma(qualifiedId); - } - - sym(1).Node = node; - - if (node) { - node->pragmaToken = loc(1); - } else { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), - QLatin1String("Expected a qualified name id"))); - - return false; // ### remove me - } -} break; - -case 26: { - AST::UiImport *node = nullptr; - - if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { - node = new (pool) AST::UiImport(importIdLiteral->value); - node->fileNameToken = loc(2); - } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { - node = new (pool) AST::UiImport(qualifiedId); - node->fileNameToken = loc(2); - } - - sym(1).Node = node; - - if (node) { - node->importToken = loc(1); - } else { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), - QLatin1String("Expected a qualified name id or a string literal"))); - - return false; // ### remove me - } -} break; - -case 27: { - sym(1).Node = nullptr; -} break; - -case 28: { - sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); -} break; - -case 29: { - sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); -} break; - -case 30: { - AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( - sym(1).UiObjectMemberList, sym(2).UiObjectMember); - sym(1).Node = node; -} break; - -case 31: { - sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); -} break; - -case 32: { - AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( - sym(1).UiArrayMemberList, sym(3).UiObjectMember); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 33: { - AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)nullptr); - node->lbraceToken = loc(1); - node->rbraceToken = loc(2); - sym(1).Node = node; -} break; - -case 34: { - AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 35: { - AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, - sym(2).UiObjectInitializer); - sym(1).Node = node; -} break; - -case 37: { - AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( - sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); - node->colonToken = loc(2); - node->lbracketToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; - -case 38: { - AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( - sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 39: { - AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( - sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); - node->colonToken = loc(2); - node->hasOnToken = true; - sym(1).Node = node; -} break; - -case 47: -{ - AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( - sym(1).UiQualifiedId, sym(3).Statement); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 48: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 49: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 50: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 51: { - AST::UiQualifiedId *node = new (pool) AST::UiQualifiedId(sym(1).UiQualifiedId, stringRef(3)); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 52: { - sym(1).Node = nullptr; -} break; - -case 53: { - sym(1).Node = sym(1).UiParameterList->finish (); -} break; - -case 54: { - AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiQualifiedId->finish(), stringRef(2)); - node->propertyTypeToken = loc(1); - node->identifierToken = loc(2); - sym(1).Node = node; -} break; - -case 55: { - AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(3).UiQualifiedId->finish(), stringRef(4)); - node->propertyTypeToken = loc(3); - node->commaToken = loc(2); - node->identifierToken = loc(4); - sym(1).Node = node; -} break; - -case 57: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); - node->type = AST::UiPublicMember::Signal; - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(2); - node->parameters = sym(4).UiParameterList; - node->semicolonToken = loc(6); - sym(1).Node = node; -} break; - -case 59: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); - node->type = AST::UiPublicMember::Signal; - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 61: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); - node->typeModifier = stringRef(2); - node->propertyToken = loc(1); - node->typeModifierToken = loc(2); - node->typeToken = loc(4); - node->identifierToken = loc(6); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; - -case 63: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->semicolonToken = loc(4); - sym(1).Node = node; -} break; - -case 65: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->semicolonToken = loc(5); - sym(1).Node = node; -} break; - -case 67: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7)); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->typeModifier = stringRef(3); - node->propertyToken = loc(2); - node->typeModifierToken = loc(2); - node->typeToken = loc(4); - node->identifierToken = loc(7); - node->semicolonToken = loc(8); - sym(1).Node = node; -} break; - -case 68: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3), - sym(5).Statement); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->colonToken = loc(4); - sym(1).Node = node; -} break; - -case 69: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), - sym(6).Statement); - node->isReadonlyMember = true; - node->readonlyToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->colonToken = loc(5); - sym(1).Node = node; -} break; - -case 70: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4), - sym(6).Statement); - node->isDefaultMember = true; - node->defaultToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->colonToken = loc(5); - sym(1).Node = node; -} break; - -case 71: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); - node->typeModifier = stringRef(2); - node->propertyToken = loc(1); - node->typeModifierToken = loc(2); - node->typeToken = loc(4); - node->identifierToken = loc(6); - node->semicolonToken = loc(7); // insert a fake ';' before ':' - - AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); - propertyName->identifierToken = loc(6); - propertyName->next = nullptr; - - AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( - propertyName, sym(9).UiArrayMemberList->finish()); - binding->colonToken = loc(7); - binding->lbracketToken = loc(8); - binding->rbracketToken = loc(10); - - node->binding = binding; - - sym(1).Node = node; -} break; - -case 72: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); - node->propertyToken = loc(1); - node->typeToken = loc(2); - node->identifierToken = loc(3); - node->semicolonToken = loc(4); // insert a fake ';' before ':' - - AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); - propertyName->identifierToken = loc(3); - propertyName->next = nullptr; - - AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( - propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); - binding->colonToken = loc(4); - - node->binding = binding; - - sym(1).Node = node; -} break; - -case 73: { - AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); - node->isReadonlyMember = true; - node->readonlyToken = loc(1); - node->propertyToken = loc(2); - node->typeToken = loc(3); - node->identifierToken = loc(4); - node->semicolonToken = loc(5); // insert a fake ';' before ':' - - AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); - propertyName->identifierToken = loc(4); - propertyName->next = nullptr; - - AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( - propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); - binding->colonToken = loc(5); - - node->binding = binding; - - sym(1).Node = node; -} break; - -case 74: { - sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); -} break; - -case 75: { - sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); -} break; - -case 76: { - AST::UiEnumDeclaration *enumDeclaration = new (pool) AST::UiEnumDeclaration(stringRef(2), sym(4).UiEnumMemberList->finish()); - enumDeclaration->enumToken = loc(1); - enumDeclaration->rbraceToken = loc(5); - sym(1).Node = enumDeclaration; - break; -} - -case 77: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1)); - node->memberToken = loc(1); - sym(1).Node = node; - break; -} - -case 78: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(stringRef(1), sym(3).dval); - node->memberToken = loc(1); - node->valueToken = loc(3); - sym(1).Node = node; - break; -} - -case 79: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3)); - node->memberToken = loc(3); - sym(1).Node = node; - break; -} - -case 80: { - AST::UiEnumMemberList *node = new (pool) AST::UiEnumMemberList(sym(1).UiEnumMemberList, stringRef(3), sym(5).dval); - node->memberToken = loc(3); - node->valueToken = loc(5); - sym(1).Node = node; - break; -} - -case 88: { - AST::ThisExpression *node = new (pool) AST::ThisExpression(); - node->thisToken = loc(1); - sym(1).Node = node; -} break; - -case 89: { - AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 90: { - AST::NullExpression *node = new (pool) AST::NullExpression(); - node->nullToken = loc(1); - sym(1).Node = node; -} break; - -case 91: { - AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); - node->trueToken = loc(1); - sym(1).Node = node; -} break; - -case 92: { - AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); - node->falseToken = loc(1); - sym(1).Node = node; -} break; - -case 93: { - AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); - node->literalToken = loc(1); - sym(1).Node = node; -} break; -case 94: -case 95: { - AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 96: { - bool rx = lexer->scanRegExp(Lexer::NoPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; // ### remove me - } - - loc(1).length = lexer->tokenLength(); - yylloc = loc(1); // adjust the location of the current token - - AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( - driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 97: { - bool rx = lexer->scanRegExp(Lexer::EqualPrefix); - if (!rx) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); - return false; - } - - loc(1).length = lexer->tokenLength(); - yylloc = loc(1); // adjust the location of the current token - - AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( - driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); - node->literalToken = loc(1); - sym(1).Node = node; -} break; - -case 98: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) nullptr); - node->lbracketToken = loc(1); - node->rbracketToken = loc(2); - sym(1).Node = node; -} break; - -case 99: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; - -case 100: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); - node->lbracketToken = loc(1); - node->rbracketToken = loc(3); - sym(1).Node = node; -} break; - -case 101: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), - (AST::Elision *) nullptr); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; - -case 102: { - AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), - sym(4).Elision->finish()); - node->lbracketToken = loc(1); - node->commaToken = loc(3); - node->rbracketToken = loc(5); - sym(1).Node = node; -} break; - -case 103: { - AST::ObjectLiteral *node = nullptr; - if (sym(2).Node) - node = new (pool) AST::ObjectLiteral( - sym(2).PropertyAssignmentList->finish ()); - else - node = new (pool) AST::ObjectLiteral(); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 104: { - AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( - sym(2).PropertyAssignmentList->finish ()); - node->lbraceToken = loc(1); - node->rbraceToken = loc(4); - sym(1).Node = node; -} break; - -case 105: { - AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); - node->lparenToken = loc(1); - node->rparenToken = loc(3); - sym(1).Node = node; -} break; - -case 106: { - if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, - QLatin1String("Ignored annotation"))); - - sym(1).Expression = mem->base; - } - - if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { - sym(1).UiQualifiedId = qualifiedId; - } else { - sym(1).UiQualifiedId = nullptr; - - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), - QLatin1String("Expected a qualified name id"))); - - return false; // ### recover - } -} break; - -case 107: { - sym(1).Node = new (pool) AST::ElementList((AST::Elision *) nullptr, sym(1).Expression); -} break; - -case 108: { - sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); -} break; - -case 109: { - AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, - (AST::Elision *) nullptr, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 110: { - AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), - sym(4).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 111: { - AST::Elision *node = new (pool) AST::Elision(); - node->commaToken = loc(1); - sym(1).Node = node; -} break; - -case 112: { - AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 113: { - AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue( - sym(1).PropertyName, sym(3).Expression); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 114: { - AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( - sym(2).PropertyName, sym(6).FunctionBody); - node->getSetToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(4); - node->lbraceToken = loc(5); - node->rbraceToken = loc(7); - sym(1).Node = node; -} break; - -case 115: { - AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( - sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody); - node->getSetToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; - -case 116: { - sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment); -} break; - -case 117: { - AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList( - sym(1).PropertyAssignmentList, sym(3).PropertyAssignment); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 118: { - AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 119: { - AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 120: { - AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 121: { - AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - -case 159: { - AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; - -case 160: { - AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 161: { - AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); - node->newToken = loc(1); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - sym(1).Node = node; -} break; - -case 163: { - AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); - node->newToken = loc(1); - sym(1).Node = node; -} break; - -case 164: { - AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 165: { - AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 166: { - AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); - node->lbracketToken = loc(2); - node->rbracketToken = loc(4); - sym(1).Node = node; -} break; - -case 167: { - AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); - node->dotToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 168: { - sym(1).Node = nullptr; -} break; - -case 169: { - sym(1).Node = sym(1).ArgumentList->finish(); -} break; - -case 170: { - sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); -} break; - -case 171: { - AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 175: { - AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); - node->incrementToken = loc(2); - sym(1).Node = node; -} break; - -case 176: { - AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); - node->decrementToken = loc(2); - sym(1).Node = node; -} break; - -case 178: { - AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); - node->deleteToken = loc(1); - sym(1).Node = node; -} break; - -case 179: { - AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); - node->voidToken = loc(1); - sym(1).Node = node; -} break; - -case 180: { - AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); - node->typeofToken = loc(1); - sym(1).Node = node; -} break; - -case 181: { - AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); - node->incrementToken = loc(1); - sym(1).Node = node; -} break; - -case 182: { - AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); - node->decrementToken = loc(1); - sym(1).Node = node; -} break; - -case 183: { - AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); - node->plusToken = loc(1); - sym(1).Node = node; -} break; - -case 184: { - AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); - node->minusToken = loc(1); - sym(1).Node = node; -} break; - -case 185: { - AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); - node->tildeToken = loc(1); - sym(1).Node = node; -} break; - -case 186: { - AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); - node->notToken = loc(1); - sym(1).Node = node; -} break; - -case 188: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Mul, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 189: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Div, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 190: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Mod, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 192: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Add, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 193: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Sub, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 195: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::LShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 196: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::RShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 197: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::URShift, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 199: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 200: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 201: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 202: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 203: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 204: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::In, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 206: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 207: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Gt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 208: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Le, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 209: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Ge, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 210: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 212: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 213: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 214: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 215: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 217: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Equal, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 218: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 219: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 220: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 222: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 224: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitAnd, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 226: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 228: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitXor, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 230: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 232: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::BitOr, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 234: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 236: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::And, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 238: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 240: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Or, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 242: { - AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; - -case 244: { - AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, - sym(3).Expression, sym(5).Expression); - node->questionToken = loc(2); - node->colonToken = loc(4); - sym(1).Node = node; -} break; - -case 246: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 248: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 249: { - sym(1).ival = QSOperator::Assign; -} break; - -case 250: { - sym(1).ival = QSOperator::InplaceMul; -} break; - -case 251: { - sym(1).ival = QSOperator::InplaceDiv; -} break; - -case 252: { - sym(1).ival = QSOperator::InplaceMod; -} break; - -case 253: { - sym(1).ival = QSOperator::InplaceAdd; -} break; - -case 254: { - sym(1).ival = QSOperator::InplaceSub; -} break; - -case 255: { - sym(1).ival = QSOperator::InplaceLeftShift; -} break; - -case 256: { - sym(1).ival = QSOperator::InplaceRightShift; -} break; - -case 257: { - sym(1).ival = QSOperator::InplaceURightShift; -} break; - -case 258: { - sym(1).ival = QSOperator::InplaceAnd; -} break; - -case 259: { - sym(1).ival = QSOperator::InplaceXor; -} break; - -case 260: { - sym(1).ival = QSOperator::InplaceOr; -} break; - -case 262: { - AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 263: { - sym(1).Node = nullptr; -} break; - -case 266: { - AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 267: { - sym(1).Node = nullptr; -} break; - -case 284: { - AST::Block *node = new (pool) AST::Block(sym(2).StatementList); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 285: { - sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); -} break; - -case 286: { - sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); -} break; - -case 287: { - sym(1).Node = nullptr; -} break; - -case 288: { - sym(1).Node = sym(1).StatementList->finish (); -} break; - -case 290: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - if (sym(1).ival == T_LET) - s = AST::VariableDeclaration::BlockScope; - else if (sym(1).ival == T_CONST) - s = AST::VariableDeclaration::ReadOnlyBlockScope; - - AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(s)); - node->declarationKindToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 291: { - sym(1).ival = T_LET; -} break; - -case 292: { - sym(1).ival = T_CONST; -} break; - -case 293: { - sym(1).ival = T_VAR; -} break; - -case 294: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); -} break; - -case 295: { - AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( - sym(1).VariableDeclarationList, sym(3).VariableDeclaration); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - -case 296: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); -} break; - -case 297: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); -} break; - -case 298: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 299: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression, s); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 300: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; - -case 301: { - sym(1).Node = nullptr; -} break; - -case 303: { - // ### TODO: AST for initializer - sym(1) = sym(2); -} break; - -case 304: { - sym(1).Node = nullptr; -} break; - -case 306: { - AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); - node->semicolonToken = loc(1); - sym(1).Node = node; -} break; - -case 308: { - AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 309: { - AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - node->elseToken = loc(6); - sym(1).Node = node; -} break; - -case 310: { - AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); - node->ifToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 313: { - AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); - node->doToken = loc(1); - node->whileToken = loc(3); - node->lparenToken = loc(4); - node->rparenToken = loc(6); - node->semicolonToken = loc(7); - sym(1).Node = node; -} break; - -case 314: { - AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); - node->whileToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 315: { - AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, - sym(5).Expression, sym(7).Expression, sym(9).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->firstSemicolonToken = loc(4); - node->secondSemicolonToken = loc(6); - node->rparenToken = loc(8); - sym(1).Node = node; -} break; - -case 316: { - AST::VariableDeclaration::VariableScope s = AST::VariableDeclaration::FunctionScope; - AST::LocalForStatement *node = new (pool) AST::LocalForStatement( - sym(4).VariableDeclarationList->finish(s), sym(6).Expression, - sym(8).Expression, sym(10).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->firstSemicolonToken = loc(5); - node->secondSemicolonToken = loc(7); - node->rparenToken = loc(9); - sym(1).Node = node; -} break; - -case 317: { - AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, - sym(5).Expression, sym(7).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->inToken = loc(4); - node->rparenToken = loc(6); - sym(1).Node = node; -} break; - -case 318: { - AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( - sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); - node->forToken = loc(1); - node->lparenToken = loc(2); - node->varToken = loc(3); - node->inToken = loc(5); - node->rparenToken = loc(7); - sym(1).Node = node; -} break; - -case 320: { - AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); - node->continueToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 322: { - AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); - node->continueToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 324: { - AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); - node->breakToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 326: { - AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); - node->breakToken = loc(1); - node->identifierToken = loc(2); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 328: { - AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); - node->returnToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 329: { - AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); - node->withToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 330: { - AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); - node->switchToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 331: { - AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(3); - sym(1).Node = node; -} break; - -case 332: { - AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); - node->lbraceToken = loc(1); - node->rbraceToken = loc(5); - sym(1).Node = node; -} break; - -case 333: { - sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); -} break; - -case 334: { - sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); -} break; - -case 335: { - sym(1).Node = nullptr; -} break; - -case 336: { - sym(1).Node = sym(1).CaseClauses->finish (); -} break; - -case 337: { - AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); - node->caseToken = loc(1); - node->colonToken = loc(3); - sym(1).Node = node; -} break; - -case 338: { - AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); - node->defaultToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 339: { - AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); - node->identifierToken = loc(1); - node->colonToken = loc(2); - sym(1).Node = node; -} break; - -case 341: { - AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); - node->throwToken = loc(1); - node->semicolonToken = loc(3); - sym(1).Node = node; -} break; - -case 342: { - AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); - node->tryToken = loc(1); - sym(1).Node = node; -} break; - -case 343: { - AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; - -case 344: { - AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); - node->tryToken = loc(1); - sym(1).Node = node; -} break; - -case 345: { - AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); - node->catchToken = loc(1); - node->lparenToken = loc(2); - node->identifierToken = loc(3); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - -case 346: { - AST::Finally *node = new (pool) AST::Finally(sym(2).Block); - node->finallyToken = loc(1); - sym(1).Node = node; -} break; - -case 348: { - AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); - node->debuggerToken = loc(1); - node->semicolonToken = loc(2); - sym(1).Node = node; -} break; - -case 350: { - AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; - -case 351: { - AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); - node->functionToken = loc(1); - if (! stringRef(2).isNull()) - node->identifierToken = loc(2); - node->lparenToken = loc(3); - node->rparenToken = loc(5); - node->lbraceToken = loc(6); - node->rbraceToken = loc(8); - sym(1).Node = node; -} break; - -case 352: { - AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody); - node->functionToken = loc(1); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - node->lbraceToken = loc(5); - node->rbraceToken = loc(7); - sym(1).Node = node; -} break; - -case 353: { - AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); - node->identifierToken = loc(1); - sym(1).Node = node; -} break; - -case 354: { - AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); - node->commaToken = loc(2); - node->identifierToken = loc(3); - sym(1).Node = node; -} break; - -case 355: { - sym(1).Node = nullptr; -} break; - -case 356: { - sym(1).Node = sym(1).FormalParameterList->finish (); -} break; - -case 357: { - sym(1).Node = nullptr; -} break; - -case 359: { - sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); -} break; - -case 361: { - sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); -} break; - -case 362: { - sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); -} break; - -case 363: { - sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); -} break; - -case 364: { - sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); -} break; - -case 365: { - sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); -} break; - -case 366: { - sym(1).Node = nullptr; -} break; - - } // switch - action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); - } // if - } while (action != 0); - - if (first_token == last_token) { - const int errorState = state_stack[tos]; - - // automatic insertion of `;' - if (yytoken != -1 && ((t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) - || t_action(errorState, T_COMPATIBILITY_SEMICOLON))) { - SavedToken &tk = token_buffer[0]; - tk.token = yytoken; - tk.dval = yylval; - tk.spell = yytokenspell; - tk.loc = yylloc; - - yylloc = yyprevlloc; - yylloc.offset += yylloc.length; - yylloc.startColumn += yylloc.length; - yylloc.length = 0; - - //const QString msg = QCoreApplication::translate("QQmlParser", "Missing `;'"); - //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); - - first_token = &token_buffer[0]; - last_token = &token_buffer[1]; - - yytoken = T_SEMICOLON; - yylval = 0; - - action = errorState; - - goto _Lcheck_token; - } - - hadErrors = true; - - token_buffer[0].token = yytoken; - token_buffer[0].dval = yylval; - token_buffer[0].spell = yytokenspell; - token_buffer[0].loc = yylloc; - - token_buffer[1].token = yytoken = lexer->lex(); - token_buffer[1].dval = yylval = lexer->tokenValue(); - token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); - token_buffer[1].loc = yylloc = location(lexer); - - if (t_action(errorState, yytoken)) { - QString msg; - int token = token_buffer[0].token; - if (token < 0 || token >= TERMINAL_COUNT) - msg = QCoreApplication::translate("QQmlParser", "Syntax error"); - else - msg = QCoreApplication::translate("QQmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - action = errorState; - goto _Lcheck_token; - } - - static int tokens[] = { - T_PLUS, - T_EQ, - - T_COMMA, - T_COLON, - T_SEMICOLON, - - T_RPAREN, T_RBRACKET, T_RBRACE, - - T_NUMERIC_LITERAL, - T_IDENTIFIER, - - T_LPAREN, T_LBRACKET, T_LBRACE, - - EOF_SYMBOL - }; - - for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { - int a = t_action(errorState, *tk); - if (a > 0 && t_action(a, yytoken)) { - const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - yytoken = *tk; - yylval = 0; - yylloc = token_buffer[0].loc; - yylloc.length = 0; - - first_token = &token_buffer[0]; - last_token = &token_buffer[2]; - - action = errorState; - goto _Lcheck_token; - } - } - - for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { - if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || - tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || - tk == T_FEED_JS_SOURCE_ELEMENT) - continue; - - int a = t_action(errorState, tk); - if (a > 0 && t_action(a, yytoken)) { - const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - - yytoken = tk; - yylval = 0; - yylloc = token_buffer[0].loc; - yylloc.length = 0; - - action = errorState; - goto _Lcheck_token; - } - } - - const QString msg = QCoreApplication::translate("QQmlParser", "Syntax error"); - diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); - } - - return false; -} - -QT_QML_END_NAMESPACE - - diff --git a/src/qml/parser/qqmljsparser_p.h b/src/qml/parser/qqmljsparser_p.h deleted file mode 100644 index b4aecd2f08..0000000000 --- a/src/qml/parser/qqmljsparser_p.h +++ /dev/null @@ -1,258 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// -// W A R N I N G -// ------------- -// -// This file is automatically generated from qqmljs.g. -// Changes should be made to that file, not here. Any change to this file will -// be lost! -// -// To regenerate this file, run: -// qlalr --no-debug --no-lines --qt qqmljs.g -// - -#ifndef QQMLJSPARSER_P_H -#define QQMLJSPARSER_P_H - -#include "qqmljsglobal_p.h" -#include "qqmljsgrammar_p.h" -#include "qqmljsast_p.h" -#include "qqmljsengine_p.h" - -#include <QtCore/qlist.h> -#include <QtCore/qstring.h> - -QT_QML_BEGIN_NAMESPACE - -namespace QQmlJS { - -class Engine; - -class QML_PARSER_EXPORT Parser: protected QQmlJSGrammar -{ -public: - union Value { - int ival; - double dval; - AST::ArgumentList *ArgumentList; - AST::CaseBlock *CaseBlock; - AST::CaseClause *CaseClause; - AST::CaseClauses *CaseClauses; - AST::Catch *Catch; - AST::DefaultClause *DefaultClause; - AST::ElementList *ElementList; - AST::Elision *Elision; - AST::ExpressionNode *Expression; - AST::Finally *Finally; - AST::FormalParameterList *FormalParameterList; - AST::FunctionBody *FunctionBody; - AST::FunctionDeclaration *FunctionDeclaration; - AST::Node *Node; - AST::PropertyName *PropertyName; - AST::PropertyAssignment *PropertyAssignment; - AST::PropertyAssignmentList *PropertyAssignmentList; - AST::SourceElement *SourceElement; - AST::SourceElements *SourceElements; - AST::Statement *Statement; - AST::StatementList *StatementList; - AST::Block *Block; - AST::VariableDeclaration *VariableDeclaration; - AST::VariableDeclarationList *VariableDeclarationList; - - AST::UiProgram *UiProgram; - AST::UiHeaderItemList *UiHeaderItemList; - AST::UiPragma *UiPragma; - AST::UiImport *UiImport; - AST::UiParameterList *UiParameterList; - AST::UiPublicMember *UiPublicMember; - AST::UiObjectDefinition *UiObjectDefinition; - AST::UiObjectInitializer *UiObjectInitializer; - AST::UiObjectBinding *UiObjectBinding; - AST::UiScriptBinding *UiScriptBinding; - AST::UiArrayBinding *UiArrayBinding; - AST::UiObjectMember *UiObjectMember; - AST::UiObjectMemberList *UiObjectMemberList; - AST::UiArrayMemberList *UiArrayMemberList; - AST::UiQualifiedId *UiQualifiedId; - AST::UiQualifiedPragmaId *UiQualifiedPragmaId; - AST::UiEnumMemberList *UiEnumMemberList; - }; - -public: - Parser(Engine *engine); - ~Parser(); - - // parse a UI program - bool parse() { return parse(T_FEED_UI_PROGRAM); } - bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } - bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } - bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } - bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } - bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } - - AST::UiProgram *ast() const - { return AST::cast<AST::UiProgram *>(program); } - - AST::Statement *statement() const - { - if (! program) - return nullptr; - - return program->statementCast(); - } - - AST::ExpressionNode *expression() const - { - if (! program) - return nullptr; - - return program->expressionCast(); - } - - AST::UiObjectMember *uiObjectMember() const - { - if (! program) - return nullptr; - - return program->uiObjectMemberCast(); - } - - AST::Node *rootNode() const - { return program; } - - QList<DiagnosticMessage> diagnosticMessages() const - { return diagnostic_messages; } - - inline DiagnosticMessage diagnosticMessage() const - { - for (const DiagnosticMessage &d : diagnostic_messages) { - if (d.kind != DiagnosticMessage::Warning) - return d; - } - - return DiagnosticMessage(); - } - - inline QString errorMessage() const - { return diagnosticMessage().message; } - - inline int errorLineNumber() const - { return diagnosticMessage().loc.startLine; } - - inline int errorColumnNumber() const - { return diagnosticMessage().loc.startColumn; } - -protected: - bool parse(int startToken); - - void reallocateStack(); - - inline Value &sym(int index) - { return sym_stack [tos + index - 1]; } - - inline QStringRef &stringRef(int index) - { return string_stack [tos + index - 1]; } - - inline AST::SourceLocation &loc(int index) - { return location_stack [tos + index - 1]; } - - AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); - AST::UiQualifiedPragmaId *reparseAsQualifiedPragmaId(AST::ExpressionNode *expr); - -protected: - Engine *driver; - MemoryPool *pool; - int tos; - int stack_size; - Value *sym_stack; - int *state_stack; - AST::SourceLocation *location_stack; - QStringRef *string_stack; - - AST::Node *program; - - // error recovery - enum { TOKEN_BUFFER_SIZE = 3 }; - - struct SavedToken { - int token; - double dval; - AST::SourceLocation loc; - QStringRef spell; - }; - - double yylval; - QStringRef yytokenspell; - AST::SourceLocation yylloc; - AST::SourceLocation yyprevlloc; - - SavedToken token_buffer[TOKEN_BUFFER_SIZE]; - SavedToken *first_token; - SavedToken *last_token; - - QList<DiagnosticMessage> diagnostic_messages; -}; - -} // end of namespace QQmlJS - - - -#define J_SCRIPT_REGEXPLITERAL_RULE1 96 - -#define J_SCRIPT_REGEXPLITERAL_RULE2 97 - -QT_QML_END_NAMESPACE - - - -#endif // QQMLJSPARSER_P_H diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 2137877427..940ebb3257 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -73,7 +73,7 @@ include(jsruntime/jsruntime.pri) include(jit/jit.pri) include(qml/qml.pri) include(debugger/debugger.pri) -qtConfig(animation) { +qtConfig(qml-animation) { include(animations/animations.pri) } include(types/types.pri) diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 412dc6cba2..6d69294c17 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -20,7 +20,6 @@ SOURCES += \ $$PWD/qqmlinfo.cpp \ $$PWD/qqmlerror.cpp \ $$PWD/qqmlvaluetype.cpp \ - $$PWD/qqmlxmlhttprequest.cpp \ $$PWD/qqmlcleanup.cpp \ $$PWD/qqmlpropertycache.cpp \ $$PWD/qqmlnotifier.cpp \ @@ -31,7 +30,6 @@ SOURCES += \ $$PWD/qqmlextensionplugin.cpp \ $$PWD/qqmlimport.cpp \ $$PWD/qqmllist.cpp \ - $$PWD/qqmllocale.cpp \ $$PWD/qqmljavascriptexpression.cpp \ $$PWD/qqmlabstractbinding.cpp \ $$PWD/qqmlvaluetypeproxybinding.cpp \ @@ -85,7 +83,6 @@ HEADERS += \ $$PWD/qqmldata_p.h \ $$PWD/qqmlerror.h \ $$PWD/qqmlvaluetype_p.h \ - $$PWD/qqmlxmlhttprequest_p.h \ $$PWD/qqmlcleanup_p.h \ $$PWD/qqmlpropertycache_p.h \ $$PWD/qqmlpropertyindex_p.h \ @@ -99,7 +96,6 @@ HEADERS += \ $$PWD/qqmlimport_p.h \ $$PWD/qqmlextensionplugin.h \ $$PWD/qqmlscriptstring_p.h \ - $$PWD/qqmllocale_p.h \ $$PWD/qqmlcomponentattached_p.h \ $$PWD/qqmljavascriptexpression_p.h \ $$PWD/qqmlabstractbinding_p.h \ @@ -120,5 +116,22 @@ HEADERS += \ $$PWD/qqmldelayedcallqueue_p.h \ $$PWD/qqmlloggingcategory_p.h +qtConfig(qml-xml-http-request) { + HEADERS += \ + $$PWD/qqmlxmlhttprequest_p.h + + SOURCES += \ + $$PWD/qqmlxmlhttprequest.cpp + +} + +qtConfig(qml-locale) { + HEADERS += \ + $$PWD/qqmllocale_p.h + + SOURCES += \ + $$PWD/qqmllocale.cpp +} + include(ftw/ftw.pri) include(v8/v8.pri) diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index fe4768db15..517c216873 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1421,7 +1421,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) QQmlComponentExtension *e = componentExtension(args->v4engine()); - QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocObject<QV4::QmlIncubatorObject>(mode)); + QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocate<QV4::QmlIncubatorObject>(mode)); QV4::ScopedObject p(scope, e->incubationProto.value()); r->setPrototype(p); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 7e11177caa..b72e07d97b 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -48,7 +48,6 @@ #include "qqmlcomponent.h" #include "qqmlvme_p.h" #include "qqmlstringconverters_p.h" -#include "qqmlxmlhttprequest_p.h" #include "qqmlscriptstring.h" #include "qqmlglobal_p.h" #include "qqmlcomponent_p.h" @@ -79,13 +78,17 @@ #include <private/qobject_p.h> #include <private/qmetaobject_p.h> +#if QT_CONFIG(qml_locale) #include <private/qqmllocale_p.h> +#endif #include <private/qqmlbind_p.h> #include <private/qqmlconnections_p.h> -#if QT_CONFIG(animation) +#if QT_CONFIG(qml_animation) #include <private/qqmltimer_p.h> #endif +#if QT_CONFIG(qml_list_model) #include <private/qqmllistmodel_p.h> +#endif #include <private/qqmlplatform_p.h> #include <private/qquickpackage_p.h> #if QT_CONFIG(qml_delegate_model) @@ -219,7 +222,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8 qmlRegisterType<QQmlConnections,1>(uri, versionMajor, (versionMinor < 3 ? 3 : versionMinor), "Connections"); //Only available in >=2.3 qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections"); -#if QT_CONFIG(animation) +#if QT_CONFIG(qml_animation) qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer"); #endif qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1 @@ -232,8 +235,10 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int // These QtQuick types' implementation resides in the QtQml module void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor) { +#if QT_CONFIG(qml_list_model) qmlRegisterType<QQmlListElement>(uri, versionMajor, versionMinor, "ListElement"); // Now in QtQml.Models, here for compatibility qmlRegisterCustomType<QQmlListModel>(uri, versionMajor, versionMinor, "ListModel", new QQmlListModelParser); // Now in QtQml.Models, here for compatibility +#endif qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript"); qmlRegisterType<QQuickPackage>(uri, versionMajor, versionMinor, "Package"); #if QT_CONFIG(qml_delegate_model) @@ -250,7 +255,9 @@ void QQmlEnginePrivate::defineQtQuick2Module() // register the QtQuick2 types which are implemented in the QtQml module. registerQtQuick2Types("QtQuick",2,0); +#if QT_CONFIG(qml_locale) qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()")); +#endif // Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward qmlRegisterModule("QtQuick", 2, QT_VERSION_MINOR); @@ -951,7 +958,9 @@ void QQmlEnginePrivate::init() if (baseModulesUninitialized) { qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler. registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks. +#if QT_CONFIG(qml_locale) qmlRegisterUncreatableType<QQmlLocale>("QtQml", 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()")); +#endif // Auto-increment the import to stay in sync with ALL future QtQml minor versions from 5.11 onward qmlRegisterModule("QtQml", 2, QT_VERSION_MINOR); diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 3fbe3df2ab..62ad9988d5 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -74,7 +74,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i Scope scope(engine); - Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>()); + Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>()); r->d()->object = object; r->d()->propertyType = propType; void *args[] = { &r->d()->property(), nullptr }; @@ -86,7 +86,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp { Scope scope(engine); - Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>()); + Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>()); r->d()->object = prop.object; r->d()->property() = prop; r->d()->propertyType = propType; diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 2a5c58b47b..cea0790280 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -825,7 +825,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale) { QV4::Scope scope(v4); QV4LocaleDataDeletable *d = localeV4Data(scope.engine); - QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>()); + QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocate<QQmlLocaleData>()); *wrapper->d()->locale = locale; QV4::ScopedObject p(scope, d->prototype.value()); wrapper->setPrototype(p); diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 8341b1f555..859c36e11b 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -58,6 +58,8 @@ #include <private/qqmlglobal_p.h> #include <private/qv4object_p.h> +QT_REQUIRE_CONFIG(qml_locale); + QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index ce35e966aa..de077b6d38 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -111,7 +111,7 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q_ASSERT(t.isValid()); Scope scope(engine); - Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocate<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typePrivate = t.priv(); QQmlType::refHandle(w->d()->typePrivate); @@ -127,7 +127,7 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q_ASSERT(importNamespace); Scope scope(engine); - Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocate<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace; t->addref(); return w.asReturnedValue(); @@ -232,7 +232,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); if (ok) { - Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>()); + Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocate<QQmlScopedEnumWrapper>()); enumWrapper->d()->typePrivate = type.priv(); QQmlType::refHandle(enumWrapper->d()->typePrivate); enumWrapper->d()->scopeEnumIndex = value; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 6196a09d94..c4c4b0b776 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -186,7 +186,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj Scope scope(engine); initProto(engine); - Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>()); + Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocate<QQmlValueTypeReference>()); r->d()->object = object; r->d()->property = property; r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject)); @@ -200,7 +200,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria Scope scope(engine); initProto(engine); - Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>()); + Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocate<QQmlValueTypeWrapper>()); r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject)); r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); r->d()->gadgetPtr = nullptr; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 567d83f3ee..9d3388c2f2 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -595,7 +595,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4) Scope scope(v4); QQmlXMLHttpRequestData *d = xhrdata(v4); if (d->nodePrototype.isUndefined()) { - ScopedObject p(scope, v4->memoryManager->allocObject<NodePrototype>()); + ScopedObject p(scope, v4->memoryManager->allocate<NodePrototype>()); d->nodePrototype.set(v4, p); v4->v8Engine->freezeObject(p); } @@ -606,7 +606,7 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data) { Scope scope(v4); - Scoped<Node> instance(scope, v4->memoryManager->allocObject<Node>(data)); + Scoped<Node> instance(scope, v4->memoryManager->allocate<Node>(data)); ScopedObject p(scope); switch (data->type) { @@ -876,7 +876,7 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data) return Encode::null(); } - ScopedObject instance(scope, v4->memoryManager->allocObject<Node>(document)); + ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document)); document->release(); // the GC should own the NodeImpl via Node now ScopedObject p(scope); instance->setPrototype((p = Document::prototype(v4))); @@ -930,7 +930,7 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list) { - return (v4->memoryManager->allocObject<NamedNodeMap>(data, list))->asReturnedValue(); + return (v4->memoryManager->allocate<NamedNodeMap>(data, list))->asReturnedValue(); } ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty) @@ -964,7 +964,7 @@ ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty) ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data) { - return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue(); + return (v4->memoryManager->allocate<NodeList>(data))->asReturnedValue(); } ReturnedValue Document::method_documentElement(const FunctionObject *b, const Value *thisObject, const Value *, int) @@ -1643,7 +1643,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f); QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager(), scope.engine); - Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r)); + Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r)); ScopedObject proto(scope, ctor->d()->proto); w->setPrototype(proto); return w.asReturnedValue(); @@ -2049,7 +2049,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4) { Scope scope(v4); - Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocObject<QQmlXMLHttpRequestCtor>(v4)); + Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocate<QQmlXMLHttpRequestCtor>(v4)); ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest"))); v4->globalObject->defineReadonlyProperty(s, ctor); diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h index f2836d8301..7515ef8dcc 100644 --- a/src/qml/qml/qqmlxmlhttprequest_p.h +++ b/src/qml/qml/qqmlxmlhttprequest_p.h @@ -55,7 +55,7 @@ #include <QtCore/qglobal.h> #include <private/qqmlglobal_p.h> -#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network) +QT_REQUIRE_CONFIG(qml_xml_http_request); QT_BEGIN_NAMESPACE @@ -64,7 +64,5 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *); QT_END_NAMESPACE -#endif // xmlstreamreader && qml_network - #endif // QQMLXMLHTTPREQUEST_P_H diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 9e7c84011b..2ec1d7e87b 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -44,7 +44,9 @@ #include <private/qqmlcomponent_p.h> #include <private/qqmlloggingcategory_p.h> #include <private/qqmlstringconverters_p.h> +#if QT_CONFIG(qml_locale) #include <private/qqmllocale_p.h> +#endif #include <private/qv8engine_p.h> #include <private/qqmldelayedcallqueue_p.h> #include <QFileInfo> @@ -138,7 +140,9 @@ void Heap::QtObject::init(QQmlEngine *qmlEngine) o->defineDefaultProperty(QStringLiteral("btoa"), QV4::QtObject::method_btoa); o->defineDefaultProperty(QStringLiteral("atob"), QV4::QtObject::method_atob); o->defineDefaultProperty(QStringLiteral("resolvedUrl"), QV4::QtObject::method_resolvedUrl); +#if QT_CONFIG(qml_locale) o->defineDefaultProperty(QStringLiteral("locale"), QV4::QtObject::method_locale); +#endif o->defineDefaultProperty(QStringLiteral("binding"), QV4::QtObject::method_binding); if (qmlEngine) { @@ -1309,6 +1313,7 @@ ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Va return QV4::QObjectWrapper::wrap(scope.engine, c); } +#if QT_CONFIG(qml_locale) /*! \qmlmethod Qt::locale(name) @@ -1343,6 +1348,7 @@ ReturnedValue QtObject::method_locale(const FunctionObject *b, const Value *, co return QQmlLocale::locale(scope.engine, code); } +#endif void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *bindingFunction) { @@ -1413,7 +1419,7 @@ ReturnedValue QtObject::method_binding(const FunctionObject *b, const Value *, c if (!f) THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function"); - return Encode(scope.engine->memoryManager->allocObject<QQmlBindingFunction>(f)); + return Encode(scope.engine->memoryManager->allocate<QQmlBindingFunction>(f)); } @@ -1792,7 +1798,7 @@ void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions ext globalObject->defineDefaultProperty(QStringLiteral("print"), QV4::ConsoleObject::method_log); - QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocObject<QV4::ConsoleObject>()); + QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocate<QV4::ConsoleObject>()); globalObject->defineDefaultProperty(QStringLiteral("console"), console); } diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index ee3b5f7d6e..e1f82df390 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -126,7 +126,9 @@ struct QtObject : Object static ReturnedValue method_resolvedUrl(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_createQmlObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_createComponent(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); +#if QT_CONFIG(qml_locale) static ReturnedValue method_locale(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); +#endif static ReturnedValue method_binding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_get_platform(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 038a75d50a..8a786e76cf 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -39,14 +39,21 @@ #include "qv8engine_p.h" +#if QT_CONFIG(qml_sequence_object) #include "qv4sequenceobject_p.h" +#endif + #include "private/qjsengine_p.h" #include <private/qqmlbuiltinfunctions_p.h> #include <private/qqmllist_p.h> #include <private/qqmlengine_p.h> +#if QT_CONFIG(qml_xml_http_request) #include <private/qqmlxmlhttprequest_p.h> +#endif +#if QT_CONFIG(qml_locale) #include <private/qqmllocale_p.h> +#endif #include <private/qqmlglobal_p.h> #include <private/qqmlmemoryprofiler_p.h> #include <private/qqmlplatform_p.h> @@ -123,11 +130,12 @@ static void restoreJSValue(QDataStream &stream, void *data) } } -QV8Engine::QV8Engine(QJSEngine *qq, QV4::ExecutionEngine *v4) - : q(qq) - , m_engine(nullptr) +QV8Engine::QV8Engine(QV4::ExecutionEngine *v4) + : m_engine(nullptr) , m_v4Engine(v4) +#if QT_CONFIG(qml_xml_http_request) , m_xmlHttpRequestData(nullptr) +#endif { #ifdef Q_PROCESSOR_X86_32 if (!qCpuHasFeature(SSE2)) { @@ -157,7 +165,7 @@ QV8Engine::~QV8Engine() qDeleteAll(m_extensionData); m_extensionData.clear(); -#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network) +#if QT_CONFIG(qml_xml_http_request) qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData); m_xmlHttpRequestData = nullptr; #endif @@ -180,14 +188,16 @@ void QV8Engine::initializeGlobal() QV4::Scope scope(m_v4Engine); QV4::GlobalExtensions::init(m_v4Engine->globalObject, QJSEngine::AllExtensions); - QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocObject<QV4::QtObject>(m_engine)); + QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocate<QV4::QtObject>(m_engine)); m_v4Engine->globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt); +#if QT_CONFIG(qml_locale) QQmlLocale::registerStringLocaleCompare(m_v4Engine); QQmlDateExtension::registerExtension(m_v4Engine); QQmlNumberExtension::registerExtension(m_v4Engine); +#endif -#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network) +#if QT_CONFIG(qml_xml_http_request) qt_add_domexceptions(m_v4Engine); m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine); #endif @@ -221,7 +231,7 @@ static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object) if (!instanceOfObject) return; - QV4::InternalClass *frozen = object->internalClass()->propertiesFrozen(); + QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen(); if (object->internalClass() == frozen) return; object->setInternalClass(frozen); diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index b6a378667e..d90f1827fe 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -154,10 +154,9 @@ class Q_QML_PRIVATE_EXPORT QV8Engine friend class QJSEngine; public: // static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; } - static QV4::ExecutionEngine *getV4(QJSEngine *q) { return q->handle(); } static QV4::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; } - QV8Engine(QJSEngine* qq, QV4::ExecutionEngine *v4); + QV8Engine(QV4::ExecutionEngine *v4); virtual ~QV8Engine(); // This enum should be in sync with QQmlEngine::ObjectOwnership @@ -170,10 +169,11 @@ public: void initQmlGlobalObject(); void setEngine(QQmlEngine *engine); QQmlEngine *engine() { return m_engine; } - QJSEngine *publicEngine() { return q; } QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; } +#if QT_CONFIG(qml_xml_http_request) void *xmlHttpRequestData() const { return m_xmlHttpRequestData; } +#endif void freezeObject(const QV4::Value &value); @@ -202,13 +202,14 @@ public: int consoleCountHelper(const QString &file, quint16 line, quint16 column); protected: - QJSEngine* q; QQmlEngine *m_engine; QQmlDelayedCallQueue m_delayedCallQueue; QV4::ExecutionEngine *m_v4Engine; +#if QT_CONFIG(qml_xml_http_request) void *m_xmlHttpRequestData; +#endif QVector<Deletable *> m_extensionData; diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h index 6e92867cf5..e02dfa5ed4 100644 --- a/src/qml/qtqmlglobal.h +++ b/src/qml/qtqmlglobal.h @@ -52,6 +52,7 @@ # endif #else # define QT_FEATURE_qml_debug -1 +# define QT_FEATURE_qml_sequence_object 1 #endif QT_BEGIN_NAMESPACE diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 44166e4aa8..6915ab6e89 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -93,7 +93,7 @@ struct DelegateModelGroupFunction : QV4::FunctionObject static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)) { - return scope->engine()->memoryManager->allocObject<DelegateModelGroupFunction>(scope, flag, code); + return scope->engine()->memoryManager->allocate<DelegateModelGroupFunction>(scope, flag, code); } static ReturnedValue call(const QV4::FunctionObject *that, const Value *thisObject, const Value *argv, int argc) @@ -487,6 +487,35 @@ void QQmlDelegateModel::setRootIndex(const QVariant &root) } /*! + \qmlproperty int QtQml.Models::DelegateModel::rows + + Contains the number of rows in the model. If the model + is a list of items, it will be equal to the number of items + in the list. + + \since QtQml.Models 2.12 +*/ +int QQmlDelegateModel::rows() const +{ + Q_D(const QQmlDelegateModel); + return d->m_adaptorModel.rowCount(); +} + +/*! + \qmlproperty int QtQml.Models::DelegateModel::columns + + Contains the number of columns in the model. If the model + is a list of items, it will be equal to \c 1. + + \since QtQml.Models 2.12 +*/ +int QQmlDelegateModel::columns() const +{ + Q_D(const QQmlDelegateModel); + return d->m_adaptorModel.columnCount(); +} + +/*! \qmlmethod QModelIndex QtQml.Models::DelegateModel::modelIndex(int index) QAbstractItemModel provides a hierarchical tree of data, whereas @@ -1045,7 +1074,10 @@ QQmlIncubator::Status QQmlDelegateModel::incubationStatus(int index) if (!it->inCache()) return QQmlIncubator::Null; - return d->m_cache.at(it.cacheIndex)->incubationTask->status(); + if (auto incubationTask = d->m_cache.at(it.cacheIndex)->incubationTask) + return incubationTask->status(); + + return QQmlIncubator::Ready; } QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index, const QString &name) @@ -1587,8 +1619,15 @@ void QQmlDelegateModel::_q_rowsMoved( void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles) { Q_D(QQmlDelegateModel); - if (begin.parent() == d->m_adaptorModel.rootIndex) - _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles); + if (begin.parent() != d->m_adaptorModel.rootIndex) + return; + + int rowCount = end.row() - begin.row() + 1; + + for (int col = begin.column(); col <= end.column(); ++col) { + int startIndex = d->m_adaptorModel.indexAt(begin.row(), col); + _q_itemsChanged(startIndex, rowCount, roles); + } } bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const QList< QPersistentModelIndex >& parents) const @@ -2482,7 +2521,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index) model->m_cacheMetaType->initializePrototype(); QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine; QV4::Scope scope(v4); - QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(cacheItem)); + QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem)); QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value()); o->setPrototype(p); ++cacheItem->scriptRef; @@ -3193,7 +3232,10 @@ QQmlIncubator::Status QQmlPartsModel::incubationStatus(int index) if (!it->inCache()) return QQmlIncubator::Null; - return model->m_cache.at(it.cacheIndex)->incubationTask->status(); + if (auto incubationTask = model->m_cache.at(it.cacheIndex)->incubationTask) + return incubationTask->status(); + + return QQmlIncubator::Ready; } int QQmlPartsModel::indexOf(QObject *item, QObject *) const @@ -3237,7 +3279,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object) static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) { - return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>(); + return e->memoryManager->allocate<QQmlDelegateModelGroupChange>(); } static QV4::ReturnedValue method_get_index(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) { @@ -3274,7 +3316,7 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object public: static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes) { - return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes); + return engine->memoryManager->allocate<QQmlDelegateModelGroupChangeArray>(changes); } quint32 count() const { return d()->changes->count(); } diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h index b0786cd088..0a76d884ed 100644 --- a/src/qml/types/qqmldelegatemodel_p.h +++ b/src/qml/types/qqmldelegatemodel_p.h @@ -88,6 +88,8 @@ class Q_QML_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, public Q_PROPERTY(QQmlListProperty<QQmlDelegateModelGroup> groups READ groups CONSTANT) Q_PROPERTY(QObject *parts READ parts CONSTANT) Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged) + Q_PROPERTY(int rows READ rows NOTIFY rowsChanged REVISION 12) + Q_PROPERTY(int columns READ columns NOTIFY columnsChanged REVISION 12) Q_CLASSINFO("DefaultProperty", "delegate") Q_INTERFACES(QQmlParserStatus) public: @@ -107,6 +109,9 @@ public: QVariant rootIndex() const; void setRootIndex(const QVariant &root); + int rows() const; + int columns() const; + Q_INVOKABLE QVariant modelIndex(int idx) const; Q_INVOKABLE QVariant parentModelIndex() const; @@ -138,6 +143,8 @@ Q_SIGNALS: void filterGroupChanged(); void defaultGroupsChanged(); void rootIndexChanged(); + Q_REVISION(12) void rowsChanged(); + Q_REVISION(12) void columnsChanged(); private Q_SLOTS: void _q_itemsChanged(int index, int count, const QVector<int> &roles); diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index 18980cfd7c..30401a2105 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -121,7 +121,7 @@ public: int groupIndex(Compositor::Group group); int modelIndex() const { return index; } - void setModelIndex(int idx) { index = idx; Q_EMIT modelIndexChanged(); } + virtual void setModelIndex(int idx) { index = idx; Q_EMIT modelIndexChanged(); } virtual QV4::ReturnedValue get() { return QV4::QObjectWrapper::wrap(v4, this); } diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index c4e33d572d..fd54a51b1d 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -2434,7 +2434,7 @@ QQmlV4Handle QQmlListModel::get(int index) const QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index); QQmlData *ddata = QQmlData::get(object); if (ddata->jsWrapper.isNullOrUndefined()) { - result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this)); + result = scope.engine->memoryManager->allocate<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this)); // Keep track of the QObjectWrapper in persistent value storage ddata->jsWrapper.set(scope.engine, result); } else { diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h index 0c0859dc80..0a9d29ac05 100644 --- a/src/qml/types/qqmllistmodel_p.h +++ b/src/qml/types/qqmllistmodel_p.h @@ -64,6 +64,8 @@ #include <private/qv4engine_p.h> #include <private/qpodvector_p.h> +QT_REQUIRE_CONFIG(qml_list_model); + QT_BEGIN_NAMESPACE diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index ad5e94c909..99e9b30aff 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -57,6 +57,8 @@ #include <private/qv4qobjectwrapper_p.h> #include <qqml.h> +QT_REQUIRE_CONFIG(qml_list_model); + QT_BEGIN_NAMESPACE diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h index 2120f25744..ae2d4b11e0 100644 --- a/src/qml/types/qqmllistmodelworkeragent_p.h +++ b/src/qml/types/qqmllistmodelworkeragent_p.h @@ -59,6 +59,8 @@ #include <private/qv8engine_p.h> +QT_REQUIRE_CONFIG(qml_list_model); + QT_BEGIN_NAMESPACE diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp index e217b63c6f..d9756704d1 100644 --- a/src/qml/types/qqmlmodelsmodule.cpp +++ b/src/qml/types/qqmlmodelsmodule.cpp @@ -39,7 +39,9 @@ #include "qqmlmodelsmodule_p.h" #include <QtCore/qitemselectionmodel.h> +#if QT_CONFIG(qml_list_model) #include <private/qqmllistmodel_p.h> +#endif #if QT_CONFIG(qml_delegate_model) #include <private/qqmldelegatemodel_p.h> #endif @@ -51,10 +53,13 @@ void QQmlModelsModule::defineModule() { const char uri[] = "QtQml.Models"; +#if QT_CONFIG(qml_list_model) qmlRegisterType<QQmlListElement>(uri, 2, 1, "ListElement"); qmlRegisterCustomType<QQmlListModel>(uri, 2, 1, "ListModel", new QQmlListModelParser); +#endif #if QT_CONFIG(qml_delegate_model) qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel"); + qmlRegisterType<QQmlDelegateModel,12>(uri, 2, 9, "DelegateModel"); qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup"); #endif qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel"); diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h index d597869994..0160e97a2f 100644 --- a/src/qml/types/qqmltimer_p.h +++ b/src/qml/types/qqmltimer_p.h @@ -57,6 +57,8 @@ #include <private/qtqmlglobal_p.h> +QT_REQUIRE_CONFIG(qml_animation); + QT_BEGIN_NAMESPACE class QQmlTimerPrivate; diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index ef92e4108d..634e2da1c9 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -37,9 +37,12 @@ ** ****************************************************************************/ +#include "qtqmlglobal_p.h" #include "qquickworkerscript_p.h" +#if QT_CONFIG(qml_list_model) #include "qqmllistmodel_p.h" #include "qqmllistmodelworkeragent_p.h" +#endif #include <private/qqmlengine_p.h> #include <private/qqmlexpression_p.h> @@ -201,7 +204,7 @@ private: }; QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent) - : QV8Engine(nullptr, new QV4::ExecutionEngine), p(parent) + : QV8Engine(new QV4::ExecutionEngine), p(parent) #if QT_CONFIG(qml_network) , accessManager(nullptr) #endif diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri index 8bcbd6e544..5d75759281 100644 --- a/src/qml/types/types.pri +++ b/src/qml/types/types.pri @@ -1,8 +1,6 @@ SOURCES += \ $$PWD/qqmlbind.cpp \ $$PWD/qqmlconnections.cpp \ - $$PWD/qqmllistmodel.cpp \ - $$PWD/qqmllistmodelworkeragent.cpp \ $$PWD/qqmlmodelsmodule.cpp \ $$PWD/qqmlmodelindexvaluetype.cpp \ $$PWD/qqmlobjectmodel.cpp \ @@ -13,9 +11,6 @@ SOURCES += \ HEADERS += \ $$PWD/qqmlbind_p.h \ $$PWD/qqmlconnections_p.h \ - $$PWD/qqmllistmodel_p.h \ - $$PWD/qqmllistmodel_p_p.h \ - $$PWD/qqmllistmodelworkeragent_p.h \ $$PWD/qqmlmodelsmodule_p.h \ $$PWD/qqmlmodelindexvaluetype_p.h \ $$PWD/qqmlobjectmodel_p.h \ @@ -24,6 +19,17 @@ HEADERS += \ $$PWD/qqmlinstantiator_p.h \ $$PWD/qqmlinstantiator_p_p.h +qtConfig(qml-list-model) { + SOURCES += \ + $$PWD/qqmllistmodel.cpp \ + $$PWD/qqmllistmodelworkeragent.cpp + + HEADERS += \ + $$PWD/qqmllistmodel_p.h \ + $$PWD/qqmllistmodel_p_p.h \ + $$PWD/qqmllistmodelworkeragent_p.h +} + qtConfig(qml-delegate-model) { SOURCES += \ $$PWD/qqmldelegatemodel.cpp @@ -33,7 +39,7 @@ qtConfig(qml-delegate-model) { $$PWD/qqmldelegatemodel_p_p.h } -qtConfig(animation) { +qtConfig(qml-animation) { SOURCES += \ $$PWD/qqmltimer.cpp diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index b4bebb9d5d..c430074f56 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -228,8 +228,8 @@ public: QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName))); QV4::ExecutionContext *global = v4->rootContext(); - QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property)); - QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property)); + QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property)); + QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property)); p->setGetter(g); p->setSetter(s); proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable); @@ -330,9 +330,8 @@ bool QQmlDMCachedModelData::resolveIndex(const QQmlAdaptorModel &, int idx) { if (index == -1) { Q_ASSERT(idx >= 0); - index = idx; cachedData.clear(); - emit modelIndexChanged(); + setModelIndex(idx); const QMetaObject *meta = metaObject(); const int propertyCount = type->propertyRoles.count(); for (int i = 0; i < propertyCount; ++i) @@ -399,13 +398,18 @@ QV4::ReturnedValue QQmlDMCachedModelData::set_property(const QV4::FunctionObject class QQmlDMAbstractItemModelData : public QQmlDMCachedModelData { Q_OBJECT + Q_PROPERTY(int row MEMBER row NOTIFY rowChanged) + Q_PROPERTY(int column MEMBER column NOTIFY columnChanged) Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT) + public: QQmlDMAbstractItemModelData( QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index) : QQmlDMCachedModelData(metaType, dataType, index) + , row(type->model->rowAt(index)) + , column(type->model->columnAt(index)) { } @@ -413,7 +417,7 @@ public: { if (index >= 0 && *type->model) { const QAbstractItemModel * const model = type->model->aim(); - return model->hasChildren(model->index(index, 0, type->model->rootIndex)); + return model->hasChildren(model->index(row, column, type->model->rootIndex)); } else { return false; } @@ -421,13 +425,13 @@ public: QVariant value(int role) const override { - return type->model->aim()->index(index, 0, type->model->rootIndex).data(role); + return type->model->aim()->index(row, column, type->model->rootIndex).data(role); } void setValue(int role, const QVariant &value) override { type->model->aim()->setData( - type->model->aim()->index(index, 0, type->model->rootIndex), value, role); + type->model->aim()->index(row, column, type->model->rootIndex), value, role); } QV4::ReturnedValue get() override @@ -438,11 +442,21 @@ public: } QV4::Scope scope(v4); QV4::ScopedObject proto(scope, type->prototype.value()); - QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocObject<QQmlDelegateModelItemObject>(this)); + QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocate<QQmlDelegateModelItemObject>(this)); o->setPrototype(proto); ++scriptRef; return o.asReturnedValue(); } + + void setModelIndex(int idx) override; + +Q_SIGNALS: + void rowChanged(); + void columnChanged(); + +private: + int row; + int column; }; class VDMAbstractItemModelDataType : public VDMModelDelegateDataType @@ -453,11 +467,16 @@ public: { } - int count(const QQmlAdaptorModel &model) const override + int rowCount(const QQmlAdaptorModel &model) const override { return model.aim()->rowCount(model.rootIndex); } + int columnCount(const QQmlAdaptorModel &model) const override + { + return model.aim()->columnCount(model.rootIndex); + } + void cleanup(QQmlAdaptorModel &model, QQmlDelegateModel *vdm) const override { QAbstractItemModel * const aim = model.aim(); @@ -485,9 +504,9 @@ public: { QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8()); if (it != roleNames.end()) { - return model.aim()->index(index, 0, model.rootIndex).data(*it); + return model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex).data(*it); } else if (role == QLatin1String("hasModelChildren")) { - return QVariant(model.aim()->hasChildren(model.aim()->index(index, 0, model.rootIndex))); + return QVariant(model.aim()->hasChildren(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex))); } else { return QVariant(); } @@ -503,7 +522,7 @@ public: QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override { return model - ? QVariant::fromValue(model.aim()->index(index, 0, model.rootIndex)) + ? QVariant::fromValue(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex)) : QVariant(); } @@ -558,6 +577,22 @@ public: } }; +void QQmlDMAbstractItemModelData::setModelIndex(int idx) +{ + QQmlDMCachedModelData::setModelIndex(idx); + + int prevRow = row; + int prevColumn = column; + + row = type->model->rowAt(idx); + column = type->model->columnAt(idx); + + if (row != prevRow) + emit rowChanged(); + if (column != prevColumn) + emit columnChanged(); +} + //----------------------------------------------------------------- // QQmlListAccessor //----------------------------------------------------------------- @@ -613,7 +648,7 @@ public: { QQmlAdaptorModelEngineData *data = engineData(v4); QV4::Scope scope(v4); - QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(this)); + QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(this)); QV4::ScopedObject p(scope, data->listItemProto.value()); o->setPrototype(p); ++scriptRef; @@ -653,11 +688,16 @@ class VDMListDelegateDataType : public QQmlAdaptorModel::Accessors public: inline VDMListDelegateDataType() {} - int count(const QQmlAdaptorModel &model) const override + int rowCount(const QQmlAdaptorModel &model) const override { return model.list.count(); } + int columnCount(const QQmlAdaptorModel &) const override + { + return 1; + } + QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override { return role == QLatin1String("modelData") @@ -737,11 +777,16 @@ public: free(metaObject); } - int count(const QQmlAdaptorModel &model) const override + int rowCount(const QQmlAdaptorModel &model) const override { return model.list.count(); } + int columnCount(const QQmlAdaptorModel &) const override + { + return 1; + } + QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override { if (QObject *object = model.list.at(index).value<QObject *>()) @@ -958,6 +1003,38 @@ bool QQmlAdaptorModel::isValid() const return accessors != &qt_vdm_null_accessors; } +int QQmlAdaptorModel::count() const +{ + return rowCount() * columnCount(); +} + +int QQmlAdaptorModel::rowCount() const +{ + return qMax(0, accessors->rowCount(*this)); +} + +int QQmlAdaptorModel::columnCount() const +{ + return qMax(isValid() ? 1 : 0, accessors->columnCount(*this)); +} + +int QQmlAdaptorModel::rowAt(int index) const +{ + int count = rowCount(); + return count <= 0 ? -1 : index % count; +} + +int QQmlAdaptorModel::columnAt(int index) const +{ + int count = rowCount(); + return count <= 0 ? -1 : index / count; +} + +int QQmlAdaptorModel::indexAt(int row, int column) const +{ + return row + (column * rowCount()); +} + void QQmlAdaptorModel::objectDestroyed(QObject *) { setModel(QVariant(), nullptr, nullptr); diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h index b152a886a5..b706fcb5f2 100644 --- a/src/qml/util/qqmladaptormodel_p.h +++ b/src/qml/util/qqmladaptormodel_p.h @@ -56,6 +56,7 @@ #include "private/qqmllistaccessor_p.h" #include <private/qqmlguard_p.h> +#include <private/qqmlnullablevalue_p.h> QT_REQUIRE_CONFIG(qml_delegate_model); @@ -75,7 +76,8 @@ public: public: inline Accessors() {} virtual ~Accessors(); - virtual int count(const QQmlAdaptorModel &) const { return 0; } + virtual int rowCount(const QQmlAdaptorModel &) const { return 0; } + virtual int columnCount(const QQmlAdaptorModel &) const { return 0; } virtual void cleanup(QQmlAdaptorModel &, QQmlDelegateModel * = nullptr) const {} virtual QVariant value(const QQmlAdaptorModel &, int, const QString &) const { @@ -116,11 +118,16 @@ public: void invalidateModel(QQmlDelegateModel *vdm); bool isValid() const; + int count() const; + int rowCount() const; + int columnCount() const; + int rowAt(int index) const; + int columnAt(int index) const; + int indexAt(int row, int column) const; inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); } inline const QAbstractItemModel *aim() const { return static_cast<const QAbstractItemModel *>(object()); } - inline int count() const { return qMax(0, accessors->count(*this)); } inline QVariant value(int index, const QString &role) const { return accessors->value(*this, index, role); } inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) { |