[Python-checkins] python/nondist/sandbox/parrot parrot-gen.py,1.4,1.5

akuchling@users.sourceforge.net akuchling@users.sourceforge.net
2002年7月20日 17:12:08 -0700


Update of /cvsroot/python/python/nondist/sandbox/parrot
In directory usw-pr-cvs1:/tmp/cvs-serv2641
Modified Files:
	parrot-gen.py 
Log Message:
Partial implementation of 'def', 'return', and function calls
Implement some more operators (**, <<, >>, 'and', 'or')
Add -t option to trace generated code when running it
Delete a bunch of visitor methods that will never be implemented because
 compile_expr() will handle them
Parrot 0.0.7 includes an intermediate-code compiler called 'imcc', which will
 take care of register scheduling, calling conventions, and other annoying
 trivia for you. My plan is to now rework parrot-gen.py to output
 IMCC-format code, which should make the implementation easier. Once that's
 running, I'll think about implementing PythonString, PythonInt, &c.
 objects.
Index: parrot-gen.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/parrot/parrot-gen.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** parrot-gen.py	20 Jul 2002 11:31:31 -0000	1.4
--- parrot-gen.py	21 Jul 2002 00:12:06 -0000	1.5
***************
*** 9,14 ****
 """
 
- # created 2001年09月21日, AMK
- 
 __revision__ = "$Id$"
 
--- 9,12 ----
***************
*** 19,22 ****
--- 17,21 ----
 -r Run Parrot assembler and interpreter on output
 -S Only produce assembly source code (.pasm file)
+ -t Use trace option when running generated code
 """
 
***************
*** 29,38 ****
 # List 31 of the 32 PMC registers as being available
 FREE_REGISTERS = []
! for i in range(1, 32):
 FREE_REGISTERS.append('P' + str(i))
 
- # Global variable: maps local variable names to their assigned register
- LOCAL_REGS = {}
- 
 symcount = 1 # Counter for symbols
 def gensym ():
--- 28,34 ----
 # List 31 of the 32 PMC registers as being available
 FREE_REGISTERS = []
! for i in range(2, 32):
 FREE_REGISTERS.append('P' + str(i))
 
 symcount = 1 # Counter for symbols
 def gensym ():
***************
*** 51,62 ****
 
 Attributes:
! lines : list of strings, each one a line of output.
 """
 
 def __init__ (self):
 self.lines = []
! self.symcount = 0
 self._last_lineno = None
! 
 def add_line (self, line):
 """add_line(line:string)
--- 47,68 ----
 
 Attributes:
! lines : [string]
! A list of strings, each one a line of assembly source code.
! functions : [string]
! More lines of assembly source, containing the functions.
 """
 
 def __init__ (self):
 self.lines = []
! self.functions = []
! self.symcount = 0 # Current number of symbol
! self.regcount = 0 # Current number of temp. register
 self._last_lineno = None
! 
! def next_register (self, type='P'):
! reg = 'P%i' % self.regcount
! self.regcount += 1
! return reg
! 
 def add_line (self, line):
 """add_line(line:string)
***************
*** 88,100 ****
 else:
 return []
 
 # Visitor methods. Most of them are currently unimplemented.
 def visitAssign (self, node):
 a_name = node.nodes[0].name
! reg = LOCAL_REGS[a_name]
 lines = (self.set_lineno(node) + 
 compile_expr(node.expr, reg, FREE_REGISTERS) )
 self.add_lines(lines)
! # XXX assign result to 'a_name.name'
 
 def visitClass (self, node):
--- 94,108 ----
 else:
 return []
+ 
 
 # Visitor methods. Most of them are currently unimplemented.
 def visitAssign (self, node):
 a_name = node.nodes[0].name
! reg = 'P0'#self.next_register()
 lines = (self.set_lineno(node) + 
 compile_expr(node.expr, reg, FREE_REGISTERS) )
 self.add_lines(lines)
! self.add_line('store_global %s, "%s"' % (reg, a_name))
! # XXX assign result to 'a_name'
 
 def visitClass (self, node):
***************
*** 129,134 ****
 self.add_lines(lines)
 
- ## def visitAnd(self, node):
- ## assert 0, "not implemented"
 ## def visitAssAttr(self, node):
 ## assert 0, "not implemented"
--- 137,140 ----
***************
*** 157,164 ****
 ## def visitBackquote(self, node):
 ## assert 0, "not implemented"
- ## def visitBitand(self, node):
- ## assert 0, "not implemented"
- ## def visitBitor(self, node):
- ## assert 0, "not implemented"
 ## def visitBitxor(self, node):
 ## assert 0, "not implemented"
--- 163,166 ----
***************
*** 171,176 ****
 ## def visitCompare(self, node):
 ## assert 0, "not implemented"
- ## def visitConst(self, node):
- ## assert 0, "not implemented"
 ## def visitContinue(self, node):
 ## assert 0, "not implemented"
