From owner-svn-ports-head@freebsd.org Thu Dec 5 14:38:40 2019 Return-Path: Delivered-To: svn-ports-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 670D21CAE37; Thu, 5 Dec 2019 14:38:40 +0000 (UTC) (envelope-from fluffy@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47TJHh2s1Zz4GHC; Thu, 5 Dec 2019 14:38:40 +0000 (UTC) (envelope-from fluffy@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 44CD11A59B; Thu, 5 Dec 2019 14:38:40 +0000 (UTC) (envelope-from fluffy@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xB5Ecem3020543; Thu, 5 Dec 2019 14:38:40 GMT (envelope-from fluffy@FreeBSD.org) Received: (from fluffy@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xB5EceQu020542; Thu, 5 Dec 2019 14:38:40 GMT (envelope-from fluffy@FreeBSD.org) Message-Id: <201912051438.xB5EceQu020542@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: fluffy set sender to fluffy@FreeBSD.org using -f From: Dima Panov Date: Thu, 5 Dec 2019 14:38:40 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r519081 - head/devel/kdev-python/files X-SVN-Group: ports-head X-SVN-Commit-Author: fluffy X-SVN-Commit-Paths: head/devel/kdev-python/files X-SVN-Commit-Revision: 519081 X-SVN-Commit-Repository: ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Dec 2019 14:38:40 -0000 Author: fluffy Date: Thu Dec 5 14:38:39 2019 New Revision: 519081 URL: https://svnweb.freebsd.org/changeset/ports/519081 Log: - devel/kdev-python: unbreak with py38 No PORTREVISION bump, build was always broken Obtained from: KDE git Added: head/devel/kdev-python/files/patch-cgite23fa8f (contents, props changed) Added: head/devel/kdev-python/files/patch-cgite23fa8f ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/devel/kdev-python/files/patch-cgite23fa8f Thu Dec 5 14:38:39 2019 (r519081) @@ -0,0 +1,739 @@ +From e23fa8f15af89a8bd4bd84dd96b5fd7017457516 Mon Sep 17 00:00:00 2001 +From: Francis Herne +Date: Fri, 20 Sep 2019 00:41:29 +0100 +Subject: Initial Python 3.8 support. + +This allows kdev-python to be built and run against CPython 3.8, + and if so to parse files containing 3.8 syntax. + +BUG: 411956 +FIXED-IN: 5.5.0 +--- + CMakeLists.txt | 4 +- + duchain/declarationbuilder.cpp | 10 ++- + duchain/declarationbuilder.h | 1 + + duchain/expressionvisitor.cpp | 4 ++ + duchain/expressionvisitor.h | 1 + + duchain/tests/pyduchaintest.cpp | 19 ++++++ + parser/ast.cpp | 7 +- + parser/ast.h | 9 +++ + parser/astbuilder.cpp | 6 ++ + parser/astdefaultvisitor.cpp | 6 ++ + parser/astdefaultvisitor.h | 2 + + parser/astvisitor.cpp | 1 + + parser/astvisitor.h | 1 + + parser/conversionGenerator.py | 11 +-- + parser/generated.h | 36 ++++++++++ + parser/python36.sdef | 102 ---------------------------- + parser/python38.sdef | 145 ++++++++++++++++++++++++++++++++++++++++ + parser/tests/pyasttest.cpp | 5 ++ + 18 files changed, 260 insertions(+), 110 deletions(-) + delete mode 100644 parser/python36.sdef + create mode 100644 parser/python38.sdef + +diff --git ./CMakeLists.txt ./CMakeLists.txt +index 6f9e465..09b089d 100644 +--- ./CMakeLists.txt ++++ ./CMakeLists.txt +@@ -31,7 +31,7 @@ add_definitions( -DTRANSLATION_DOMAIN=\"kdevpython\" ) + + # CMake looks for exactly the specified version first and ignores newer versions. + # To avoid that, start looking for the newest supported version and work down. +-set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5 3.4) ++set(Python_ADDITIONAL_VERSIONS 3.8 3.7 3.6 3.5 3.4) + foreach(_PYTHON_V ${Python_ADDITIONAL_VERSIONS}) + find_package(PythonInterp ${_PYTHON_V}) + if ( PYTHONINTERP_FOUND ) +@@ -49,7 +49,7 @@ if ( PYTHONINTERP_FOUND AND PYTHON_VERSION_STRING VERSION_GREATER "3.4" ) + endif() + + if ( NOT PYTHONLIBS_FOUND OR PYTHONLIBS_VERSION_STRING VERSION_LESS "3.4.3" ) +- message(FATAL_ERROR "Python >= 3.4.3 but < 3.8 with --enable-shared is required to build kdev-python") ++ message(FATAL_ERROR "Python >= 3.4.3 but < 3.9 with --enable-shared is required to build kdev-python") + endif() + + configure_file(kdevpythonversion.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/kdevpythonversion.h" @ONLY) +diff --git ./duchain/declarationbuilder.cpp ./duchain/declarationbuilder.cpp +index e3cb2b9..61e144c 100644 +--- ./duchain/declarationbuilder.cpp ++++ ./duchain/declarationbuilder.cpp +@@ -1354,6 +1354,14 @@ void DeclarationBuilder::visitAnnotationAssignment(AnnotationAssignmentAst* node + assignToUnknown(node->target, assignType); + } + ++void DeclarationBuilder::visitAssignmentExpression(AssignmentExpressionAst* node) { ++ AstDefaultVisitor::visitAssignmentExpression(node); ++ ++ ExpressionVisitor v(currentContext()); ++ v.visitNode(node->value); ++ assignToUnknown(node->target, v.lastType()); ++} ++ + void DeclarationBuilder::visitClassDefinition( ClassDefinitionAst* node ) + { + visitNodeList(node->decorators); +@@ -1745,7 +1753,7 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node ) + int parametersCount = node->arguments.length(); + int firstDefaultParameterOffset = parametersCount - defaultParametersCount; + int currentIndex = 0; +- foreach ( ArgAst* arg, node->arguments + node->kwonlyargs ) { ++ foreach ( ArgAst* arg, node->posonlyargs + node->arguments + node->kwonlyargs ) { + // Iterate over all the function's arguments, create declarations, and add the arguments + // to the functions FunctionType. + currentIndex += 1; +diff --git ./duchain/declarationbuilder.h ./duchain/declarationbuilder.h +index adee6d6..1992b78 100644 +--- ./duchain/declarationbuilder.h ++++ ./duchain/declarationbuilder.h +@@ -90,6 +90,7 @@ protected: + void visitFunctionDefinition(FunctionDefinitionAst* node) override; + void visitAssignment(AssignmentAst* node) override; + void visitAnnotationAssignment(AnnotationAssignmentAst* node) override; ++ void visitAssignmentExpression(AssignmentExpressionAst* node) override; + void visitFor(ForAst* node) override; + void visitImport(ImportAst* node) override; + void visitImportFrom(ImportFromAst* node) override; +diff --git ./duchain/expressionvisitor.cpp ./duchain/expressionvisitor.cpp +index 5c5286a..055c5b4 100644 +--- ./duchain/expressionvisitor.cpp ++++ ./duchain/expressionvisitor.cpp +@@ -757,5 +757,9 @@ void ExpressionVisitor::visitBooleanOperation(Python::BooleanOperationAst* node) + encounter(result); + } + ++void ExpressionVisitor::visitAssignmentExpression(Python::AssignmentExpressionAst* node) { ++ visitNode(node->value); ++} ++ + } + +diff --git ./duchain/expressionvisitor.h ./duchain/expressionvisitor.h +index 25ca231..a56481a 100644 +--- ./duchain/expressionvisitor.h ++++ ./duchain/expressionvisitor.h +@@ -81,6 +81,7 @@ public: + void visitSetComprehension(SetComprehensionAst* node) override; + void visitIfExpression(IfExpressionAst* node) override; + void visitNameConstant(NameConstantAst* node) override; ++ void visitAssignmentExpression(AssignmentExpressionAst* node) override; + + /** + * @brief Checks for magic docstrings that override a call's return type. +diff --git ./duchain/tests/pyduchaintest.cpp ./duchain/tests/pyduchaintest.cpp +index 7142ed2..17ba34e 100644 +--- ./duchain/tests/pyduchaintest.cpp ++++ ./duchain/tests/pyduchaintest.cpp +@@ -838,6 +838,7 @@ void PyDUChainTest::testTypes() + QEXPECT_FAIL("init_class_no_decl", "aliasing info lost", Continue); + QEXPECT_FAIL("property_wrong", "visitCall uses declaration if no type", Continue); + QEXPECT_FAIL("property_setter", "very basic property support", Continue); ++ QEXPECT_FAIL("assignment_expr_context", "not implemented", Continue); + QCOMPARE(visitor->found, true); + } + +@@ -1302,6 +1303,21 @@ void PyDUChainTest::testTypes_data() + " def foo(self, ccc=aaa, ddd=bbb):\n" // self.bbb is visible here, Foo().aaa isn't. + " return ccc, ddd\n" + "checkme = Foo().Bar().foo()\n" << "tuple of (str, int)"; ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ QTest::newRow("assignment_expr_while") << ++ "file = open('foo.txt')\n" ++ "while q := file.readline():\n" ++ " checkme = q\n" << "str"; ++ QTest::newRow("assignment_expr_comprehension") << ++ "checkme = [z for q in (1, 2, 3) if (z := q % 2)]" << "list of int"; ++ QTest::newRow("assignment_expr_context") << ++ "a = [z for q in (1, 2, 3) if (z := q % 2)]\n" ++ "checkme = z" << "int"; ++ QTest::newRow("positional_params") << ++ "def foo(a, b, /, c, d):\n" ++ " return a, b, c, d\n" ++ "checkme = foo(10, 'x', 2.3, d='y')\n" << "tuple of (int, str, float, str)"; ++#endif + } + + typedef QPair pair; +@@ -1780,6 +1796,9 @@ void PyDUChainTest::testVariableCreation_data() + << QStringList{"int", "int", "float"}; + QTest::newRow("for_loop_tuple") << "for a in 1, 2: pass" << QStringList{"a"} << QStringList{"int"}; + QTest::newRow("for_loop_dict") << "for a in {'foo': 1}: pass" << QStringList{"a"} << QStringList{"str"}; ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ QTest::newRow("assignment_expr") << "a = (b := 10)" << QStringList{"a", "b"} << QStringList{"int", "int"}; ++#endif + } + + void PyDUChainTest::testCleanupMultiplePasses() +diff --git ./parser/ast.cpp ./parser/ast.cpp +index 9892b18..cd570d3 100644 +--- ./parser/ast.cpp ++++ ./parser/ast.cpp +@@ -163,6 +163,11 @@ ExpressionAst::ExpressionAst(Ast* parent, AstType type): Ast(parent, type), valu + + } + ++AssignmentExpressionAst::AssignmentExpressionAst(Ast* parent): ExpressionAst(parent, Ast::AssignmentExpressionAstType), value(nullptr) ++{ ++ ++} ++ + YieldFromAst::YieldFromAst(Ast* parent) : ExpressionAst(parent, Ast::YieldFromAstType) + { + +@@ -248,7 +253,7 @@ NameConstantAst::NameConstantAst(Ast* parent): ExpressionAst(parent, Ast::NameCo + + } + +-NumberAst::NumberAst(Ast* parent): ExpressionAst(parent, Ast::NumberAstType), value(0) ++NumberAst::NumberAst(Ast* parent): ExpressionAst(parent, Ast::NumberAstType), value(0), isInt(false) + { + + } +diff --git ./parser/ast.h ./parser/ast.h +index 378af0b..65fef1c 100644 +--- ./parser/ast.h ++++ ./parser/ast.h +@@ -131,6 +131,7 @@ public: + SliceAstType, + EllipsisAstType, + IndexAstType, ++ AssignmentExpressionAstType, + LastExpressionType, // keep this at the end of the expr ast list + + CodeAstType, +@@ -457,6 +458,13 @@ public: + ExpressionAst* value; // WARNING this is not set in most cases! + }; + ++class KDEVPYTHONPARSER_EXPORT AssignmentExpressionAst : public ExpressionAst { ++public: ++ AssignmentExpressionAst(Ast* parent); ++ ExpressionAst* target; ++ ExpressionAst* value; ++}; ++ + class KDEVPYTHONPARSER_EXPORT AwaitAst : public ExpressionAst { + public: + AwaitAst(Ast* parent); +@@ -743,6 +751,7 @@ public: + ArgumentsAst(Ast* parent); + QList arguments; + QList kwonlyargs; ++ QList posonlyargs; + QList defaultValues; + ArgAst* vararg; + ArgAst* kwarg; +diff --git ./parser/astbuilder.cpp ./parser/astbuilder.cpp +index a1ccd68..ad2e0dc 100644 +--- ./parser/astbuilder.cpp ++++ ./parser/astbuilder.cpp +@@ -101,7 +101,13 @@ CodeAst::Ptr AstBuilder::parse(const QUrl& filename, QString &contents) + PythonInitializer pyIniter(pyInitLock); + PyArena* arena = pyIniter.arena; + ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ PyCompilerFlags flags; ++ flags.cf_flags = PyCF_SOURCE_IS_UTF8 | PyCF_IGNORE_COOKIE | PyCF_ONLY_AST; ++ flags.cf_feature_version = 7; ++#else + PyCompilerFlags flags = {PyCF_SOURCE_IS_UTF8 | PyCF_IGNORE_COOKIE}; ++#endif + + CythonSyntaxRemover cythonSyntaxRemover; + +diff --git ./parser/astdefaultvisitor.cpp ./parser/astdefaultvisitor.cpp +index 5db1f6f..cdd31bb 100644 +--- ./parser/astdefaultvisitor.cpp ++++ ./parser/astdefaultvisitor.cpp +@@ -292,6 +292,12 @@ void AstDefaultVisitor::visitAnnotationAssignment(AnnotationAssignmentAst* node) + visitNode(node->value); + } + ++void AstDefaultVisitor::visitAssignmentExpression(AssignmentExpressionAst* node) ++{ ++ visitNode(node->target); ++ visitNode(node->value); ++} ++ + void AstDefaultVisitor::visitBinaryOperation(BinaryOperationAst* node) + { + visitNode(node->lhs); +diff --git ./parser/astdefaultvisitor.h ./parser/astdefaultvisitor.h +index e8e0d3d..aa1f540 100644 +--- ./parser/astdefaultvisitor.h ++++ ./parser/astdefaultvisitor.h +@@ -49,6 +49,7 @@ public: + void visitAssignment(AssignmentAst* node) override; + void visitAugmentedAssignment(AugmentedAssignmentAst* node) override; + void visitAnnotationAssignment(AnnotationAssignmentAst* node) override; ++ void visitAssignmentExpression(AssignmentExpressionAst* node) override; + void visitFor(ForAst* node) override; + void visitWhile(WhileAst* node) override; + void visitIf(IfAst* node) override; +@@ -122,6 +123,7 @@ public: + void visitAssignment(AssignmentAst* node) override { AstDefaultVisitor::visitAssignment(node); delete node; } + void visitAugmentedAssignment(AugmentedAssignmentAst* node) override { AstDefaultVisitor::visitAugmentedAssignment(node); delete node; } + void visitAnnotationAssignment(AnnotationAssignmentAst* node) override { AstDefaultVisitor::visitAnnotationAssignment(node); delete node; } ++ void visitAssignmentExpression(AssignmentExpressionAst* node) override { AstDefaultVisitor::visitAssignmentExpression(node); delete node; } + void visitFor(ForAst* node) override { AstDefaultVisitor::visitFor(node); delete node; } + void visitWhile(WhileAst* node) override { AstDefaultVisitor::visitWhile(node); delete node; } + void visitIf(IfAst* node) override { AstDefaultVisitor::visitIf(node); delete node; } +diff --git ./parser/astvisitor.cpp ./parser/astvisitor.cpp +index ace7d61..51c5a1c 100644 +--- ./parser/astvisitor.cpp ++++ ./parser/astvisitor.cpp +@@ -47,6 +47,7 @@ void AstVisitor::visitNode(Ast* node) + case Ast::AssignmentAstType: this->visitAssignment(static_cast(node)); break; + case Ast::AugmentedAssignmentAstType: this->visitAugmentedAssignment(static_cast(node)); break; + case Ast::AnnotationAssignmentAstType: this->visitAnnotationAssignment(static_cast(node)); break; ++ case Ast::AssignmentExpressionAstType: this->visitAssignmentExpression(static_cast(node)); break; + case Ast::ForAstType: this->visitFor(static_cast(node)); break; + case Ast::WhileAstType: this->visitWhile(static_cast(node)); break; + case Ast::IfAstType: this->visitIf(static_cast(node)); break; +diff --git ./parser/astvisitor.h ./parser/astvisitor.h +index 1908e9d..51aa47b 100644 +--- ./parser/astvisitor.h ++++ ./parser/astvisitor.h +@@ -61,6 +61,7 @@ public: + virtual void visitAssignment(AssignmentAst* node) { Q_UNUSED(node); }; + virtual void visitAugmentedAssignment(AugmentedAssignmentAst* node) { Q_UNUSED(node); }; + virtual void visitAnnotationAssignment(AnnotationAssignmentAst* node) { Q_UNUSED(node); }; ++ virtual void visitAssignmentExpression(AssignmentExpressionAst* node) { Q_UNUSED(node); }; + virtual void visitFor(ForAst* node) { Q_UNUSED(node); }; + virtual void visitWhile(WhileAst* node) { Q_UNUSED(node); }; + virtual void visitIf(IfAst* node) { Q_UNUSED(node); }; +diff --git ./parser/conversionGenerator.py ./parser/conversionGenerator.py +index 9d65cc0..6605595 100644 +--- ./parser/conversionGenerator.py ++++ ./parser/conversionGenerator.py +@@ -9,7 +9,7 @@ + + import sys + +-contents = open('python36.sdef').read().replace("\n", "").split(';;') ++contents = open('python38.sdef').read().replace("\n", "").split(';;') + + func_structure = ''' + Ast* visitNode(%{RULE_FOR}* node) { +@@ -45,7 +45,6 @@ simple_func_structure = ''' + + switch_line = ''' case %{KIND}: { + %{ACTIONS} +- result = v; + break; + }''' + +@@ -139,6 +138,7 @@ for rule in contents: + results[rule_for] = list() + + current_actions = list() ++ created_v = False + for action in actions: + command = action.split('|')[0] + try: +@@ -204,14 +204,17 @@ for rule in contents: + elif command == 'create': + astType = arguments + current_actions.append(create_ast_line.replace('%{AST_TYPE}', astType)) +- ++ created_v = True ++ + if code: + current_actions.append(code); +- ++ + current_actions = "\n".join(current_actions) + if kind == 'any': + current_stmt = current_actions + else: ++ if created_v: ++ current_actions += "\n result = v;" + current_stmt = switch_line.replace('%{KIND}', kind).replace('%{ACTIONS}', current_actions) + if before_version: + version_cpp_if = ("#if PYTHON_VERSION < QT_VERSION_CHECK(%d, %d, 0)\n" +diff --git ./parser/generated.h ./parser/generated.h +index 9061deb..e1136f8 100644 +--- ./parser/generated.h ++++ ./parser/generated.h +@@ -76,12 +76,23 @@ private: + Ast* visitNode(_arguments* node) { + bool ranges_copied = false; Q_UNUSED(ranges_copied); + if ( ! node ) return nullptr; ++#if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0) + ArgumentsAst* v = new ArgumentsAst(parent()); + nodeStack.push(v); v->vararg = static_cast(visitNode(node->vararg)); nodeStack.pop(); + nodeStack.push(v); v->kwarg = static_cast(visitNode(node->kwarg)); nodeStack.pop(); + nodeStack.push(v); v->arguments = visitNodeList<_arg, ArgAst>(node->args); nodeStack.pop(); + nodeStack.push(v); v->defaultValues = visitNodeList<_expr, ExpressionAst>(node->defaults); nodeStack.pop(); + nodeStack.push(v); v->kwonlyargs = visitNodeList<_arg, ArgAst>(node->kwonlyargs); nodeStack.pop(); ++#endif ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ ArgumentsAst* v = new ArgumentsAst(parent()); ++ nodeStack.push(v); v->vararg = static_cast(visitNode(node->vararg)); nodeStack.pop(); ++ nodeStack.push(v); v->kwarg = static_cast(visitNode(node->kwarg)); nodeStack.pop(); ++ nodeStack.push(v); v->arguments = visitNodeList<_arg, ArgAst>(node->args); nodeStack.pop(); ++ nodeStack.push(v); v->defaultValues = visitNodeList<_expr, ExpressionAst>(node->defaults); nodeStack.pop(); ++ nodeStack.push(v); v->kwonlyargs = visitNodeList<_arg, ArgAst>(node->kwonlyargs); nodeStack.pop(); ++ nodeStack.push(v); v->posonlyargs = visitNodeList<_arg, ArgAst>(node->posonlyargs); nodeStack.pop(); ++#endif + return v; + } + +@@ -280,18 +291,22 @@ private: + break; + } + #endif ++#if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0) + case Num_kind: { + NumberAst* v = new NumberAst(parent()); + v->isInt = PyLong_Check(node->v.Num.n); v->value = PyLong_AsLong(node->v.Num.n); + result = v; + break; + } ++#endif ++#if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0) + case Str_kind: { + StringAst* v = new StringAst(parent()); + v->value = PyUnicodeObjectToQString(node->v.Str.s); + result = v; + break; + } ++#endif + #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0) + case JoinedStr_kind: { + JoinedStringAst* v = new JoinedStringAst(parent()); +@@ -310,12 +325,14 @@ private: + break; + } + #endif ++#if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0) + case Bytes_kind: { + BytesAst* v = new BytesAst(parent()); + v->value = PyUnicodeObjectToQString(node->v.Bytes.s); + result = v; + break; + } ++#endif + case Attribute_kind: { + AttributeAst* v = new AttributeAst(parent()); + v->attribute = node->v.Attribute.attr ? new Python::Identifier(PyUnicodeObjectToQString(node->v.Attribute.attr)) : nullptr; +@@ -374,23 +391,42 @@ private: + result = v; + break; + } ++#if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0) + case Ellipsis_kind: { + EllipsisAst* v = new EllipsisAst(parent()); + result = v; + break; + } ++#endif ++#if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0) + case NameConstant_kind: { + NameConstantAst* v = new NameConstantAst(parent()); + v->value = node->v.NameConstant.value == Py_None ? NameConstantAst::None : node->v.NameConstant.value == Py_False ? NameConstantAst::False : NameConstantAst::True; + result = v; + break; + } ++#endif + case YieldFrom_kind: { + YieldFromAst* v = new YieldFromAst(parent()); + nodeStack.push(v); v->value = static_cast(visitNode(node->v.YieldFrom.value)); nodeStack.pop(); + result = v; + break; + } ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ case Constant_kind: { ++PyObject *value = node->v.Constant.value;if (value == Py_None) { NameConstantAst* v = new NameConstantAst(parent()); v->value = NameConstantAst::None; result = v;}else if (value == Py_True) { NameConstantAst* v = new NameConstantAst(parent()); v->value = NameConstantAst::True; result = v;}else if (value == Py_False) { NameConstantAst* v = new NameConstantAst(parent()); v->value = NameConstantAst::False; result = v;}else if (value->ob_type == &PyLong_Type) { NumberAst* v = new NumberAst(parent()); v->isInt = true; v->value = PyLong_AsLong(value); result = v;}else if (value->ob_type == &PyFloat_Type || value->ob_type == &PyComplex_Type) { result = new NumberAst(parent());}else if (value->ob_type == &PyUnicode_Type) { StringAst* v = new StringAst(parent()); v->value = PyUnicodeObjectToQString(value); result = v;}else if (value->ob_type == &PyBytes_Type) { result = new BytesAst(parent());}else if (value->ob_type == &PyEllipsis_Typ e) { result = new EllipsisAst(parent());}else { qWarning() << "Unhandled constant type: " << value->ob_type->tp_name; Q_ASSERT(false);}; ++ break; ++ } ++#endif ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ case NamedExpr_kind: { ++ AssignmentExpressionAst* v = new AssignmentExpressionAst(parent()); ++ nodeStack.push(v); v->target = static_cast(visitNode(node->v.NamedExpr.target)); nodeStack.pop(); ++ nodeStack.push(v); v->value = static_cast(visitNode(node->v.NamedExpr.value)); nodeStack.pop(); ++ result = v; ++ break; ++ } ++#endif + default: + qWarning() << "Unsupported _expr AST type: " << node->kind; + Q_ASSERT(false); +diff --git ./parser/python36.sdef ./parser/python36.sdef +deleted file mode 100644 +index f53ff1c..0000000 +--- ./parser/python36.sdef ++++ /dev/null +@@ -1,102 +0,0 @@ +-COMMENT;This file specifies rules for a conversion of a python (C) to a plugin-internal (C++) syntax tree;; +-COMMENT;All lines are terminated by a double semicolon token, newlines are ignored.;; +-COMMENT;-> stands for "convert AST", => for "convert AST list", ~> for "make an identifier", :> is an assignment w/o conversion, and *> is an enum cast.;; +-COMMENT;$> is a string assignment, +> is a "mindless assignment, like, it just does v->arg = node->arg. +-COMMENT;_> is a Singleton Assignment (converts Py_True, Py_False, Py_None to enum) +-COMMENT;the CODE statement can be used to add custom code.;; +- +- +-RULE_FOR _stmt;KIND Expr_kind;ACTIONS create|ExpressionAst set|value->ExpressionAst,value;; +-RULE_FOR _stmt;KIND FunctionDef_kind;ACTIONS create|FunctionDefinitionAst set|name~>name set|arguments->ArgumentsAst,args +- set|body=>Ast,body set|decorators=>ExpressionAst,decorator_list set|returns->ExpressionAst,returns;; +-RULE_FOR _stmt;KIND AsyncFunctionDef_kind;ACTIONS create|FunctionDefinitionAst set|name~>name set|arguments->ArgumentsAst,args +- set|body=>Ast,body set|decorators=>ExpressionAst,decorator_list set|returns->ExpressionAst,returns;SINCE 3.5;CODE v->async = true;; +-RULE_FOR _stmt;KIND ClassDef_kind;ACTIONS create|ClassDefinitionAst set|name~>name set|baseClasses=>ExpressionAst,bases set|body=>Ast,body +- set|decorators=>ExpressionAst,decorator_list;; +-RULE_FOR _stmt;KIND Return_kind;ACTIONS create|ReturnAst set|value->ExpressionAst,value;; +-RULE_FOR _stmt;KIND Delete_kind;ACTIONS create|DeleteAst set|targets=>ExpressionAst,targets;; +-RULE_FOR _stmt;KIND Assign_kind;ACTIONS create|AssignmentAst set|targets=>ExpressionAst,targets set|value->ExpressionAst,value;; +-RULE_FOR _stmt;KIND AugAssign_kind;ACTIONS create|AugmentedAssignmentAst set|target->ExpressionAst,target set|op*>OperatorTypes,op set|value->ExpressionAst,value;; +-RULE_FOR _stmt;KIND AnnAssign_kind;ACTIONS create|AnnotationAssignmentAst set|target->ExpressionAst,target set|annotation->ExpressionAst,annotation set|value->ExpressionAst,value;SINCE 3.6;; +-RULE_FOR _stmt;KIND For_kind;ACTIONS create|ForAst set|target->ExpressionAst,target set|iterator->ExpressionAst,iter set|body=>Ast,body set|orelse=>Ast,orelse;; +-RULE_FOR _stmt;KIND AsyncFor_kind;ACTIONS create|ForAst set|target->ExpressionAst,target set|iterator->ExpressionAst,iter set|body=>Ast,body set|orelse=>Ast,orelse;SINCE 3.5;; +-RULE_FOR _stmt;KIND While_kind;ACTIONS create|WhileAst set|condition->ExpressionAst,test set|body=>Ast,body set|orelse=>Ast,orelse;; +-RULE_FOR _stmt;KIND If_kind;ACTIONS create|IfAst set|condition->ExpressionAst,test set|body=>Ast,body set|orelse=>Ast,orelse;; +-RULE_FOR _stmt;KIND With_kind;ACTIONS create|WithAst set|body=>Ast,body set|items=>WithItemAst,items;; +-RULE_FOR _stmt;KIND AsyncWith_kind;ACTIONS create|WithAst set|body=>Ast,body set|items=>WithItemAst,items;SINCE 3.5;; +- +-COMMENT;FIXME: the struct Raise has changed, so the following line is likely wrong;; +-RULE_FOR _stmt;KIND Raise_kind;ACTIONS create|RaiseAst set|type->ExpressionAst,exc;; +-RULE_FOR _stmt;KIND Try_kind;ACTIONS create|TryAst set|body=>Ast,body set|handlers=>ExceptionHandlerAst,handlers set|orelse=>Ast,orelse set|finally=>Ast,finalbody;; +-RULE_FOR _stmt;KIND Assert_kind;ACTIONS create|AssertionAst set|condition->ExpressionAst,test set|message->ExpressionAst,msg;; +-RULE_FOR _stmt;KIND Import_kind;ACTIONS create|ImportAst set|names=>AliasAst,names;; +-RULE_FOR _stmt;KIND ImportFrom_kind;ACTIONS create|ImportFromAst set|module~>module set|names=>AliasAst,names set|level:>level;; +-RULE_FOR _stmt;KIND Global_kind;ACTIONS create|GlobalAst set|names=>Identifier,names;; +-RULE_FOR _stmt;KIND Break_kind;ACTIONS create|BreakAst;; +-RULE_FOR _stmt;KIND Continue_kind;ACTIONS create|ContinueAst;; +-RULE_FOR _stmt;KIND Pass_kind;ACTIONS create|PassAst;; +-RULE_FOR _stmt;KIND Nonlocal_kind;ACTIONS create|NonlocalAst;; +- +-RULE_FOR _expr;KIND Await_kind;ACTIONS create|AwaitAst set|value->ExpressionAst,value;SINCE 3.5;; +-RULE_FOR _expr;KIND BoolOp_kind;ACTIONS create|BooleanOperationAst set|type*>BooleanOperationTypes,op set|values=>ExpressionAst,values;; +-RULE_FOR _expr;KIND BinOp_kind;ACTIONS create|BinaryOperationAst set|type*>OperatorTypes,op set|lhs->ExpressionAst,left set|rhs->ExpressionAst,right;; +-RULE_FOR _expr;KIND UnaryOp_kind;ACTIONS create|UnaryOperationAst set|type*>UnaryOperatorTypes,op set|operand->ExpressionAst,operand;; +-RULE_FOR _expr;KIND Lambda_kind;ACTIONS create|LambdaAst set|arguments->ArgumentsAst,args set|body->ExpressionAst,body;; +-RULE_FOR _expr;KIND IfExp_kind;ACTIONS create|IfExpressionAst set|condition->ExpressionAst,test set|body->ExpressionAst,body set|orelse->ExpressionAst,orelse;; +-RULE_FOR _expr;KIND Dict_kind;ACTIONS create|DictAst set|keys=>ExpressionAst,keys set|values=>ExpressionAst,values;; +-RULE_FOR _expr;KIND Set_kind;ACTIONS create|SetAst set|elements=>ExpressionAst,elts;; +-RULE_FOR _expr;KIND ListComp_kind;ACTIONS create|ListComprehensionAst set|element->ExpressionAst,elt set|generators=>ComprehensionAst,generators;; +-RULE_FOR _expr;KIND SetComp_kind;ACTIONS create|SetComprehensionAst set|element->ExpressionAst,elt set|generators=>ComprehensionAst,generators;; +-RULE_FOR _expr;KIND DictComp_kind;ACTIONS create|DictionaryComprehensionAst set|key->ExpressionAst,key set|value->ExpressionAst,value set|generators=>ComprehensionAst,generators;; +-RULE_FOR _expr;KIND GeneratorExp_kind;ACTIONS create|GeneratorExpressionAst set|element->ExpressionAst,elt set|generators=>ComprehensionAst,generators;; +-RULE_FOR _expr;KIND Yield_kind;ACTIONS create|YieldAst set|value->ExpressionAst,value;; +-RULE_FOR _expr;KIND Compare_kind;ACTIONS create|CompareAst set|leftmostElement->ExpressionAst,left set|operators#>ComparisonOperatorTypes,ops set|comparands=>ExpressionAst,comparators;; +-RULE_FOR _expr;KIND Call_kind;ACTIONS create|CallAst set|function->ExpressionAst,func set|arguments=>ExpressionAst,args set|keywords=>KeywordAst,keywords;SINCE 3.5;; +-RULE_FOR _expr;KIND Call_kind;ACTIONS create|CallAst set|function->ExpressionAst,func set|arguments=>ExpressionAst,args set|keywords=>KeywordAst,keywords;BEFORE 3.5; +-CODE /* Convert 3.4 unpacked-args AST to match the new format from 3.5+ */ +-if (node->v.Call.starargs) { +- nodeStack.push(v); +- auto starred = new StarredAst(v); +- starred->context = ExpressionAst::Context::Load; +- nodeStack.push(starred); +- starred->value = static_cast(visitNode(node->v.Call.starargs)); +- nodeStack.pop(); +- v->arguments.append(starred); +- nodeStack.pop(); +-}; +-if (node->v.Call.kwargs) { +- nodeStack.push(v); +- auto kwargs = new KeywordAst(v); +- nodeStack.push(kwargs); +- kwargs->value = static_cast(visitNode(node->v.Call.kwargs)); +- nodeStack.pop(); +- v->keywords.append(kwargs); +- nodeStack.pop(); +-};; +-RULE_FOR _expr;KIND Num_kind;ACTIONS create|NumberAst;CODE v->isInt = PyLong_Check(node->v.Num.n); v->value = PyLong_AsLong(node->v.Num.n);; +-RULE_FOR _expr;KIND Str_kind;ACTIONS create|StringAst set|value$>s;; +-RULE_FOR _expr;KIND JoinedStr_kind;ACTIONS create|JoinedStringAst set|values=>ExpressionAst,values;SINCE 3.6;; +-RULE_FOR _expr;KIND FormattedValue_kind;ACTIONS create|FormattedValueAst set|value->ExpressionAst,value set|conversion:>conversion set|formatSpec->ExpressionAst,format_spec;SINCE 3.6;; +-RULE_FOR _expr;KIND Bytes_kind;ACTIONS create|BytesAst set|value$>s;; +-RULE_FOR _expr;KIND Attribute_kind;ACTIONS create|AttributeAst set|attribute~>attr set|value->ExpressionAst,value set|context*>Context,ctx;; +-RULE_FOR _expr;KIND Subscript_kind;ACTIONS create|SubscriptAst set|value->ExpressionAst,value set|slice->SliceAst,slice set|context*>Context,ctx;; +-RULE_FOR _expr;KIND Starred_kind;ACTIONS create|StarredAst set|value->ExpressionAst,value set|context*>Context,ctx;; +-RULE_FOR _expr;KIND Name_kind;ACTIONS create|NameAst set|identifier~>id set|context*>Context,ctx;; +-RULE_FOR _expr;KIND List_kind;ACTIONS create|ListAst set|elements=>ExpressionAst,elts set|context*>Context,ctx;; +-RULE_FOR _expr;KIND Tuple_kind;ACTIONS create|TupleAst set|elements=>ExpressionAst,elts set|context*>Context,ctx;; +-RULE_FOR _expr;KIND Ellipsis_kind;ACTIONS create|EllipsisAst;; +-RULE_FOR _expr;KIND NameConstant_kind;ACTIONS create|NameConstantAst set|value_>value;; +-RULE_FOR _expr;KIND YieldFrom_kind;ACTIONS create|YieldFromAst set|value->ExpressionAst,value;; +- +-RULE_FOR _slice;KIND Slice_kind;ACTIONS create|SliceAst set|lower->ExpressionAst,lower set|upper->ExpressionAst,upper set|step->ExpressionAst,step;; +-RULE_FOR _slice;KIND ExtSlice_kind;ACTIONS create|ExtendedSliceAst set|dims=>SliceAst,dims;; +-RULE_FOR _slice;KIND Index_kind;ACTIONS create|IndexAst set|value->ExpressionAst,value;; +- +- +-RULE_FOR _comprehension;KIND any;ACTIONS create|ComprehensionAst set|target->ExpressionAst,target set|iterator->ExpressionAst,iter set|conditions=>ExpressionAst,ifs;; +-RULE_FOR _excepthandler;KIND ExceptHandler_kind;ACTIONS create|ExceptionHandlerAst set|type->ExpressionAst,type set|name~>name set|body=>Ast,body;; +-RULE_FOR _arguments;KIND any;ACTIONS create|ArgumentsAst set|vararg->ArgAst,vararg set|kwarg->ArgAst,kwarg set|arguments=>ArgAst,args set|defaultValues=>ExpressionAst,defaults set|kwonlyargs=>ArgAst,kwonlyargs;; +-RULE_FOR _arg;KIND any;ACTIONS create|ArgAst set|argumentName~>arg set|annotation->ExpressionAst,annotation;; +-RULE_FOR _keyword;KIND any;ACTIONS create|KeywordAst set|argumentName~>arg set|value->ExpressionAst,value;; +-RULE_FOR _alias;KIND any;ACTIONS create|AliasAst set|name~>name set|asName~>asname;; +-RULE_FOR _withitem;KIND any; ACTIONS create|WithItemAst set|contextExpression->ExpressionAst,context_expr set|optionalVars->ExpressionAst,optional_vars;; +diff --git ./parser/python38.sdef ./parser/python38.sdef +new file mode 100644 +index 0000000..30d9f95 +--- /dev/null ++++ ./parser/python38.sdef +@@ -0,0 +1,145 @@ ++COMMENT;This file specifies rules for a conversion of a python (C) to a plugin-internal (C++) syntax tree;; ++COMMENT;All lines are terminated by a double semicolon token, newlines are ignored.;; ++COMMENT;-> stands for "convert AST", => for "convert AST list", ~> for "make an identifier", :> is an assignment w/o conversion, and *> is an enum cast.;; ++COMMENT;$> is a string assignment, +> is a "mindless assignment, like, it just does v->arg = node->arg. ++COMMENT;_> is a Singleton Assignment (converts Py_True, Py_False, Py_None to enum) ++COMMENT;the CODE statement can be used to add custom code.;; ++ ++ ++RULE_FOR _stmt;KIND Expr_kind;ACTIONS create|ExpressionAst set|value->ExpressionAst,value;; ++RULE_FOR _stmt;KIND FunctionDef_kind;ACTIONS create|FunctionDefinitionAst set|name~>name set|arguments->ArgumentsAst,args ++ set|body=>Ast,body set|decorators=>ExpressionAst,decorator_list set|returns->ExpressionAst,returns;; ++RULE_FOR _stmt;KIND AsyncFunctionDef_kind;ACTIONS create|FunctionDefinitionAst set|name~>name set|arguments->ArgumentsAst,args ++ set|body=>Ast,body set|decorators=>ExpressionAst,decorator_list set|returns->ExpressionAst,returns;SINCE 3.5;CODE v->async = true;; ++RULE_FOR _stmt;KIND ClassDef_kind;ACTIONS create|ClassDefinitionAst set|name~>name set|baseClasses=>ExpressionAst,bases set|body=>Ast,body ++ set|decorators=>ExpressionAst,decorator_list;; ++RULE_FOR _stmt;KIND Return_kind;ACTIONS create|ReturnAst set|value->ExpressionAst,value;; ++RULE_FOR _stmt;KIND Delete_kind;ACTIONS create|DeleteAst set|targets=>ExpressionAst,targets;; ++RULE_FOR _stmt;KIND Assign_kind;ACTIONS create|AssignmentAst set|targets=>ExpressionAst,targets set|value->ExpressionAst,value;; ++RULE_FOR _stmt;KIND AugAssign_kind;ACTIONS create|AugmentedAssignmentAst set|target->ExpressionAst,target set|op*>OperatorTypes,op set|value->ExpressionAst,value;; ++RULE_FOR _stmt;KIND AnnAssign_kind;ACTIONS create|AnnotationAssignmentAst set|target->ExpressionAst,target set|annotation->ExpressionAst,annotation set|value->ExpressionAst,value;SINCE 3.6;; ++RULE_FOR _stmt;KIND For_kind;ACTIONS create|ForAst set|target->ExpressionAst,target set|iterator->ExpressionAst,iter set|body=>Ast,body set|orelse=>Ast,orelse;; ++RULE_FOR _stmt;KIND AsyncFor_kind;ACTIONS create|ForAst set|target->ExpressionAst,target set|iterator->ExpressionAst,iter set|body=>Ast,body set|orelse=>Ast,orelse;SINCE 3.5;; ++RULE_FOR _stmt;KIND While_kind;ACTIONS create|WhileAst set|condition->ExpressionAst,test set|body=>Ast,body set|orelse=>Ast,orelse;; ++RULE_FOR _stmt;KIND If_kind;ACTIONS create|IfAst set|condition->ExpressionAst,test set|body=>Ast,body set|orelse=>Ast,orelse;; ++RULE_FOR _stmt;KIND With_kind;ACTIONS create|WithAst set|body=>Ast,body set|items=>WithItemAst,items;; ++RULE_FOR _stmt;KIND AsyncWith_kind;ACTIONS create|WithAst set|body=>Ast,body set|items=>WithItemAst,items;SINCE 3.5;; ++ ++COMMENT;FIXME: the struct Raise has changed, so the following line is likely wrong;; ++RULE_FOR _stmt;KIND Raise_kind;ACTIONS create|RaiseAst set|type->ExpressionAst,exc;; ++RULE_FOR _stmt;KIND Try_kind;ACTIONS create|TryAst set|body=>Ast,body set|handlers=>ExceptionHandlerAst,handlers set|orelse=>Ast,orelse set|finally=>Ast,finalbody;; ++RULE_FOR _stmt;KIND Assert_kind;ACTIONS create|AssertionAst set|condition->ExpressionAst,test set|message->ExpressionAst,msg;; ++RULE_FOR _stmt;KIND Import_kind;ACTIONS create|ImportAst set|names=>AliasAst,names;; ++RULE_FOR _stmt;KIND ImportFrom_kind;ACTIONS create|ImportFromAst set|module~>module set|names=>AliasAst,names set|level:>level;; ++RULE_FOR _stmt;KIND Global_kind;ACTIONS create|GlobalAst set|names=>Identifier,names;; ++RULE_FOR _stmt;KIND Break_kind;ACTIONS create|BreakAst;; ++RULE_FOR _stmt;KIND Continue_kind;ACTIONS create|ContinueAst;; ++RULE_FOR _stmt;KIND Pass_kind;ACTIONS create|PassAst;; ++RULE_FOR _stmt;KIND Nonlocal_kind;ACTIONS create|NonlocalAst;; ++ ++RULE_FOR _expr;KIND Await_kind;ACTIONS create|AwaitAst set|value->ExpressionAst,value;SINCE 3.5;; ++RULE_FOR _expr;KIND BoolOp_kind;ACTIONS create|BooleanOperationAst set|type*>BooleanOperationTypes,op set|values=>ExpressionAst,values;; ++RULE_FOR _expr;KIND BinOp_kind;ACTIONS create|BinaryOperationAst set|type*>OperatorTypes,op set|lhs->ExpressionAst,left set|rhs->ExpressionAst,right;; ++RULE_FOR _expr;KIND UnaryOp_kind;ACTIONS create|UnaryOperationAst set|type*>UnaryOperatorTypes,op set|operand->ExpressionAst,operand;; ++RULE_FOR _expr;KIND Lambda_kind;ACTIONS create|LambdaAst set|arguments->ArgumentsAst,args set|body->ExpressionAst,body;; ++RULE_FOR _expr;KIND IfExp_kind;ACTIONS create|IfExpressionAst set|condition->ExpressionAst,test set|body->ExpressionAst,body set|orelse->ExpressionAst,orelse;; ++RULE_FOR _expr;KIND Dict_kind;ACTIONS create|DictAst set|keys=>ExpressionAst,keys set|values=>ExpressionAst,values;; ++RULE_FOR _expr;KIND Set_kind;ACTIONS create|SetAst set|elements=>ExpressionAst,elts;; ++RULE_FOR _expr;KIND ListComp_kind;ACTIONS create|ListComprehensionAst set|element->ExpressionAst,elt set|generators=>ComprehensionAst,generators;; ++RULE_FOR _expr;KIND SetComp_kind;ACTIONS create|SetComprehensionAst set|element->ExpressionAst,elt set|generators=>ComprehensionAst,generators;; ++RULE_FOR _expr;KIND DictComp_kind;ACTIONS create|DictionaryComprehensionAst set|key->ExpressionAst,key set|value->ExpressionAst,value set|generators=>ComprehensionAst,generators;; ++RULE_FOR _expr;KIND GeneratorExp_kind;ACTIONS create|GeneratorExpressionAst set|element->ExpressionAst,elt set|generators=>ComprehensionAst,generators;; ++RULE_FOR _expr;KIND Yield_kind;ACTIONS create|YieldAst set|value->ExpressionAst,value;; ++RULE_FOR _expr;KIND Compare_kind;ACTIONS create|CompareAst set|leftmostElement->ExpressionAst,left set|operators#>ComparisonOperatorTypes,ops set|comparands=>ExpressionAst,comparators;; ++RULE_FOR _expr;KIND Call_kind;ACTIONS create|CallAst set|function->ExpressionAst,func set|arguments=>ExpressionAst,args set|keywords=>KeywordAst,keywords;SINCE 3.5;; ++RULE_FOR _expr;KIND Call_kind;ACTIONS create|CallAst set|function->ExpressionAst,func set|arguments=>ExpressionAst,args set|keywords=>KeywordAst,keywords;BEFORE 3.5; ++CODE /* Convert 3.4 unpacked-args AST to match the new format from 3.5+ */ ++if (node->v.Call.starargs) { ++ nodeStack.push(v); ++ auto starred = new StarredAst(v); ++ starred->context = ExpressionAst::Context::Load; ++ nodeStack.push(starred); ++ starred->value = static_cast(visitNode(node->v.Call.starargs)); ++ nodeStack.pop(); ++ v->arguments.append(starred); ++ nodeStack.pop(); ++}; ++if (node->v.Call.kwargs) { ++ nodeStack.push(v); ++ auto kwargs = new KeywordAst(v); ++ nodeStack.push(kwargs); ++ kwargs->value = static_cast(visitNode(node->v.Call.kwargs)); ++ nodeStack.pop(); ++ v->keywords.append(kwargs); ++ nodeStack.pop(); ++};; ++RULE_FOR _expr;KIND Num_kind;ACTIONS create|NumberAst;BEFORE 3.8;CODE v->isInt = PyLong_Check(node->v.Num.n); v->value = PyLong_AsLong(node->v.Num.n);; ++RULE_FOR _expr;KIND Str_kind;ACTIONS create|StringAst set|value$>s;BEFORE 3.8;; ++RULE_FOR _expr;KIND JoinedStr_kind;ACTIONS create|JoinedStringAst set|values=>ExpressionAst,values;SINCE 3.6;; ++RULE_FOR _expr;KIND FormattedValue_kind;ACTIONS create|FormattedValueAst set|value->ExpressionAst,value set|conversion:>conversion set|formatSpec->ExpressionAst,format_spec;SINCE 3.6;; ++RULE_FOR _expr;KIND Bytes_kind;ACTIONS create|BytesAst set|value$>s;BEFORE 3.8;; ++RULE_FOR _expr;KIND Attribute_kind;ACTIONS create|AttributeAst set|attribute~>attr set|value->ExpressionAst,value set|context*>Context,ctx;; ++RULE_FOR _expr;KIND Subscript_kind;ACTIONS create|SubscriptAst set|value->ExpressionAst,value set|slice->SliceAst,slice set|context*>Context,ctx;; ++RULE_FOR _expr;KIND Starred_kind;ACTIONS create|StarredAst set|value->ExpressionAst,value set|context*>Context,ctx;; ++RULE_FOR _expr;KIND Name_kind;ACTIONS create|NameAst set|identifier~>id set|context*>Context,ctx;; ++RULE_FOR _expr;KIND List_kind;ACTIONS create|ListAst set|elements=>ExpressionAst,elts set|context*>Context,ctx;; ++RULE_FOR _expr;KIND Tuple_kind;ACTIONS create|TupleAst set|elements=>ExpressionAst,elts set|context*>Context,ctx;; ++RULE_FOR _expr;KIND Ellipsis_kind;ACTIONS create|EllipsisAst;BEFORE 3.8;; ++RULE_FOR _expr;KIND NameConstant_kind;ACTIONS create|NameConstantAst set|value_>value;BEFORE 3.8;; ++RULE_FOR _expr;KIND YieldFrom_kind;ACTIONS create|YieldFromAst set|value->ExpressionAst,value;; ++RULE_FOR _expr;KIND Constant_kind;ACTIONS;SINCE 3.8;CODE ++PyObject *value = node->v.Constant.value; ++if (value == Py_None) { ++ NameConstantAst* v = new NameConstantAst(parent()); ++ v->value = NameConstantAst::None; ++ result = v; ++} ++else if (value == Py_True) { ++ NameConstantAst* v = new NameConstantAst(parent()); ++ v->value = NameConstantAst::True; ++ result = v; ++} ++else if (value == Py_False) { ++ NameConstantAst* v = new NameConstantAst(parent()); ++ v->value = NameConstantAst::False; ++ result = v; ++} ++else if (value->ob_type == &PyLong_Type) { ++ NumberAst* v = new NumberAst(parent()); ++ v->isInt = true; ++ v->value = PyLong_AsLong(value); ++ result = v; ++} ++else if (value->ob_type == &PyFloat_Type || value->ob_type == &PyComplex_Type) { ++ result = new NumberAst(parent()); ++} ++else if (value->ob_type == &PyUnicode_Type) { ++ StringAst* v = new StringAst(parent()); ++ v->value = PyUnicodeObjectToQString(value); ++ result = v; ++} ++else if (value->ob_type == &PyBytes_Type) { ++ result = new BytesAst(parent()); ++} ++else if (value->ob_type == &PyEllipsis_Type) { ++ result = new EllipsisAst(parent()); ++} ++else { ++ qWarning() << "Unhandled constant type: " << value->ob_type->tp_name; ++ Q_ASSERT(false); ++};; ++RULE_FOR _expr;KIND NamedExpr_kind;ACTIONS create|AssignmentExpressionAst set|target->ExpressionAst,target set|value->ExpressionAst,value;SINCE 3.8;; ++ ++RULE_FOR _slice;KIND Slice_kind;ACTIONS create|SliceAst set|lower->ExpressionAst,lower set|upper->ExpressionAst,upper set|step->ExpressionAst,step;; ++RULE_FOR _slice;KIND ExtSlice_kind;ACTIONS create|ExtendedSliceAst set|dims=>SliceAst,dims;; ++RULE_FOR _slice;KIND Index_kind;ACTIONS create|IndexAst set|value->ExpressionAst,value;; ++ ++ ++RULE_FOR _comprehension;KIND any;ACTIONS create|ComprehensionAst set|target->ExpressionAst,target set|iterator->ExpressionAst,iter set|conditions=>ExpressionAst,ifs;; ++RULE_FOR _excepthandler;KIND ExceptHandler_kind;ACTIONS create|ExceptionHandlerAst set|type->ExpressionAst,type set|name~>name set|body=>Ast,body;; ++RULE_FOR _arguments;KIND any;ACTIONS create|ArgumentsAst set|vararg->ArgAst,vararg set|kwarg->ArgAst,kwarg set|arguments=>ArgAst,args set|defaultValues=>ExpressionAst,defaults set|kwonlyargs=>ArgAst,kwonlyargs;BEFORE 3.8;; ++RULE_FOR _arguments;KIND any;ACTIONS create|ArgumentsAst set|vararg->ArgAst,vararg set|kwarg->ArgAst,kwarg set|arguments=>ArgAst,args set|defaultValues=>ExpressionAst,defaults set|kwonlyargs=>ArgAst,kwonlyargs set|posonlyargs=>ArgAst,posonlyargs;SINCE 3.8;; ++RULE_FOR _arg;KIND any;ACTIONS create|ArgAst set|argumentName~>arg set|annotation->ExpressionAst,annotation;; ++RULE_FOR _keyword;KIND any;ACTIONS create|KeywordAst set|argumentName~>arg set|value->ExpressionAst,value;; ++RULE_FOR _alias;KIND any;ACTIONS create|AliasAst set|name~>name set|asName~>asname;; ++RULE_FOR _withitem;KIND any; ACTIONS create|WithItemAst set|contextExpression->ExpressionAst,context_expr set|optionalVars->ExpressionAst,optional_vars;; +diff --git ./parser/tests/pyasttest.cpp ./parser/tests/pyasttest.cpp +index 4fd5f4e..c28f6fc 100644 +--- ./parser/tests/pyasttest.cpp ++++ ./parser/tests/pyasttest.cpp +@@ -238,6 +238,11 @@ void PyAstTest::testExpressions_data() + " **{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions},\n" + "}"; + #endif ++#if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0) ++ QTest::newRow("assignment_expr_1") << "a = (b := 10)"; ++ QTest::newRow("assignment_expr_2") << "a = [q for z in (1, 2, 3) if (q := 2*z)]"; ++ QTest::newRow("positional_params") << "def foo(a, b, /, c, d, *, e): pass"; ++#endif + } + + void PyAstTest::testCorrectedFuncRanges() +-- +cgit v1.1 +