<reponame>ncbray/pystream<filename>sandbox/streamRT/kernel.py<gh_stars>1-10
# Copyright 2011 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import absolute_import

import types

def shouldIterate(o, role):
	return isinstance(o, stream) and role != 'uniform'

class StreamMismatchError(Exception):
	pass

# Used to generated debug info if checkStreams fails.
def getLengths(args):
	lengths = []
	for arg in args:
		if isinstance(arg, stream):
			lengths.append(len(arg))
		else:
			lengths.append(None)
	return lengths

# Check for stream arguments.
# If there's more than one, check that they're the same length.
def checkStreams(args, config):
	streams = False
	length = 0

	for arg, role in zip(args, config.roles):
		if shouldIterate(arg, role):
			if not streams:
				length = len(arg)
				streams = True
			elif length != len(arg):
				lengths = getLengths(args)
				raise StreamMismatchError, "Kernel called with streams of different lengths: %s" % str(tuple(lengths))
	return streams




class UniformIterator(object):
	__slots__ = 'value'
	def __init__(self, value):
		self.value = value

	def __iter__(self):
		return self

	def next(self):
		return self.value

def getStreamIterator(o, role):
	if shouldIterate(o, role):
		return iter(o)
	else:
		return UniformIterator(o)

def argiterator(args, config):
	args = [getStreamIterator(arg, role) for arg, role in zip(args, config.roles)]
	while args:
		yield [it.next() for it in args]


class kernel(object):
	__slots__ = 'f', 'config'

	def __init__(self, f, config):
		self.f = f
		self.config = config

	def __call__(self, *args):
		if checkStreams(args, self.config):
			out = []
			for iterargs in argiterator(args, self.config):
				out.append(self.f(*iterargs))
			return stream(out)
		else:
			return self.f(*args)

	def __get__(self, instance, owner):
		return types.MethodType(self, instance, owner)

uniform = 'uniform'
default = 'default'


def getArgnames(f):
	code = f.func_code
	return code.co_varnames[:code.co_argcount]

class KernelConfiguration(object):
	__slots__ = 'unpack', 'roles'
	def __init__(self, unpack, roles):
		self.unpack = unpack
		self.roles  = roles



class KernelConfigAccumulator(object):
	__slots__ = '_roles', '_unpack'
	def __init__(self):
		self._roles = {}
		self._unpack = False

	@property
	def unpack(self):
		self._unpack = True

	def roles(self, **kargs):
		self._roles = kargs

	def __call__(self, f):
		assert hasattr(f, '__call__')
		return kernelcls(f, self.__createConfig(f))

	def __createConfig(self, f):
		argnames = getArgnames(f)

		roleList = []
		for name in argnames:
			if name in self._roles:
				roleList.append(self._roles[name])
			else:
				roleList.append(default)

		return KernelConfiguration(self._unpack, roleList)



class KernelDecorator(object):
	__slots__ = ()
	def roles(self, **kargs):
		accum = KernelConfigAccumulator()
		accum.roles(**kargs)
		return accum

	@property
	def unpack(self):
		accum = KernelConfigAccumulator()
		accum.unpack
		return accum

	def __call__(self, *args, **kargs):
		accum = KernelConfigAccumulator()

		if len(args) == 1 and len(kargs) == 0 and hasattr(args[0], '__call__'):
			# decorator called directly on function.
			return accum(args[0])
		elif len(args) == 0 and len(kargs) > 0:
			accum.roles(**kargs)
			return accum
		else:
			assert False

kerneldecorator = KernelDecorator()


# HACK
kernelcls = kernel
kernel = kerneldecorator

class stream(object):
	__slots__ = 'elements'
	def __init__(self, l=None):
		if l == None:
			self.elements = []
		else:
			assert isinstance(l, list)
			self.elements = l

	def __getitem__(self, key):
		return self.elements[key]

	def __len__(self):
		return len(self.elements)

	def __iter__(self):
		return iter(self.elements)

	# HACK?
	def append(self, value):
		self.elements.append(value)

	# Check writeability?
	def push(self, value):
		self.elements.append(value)

	@kernel
	def __add__(self, other):
		return self+other

	@kernel
	def __sub__(self, other):
		return self-other

	@kernel
	def __mul__(self, other):
		return self*other

	@kernel
	def __div__(self, other):
		return self/other

	@kernel
	def __floordiv__(self, other):
		return self//other

	@kernel
	def __mod__(self, other):
		return self%other

	@kernel
	def __divmod__(self, other):
		return divmod(self, other)


	@kernel
	def __pow__(self, other, modulo=None):
		if modulo == None:
			return self**other
		else:
			return pow(self, other, modulo)

	# Binary: lshift, rshift, and, or, xor
	#

	@kernel
	def __radd__(self, other):
		return other+self

	@kernel
	def __rsub__(self, other):
		return other-self

	@kernel
	def __rmul__(self, other):
		return other*self

	@kernel
	def __rdiv__(self, other):
		return other/self

# Copyright 2011 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import absolute_import

import types

