Skip to content
Snippets Groups Projects
Commit 4dd92e28 authored by Dominic Kempf's avatar Dominic Kempf
Browse files

Add the work on preamble generation infrastructure

parent 7f573c27
No related branches found
No related tags found
No related merge requests found
""" This module provides the infrastructure for loopy preambles that have
a complex requirement structure. This includes:
* preambles triggering the creation of other preambles
* a caching mechanism to avoid duplicated preambles where harmful
"""
class UFL2LoopyDataCache(dict):
""" The cache data structure
The data is stored as key value pairs of the following form:
(function, cache_tuple) -> (code, priority_tag, preamble)
The parameters are:
function : the function that generates the preamble code snippet
cache_tuple : A frozen (sub)set of arguments to the function.
The map from function arguments to cache tuple controls
the amount of caching.
code : The code snippet to generate. No assumptions made.
priority_tag : Will later decide the ordering of the preambles.
preamble : A bool whether this cache entry does generate a loopy preamble.
This is usually not the case, when you generate someting
like symbol names. Those are inserted into other snippets,
but not on their own right.
"""
def __init__(self):
self.counter = 0
def register(self, cachekey, code, preamble):
self.counter = self.counter - 1
self[cachekey] = (code, self.counter, preamble)
def extract_preambles(self):
print self.values()
return [(p[1], p[0]) for p in self.values() if p[2]]
# have one such cache on the module level. It is easier than handing around an instance of it.
_cache = UFL2LoopyDataCache()
def generate_cache_tuple(*args):
""" A function that maps its arguments to a mutable tuple
This is used as the cache key generator for the default case
when caching is wanted invariably/
"""
from collections import Hashable, Iterable, MutableMapping
def freeze(data):
# Strings are iterable and hashable, but they do not pose any problems.
if isinstance(data, str):
return data
# Check if the given data is already hashable
if isinstance(data, Hashable):
if isinstance(data, Iterable):
return type(data)(freeze(i) for i in data)
return data
# convert standard mutable containers
if isinstance(data, MutableMapping):
return tuple((freeze(k), freeze(v)) for k,v in data.iteritems())
if isinstance(data, Iterable):
return tuple(freeze(i) for i in data)
# we don't know how to handle this object, so we give up
raise TypeError('Cannot freeze non-hashable object {} of type {}'.format(data, type(data)))
return freeze(args)
# We do also provide a shortcut for no caching at all.
no_caching = lambda *a : ()
# Data structure for a registered function to be used when decorating something
class RegisteredFunction(object):
""" The data structure for a function that generates a preambel """
def __init__(self, func,
cache_key_generator=generate_cache_tuple,
generate_preamble=True
):
self.func = func
self.cache_key_generator = cache_key_generator
self.generate_preamble = generate_preamble
# TODO: do we want this to contain kwargs?
def __call__(self, *args):
cache_key = (self.func, self.cache_key_generator(*args))
if cache_key in _cache:
if not self.generate_preamble:
return _cache[cache_key][0]
else:
code = self.func(*args)
_cache.register(cache_key, code, self.generate_preamble)
if not self.generate_preamble:
return code
# The decorator: it works both with and without (keyword!) arguments.
def dune_preambel(*args, **kwargs):
""" The decorator for a function that generates a preambel
Note that this may be used with or without arguments.
Possible keyword arguments:
---------------------------
cache_key_generator : function
A function that maps the arguments to the function to an immutable cache key.
Defaults to generate_cache_tuple.
"""
if args:
assert len(args)==1
return RegisteredFunction(args[0])
else:
return lambda f: RegisteredFunction(f, **kwargs)
def dune_symbol(*args, **kwargs):
""" The decorator for a function that generates a dune symbol name.
Note that this may be used with or without arguments.
Possible keyword arguments:
---------------------------
cache_key_generator : function
A function that maps the arguments to the function to an immutable cache key.
Defaults to generate_cache_tuple.
"""
if args:
assert len(args)==1
return RegisteredFunction(args[0], generate_preamble=False)
else:
assert "generate_preamble" not in kwargs
return lambda f: RegisteredFunction(f, generate_preamble=False, **kwargs)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment