File indexing completed on 2024-05-19 15:42:35

0001 #include "asttransformer.h"
0002 #include "astbuilder.h"
0003 
0004 namespace Python
0005 {
0006 
0007 template <>
0008 QString AstTransformer::getattr(PyObject *obj, const char *attr) const
0009 {
0010     PyObject *v = PyObject_GetAttrString(obj, attr);
0011     // qDebug() << "getattr<str>: " << PyUnicodeObjectToQString(PyObject_Str(obj)) << "." << attr << "v=" << PyUnicodeObjectToQString(PyObject_Str(v));
0012     Q_ASSERT(v); // attr missing
0013     if (PyUnicode_Check(v))
0014         return PyUnicodeObjectToQString(v);
0015     Py_XDECREF(v);
0016     return "";
0017 }
0018 
0019 template <>
0020 bool AstTransformer::getattr(PyObject *obj, const char *attr) const
0021 {
0022     PyObject *v = PyObject_GetAttrString(obj, attr);
0023     // qDebug() << "getattr<bool>: " << PyUnicodeObjectToQString(PyObject_Str(obj)) << "." << attr;
0024     Q_ASSERT(v); // attr missing
0025     bool r = PyObject_IsTrue(v) == 1;
0026     Py_XDECREF(v);
0027     return r;
0028 }
0029 
0030 template <>
0031 int AstTransformer::getattr(PyObject *obj, const char *attr) const
0032 {
0033     int result;
0034     PyObject *v = PyObject_GetAttrString(obj, attr);
0035     // qDebug() << "getattr<int>: " << PyUnicodeObjectToQString(PyObject_Str(obj)) << "." << attr << "v=" << PyUnicodeObjectToQString(PyObject_Str(v));
0036     if (v && PyLong_Check(v)) {
0037         result = PyLong_AsLong(v);
0038     } else {
0039         result = 0;
0040     }
0041     Py_XDECREF(v);
0042     return result;
0043 }
0044 
0045 
0046 template <>
0047 PyObject* AstTransformer::getattr(PyObject *obj, const char *attr) const
0048 {
0049     // qDebug() << "getattr<obj>: " << PyUnicodeObjectToQString(PyObject_Str(obj)) << "." << attr;;
0050     PyObject* v = PyObject_GetAttrString(obj, attr);
0051     Q_ASSERT(v); // attr missing
0052     return v;
0053 }
0054 
0055 template <>
0056 PyObjectRef AstTransformer::getattr(PyObject *obj, const char *attr) const
0057 {
0058     return getattr<PyObject*>(obj, attr);
0059 }
0060 
0061 template <>
0062 ExpressionAst::Context AstTransformer::getattr(PyObject *obj, const char *attr) const
0063 {
0064     ExpressionAst::Context result;
0065     PyObject *v = PyObject_GetAttrString(obj, attr);
0066     // qDebug() << "getattr<expr:ctx>: " << PyUnicodeObjectToQString(PyObject_Str(obj)) << "." << attr<< "ctx: " << PyUnicodeObjectToQString(PyObject_Str(v));
0067     Q_ASSERT(v); // attr missing
0068     if (PyObject_IsInstance(v, grammar.ast_Load))
0069         result = ExpressionAst::Context::Load;
0070     else if (PyObject_IsInstance(v, grammar.ast_Store))
0071         result = ExpressionAst::Context::Store;
0072     else if (PyObject_IsInstance(v, grammar.ast_Delete))
0073         result = ExpressionAst::Context::Delete;
0074     else
0075         result = ExpressionAst::Context::Invalid;
0076     Py_XDECREF(v);
0077     return result;
0078 }
0079 
0080 template <>
0081 Ast::OperatorTypes  AstTransformer::getattr(PyObject *obj, const char *attr) const
0082 {
0083     Ast::OperatorTypes result;
0084     PyObject *op = PyObject_GetAttrString(obj, attr);
0085     // qDebug() << "getattr<expr:ctx>: " << PyUnicodeObjectToQString(PyObject_Str(obj)) << "." << attr<< "op: " << PyUnicodeObjectToQString(PyObject_Str(op));
0086     Q_ASSERT(op); // attr missing
0087     if (PyObject_IsInstance(op, grammar.ast_Add))
0088         result = Ast::OperatorAdd;
0089     else if (PyObject_IsInstance(op, grammar.ast_BitAnd))
0090         result = Ast::OperatorBitwiseAnd;
0091     else if (PyObject_IsInstance(op, grammar.ast_BitOr))
0092         result = Ast::OperatorBitwiseOr;
0093     else if (PyObject_IsInstance(op, grammar.ast_BitXor))
0094         result = Ast::OperatorBitwiseXor;
0095     else if (PyObject_IsInstance(op, grammar.ast_Div))
0096         result = Ast::OperatorDiv;
0097     else if (PyObject_IsInstance(op, grammar.ast_FloorDiv))
0098         result = Ast::OperatorFloorDivision;
0099     else if (PyObject_IsInstance(op, grammar.ast_LShift))
0100         result = Ast::OperatorLeftShift;
0101     else if (PyObject_IsInstance(op, grammar.ast_Mod))
0102         result = Ast::OperatorMod;
0103     else if (PyObject_IsInstance(op, grammar.ast_Mult))
0104         result = Ast::OperatorMult;
0105     else if (PyObject_IsInstance(op, grammar.ast_MatMult))
0106         result = Ast::OperatorMatMult;
0107     else if (PyObject_IsInstance(op, grammar.ast_Pow))
0108         result = Ast::OperatorPow;
0109     else if (PyObject_IsInstance(op, grammar.ast_RShift))
0110         result = Ast::OperatorRightShift;
0111     else if (PyObject_IsInstance(op, grammar.ast_Sub))
0112         result = Ast::OperatorSub;
0113     else
0114         result = Ast::OperatorInvalid;
0115     Py_XDECREF(op);
0116     return result;
0117 }
0118 
0119 Ast* AstTransformer::visitModuleNode(PyObject* node, Ast* parent)
0120 {
0121     Q_UNUSED(parent);
0122     if (!PyObject_IsInstance(node, grammar.ast_Module)) return nullptr;
0123     CodeAst* ast = new CodeAst();
0124     {
0125         // qDebug() << "Visit module: " << PyUnicodeObjectToQString(PyObject_Str(node));
0126         PyObjectRef body = getattr<PyObjectRef>(node, "body");
0127         ast->body = visitNodeList<Ast>(body, ast);
0128     }
0129     return ast;
0130 }
0131 
0132 template<typename K>
0133 QList<K*> AstTransformer::visitNodeList(PyObject* node, Ast* parent)
0134 {
0135     // qDebug() << "visit list: " << PyUnicodeObjectToQString(PyObject_Str(node));
0136     QList<K*> nodelist;
0137     Q_ASSERT(PyList_Check(node));
0138     for ( int i=0; i < PyList_Size(node); i++ )
0139     {
0140         PyObject* currentNode = PyList_GetItem(node, i);
0141         Ast* result = visitNode(currentNode, parent);
0142         K* transformedNode = static_cast<K*>(result);
0143         nodelist.append(transformedNode);
0144     }
0145     // qDebug() << "  size: " << nodelist.size();
0146     return nodelist;
0147 }
0148 
0149 Ast* AstTransformer::visitNode(PyObject* node, Ast* parent)
0150 {
0151     if ( ! node || node == Py_None ) return nullptr;
0152     // qDebug() << "visit node: " << PyUnicodeObjectToQString(PyObject_Str(node));
0153 
0154     if (PyObject_IsInstance(node, grammar.ast_expr))
0155         return visitExprNode(node, parent);
0156     if (PyObject_IsInstance(node, grammar.ast_stmt))
0157         return visitStmtNode(node, parent);
0158     if (PyObject_IsInstance(node, grammar.ast_arg))
0159         return visitArgNode(node, parent);
0160     if (PyObject_IsInstance(node, grammar.ast_comprehension))
0161         return visitComprehensionNode(node, parent);
0162     if (PyObject_IsInstance(node, grammar.ast_arguments))
0163         return visitArgumentsNode(node, parent);
0164     if (PyObject_IsInstance(node, grammar.ast_keyword))
0165         return visitKeywordNode(node, parent);
0166     if (PyObject_IsInstance(node, grammar.ast_alias))
0167         return visitAliasNode(node, parent);
0168     if (PyObject_IsInstance(node, grammar.ast_withitem))
0169         return visitWithItemNode(node, parent);
0170     if (PyObject_IsInstance(node, grammar.ast_excepthandler))
0171         return visitExceptHandlerNode(node, parent);
0172     if (PyObject_IsInstance(node, grammar.ast_slice))
0173         return visitSliceNode(node, parent);
0174 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
0175     if (PyObject_IsInstance(node, grammar.ast_match_case))
0176         return visitMatchCaseNode(node, parent);
0177     if (PyObject_IsInstance(node, grammar.ast_pattern))
0178         return visitPatternNode(node, parent);
0179 #endif
0180     if (PyObject_IsInstance(node, grammar.ast_mod))
0181         return visitModuleNode(node, parent);
0182     qWarning() << "Unsupported AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
0183     Q_UNREACHABLE();
0184 }
0185 
0186 Ast* AstTransformer::visitAliasNode(PyObject* node, Ast* parent)
0187 {
0188     if (!node) return nullptr;
0189     // qDebug() << "visit alias: " << PyUnicodeObjectToQString(PyObject_Str(node));
0190     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_alias));
0191     AliasAst* v = new  AliasAst(parent);
0192     v->name = new Python::Identifier(getattr<QString>(node, "name"));
0193     v->name->startLine = tline(getattr<int>(node, "lineno"));
0194     v->name->startCol = getattr<int>(node, "col_offset");
0195     v->name->endCol = v->name->startCol + v->name->value.size() - 1;
0196     v->name->endLine = v->name->startLine;
0197     v->startLine = v->name->startLine;;
0198     v->startCol = v->name->startCol;
0199     v->endCol = v->name->endCol;
0200     v->endLine = v->name->endLine;
0201     QString asname = getattr<QString>(node, "asname");
0202     v->asName = asname.size() ? new Python::Identifier(asname) : nullptr;
0203     return v;
0204 }
0205 
0206 
0207 Ast* AstTransformer::visitArgNode(PyObject* node, Ast* parent)
0208 {
0209     if (!node || node == Py_None) return nullptr;
0210     // qDebug() << "visit arg: " << PyUnicodeObjectToQString(PyObject_Str(node));
0211     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_arg));
0212     ArgAst* v = new  ArgAst(parent);
0213     QString arg = getattr<QString>(node, "arg");
0214     if (arg.size()) {
0215         v->argumentName = new Python::Identifier(arg);
0216         v->argumentName->startCol = getattr<int>(node, "col_offset");
0217         v->argumentName->startLine = tline(getattr<int>(node, "lineno"));
0218         v->argumentName->endCol = v->argumentName->startCol + arg.size() - 1;
0219         v->argumentName->endLine = v->argumentName->startLine;
0220 
0221         v->startCol = v->argumentName->startCol;
0222         v->startLine = v->argumentName->startLine;
0223         v->endCol = v->argumentName->endCol;
0224         v->endLine = v->argumentName->endLine;
0225     } else {
0226         v->argumentName = nullptr;
0227     }
0228     {
0229         PyObjectRef annotation = getattr<PyObjectRef>(node, "annotation");
0230         v->annotation = static_cast<ExpressionAst*>(visitExprNode(annotation, v));
0231     }
0232     return v;
0233 }
0234 
0235 Ast* AstTransformer::visitArgumentsNode(PyObject* node, Ast* parent)
0236 {
0237     if (!node || node == Py_None) return nullptr;
0238     // qDebug() << "visit args: " << PyUnicodeObjectToQString(PyObject_Str(node));
0239     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_arguments));
0240     ArgumentsAst* v = new  ArgumentsAst(parent);
0241     {
0242         PyObjectRef vararg = getattr<PyObjectRef>(node, "vararg");
0243         v->vararg = static_cast<ArgAst*>(visitArgNode(vararg, v));
0244     }
0245     {
0246         PyObjectRef kwarg = getattr<PyObjectRef>(node, "kwarg");
0247         v->kwarg = static_cast<ArgAst*>(visitArgNode(kwarg, v));
0248     }
0249     {
0250         PyObjectRef args = getattr<PyObjectRef>(node, "args");
0251         v->arguments = visitNodeList<ArgAst>(args, v);
0252     }
0253 
0254     {
0255         PyObjectRef defaults = getattr<PyObjectRef>(node, "defaults");
0256         v->defaultValues = visitNodeList<ExpressionAst>(defaults, v);
0257     }
0258 
0259     {
0260         PyObjectRef kwonlyargs = getattr<PyObjectRef>(node, "kwonlyargs");
0261         v->kwonlyargs = visitNodeList<ArgAst>(kwonlyargs, v);
0262     }
0263 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0)
0264     {
0265         PyObjectRef posonlyargs = getattr<PyObjectRef>(node, "posonlyargs");
0266         v->posonlyargs = visitNodeList<ArgAst>(posonlyargs, v);
0267     }
0268 #endif
0269     {
0270         PyObjectRef kw_defaults = getattr<PyObjectRef>(node, "kw_defaults");
0271         v->defaultKwValues = visitNodeList<ExpressionAst>(kw_defaults, v);
0272     }
0273 
0274     return v;
0275 }
0276 
0277 Ast* AstTransformer::visitComprehensionNode(PyObject* node, Ast* parent) {
0278     if ( ! node || node == Py_None ) return nullptr;
0279     // qDebug() << "visit comp: " << PyUnicodeObjectToQString(PyObject_Str(node));
0280     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_comprehension));
0281     ComprehensionAst* v = new  ComprehensionAst(parent);
0282     {
0283         PyObjectRef target = getattr<PyObjectRef>(node, "target");
0284         v->target = static_cast<ExpressionAst*>(visitExprNode(target, v));
0285     }
0286     {
0287         PyObjectRef iter = getattr<PyObjectRef>(node, "iter");
0288         v->iterator = static_cast<ExpressionAst*>(visitExprNode(iter, v));
0289     }
0290     {
0291         PyObjectRef ifs = getattr<PyObjectRef>(node, "ifs");
0292         v->conditions = visitNodeList<ExpressionAst>(ifs, v);
0293     }
0294     return v;
0295 }
0296 
0297 Ast* AstTransformer::visitExceptHandlerNode(PyObject* node, Ast* parent)
0298 {
0299     if ( !node || node == Py_None ) return nullptr;
0300     // qDebug() << "visit except hdlr: " << PyUnicodeObjectToQString(PyObject_Str(node));
0301     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_excepthandler));
0302     ExceptionHandlerAst* v = new  ExceptionHandlerAst(parent);
0303     {
0304         PyObjectRef type = getattr<PyObjectRef>(node, "type");
0305         v->type = static_cast<ExpressionAst*>(visitExprNode(type, v));
0306     }
0307     QString name = getattr<QString>(node, "name");
0308     if (name.size())
0309     {
0310         v->name = new Python::Identifier(name);
0311         v->name->startCol = getattr<int>(node, "col_offset");
0312         v->name->startLine = tline(getattr<int>(node, "lineno"));
0313         v->name->endCol = v->name->startCol + name.size() - 1;
0314         v->name->endLine = v->name->startLine;
0315 
0316         v->startCol = v->name->startCol;
0317         v->startLine = v->name->startLine;
0318         v->endCol = v->name->endCol;
0319         v->endLine = v->name->endLine;
0320     } else {
0321         v->name = nullptr;
0322     }
0323 
0324     {
0325         PyObjectRef body = getattr<PyObjectRef>(node, "body");
0326         v->body = visitNodeList<Ast>(body, v);
0327     }
0328     updateRanges(v);
0329     return v;
0330 }
0331 
0332 Ast* AstTransformer::visitExprNode(PyObject* node, Ast* parent)
0333 {
0334     if (!node || node == Py_None) return nullptr;
0335     // qDebug() << "visit expr: " << PyUnicodeObjectToQString(PyObject_Str(node));
0336     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_expr));
0337     Ast* result = nullptr;
0338 
0339     bool ranges_copied = false;
0340 
0341     if (PyObject_IsInstance(node, grammar.ast_Await)) {
0342         AwaitAst* v = new  AwaitAst(parent);
0343         {
0344             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0345             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0346         }
0347         result = v;
0348     }
0349     else if (PyObject_IsInstance(node, grammar.ast_BoolOp)) {
0350         BooleanOperationAst* v = new  BooleanOperationAst(parent);
0351         {
0352             PyObjectRef op = getattr<PyObjectRef>(node, "op");
0353             if (PyObject_IsInstance(op, grammar.ast_And))
0354                 v->type = Ast::BooleanAnd;
0355             else if (PyObject_IsInstance(op, grammar.ast_Or))
0356                 v->type = Ast::BooleanOr;
0357             else
0358                 v->type = Ast::BooleanInvalidOperation;
0359         }
0360         {
0361             PyObjectRef values = getattr<PyObjectRef>(node, "values");
0362             v->values = visitNodeList<ExpressionAst>(values, v);
0363         }
0364         result = v;
0365     }
0366     else if (PyObject_IsInstance(node, grammar.ast_BinOp)) {
0367         BinaryOperationAst* v = new  BinaryOperationAst(parent);
0368         v->type = getattr<Ast::OperatorTypes>(node, "op");
0369         {
0370             PyObjectRef left = getattr<PyObjectRef>(node, "left");
0371             v->lhs = static_cast<ExpressionAst*>(visitExprNode(left, v));
0372         }
0373         {
0374             PyObjectRef right = getattr<PyObjectRef>(node, "right");
0375             v->rhs = static_cast<ExpressionAst*>(visitExprNode(right, v));
0376         }
0377         result = v;
0378     }
0379     else if (PyObject_IsInstance(node, grammar.ast_UnaryOp)) {
0380         UnaryOperationAst* v = new  UnaryOperationAst(parent);
0381         {
0382             PyObjectRef op = getattr<PyObjectRef>(node, "op");
0383             if (PyObject_IsInstance(op, grammar.ast_Invert))
0384                 v->type = Ast::UnaryOperatorInvert;
0385             else if (PyObject_IsInstance(op, grammar.ast_Not))
0386                 v->type = Ast::UnaryOperatorNot;
0387             else if (PyObject_IsInstance(op, grammar.ast_UAdd))
0388                 v->type = Ast::UnaryOperatorAdd;
0389             else if (PyObject_IsInstance(op, grammar.ast_USub))
0390                 v->type = Ast::UnaryOperatorSub;
0391             else
0392                 v->type = Ast::UnaryOperatorInvalid;
0393         }
0394         {
0395             PyObjectRef operand = getattr<PyObjectRef>(node, "operand");
0396             v->operand = static_cast<ExpressionAst*>(visitExprNode(operand, v));
0397         }
0398         result = v;
0399     }
0400     else if (PyObject_IsInstance(node, grammar.ast_Lambda)) {
0401         LambdaAst* v = new  LambdaAst(parent);
0402         {
0403             PyObjectRef args = getattr<PyObjectRef>(node, "args");
0404             v->arguments = static_cast<ArgumentsAst*>(visitArgumentsNode(args, v));
0405         }
0406         {
0407             PyObjectRef body = getattr<PyObjectRef>(node, "body");
0408             v->body = static_cast<ExpressionAst*>(visitExprNode(body, v));
0409         }
0410         result = v;
0411     }
0412     else if (PyObject_IsInstance(node, grammar.ast_IfExp)) {
0413         IfExpressionAst* v = new  IfExpressionAst(parent);
0414         {
0415             PyObjectRef test = getattr<PyObjectRef>(node, "test");
0416             v->condition = static_cast<ExpressionAst*>(visitExprNode(test, v));
0417         }
0418         {
0419             PyObjectRef body = getattr<PyObjectRef>(node, "body");
0420             v->body = static_cast<ExpressionAst*>(visitExprNode(body, v));
0421         }
0422         {
0423             PyObjectRef orelse = getattr<PyObjectRef>(node, "orelse");
0424             v->orelse = static_cast<ExpressionAst*>(visitExprNode(orelse, v));
0425         }
0426         result = v;
0427     }
0428     else if (PyObject_IsInstance(node, grammar.ast_Dict)) {
0429         DictAst* v = new  DictAst(parent);
0430         {
0431             PyObjectRef keys = getattr<PyObjectRef>(node, "keys");
0432             v->keys = visitNodeList<ExpressionAst>(keys, v);
0433         }
0434         {
0435             PyObjectRef values = getattr<PyObjectRef>(node, "values");
0436             v->values = visitNodeList<ExpressionAst>(values, v);
0437         }
0438         result = v;
0439     }
0440     else if (PyObject_IsInstance(node, grammar.ast_Set)) {
0441         SetAst* v = new  SetAst(parent);
0442         {
0443             PyObjectRef elts = getattr<PyObjectRef>(node, "elts");
0444             v->elements = visitNodeList<ExpressionAst>(elts, v);
0445         }
0446         result = v;
0447     }
0448     else if (PyObject_IsInstance(node, grammar.ast_ListComp)) {
0449         ListComprehensionAst* v = new  ListComprehensionAst(parent);
0450         {
0451             PyObjectRef elt = getattr<PyObjectRef>(node, "elt");
0452             v->element = static_cast<ExpressionAst*>(visitExprNode(elt, v));
0453         }
0454         {
0455             PyObjectRef generators = getattr<PyObjectRef>(node, "generators");
0456             v->generators = visitNodeList<ComprehensionAst>(generators, v);
0457         }
0458         result = v;
0459     }
0460     else if (PyObject_IsInstance(node, grammar.ast_SetComp)) {
0461         SetComprehensionAst* v = new  SetComprehensionAst(parent);
0462         {
0463             PyObjectRef elt = getattr<PyObjectRef>(node, "elt");
0464             v->element = static_cast<ExpressionAst*>(visitExprNode(elt, v));
0465         }
0466         {
0467             PyObjectRef generators = getattr<PyObjectRef>(node, "generators");
0468             v->generators = visitNodeList<ComprehensionAst>(generators, v);
0469         }
0470         result = v;
0471     }
0472     else if (PyObject_IsInstance(node, grammar.ast_DictComp)) {
0473         DictionaryComprehensionAst* v = new  DictionaryComprehensionAst(parent);
0474         {
0475             PyObjectRef key = getattr<PyObjectRef>(node, "key");
0476             v->key = static_cast<ExpressionAst*>(visitExprNode(key, v));
0477         }
0478         {
0479             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0480             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0481         }
0482         {
0483             PyObjectRef generators = getattr<PyObjectRef>(node, "generators");
0484             v->generators = visitNodeList<ComprehensionAst>(generators, v);
0485         }
0486         result = v;
0487     }
0488     else if (PyObject_IsInstance(node, grammar.ast_GeneratorExp)) {
0489         GeneratorExpressionAst* v = new  GeneratorExpressionAst(parent);
0490         {
0491             PyObjectRef elt = getattr<PyObjectRef>(node, "elt");
0492             v->element = static_cast<ExpressionAst*>(visitExprNode(elt, v));
0493         }
0494         {
0495             PyObjectRef generators = getattr<PyObjectRef>(node, "generators");
0496             v->generators = visitNodeList<ComprehensionAst>(generators, v);
0497 
0498         }
0499         result = v;
0500     }
0501     else if (PyObject_IsInstance(node, grammar.ast_Yield)) {
0502         YieldAst* v = new  YieldAst(parent);
0503         {
0504             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0505             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0506         }
0507         result = v;
0508     }
0509     else if (PyObject_IsInstance(node, grammar.ast_Compare)) {
0510         CompareAst* v = new  CompareAst(parent);
0511         {
0512             PyObjectRef left = getattr<PyObjectRef>(node, "left");
0513             v->leftmostElement = static_cast<ExpressionAst*>(visitExprNode(left, v));
0514         }
0515 
0516         {
0517             PyObject* ops = getattr<PyObject*>(node, "ops");
0518             Q_ASSERT(PyList_Check(ops));
0519             for ( int _i = 0; _i < PyList_Size(ops); _i++ ) {
0520                 PyObject* elt = PyList_GET_ITEM(ops, _i); // borrowed
0521                 ExpressionAst::ComparisonOperatorTypes cmp;
0522                 if (PyObject_IsInstance(elt, grammar.ast_Eq))
0523                     cmp = Ast::ComparisonOperatorEquals;
0524                 else if (PyObject_IsInstance(elt, grammar.ast_NotEq))
0525                     cmp = Ast::ComparisonOperatorNotEquals;
0526                 else if (PyObject_IsInstance(elt, grammar.ast_Lt))
0527                     cmp = Ast::ComparisonOperatorLessThan;
0528                 else if (PyObject_IsInstance(elt, grammar.ast_LtE))
0529                     cmp = Ast::ComparisonOperatorLessThanEqual;
0530                 else if (PyObject_IsInstance(elt, grammar.ast_Gt))
0531                     cmp = Ast::ComparisonOperatorGreaterThan;
0532                 else if (PyObject_IsInstance(elt, grammar.ast_GtE))
0533                     cmp = Ast::ComparisonOperatorGreaterThanEqual;
0534                 else if (PyObject_IsInstance(elt, grammar.ast_Is))
0535                     cmp = Ast::ComparisonOperatorIs;
0536                 else if (PyObject_IsInstance(elt, grammar.ast_IsNot))
0537                     cmp = Ast::ComparisonOperatorIsNot;
0538                 else if (PyObject_IsInstance(elt, grammar.ast_In))
0539                     cmp = Ast::ComparisonOperatorIn;
0540                 else if (PyObject_IsInstance(elt, grammar.ast_NotIn))
0541                     cmp = Ast::ComparisonOperatorNotIn;
0542                 else
0543                     cmp = Ast::ComparisonOperatorInvalid;
0544                 v->operators.append(cmp);
0545             }
0546             Py_DECREF(ops);
0547         }
0548 
0549         {
0550             PyObjectRef comparators = getattr<PyObjectRef>(node, "comparators");
0551             v->comparands = visitNodeList<ExpressionAst>(comparators, v);
0552         }
0553         result = v;
0554     }
0555     else if (PyObject_IsInstance(node, grammar.ast_Call)) {
0556         CallAst* v = new  CallAst(parent);
0557         {
0558             PyObjectRef func = getattr<PyObjectRef>(node, "func");
0559             v->function = static_cast<ExpressionAst*>(visitExprNode(func, v));
0560         }
0561         {
0562             PyObjectRef args = getattr<PyObjectRef>(node, "args");
0563             v->arguments = visitNodeList<ExpressionAst>(args, v);
0564         }
0565         {
0566             PyObjectRef keywords = getattr<PyObjectRef>(node, "keywords");
0567             v->keywords = visitNodeList<KeywordAst>(keywords, v);
0568         }
0569 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 5, 0)
0570         /* Convert 3.4 unpacked-args AST to match the new format from 3.5+ */
0571         // TODO
0572 #endif
0573         result = v;
0574     }
0575 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0)
0576     else if (PyObject_IsInstance(node, grammar.ast_Num)) {
0577         NumberAst* v = new  NumberAst(parent);
0578         {
0579             PyObjectRef n = getattr<PyObjectRef>(node, "n");
0580             v->isInt = PyLong_Check(n);
0581             v->value = PyLong_AsLong(n);
0582         }
0583         result = v;
0584     }
0585 #endif
0586 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0)
0587     else if (PyObject_IsInstance(node, grammar.ast_Str)) {
0588         StringAst* v = new  StringAst(parent);
0589         v->value = getattr<QString>(node, "s");
0590         result = v;
0591     }
0592 #endif
0593 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
0594     else if (PyObject_IsInstance(node, grammar.ast_JoinedStr)) {
0595         JoinedStringAst* v = new  JoinedStringAst(parent);
0596         {
0597             PyObjectRef values = getattr<PyObjectRef>(node, "values");
0598             v->values = visitNodeList<ExpressionAst>(values, v);
0599         }
0600         result = v;
0601     }
0602 #endif
0603 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
0604     else if (PyObject_IsInstance(node, grammar.ast_FormattedValue)) {
0605         FormattedValueAst* v = new  FormattedValueAst(parent);
0606         {
0607             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0608             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0609 
0610         }
0611         v->conversion = getattr<int>(node, "conversion");
0612         {
0613             PyObjectRef format_spec = getattr<PyObjectRef>(node, "format_spec");
0614             v->formatSpec = static_cast<ExpressionAst*>(visitExprNode(format_spec, v));
0615         }
0616         result = v;
0617     }
0618 #endif
0619 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0)
0620     else if (PyObject_IsInstance(node, grammar.ast_Bytes)) {
0621         BytesAst* v = new  BytesAst(parent);
0622         v->value = getattr<QString>(node, "s");
0623         result = v;
0624     }
0625 #endif
0626     else if (PyObject_IsInstance(node, grammar.ast_Attribute)) {
0627         AttributeAst* v = new  AttributeAst(parent);
0628         QString attr = getattr<QString>(node, "attr");
0629         if (attr.size()) {
0630             v->attribute = new Python::Identifier(attr);
0631             v->attribute->startCol = getattr<int>(node, "col_offset");
0632             v->attribute->startLine = tline(getattr<int>(node, "lineno"));
0633             v->attribute->endCol = v->attribute->startCol + attr.size() - 1;
0634             v->attribute->endLine = v->attribute->startLine;
0635 
0636             v->startCol = v->attribute->startCol;
0637             v->startLine = v->attribute->startLine;
0638             v->endCol = v->attribute->endCol;
0639             v->endLine = v->attribute->endLine;
0640             ranges_copied = true;
0641         } else {
0642             v->attribute = nullptr;
0643         }
0644         {
0645             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0646             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0647         }
0648         v->context = getattr<ExpressionAst::Context>(node, "ctx");
0649         result = v;
0650     }
0651     else if (PyObject_IsInstance(node, grammar.ast_Subscript)) {
0652         SubscriptAst* v = new  SubscriptAst(parent);
0653         {
0654             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0655             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0656         }
0657         {
0658             PyObjectRef slice = getattr<PyObjectRef>(node, "slice");
0659             v->slice = static_cast<SliceAst*>(visitNode(slice, v));
0660         }
0661         v->context = getattr<ExpressionAst::Context>(node, "ctx");
0662         result = v;
0663     }
0664     else if (PyObject_IsInstance(node, grammar.ast_Starred)) {
0665         StarredAst* v = new  StarredAst(parent);
0666         {
0667             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0668             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0669         }
0670         v->context = getattr<ExpressionAst::Context>(node, "ctx");
0671         result = v;
0672     }
0673     else if (PyObject_IsInstance(node, grammar.ast_Name)) {
0674         NameAst* v = new  NameAst(parent);
0675         QString id = getattr<QString>(node, "id");
0676         if ( id.size() ) {
0677             v->identifier = new Python::Identifier(id);
0678             v->identifier->startCol = getattr<int>(node, "col_offset");
0679             v->identifier->startLine = tline(getattr<int>(node, "lineno"));
0680             v->identifier->endCol = v->identifier->startCol + id.size() - 1;
0681             v->identifier->endLine = v->identifier->startLine;
0682             v->startCol = v->identifier->startCol;
0683             v->startLine = v->identifier->startLine;
0684             v->endCol = v->identifier->endCol;
0685             v->endLine = v->identifier->endLine;
0686             ranges_copied = true;
0687         } else {
0688             v->identifier = nullptr;
0689         }
0690         v->context = getattr<ExpressionAst::Context>(node, "ctx");
0691         result = v;
0692     }
0693     else if (PyObject_IsInstance(node, grammar.ast_List)) {
0694         ListAst* v = new  ListAst(parent);
0695         {
0696             PyObjectRef elts = getattr<PyObjectRef>(node, "elts");
0697             v->elements = visitNodeList<ExpressionAst>(elts, v);
0698         }
0699         v->context = getattr<ExpressionAst::Context>(node, "ctx");
0700         result = v;
0701     }
0702     else if (PyObject_IsInstance(node, grammar.ast_Tuple)) {
0703         TupleAst* v = new  TupleAst(parent);
0704         {
0705             PyObjectRef elts = getattr<PyObjectRef>(node, "elts");
0706             v->elements = visitNodeList<ExpressionAst>(elts, v);
0707         }
0708         v->context = getattr<ExpressionAst::Context>(node, "ctx");
0709         result = v;
0710     }
0711 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0)
0712     else if (PyObject_IsInstance(node, grammar.ast_Ellipsis)) {
0713         EllipsisAst* v = new  EllipsisAst(parent);
0714         result = v;
0715     }
0716 #endif
0717 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 8, 0)
0718     else if (PyObject_IsInstance(node, grammar.ast_NameConstant)) {
0719         NameConstantAst* v = new NameConstantAst(parent);
0720         {
0721             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0722             if (value == Py_None)
0723                 v->value = NameConstantAst::None;
0724             else if (value == Py_False)
0725                 v->value = NameConstantAst::False;
0726             else
0727                 v->value = NameConstantAst::True;
0728         }
0729         result = v;
0730     }
0731 #endif
0732     else if (PyObject_IsInstance(node, grammar.ast_YieldFrom)) {
0733         YieldFromAst* v = new  YieldFromAst(parent);
0734         {
0735             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0736             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0737         }
0738         result = v;
0739     }
0740 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0)
0741     else if (PyObject_IsInstance(node, grammar.ast_Constant)) {
0742         PyObject* value = getattr<PyObject*>(node, "value");
0743         if (value == Py_None) {
0744             NameConstantAst* v = new NameConstantAst(parent);
0745             v->value = NameConstantAst::None;
0746             result = v;
0747 
0748         } else if (value == Py_True) {
0749             NameConstantAst* v = new  NameConstantAst(parent);
0750             v->value = NameConstantAst::True;
0751             result = v;
0752 
0753         } else if (value == Py_False) {
0754             NameConstantAst* v = new  NameConstantAst(parent);
0755             v->value = NameConstantAst::False;
0756             result = v;
0757 
0758         } else if (value->ob_type == &PyLong_Type) {
0759             NumberAst* v = new NumberAst(parent);
0760             v->isInt = true;
0761             v->value = PyLong_AsLong(value);
0762             result = v;
0763         } else if (value->ob_type == &PyFloat_Type || value->ob_type == &PyComplex_Type) {
0764             result = new NumberAst(parent);
0765 
0766         } else if (value->ob_type == &PyUnicode_Type) {
0767             StringAst* v = new StringAst(parent);
0768             v->value = PyUnicodeObjectToQString(value);
0769             result = v;
0770         } else if (value->ob_type == &PyBytes_Type) {
0771             result = new BytesAst(parent);
0772         } else if (value->ob_type == &PyEllipsis_Type) {
0773             result = new EllipsisAst(parent);
0774         } else {
0775             qWarning() << "Unhandled constant type: " << value->ob_type->tp_name;
0776             Q_ASSERT(false);
0777 
0778         };
0779         Py_DECREF(value);
0780     }
0781 #endif
0782 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 8, 0)
0783     else if (PyObject_IsInstance(node, grammar.ast_NamedExpr)) {
0784         AssignmentExpressionAst* v = new  AssignmentExpressionAst(parent);
0785         {
0786             PyObjectRef target = getattr<PyObjectRef>(node, "target");
0787             v->target = static_cast<ExpressionAst*>(visitExprNode(target, v));
0788         }
0789         {
0790             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0791             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0792         }
0793         result = v;
0794     }
0795 #endif
0796 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 9, 0)
0797     else if (PyObject_IsInstance(node, grammar.ast_Slice)) {
0798         SliceAst* v = new  SliceAst(parent);
0799         {
0800             PyObjectRef lower = getattr<PyObjectRef>(node, "lower");
0801             v->lower = static_cast<ExpressionAst*>(visitExprNode(lower, v));
0802         }
0803         {
0804             PyObjectRef upper = getattr<PyObjectRef>(node, "upper");
0805             v->upper = static_cast<ExpressionAst*>(visitExprNode(upper, v));
0806         }
0807         {
0808             PyObjectRef step = getattr<PyObjectRef>(node, "step");
0809             v->step = static_cast<ExpressionAst*>(visitExprNode(step, v));
0810         }
0811         result = v;
0812     }
0813 #endif
0814     else {
0815         qWarning() << "Unsupported _expr AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
0816         Q_ASSERT(false);
0817     }
0818 
0819     if ( ! result ) return nullptr;
0820     if ( ! ranges_copied ) {
0821         result->startCol = getattr<int>(node, "col_offset");
0822         result->endCol = result->startCol;
0823         result->startLine = tline(getattr<int>(node, "lineno"));
0824         result->endLine = result->startLine;
0825         result->hasUsefulRangeInformation = true;
0826     }
0827     else {
0828         result->hasUsefulRangeInformation = true;
0829     }
0830     updateRanges(result);
0831     return result;
0832 }
0833 
0834 
0835 Ast* AstTransformer::visitSliceNode(PyObject* node, Ast* parent)
0836 {
0837     if ( ! node || node == Py_None ) return nullptr;
0838     // qDebug() << "visit slice: " << PyUnicodeObjectToQString(PyObject_Str(node));
0839     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_slice));
0840     Ast* result = nullptr;
0841 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 9, 0)
0842     if (PyObject_IsInstance(node, grammar.ast_Slice)) {
0843         SliceAst* v = new  SliceAst(parent);
0844         {
0845             PyObjectRef lower = getattr<PyObjectRef>(node, "lower");
0846             v->lower = static_cast<ExpressionAst*>(visitExprNode(lower, v));
0847         }
0848         {
0849             PyObjectRef upper = getattr<PyObjectRef>(node, "upper");
0850             v->upper = static_cast<ExpressionAst*>(visitExprNode(upper, v));
0851         }
0852         {
0853             PyObjectRef step = getattr<PyObjectRef>(node, "step");
0854             v->step = static_cast<ExpressionAst*>(visitExprNode(step, v));
0855         }
0856         result = v;
0857     }
0858 #endif
0859 #if PYTHON_VERSION < QT_VERSION_CHECK(3, 9, 0)
0860     if (PyObject_IsInstance(node, grammar.ast_ExtSlice)) {
0861         TupleAst* v = new  TupleAst(parent);
0862         {
0863             PyObjectRef dims = getattr<PyObjectRef>(node, "dims");
0864             v->elements = visitNodeList<ExpressionAst>(dims, parent);
0865         }
0866         result = v;
0867     }
0868     else if (PyObject_IsInstance(node, grammar.ast_Index)) {
0869         PyObjectRef value = getattr<PyObjectRef>(node, "value");
0870         return visitNode(value, parent);
0871     }
0872 #endif
0873     else {
0874         qWarning() << "Unsupported _slice AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
0875         Q_ASSERT(false);
0876     }
0877     updateRanges(result);
0878     return result;
0879 }
0880 
0881 Ast* AstTransformer::visitStmtNode(PyObject* node, Ast* parent)
0882 {
0883     if ( !node || node == Py_None ) return nullptr;
0884     // qDebug() << "visit stmt: " << PyUnicodeObjectToQString(PyObject_Str(node));
0885     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_stmt));
0886     bool ranges_copied = false;
0887     Ast* result = nullptr;
0888     if (PyObject_IsInstance(node, grammar.ast_Expr)) {
0889         ExpressionAst* v = new  ExpressionAst(parent);
0890         {
0891             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0892             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0893         }
0894         result = v;
0895     }
0896     else if (PyObject_IsInstance(node, grammar.ast_FunctionDef)
0897 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
0898              || PyObject_IsInstance(node, grammar.ast_AsyncFunctionDef)
0899 #endif
0900             ) {
0901         FunctionDefinitionAst* v = new  FunctionDefinitionAst(parent);
0902         QString name = getattr<QString>(node, "name");
0903         if ( name.size() ) {
0904             v->name = new Python::Identifier(name);
0905             v->name->startCol = getattr<int>(node, "col_offset");
0906             v->name->startLine = tline(getattr<int>(node, "lineno"));
0907             v->name->endCol = v->name->startCol + name.size() - 1;
0908             v->name->endLine = v->name->startLine;
0909 
0910             v->startCol = v->name->startCol;
0911             v->startLine = v->name->startLine;
0912             v->endCol = v->name->endCol;
0913             v->endLine = v->name->endLine;
0914             ranges_copied = true;
0915         }
0916         else {
0917             v->name = nullptr;
0918         }
0919 
0920         {
0921             PyObjectRef args = getattr<PyObjectRef>(node, "args");
0922             v->arguments = static_cast<ArgumentsAst*>(visitArgumentsNode(args, v));
0923         }
0924         {
0925             PyObjectRef body = getattr<PyObjectRef>(node, "body");
0926             v->body = visitNodeList<Ast>(body, v);
0927         }
0928         {
0929             PyObjectRef decorator_list = getattr<PyObjectRef>(node, "decorator_list");
0930             v->decorators = visitNodeList<ExpressionAst>(decorator_list, v);
0931         }
0932         {
0933             PyObjectRef returns = getattr<PyObjectRef>(node, "returns");
0934             v->returns = static_cast<ExpressionAst*>(visitExprNode(returns, v));
0935         }
0936 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
0937         v->async = PyObject_IsInstance(node, grammar.ast_AsyncFunctionDef);
0938 #endif
0939         result = v;
0940     }
0941     else if (PyObject_IsInstance(node, grammar.ast_ClassDef)) {
0942         ClassDefinitionAst* v = new  ClassDefinitionAst(parent);
0943         QString name = getattr<QString>(node, "name");
0944         if ( name.size() ) {
0945             v->name = new Python::Identifier(name);
0946             v->name->startCol = getattr<int>(node, "col_offset");
0947             v->name->startLine = tline(getattr<int>(node, "lineno"));
0948             v->name->endCol = v->name->startCol + name.size() - 1;
0949             v->name->endLine = v->name->startLine;
0950 
0951             v->startCol = v->name->startCol;
0952             v->startLine = v->name->startLine;
0953             v->endCol = v->name->endCol;
0954             v->endLine = v->name->endLine;
0955             ranges_copied = true;
0956         }
0957         else {
0958             v->name = nullptr;
0959         }
0960 
0961         {
0962             PyObjectRef bases = getattr<PyObjectRef>(node, "bases");
0963             v->baseClasses = visitNodeList<ExpressionAst>(bases, v);
0964         }
0965         {
0966             PyObjectRef body = getattr<PyObjectRef>(node, "body");
0967             v->body = visitNodeList<Ast>(body, v);
0968         }
0969         {
0970             PyObjectRef decorator_list = getattr<PyObjectRef>(node, "decorator_list");
0971             v->decorators = visitNodeList<ExpressionAst>(decorator_list, v);
0972         }
0973         result = v;
0974     }
0975     else if (PyObject_IsInstance(node, grammar.ast_Return)) {
0976         ReturnAst* v = new  ReturnAst(parent);
0977         PyObjectRef value = getattr<PyObjectRef>(node, "value");
0978         v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0979         result = v;
0980     }
0981     else if (PyObject_IsInstance(node, grammar.ast_Delete)) {
0982         DeleteAst* v = new  DeleteAst(parent);
0983         PyObjectRef targets = getattr<PyObjectRef>(node, "targets");
0984         v->targets = visitNodeList<ExpressionAst>(targets, v);
0985         result = v;
0986     }
0987     else if (PyObject_IsInstance(node, grammar.ast_Assign)) {
0988         AssignmentAst* v = new  AssignmentAst(parent);
0989         {
0990             PyObjectRef targets = getattr<PyObjectRef>(node, "targets");
0991             v->targets = visitNodeList<ExpressionAst>(targets, v);
0992         }
0993         {
0994             PyObjectRef value = getattr<PyObjectRef>(node, "value");
0995             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
0996         }
0997         result = v;
0998     }
0999     else if (PyObject_IsInstance(node, grammar.ast_AugAssign)) {
1000         AugmentedAssignmentAst* v = new  AugmentedAssignmentAst(parent);
1001         {
1002             PyObjectRef target = getattr<PyObjectRef>(node, "target");
1003             v->target = static_cast<ExpressionAst*>(visitExprNode(target, v));
1004         }
1005         v->op = getattr<Ast::OperatorTypes>(node, "op");
1006         {
1007             PyObjectRef value = getattr<PyObjectRef>(node, "value");
1008             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
1009         }
1010         result = v;
1011     }
1012 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
1013     else if (PyObject_IsInstance(node, grammar.ast_AnnAssign)) {
1014         AnnotationAssignmentAst* v = new  AnnotationAssignmentAst(parent);
1015         {
1016             PyObjectRef target = getattr<PyObjectRef>(node, "target");
1017             v->target = static_cast<ExpressionAst*>(visitExprNode(target, v));
1018         }
1019         {
1020             PyObjectRef annotation = getattr<PyObjectRef>(node, "annotation");
1021             v->annotation = static_cast<ExpressionAst*>(visitExprNode(annotation, v));
1022         }
1023         {
1024             PyObjectRef value = getattr<PyObjectRef>(node, "value");
1025             v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
1026         }
1027         result = v;
1028     }
1029 #endif
1030     else if (PyObject_IsInstance(node, grammar.ast_For)
1031 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
1032         || PyObject_IsInstance(node, grammar.ast_AsyncFor)
1033 #endif
1034     ) {
1035         ForAst* v = new  ForAst(parent);
1036         {
1037             PyObjectRef target = getattr<PyObjectRef>(node, "target");
1038             v->target = static_cast<ExpressionAst*>(visitExprNode(target, v));
1039         }
1040         {
1041             PyObjectRef iter = getattr<PyObjectRef>(node, "iter");
1042             v->iterator = static_cast<ExpressionAst*>(visitExprNode(iter, v));
1043         }
1044         {
1045             PyObjectRef body = getattr<PyObjectRef>(node, "body");
1046             v->body = visitNodeList<Ast>(body, v);
1047         }
1048         {
1049             PyObjectRef orelse = getattr<PyObjectRef>(node, "orelse");
1050             v->orelse = visitNodeList<Ast>(orelse, v);
1051         }
1052 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
1053         v->async = PyObject_IsInstance(node, grammar.ast_AsyncFor);
1054 #endif
1055         result = v;
1056     }
1057     else if (PyObject_IsInstance(node, grammar.ast_While)) {
1058         WhileAst* v = new  WhileAst(parent);
1059         {
1060             PyObjectRef test = getattr<PyObjectRef>(node, "test");
1061             v->condition = static_cast<ExpressionAst*>(visitExprNode(test, v));
1062         }
1063         {
1064             PyObjectRef body = getattr<PyObjectRef>(node, "body");
1065             v->body = visitNodeList<Ast>(body, v);
1066         }
1067         {
1068             PyObjectRef orelse = getattr<PyObjectRef>(node, "orelse");
1069             v->orelse = visitNodeList<Ast>(orelse, v);
1070         }
1071         result = v;
1072     }
1073     else if (PyObject_IsInstance(node, grammar.ast_If)) {
1074         IfAst* v = new  IfAst(parent);
1075         {
1076             PyObjectRef test = getattr<PyObjectRef>(node, "test");
1077             v->condition = static_cast<ExpressionAst*>(visitExprNode(test, v));
1078         }
1079         {
1080             PyObjectRef body = getattr<PyObjectRef>(node, "body");
1081             v->body = visitNodeList<Ast>(body, v);
1082         }
1083         {
1084             PyObjectRef orelse = getattr<PyObjectRef>(node, "orelse");
1085             v->orelse = visitNodeList<Ast>(orelse, v);
1086         }
1087         result = v;
1088     }
1089     else if (PyObject_IsInstance(node, grammar.ast_With)
1090 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 6, 0)
1091         || PyObject_IsInstance(node, grammar.ast_AsyncWith)
1092 #endif
1093     ) {
1094             WithAst* v = new  WithAst(parent);
1095             {
1096                 PyObjectRef body = getattr<PyObjectRef>(node, "body");
1097                 v->body = visitNodeList<Ast>(body, v);
1098             }
1099             {
1100                 PyObjectRef items = getattr<PyObjectRef>(node, "items");
1101                 v->items = visitNodeList<WithItemAst>(items, v);
1102             }
1103 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 5, 0)
1104             v->async = PyObject_IsInstance(node, grammar.ast_AsyncWith);
1105 #endif
1106             result = v;
1107     }
1108 
1109     else if (PyObject_IsInstance(node, grammar.ast_Raise)) {
1110         RaiseAst* v = new  RaiseAst(parent);
1111         {
1112             PyObjectRef exc = getattr<PyObjectRef>(node, "exc");
1113             v->type = static_cast<ExpressionAst*>(visitExprNode(exc, v));
1114         }
1115         result = v;
1116     }
1117     else if (PyObject_IsInstance(node, grammar.ast_Try)) {
1118         TryAst* v = new  TryAst(parent);
1119         {
1120             PyObjectRef body = getattr<PyObjectRef>(node, "body");
1121             v->body = visitNodeList<Ast>(body, v);
1122         }
1123         {
1124             PyObjectRef handlers = getattr<PyObjectRef>(node, "handlers");
1125             v->handlers = visitNodeList<ExceptionHandlerAst>(handlers, v);
1126 
1127         }
1128         {
1129             PyObjectRef orelse = getattr<PyObjectRef>(node, "orelse");
1130             v->orelse = visitNodeList<Ast>(orelse, v);
1131         }
1132         {
1133             PyObjectRef finalbody = getattr<PyObjectRef>(node, "finalbody");
1134             v->finally = visitNodeList<Ast>(finalbody, v);
1135         }
1136         result = v;
1137     }
1138     else if (PyObject_IsInstance(node, grammar.ast_Assert)) {
1139         AssertionAst* v = new  AssertionAst(parent);
1140         {
1141             PyObjectRef test = getattr<PyObjectRef>(node, "test");
1142             v->condition = static_cast<ExpressionAst*>(visitExprNode(test, v));
1143         }
1144         {
1145             PyObjectRef msg = getattr<PyObjectRef>(node, "msg");
1146             v->message = static_cast<ExpressionAst*>(visitExprNode(msg, v));
1147         }
1148         result = v;
1149     }
1150     else if (PyObject_IsInstance(node, grammar.ast_Import)) {
1151         ImportAst* v = new  ImportAst(parent);
1152         {
1153             PyObjectRef names = getattr<PyObjectRef>(node, "names");
1154             v->names = visitNodeList<AliasAst>(names, v);
1155         }
1156         result = v;
1157     }
1158     else if (PyObject_IsInstance(node, grammar.ast_ImportFrom)) {
1159         ImportFromAst* v = new  ImportFromAst(parent);
1160         QString module = getattr<QString>(node, "module");
1161         if ( module.size() ) {
1162             v->module = new Python::Identifier(module);
1163             v->module->startCol = getattr<int>(node, "col_offset");
1164             v->module->startLine = tline(getattr<int>(node, "lineno"));
1165             v->module->endCol = v->module->startCol + module.size() - 1;
1166             v->module->endLine = v->module->startLine;
1167 
1168             v->startCol = v->module->startCol;
1169             v->startLine = v->module->startLine;
1170             v->endCol = v->module->endCol;
1171             v->endLine = v->module->endLine;
1172             ranges_copied = true;
1173         } else {
1174             v->module = nullptr;
1175         }
1176         {
1177             PyObjectRef names = getattr<PyObjectRef>(node, "names");
1178             v->names = visitNodeList<AliasAst>(names, v);
1179         }
1180         v->level = getattr<int>(node, "level");
1181         result = v;
1182     }
1183     else if (PyObject_IsInstance(node, grammar.ast_Global)) {
1184         GlobalAst* v = new  GlobalAst(parent);
1185 
1186         PyObject* names = getattr<PyObject*>(node, "names");
1187         Q_ASSERT(PyList_Check(names));
1188         for ( int _i = 0; _i < PyList_Size(names); _i++ ) {
1189             Python::Identifier* id = new Python::Identifier(PyUnicodeObjectToQString(
1190                             static_cast<PyObject*>(PyList_GET_ITEM(names, _i))
1191                     ));
1192             v->names.append(id);
1193         }
1194         Py_DECREF(names);
1195 
1196         result = v;
1197     }
1198     else if (PyObject_IsInstance(node, grammar.ast_Break)) {
1199         BreakAst* v = new  BreakAst(parent);
1200         result = v;
1201     }
1202     else if (PyObject_IsInstance(node, grammar.ast_Continue)) {
1203         ContinueAst* v = new  ContinueAst(parent);
1204         result = v;
1205     }
1206     else if (PyObject_IsInstance(node, grammar.ast_Pass)) {
1207         PassAst* v = new  PassAst(parent);
1208         result = v;
1209     }
1210     else if (PyObject_IsInstance(node, grammar.ast_Nonlocal)) {
1211         NonlocalAst* v = new  NonlocalAst(parent);
1212         result = v;
1213     }
1214 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
1215     else if (PyObject_IsInstance(node, grammar.ast_Match)) {
1216         MatchAst* v = new  MatchAst(parent);
1217         {
1218             PyObjectRef subject = getattr<PyObjectRef>(node, "subject");
1219             v->subject = static_cast<ExpressionAst*>(visitExprNode(subject, v));
1220         }
1221         {
1222             PyObjectRef cases = getattr<PyObjectRef>(node, "cases");
1223             v->cases = visitNodeList<MatchCaseAst>(cases, v);
1224         }
1225         result = v;
1226     }
1227 #endif
1228 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 11, 0)
1229     else if (PyObject_IsInstance(node, grammar.ast_TryStar)) {
1230         TryStarAst* v = new  TryStarAst(parent);
1231         {
1232             PyObjectRef body = getattr<PyObjectRef>(node, "body");
1233             v->body = visitNodeList<Ast>(body, v);
1234         }
1235         {
1236             PyObjectRef handlers = getattr<PyObjectRef>(node, "handlers");
1237             v->handlers = visitNodeList<ExceptionHandlerAst>(handlers, v);
1238         }
1239         {
1240             PyObjectRef orelse = getattr<PyObjectRef>(node, "orelse");
1241             v->orelse = visitNodeList<Ast>(orelse, v);
1242         }
1243         {
1244             PyObjectRef finalbody = getattr<PyObjectRef>(node, "finalbody");
1245             v->finally = visitNodeList<Ast>(finalbody, v);
1246         }
1247         result = v;
1248     }
1249 #endif
1250     else {
1251         qWarning() << "Unsupported _stmt AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
1252         Q_ASSERT(false);
1253     }
1254 
1255     if ( ! result ) return nullptr;
1256     if ( ! ranges_copied ) {
1257         result->startCol = getattr<int>(node, "col_offset");
1258         result->endCol = result->endCol;
1259         result->startLine = tline(getattr<int>(node, "lineno"));
1260         result->endLine = result->startLine;
1261         result->hasUsefulRangeInformation = true;
1262     } else {
1263         result->hasUsefulRangeInformation = true;
1264     }
1265     updateRanges(result);
1266     return result;
1267 }
1268 
1269 Ast* AstTransformer::visitKeywordNode(PyObject* node, Ast* parent)
1270 {
1271     if ( !node || node == Py_None ) return nullptr;
1272     // qDebug() << "visit keyword: " << PyUnicodeObjectToQString(PyObject_Str(node));
1273     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_keyword));
1274     KeywordAst* v = new  KeywordAst(parent);
1275     QString arg = getattr<QString>(node, "arg");
1276     v->argumentName = arg.size() ? new Python::Identifier(arg) : nullptr;
1277     {
1278         PyObjectRef value = getattr<PyObjectRef>(node, "value");
1279         v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
1280     }
1281     return v;
1282 }
1283 
1284 
1285 Ast* AstTransformer::visitWithItemNode(PyObject* node, Ast* parent)
1286 {
1287     if ( !node || node == Py_None ) return nullptr;
1288     // qDebug() << "visit with item: " << PyUnicodeObjectToQString(PyObject_Str(node));
1289     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_withitem));
1290     WithItemAst* v = new  WithItemAst(parent);
1291     {
1292         PyObjectRef context_expr = getattr<PyObjectRef>(node, "context_expr");
1293         v->contextExpression = static_cast<ExpressionAst*>(visitExprNode(context_expr, v));
1294     }
1295     {
1296         PyObjectRef optional_vars = getattr<PyObjectRef>(node, "optional_vars");
1297         v->optionalVars = static_cast<ExpressionAst*>(visitExprNode(optional_vars, v));
1298     }
1299     return v;
1300 }
1301 
1302 #if PYTHON_VERSION >= QT_VERSION_CHECK(3, 10, 0)
1303 Ast* AstTransformer::visitMatchCaseNode(PyObject* node, Ast* parent)
1304 {
1305     if ( !node || node == Py_None ) return nullptr;
1306     // qDebug() << "visit match case: " << PyUnicodeObjectToQString(PyObject_Str(node));
1307     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_match_case));
1308     MatchCaseAst* v = new  MatchCaseAst(parent);
1309     {
1310         PyObjectRef pattern = getattr<PyObjectRef>(node, "pattern");
1311         v->pattern = static_cast<PatternAst*>(visitPatternNode(pattern, v));
1312     }
1313     {
1314         PyObjectRef guard = getattr<PyObjectRef>(node, "guard");
1315         v->guard = static_cast<ExpressionAst*>(visitExprNode(guard, v));
1316     }
1317     {
1318         PyObjectRef body = getattr<PyObjectRef>(node, "body");
1319         v->body = visitNodeList<Ast>(body, v);
1320     }
1321     return v;
1322 }
1323 Ast* AstTransformer::visitPatternNode(PyObject* node, Ast* parent)
1324 {
1325     if ( !node || node == Py_None ) return nullptr;
1326     // qDebug() << "visit pattern: " << PyUnicodeObjectToQString(PyObject_Str(node));
1327     Q_ASSERT(PyObject_IsInstance(node, grammar.ast_pattern));
1328     Ast* result = nullptr;
1329     if (PyObject_IsInstance(node, grammar.ast_MatchValue)) {
1330         MatchValueAst* v = new  MatchValueAst(parent);
1331         PyObjectRef value = getattr<PyObjectRef>(node, "value");
1332         v->value = static_cast<ExpressionAst*>(visitExprNode(value, v));
1333         result = v;
1334     }
1335     else if (PyObject_IsInstance(node, grammar.ast_MatchSingleton)) {
1336         MatchSingletonAst* v = new  MatchSingletonAst(parent);
1337         {
1338             PyObjectRef value = getattr<PyObjectRef>(node, "value");
1339             if (value == Py_None)
1340                 v->value = NameConstantAst::None;
1341             else if (value == Py_False)
1342                 v->value = NameConstantAst::False;
1343             else
1344                 v->value = NameConstantAst::True;
1345         }
1346         result = v;
1347     }
1348     else if (PyObject_IsInstance(node, grammar.ast_MatchSequence)) {
1349         MatchSequenceAst* v = new  MatchSequenceAst(parent);
1350         PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
1351         v->patterns = visitNodeList<PatternAst>(patterns, v);
1352         result = v;
1353     }
1354     else if (PyObject_IsInstance(node, grammar.ast_MatchMapping)) {
1355         MatchMappingAst* v = new  MatchMappingAst(parent);
1356         {
1357             PyObjectRef keys = getattr<PyObjectRef>(node, "keys");
1358             v->keys = visitNodeList<ExpressionAst>(keys, v);
1359         }
1360         {
1361             QString rest = getattr<QString>(node, "rest");
1362             v->rest = rest.size() ? new Python::Identifier(rest) : nullptr;
1363         }
1364         {
1365             PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
1366             v->patterns = visitNodeList<PatternAst>(patterns, v);
1367         }
1368         result = v;
1369     }
1370     else if (PyObject_IsInstance(node, grammar.ast_MatchClass)) {
1371         MatchClassAst* v = new  MatchClassAst(parent);
1372         {
1373             PyObjectRef cls = getattr<PyObjectRef>(node, "cls");
1374             v->cls = static_cast<ExpressionAst*>(visitExprNode(cls, v));
1375         }
1376         {
1377             PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
1378             v->patterns = visitNodeList<PatternAst>(patterns, v);
1379         }
1380         {
1381             QString kwd_attrs = getattr<QString>(node, "kwd_attrs");
1382             v->kwdAttrs = kwd_attrs.size() ? new Python::Identifier(kwd_attrs) : nullptr;
1383         }
1384         {
1385             PyObjectRef kwd_patterns = getattr<PyObjectRef>(node, "kwd_patterns");
1386             v->kwdPatterns = visitNodeList<PatternAst>(kwd_patterns, v);
1387         }
1388         result = v;
1389     }
1390     else if (PyObject_IsInstance(node, grammar.ast_MatchStar)) {
1391         MatchStarAst* v = new  MatchStarAst(parent);
1392         QString name = getattr<QString>(node, "name");
1393         v->name = name.size() ? new Python::Identifier(name) : nullptr;
1394         result = v;
1395     }
1396     else if (PyObject_IsInstance(node, grammar.ast_MatchAs)) {
1397         MatchAsAst* v = new  MatchAsAst(parent);
1398         {
1399             PyObjectRef pattern = getattr<PyObjectRef>(node, "pattern");
1400             v->pattern = static_cast<PatternAst*>(visitPatternNode(pattern, v));
1401         }
1402         {
1403             QString name = getattr<QString>(node, "name");
1404             v->name = name.size() ? new Python::Identifier(name) : nullptr;
1405             if (v->name) {
1406                 v->name->startLine = tline(getattr<int>(node, "end_lineno"));
1407                 v->name->endCol = getattr<int>(node, "end_col_offset") - 1;
1408                 v->name->endLine = v->name->startLine;
1409                 v->name->startCol = v->name->endCol - name.size() + 1;
1410                 v->copyRange(v->name);
1411             }
1412         }
1413         result = v;
1414     }
1415     else if (PyObject_IsInstance(node, grammar.ast_MatchOr)) {
1416         MatchOrAst* v = new MatchOrAst(parent);
1417         {
1418             PyObjectRef patterns = getattr<PyObjectRef>(node, "patterns");
1419             v->patterns = visitNodeList<PatternAst>(patterns, v);
1420         }
1421         result = v;
1422     }
1423     else {
1424         qWarning() << "Unsupported pattern AST type: " << PyUnicodeObjectToQString(PyObject_Str(node));
1425         Q_ASSERT(false);
1426     }
1427     if ( ! result ) return nullptr;
1428     updateRanges(result);
1429     return result;
1430 }
1431 #endif
1432 
1433 void AstTransformer::updateRanges(Ast* result)
1434 {
1435     // Walk through the tree and set proper end columns and lines, as the python parser sadly does not do this for us
1436     if ( result->hasUsefulRangeInformation ) {
1437         Ast* parent = result->parent;
1438         while ( parent ) {
1439             if ( parent->endLine < result->endLine ) {
1440                 parent->endLine = result->endLine;
1441                 parent->endCol = result->endCol;
1442             }
1443             if ( ! parent->hasUsefulRangeInformation && parent->startLine == -99999 ) {
1444                 parent->startLine = result->startLine;
1445                 parent->startCol = result->startCol;
1446             }
1447             parent = parent->parent;
1448         }
1449     }
1450 
1451     if ( result && result->astType == Ast::NameAstType ) {
1452         NameAst* r = static_cast<NameAst*>(result);
1453         r->startCol = r->identifier->startCol;
1454         r->endCol = r->identifier->endCol;
1455         r->startLine = r->identifier->startLine;
1456         r->endLine = r->identifier->endLine;
1457     }
1458 }
1459 
1460 } // end namespace Python