Commit 4672b492 authored by Dylan Trotter's avatar Dylan Trotter

Add root accessor to Block and move access to ModuleBlock attrs to use root.

parent daa02fe6
......@@ -56,17 +56,9 @@ class Block(object):
__metaclass__ = abc.ABCMeta
# These are ModuleBlock attributes. Avoid pylint errors for accessing them on
# Block objects by defining them here.
_filename = None
_full_package_name = None
_buffer = None
_strings = None
imports = None
_future_features = None
def __init__(self, parent_block, name):
self.parent_block = parent_block
def __init__(self, parent, name):
self.root = parent.root if parent else self
self.parent = parent
self.name = name
self.free_temps = set()
self.used_temps = set()
......@@ -76,33 +68,6 @@ class Block(object):
self.loop_stack = []
self.is_generator = False
block = self
while block and not isinstance(block, ModuleBlock):
block = block.parent_block
self._module_block = block
@property
def full_package_name(self):
# pylint: disable=protected-access
return self._module_block._full_package_name
@property
def filename(self):
return self._module_block._filename # pylint: disable=protected-access
@property
def buffer(self):
return self._module_block._buffer # pylint: disable=protected-access
@property
def strings(self):
return self._module_block._strings # pylint: disable=protected-access
@property
def future_features(self):
# pylint: disable=protected-access
return self._module_block._future_features
@abc.abstractmethod
def bind_var(self, writer, name, value):
"""Writes Go statements for assigning value to named var in this block.
......@@ -153,10 +118,10 @@ class Block(object):
alias = None
if name == 'grumpy':
alias = 'πg'
if name in self._module_block.imports:
return self._module_block.imports[name]
if name in self.root.imports:
return self.root.imports[name]
package = Package(name, alias)
self._module_block.imports[name] = package
self.root.imports[name] = package
return package
def genlabel(self, is_checkpoint=False):
......@@ -197,7 +162,7 @@ class Block(object):
def intern(self, s):
if len(s) > 64 or _non_word_re.search(s):
return 'πg.NewStr({})'.format(util.go_str(s))
self.strings.add(s)
self.root.strings.add(s)
return 'ß' + s
def _resolve_global(self, writer, name):
......@@ -216,12 +181,12 @@ class ModuleBlock(Block):
def __init__(self, full_package_name, filename, src, future_features):
Block.__init__(self, None, '<module>')
self._full_package_name = full_package_name
self._filename = filename
self._buffer = source.Buffer(src)
self._strings = set()
self.full_package_name = full_package_name
self.filename = filename
self.buffer = source.Buffer(src)
self.strings = set()
self.imports = {}
self._future_features = future_features
self.future_features = future_features
def bind_var(self, writer, name, value):
writer.write_checked_call1(
......@@ -239,19 +204,19 @@ class ModuleBlock(Block):
class ClassBlock(Block):
"""Python block for a class definition."""
def __init__(self, parent_block, name, global_vars):
Block.__init__(self, parent_block, name)
def __init__(self, parent, name, global_vars):
Block.__init__(self, parent, name)
self.global_vars = global_vars
def bind_var(self, writer, name, value):
if name in self.global_vars:
return self._module_block.bind_var(writer, name, value)
return self.root.bind_var(writer, name, value)
writer.write_checked_call1('πClass.SetItem(πF, {}.ToObject(), {})',
self.intern(name), value)
def del_var(self, writer, name):
if name in self.global_vars:
return self._module_block.del_var(writer, name)
return self.root.del_var(writer, name)
writer.write_checked_call1('πg.DelVar(πF, πClass, {})', self.intern(name))
def resolve_name(self, writer, name):
......@@ -260,7 +225,7 @@ class ClassBlock(Block):
# Only look for a local in an outer block when name hasn't been declared
# global in this block. If it has been declared global then we fallback
# straight to the global dict.
block = self.parent_block
block = self.parent
while not isinstance(block, ModuleBlock):
if isinstance(block, FunctionBlock) and name in block.vars:
var = block.vars[name]
......@@ -268,7 +233,7 @@ class ClassBlock(Block):
local = util.adjust_local_name(name)
# When it is declared global, prefer it to anything in outer blocks.
break
block = block.parent_block
block = block.parent
result = self.alloc_temp()
writer.write_checked_call2(
result, 'πg.ResolveClass(πF, πClass, {}, {})',
......@@ -279,15 +244,15 @@ class ClassBlock(Block):
class FunctionBlock(Block):
"""Python block for a function definition."""
def __init__(self, parent_block, name, block_vars, is_generator):
Block.__init__(self, parent_block, name)
def __init__(self, parent, name, block_vars, is_generator):
Block.__init__(self, parent, name)
self.vars = block_vars
self.parent_block = parent_block
self.parent = parent
self.is_generator = is_generator
def bind_var(self, writer, name, value):
if self.vars[name].type == Var.TYPE_GLOBAL:
return self._module_block.bind_var(writer, name, value)
return self.root.bind_var(writer, name, value)
writer.write('{} = {}'.format(util.adjust_local_name(name), value))
def del_var(self, writer, name):
......@@ -296,7 +261,7 @@ class FunctionBlock(Block):
raise util.ParseError(
None, 'cannot delete nonexistent local: {}'.format(name))
if var.type == Var.TYPE_GLOBAL:
return self._module_block.del_var(writer, name)
return self.root.del_var(writer, name)
adjusted_name = util.adjust_local_name(name)
# Resolve local first to ensure the variable is already bound.
writer.write_checked_call1('πg.CheckLocal(πF, {}, {})',
......@@ -315,7 +280,7 @@ class FunctionBlock(Block):
util.adjust_local_name(name),
util.go_str(name))
return expr.GeneratedLocalVar(name)
block = block.parent_block
block = block.parent
return self._resolve_global(writer, name)
......
......@@ -458,7 +458,7 @@ class ExprVisitor(algorithm.Visitor):
'$flags, func(πF *πg.Frame, πArgs []*πg.Object) '
'(*πg.Object, *πg.BaseException) {',
result=result.name, name=util.go_str(node.name),
filename=util.go_str(self.block.filename), args=func_args.expr,
filename=util.go_str(self.block.root.filename), args=func_args.expr,
flags=' | '.join(flags) if flags else 0)
with self.writer.indent_block():
for var in func_block.vars.values():
......
......@@ -140,7 +140,7 @@ class StatementVisitor(algorithm.Visitor):
def __init__(self, block_):
self.block = block_
self.future_features = self.block.future_features or FutureFeatures()
self.future_features = self.block.root.future_features or FutureFeatures()
self.writer = util.Writer()
self.expr_visitor = expr_visitor.ExprVisitor(self.block, self.writer)
......@@ -220,7 +220,7 @@ class StatementVisitor(algorithm.Visitor):
\tπClass := $cls
\t_ = πClass""")
self.writer.write_tmpl(tmpl, name=util.go_str(node.name),
filename=util.go_str(self.block.filename),
filename=util.go_str(self.block.root.filename),
cls=cls.expr)
with self.writer.indent_block():
self.writer.write_temp_decls(body_visitor.block)
......@@ -694,7 +694,7 @@ class StatementVisitor(algorithm.Visitor):
code_objs = []
for i in xrange(len(parts)):
package_name = '/'.join(parts[:i + 1])
if package_name != self.block.full_package_name:
if package_name != self.block.root.full_package_name:
package = self.block.add_import(package_name)
code_objs.append('{}.Code'.format(package.alias))
else:
......@@ -816,6 +816,6 @@ class StatementVisitor(algorithm.Visitor):
def _write_py_context(self, lineno):
if lineno:
line = self.block.buffer.source_line(lineno).strip()
line = self.block.root.buffer.source_line(lineno).strip()
self.writer.write('// line {}: {}'.format(lineno, line))
self.writer.write('πF.SetLineno({})'.format(lineno))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment