• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# This is the Python adaptation and derivative work of Myia (https://github.com/mila-iqia/myia/).
2#
3# Copyright 2020 Huawei Technologies Co., Ltd
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# ============================================================================
17"""The module of parser python object, called by c++."""
18
19import os
20import ast
21import hashlib
22import inspect
23import types
24from dataclasses import is_dataclass
25from textwrap import dedent
26
27import asttokens
28
29from mindspore import Tensor
30from mindspore import log as logger
31from mindspore import nn
32from mindspore import ops
33from mindspore.common.api import _MindsporeFunctionExecutor
34from mindspore.common.dtype import pytype_to_dtype
35from .namespace import CellNamespace, ClosureNamespace, ClassMemberNamespace
36from .resources import parse_object_map, convert_object_map, trope_ns, SYMBOL_UNDEFINE, NO_IMPLEMENT
37
38# define return value
39RET_SUCCESS = 0
40RET_FAILURE = 0xFF
41
42# define resolve type
43RESOLVE_TYPE_NONE = 0                   # resolve None
44RESOLVE_TYPE_FUNCTION = 1               # resolve function
45RESOLVE_TYPE_METHOD = 2                 # resolve class method
46RESOLVE_TYPE_CLASS_TYPE = 3             # resolve class type
47RESOLVE_TYPE_CLASS_INSTANCE = 4         # resolve the class instance of common class
48RESOLVE_TYPE_INVALID = 0xFF
49
50# define the class instance detail type
51# When the type is RESOLVE_TYPE_CLASS_INSTANCE
52CLASS_INSTANCE_TYPE_CELL = 0            # class instance type is Cell
53CLASS_INSTANCE_TYPE_PRIMITIVE = 1       # class instance type is Primitive
54CLASS_INSTANCE_TYPE_INVALID = 0xFF
55
56# Ast main type
57AST_MAIN_TYPE_STMT = 0                  # ast.Stmt
58AST_MAIN_TYPE_EXPR = 1                  # ast.Expr
59AST_MAIN_TYPE_SLICE = 2                 # ast.Slice
60AST_MAIN_TYPE_UNKNOWN = 0xFF            # unknown
61
62# Ast sub type
63AST_SUB_TYPE_AND = 3                   # ast.And
64AST_SUB_TYPE_OR = 4                    # ast.Or
65AST_SUB_TYPE_NAME = 5                  # ast.Name
66AST_SUB_TYPE_TUPLE = 6                 # ast.Tuple
67AST_SUB_TYPE_SUBSCRIPT = 7             # ast.Subscript
68AST_SUB_TYPE_STARRED = 8               # ast.Starred
69AST_SUB_TYPE_ATTRIBUTE = 9             # ast.Attribute
70AST_SUB_TYPE_UNKNOWN = 0xFF            # unknown
71
72# Process expr statement white list
73# add as needed, eg: "clear", "extend", "insert", "remove", "reverse"
74parse_expr_statement_white_list = (
75    "append",
76)
77
78_builtin_function_or_method_type = type(abs)
79
80
81def create_slice_obj(start, end, step):
82    """Create slice object"""
83    return slice(start, end, step)
84
85
86def parse_cb(func, parse_method=None):
87    """Implements the function of parse."""
88    return Parser(func, parse_method)
89
90
91def get_parse_method_of_class(obj, parse_method=None):
92    """
93    Het parse method of class.
94
95    Args:
96        obj(Object): Instance of class.
97        parse_method(str): Save the method name. Cell object has default method named 'construct'.
98
99    Returns:
100        Function, obj's method.
101    """
102    method = None
103    method_name = None
104    if parse_method is not None:
105        method_name = parse_method
106    elif isinstance(obj, nn.Cell):
107        if obj.enable_hook:
108            method_name = "_hook_construct"
109        else:
110            method_name = "construct"
111    if method_name is not None:
112        if hasattr(obj, method_name):
113            method = getattr(obj, method_name)
114    return method
115
116
117def get_bprop_method_of_class(obj, parse_method=None):
118    """
119    Get bprop method of class.
120
121    Args:
122        obj (Object): Instance of class.
123        parse_method(str): Save the method name. Cell object has default method named 'bprop'.
124
125    Returns:
126        Function, obj's method.
127    """
128    method = None
129    if isinstance(obj, nn.Cell):
130        method_name = "bprop"
131        if hasattr(obj, method_name):
132            method = getattr(obj, method_name)
133    return method
134
135# The fallback feature is enabled in default.
136# Not support change the flag during the process is alive.
137support_fallback_ = os.getenv('ENV_SUPPORT_FALLBACK')
138
139
140def resolve_symbol(namespace, symbol):
141    """
142    Resolve a symbol.
143
144    Note:
145        Can't get function when use closure function. So save the fn on namespace.
146
147    Args:
148        namespace (Object): Symbol's namespace.
149        symbol (str): Need resolve symbol.
150
151    Returns:
152        Object, resolve result of symbol.
153    """
154    # All exceptions need to be caught in this function
155    try:
156        resolve_ = namespace[symbol]
157
158        # list and dict is not hashable ,it can not be key for the map, just return the result
159        if isinstance(resolve_, (tuple, list, dict)):
160            return resolve_
161
162        # dataclass may not be hashable
163        if getattr(resolve_, "__hash__") is None:
164            return resolve_
165
166        # Raise a proper error if not using Fallback feature.
167        if support_fallback_ != '1':
168            # Raise NotImplementedError when parsing the numpy methods, but not the numpy constant.
169            if namespace.name == "numpy" and \
170                isinstance(resolve_, (types.FunctionType, types.MethodType, types.ModuleType)):
171                raise NotImplementedError("Mindspore does not support to use the numpy methods " \
172                                          "within the construct() or @ms_function decorated function in graph mode.")
173
174        # If need trope the obj
175        if resolve_ in convert_object_map:
176            resolve_ = convert_object_map.get(resolve_)
177            logger.debug("convert resolve = %r", resolve_)
178            if resolve_ == NO_IMPLEMENT:
179                raise NotImplementedError(f"Not support for `{symbol}`.")
180    except Exception as e:
181        if isinstance(e, NotImplementedError):
182            raise e
183        resolve_ = None
184        logger.debug("resolve exception occurred, value = %r", e)
185        logger.debug("resolve type is invalid, namespace = %s, symbol = %s",
186                     namespace.__str__(), symbol)
187
188    if isinstance(resolve_, _MindsporeFunctionExecutor):
189        logger.debug("resolve class _MindsporeFunctionExecutor, resolve fn instead.")
190        resolve_ = resolve_.fn
191    logger.debug(f'found: {symbol} in {namespace.__str__()}, resolve: {resolve_} / {type(resolve_)}')
192    return resolve_
193
194
195def generate_scope(obj):
196    """Generate the scope for every cell object in the network."""
197    if isinstance(obj, nn.Cell):
198        obj.generate_scope()
199
200
201def get_scope_name(obj):
202    """Returns the scope of a cell object in one network."""
203    if isinstance(obj, nn.Cell):
204        return obj.get_scope()
205    return None
206
207
208def get_object_key(obj):
209    """Return the function key: module + name."""
210    obj_key = ""
211    if hasattr(obj, "__name__"):
212        if hasattr(obj, "cell_init_args"):
213            obj_key = "%s_ID" % (str(obj.__class__.__name__) + str(obj.__name__) + obj.cell_init_args)
214        obj_id = "%s_ID%d" % (str(obj.__class__.__name__) + str(obj.__name__), id(obj))
215    else:
216        # `<class 'xxxxxxx'>`
217        # -> `xxxxxxx`
218        tag = str(obj.__class__)[8:-2]
219        if hasattr(obj, "cell_init_args"):
220            obj_key = "%s_ID" % (tag + obj.cell_init_args)
221        obj_id = "%s_ID%d" % (tag, id(obj))
222    logger.debug("obj_key %s obj_id = %s", obj_key, obj_id)
223
224    # method has same id of different instance
225    if isinstance(obj, types.MethodType):
226        method_instance = obj.__self__
227        instance_id = "%s_ID%d" % (str(method_instance.__class__.__name__), id(method_instance))
228        obj_id = instance_id + obj_id + str(obj.__hash__())
229    return obj_id, obj_key
230
231
232def is_class_member(node):
233    """Check the attr is class member variable."""
234    type_ = node.__class__.__name__
235    if type_ == "Attribute":
236        if not hasattr(node.value, "id"):
237            return False
238        id_ = node.value.id
239        if id_ == "self":
240            return True
241    return False
242
243
244def get_obj_id(obj):
245    """Get the obj id."""
246    return str(id(obj))
247
248
249def get_obj_type(obj):
250    """Get the obj type."""
251    logger.debug("Get object type: %r", obj)
252    obj_type = RESOLVE_TYPE_INVALID
253    if obj is None:
254        obj_type = RESOLVE_TYPE_NONE
255    elif isinstance(obj, types.FunctionType):
256        obj_type = RESOLVE_TYPE_FUNCTION
257    elif isinstance(obj, types.MethodType):
258        obj_type = RESOLVE_TYPE_METHOD
259    elif isinstance(obj, type):
260        obj_type = RESOLVE_TYPE_CLASS_TYPE
261    elif _is_class_instance(obj):
262        obj_type = RESOLVE_TYPE_CLASS_INSTANCE
263    else:
264        # here for ndarray, just print its shape (in case of the array to large and print many data in screen)
265        is_ndarray = type(obj).__name__ == 'ndarray' and hasattr(obj, 'shape')
266        raise TypeError(f'Not support for this object with type `{type(obj)}` and {"shape" if is_ndarray else "value"} '
267                        f'`{obj.shape if is_ndarray else obj}`.')
268    return obj_type
269
270
271def get_class_instance_type(obj):
272    """Get the class instance detail type."""
273    # check the obj type
274    logger.debug("Get the class type(%r)", obj)
275    class_type = CLASS_INSTANCE_TYPE_INVALID
276    if _is_class_instance(obj):
277        if isinstance(obj, nn.Cell):
278            class_type = CLASS_INSTANCE_TYPE_CELL
279        elif isinstance(obj, ops.Primitive):
280            class_type = CLASS_INSTANCE_TYPE_PRIMITIVE
281        # Add the other type base requirement
282    return class_type
283
284
285def _is_class_instance(obj):
286    """Confirm the obj is class instance."""
287    return isinstance(obj, (nn.Cell, ops.Primitive)) or _is_dataclass_instance(obj)
288
289
290def _is_dataclass_instance(obj):
291    """check whether a class is an instance of a dataclass (and not a dataclass itself)"""
292    return is_dataclass(obj) and not isinstance(obj, type)
293
294
295def _convert_tuple_to_args_kwargs(params):
296    args = tuple()
297    kwargs = dict()
298    for param in params:
299        if isinstance(param, dict):
300            kwargs.update(param)
301        else:
302            args += (param,)
303    return (args, kwargs)
304
305
306def is_supported_create_instance_type(cls_type):
307    return issubclass(cls_type, (nn.Cell, ops.Primitive))
308
309
310def create_instance(cls_type, params=None):
311    """Create python instance."""
312    if not isinstance(cls_type, type):
313        logger.warning(f"create_instance(), cls_type is not a type, cls_type: {cls_type}")
314        return None
315
316    # Check the type, now only support nn.Cell and Primitive.
317    obj = None
318    if is_supported_create_instance_type(cls_type):
319        # Check arguments, only support *args or **kwargs.
320        if params is None:
321            obj = cls_type()
322        elif isinstance(params, tuple):
323            args, kwargs = _convert_tuple_to_args_kwargs(params)
324            logger.debug(f"create_instance(), args: {args}, kwargs: {kwargs}")
325            if args and kwargs:
326                obj = cls_type(*args, **kwargs)
327            elif args:
328                obj = cls_type(*args)
329            elif kwargs:
330                obj = cls_type(**kwargs)
331        # If invalid parameters.
332        if obj is None:
333            raise ValueError(f"When call 'create_instance', the parameter should be *args or **kwargs, "
334                             f"but got {params.__class__.__name__}, params: {params}")
335    return obj
336
337
338def get_module_namespace(obj):
339    """Get the module's namespace."""
340    logger.debug("get module namespace, module = %r", obj)
341    mod_namespace = None
342    if isinstance(obj, types.ModuleType):
343        mod_namespace = CellNamespace(obj.__name__)
344    else:
345        logger.warning("Module(%r) is invalid, get namespace failure!", obj)
346    return mod_namespace
347
348
349def get_class_member_namespace_symbol(obj):
350    """Get obj class member type."""
351    logger.debug("get class instance namespace, object = %r", obj)
352    class_namespace = ClassMemberNamespace(obj)
353    logger.debug("class namesapce = %r", class_namespace)
354    return class_namespace
355
356
357def get_dataclass_attributes(cls):
358    """Get attributes of dataclass."""
359    fields = cls.__dataclass_fields__
360    attributes = {name: pytype_to_dtype(field.type)
361                  for name, field in fields.items()}
362    return attributes
363
364
365def get_dataclass_methods(cls):
366    """Get functions of dataclass."""
367    methods = {name: getattr(cls, name)
368               for name in dir(cls)
369               if isinstance(getattr(cls, name), (types.FunctionType,))}
370    return methods
371
372
373def convert_to_ms_tensor(data):
374    """Convert C++ tensor to mindspore tensor."""
375    return Tensor(data)
376
377
378def get_object_description(obj, fname, fline):
379    """return method or funcition description for error report, include location, class name, etc."""
380    if isinstance(obj, types.MethodType):
381        obj_cls = obj.__self__.__class__
382        class_name = f'{obj_cls.__module__}.{obj_cls.__qualname__}'
383        cls_fname = inspect.getfile(obj_cls)
384        _, cls_fline = inspect.getsourcelines(obj_cls)
385        class_loc = f'{cls_fname}:{cls_fline}'
386        return f"bound method '{obj.__name__}' at {fname}:{fline} of <{class_name} at {class_loc} object>"
387    if isinstance(obj, types.FunctionType):
388        return f"function '{obj.__name__}' at {fname}:{fline}"
389    if isinstance(obj, ast.FunctionDef):
390        return f"function '{obj.name}' at {fname}:{fline}"
391    if isinstance(obj, ast.Attribute):
392        return f"attribute "
393    return str(obj)
394
395
396def expand_expr_statement(node):
397    """
398    Process the expr statement and expand it.
399
400    Returns:
401        tuple, (True, expr.value, x)/(False, None, None).
402    """
403    if isinstance(node, ast.Expr):
404        expr_value = node.value
405        if isinstance(expr_value, ast.Call):
406            func = expr_value.func
407            if isinstance(func, ast.Attribute) and \
408                    hasattr(func, "attr") and \
409                    hasattr(func, "value"):
410                method = func.attr
411                target = func.value
412                if method in parse_expr_statement_white_list:
413                    logger.debug("Expand expr, target:%s, method:%s", target, method)
414                    return True, expr_value, target
415        if not isinstance(expr_value, ast.Str):
416            return True, expr_value
417    return (False,)
418
419
420def get_ast_namespace_symbol(obj):
421    """Get obj type and namespace and symbol."""
422    # step 1:get symbol from object map
423    ops_info = parse_object_map.get(type(obj), SYMBOL_UNDEFINE)
424    logger.debug("ops info = %r", ops_info)
425    return ops_info
426
427
428def get_operation_namespace_symbol(var: str):
429    """Get operation namespace and symbol."""
430    ops_info = (trope_ns, var)
431    logger.debug("get operation ops info = %r", ops_info)
432    return ops_info
433
434
435def get_ast_type(node):
436    """Get the ast type."""
437    ast_type = AST_SUB_TYPE_UNKNOWN
438    if isinstance(node, ast.And):
439        ast_type = AST_SUB_TYPE_AND
440    elif isinstance(node, ast.Or):
441        ast_type = AST_SUB_TYPE_OR
442    elif isinstance(node, ast.Name):
443        ast_type = AST_SUB_TYPE_NAME
444    elif isinstance(node, ast.Tuple):
445        ast_type = AST_SUB_TYPE_TUPLE
446    elif isinstance(node, ast.Subscript):
447        ast_type = AST_SUB_TYPE_SUBSCRIPT
448    elif isinstance(node, ast.Starred):
449        ast_type = AST_SUB_TYPE_STARRED
450    elif isinstance(node, ast.Attribute):
451        ast_type = AST_SUB_TYPE_ATTRIBUTE
452    else:
453        ast_type = AST_SUB_TYPE_UNKNOWN
454    return ast_type
455
456
457def get_node_type(node):
458    """Process an ast node."""
459    method_name = f'{node.__class__.__name__}'
460    node_type = [method_name]
461    # judge the ast main type
462    if isinstance(node, ast.stmt):
463        node_type.append(AST_MAIN_TYPE_STMT)
464    elif isinstance(node, (ast.expr, ast.slice)) or node is None:
465        # ast.slice and ast.expr should be expr
466        node_type.append(AST_MAIN_TYPE_EXPR)
467    else:
468        node_type.append(AST_MAIN_TYPE_UNKNOWN)
469    return node_type
470
471
472def get_args_default_values(node):
473    """get the args'default values of parse object."""
474    nondefaults = [None] * (len(node.args.args) - len(node.args.defaults))
475    defaults = nondefaults + node.args.defaults + node.args.kw_defaults
476    if node.args.vararg:
477        defaults.append(None)
478    if node.args.kwarg:
479        defaults.append(None)
480    return defaults
481
482
483def get_args(node):
484    """Get the arg of parse object."""
485    args = []
486    # process position args
487    for arg in node.args.args:
488        args.append(arg)
489
490    # process kwonlyargs: kwonlyargs is append after position args
491    if node.args.kwonlyargs:
492        for kwarg in node.args.kwonlyargs:
493            args.append(kwarg)
494    # process vararg: vararg is append after kwonlyargs
495    if node.args.vararg:
496        args.append(node.args.vararg)
497    # process kwarg: kwarg is append after vararg
498    if node.args.kwarg:
499        args.append(node.args.kwarg)
500    return args
501
502
503def eval_script(exp_str, params):
504    """Evaluate a python expression."""
505    if not isinstance(params, tuple):
506        raise ValueError(f"eval_script(), params is not a tuple, params: {params}")
507    if len(params) != 2:
508        raise ValueError(f"eval_script(), params tuple length is wrong, params: {params}")
509
510    logger.debug(f'exp_str: {exp_str}, params: {params}')
511    global_params = params[0]
512    local_params = params[1]
513    obj = eval(exp_str, global_params, local_params)
514    if obj is None:
515        raise ValueError(f"When call 'eval', the result is none. exp_str: '{exp_str}'")
516    return obj
517
518
519class Parser:
520    """
521    Parser python code to ast tree.
522
523    Args:
524        fn(FunctionType/MethodType): Need parse object instance.
525        parse_method(ExtendInfoOfParseObj): Extend information for parse the function.
526        ast_cache: Dictionary for caching ast tree.
527    """
528    ast_cache = {}
529
530    def __init__(self, fn: (types.FunctionType, types.MethodType), parse_method=None) -> None:
531        self.fn = fn
532        self.parse_method = parse_method
533        self.line_offset = 0
534        self.filename: str = inspect.getfile(inspect.unwrap(self.fn))
535
536        # Used to resolve mindspore builtin ops namespace.
537        self.ms_common_ns = CellNamespace('mindspore.common')
538        self.ms_ops_ns = CellNamespace('mindspore.ops')
539        self.ms_ops_c_ns = CellNamespace('mindspore.ops.composite')
540        self.ms_ops_c_multitype_ns = CellNamespace('mindspore.ops.composite.multitype_ops')
541        self.ms_ops_p_ns = CellNamespace('mindspore.ops.operations')
542        # Used to resolve the function's globals namespace.
543        self.global_namespace = CellNamespace(fn.__module__)
544        self.function_module = fn.__module__
545        # Used to resolve the function's nonlocals.
546        self.closure_namespace = ClosureNamespace(inspect.unwrap(self.fn))
547        self.function_name = fn.__name__
548        self.col_offset = 0
549
550    def parse(self):
551        """Parse the function or method."""
552        logger.debug("fn = %r", self.fn)
553        if isinstance(self.fn, (types.FunctionType, types.MethodType)):
554            try:
555                lines, self.line_offset = inspect.getsourcelines(self.fn)
556            except OSError as e:
557                if e.__str__() == "could not get source code":
558                    raise OSError(f"Mindspore can not compile temporary source code in terminal. "
559                                  f"Please write source code to a python file and run the file.")
560                raise e
561            original_src = ''.join(lines)
562            hexstr = hashlib.sha256(original_src.encode()).hexdigest()
563            ast_tokens = Parser.ast_cache.get(hexstr)
564            if not ast_tokens:
565                src = dedent(original_src)
566                self.col_offset = \
567                    len(original_src.split('\n')[0]) - len(src.split('\n')[0])
568                logger.debug("Get source = %s", src)
569                try:
570                    ast_tokens = asttokens.ASTTokens(src, parse=True)
571                except IndentationError as idt_err:
572                    idt_err.filename = self.filename
573                    idt_err.lineno = self.line_offset
574                    idt_err.msg = f"There are incorrect indentations in definition or comment of function: " \
575                                  f"'{self.fn.__qualname__}'."
576                    raise idt_err
577                Parser.ast_cache[hexstr] = ast_tokens
578            return ast_tokens, ast_tokens.tree
579
580        logger.error("Fn type is invalid")
581        return None, None
582
583    def is_unsupported_namespace(self, value):
584        unsupported = isinstance(value, _builtin_function_or_method_type) and value not in convert_object_map
585        logger.debug(f'`{value}` unsupported: {unsupported}.')
586        return unsupported
587
588    def get_namespace_symbol(self, var: str):
589        """Get symbol type and namespace and symbol."""
590        if var in self.closure_namespace:
591            logger.debug(f"Found `{var}` in closure_namespace {self.closure_namespace.__str__()}")
592            return self.closure_namespace, var
593        if var in self.global_namespace:
594            logger.debug(f"Found `{var}` in global_namespace {self.global_namespace.__str__()}")
595            value = self.global_namespace[var]
596            if self.is_unsupported_namespace(value):
597                error_info = f"The builtin function '{var}' of python is not supported in graph mode."
598                return None, var, error_info
599            return self.global_namespace, var
600
601        error_info = f"The symbol '{var}' is not defined in function '{self.function_name}'."
602        return None, var, error_info
603
604    def is_unsupported_builtin_type(self, value_type):
605        """To check if not supported builtin type"""
606        logger.debug(f'value_type: {value_type}, {type([])}, {type(())}.')
607        return value_type in (list, tuple)
608
609    def is_supported_namespace_module(self, value):
610        """To check if the module is allowed to support."""
611        # Check `mindspore` namespace.
612        if not hasattr(value, '__name__'):
613            logger.debug(f'`{str(value)}` has no `__name__` attribute.')
614            return True
615        name = value.__name__
616        if name == 'mindspore':
617            logger.debug(f'Found `{name}` in mindspore root namespace.')
618            return True
619
620        # Check `Tensor` namespace.
621        if value == Tensor:
622            logger.debug(f'Not support `{name}`.')
623            return False
624
625        # Check `builtins` namespace.
626        if hasattr(value, '__module__'):  # Not types.ModuleType
627            mod = value.__module__
628            if mod == 'builtins':
629                logger.debug(f'Found `{name}` in `builtins` namespace.')
630                return True
631
632        # We suppose it's supported if not a Module.
633        if not isinstance(value, types.ModuleType):
634            logger.debug(f'Found `{name}`, not a module.')
635            return True
636
637        # Check supported Module namespace.
638        rightmost_name = name.split('.')[-1]
639        if rightmost_name in self.ms_ops_ns:
640            logger.debug(f'Found `{name}`({rightmost_name}) in ops namespace: {str(self.ms_ops_ns)}.')
641            return True
642        if rightmost_name in self.ms_ops_c_ns:
643            logger.debug(f'Found `{name}`({rightmost_name}) in C namespace: {str(self.ms_ops_c_ns)}.')
644            return True
645        if rightmost_name in self.ms_ops_c_multitype_ns:
646            logger.debug(
647                f'Found `{name}`({rightmost_name}) in C.multitype namespace: {str(self.ms_ops_c_multitype_ns)}.')
648            return True
649        if rightmost_name in self.ms_ops_p_ns:
650            logger.debug(f'Found `{name}`({rightmost_name}) in P namespace: {str(self.ms_ops_p_ns)}.')
651            return True
652        if rightmost_name in self.ms_common_ns:
653            logger.debug(f'Found `{name}`({rightmost_name}) in P namespace: {str(self.ms_common_ns)}.')
654            return True
655        if rightmost_name in trope_ns:
656            logger.debug(f'Found `{name}`({rightmost_name}) in trope namespace: {str(trope_ns)}.')
657            return True
658
659        logger.error(f'Not found `{name}` in mindspore supported namespace.')
660        return False
661
662    def get_builtin_namespace_symbol(self, var: str):
663        """Get mindspore builtin namespace and symbol."""
664        if var in self.closure_namespace:
665            logger.debug(f"Found `{var}` in closure_namespace {self.closure_namespace.__str__()}.")
666            return self.closure_namespace, var
667        if var in self.global_namespace:
668            logger.debug(f"Found `{var}` in global_namespace {self.global_namespace.__str__()}.")
669            value = self.global_namespace[var]
670            value_str = value.__name__ if hasattr(value, '__name__') else str(value)
671            logger.debug(f"value: {type(value)}, `{value_str}`, hasattr(__name__): {hasattr(value, '__name__')}.")
672            # To check if allowed to support.
673            if self.is_unsupported_namespace(value):
674                return self.global_namespace, var, value
675            if self.is_unsupported_builtin_type(value):
676                return self.global_namespace, var, value
677            if not self.is_supported_namespace_module(value):  # Check if support including instance of types.ModuleType
678                return self.global_namespace, var, value
679            return self.global_namespace, var
680
681        error_info = f"The name '{var}' is not defined, or not supported in graph mode."
682        logger.debug(f'error info: {error_info}')
683        return None, var, error_info
684
685    def analyze_super(self, class_type_node, subclass_instance):
686        """Analyze super and return a class instance."""
687        sub_class = type(subclass_instance)
688        if class_type_node is None:
689            return super(sub_class, subclass_instance)
690        if isinstance(class_type_node, ast.Name):
691            class_name = getattr(class_type_node, 'id')
692        elif isinstance(class_type_node, ast.Attribute):
693            class_name = getattr(class_type_node, 'attr')
694        else:
695            raise ValueError(f"The first argument of 'super()' must be a class type, "
696                             f"but got {class_type_node.__class__.__name__}.")
697
698        target_father_class = None
699        for class_element in sub_class.mro():
700            if class_element.__name__ == class_name:
701                target_father_class = class_element
702                break
703        if target_father_class is None:
704            raise ValueError(f"The second argument of 'super()' must be 'self', "
705                             f"but got {subclass_instance}.")
706        return super(target_father_class, subclass_instance)
707
708    def get_location(self, node):
709        """
710        Get location of node start and end line no.
711
712        Args:
713            node: AST op node or tuple or List. This is a node in the ANF diagram,
714                  here is the code location to get this node.
715
716        Returns:
717            List, [fileName, linestart, colstart, lineend, colend].
718        """
719        ret = [self.filename]
720        err_exit = 0
721        if isinstance(node, (list, tuple)):
722            node_size = len(node)
723            if node_size == 0:
724                err_exit = 1
725            else:
726                start_node = node[0]
727                end_node = node[-1]
728        else:
729            start_node = node
730            end_node = node
731
732        if err_exit == 0:
733            if hasattr(start_node, "lineno") and \
734                    hasattr(end_node, "col_offset"):
735                start_lineno, start_colno = start_node.first_token.start
736                end_lineno, end_colno = end_node.last_token.end
737                start_lineno += self.line_offset - 1
738                start_colno += self.col_offset
739                end_lineno += self.line_offset - 1
740                end_colno += self.col_offset
741                ret = ret + [start_lineno, start_colno, end_lineno, end_colno]
742            else:
743                ret = ret + [0, 0, 0, 0]
744        return ret
745