def translate_to_statements(self, statements, conditional_write_vars): lines = [] for stmt in statements: if stmt.op == ':=' and not stmt.var in self.variables: self.temporary_vars.add((stmt.var, stmt.dtype)) line = self.translate_statement(stmt) if stmt.var in conditional_write_vars: subs = {} condvar = conditional_write_vars[stmt.var] lines.append('if %s:' % condvar) lines.append(indent(line)) else: lines.append(line) return lines
def exceptions(self): exc_list = [] for configuration in self.configurations: curconfig = [] for ft in self.feature_tests: sym, txt, exc, tb, runtime, prof_info = self.full_results[ configuration.name, ft.fullname()] if tb is not None: curconfig.append((ft.fullname(), tb)) if len(curconfig): exc_list.append((configuration.name, curconfig)) if len(exc_list) == 0: return '' r = '' s = 'Exceptions' r += s + '\n' + '-' * len(s) + '\n\n' for config_name, curconfig in exc_list: s = config_name r += s + '\n' + '^' * len(s) + '\n\n' for name, tb in curconfig: r += name + '::\n\n' + indent(tb) + '\n\n' return r
def _get_one_documentation(self, basename, link_targets): ''' Document a single category of preferences. ''' s = '' if not basename in self.pref_register: raise ValueError( 'No preferences under the name "%s" are registered' % basename) prefdefs, basedoc = self.pref_register[basename] s += deindent(basedoc, docstring=True).strip() + '\n\n' for name in sorted(prefdefs.keys()): pref = prefdefs[name] name = basename + '.' + name linkname = name.replace('_', '-').replace('.', '-') if link_targets: # Make a link target s += '.. _angela-pref-{name}:\n\n'.format(name=linkname) s += '``{name}`` = ``{default}``\n'.format( name=name, default=pref.representor(pref.default)) s += indent(deindent(pref.docs, docstring=True)) s += '\n\n' return s
def __str__(self): s = '' for k, v in list(self._templates.items()): s += k + ':\n' s += strip_empty_lines(indent(v)) + '\n' return s
def __str__(self): s = 'def %s(%s):\n%s\n return %s\n' % (self.name, ', '.join( self.args), indent(self.code), self.return_expr) return s
def vectorise_code(self, statements, variables, variable_indices, index='_idx'): created_vars = {stmt.var for stmt in statements if stmt.op == ':='} try: lines = [] used_variables = set() for statement in statements: lines.append('# Abstract code: {var} {op} {expr}'.format(var=statement.var, op=statement.op, expr=statement.expr)) # We treat every statement individually with its own read and write code # to be on the safe side read, write, indices, conditional_write_vars = self.arrays_helper([statement]) # We make sure that we only add code to `lines` after it went # through completely ufunc_lines = [] # No need to load a variable if it is only in read because of # the in-place operation if (statement.inplace and variable_indices[statement.var] != '_idx' and statement.var not in get_identifiers(statement.expr)): read = read - {statement.var} ufunc_lines.extend(self.read_arrays(read, write, indices, variables, variable_indices)) ufunc_lines.append(self.ufunc_at_vectorisation(statement, variables, variable_indices, conditional_write_vars, created_vars, used_variables, )) # Do not write back such values, the ufuncs have modified the # underlying array already if statement.inplace and variable_indices[statement.var] != '_idx': write = write - {statement.var} ufunc_lines.extend(self.write_arrays([statement], read, write, variables, variable_indices)) lines.extend(ufunc_lines) except VectorisationError: if self._use_ufunc_at_vectorisation: logger.info("Failed to vectorise code, falling back on Python loop: note that " "this will be very slow! Switch to another code generation target for " "best performance (e.g. cython). First line is: "+str(statements[0]), once=True) lines = [] lines.extend(['_full_idx = _idx', 'for _idx in _full_idx:', ' _vectorisation_idx = _idx' ]) read, write, indices, conditional_write_vars = self.arrays_helper(statements) lines.extend(indent(code) for code in self.read_arrays(read, write, indices, variables, variable_indices)) for statement in statements: line = self.translate_statement(statement) if statement.var in conditional_write_vars: lines.append(indent('if {}:'.format(conditional_write_vars[statement.var]))) lines.append(indent(line, 2)) else: lines.append(indent(line)) lines.extend(indent(code) for code in self.write_arrays(statements, read, write, variables, variable_indices)) return lines
:maxdepth: 1 :titlesonly: ''' for tutorial, _ in tutorials: text += ' ' + tutorial + '\n' text += ''' .. only:: html Interactive notebooks and files ------------------------------- ''' for tutorial, _ in tutorials: text += indent( deindent(''' .. |launchbinder{tutid}| image:: http://mybinder.org/badge.svg .. _launchbinder{tutid}: https://mybinder.org/v2/gh/angela-team/angela2-binder/master?filepath=tutorials/{tutorial}.ipynb '''.format(tutorial=tutorial, tutid=tutorial.replace('-', '')))) text += '\n' for tutorial, title in tutorials: text += ' * |launchbinder{tutid}|_ :download:`{title} <{tutorial}.ipynb>`\n'.format( title=title, tutorial=tutorial, tutid=tutorial.replace('-', '')) text += ''' .. _`Jupyter Notebooks`: http://jupyter-notebook-beginner-guide.readthedocs.org/en/latest/what_is_jupyter.html .. _`Jupyter`: http://jupyter.org/ .. _`Jupyter Notebook documentation`: http://jupyter.readthedocs.org/ .. [#] Formerly known as "IPython Notebooks". '''
def code_object(self, owner, name, abstract_code, variables, template_name, variable_indices, codeobj_class=None, template_kwds=None, override_conditional_write=None, compiler_kwds=None): if compiler_kwds is None: compiler_kwds = {} name = find_name(name) codeobj_class = self.code_object_class(codeobj_class) template = getattr(codeobj_class.templater, template_name) iterate_all = template.iterate_all generator = codeobj_class.generator_class( variables=variables, variable_indices=variable_indices, owner=owner, iterate_all=iterate_all, codeobj_class=codeobj_class, override_conditional_write=override_conditional_write, allows_scalar_write=template.allows_scalar_write, name=name, template_name=template_name) if template_kwds is None: template_kwds = dict() else: template_kwds = template_kwds.copy() logger.diagnostic('%s abstract code:\n%s' % (name, indent(code_representation(abstract_code)))) scalar_code, vector_code, kwds = generator.translate( abstract_code, dtype=prefs['core.default_float_dtype']) # Add the array names as keywords as well for varname, var in variables.items(): if isinstance(var, ArrayVariable): pointer_name = generator.get_array_name(var) if var.scalar: pointer_name += '[0]' template_kwds[varname] = pointer_name if hasattr(var, 'resize'): dyn_array_name = generator.get_array_name( var, access_data=False) template_kwds['_dynamic_' + varname] = dyn_array_name template_kwds.update(kwds) logger.diagnostic('%s snippet (scalar):\n%s' % (name, indent(code_representation(scalar_code)))) logger.diagnostic('%s snippet (vector):\n%s' % (name, indent(code_representation(vector_code)))) code = template(scalar_code, vector_code, owner=owner, variables=variables, codeobj_name=name, variable_indices=variable_indices, get_array_name=generator.get_array_name, **template_kwds) logger.diagnostic('%s code:\n%s' % (name, indent(code_representation(code)))) codeobj = codeobj_class(owner, code, variables, variable_indices, template_name=template_name, template_source=template.template_source, name=name, compiler_kwds=compiler_kwds) codeobj.compile() return codeobj
def create_runner_codeobj(group, code, template_name, run_namespace, user_code=None, variable_indices=None, name=None, check_units=True, needed_variables=None, additional_variables=None, template_kwds=None, override_conditional_write=None, codeobj_class=None): ''' Create a `CodeObject` for the execution of code in the context of a `Group`. Parameters ---------- group : `Group` The group where the code is to be run code : str or dict of str The code to be executed. template_name : str The name of the template to use for the code. run_namespace : dict-like An additional namespace that is used for variable lookup (either an explicitly defined namespace or one taken from the local context). user_code : str, optional The code that had been specified by the user before other code was added automatically. If not specified, will be assumed to be identical to ``code``. variable_indices : dict-like, optional A mapping from `Variable` objects to index names (strings). If none is given, uses the corresponding attribute of `group`. name : str, optional A name for this code object, will use ``group + '_codeobject*'`` if none is given. check_units : bool, optional Whether to check units in the statement. Defaults to ``True``. needed_variables: list of str, optional A list of variables that are neither present in the abstract code, nor in the ``USES_VARIABLES`` statement in the template. This is only rarely necessary, an example being a `StateMonitor` where the names of the variables are neither known to the template nor included in the abstract code statements. additional_variables : dict-like, optional A mapping of names to `Variable` objects, used in addition to the variables saved in `group`. template_kwds : dict, optional A dictionary of additional information that is passed to the template. override_conditional_write: list of str, optional A list of variable names which are used as conditions (e.g. for refractoriness) which should be ignored. codeobj_class : class, optional The `CodeObject` class to run code with. If not specified, defaults to the `group`'s ``codeobj_class`` attribute. ''' if name is None: if group is not None: name = '%s_%s_codeobject*' % (group.name, template_name) else: name = '%s_codeobject*' % template_name if user_code is None: user_code = code if isinstance(code, str): code = {None: code} user_code = {None: user_code} msg = 'Creating code object (group=%s, template name=%s) for abstract code:\n' % ( group.name, template_name) msg += indent(code_representation(code)) logger.diagnostic(msg) from angela2.devices import get_device device = get_device() if override_conditional_write is None: override_conditional_write = set([]) else: override_conditional_write = set(override_conditional_write) if codeobj_class is None: codeobj_class = device.code_object_class(group.codeobj_class) else: codeobj_class = device.code_object_class(codeobj_class) template = getattr(codeobj_class.templater, template_name) template_variables = getattr(template, 'variables', None) all_variables = dict(group.variables) if additional_variables is not None: all_variables.update(additional_variables) # Determine the identifiers that were used identifiers = set() user_identifiers = set() for v, u_v in zip(code.values(), user_code.values()): _, uk, u = analyse_identifiers(v, all_variables, recursive=True) identifiers |= uk | u _, uk, u = analyse_identifiers(u_v, all_variables, recursive=True) user_identifiers |= uk | u # Add variables that are not in the abstract code, nor specified in the # template but nevertheless necessary if needed_variables is None: needed_variables = [] # Resolve all variables (variables used in the code and variables needed by # the template) variables = group.resolve_all( identifiers | set(needed_variables) | set(template_variables), # template variables are not known to the user: user_identifiers=user_identifiers, additional_variables=additional_variables, run_namespace=run_namespace) # We raise this error only now, because there is some non-obvious code path # where Jinja tries to get a Synapse's "name" attribute via syn['name'], # which then triggers the use of the `group_get_indices` template which does # not exist for standalone. Putting the check for template == None here # means we will first raise an error about the unknown identifier which will # then make Jinja try syn.name if template is None: codeobj_class_name = codeobj_class.class_name or codeobj_class.__name__ raise AttributeError( ('"%s" does not provide a code generation ' 'template "%s"') % (codeobj_class_name, template_name)) conditional_write_variables = {} # Add all the "conditional write" variables for var in variables.values(): cond_write_var = getattr(var, 'conditional_write', None) if cond_write_var in override_conditional_write: continue if cond_write_var is not None: if (cond_write_var.name in variables and not variables[cond_write_var.name] is cond_write_var): logger.diagnostic(('Variable "%s" is needed for the ' 'conditional write mechanism of variable ' '"%s". Its name is already used for %r.') % (cond_write_var.name, var.name, variables[cond_write_var.name])) else: conditional_write_variables[ cond_write_var.name] = cond_write_var variables.update(conditional_write_variables) if check_units: for c in code.values(): # This is the first time that the code is parsed, catch errors try: check_units_statements(c, variables) except (SyntaxError, ValueError) as ex: error_msg = _error_msg(c, name) raise ValueError(error_msg) from ex all_variable_indices = copy.copy(group.variables.indices) if additional_variables is not None: all_variable_indices.update(additional_variables.indices) if variable_indices is not None: all_variable_indices.update(variable_indices) # Make "conditional write" variables use the same index as the variable # that depends on them for varname, var in variables.items(): cond_write_var = getattr(var, 'conditional_write', None) if cond_write_var is not None: all_variable_indices[ cond_write_var.name] = all_variable_indices[varname] # Check that all functions are available for varname, value in variables.items(): if isinstance(value, Function): try: value.implementations[codeobj_class] except KeyError as ex: # if we are dealing with numpy, add the default implementation from angela2.codegen.runtime.numpy_rt import NumpyCodeObject if codeobj_class is NumpyCodeObject: value.implementations.add_numpy_implementation( value.pyfunc) else: raise NotImplementedError( ('Cannot use function ' '%s: %s') % (varname, ex)) from ex # Gather the additional compiler arguments declared by function # implementations all_keywords = [ _gather_compiler_kwds(var, codeobj_class) for var in variables.values() if isinstance(var, Function) ] compiler_kwds = _merge_compiler_kwds(all_keywords) # Add the indices needed by the variables for varname in list(variables): var_index = all_variable_indices[varname] if not var_index in ('_idx', '0'): variables[var_index] = all_variables[var_index] return device.code_object( owner=group, name=name, abstract_code=code, variables=variables, template_name=template_name, variable_indices=all_variable_indices, template_kwds=template_kwds, codeobj_class=codeobj_class, override_conditional_write=override_conditional_write, compiler_kwds=compiler_kwds)