from ...utility import visitation
import collections.abc
[docs]
class SourceRenderer(object):
HCOL = 39
INDENT = 2
WIDTH = 80
def __init__(self, istart=0):
'''
Renders the IR into source code.
Args:
istart:
The starting indentation level. This time ``indent`` gives the
starting column for each line.
Provided by the derived class:
HCOL:
The column at which to start side-by-side content.
INDENT:
The number of spaces to prefix for each indentation level.
WIDTH:
The ideal line length.
Returns:
A string of source code.
'''
self.istart = istart
[docs]
def renderLines(self, lines):
'''
Renders list-formatted code into a string.
The input is possibly-nested lists of strings or string pairs. The list
nestings correspond to indentation levels. Pairs are rendered as code
followed by a comment to the right.
'''
return self._addPrefix(self.format(lines))
@visitation.dispatch.on('arg')
def format(self, arg, level=-1):
'''
Formats one line or block of code, with the proper indentation. Long lines
are split.
'''
assert False
@format.when(str)
def format(self, line, level=-1):
prefix = ' ' * (self.INDENT * level)
yield prefix + line
@format.when(collections.abc.Iterable, no=(str, tuple))
def format(self, seq, level=-1):
if self.BLOCK_OPEN and level >= 0:
for line in self.format(self.BLOCK_OPEN, level):
yield line
for line in seq:
for rline in self.format(line, level+1):
yield rline
if self.BLOCK_CLOSE and level >= 0:
for line in self.format(self.BLOCK_CLOSE, level):
yield line
def _addPrefix(self, lines):
prefix = ' ' * (self.INDENT * self.istart)
if prefix:
return '\n'.join('%s%s' % (prefix, line) for line in lines)
else:
return '\n'.join(lines)
[docs]
def justify(self, seq, maximum=None):
width = max([len(x) for x in seq])
if maximum is None:
maximum = self.HCOL + 2 * self.INDENT + 1
return min(width, maximum)
[docs]
def prettylist(self, seq, level=0):
'''Formats a list as one element per line with leading commas.'''
it = iter(seq)
try:
v = next(it)
except StopIteration:
pass
else:
prefill = (2 * level + 1) * self.INDENT * ' '
fprefix = '{}%-{}s'.format(prefill, self.INDENT)
yield fprefix % ' ', v
commafill = fprefix % ','
for v in it:
yield commafill, v
[docs]
class ShSourceRenderer(SourceRenderer):
BLOCK_CLOSE = None
BLOCK_OPEN = None
COMMENT_STR = '#'
SOURCE_NAME = 'sh'
SH_RENDERER = ShSourceRenderer()
[docs]
class PySourceRenderer(SourceRenderer):
BLOCK_CLOSE = None
BLOCK_OPEN = None
COMMENT_STR = '#'
SOURCE_NAME = 'Python'
PY_RENDERER = PySourceRenderer()
[docs]
class CxxSourceRenderer(SourceRenderer):
BLOCK_CLOSE = '}'
BLOCK_OPEN = '{'
COMMENT_STR = '//'
HCOL = 20
SOURCE_NAME = 'C++'
CXX_RENDERER = CxxSourceRenderer()