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