[pypy-svn] r24465 - pypy/dist/pypy/translator/squeak
nik at codespeak.net
nik at codespeak.net
Thu Mar 16 14:42:28 CET 2006
Author: nik
Date: Thu Mar 16 14:42:27 2006
New Revision: 24465
Added:
pypy/dist/pypy/translator/squeak/node.py
Modified:
pypy/dist/pypy/translator/squeak/gensqueak.py
pypy/dist/pypy/translator/squeak/opformatter.py
Log:
move node classes into their own module.
Modified: pypy/dist/pypy/translator/squeak/gensqueak.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/gensqueak.py (original)
+++ pypy/dist/pypy/translator/squeak/gensqueak.py Thu Mar 16 14:42:27 2006
@@ -1,11 +1,7 @@
-import datetime, sys
-from pypy.objspace.flow.model import Constant, Variable, Block
-from pypy.objspace.flow.model import last_exception, checkgraph
+from pypy.objspace.flow.model import Constant
from pypy.translator.gensupp import NameManager
from pypy.translator.squeak.message import Message, camel_case
-from pypy.translator.squeak.opformatter import OpFormatter
-from pypy.rpython.ootypesystem.ootype import Instance, ROOT
-from pypy import conftest
+from pypy.translator.squeak.node import FunctionNode, ClassNode, SetupNode
try:
set
except NameError:
@@ -32,9 +28,6 @@
self.generated_nodes = set()
self.constant_insts = {}
- if conftest.option.view:
- self.translator.view()
-
graph = self.translator.graphs[0]
self.pending_nodes.append(FunctionNode(self, graph))
self.filename = '%s.st' % graph.name
@@ -120,321 +113,3 @@
return unique
-class CodeNode:
-
- def __hash__(self):
- return hash(self.hash_key)
-
- def __eq__(self, other):
- return isinstance(other, CodeNode) \
- and self.hash_key == other.hash_key
-
- # XXX need other comparison methods?
-
- def render_fileout_header(self, class_name, category):
- return "!%s methodsFor: '%s' stamp: 'pypy %s'!" % (
- class_name, category,
- datetime.datetime.now().strftime("%m/%d/%Y %H:%M"))
-
- def unique_field(self, INSTANCE, field_name):
- # XXX for now we ignore the issue of nameclashes between
- # field names. It's not so simple because superclasses must
- # be considered, too.
- return camel_case(field_name)
-
-class ClassNode(CodeNode):
-
- def __init__(self, gen, INSTANCE, class_vars=None):
- self.gen = gen
- self.INSTANCE = INSTANCE
- self.class_vars = [] # XXX should probably go away
- if class_vars is not None:
- self.class_vars = class_vars
- self.hash_key = INSTANCE
-
- def dependencies(self):
- if self.INSTANCE._superclass is not None: # not root
- return [ClassNode(self.gen, self.INSTANCE._superclass)]
- else:
- return []
-
- def render(self):
- yield "%s subclass: #%s" % (
- self.gen.nameof_Instance(self.INSTANCE._superclass),
- self.gen.nameof_Instance(self.INSTANCE))
- fields = [self.unique_field(self.INSTANCE, f) for f in
- self.INSTANCE._fields.iterkeys()]
- yield " instanceVariableNames: '%s'" % ' '.join(fields)
- yield " classVariableNames: '%s'" % ' '.join(self.class_vars)
- yield " poolDictionaries: ''"
- yield " category: 'PyPy-Test'!"
-
-class LoopFinder:
-
- def __init__(self, startblock):
- self.loops = {}
- self.parents = {startblock: startblock}
- self.temps = {}
- self.seen = []
- self.visit_Block(startblock)
-
- def visit_Block(self, block, switches=[]):
- #self.temps.has_key()
- self.seen.append(block)
- if block.exitswitch:
- switches.append(block)
- self.parents[block] = block
- for link in block.exits:
- self.visit_Link(link, switches)
-
- def visit_Link(self, link, switches):
- if link.target in switches:
- self.loops[link.target] = True
- if not link.target in self.seen:
- self.parents[link.target] = self.parents[link.prevblock]
- self.visit_Block(link.target, switches)
-
-class CallableNode(CodeNode):
-
- def render_body(self, startblock):
- self.loops = LoopFinder(startblock).loops
- args = self.arguments(startblock)
- sel = Message(self.name)
- yield sel.signature([self.expr(v) for v in args])
-
- # XXX should declare local variables here
- for line in self.render_block(startblock):
- yield " %s" % line
- yield '! !'
-
- def expr(self, v):
- if isinstance(v, Variable):
- return camel_case(v.name)
- elif isinstance(v, Constant):
- if isinstance(v.concretetype, Instance):
- const_id = self.gen.unique_name(
- v, "const_%s" % self.gen.nameof(v.value._TYPE))
- self.gen.constant_insts[v] = const_id
- return "(PyConstants getConstant: '%s')" % const_id
- return self.gen.nameof(v.value)
- else:
- raise TypeError, "expr(%r)" % (v,)
-
- def render_return(self, args):
- if len(args) == 2:
- # exception
- exc_cls = self.expr(args[0])
- exc_val = self.expr(args[1])
- yield "(PyOperationError class: %s value: %s) signal." % (exc_cls, exc_val)
- else:
- # regular return block
- retval = self.expr(args[0])
- yield "^%s" % retval
-
- def render_link(self, link):
- block = link.target
- if link.args:
- for i in range(len(link.args)):
- yield '%s := %s.' % \
- (self.expr(block.inputargs[i]), self.expr(link.args[i]))
- for line in self.render_block(block):
- yield line
-
- def render_block(self, block):
- if self.loops.has_key(block):
- if not self.loops[block]:
- yield '"skip1"'
- return
- yield "["
- formatter = OpFormatter(self.gen, self)
- for op in block.operations:
- yield "%s." % formatter.format(op)
- if len(block.exits) == 0:
- for line in self.render_return(block.inputargs):
- yield line
- return
- elif block.exitswitch is None:
- # single-exit block
- assert len(block.exits) == 1
- for line in self.render_link(block.exits[0]):
- yield line
- else:
- #exitswitch
- if self.loops.has_key(block):
- if self.loops[block]:
- self.loops[block] = False
- yield "%s] whileTrue: [" % self.expr(block.exitswitch)
- for line in self.render_link(block.exits[True]):
- yield " %s" % line
- yield "]."
- for line in self.render_link(block.exits[False]):
- yield "%s" % line
- else:
- yield "%s ifTrue: [" % self.expr(block.exitswitch)
- for line in self.render_link(block.exits[True]):
- yield " %s" % line
- yield "] ifFalse: ["
- for line in self.render_link(block.exits[False]):
- yield " %s" % line
- yield "]"
-
-class MethodNode(CallableNode):
-
- def __init__(self, gen, INSTANCE, method_name):
- self.gen = gen
- self.INSTANCE = INSTANCE
- self.name = method_name
- self.self = None # Will be set upon rendering
- self.hash_key = (INSTANCE, method_name)
-
- def dependencies(self):
- return [ClassNode(self.gen, self.INSTANCE)]
-
- def arguments(self, startblock):
- # Omit the explicit self
- return startblock.inputargs[1:]
-
- def render(self):
- yield self.render_fileout_header(
- self.gen.nameof(self.INSTANCE), "methods")
- graph = self.INSTANCE._methods[self.name].graph
- self.self = graph.startblock.inputargs[0]
- for line in self.render_body(graph.startblock):
- yield line
-
-class FunctionNode(CallableNode):
-
- FUNCTIONS = Instance("Functions", ROOT)
-
- def __init__(self, gen, graph):
- self.gen = gen
- self.graph = graph
- self.name = gen.nameof(graph.func)
- self.self = None
- self.hash_key = graph
-
- def dependencies(self):
- return [ClassNode(self.gen, self.FUNCTIONS)]
-
- def arguments(self, startblock):
- return startblock.inputargs
-
- def render(self):
- yield self.render_fileout_header("PyFunctions class", "functions")
- for line in self.render_body(self.graph.startblock):
- yield line
-
-class AccessorNode(CodeNode):
-
- def __init__(self, gen, INSTANCE, field_name):
- self.gen = gen
- self.INSTANCE = INSTANCE
- self.field_name = field_name
- self.hash_key = (INSTANCE, field_name, self.__class__)
-
- def dependencies(self):
- return [ClassNode(self.gen, self.INSTANCE)]
-
-class SetterNode(AccessorNode):
-
- def render(self):
- yield self.render_fileout_header(
- self.gen.nameof_Instance(self.INSTANCE), "accessors")
- yield "%s: value" % self.field_name
- yield " %s := value" % self.field_name
- yield "! !"
-
-class GetterNode(AccessorNode):
-
- def render(self):
- yield self.render_fileout_header(
- self.gen.nameof_Instance(self.INSTANCE), "accessors")
- yield self.field_name
- yield " ^%s" % self.field_name
- yield "! !"
-
-class HelperNode(CodeNode):
-
- HELPERS = Instance("Helpers", ROOT)
-
- def __init__(self, gen, message, code):
- self.gen = gen
- self.message = message
- self.code = code
- self.hash_key = ("helper", code)
-
- def apply(self, args):
- return self.message.send_to(self.HELPERS, args)
-
- def dependencies(self):
- return [ClassNode(self.gen, self.HELPERS)]
-
- def render(self):
- # XXX should not use explicit name "PyHelpers" here
- yield self.render_fileout_header("PyHelpers class", "helpers")
- for line in self.code.strip().split("\n"):
- yield line
- yield "! !"
-
-class FieldInitializerNode(CodeNode):
-
- def __init__(self, gen, INSTANCE):
- self.gen = gen
- self.INSTANCE = INSTANCE
- self.hash_key = ("fieldinit", INSTANCE)
-
- def dependencies(self):
- return [ClassNode(self.gen, self.INSTANCE)]
-
- def render(self):
- yield self.render_fileout_header(
- self.gen.nameof_Instance(self.INSTANCE), "initializers")
- fields = self.INSTANCE._allfields()
- sel = Message("field_init")
- arg_names = ["a%s" % i for i in range(len(fields))]
- yield sel.signature(arg_names)
- for field_name, arg_name in zip(fields.keys(), arg_names):
- yield " %s := %s." % (
- self.unique_field(self.INSTANCE, field_name),
- arg_name)
- yield "! !"
-
-class SetupNode(CodeNode):
-
- CONSTANTS = Instance("Constants", ROOT)
-
- def __init__(self, gen, constants):
- self.gen = gen
- self.constants = constants
- self.hash_key = "setup"
-
- def dependencies(self):
- # Important: Field initializers for the *runtime* type
- return [FieldInitializerNode(self.gen, c.value._TYPE)
- for c in self.constants.iterkeys()] + \
- [ClassNode(self.gen, self.CONSTANTS, class_vars=["Constants"])]
-
- def render(self):
- yield self.render_fileout_header("PyConstants class", "internals")
- sel = Message("setupConstants")
- yield sel.signature([])
- yield " Constants := Dictionary new."
- for const, const_id in self.constants.iteritems():
- INST = const.value._TYPE
- class_name = self.gen.nameof(INST)
- field_names = INST._allfields().keys()
- field_values = [self.gen.nameof(getattr(const.value, f))
- for f in field_names]
- init_sel = Message("field_init")
- yield " Constants at: '%s' put: (%s new %s)." \
- % (const_id, class_name,
- init_sel.signature(field_values))
- yield "! !"
- yield ""
-
- yield self.render_fileout_header("PyConstants class", "internals")
- sel = Message("getConstant")
- yield sel.signature(["constId"])
- yield " ^ Constants at: constId"
- yield "! !"
-
Added: pypy/dist/pypy/translator/squeak/node.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/squeak/node.py Thu Mar 16 14:42:27 2006
@@ -0,0 +1,324 @@
+import datetime
+from pypy.objspace.flow.model import Constant, Variable
+from pypy.translator.squeak.message import Message, camel_case
+from pypy.translator.squeak.opformatter import OpFormatter
+from pypy.rpython.ootypesystem.ootype import Instance, ROOT
+
+class CodeNode:
+
+ def __hash__(self):
+ return hash(self.hash_key)
+
+ def __eq__(self, other):
+ return isinstance(other, CodeNode) \
+ and self.hash_key == other.hash_key
+
+ # XXX need other comparison methods?
+
+ def render_fileout_header(self, class_name, category):
+ return "!%s methodsFor: '%s' stamp: 'pypy %s'!" % (
+ class_name, category,
+ datetime.datetime.now().strftime("%m/%d/%Y %H:%M"))
+
+ def unique_field(self, INSTANCE, field_name):
+ # XXX for now we ignore the issue of nameclashes between
+ # field names. It's not so simple because superclasses must
+ # be considered, too.
+ return camel_case(field_name)
+
+class ClassNode(CodeNode):
+
+ def __init__(self, gen, INSTANCE, class_vars=None):
+ self.gen = gen
+ self.INSTANCE = INSTANCE
+ self.class_vars = [] # XXX should probably go away
+ if class_vars is not None:
+ self.class_vars = class_vars
+ self.hash_key = INSTANCE
+
+ def dependencies(self):
+ if self.INSTANCE._superclass is not None: # not root
+ return [ClassNode(self.gen, self.INSTANCE._superclass)]
+ else:
+ return []
+
+ def render(self):
+ yield "%s subclass: #%s" % (
+ self.gen.nameof_Instance(self.INSTANCE._superclass),
+ self.gen.nameof_Instance(self.INSTANCE))
+ fields = [self.unique_field(self.INSTANCE, f) for f in
+ self.INSTANCE._fields.iterkeys()]
+ yield " instanceVariableNames: '%s'" % ' '.join(fields)
+ yield " classVariableNames: '%s'" % ' '.join(self.class_vars)
+ yield " poolDictionaries: ''"
+ yield " category: 'PyPy-Test'!"
+
+class LoopFinder:
+
+ def __init__(self, startblock):
+ self.loops = {}
+ self.parents = {startblock: startblock}
+ self.temps = {}
+ self.seen = []
+ self.visit_Block(startblock)
+
+ def visit_Block(self, block, switches=[]):
+ #self.temps.has_key()
+ self.seen.append(block)
+ if block.exitswitch:
+ switches.append(block)
+ self.parents[block] = block
+ for link in block.exits:
+ self.visit_Link(link, switches)
+
+ def visit_Link(self, link, switches):
+ if link.target in switches:
+ self.loops[link.target] = True
+ if not link.target in self.seen:
+ self.parents[link.target] = self.parents[link.prevblock]
+ self.visit_Block(link.target, switches)
+
+class CallableNode(CodeNode):
+
+ def render_body(self, startblock):
+ self.loops = LoopFinder(startblock).loops
+ args = self.arguments(startblock)
+ sel = Message(self.name)
+ yield sel.signature([self.expr(v) for v in args])
+
+ # XXX should declare local variables here
+ for line in self.render_block(startblock):
+ yield " %s" % line
+ yield '! !'
+
+ def expr(self, v):
+ if isinstance(v, Variable):
+ return camel_case(v.name)
+ elif isinstance(v, Constant):
+ if isinstance(v.concretetype, Instance):
+ const_id = self.gen.unique_name(
+ v, "const_%s" % self.gen.nameof(v.value._TYPE))
+ self.gen.constant_insts[v] = const_id
+ return "(PyConstants getConstant: '%s')" % const_id
+ return self.gen.nameof(v.value)
+ else:
+ raise TypeError, "expr(%r)" % (v,)
+
+ def render_return(self, args):
+ if len(args) == 2:
+ # exception
+ exc_cls = self.expr(args[0])
+ exc_val = self.expr(args[1])
+ yield "(PyOperationError class: %s value: %s) signal." % (exc_cls, exc_val)
+ else:
+ # regular return block
+ retval = self.expr(args[0])
+ yield "^%s" % retval
+
+ def render_link(self, link):
+ block = link.target
+ if link.args:
+ for i in range(len(link.args)):
+ yield '%s := %s.' % \
+ (self.expr(block.inputargs[i]), self.expr(link.args[i]))
+ for line in self.render_block(block):
+ yield line
+
+ def render_block(self, block):
+ if self.loops.has_key(block):
+ if not self.loops[block]:
+ yield '"skip1"'
+ return
+ yield "["
+ formatter = OpFormatter(self.gen, self)
+ for op in block.operations:
+ yield "%s." % formatter.format(op)
+ if len(block.exits) == 0:
+ for line in self.render_return(block.inputargs):
+ yield line
+ return
+ elif block.exitswitch is None:
+ # single-exit block
+ assert len(block.exits) == 1
+ for line in self.render_link(block.exits[0]):
+ yield line
+ else:
+ #exitswitch
+ if self.loops.has_key(block):
+ if self.loops[block]:
+ self.loops[block] = False
+ yield "%s] whileTrue: [" % self.expr(block.exitswitch)
+ for line in self.render_link(block.exits[True]):
+ yield " %s" % line
+ yield "]."
+ for line in self.render_link(block.exits[False]):
+ yield "%s" % line
+ else:
+ yield "%s ifTrue: [" % self.expr(block.exitswitch)
+ for line in self.render_link(block.exits[True]):
+ yield " %s" % line
+ yield "] ifFalse: ["
+ for line in self.render_link(block.exits[False]):
+ yield " %s" % line
+ yield "]"
+
+class MethodNode(CallableNode):
+
+ def __init__(self, gen, INSTANCE, method_name):
+ self.gen = gen
+ self.INSTANCE = INSTANCE
+ self.name = method_name
+ self.self = None # Will be set upon rendering
+ self.hash_key = (INSTANCE, method_name)
+
+ def dependencies(self):
+ return [ClassNode(self.gen, self.INSTANCE)]
+
+ def arguments(self, startblock):
+ # Omit the explicit self
+ return startblock.inputargs[1:]
+
+ def render(self):
+ yield self.render_fileout_header(
+ self.gen.nameof(self.INSTANCE), "methods")
+ graph = self.INSTANCE._methods[self.name].graph
+ self.self = graph.startblock.inputargs[0]
+ for line in self.render_body(graph.startblock):
+ yield line
+
+class FunctionNode(CallableNode):
+
+ FUNCTIONS = Instance("Functions", ROOT)
+
+ def __init__(self, gen, graph):
+ self.gen = gen
+ self.graph = graph
+ self.name = gen.nameof(graph.func)
+ self.self = None
+ self.hash_key = graph
+
+ def dependencies(self):
+ return [ClassNode(self.gen, self.FUNCTIONS)]
+
+ def arguments(self, startblock):
+ return startblock.inputargs
+
+ def render(self):
+ yield self.render_fileout_header("PyFunctions class", "functions")
+ for line in self.render_body(self.graph.startblock):
+ yield line
+
+class AccessorNode(CodeNode):
+
+ def __init__(self, gen, INSTANCE, field_name):
+ self.gen = gen
+ self.INSTANCE = INSTANCE
+ self.field_name = field_name
+ self.hash_key = (INSTANCE, field_name, self.__class__)
+
+ def dependencies(self):
+ return [ClassNode(self.gen, self.INSTANCE)]
+
+class SetterNode(AccessorNode):
+
+ def render(self):
+ yield self.render_fileout_header(
+ self.gen.nameof_Instance(self.INSTANCE), "accessors")
+ yield "%s: value" % self.field_name
+ yield " %s := value" % self.field_name
+ yield "! !"
+
+class GetterNode(AccessorNode):
+
+ def render(self):
+ yield self.render_fileout_header(
+ self.gen.nameof_Instance(self.INSTANCE), "accessors")
+ yield self.field_name
+ yield " ^%s" % self.field_name
+ yield "! !"
+
+class HelperNode(CodeNode):
+
+ HELPERS = Instance("Helpers", ROOT)
+
+ def __init__(self, gen, message, code):
+ self.gen = gen
+ self.message = message
+ self.code = code
+ self.hash_key = ("helper", code)
+
+ def apply(self, args):
+ return self.message.send_to(self.HELPERS, args)
+
+ def dependencies(self):
+ return [ClassNode(self.gen, self.HELPERS)]
+
+ def render(self):
+ # XXX should not use explicit name "PyHelpers" here
+ yield self.render_fileout_header("PyHelpers class", "helpers")
+ for line in self.code.strip().split("\n"):
+ yield line
+ yield "! !"
+
+class FieldInitializerNode(CodeNode):
+
+ def __init__(self, gen, INSTANCE):
+ self.gen = gen
+ self.INSTANCE = INSTANCE
+ self.hash_key = ("fieldinit", INSTANCE)
+
+ def dependencies(self):
+ return [ClassNode(self.gen, self.INSTANCE)]
+
+ def render(self):
+ yield self.render_fileout_header(
+ self.gen.nameof_Instance(self.INSTANCE), "initializers")
+ fields = self.INSTANCE._allfields()
+ sel = Message("field_init")
+ arg_names = ["a%s" % i for i in range(len(fields))]
+ yield sel.signature(arg_names)
+ for field_name, arg_name in zip(fields.keys(), arg_names):
+ yield " %s := %s." % (
+ self.unique_field(self.INSTANCE, field_name),
+ arg_name)
+ yield "! !"
+
+class SetupNode(CodeNode):
+
+ CONSTANTS = Instance("Constants", ROOT)
+
+ def __init__(self, gen, constants):
+ self.gen = gen
+ self.constants = constants
+ self.hash_key = "setup"
+
+ def dependencies(self):
+ # Important: Field initializers for the *runtime* type
+ return [FieldInitializerNode(self.gen, c.value._TYPE)
+ for c in self.constants.iterkeys()] + \
+ [ClassNode(self.gen, self.CONSTANTS, class_vars=["Constants"])]
+
+ def render(self):
+ yield self.render_fileout_header("PyConstants class", "internals")
+ sel = Message("setupConstants")
+ yield sel.signature([])
+ yield " Constants := Dictionary new."
+ for const, const_id in self.constants.iteritems():
+ INST = const.value._TYPE
+ class_name = self.gen.nameof(INST)
+ field_names = INST._allfields().keys()
+ field_values = [self.gen.nameof(getattr(const.value, f))
+ for f in field_names]
+ init_sel = Message("field_init")
+ yield " Constants at: '%s' put: (%s new %s)." \
+ % (const_id, class_name,
+ init_sel.signature(field_values))
+ yield "! !"
+ yield ""
+
+ yield self.render_fileout_header("PyConstants class", "internals")
+ sel = Message("getConstant")
+ yield sel.signature(["constId"])
+ yield " ^ Constants at: constId"
+ yield "! !"
+
Modified: pypy/dist/pypy/translator/squeak/opformatter.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/opformatter.py (original)
+++ pypy/dist/pypy/translator/squeak/opformatter.py Thu Mar 16 14:42:27 2006
@@ -75,7 +75,7 @@
sent_message = message.send_to(op.args[0], op.args[1:])
if opname in self.wrapping_ops \
and self.int_masks.has_key(ptype):
- from pypy.translator.squeak.gensqueak import HelperNode
+ from pypy.translator.squeak.node import HelperNode
mask_name, mask_code = self.int_masks[ptype]
helper = HelperNode(self.gen, Message(mask_name), mask_code)
sent_message = helper.apply([sent_message])
@@ -88,7 +88,7 @@
receiver = Self()
else:
receiver = op.args[1]
- from pypy.translator.squeak.gensqueak import MethodNode
+ from pypy.translator.squeak.node import MethodNode
self.gen.schedule_node(
MethodNode(self.gen, op.args[1].concretetype, message_name))
sent_message = Message(message_name).send_to(receiver, op.args[2:])
@@ -104,7 +104,7 @@
rvalue = Field(field_name)
else:
# Public field access
- from pypy.translator.squeak.gensqueak import GetterNode
+ from pypy.translator.squeak.node import GetterNode
self.gen.schedule_node(GetterNode(self.gen, INST, field_name))
rvalue = Message(field_name).send_to(op.args[0], [])
return self.codef.format(Assignment(op.result, rvalue))
@@ -119,7 +119,7 @@
return self.codef.format(Assignment(Field(field_name), field_value))
else:
# Public field access
- from pypy.translator.squeak.gensqueak import SetterNode
+ from pypy.translator.squeak.node import SetterNode
self.gen.schedule_node(SetterNode(self.gen, INST, field_name))
setter = Message(field_name).send_to(op.args[0], [field_value])
return self.codef.format(setter)
@@ -128,7 +128,7 @@
return self.codef.format(Assignment(op.result, op.args[0]))
def op_direct_call(self, op):
- from pypy.translator.squeak.gensqueak import FunctionNode
+ from pypy.translator.squeak.node import FunctionNode
function_name = self.node.expr(op.args[0])
self.gen.schedule_node(
FunctionNode(self.gen, op.args[0].value.graph))
More information about the Pypy-commit
mailing list