You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

parse.cc 56 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /**
  2. * This is the C++ adaptation and derivative work of Myia (https://github.com/mila-iqia/myia/).
  3. *
  4. * Copyright 2019 Huawei Technologies Co., Ltd
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "pipeline/parse/parse.h"
  19. #include <string>
  20. #include <memory>
  21. #include <sstream>
  22. #include <unordered_map>
  23. #include <algorithm>
  24. #include "operator/ops.h"
  25. #include "pipeline/parse/data_converter.h"
  26. #include "operator/composite/composite.h"
  27. #include "utils/context/ms_context.h"
  28. #include "debug/trace.h"
  29. namespace mindspore {
  30. namespace parse {
  31. FuncGraphPtr ParsePythonCode(const py::object &obj, const std::string &python_mod_get_parse_method) {
  32. (void)python_adapter::set_python_scoped();
  33. if (obj == nullptr || py::isinstance<py::none>(obj)) {
  34. MS_LOG(ERROR) << "Parse the python code failed, obj is nullptr or none";
  35. return nullptr;
  36. }
  37. auto ast = std::make_shared<ParseAst>(obj);
  38. bool success = ast->InitParseAstInfo(python_mod_get_parse_method);
  39. if (!success) {
  40. MS_LOG(ERROR) << "Parse code to ast tree failed.";
  41. return nullptr;
  42. }
  43. auto parser = std::make_shared<Parser>(ast);
  44. FuncGraphPtr func_graph = parser->ParseFuncGraph();
  45. if (func_graph == nullptr) {
  46. MS_LOG(ERROR) << "Parse python code failed, errcode = " << parser->errcode();
  47. return nullptr;
  48. }
  49. return func_graph;
  50. }
  51. // if any mixed precision flag add a cast node after the parameter node.
  52. AnfNodePtr GetMixedPrecisionCastHelp(const FuncGraphPtr &func_graph, const AnfNodePtr &param) {
  53. TypePtr dst_type;
  54. if (func_graph->has_flag(GRAPH_FLAG_MIX_PRECISION_FP32)) {
  55. dst_type = kFloat32;
  56. } else if (func_graph->has_flag(GRAPH_FLAG_MIX_PRECISION_FP16)) {
  57. dst_type = kFloat16;
  58. } else {
  59. return param;
  60. }
  61. auto cast_helper = prim::GetPythonOps("_mp_cast_helper", "mindspore.ops.composite.base");
  62. auto cast = func_graph->NewCNode({NewValueNode(cast_helper), NewValueNode(dst_type), param});
  63. return cast;
  64. }
  65. FuncGraphWeakPtr Parser::top_func_graph_ = FuncGraphWeakPtr();
  66. Parser::Parser(const std::shared_ptr<ParseAst> &ast) : ast_(ast) {
  67. errcode_ = PARSE_SUCCESS;
  68. BuildMethodMap();
  69. }
  70. void Parser::BuildMethodMap() {
  71. stmt_method_map_["Return"] = &Parser::ParseReturn;
  72. stmt_method_map_["Expr"] = &Parser::ParseExpr;
  73. stmt_method_map_["If"] = &Parser::ParseIf;
  74. stmt_method_map_["Assign"] = &Parser::ParseAssign;
  75. stmt_method_map_["While"] = &Parser::ParseWhile;
  76. stmt_method_map_["For"] = &Parser::ParseFor;
  77. stmt_method_map_["FunctionDef"] = &Parser::ParseFunctionDef;
  78. stmt_method_map_["AugAssign"] = &Parser::ParseAugAssign;
  79. stmt_method_map_["Global"] = &Parser::ParseGlobal;
  80. expr_method_map_["NoneType"] = &Parser::ParseNone;
  81. expr_method_map_["BinOp"] = &Parser::ParseBinOp;
  82. expr_method_map_["Name"] = &Parser::ParseName;
  83. expr_method_map_["Num"] = &Parser::ParseNum;
  84. expr_method_map_["Str"] = &Parser::ParseStr;
  85. expr_method_map_["NameConstant"] = &Parser::ParseNameConstant;
  86. expr_method_map_["Call"] = &Parser::ParseCall;
  87. expr_method_map_["IfExp"] = &Parser::ParseIfExp;
  88. expr_method_map_["Attribute"] = &Parser::ParseAttribute;
  89. expr_method_map_["Compare"] = &Parser::ParseCompare;
  90. expr_method_map_["BoolOp"] = &Parser::ParseBoolOp;
  91. expr_method_map_["Lambda"] = &Parser::ParseLambda;
  92. expr_method_map_["Tuple"] = &Parser::ParseTuple;
  93. expr_method_map_["List"] = &Parser::ParseList;
  94. expr_method_map_["Subscript"] = &Parser::ParseSubscript;
  95. expr_method_map_["Slice"] = &Parser::ParseSlice;
  96. expr_method_map_["ExtSlice"] = &Parser::ParseExtSlice;
  97. expr_method_map_["Index"] = &Parser::ParseIndex;
  98. expr_method_map_["UnaryOp"] = &Parser::ParseUnaryOp;
  99. expr_method_map_["Dict"] = &Parser::ParseDict;
  100. expr_method_map_["Ellipsis"] = &Parser::ParseEllipsis;
  101. }
  102. void Parser::UpdateTopFuncGraph(const FuncGraphPtr &func_graph) { top_func_graph_ = FuncGraphWeakPtr(func_graph); }
  103. void Parser::InitParserEnvironment(const py::object &obj) {
  104. Parser::top_func_graph_ = FuncGraphWeakPtr();
  105. ScopeManager::GetInstance().ClearScope();
  106. (void)python_adapter::CallPyFn(PYTHON_MOD_PARSE_MODULE, PYTHON_PARSE_GENERATE_SCOPE, obj);
  107. }
  108. void Parser::CleanParserResource() {
  109. Parser::top_func_graph_ = FuncGraphWeakPtr();
  110. ScopeManager::GetInstance().ClearScope();
  111. }
  112. FuncGraphPtr Parser::ParseFuncGraph() {
  113. // get ast FunctionDef node
  114. py::object node = ast_->GetAstNode();
  115. FunctionBlockPtr pFnBlock = ParseFunction(node);
  116. if (errcode() != PARSE_SUCCESS) {
  117. MS_LOG(ERROR) << "Parse function error, code is " << errcode();
  118. return nullptr;
  119. }
  120. RemoveUnnecessaryPhis();
  121. MS_EXCEPTION_IF_NULL(pFnBlock);
  122. return pFnBlock->func_graph();
  123. }
  124. void Parser::GenerateArgsNodeForFunction(const FunctionBlockPtr &block, const py::object &fn_node) {
  125. py::object func_args = python_adapter::GetPyObjAttr(fn_node, "args");
  126. py::object var_arg_node = python_adapter::GetPyObjAttr(func_args, "vararg");
  127. block->func_graph()->set_has_vararg(!py::isinstance<py::none>(var_arg_node));
  128. py::object kw_arg_node = python_adapter::GetPyObjAttr(func_args, "kwarg");
  129. block->func_graph()->set_has_kwarg(!py::isinstance<py::none>(kw_arg_node));
  130. py::list kwonly_args = python_adapter::GetPyObjAttr(func_args, "kwonlyargs");
  131. block->func_graph()->set_kwonlyargs_count(SizeToInt(kwonly_args.size()));
  132. MS_EXCEPTION_IF_NULL(ast_);
  133. py::list args = ast_->GetArgs(fn_node);
  134. for (std::size_t i = 0; i < args.size(); i++) {
  135. std::string arg_name = py::cast<std::string>(args[i].attr("arg"));
  136. if (ast()->target_type() == PARSE_TARGET_OBJECT_INSTANCE) {
  137. if (arg_name == "self") {
  138. continue;
  139. }
  140. }
  141. TraceManager::DebugTrace(GetLocation(args[i]));
  142. auto para_node = std::make_shared<Parameter>(block->func_graph());
  143. MS_EXCEPTION_IF_NULL(para_node);
  144. TraceManager::EndTrace();
  145. para_node->set_name(arg_name);
  146. para_node->debug_info()->set_name(arg_name);
  147. block->func_graph()->add_parameter(para_node);
  148. AnfNodePtr para_after_cast = GetMixedPrecisionCastHelp(block->func_graph(), para_node);
  149. block->WriteVariable(arg_name, para_after_cast);
  150. MS_LOG(DEBUG) << "The arg[" << i << "] is " << arg_name;
  151. }
  152. }
  153. void Parser::GenerateArgsDefaultValueForFunction(const FunctionBlockPtr &block, const py::object &fn_node) {
  154. py::list defaults = ast_->GetArgsDefaultValues(fn_node);
  155. py::list args = ast_->GetArgs(fn_node);
  156. std::vector<std::string> namelist_for_default_value;
  157. std::vector<AnfNodePtr> default_values;
  158. for (std::size_t i = 0; i < args.size(); i++) {
  159. std::string arg_name = py::cast<std::string>(args[i].attr("arg"));
  160. if (ast()->target_type() == PARSE_TARGET_OBJECT_INSTANCE) {
  161. if (arg_name == "self") {
  162. continue;
  163. }
  164. }
  165. namelist_for_default_value.push_back(arg_name);
  166. if (py::isinstance<py::none>(defaults[i])) {
  167. default_values.push_back(NewValueNode(kNull));
  168. } else {
  169. default_values.push_back(ParseExprNode(block, defaults[i]));
  170. }
  171. }
  172. block->func_graph()->SetDefaultValues(namelist_for_default_value, default_values);
  173. }
  174. ScopePtr Parser::GetScopeForParseFunction() {
  175. ScopePtr scope = ScopeManager::GetInstance().GetCurrentScope();
  176. if (ast()->target_type() == PARSE_TARGET_OBJECT_INSTANCE) {
  177. py::object scope_str = python_adapter::CallPyFn(PYTHON_MOD_PARSE_MODULE, PYTHON_PARSE_GET_SCOPE_NAME, ast_->obj());
  178. if (!py::isinstance<py::none>(scope_str)) {
  179. auto scope_name = py::cast<std::string>(scope_str);
  180. scope = std::make_shared<Scope>(scope_name);
  181. }
  182. }
  183. return scope;
  184. }
  185. FunctionBlockPtr Parser::ParseFunction(const py::object &node, const FunctionBlockPtr &block) {
  186. ScopePtr scope = GetScopeForParseFunction();
  187. // the node created in the parsefunction context, will inherit the scope created using scope_guard
  188. ScopeGuard scope_guard(scope);
  189. TraceGuard trace_guard(data_converter::GetObjKey(ast()->obj())[0], GetLocation(node));
  190. FunctionBlockPtr pFunBlock = MakeFunctionBlock(*this);
  191. if (block != nullptr) {
  192. pFunBlock->AddPrevBlock(block);
  193. } else {
  194. func_graph_ = pFunBlock->func_graph();
  195. }
  196. pFunBlock->Mature();
  197. auto current_fg = pFunBlock->func_graph();
  198. auto function_name = py::cast<std::string>(python_adapter::GetPyObjAttr(node, "name"));
  199. MS_LOG(DEBUG) << "The function name is " << function_name;
  200. current_fg->debug_info()->set_name(function_name);
  201. MS_EXCEPTION_IF_NULL(ast_);
  202. py::list deco_list = node.attr("decorator_list");
  203. if (deco_list.size() > 0) {
  204. current_fg->debug_info()->set_deco_location(GetLocation(deco_list));
  205. }
  206. bool set_flag = ast_->UpdateFuncGraphFlags(current_fg);
  207. if (!set_flag) {
  208. MS_LOG(ERROR) << "Set flags failed";
  209. return nullptr;
  210. }
  211. GenerateArgsNodeForFunction(pFunBlock, node);
  212. // when parsing the top graph of construct, save the top graph
  213. if (GetTopFuncGraph() == nullptr) {
  214. UpdateTopFuncGraph(pFunBlock->func_graph());
  215. }
  216. // save the function node to block
  217. pFunBlock->WriteVariable(function_name, NewValueNode(current_fg));
  218. py::object funcObj = python_adapter::GetPyObjAttr(node, "body");
  219. (void)ParseStatements(pFunBlock, funcObj);
  220. if (current_fg->get_return() == nullptr) {
  221. MS_LOG(ERROR) << "Graph return node is null, loc:" << GetLocation(node)->ToString();
  222. errcode_ = PARSE_NO_RETURN;
  223. return pFunBlock;
  224. }
  225. GenerateArgsDefaultValueForFunction(pFunBlock, node);
  226. return pFunBlock;
  227. }
  228. FunctionBlockPtr Parser::ParseStatements(FunctionBlockPtr fn_block, const py::object &nodes) {
  229. py::int_ pcount = python_adapter::CallPyObjMethod(nodes, "__len__");
  230. size_t count = IntToSize(pcount);
  231. MS_LOG(DEBUG) << "The nodes count is " << count;
  232. for (size_t i = 0; i < count; i++) {
  233. auto node = py::cast<py::list>(nodes)[i];
  234. TraceManager::DebugTrace(GetLocation(node));
  235. fn_block = ParseStatement(fn_block, node);
  236. TraceManager::EndTrace();
  237. // insert appropriate depended items for the function block if it has a return node
  238. if (fn_block->func_graph()->get_return() != nullptr) {
  239. fn_block->InsertDependItemsBeforeReturn();
  240. }
  241. }
  242. return fn_block;
  243. }
  244. FunctionBlockPtr Parser::ParseStatement(const FunctionBlockPtr &block, const py::object &node) {
  245. auto node_type = ast_->GetNodeType(node);
  246. // check the node type
  247. AstMainType nodeType = node_type->main_type();
  248. if (nodeType != AST_MAIN_TYPE_STMT) {
  249. MS_LOG(INFO) << "Node type is error : " << nodeType;
  250. return block;
  251. }
  252. // call the process function
  253. std::string node_name = node_type->node_name();
  254. MS_LOG(DEBUG) << "Ast node is " << node_name;
  255. if (stmt_method_map_.count(node_name)) {
  256. TraceManager::DebugTrace(GetLocation(node));
  257. auto stmt_block = (this->*stmt_method_map_[node_name])(block, node);
  258. TraceManager::EndTrace();
  259. return stmt_block;
  260. } else {
  261. errcode_ = PARSE_NODE_METHOD_UNSUPPORTED;
  262. py::list location = ast_->CallParserObjMethod(PYTHON_PARSE_GET_LOCATION, node);
  263. if (location.size() < 2) {
  264. MS_LOG(EXCEPTION) << "List size should not be less than 2.";
  265. }
  266. auto filename = location[0].cast<std::string>();
  267. auto line_no = location[1].cast<int>();
  268. MS_LOG(EXCEPTION) << "Unsupported syntax '" << node_name << "' at " << filename << ":" << line_no;
  269. }
  270. }
  271. AnfNodePtr Parser::ParseExprNode(const FunctionBlockPtr &block, const py::object &node) {
  272. MS_LOG(DEBUG) << "Process ast expr";
  273. auto node_type = ast_->GetNodeType(node);
  274. // check the node type
  275. AstMainType node_main_type = node_type->main_type();
  276. if (node_main_type != AST_MAIN_TYPE_EXPR) {
  277. MS_LOG(ERROR) << "Node type is error : " << node_main_type;
  278. errcode_ = PARSE_NODE_TYPE_NO_MATCH;
  279. return nullptr;
  280. }
  281. // call the process function
  282. std::string node_name = node_type->node_name();
  283. MS_LOG(DEBUG) << "Ast node is " << node_name;
  284. if (expr_method_map_.count(node_name)) {
  285. TraceManager::DebugTrace(GetLocation(node));
  286. auto expr_node = (this->*expr_method_map_[node_name])(block, node);
  287. TraceManager::EndTrace();
  288. return expr_node;
  289. } else {
  290. errcode_ = PARSE_NODE_METHOD_UNSUPPORTED;
  291. py::list ret = ast_->CallParserObjMethod(PYTHON_PARSE_GET_LOCATION, node);
  292. auto filename = ret[0].cast<std::string>();
  293. auto line_no = ret[1].cast<int>();
  294. MS_LOG(EXCEPTION) << "Unsupported syntax '" << node_name << "' at " << filename << ":" << line_no;
  295. }
  296. }
  297. // process the expr statement and expand it
  298. // eg: x.append(y) -> x = x.append(y)
  299. FunctionBlockPtr Parser::ParseExpr(const FunctionBlockPtr &block, const py::object &node) {
  300. MS_LOG(DEBUG) << "Process ast Expr";
  301. // Expr only have value , no target
  302. py::tuple expand_info = ast_->CallParserObjMethod(PYTHON_PARSE_EXPAND_EXPR_STATEMENT, node);
  303. // refer python function expand_expr_statement, expand_info is one of the following:
  304. // True, expr.value, x
  305. // True, expr.value
  306. // False, None, None
  307. // check the expand info result
  308. auto is_expand = py::cast<bool>(expand_info[0]);
  309. if (is_expand) {
  310. // process the expr statement
  311. py::object value_object = expand_info[1];
  312. AnfNodePtr value_node = ParseExprNode(block, value_object);
  313. if (py::len(expand_info) == 2) {
  314. // add to depend list and insert before output
  315. block->AddAutoDepend(value_node);
  316. } else {
  317. // expand the assign statement
  318. py::object target_node = expand_info[2];
  319. WriteAssignVars(block, target_node, value_node);
  320. }
  321. }
  322. return block;
  323. }
  324. LocationPtr Parser::GetLocation(const py::object &node) const {
  325. MS_EXCEPTION_IF_NULL(ast_);
  326. py::list ret = ast_->CallParserObjMethod(PYTHON_PARSE_GET_LOCATION, node);
  327. if (ret.size() < 5) {
  328. MS_LOG(EXCEPTION) << "List size should not be less than 5.";
  329. }
  330. // refer to Location::Location() for each member of ret: line, column, line_end, column_end.
  331. auto location = std::make_shared<Location>(ret[0].cast<std::string>(), ret[1].cast<int>(), ret[2].cast<int>(),
  332. ret[3].cast<int>(), ret[4].cast<int>());
  333. return location;
  334. }
  335. void Parser::MakeConditionBlocks(const FunctionBlockPtr &pre_block, const FunctionBlockPtr &true_block,
  336. const FunctionBlockPtr &false_block) {
  337. true_block->AddPrevBlock(pre_block);
  338. true_block->Mature();
  339. false_block->AddPrevBlock(pre_block);
  340. false_block->Mature();
  341. }
  342. FunctionBlockPtr Parser::ParseReturn(const FunctionBlockPtr &block, const py::object &node) {
  343. MS_LOG(DEBUG) << "Process ast return";
  344. MS_EXCEPTION_IF_NULL(block);
  345. // create return valuenode
  346. AnfNodePtr pReturnValueNode = NewValueNode(prim::kPrimReturn);
  347. // parse the return Statements value
  348. py::object value = python_adapter::GetPyObjAttr(node, "value");
  349. AnfNodePtr pReturnStatementNode = ParseExprNode(block, value);
  350. // Create the cnode
  351. CNodePtr pReturnCNode = block->func_graph()->NewCNode({pReturnValueNode, pReturnStatementNode});
  352. block->func_graph()->set_return(pReturnCNode);
  353. return block;
  354. }
  355. // Process binary operators,eg: `a + b`, `a | b`, etc.
  356. AnfNodePtr Parser::ParseBinOp(const FunctionBlockPtr &block, const py::object &node) {
  357. MS_LOG(DEBUG) << "Process ast BinOP";
  358. py::object left = python_adapter::GetPyObjAttr(node, "left");
  359. py::object right = python_adapter::GetPyObjAttr(node, "right");
  360. py::object op = python_adapter::GetPyObjAttr(node, "op");
  361. // create left and right ANF node
  362. AnfNodePtr left_node = ParseExprNode(block, left);
  363. if (left_node == nullptr) {
  364. MS_LOG(WARNING) << "DoBinOp process left node failed: " << errcode();
  365. return nullptr;
  366. }
  367. AnfNodePtr right_node = ParseExprNode(block, right);
  368. if (right_node == nullptr) {
  369. MS_LOG(WARNING) << "DoBinOp process right node failed:" << errcode();
  370. return nullptr;
  371. }
  372. // resolve the op
  373. AnfNodePtr op_node = block->MakeResolveAstOp(op);
  374. // create apply node
  375. return block->func_graph()->NewCNode({op_node, left_node, right_node});
  376. }
  377. AnfNodePtr Parser::ParseName(const FunctionBlockPtr &block, const py::object &node) {
  378. MS_LOG(DEBUG) << "Process ast Name";
  379. auto name_id = py::cast<std::string>(python_adapter::GetPyObjAttr(node, "id"));
  380. MS_LOG(DEBUG) << "The Name id is " << name_id;
  381. TraceGuard trace_guard(GetLocation(node));
  382. if (block->IsGlobalVar(name_id)) {
  383. return block->MakeResolveSymbol(name_id);
  384. }
  385. return block->ReadVariable(name_id);
  386. }
  387. AnfNodePtr Parser::ParseNone(const FunctionBlockPtr &, const py::object &) {
  388. MS_LOG(DEBUG) << "Process ast NoneType";
  389. return NewValueNode(kNone);
  390. }
  391. AnfNodePtr Parser::ParseEllipsis(const FunctionBlockPtr &, const py::object &) {
  392. MS_LOG(DEBUG) << "Process ast Ellipsis";
  393. return NewValueNode(kEllipsis);
  394. }
  395. AnfNodePtr Parser::ParseNum(const FunctionBlockPtr &, const py::object &node) {
  396. MS_LOG(DEBUG) << "Process ast Num";
  397. py::object obj = python_adapter::GetPyObjAttr(node, "n");
  398. TraceGuard trace_guard(GetLocation(node));
  399. if (py::isinstance<py::int_>(obj)) {
  400. MS_LOG(INFO) << "The Num is int:" << (std::string)py::str(obj);
  401. auto data = py::cast<int>(obj);
  402. return NewValueNode(data);
  403. } else if (py::isinstance<py::float_>(obj)) {
  404. MS_LOG(INFO) << "The Num is float:" << (std::string)py::str(obj);
  405. auto data = py::cast<float>(obj);
  406. return NewValueNode(data);
  407. } else {
  408. // no else actually
  409. MS_LOG(ERROR) << "Unsupported Num type : " << (std::string)py::str(obj) << GetLocation(node)->ToString();
  410. errcode_ = PARSE_NODE_TYPE_UNKOWN;
  411. return nullptr;
  412. }
  413. }
  414. AnfNodePtr Parser::ParseStr(const FunctionBlockPtr &, const py::object &node) {
  415. MS_LOG(DEBUG) << "Process ast Str";
  416. auto str_s = py::cast<std::string>(python_adapter::GetPyObjAttr(node, "s"));
  417. return NewValueNode(str_s);
  418. }
  419. AnfNodePtr Parser::ParseNameConstant(const FunctionBlockPtr &, const py::object &node) {
  420. MS_LOG(DEBUG) << "Process ast NameConstant";
  421. py::object obj = python_adapter::GetPyObjAttr(node, "value");
  422. TraceGuard trace_guard(GetLocation(node));
  423. if (py::isinstance<py::bool_>(obj)) {
  424. MS_LOG(INFO) << "The NameConstant is bool:" << (std::string)py::str(obj);
  425. auto data = py::cast<bool>(obj);
  426. return NewValueNode(data);
  427. } else if (py::isinstance<py::none>(obj)) {
  428. MS_LOG(INFO) << "The NameConstant is none:" << (std::string)py::str(obj);
  429. return NewValueNode(kNone);
  430. } else {
  431. // no else actually
  432. MS_LOG(ERROR) << "Unsupported NameConstant type: " << (std::string)py::str(obj) << GetLocation(node)->ToString();
  433. errcode_ = PARSE_NODE_TYPE_UNKOWN;
  434. return nullptr;
  435. }
  436. }
  437. AnfNodePtr Parser::GenerateMakeTuple(const FunctionBlockPtr &block, const std::vector<AnfNodePtr> &element_nodes) {
  438. AnfNodePtr make_tuple_op = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKETUPLE);
  439. std::vector<AnfNodePtr> make_tuple_nodes;
  440. make_tuple_nodes.push_back(make_tuple_op);
  441. (void)std::transform(element_nodes.begin(), element_nodes.end(), std::back_inserter(make_tuple_nodes),
  442. [](AnfNodePtr arg) -> AnfNodePtr { return arg; });
  443. return block->func_graph()->NewCNode(make_tuple_nodes);
  444. }
  445. // process function call, eg : f1(x, y) ...
  446. AnfNodePtr Parser::ParseCall(const FunctionBlockPtr &block, const py::object &node) {
  447. MS_LOG(DEBUG) << "Process ast Call";
  448. // process function call
  449. py::object function_ast_node = python_adapter::GetPyObjAttr(node, "func");
  450. AnfNodePtr call_function_anf_node = ParseExprNode(block, function_ast_node);
  451. // function call arguments should be passed in as groups and unpacked later using unpack call
  452. py::list args = python_adapter::GetPyObjAttr(node, "args");
  453. std::vector<AnfNodePtr> packed_arguments;
  454. std::vector<AnfNodePtr> group_arguments;
  455. bool need_unpack_args = ParseArgsInCall(block, args, &packed_arguments, &group_arguments);
  456. bool need_unpack_keywords = ParseKeywordsInCall(block, node, &packed_arguments);
  457. // if there is stared or keyword argument, unpack may be needed
  458. bool need_unpack = need_unpack_args || need_unpack_keywords;
  459. return GenerateAnfNodeForCall(block, call_function_anf_node, packed_arguments, group_arguments, need_unpack);
  460. }
  461. AnfNodePtr Parser::GenerateAnfNodeForCall(const FunctionBlockPtr &block, const AnfNodePtr &call_function_anf_node,
  462. const std::vector<AnfNodePtr> &packed_arguments,
  463. const std::vector<AnfNodePtr> &group_arguments, bool need_unpack) const {
  464. // if there is keyword arguments or starred, using an unpack_call op to unpack the argument
  465. if (need_unpack) {
  466. std::vector<AnfNodePtr> unpack_call_nodes;
  467. auto unpack_call_op = NewValueNode(std::make_shared<prim::UnpackCall>(NAMED_METAGRAPH_UNPACKCALL));
  468. unpack_call_nodes.push_back(unpack_call_op);
  469. unpack_call_nodes.push_back(call_function_anf_node);
  470. (void)std::transform(packed_arguments.begin(), packed_arguments.end(), std::back_inserter(unpack_call_nodes),
  471. [](AnfNodePtr node) -> AnfNodePtr { return node; });
  472. CNodePtr unpack_call = block->func_graph()->NewCNode(unpack_call_nodes);
  473. return unpack_call;
  474. }
  475. // else there is no keyword arguments and starred, parsed as normal arguments without unpack
  476. std::vector<AnfNodePtr> func_call_nodes;
  477. func_call_nodes.push_back(call_function_anf_node);
  478. (void)std::transform(group_arguments.begin(), group_arguments.end(), std::back_inserter(func_call_nodes),
  479. [](AnfNodePtr node) -> AnfNodePtr { return node; });
  480. CNodePtr call_anf_node = block->func_graph()->NewCNode(func_call_nodes);
  481. return call_anf_node;
  482. }
  483. bool Parser::ParseArgsInCall(const FunctionBlockPtr &block, const py::list &args,
  484. std::vector<AnfNodePtr> *packed_arguments, std::vector<AnfNodePtr> *group_arguments) {
  485. bool need_unpack = false;
  486. for (size_t i = 0; i < args.size(); i++) {
  487. auto arg_node = AstSubType(py::cast<int32_t>(ast_->CallParserObjMethod(PYTHON_PARSE_GET_AST_TYPE, args[i])));
  488. if (arg_node == AST_SUB_TYPE_STARRED) {
  489. if (!group_arguments->empty()) {
  490. packed_arguments->push_back(GenerateMakeTuple(block, *group_arguments));
  491. }
  492. packed_arguments->push_back(ParseExprNode(block, python_adapter::GetPyObjAttr(args[i], "value")));
  493. group_arguments->clear();
  494. need_unpack = true;
  495. } else {
  496. group_arguments->push_back(ParseExprNode(block, args[i]));
  497. }
  498. }
  499. if (!group_arguments->empty()) {
  500. packed_arguments->push_back(GenerateMakeTuple(block, *group_arguments));
  501. }
  502. return need_unpack;
  503. }
  504. bool Parser::ParseKeywordsInCall(const FunctionBlockPtr &block, const py::object &node,
  505. std::vector<AnfNodePtr> *packed_arguments) {
  506. bool need_unpack = false;
  507. py::list keywords = python_adapter::GetPyObjAttr(node, "keywords");
  508. if (!keywords.empty()) {
  509. need_unpack = true;
  510. std::vector<AnfNodePtr> keys;
  511. std::vector<AnfNodePtr> values;
  512. for (size_t index = 0; index < keywords.size(); index++) {
  513. auto kw_key = python_adapter::GetPyObjAttr(keywords[index], "arg");
  514. auto kw_value = python_adapter::GetPyObjAttr(keywords[index], "value");
  515. if (py::isinstance<py::none>(kw_key)) {
  516. packed_arguments->push_back(ParseExprNode(block, kw_value));
  517. } else {
  518. auto kw_key_c = kw_key.cast<std::string>();
  519. keys.push_back(NewValueNode(kw_key_c));
  520. values.push_back(ParseExprNode(block, kw_value));
  521. }
  522. }
  523. auto keys_tuple = GenerateMakeTuple(block, keys);
  524. auto values_tuple = GenerateMakeTuple(block, values);
  525. auto make_dict_op = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKEDICT);
  526. std::vector<AnfNodePtr> make_dict_nodes;
  527. make_dict_nodes.push_back(make_dict_op);
  528. make_dict_nodes.push_back(keys_tuple);
  529. make_dict_nodes.push_back(values_tuple);
  530. packed_arguments->push_back(block->func_graph()->NewCNode(make_dict_nodes));
  531. }
  532. return need_unpack;
  533. }
  534. // process call attributes of class type define, eg: x.y()
  535. AnfNodePtr Parser::ParseAttribute(const FunctionBlockPtr &block, const py::object &node) {
  536. MS_LOG(DEBUG) << "Process ast Attribute";
  537. // process class value,eg: self.xx
  538. if (ast()->target_type() == PARSE_TARGET_OBJECT_INSTANCE) {
  539. if (ast_->IsClassMember(node)) {
  540. std::string var_name = "self.";
  541. std::string attr_name = node.attr("attr").cast<std::string>();
  542. (void)var_name.append(attr_name);
  543. auto obj = ast()->obj().attr(attr_name.c_str());
  544. if (py::hasattr(ast()->obj(), attr_name.c_str()) &&
  545. (data_converter::IsCellInstance(obj) || py::hasattr(obj, PYTHON_PRIMITIVE_FLAG))) {
  546. return block->MakeResolveSymbol(var_name);
  547. } else {
  548. return block->ReadVariable(var_name);
  549. }
  550. }
  551. }
  552. // process the get attr
  553. // Use the Primitive replace the operation resolve node (getattr)
  554. // because the getattr will eventually be converted to Primitive node
  555. AnfNodePtr op_node = NewValueNode(prim::kPrimGetAttr);
  556. // process the attr body
  557. py::object value_body = python_adapter::GetPyObjAttr(node, "value");
  558. AnfNodePtr value_node = ParseExprNode(block, value_body);
  559. if (value_node == nullptr) {
  560. MS_LOG(WARNING) << "Parse attribute failed";
  561. return nullptr;
  562. }
  563. // process the node attr
  564. auto attr_str = python_adapter::GetPyObjAttr(node, "attr").cast<std::string>();
  565. MS_LOG(DEBUG) << "Attr = " << attr_str;
  566. TraceManager::DebugTrace(GetLocation(python_adapter::GetPyObjAttr(node, "attr")));
  567. AnfNodePtr attr_node = NewValueNode(attr_str);
  568. TraceManager::EndTrace();
  569. // create the apply node
  570. return block->func_graph()->NewCNode({op_node, value_node, attr_node});
  571. }
  572. // Process comparison expression : a == b. a > b etc.
  573. AnfNodePtr Parser::ParseCompare(const FunctionBlockPtr &block, const py::object &node) {
  574. MS_LOG(DEBUG) << "Process ast Compare";
  575. // for python comparison ,there may be if x>y>5 ,
  576. // which there is two ops , but we only support one now
  577. py::list ops = python_adapter::GetPyObjAttr(node, "ops");
  578. if (ops.size() > MAX_COMPARISON_OPS_SUPPORTED) {
  579. MS_LOG(ERROR) << "MindSpore does not support comparison with operators more than one now, ops size =" << ops.size();
  580. return nullptr;
  581. }
  582. py::object left = python_adapter::GetPyObjAttr(node, "left");
  583. py::list comparators = python_adapter::GetPyObjAttr(node, "comparators");
  584. AnfNodePtr left_node = ParseExprNode(block, left);
  585. AnfNodePtr right_node = ParseExprNode(block, comparators[0]);
  586. MS_EXCEPTION_IF_NULL(block);
  587. AnfNodePtr op_node = block->MakeResolveAstOp(ops[0]);
  588. return block->func_graph()->NewCNode({op_node, left_node, right_node});
  589. }
  590. AnfNodePtr Parser::ProcessBoolOpValueList(const FunctionBlockPtr &block, const py::list &value_list,
  591. const py::object &op) {
  592. // if there is only one bool op now
  593. if (value_list.size() == 1) {
  594. AnfNodePtr first_node = ParseExprNode(block, value_list[0]);
  595. return first_node;
  596. } else {
  597. py::object first = value_list[0];
  598. py::list rest;
  599. for (size_t i = 1; i < value_list.size(); i++) {
  600. rest.append(value_list[i]);
  601. }
  602. AnfNodePtr first_node = ParseExprNode(block, first);
  603. AnfNodePtr rest_node = ProcessBoolOpValueList(block, rest, op);
  604. auto op_node = block->MakeResolveAstOp(op);
  605. return block->func_graph()->NewCNode({op_node, first_node, rest_node});
  606. }
  607. }
  608. // Process comparison expression : a and b. a or b .
  609. AnfNodePtr Parser::ParseBoolOp(const FunctionBlockPtr &block, const py::object &node) {
  610. MS_LOG(DEBUG) << "Process ast BoolOp";
  611. py::object op_node = python_adapter::GetPyObjAttr(node, "op");
  612. py::list op_values = python_adapter::GetPyObjAttr(node, "values");
  613. return ProcessBoolOpValueList(block, op_values, op_node);
  614. }
  615. // Process a function def
  616. FunctionBlockPtr Parser::ParseFunctionDef(const FunctionBlockPtr &block, const py::object &node) {
  617. MS_LOG(DEBUG) << "Process ast FunctionDef";
  618. FunctionBlockPtr function_block = ParseFunction(node, block);
  619. MS_EXCEPTION_IF_NULL(function_block);
  620. // get function name
  621. py::str name = python_adapter::GetPyObjAttr(node, "name");
  622. std::string function_name = name;
  623. ValueNodePtr valuenode_graph = NewValueNode(function_block->func_graph());
  624. block->WriteVariable(function_name, valuenode_graph);
  625. return block;
  626. }
  627. // Process a lambda expression . like lambda x,y: x + y
  628. AnfNodePtr Parser::ParseLambda(const FunctionBlockPtr &block, const py::object &node) {
  629. MS_LOG(DEBUG) << "Process ast Lambda";
  630. FunctionBlockPtr func_block = MakeFunctionBlock(*this);
  631. func_block->AddPrevBlock(block);
  632. func_block->Mature();
  633. // get lambda args
  634. py::list args = ast_->GetArgs(node);
  635. for (std::size_t i = 0; i < args.size(); i++) {
  636. std::string arg = py::cast<std::string>(args[i].attr("arg"));
  637. TraceManager::DebugTrace(GetLocation(args[i]));
  638. auto para_node = std::make_shared<Parameter>(func_block->func_graph());
  639. TraceManager::EndTrace();
  640. para_node->debug_info()->set_name(arg);
  641. func_block->func_graph()->add_parameter(para_node);
  642. func_block->WriteVariable(arg, para_node);
  643. MS_LOG(DEBUG) << "The arg[" << i << "] is " << arg;
  644. }
  645. py::object body_node = python_adapter::GetPyObjAttr(node, "body");
  646. AnfNodePtr lambda_body_node = ParseExprNode(func_block, body_node);
  647. func_block->func_graph()->set_output(lambda_body_node);
  648. ValueNodePtr const_graph = NewValueNode(func_block->func_graph());
  649. return const_graph;
  650. }
  651. // process a tuple
  652. AnfNodePtr Parser::ParseTuple(const FunctionBlockPtr &block, const py::object &node) {
  653. MS_LOG(DEBUG) << "Process ast Tuple";
  654. MS_EXCEPTION_IF_NULL(block);
  655. py::tuple elts = python_adapter::GetPyObjAttr(node, "elts");
  656. if (elts.size() == 0) {
  657. auto empty_tuple = std::vector<ValuePtr>();
  658. return NewValueNode(std::make_shared<ValueTuple>(empty_tuple));
  659. }
  660. std::vector<AnfNodePtr> tuple_vec;
  661. AnfNodePtr make_tuple_op = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKETUPLE);
  662. tuple_vec.emplace_back(make_tuple_op);
  663. for (size_t i = 0; i < elts.size(); i++) {
  664. AnfNodePtr node_ptr = ParseExprNode(block, elts[i]);
  665. tuple_vec.emplace_back(node_ptr);
  666. }
  667. CNodePtr tuple_app = block->func_graph()->NewCNode(tuple_vec);
  668. return tuple_app;
  669. }
  670. // process a list
  671. AnfNodePtr Parser::ParseList(const FunctionBlockPtr &block, const py::object &node) {
  672. MS_LOG(DEBUG) << "Process ast List";
  673. MS_EXCEPTION_IF_NULL(block);
  674. py::tuple elts = python_adapter::GetPyObjAttr(node, "elts");
  675. if (elts.size() == 0) {
  676. auto empty_list = std::vector<ValuePtr>();
  677. return NewValueNode(std::make_shared<ValueList>(empty_list));
  678. }
  679. std::vector<AnfNodePtr> list_vec;
  680. AnfNodePtr make_list_op = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKELIST);
  681. list_vec.emplace_back(make_list_op);
  682. for (size_t i = 0; i < elts.size(); i++) {
  683. AnfNodePtr node_ptr = ParseExprNode(block, elts[i]);
  684. list_vec.emplace_back(node_ptr);
  685. }
  686. CNodePtr list_app = block->func_graph()->NewCNode(list_vec);
  687. return list_app;
  688. }
  689. // process a subscript, such as x[y] , node expressed as value[slice]
  690. AnfNodePtr Parser::ParseSubscript(const FunctionBlockPtr &block, const py::object &node) {
  691. MS_LOG(DEBUG) << "Process ast Subscript";
  692. MS_EXCEPTION_IF_NULL(block);
  693. AnfNodePtr op_getitem = block->MakeResolveOperation(NAMED_PRIMITIVE_GETITEM);
  694. py::object value_node = python_adapter::GetPyObjAttr(node, "value");
  695. py::object slice_node = python_adapter::GetPyObjAttr(node, "slice");
  696. AnfNodePtr value = ParseExprNode(block, value_node);
  697. AnfNodePtr slice = ParseExprNode(block, slice_node);
  698. return block->func_graph()->NewCNode({op_getitem, value, slice});
  699. }
  700. // process a slice, get the slice value
  701. AnfNodePtr Parser::ParseSlice(const FunctionBlockPtr &block, const py::object &node) {
  702. MS_LOG(DEBUG) << "Process ast Slice";
  703. MS_EXCEPTION_IF_NULL(block);
  704. AnfNodePtr op_makeslice = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKESLICE);
  705. py::object start = python_adapter::GetPyObjAttr(node, "lower");
  706. py::object stop = python_adapter::GetPyObjAttr(node, "upper");
  707. py::object step = python_adapter::GetPyObjAttr(node, "step");
  708. AnfNodePtr start_node = ParseExprNode(block, start);
  709. AnfNodePtr stop_node = ParseExprNode(block, stop);
  710. AnfNodePtr step_node = ParseExprNode(block, step);
  711. return block->func_graph()->NewCNode({op_makeslice, start_node, stop_node, step_node});
  712. }
  713. // process a extslice
  714. AnfNodePtr Parser::ParseExtSlice(const FunctionBlockPtr &block, const py::object &node) {
  715. MS_LOG(DEBUG) << "Process ast ExtSlice";
  716. MS_EXCEPTION_IF_NULL(block);
  717. AnfNodePtr make_tuple_op = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKETUPLE);
  718. py::tuple slice_tuple = python_adapter::GetPyObjAttr(node, "dims");
  719. std::vector<AnfNodePtr> node_vec;
  720. node_vec.emplace_back(make_tuple_op);
  721. for (size_t i = 0; i < slice_tuple.size(); i++) {
  722. AnfNodePtr node_ptr = ParseExprNode(block, slice_tuple[i]);
  723. node_vec.emplace_back(node_ptr);
  724. }
  725. CNodePtr tuple_conde = block->func_graph()->NewCNode(node_vec);
  726. return tuple_conde;
  727. }
  728. // process a index, get the index number
  729. AnfNodePtr Parser::ParseIndex(const FunctionBlockPtr &block, const py::object &node) {
  730. MS_LOG(DEBUG) << "Process ast Index";
  731. py::object value_node = python_adapter::GetPyObjAttr(node, "value");
  732. return ParseExprNode(block, value_node);
  733. }
  734. // process a UnaryOp, +a, -b
  735. AnfNodePtr Parser::ParseUnaryOp(const FunctionBlockPtr &block, const py::object &node) {
  736. MS_LOG(DEBUG) << "Process ast UnaryOp";
  737. py::object op = python_adapter::GetPyObjAttr(node, "op");
  738. MS_EXCEPTION_IF_NULL(block);
  739. // resolve the op
  740. AnfNodePtr op_node = block->MakeResolveAstOp(op);
  741. py::object operand = python_adapter::GetPyObjAttr(node, "operand");
  742. AnfNodePtr operand_node = ParseExprNode(block, operand);
  743. return block->func_graph()->NewCNode({op_node, operand_node});
  744. }
  745. // process a dict ast node expression
  746. AnfNodePtr Parser::ParseDict(const FunctionBlockPtr &block, const py::object &node) {
  747. MS_LOG(DEBUG) << "Process ast Dict";
  748. py::list keys = node.attr("keys");
  749. py::list values = node.attr("values");
  750. std::vector<AnfNodePtr> key_nodes;
  751. std::vector<AnfNodePtr> value_nodes;
  752. for (size_t i = 0; i < keys.size(); i++) {
  753. key_nodes.push_back(ParseExprNode(block, keys[i]));
  754. value_nodes.push_back(ParseExprNode(block, values[i]));
  755. }
  756. auto keys_tuple = GenerateMakeTuple(block, key_nodes);
  757. auto values_tuple = GenerateMakeTuple(block, value_nodes);
  758. MS_EXCEPTION_IF_NULL(block);
  759. auto make_dict_op = block->MakeResolveOperation(NAMED_PRIMITIVE_MAKEDICT);
  760. return block->func_graph()->NewCNode({make_dict_op, keys_tuple, values_tuple});
  761. }
  762. // process a augment assign such as a += b;
  763. FunctionBlockPtr Parser::ParseAugAssign(const FunctionBlockPtr &block, const py::object &node) {
  764. MS_LOG(DEBUG) << "Process ast AugAssign";
  765. py::object op = python_adapter::GetPyObjAttr(node, "op");
  766. MS_EXCEPTION_IF_NULL(block);
  767. // resolve the op
  768. AnfNodePtr op_node = block->MakeResolveAstOp(op);
  769. py::object target_node = python_adapter::GetPyObjAttr(node, "target");
  770. MS_EXCEPTION_IF_NULL(ast_);
  771. auto ast_type = AstSubType(py::cast<int32_t>(ast_->CallParserObjMethod(PYTHON_PARSE_GET_AST_TYPE, target_node)));
  772. AnfNodePtr read_node = nullptr;
  773. if (ast_type == AST_SUB_TYPE_NAME) {
  774. read_node = ParseName(block, target_node);
  775. } else if (ast_->IsClassMember(target_node)) {
  776. read_node = ParseAttribute(block, target_node);
  777. } else {
  778. MS_LOG(EXCEPTION) << "Not supported augassign";
  779. }
  780. if (read_node == nullptr) {
  781. MS_LOG(EXCEPTION) << "Can not get target node ";
  782. }
  783. py::object value = python_adapter::GetPyObjAttr(node, "value");
  784. AnfNodePtr value_node = ParseExprNode(block, value);
  785. CNodePtr augassign_app = block->func_graph()->NewCNode({op_node, read_node, value_node});
  786. WriteAssignVars(block, target_node, augassign_app);
  787. return block;
  788. }
  789. // process global declaration such as 'global x';
  790. FunctionBlockPtr Parser::ParseGlobal(const FunctionBlockPtr &block, const py::object &node) {
  791. MS_LOG(DEBUG) << "Process ast Global";
  792. MS_EXCEPTION_IF_NULL(block);
  793. py::list vars = python_adapter::GetPyObjAttr(node, "names");
  794. for (auto &item : vars) {
  795. block->AddGlobalVar(py::cast<std::string>(item));
  796. }
  797. return block;
  798. }
  799. // process a if statement
  800. FunctionBlockPtr Parser::ParseIf(const FunctionBlockPtr &block, const py::object &node) {
  801. MS_LOG(DEBUG) << "Process ast If";
  802. py::object test_node = python_adapter::GetPyObjAttr(node, "test");
  803. AnfNodePtr condition_node = ParseExprNode(block, test_node);
  804. MS_EXCEPTION_IF_NULL(block);
  805. CNodePtr bool_node = block->ForceToBoolNode(condition_node);
  806. TraceManager::DebugTrace(std::make_shared<TraceIfStmtTrueBranch>(block->func_graph()->debug_info()));
  807. FunctionBlockPtr true_block = MakeFunctionBlock(*this);
  808. TraceManager::EndTrace();
  809. TraceManager::DebugTrace(std::make_shared<TraceIfStmtFalseBranch>(block->func_graph()->debug_info()));
  810. FunctionBlockPtr false_block = MakeFunctionBlock(*this);
  811. TraceManager::EndTrace();
  812. MakeConditionBlocks(block, true_block, false_block);
  813. TraceManager::DebugTrace(std::make_shared<TraceIfStmtAfterBranch>(block->func_graph()->debug_info()));
  814. FunctionBlockPtr after_block = MakeFunctionBlock(*this);
  815. TraceManager::EndTrace();
  816. // process the if-true branch
  817. py::object bodyNode = python_adapter::GetPyObjAttr(node, "body");
  818. FunctionBlockPtr true_end = ParseStatements(true_block, bodyNode);
  819. // if the return_ is set ,it has its own continuation block
  820. if (true_end->func_graph()->get_return() == nullptr) {
  821. true_end->Jump(after_block, nullptr);
  822. }
  823. // process the orelse branch
  824. py::object orelseNode = python_adapter::GetPyObjAttr(node, "orelse");
  825. FunctionBlockPtr false_end = ParseStatements(false_block, orelseNode);
  826. // if the return_ is set ,it has its own continuation block
  827. if (false_end->func_graph()->get_return() == nullptr) {
  828. false_end->Jump(after_block, nullptr);
  829. }
  830. block->ConditionalJump(bool_node, true_block, false_block);
  831. after_block->Mature();
  832. return after_block;
  833. }
  834. FunctionBlockPtr Parser::ParseWhile(const FunctionBlockPtr &block, const py::object &node) {
  835. MS_LOG(DEBUG) << "Process ast While";
  836. MS_EXCEPTION_IF_NULL(block);
  837. MS_LOG(INFO) << "Parse while statement";
  838. TraceManager::DebugTrace(std::make_shared<TraceWhileHeader>(block->func_graph()->debug_info()));
  839. FunctionBlockPtr header_block = MakeFunctionBlock(*this);
  840. if (MsContext::GetInstance()->is_multi_graph_sink()) {
  841. header_block->func_graph()->set_flags(FUNC_GRAPH_FLAG_IGNORE_VALUES, true);
  842. }
  843. TraceManager::EndTrace();
  844. TraceManager::DebugTrace(std::make_shared<TraceWhileBody>(block->func_graph()->debug_info()));
  845. FunctionBlockPtr body_block = MakeFunctionBlock(*this);
  846. TraceManager::EndTrace();
  847. TraceManager::DebugTrace(std::make_shared<TraceWhileAfter>(block->func_graph()->debug_info()));
  848. FunctionBlockPtr after_block = MakeFunctionBlock(*this);
  849. TraceManager::EndTrace();
  850. body_block->AddPrevBlock(header_block);
  851. after_block->AddPrevBlock(header_block);
  852. block->Jump(header_block, nullptr);
  853. py::object test_node = python_adapter::GetPyObjAttr(node, "test");
  854. AnfNodePtr condition_node = ParseExprNode(header_block, test_node);
  855. body_block->Mature();
  856. header_block->ConditionalJump(condition_node, body_block, after_block);
  857. py::object body_node = python_adapter::GetPyObjAttr(node, "body");
  858. FunctionBlockPtr after_body = ParseStatements(body_block, body_node);
  859. if (after_body->func_graph()->get_return() == nullptr) {
  860. after_body->Jump(header_block, nullptr);
  861. }
  862. header_block->Mature();
  863. after_block->Mature();
  864. return after_block;
  865. }
  866. CNodePtr Parser::GenerateIteratorInFor(const FunctionBlockPtr &block, const py::object &node,
  867. const AnfNodePtr &op_iter) {
  868. py::object iter_node = python_adapter::GetPyObjAttr(node, "iter");
  869. AnfNodePtr iter_anf_node = ParseExprNode(block, iter_node);
  870. return block->func_graph()->NewCNode({op_iter, iter_anf_node});
  871. }
  872. CNodePtr Parser::GenerateCondInFor(const ParameterPtr &iter_param, const FunctionBlockPtr &header_block,
  873. const AnfNodePtr &op_hasnext) {
  874. MS_EXCEPTION_IF_NULL(header_block);
  875. return header_block->func_graph()->NewCNode({op_hasnext, iter_param});
  876. }
  877. FunctionBlockPtr Parser::GenerateBlockInFor(const TraceInfoPtr &trace_info) {
  878. TraceManager::DebugTrace(trace_info);
  879. FunctionBlockPtr body_block = MakeFunctionBlock(*this);
  880. TraceManager::EndTrace();
  881. return body_block;
  882. }
  883. // A for loop will generate 3 functions :the test, the body, and the continuation
  884. // for x in xs:
  885. // body
  886. // it compiled to be following statement
  887. // it = iter(xs)
  888. // while hastnext(it)
  889. // x, it = next(it)
  890. // body
  891. FunctionBlockPtr Parser::ParseFor(const FunctionBlockPtr &block, const py::object &node) {
  892. MS_LOG(DEBUG) << "Process ast For";
  893. MS_EXCEPTION_IF_NULL(block);
  894. AnfNodePtr op_iter = block->MakeResolveOperation(NAMED_PRIMITIVE_ITER);
  895. AnfNodePtr op_next = block->MakeResolveOperation(NAMED_PRIMITIVE_NEXT);
  896. AnfNodePtr op_getitem = block->MakeResolveOperation(NAMED_PRIMITIVE_GETITEM);
  897. AnfNodePtr op_hasnext = block->MakeResolveOperation(NAMED_PRIMITIVE_HASNEXT);
  898. // generate the iterator apply
  899. CNodePtr iter_apply = GenerateIteratorInFor(block, node, op_iter);
  900. MS_EXCEPTION_IF_NULL(iter_apply);
  901. FunctionBlockPtr header_block =
  902. GenerateBlockInFor(std::make_shared<TraceForHeader>(block->func_graph()->debug_info()));
  903. MS_EXCEPTION_IF_NULL(header_block);
  904. // generate the hasnext apply which is a condition
  905. ParameterPtr iter_param = header_block->func_graph()->add_parameter();
  906. CNodePtr cond_apply = GenerateCondInFor(iter_param, header_block, op_hasnext);
  907. // generate the body of the for statement
  908. FunctionBlockPtr body_block = GenerateBlockInFor(std::make_shared<TraceForBody>(block->func_graph()->debug_info()));
  909. MS_EXCEPTION_IF_NULL(body_block);
  910. body_block->AddPrevBlock(header_block);
  911. // generate the iterator next apply
  912. // process as following: `app = next(it); target = app[0]; it = app[1];`
  913. CNodePtr app = body_block->func_graph()->NewCNode({op_next, iter_param});
  914. CNodePtr target_app = body_block->func_graph()->NewCNode({op_getitem, app, NewValueNode(0)});
  915. py::object target_node = python_adapter::GetPyObjAttr(node, "target");
  916. auto name_id = py::cast<std::string>(python_adapter::GetPyObjAttr(target_node, "id"));
  917. target_app->debug_info()->set_name(name_id);
  918. CNodePtr iter2_app = body_block->func_graph()->NewCNode({op_getitem, app, NewValueNode(1)});
  919. body_block->WriteVariable(name_id, target_app);
  920. // link the variable name with the target
  921. auto it_info = std::make_shared<TraceIterator>(target_app->debug_info());
  922. iter_param->debug_info()->set_trace_info(it_info);
  923. iter2_app->debug_info()->set_trace_info(it_info);
  924. iter_apply->debug_info()->set_trace_info(it_info);
  925. TraceManager::DebugTrace(std::make_shared<TraceForAfter>(block->func_graph()->debug_info()));
  926. FunctionBlockPtr after_block = MakeFunctionBlock(*this);
  927. MS_EXCEPTION_IF_NULL(after_block);
  928. TraceManager::EndTrace();
  929. after_block->AddPrevBlock(header_block);
  930. block->Jump(header_block, iter_apply);
  931. body_block->Mature();
  932. header_block->ConditionalJump(cond_apply, body_block, after_block);
  933. py::object body_node = python_adapter::GetPyObjAttr(node, "body");
  934. FunctionBlockPtr after_body_block = ParseStatements(body_block, body_node);
  935. if (after_body_block->func_graph()->get_return() == nullptr) {
  936. after_body_block->Jump(header_block, iter2_app);
  937. }
  938. header_block->Mature();
  939. after_block->Mature();
  940. return after_block;
  941. }
  942. AnfNodePtr Parser::ParseIfExp(const FunctionBlockPtr &block, const py::object &node) {
  943. MS_LOG(DEBUG) << "Process ast IfExp";
  944. MS_EXCEPTION_IF_NULL(block);
  945. py::object test_node = python_adapter::GetPyObjAttr(node, "test");
  946. AnfNodePtr condition_node = ParseExprNode(block, test_node);
  947. CNodePtr bool_node = block->ForceToBoolNode(condition_node);
  948. TraceManager::DebugTrace(std::make_shared<TraceIfExpTrueBranch>(block->func_graph()->debug_info()));
  949. FunctionBlockPtr true_block = MakeFunctionBlock(*this);
  950. TraceManager::EndTrace();
  951. TraceManager::DebugTrace(std::make_shared<TraceIfExpFalseBranch>(block->func_graph()->debug_info()));
  952. FunctionBlockPtr false_block = MakeFunctionBlock(*this);
  953. TraceManager::EndTrace();
  954. MakeConditionBlocks(block, true_block, false_block);
  955. // process the if-true branch
  956. py::object bodyNode = python_adapter::GetPyObjAttr(node, "body");
  957. true_block->func_graph()->debug_info()->set_location(GetLocation(bodyNode));
  958. AnfNodePtr true_node = ParseExprNode(true_block, bodyNode);
  959. // process the orelse branch
  960. py::object orelseNode = python_adapter::GetPyObjAttr(node, "orelse");
  961. false_block->func_graph()->debug_info()->set_location(GetLocation(orelseNode));
  962. AnfNodePtr false_node = ParseExprNode(false_block, orelseNode);
  963. true_block->func_graph()->set_output(true_node);
  964. false_block->func_graph()->set_output(false_node);
  965. // Use the Primitive replace the operation resolve node (switch)
  966. // because the switch will eventually be converted to Primitive node
  967. CNodePtr switch_app =
  968. block->func_graph()->NewCNode({NewValueNode(prim::kPrimSwitch), bool_node, NewValueNode(true_block->func_graph()),
  969. NewValueNode(false_block->func_graph())});
  970. std::vector<AnfNodePtr> call_graph_nodes{switch_app};
  971. CNodePtr switch_app_call = block->func_graph()->NewCNode(call_graph_nodes);
  972. return switch_app_call;
  973. }
  974. void Parser::HandleAssignName(const FunctionBlockPtr &block, const py::object &targ, const AnfNodePtr &assigned_node) {
  975. MS_EXCEPTION_IF_NULL(block);
  976. MS_EXCEPTION_IF_NULL(assigned_node);
  977. py::str name = python_adapter::GetPyObjAttr(targ, "id");
  978. std::string name_id = name;
  979. assigned_node->debug_info()->set_name(name_id);
  980. // set the debug name of the constant graph
  981. if (IsValueNode<FuncGraph>(assigned_node)) {
  982. // the value should be graph
  983. auto fg = GetValueNode<FuncGraphPtr>(assigned_node);
  984. if (fg->debug_info()->name().empty()) {
  985. fg->debug_info()->set_name(name_id);
  986. }
  987. }
  988. block->WriteVariable(name_id, assigned_node);
  989. }
  990. void Parser::HandleAssignTuple(const FunctionBlockPtr &block, const py::object &targ, const AnfNodePtr &assigned_node) {
  991. MS_EXCEPTION_IF_NULL(block);
  992. AnfNodePtr op_getitem = block->MakeResolveOperation(NAMED_PRIMITIVE_GETITEM);
  993. py::list items = python_adapter::GetPyObjAttr(targ, "elts");
  994. for (size_t i = 0; i < items.size(); i++) {
  995. // Use the Primitive replace the operation resolve node (getitem)
  996. // because the getitem will eventually be converted to Primitive node
  997. CNodePtr item_apply = block->func_graph()->NewCNode({op_getitem, assigned_node, NewValueNode(static_cast<int>(i))});
  998. py::object elt = items[i];
  999. WriteAssignVars(block, elt, item_apply);
  1000. }
  1001. }
  1002. void Parser::HandleAssignClassMember(const FunctionBlockPtr &block, const py::object &targ,
  1003. const AnfNodePtr &assigned_node) {
  1004. // Now only support the self.xx = xxxxx, can't support x.y = xxxx
  1005. AnfNodePtr target_node = ParseExprNode(block, targ);
  1006. MS_EXCEPTION_IF_NULL(target_node);
  1007. std::string var_name = "self.";
  1008. (void)var_name.append(targ.attr("attr").cast<std::string>());
  1009. MS_LOG(DEBUG) << "assign " << var_name;
  1010. MS_EXCEPTION_IF_NULL(block);
  1011. block->WriteVariable(var_name, assigned_node);
  1012. MS_LOG(DEBUG) << "SetState write " << var_name << " : " << target_node->ToString();
  1013. block->SetStateAssgin(target_node, var_name);
  1014. }
  1015. void Parser::HandleAssignSubscript(const FunctionBlockPtr &block, const py::object &targ,
  1016. const AnfNodePtr &assigned_node) {
  1017. MS_EXCEPTION_IF_NULL(block);
  1018. AnfNodePtr op_setitem = block->MakeResolveOperation(NAMED_PRIMITIVE_SETITEM);
  1019. py::object value_obj = python_adapter::GetPyObjAttr(targ, "value");
  1020. py::object slice_obj = python_adapter::GetPyObjAttr(targ, "slice");
  1021. AnfNodePtr value_node = ParseExprNode(block, value_obj);
  1022. AnfNodePtr slice_node = ParseExprNode(block, slice_obj);
  1023. CNodePtr setitem_app = block->func_graph()->NewCNode({op_setitem, value_node, slice_node, assigned_node});
  1024. // getitem apply should return the sequence data structure itself
  1025. std::string var_name = "";
  1026. if (ast_->IsClassMember(value_obj)) {
  1027. var_name = "self.";
  1028. (void)var_name.append(value_obj.attr("attr").cast<std::string>());
  1029. } else {
  1030. var_name = value_obj.attr("id").cast<std::string>();
  1031. }
  1032. block->WriteVariable(var_name, setitem_app);
  1033. }
  1034. void Parser::WriteAssignVars(const FunctionBlockPtr &block, const py::object &targ, const AnfNodePtr &value_node) {
  1035. MS_EXCEPTION_IF_NULL(value_node);
  1036. MS_LOG(DEBUG) << "Process WriteAssignVars";
  1037. auto ast_type = AstSubType(py::cast<int32_t>(ast_->CallParserObjMethod(PYTHON_PARSE_GET_AST_TYPE, targ)));
  1038. if (ast_type == AST_SUB_TYPE_NAME) {
  1039. HandleAssignName(block, targ, value_node);
  1040. } else if (ast_type == AST_SUB_TYPE_TUPLE) {
  1041. HandleAssignTuple(block, targ, value_node);
  1042. } else if (ast_type == AST_SUB_TYPE_SUBSCRIPT) {
  1043. HandleAssignSubscript(block, targ, value_node);
  1044. } else if (ast_->IsClassMember(targ)) {
  1045. HandleAssignClassMember(block, targ, value_node);
  1046. } else {
  1047. MS_LOG(EXCEPTION) << "Not supported assign type: " << ast_type
  1048. << " NodeInfo: " << trace::GetDebugInfo(value_node->debug_info());
  1049. }
  1050. }
  1051. // process a assign statement , such as a =b, a,b = tup
  1052. FunctionBlockPtr Parser::ParseAssign(const FunctionBlockPtr &block, const py::object &node) {
  1053. MS_LOG(DEBUG) << "Process ast assgin";
  1054. py::object value_object = python_adapter::GetPyObjAttr(node, "value");
  1055. AnfNodePtr value_node = ParseExprNode(block, value_object);
  1056. py::object targets_object = python_adapter::GetPyObjAttr(node, "targets");
  1057. py::int_ pcount = python_adapter::CallPyObjMethod(targets_object, "__len__");
  1058. size_t count = IntToSize(pcount);
  1059. MS_LOG(DEBUG) << "The nodes count is " << count;
  1060. for (size_t i = 0; i < count; i++) {
  1061. auto target_node = py::cast<py::list>(targets_object)[i];
  1062. WriteAssignVars(block, target_node, value_node);
  1063. }
  1064. return block;
  1065. }
  1066. void Parser::RemoveUnnecessaryPhis() {
  1067. // merge all removable phis to one map;
  1068. std::unordered_map<ParameterPtr, AnfNodePtr> removable_phis;
  1069. for (FunctionBlockPtr &block : func_block_list_) {
  1070. MS_EXCEPTION_IF_NULL(block);
  1071. removable_phis.insert(block->removable_phis().begin(), block->removable_phis().end());
  1072. }
  1073. if (removable_phis.size() == 0) {
  1074. return;
  1075. }
  1076. for (auto &node : DeepUsedGraphSearch(func_graph_->get_return())) {
  1077. if (node->isa<CNode>()) {
  1078. const auto &cnode = node->cast<CNodePtr>();
  1079. auto &inputs = cnode->inputs();
  1080. for (std::size_t i = 0; i < inputs.size(); i++) {
  1081. if (inputs[i]->isa<Parameter>()) {
  1082. const auto &inp = inputs[i]->cast<ParameterPtr>();
  1083. const auto &iter = removable_phis.find(inp);
  1084. if (iter == removable_phis.end()) {
  1085. continue;
  1086. }
  1087. auto &argNode = iter->second;
  1088. MS_LOG(DEBUG) << "graph " << cnode->func_graph()->ToString() << " replace phi " << inp->ToString() << " in "
  1089. << cnode->DebugString() << " with " << argNode->DebugString();
  1090. cnode->set_input(i, argNode);
  1091. }
  1092. }
  1093. }
  1094. }
  1095. }
  1096. // ParseAst class code
  1097. bool ParseAst::InitParseAstInfo(const std::string &python_mod_get_parse_method) {
  1098. // init the type
  1099. target_type_ = PARSE_TARGET_UNKNOW;
  1100. // call python parse, get the parser fn
  1101. module_ = python_adapter::GetPyModule(PYTHON_MOD_PARSE_MODULE);
  1102. py::object parse_method = python_adapter::GetPyObjAttr(obj_, PYTHON_EXTERN_PARSE_METHOD);
  1103. // get the obj type
  1104. auto type = data_converter::GetObjType(obj_);
  1105. if (type == RESOLVE_TYPE_FUNCTION) {
  1106. target_type_ = PARSE_TARGET_FUNCTION;
  1107. function_ = obj_;
  1108. } else if (type == RESOLVE_TYPE_METHOD) {
  1109. // process the method ,need get the method's self obj
  1110. target_type_ = PARSE_TARGET_METHOD;
  1111. py::object method_object = python_adapter::GetPyObjAttr(obj_, PYTHON_GET_METHOD_SELF_CLASS);
  1112. if (py::isinstance<py::none>(method_object)) {
  1113. MS_LOG(ERROR) << "Get method's self object instance failed.";
  1114. return false;
  1115. }
  1116. target_type_ = PARSE_TARGET_OBJECT_INSTANCE;
  1117. function_ = obj_;
  1118. obj_ = method_object;
  1119. } else if (type == RESOLVE_TYPE_CLASS_INSTANCE) {
  1120. // obj is class instance, get the method to parse.
  1121. function_ = python_adapter::CallPyModFn(module_, python_mod_get_parse_method, obj_, parse_method);
  1122. if (py::isinstance<py::none>(function_)) {
  1123. MS_LOG(ERROR) << "Get obj method function failed.";
  1124. return false;
  1125. }
  1126. target_type_ = PARSE_TARGET_OBJECT_INSTANCE;
  1127. // check the fn is method
  1128. auto obj_type = data_converter::GetObjType(function_);
  1129. if (obj_type != RESOLVE_TYPE_METHOD) {
  1130. MS_LOG(WARNING) << "Parse method function is invalid.";
  1131. return false;
  1132. }
  1133. } else {
  1134. MS_LOG(WARNING) << "Parse obj is invalid, only can parse function and obj, type = " << type;
  1135. return false;
  1136. }
  1137. // call python parse get ast tree
  1138. parser_ = python_adapter::CallPyModFn(module_, PYTHON_MOD_PARSE_OBJECT_FUNCTION, function_, parse_method);
  1139. ast_tree_ = python_adapter::CallPyObjMethod(parser_, "parse");
  1140. // get fn name and module
  1141. function_module_ = py::cast<std::string>(python_adapter::GetPyObjAttr(parser_, "function_module"));
  1142. function_name_ = py::cast<std::string>(python_adapter::GetPyObjAttr(parser_, "function_name"));
  1143. function_filename_ = py::cast<std::string>(python_adapter::GetPyObjAttr(parser_, "filename"));
  1144. function_line_offset_ = py::cast<int>(python_adapter::GetPyObjAttr(parser_, "line_offset"));
  1145. return true;
  1146. }
  1147. // Get ast tree node : is the tree bode list[0]
  1148. py::object ParseAst::GetAstNode() {
  1149. py::list tree_body = python_adapter::GetPyObjAttr(ast_tree_, "body");
  1150. py::object ast_node = tree_body[0];
  1151. return ast_node;
  1152. }
  1153. py::list ParseAst::GetArgs(const py::object &func_node) {
  1154. py::list ret = python_adapter::CallPyObjMethod(parser_, PYTHON_PARSE_GET_ARGS, func_node);
  1155. return ret;
  1156. }
  1157. py::list ParseAst::GetArgsDefaultValues(const py::object &func_node) {
  1158. py::list ret = python_adapter::CallPyObjMethod(parser_, PYTHON_PARSE_GET_ARGS_DEFAULT_VALUES, func_node);
  1159. return ret;
  1160. }
  1161. AstNodeTypePtr ParseAst::GetNodeType(const py::object &node) {
  1162. py::list list_value = python_adapter::CallPyObjMethod(parser_, PYTHON_PARSE_GET_NODE_TYPE, node);
  1163. if (list_value.size() < 2) {
  1164. MS_LOG(ERROR) << "The node of python method must has 2 values.";
  1165. return nullptr;
  1166. }
  1167. auto node_name = py::cast<std::string>(list_value[0]);
  1168. auto type = AstMainType(py::cast<int32_t>(list_value[1]));
  1169. return std::make_shared<AstNodeType>(node, node_name, type);
  1170. }
  1171. AstSubType ParseAst::GetOpType(const py::object &node) {
  1172. auto op_type = AstSubType(python_adapter::CallPyObjMethod(parser_, PYTHON_PARSE_GET_AST_TYPE, node).cast<int32_t>());
  1173. return op_type;
  1174. }
  1175. bool ParseAst::IsClassMember(const py::object &node) {
  1176. py::object ret = CallParseModFunction(PYTHON_MOD_PARSE_CHECK_IS_CLASS_MEMBER, node);
  1177. if (!py::isinstance<py::bool_>(ret)) {
  1178. MS_LOG(ERROR) << "The result of mod function parse, should be bool type.";
  1179. return false;
  1180. }
  1181. return ret.cast<bool>();
  1182. }
  1183. bool ParseAst::UpdateFuncGraphFlags(const FuncGraphPtr &func_graph) {
  1184. if (func_graph == nullptr) {
  1185. MS_LOG(ERROR) << "FuncGraph is null";
  1186. return false;
  1187. }
  1188. if (!py::hasattr(obj_, PYTHON_EXTERN_MINDSPORE_FLAG)) {
  1189. MS_LOG(DEBUG) << "No flags";
  1190. return true;
  1191. }
  1192. py::dict flags = python_adapter::GetPyObjAttr(obj_, PYTHON_EXTERN_MINDSPORE_FLAG);
  1193. for (auto &item : flags) {
  1194. if (!py::isinstance<py::str>(item.first) || !py::isinstance<py::bool_>(item.second)) {
  1195. MS_LOG(ERROR) << "Type error in flags dict convert";
  1196. return false;
  1197. }
  1198. auto name = py::cast<std::string>(item.first);
  1199. auto value = py::cast<bool>(item.second);
  1200. MS_LOG(DEBUG) << "Flag name: " << name << ". Value: " << value;
  1201. func_graph->set_flags(name, value);
  1202. }
  1203. return true;
  1204. }
  1205. } // namespace parse
  1206. } // namespace mindspore