--- 173,176 ----
***************
*** 193,200 ****
 ## def visitFrom(self, node):
 ## assert 0, "not implemented"
! ## def visitFunction(self, node):
! ## assert 0, "not implemented"
! ## def visitFunction(self, node):
! ## assert 0, "not implemented"
 ## def visitGetattr(self, node):
 ## assert 0, "not implemented"
--- 193,210 ----
 ## def visitFrom(self, node):
 ## assert 0, "not implemented"
! def visitFunction(self, node):
! symbol = gensym()
! self.add_lines(['set_addr I0, %s' % symbol,
! 'new P0, .Sub',
! 'set P0, I0',
! 'store_global P0, "%s"' % node.name])
! 
! # Generate code for the function body
! vtor = visitor.ASTVisitor()
! pv = ParrotVisitor()
! vtor.preorder(node.code, pv)
! self.functions += (['%s:' % symbol] + pv.lines + ['\t' 'ret'] +
! pv.functions)
! 
 ## def visitGetattr(self, node):
 ## assert 0, "not implemented"
***************
*** 207,212 ****
 def visitImport(self, node):
 assert 0, "not implemented"
- ## def visitInvert(self, node):
- ## assert 0, "not implemented"
 ## def visitKeyword(self, node):
 ## assert 0, "not implemented"
--- 217,220 ----
***************
*** 215,220 ****
 ## def visitLambda(self, node):
 ## assert 0, "not implemented"
- ## def visitLeftShift(self, node):
- ## assert 0, "not implemented"
 ## def visitList(self, node):
 ## assert 0, "not implemented"
--- 223,226 ----
***************
*** 228,250 ****
 ## pass
 ## #assert 0, "not implemented"
- ## def visitMul(self, node):
- ## assert 0, "not implemented"
- ## def visitName(self, node):
- ## assert 0, "not implemented"
- ## def visitNot(self, node):
- ## assert 0, "not implemented"
- ## def visitOr(self, node):
- ## assert 0, "not implemented"
 def visitPass(self, node):
 self.add_lines(self.set_lineno(node))
 self.add_lines(["noop"])
- ## def visitPower(self, node):
- ## assert 0, "not implemented"
 ## def visitRaise(self, node):
 ## assert 0, "not implemented"
! ## def visitReturn(self, node):
! ## assert 0, "not implemented"
! ## def visitRightShift(self, node):
! ## assert 0, "not implemented"
 ## def visitSlice(self, node, aug_flag=None):
 ## assert 0, "not implemented"
--- 234,247 ----
 ## pass
 ## #assert 0, "not implemented"
 def visitPass(self, node):
 self.add_lines(self.set_lineno(node))
 self.add_lines(["noop"])
 ## def visitRaise(self, node):
 ## assert 0, "not implemented"
! def visitReturn(self, node):
! lines = compile_expr(node.value, 'P0', FREE_REGISTERS[:])
! self.add_lines(lines)
! # XXX should ensure None is returned here
! self.add_line('\t' 'ret')
 ## def visitSlice(self, node, aug_flag=None):
 ## assert 0, "not implemented"
***************
*** 263,272 ****
 ## def visitTuple(self, node):
 ## assert 0, "not implemented"
- ## def visitUnaryAdd(self, node):
- ## assert 0, "not implemented"
- ## def visitUnaryInvert(self, node):
- ## assert 0, "not implemented"
- ## def visitUnarySub(self, node):
- ## assert 0, "not implemented"
 
 def visitWhile(self, node):