def shouldIterate(o, role):
	return isinstance(o, stream) and role != 'uniform'

class StreamMismatchError(Exception):
	pass

# Used to generated debug info if checkStreams fails.
def getLengths(args):
	lengths = []
	for arg in args:
		if isinstance(arg, stream):
			lengths.append(len(arg))
		else:
			lengths.append(None)
	return lengths

# Check for stream arguments.
# If there's more than one, check that they're the same length.
def checkStreams(args, config):
	streams = False
	length = 0

	for arg, role in zip(args, config.roles):
		if shouldIterate(arg, role):
			if not streams:
				length = len(arg)
				streams = True
			elif length != len(arg):
				lengths = getLengths(args)
				raise StreamMismatchError, "Kernel called with streams of different lengths: %s" % str(tuple(lengths))
	return streams




class UniformIterator(object):
	__slots__ = 'value'
	def __init__(self, value):
		self.value = value

	def __iter__(self):
		return self

	def next(self):
		return self.value

def getStreamIterator(o, role):
	if shouldIterate(o, role):
		return iter(o)
	else:
		return UniformIterator(o)

def argiterator(args, config):
	args = [getStreamIterator(arg, role) for arg, role in zip(args, config.roles)]
	while args:
		yield [it.next() for it in args]


class kernel(object):
	__slots__ = 'f', 'config'

	def __init__(self, f, config):
		self.f = f
		self.config = config

	def __call__(self, *args):
		if checkStreams(args, self.config):
			out = []
			for iterargs in argiterator(args, self.config):
				out.append(self.f(*iterargs))
			return stream(out)
		else:
			return self.f(*args)

	def __get__(self, instance, owner):
		return types.MethodType(self, instance, owner)

uniform = 'uniform'
default = 'default'


def getArgnames(f):
	code = f.func_code
	return code.co_varnames[:code.co_argcount]

class KernelConfiguration(object):
	__slots__ = 'unpack', 'roles'
	def __init__(self, unpack, roles):
		self.unpack = unpack
		self.roles  = roles



class KernelConfigAccumulator(object):
	__slots__ = '_roles', '_unpack'
	def __init__(self):
		self._roles = {}
		self._unpack = False

	@property
	def unpack(self):
		self._unpack = True

	def roles(self, **kargs):
		self._roles = kargs

	def __call__(self, f):
		assert hasattr(f, '__call__')
		return kernelcls(f, self.__createConfig(f))

	def __createConfig(self, f):
		argnames = getArgnames(f)

		roleList = []
		for name in argnames:
			if name in self._roles:
				roleList.append(self._roles[name])
			else:
				roleList.append(default)

		return KernelConfiguration(self._unpack, roleList)



class KernelDecorator(object):
	__slots__ = ()
	def roles(self, **kargs):
		accum = KernelConfigAccumulator()
		accum.roles(**kargs)
		return accum

	@property
	def unpack(self):
		accum = KernelConfigAccumulator()
		accum.unpack
		return accum

	def __call__(self, *args, **kargs):
		accum = KernelConfigAccumulator()

		if len(args) == 1 and len(kargs) == 0 and hasattr(args[0], '__call__'):
			# decorator called directly on function.
			return accum(args[0])
		elif len(args) == 0 and len(kargs) > 0:
			accum.roles(**kargs)
			return accum
		else:
			assert False

kerneldecorator = KernelDecorator()


# HACK
kernelcls = kernel
kernel = kerneldecorator

class stream(object):
	__slots__ = 'elements'
	def __init__(self, l=None):
		if l == None:
			self.elements = []
		else:
			assert isinstance(l, list)
			self.elements = l

	def __getitem__(self, key):
		return self.elements[key]

	def __len__(self):
		return len(self.elements)

	def __iter__(self):
		return iter(self.elements)

	# HACK?
	def append(self, value):
		self.elements.append(value)

	# Check writeability?
	def push(self, value):
		self.elements.append(value)

	@kernel
	def __add__(self, other):
		return self+other

	@kernel
	def __sub__(self, other):
		return self-other

	@kernel
	def __mul__(self, other):
		return self*other

	@kernel
	def __div__(self, other):
		return self/other

	@kernel
	def __floordiv__(self, other):
		return self//other

	@kernel
	def __mod__(self, other):
		return self%other

	@kernel
	def __divmod__(self, other):
		return divmod(self, other)


	@kernel
	def __pow__(self, other, modulo=None):
		if modulo == None:
			return self**other
		else:
			return pow(self, other, modulo)

	# Binary: lshift, rshift, and, or, xor
	#

	@kernel
	def __radd__(self, other):
		return other+self

	@kernel
	def __rsub__(self, other):
		return other-self

	@kernel
	def __rmul__(self, other):
		return other*self

	@kernel
	def __rdiv__(self, other):
		return other/self
# Copyright 2011 <NAME> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # #     http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Used to generated debug info if checkStreams fails. # Check for stream arguments. # If there's more than one, check that they're the same length. # decorator called directly on function. # HACK # HACK? # Check writeability? # Binary: lshift, rshift, and, or, xor #