def visit_content_in_condition_control(self, node, level): if isinstance(node, ast.Expr): self.visit_Expr(node, level) elif isinstance(node, ast.Assert): self.visit_Assert(node, level) elif isinstance(node, ast.Assign): self.visit_Assign(node, level) elif isinstance(node, ast.AugAssign): self.visit_AugAssign(node, level) elif isinstance(node, ast.If): self.visit_If(node, level) elif isinstance(node, ast.For): self.visit_For(node, level) elif isinstance(node, ast.While): self.visit_While(node, level) elif isinstance(node, ast.Call): self.visit_Call(node, level) elif isinstance(node, ast.Raise): self.visit_Raise(node, level) elif isinstance(node, ast.Return): self.visit_Return(node, level) else: code = tools.ast2code(ast.fix_missing_locations(node)) raise errors.CodeError(f'BrainPy does not support {type(node)} ' f'in Numba backend.\n\n{code}')
def _analyze_cls_func(host, code, show_code, self_name=None, pop_self=True, **jit_setting): """Analyze the bounded function of one object. Parameters ---------- host : Base The data host. code : str The function source code. self_name : optional, str The class name, like "self", "cls". show_code : bool """ # arguments tree = ast.parse(code) if self_name is None: self_name = tree.body[0].args.args[0].arg # data assigned by self.xx in line right if self_name not in CLASS_KEYWORDS: raise errors.CodeError( f'BrainPy only support class keyword ' f'{CLASS_KEYWORDS}, but we got {self_name}.') if pop_self: tree.body[0].args.args.pop(0) # remove "self" etc. class argument # analyze function body r = _analyze_cls_func_body(host=host, self_name=self_name, code=code, tree=tree, show_code=show_code, has_func_def=True, **jit_setting) code, arguments, arg2call, nodes, code_scope = r return code, arguments, arg2call, nodes, code_scope
def visit_Delete(self, node): raise errors.CodeError( 'Do not support "del" operation in Numba backend.')
def visit_With(self, node): raise errors.CodeError('Do not support "with" block in Numba backend.')
def visit_Try(self, node): raise errors.CodeError( 'Do not support "try" handler in Numba backend.')
def visit_Call(self, node, level=0): if getattr(node, 'starargs', None) is not None: raise ValueError("Variable number of arguments not supported") if getattr(node, 'kwargs', None) is not None: raise ValueError("Keyword arguments not supported") if node in self.visited_calls: return node calls = self.visit_attr(node.func) calls = calls[::-1] # get the object and the function if calls[0] not in backend.CLASS_KEYWORDS: return node obj = self.host for data in calls[1:-1]: obj = getattr(obj, data) obj_func = getattr(obj, calls[-1]) # get function arguments args = [] for arg in node.args: args.append(tools.ast2code(ast.fix_missing_locations(arg))) kw_args = OrderedDict() for keyword in node.keywords: kw_args[keyword.arg] = tools.ast2code( ast.fix_missing_locations(keyword.value)) # TASK 1 : extract delay push and delay pull # ------ # Replace the delay function call to the delay_data # index. In such a way, delay function will be removed. # ------ if calls[-1] in ['push', 'pull'] and isinstance( obj, delays.ConstantDelay) and callable(obj_func): dvar4call = '.'.join(calls[0:-1]) uniform_delay = getattr(obj, 'uniform_delay') if calls[-1] == 'push': data_need_pass = [ f'{dvar4call}.delay_data', f'{dvar4call}.delay_in_idx' ] idx_or_val = kw_args['idx_or_val'] if len( args) == 0 else args[0] if len(args) + len(kw_args) == 1: rep_expression = f'{dvar4call}.delay_data[{dvar4call}.delay_in_idx] = {idx_or_val}' elif len(args) + len(kw_args) == 2: value = kw_args['value'] if len(args) <= 1 else args[1] if uniform_delay: rep_expression = f'{dvar4call}.delay_data[{dvar4call}.delay_in_idx, {idx_or_val}] = {value}' else: rep_expression = f'{dvar4call}.delay_data[{dvar4call}.delay_in_idx[{idx_or_val}], {idx_or_val}] = {value}' else: raise errors.CodeError( f'Cannot analyze the code: \n\n' f'{tools.ast2code(ast.fix_missing_locations(node))}') else: data_need_pass = [ f'{dvar4call}.delay_data', f'{dvar4call}.delay_out_idx' ] if len(args) + len(kw_args) == 0: rep_expression = f'{dvar4call}.delay_data[{dvar4call}.delay_out_idx]' elif len(args) + len(kw_args) == 1: idx = kw_args['idx'] if len(args) == 0 else args[0] if uniform_delay: rep_expression = f'{dvar4call}.delay_data[{dvar4call}.delay_out_idx, {idx}]' else: rep_expression = f'{dvar4call}.delay_data[{dvar4call}.delay_out_idx[{idx}], {idx}]' else: raise errors.CodeError( f'Cannot analyze the code: \n\n' f'{tools.ast2code(ast.fix_missing_locations(node))}') org_call = tools.ast2code(ast.fix_missing_locations(node)) self.visited_calls[node] = dict(type=calls[-1], org_call=org_call, rep_call=rep_expression, data_need_pass=data_need_pass) self.generic_visit(node)
def check_kws(parameters, keywords): for key, meaning in keywords.items(): if key in parameters: raise errors.CodeError(f'"{key}" is a keyword for ' f'numerical solvers in BrainPy, denoting ' f'"{meaning}". Please change another name.')