Skip to content

Commit

Permalink
Merge 894c121 into 1ebd801
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Stimberg committed Jan 16, 2014
2 parents 1ebd801 + 894c121 commit 23ab196
Show file tree
Hide file tree
Showing 63 changed files with 1,434 additions and 1,326 deletions.
107 changes: 2 additions & 105 deletions brian2/codegen/codeobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,94 +6,16 @@
import weakref

from brian2.core.functions import Function
from brian2.core.preferences import brian_prefs
from brian2.core.names import Nameable, find_name
from brian2.core.base import Updater
from brian2.core.names import Nameable
from brian2.utils.logger import get_logger

from .functions import add_numpy_implementation
from .translation import translate

__all__ = ['CodeObject',
'create_codeobject',
'CodeObjectUpdater',
]

logger = get_logger(__name__)


def prepare_namespace(namespace, variables, codeobj_class):
# We do the import here to avoid import problems
from .runtime.numpy_rt.numpy_rt import NumpyCodeObject

# Check that all functions are available
for name, value in namespace.iteritems():
if isinstance(value, Function):
try:
value.implementations[codeobj_class]
except KeyError as ex:
# if we are dealing with numpy, add the default implementation
if codeobj_class is NumpyCodeObject:
add_numpy_implementation(value, value.pyfunc)
else:
raise NotImplementedError(('Cannot use function '
'%s: %s') % (name, ex))

return namespace


def create_codeobject(owner, name, abstract_code, namespace, variables,
template_name, variable_indices, codeobj_class,
template_kwds=None):
'''
The following arguments keywords are passed to the template:
* code_lines coming from translation applied to abstract_code, a list
of lines of code, given to the template as ``code_lines`` keyword.
* ``template_kwds`` dict
* ``kwds`` coming from `translate` function overwrite those in
``template_kwds`` (but you should ensure there are no name
clashes.
'''

if template_kwds is None:
template_kwds = dict()
else:
template_kwds = template_kwds.copy()

template = getattr(codeobj_class.templater, template_name)


namespace = prepare_namespace(namespace, variables,
codeobj_class=codeobj_class)

if isinstance(abstract_code, dict):
for k, v in abstract_code.items():
logger.debug('%s abstract code key %s:\n%s' % (name, k, v))
else:
logger.debug(name + " abstract code:\n" + abstract_code)
iterate_all = template.iterate_all
snippet, kwds = translate(abstract_code, variables, namespace,
dtype=brian_prefs['core.default_scalar_dtype'],
codeobj_class=codeobj_class,
variable_indices=variable_indices,
iterate_all=iterate_all)
template_kwds.update(kwds)
logger.debug(name + " snippet:\n" + str(snippet))

name = find_name(name)

code = template(snippet,
owner=owner, variables=variables, codeobj_name=name, namespace=namespace,
variable_indices=variable_indices,
**template_kwds)
logger.debug(name + " code:\n" + str(code))

codeobj = codeobj_class(owner, code, namespace, variables, name=name)
codeobj.compile()
return codeobj


class CodeObject(Nameable):
'''
Executable code object.
Expand All @@ -113,28 +35,16 @@ class CodeObject(Nameable):
#: A short name for this type of `CodeObject`
class_name = None

def __init__(self, owner, code, namespace, variables, name='codeobject*'):
def __init__(self, owner, code, variables, name='codeobject*'):
Nameable.__init__(self, name=name)
try:
owner = weakref.proxy(owner)
except TypeError:
pass # if owner was already a weakproxy then this will be the error raised
self.owner = owner
self.code = code
self.namespace = namespace
self.variables = variables

self.variables_to_namespace()

def variables_to_namespace(self):
'''
Add the values from the variables dictionary to the namespace.
This should involve calling the `Variable.get_value` methods and
possibly take track of variables that need to be updated at every
timestep (see `update_namespace`).
'''
raise NotImplementedError()

def update_namespace(self):
'''
Update the namespace for this timestep. Should only deal with variables
Expand Down Expand Up @@ -172,17 +82,4 @@ def run(self):
defined during the call of `Language.code_object`.
'''
raise NotImplementedError()

def get_updater(self):
'''
Returns a `CodeObjectUpdater` that updates this `CodeObject`
'''
return CodeObjectUpdater(self)


class CodeObjectUpdater(Updater):
'''
Used to update ``CodeObject``.
'''
def run(self):
self.owner()
41 changes: 35 additions & 6 deletions brian2/codegen/languages/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,60 @@ class Language(object):

# Subclasses should override this
language_id = ''


def get_array_name(self, var, access_data=True):
'''
Get a globally unique name for a `ArrayVariable`.
Parameters
----------
var : `ArrayVariable`
The variable for which a name should be found.
access_data : bool, optional
For `DynamicArrayVariable` objects, specifying `True` here means the
name for the underlying data is returned. If specifying `False`,
the name of object itself is returned (e.g. to allow resizing).
Returns
-------
name : str
A uniqe name for `var`.
'''
# We have to do the import here to avoid circular import dependencies.
from brian2.devices.device import get_device
device = get_device()
return device.get_array_name(var, access_data=access_data)

def translate_expression(self, expr, namespace, codeobj_class):
'''
Translate the given expression string into a string in the target
language, returns a string.
'''
raise NotImplementedError

def translate_statement(self, statement, namespace, codeobj_class):
def translate_statement(self, statement, variables, codeobj_class):
'''
Translate a single line `Statement` into the target language, returns
a string.
'''
raise NotImplementedError

def translate_statement_sequence(self, statements, variables, namespace,
def translate_statement_sequence(self, statements, variables,
variable_indices, iterate_all,
codeobj_class):
'''
Translate a sequence of `Statement` into the target language, taking
care to declare variables, etc. if necessary.
Returns a pair ``(code_lines, kwds)`` where ``code`` is a list of the
lines of code in the inner loop, and ``kwds`` is a dictionary of values
that is made available to the template.
Returns a tuple ``(code_lines, array_names, dynamic_array_names, kwds)``
where ``code`` is list of the lines of code in the inner loop,
``array_names`` is a dictionary mapping variable names to the names of
the underlying array (or a pointer to this array in the case of C code),
``dynamic_array_names`` is a dictionary mapping ``_object``+variable
names to the corresponding dynamic array objects and ``kwds`` is a
dictionary of values that is made available to the template. Note that
the content of ``array_names`` will also be added to the template
keywords automatically. The same goes for ``dynamic_array_names`` but
note that the keys in this array start all with ``_object``.
'''
raise NotImplementedError

Expand Down
Loading

0 comments on commit 23ab196

Please sign in to comment.