--- 260,263 ----
***************
*** 298,301 ****
--- 289,303 ----
 XXX how to handle string constants, or constants of other types?
 """
+ dict_lr = {ast.Add: "add", ast.Sub: "sub",
+ ast.Mul: "mul", ast.Div: "div",
+ ast.Mod: "mod",
+ ast.Power: "pow",
+ ast.RightShift: 'shr', ast.LeftShift: 'shl'}
+ dict_bool = {ast.And: 'and', ast.Or: 'or'}
+ 
+ # XXX Parrot 0.0.7 seems to have a mysterious core-dumping bug
+ # with register P1. 
+ if dest_register == 'P1': raise RuntimeError
+ 
 # Copy avail_registers, because we'll be mutating it later
 avail_registers = avail_registers[:]
***************
*** 322,338 ****
 
 elif isinstance(expr, ast.Name):
! reg = LOCAL_REGS[expr.name]
! return ["set %s, %s" % (dest_register, reg)]
 
! elif (isinstance(expr, ast.Add) or
! isinstance(expr, ast.Sub) or
! isinstance(expr, ast.Mul) or
! isinstance(expr, ast.Div) or
! isinstance(expr, ast.Mod)
! ):
! dict = {ast.Add: "add", ast.Sub: "sub",
! ast.Mul: "mul", ast.Div: "div",
! ast.Mod: "mod"}
! opcode = dict[expr.__class__]
 temp1 = random.choice(avail_registers)
 avail_registers.remove(temp1)
--- 324,331 ----
 
 elif isinstance(expr, ast.Name):
! return ['find_global %s, "%s"' % (dest_register, expr.name)]
 
! elif isinstance(expr, tuple(dict_lr.keys())):
! opcode = dict_lr[expr.__class__]
 temp1 = random.choice(avail_registers)
 avail_registers.remove(temp1)
***************
*** 346,349 ****
--- 339,355 ----
 )
 
+ elif isinstance(expr, tuple(dict_bool.keys())):
+ opcode = dict_bool[expr.__class__]
+ temp1 = random.choice(avail_registers)
+ avail_registers.remove(temp1)
+ lines = []
+ lines += compile_expr(expr.nodes[0], dest_register, avail_registers)
+ for n in expr.nodes[1:-1]:
+ lines += compile_expr(n, temp1, avail_registers)
+ lines += ["%s %s, %s, %s" % (opcode, dest_register, dest_register, temp1)]
+ lines += compile_expr(expr.nodes[-1], temp1, avail_registers)
+ lines += ["%s %s, %s, %s" % (opcode, dest_register, dest_register, temp1)]
+ 
+ 
 elif isinstance(expr, ast.Compare):
 dict = {'<':'lt', '>':'gt', '==':'eq',
***************
*** 370,373 ****
--- 376,397 ----
 "%s:" % sym2]
 
+ elif isinstance(expr, ast.CallFunc):
+ assert expr.args == [], 'Arguments not handled'
+ assert expr.star_args is None, '*args not handled'
+ assert expr.dstar_args is None, '**args not handled'
+ temp1 = random.choice(avail_registers)
+ assert isinstance(expr.node, ast.Name), \
+ "can only call functions directly"
+ name = expr.node.name
+ lines = compile_expr(expr.node, temp1, avail_registers)
+ 
+ # XXX fix case where dest_register == 'P0'
+ if dest_register != 'P0':
+ lines.append('save P0')
+ lines += ['find_global P0, "%s"' % name,
+ 'call']
+ if dest_register != 'P0':
+ lines += ['add %s, P0, 0' % dest_register, 'restore P0']
+ 
 else:
 raise RuntimeError, "Unexpected node in expression: %r" % expr
***************
*** 381,389 ****
 ## print ast
 
! # Determine locals and assign them to registers 
! lnf = walk(ast, LocalNameFinder(), verbose=0)
! for name in lnf.getLocals().elements():
! reg = LOCAL_REGS[name] = random.choice(FREE_REGISTERS)
! FREE_REGISTERS.remove(reg)
 ## print LOCAL_REGS
 
--- 405,414 ----
 ## print ast
 
! # Determine locals and assign them to registers
! # Disabled -- all variables are global for the moment
! ## lnf = walk(ast, LocalNameFinder(), verbose=0)
! ## for name in lnf.getLocals().elements():
! ## reg = LOCAL_REGS[name] = random.choice(FREE_REGISTERS)
! ## FREE_REGISTERS.remove(reg)
 ## print LOCAL_REGS
 
***************
*** 399,417 ****
 # Generate lines of assembly code
 vtor.preorder(ast, pv)
! 
! pv.add_line('end')
 
 # Write the generated assembly code
! lines = ["main:\n"] + pv.lines + ["\tend\n"]
 output = open(output_name, 'w')
! output.writelines(pv.lines)
 output.close()
 
 
 def main():
! opts, args = getopt.getopt(sys.argv[1:], 'hrS', ['help'])
 
 do_run = 0
 do_assemble = 1
 for opt, param in opts:
 if opt in ['-h', '--help']:
--- 424,442 ----
 # Generate lines of assembly code
 vtor.preorder(ast, pv)
! pv.add_line('\t' 'end')
 
 # Write the generated assembly code
! lines = pv.lines + pv.functions
 output = open(output_name, 'w')
! output.writelines(lines)
 output.close()
 
 
 def main():
! opts, args = getopt.getopt(sys.argv[1:], 'hrSt', ['help'])
 
 do_run = 0
 do_assemble = 1
+ do_trace = 0
 for opt, param in opts:
 if opt in ['-h', '--help']:
***************
*** 422,425 ****
--- 447,452 ----
 elif opt == '-S':
 do_assemble = 0
+ elif opt == '-t':
+ do_trace = 1
 
 if len(args) != 1:
***************
*** 438,443 ****
 if err: sys.exit(err)
 if do_run:
! err = os.system('%s/parrot -t %s' % (PARROT_SRC,
! bytecode_filename))
 if err == 139:
 print 'Parrot interpreter dumped core'
--- 465,474 ----
 if err: sys.exit(err)
 if do_run:
! if do_trace: trace_opt = '-t'
! else: trace_opt = ''
! cmd_line = '%s/parrot %s %s' % (PARROT_SRC, trace_opt,
! bytecode_filename)
! print cmd_line
! err = os.system(cmd_line)
 if err == 139:
 print 'Parrot interpreter dumped core'

AltStyle によって変換されたページ (->オリジナル) /