Skip to content

Commit a041ba3

Browse files
author
Troy Melhase
committed
work in progress.
1 parent 724b4e9 commit a041ba3

File tree

9 files changed

+157
-114
lines changed

9 files changed

+157
-114
lines changed

java2python/compiler/template.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,11 @@ class Module(Base):
319319
def iterBody(self):
320320
""" Yields the items in the body of this template. """
321321
blank, prev = self.factory.expr(), None
322-
def pred(p, c):
323-
return (p and not p.isClass) and (c.isClass and not c.isComment)
324322
for child in super(Module, self).iterBody():
325-
if pred(prev, child):
323+
if prev and not prev.isComment:
326324
yield blank
325+
if prev and prev.isClass and child and child.isClass:
326+
yield blank
327327
yield child
328328
prev = child
329329

java2python/compiler/visitor.py

Lines changed: 105 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Needs some introductory comments.
66

77
from functools import reduce, partial
8-
from itertools import ifilter, izip
8+
from itertools import ifilter, ifilterfalse, izip, tee
99
from logging import debug
1010
from re import compile as recompile, sub as resub
1111

@@ -72,6 +72,8 @@ def walk(self, tree, memo=None):
7272
comIns(self, tree, tree.tokenStopIndex, memo)
7373
if tree.isJavaSource:
7474
comIns(self, tree, len(tree.parser.input.tokens), memo)
75+
# fixme: we're calling the mutators far too frequently instead
76+
# of only once per object after its walk is finished.
7577
for handler in self.configHandlers('PostWalk', suffix='Mutators'):
7678
handler(self)
7779

@@ -80,6 +82,22 @@ def zipWalk(self, nodes, visitors, memo):
8082
for node, visitor in izip(nodes, visitors):
8183
visitor.walk(node, memo)
8284

85+
def nodeTypeToString(self, node):
86+
""" Returns the TYPE or QUALIFIED_TYPE_IDENT of the given node. """
87+
# (TYPE primitiveType
88+
# | TYPE qualifiedTypeIdent
89+
# | TYPE qualifiedTypeIdentSimplified
90+
# ) arrayDeclaratorList?
91+
alt = self.altIdent
92+
ntype = node.firstChildOfType(tokens.TYPE)
93+
nnext = ntype.children[0]
94+
if nnext.type == tokens.QUALIFIED_TYPE_IDENT:
95+
names = [alt(t.text) for t in nnext.childrenOfType(tokens.IDENT)]
96+
stype = '.'.join(names)
97+
else:
98+
stype = nnext.text
99+
return alt(stype)
100+
83101

84102
class TypeAcceptor(object):
85103
""" TypeAcceptor -> shared visitor method(s) for type declarations.
@@ -125,26 +143,77 @@ class ModifiersAcceptor(object):
125143
"""
126144
def acceptModifierList(self, node, memo):
127145
""" Accept and process class and method modifiers. """
128-
# modifier lists come with class, interface, enum and
129-
# annotation declarations. they also come with method and var
130-
# decls; see those methods in the Class definition.
146+
isAnno = lambda token:token.type==tokens.AT
147+
for ano in ifilter(isAnno, node.children):
148+
self.nodesToAnnos(ano, memo)
149+
for mod in ifilterfalse(isAnno, node.children):
150+
self.nodesToModifiers(mod, node)
151+
return self
131152

132-
for branch in [c for c in node.children if c.type==tokens.AT]:
133-
# TODO: walk annotation correctly
134-
name = branch.firstChildOfType(tokens.IDENT).text
153+
def nodesToAnnos(self, branch, memo):
154+
""" Convert the annotations in the given branch to a decorator. """
155+
name = branch.firstChildOfType(tokens.IDENT).text
156+
init = branch.firstChildOfType(tokens.ANNOTATION_INIT_BLOCK)
157+
if not init:
135158
deco = self.factory.expr(left=name, fs='@{left}()')
159+
else:
160+
defKey = init.firstChildOfType(tokens.ANNOTATION_INIT_DEFAULT_KEY)
161+
if defKey:
162+
deco = self.factory.expr(left=name, fs='@{left}({right})')
163+
deco.right = right = self.factory.expr(parent=deco)
164+
right.walk(defKey.firstChild())
165+
else:
166+
deco = self.factory.expr(left=name, fs='@{left}({right})')
167+
arg = deco.right = self.factory.expr(parent=deco)
168+
keys = init.firstChildOfType(tokens.ANNOTATION_INIT_KEY_LIST)
169+
for child in keys.children:
170+
fs, expr = child.text + '={right}', child.firstChild()
171+
fs += (', ' if child is not keys.children[-1] else '')
172+
arg.left = self.factory.expr(fs=fs, parent=arg)
173+
arg.left.walk(expr, memo)
174+
arg.right = arg = self.factory.expr(parent=arg)
136175
self.decorators.append(deco)
137176

138-
for branch in [c for c in node.children if c.type != tokens.AT]:
139-
if node.parentType in tokens.methodTypes:
140-
self.modifiers.extend(n.text for n in node.children) # wrong
141-
if self.isStatic:
142-
self.parameters[0]['name'] = 'cls'
143-
self.modifiers.append(branch.text)
177+
def nodesToModifiers(self, branch, root):
178+
""" Convert the modifiers in the given branch to template modifiers. """
179+
if root.parentType in tokens.methodTypes:
180+
self.modifiers.extend(n.text for n in root.children)
181+
if self.isStatic and self.parameters:
182+
self.parameters[0]['name'] = 'cls'
183+
self.modifiers.append(branch.text)
184+
185+
186+
class VarAcceptor(object):
187+
def acceptVarDeclaration(self, node, memo):
188+
""" Creates a new expression for a variable declaration. """
189+
varDecls = node.firstChildOfType(tokens.VAR_DECLARATOR_LIST)
190+
for varDecl in varDecls.childrenOfType(tokens.VAR_DECLARATOR):
191+
ident = varDecl.firstChildOfType(tokens.IDENT)
192+
self.variables.append(ident.text)
193+
identExp = self.factory.expr(left=ident.text, parent=self)
194+
declExp = varDecl.firstChildOfType(tokens.EXPR)
195+
assgnExp = identExp.pushRight(' = ')
196+
declArr = varDecl.firstChildOfType(tokens.ARRAY_INITIALIZER)
197+
if declExp:
198+
assgnExp.walk(declExp, memo)
199+
elif declArr:
200+
assgnExp.right = exp = self.factory.expr(fs='['+FS.lr+']', parent=identExp)
201+
children = list(declArr.childrenOfType(tokens.EXPR))
202+
for child in children:
203+
fs = FS.lr if child is children[-1] else FS.lr + ', '
204+
exp.left = self.factory.expr(fs=fs, parent=identExp)
205+
exp.left.walk(child, memo)
206+
exp.right = exp = self.factory.expr(parent=identExp)
207+
else:
208+
if node.firstChildOfType(tokens.TYPE).firstChildOfType(tokens.ARRAY_DECLARATOR_LIST):
209+
val = assgnExp.pushRight('[]')
210+
else:
211+
typ = self.nodeTypeToString(node)
212+
val = assgnExp.pushRight('{0}()'.format(typ))
144213
return self
145214

146215

147-
class Class(TypeAcceptor, ModifiersAcceptor, Base):
216+
class Class(VarAcceptor, TypeAcceptor, ModifiersAcceptor, Base):
148217
""" Class -> accepts AST branches for class-level objects.
149218
150219
"""
@@ -183,36 +252,6 @@ def acceptFunctionMethodDecl(self, node, memo):
183252
mods = node.firstChildOfType(tokens.MODIFIER_LIST)
184253
return self.factory.method(name=ident.text, type=type, parent=self)
185254

186-
def acceptVarDeclaration(self, node, memo):
187-
""" Creates a new expression for a variable declaration. """
188-
# this is strikingly similar to
189-
# MethodContent.acceptVarDeclaration; merge and fix.
190-
mods = node.firstChildOfType(tokens.MODIFIER_LIST)
191-
decl = node.firstChildOfType(tokens.VAR_DECLARATOR_LIST)
192-
for vard in decl.childrenOfType(tokens.VAR_DECLARATOR):
193-
ident = vard.firstChildOfType(tokens.IDENT)
194-
self.variables.append(ident.text)
195-
expr = vard.firstChildOfType(tokens.EXPR)
196-
child = self.factory.expr(left=ident.text, parent=self)
197-
assgn = child.pushRight(' = ')
198-
arinit = vard.firstChildOfType(tokens.ARRAY_INITIALIZER)
199-
if arinit:
200-
assgn.right = exp = self.factory.expr(fs='['+FS.lr+']', parent=child)
201-
children = list(arinit.childrenOfType(tokens.EXPR))
202-
for c in children:
203-
fs = FS.lr if c is children[-1] else FS.lr + ', '
204-
exp.left = self.factory.expr(fs=fs, parent=child)
205-
exp.left.walk(c, memo)
206-
exp.right = exp = self.factory.expr(parent=child)
207-
elif expr:
208-
assgn.walk(expr, memo)
209-
else:
210-
typ = node.firstChildOfType(tokens.TYPE)
211-
typ = typ.children[0].text
212-
val = assgn.pushRight()
213-
val.left = '{0}()'.format(typ) # wrong
214-
return self
215-
216255
def acceptVoidMethodDecl(self, node, memo):
217256
""" Accept and process a void method declaration. """
218257
ident = node.firstChildOfType(tokens.IDENT)
@@ -341,10 +380,17 @@ def acceptDo(self, node, memo):
341380
ifStat.expr.walk(parNode, memo)
342381
breakStat = self.factory.statement('break', parent=ifStat)
343382

383+
goodExprParents = (
384+
tokens.BLOCK_SCOPE,
385+
tokens.CASE,
386+
tokens.DEFAULT,
387+
tokens.FOR_EACH
388+
)
389+
344390
def acceptExpr(self, node, memo):
345391
""" Creates a new expression. """
346-
goodParents = (tokens.BLOCK_SCOPE, tokens.CASE, tokens.DEFAULT, tokens.FOR_EACH)
347-
if node.parentType in goodParents: # wrong
392+
# this works but isn't precise
393+
if node.parentType in self.goodExprParents:
348394
return self.factory.expr(parent=self)
349395

350396
def acceptFor(self, node, memo):
@@ -466,45 +512,19 @@ def acceptTry(self, node, memo):
466512
finStat = self.factory.statement('finally', fs=FS.lc, parent=self)
467513
finStat.walk(finNode, memo)
468514

515+
goodReturnParents = (
516+
tokens.BLOCK_SCOPE,
517+
)
518+
469519
def acceptReturn(self, node, memo):
470520
""" Creates a new return expression. """
471-
if node.parentType == tokens.BLOCK_SCOPE: # wrong
521+
# again, this works but isn't as precise as it should be
522+
if node.parentType in self.goodReturnParents:
472523
expr = self.factory.expr(left='return', parent=self)
473524
if node.children:
474525
expr.fs, expr.right = FS.lsr, self.factory.expr(parent=expr)
475526
expr.right.walk(node, memo)
476527

477-
def acceptVarDeclaration(self, node, memo):
478-
""" Creates a new expression for a variable declaration. """
479-
varDecls = node.firstChildOfType(tokens.VAR_DECLARATOR_LIST)
480-
for varDecl in varDecls.childrenOfType(tokens.VAR_DECLARATOR):
481-
ident = varDecl.firstChildOfType(tokens.IDENT)
482-
self.variables.append(ident.text)
483-
identExp = self.factory.expr(left=ident.text, parent=self)
484-
assgnExp = identExp.pushRight(' = ')
485-
declExp = varDecl.firstChildOfType(tokens.EXPR)
486-
declArr = varDecl.firstChildOfType(tokens.ARRAY_INITIALIZER)
487-
if declExp:
488-
assgnExp.walk(declExp, memo)
489-
elif declArr:
490-
assgnExp.right = exp = self.factory.expr(fs='['+FS.lr+']')
491-
children = list(declArr.childrenOfType(tokens.EXPR))
492-
for child in children:
493-
fs = FS.lr if child is children[-1] else FS.lr + ', '
494-
exp.left = self.factory.expr(fs=fs)
495-
exp.left.walk(child, memo)
496-
exp.right = exp = self.factory.expr()
497-
else:
498-
if node.firstChildOfType(tokens.TYPE).firstChildOfType(tokens.ARRAY_DECLARATOR_LIST):
499-
val = assgnExp.pushRight()
500-
val.left = '[]'
501-
else:
502-
typ = node.firstChildOfType(tokens.TYPE)
503-
typ = typ.children[0].text
504-
val = assgnExp.pushRight()
505-
val.left = '{0}()'.format(typ) # wrong
506-
return self
507-
508528
def acceptWhile(self, node, memo):
509529
""" Accept and process a while block. """
510530
# WHILE - PARENTESIZED_EXPR - BLOCK_SCOPE
@@ -514,18 +534,14 @@ def acceptWhile(self, node, memo):
514534
whileStat.walk(blkNode, memo)
515535

516536

517-
class Method(ModifiersAcceptor, MethodContent):
537+
class Method(VarAcceptor, ModifiersAcceptor, MethodContent):
518538
""" Method -> accepts AST branches for method-level objects.
519539
520540
"""
521541
def acceptFormalParamStdDecl(self, node, memo):
522542
""" Accept and process a single parameter declaration. """
523543
ident = node.firstChildOfType(tokens.IDENT)
524-
ptype = list(node.findChildrenOfType(tokens.TYPE))[0] # wrong
525-
try:
526-
ptype = list(ptype.findChildrenOfType(tokens.IDENT))[0].text
527-
except (IndexError, ):
528-
ptype = ptype.firstChild().text
544+
ptype = self.nodeTypeToString(node)
529545
self.parameters.append(self.makeParam(ident.text, ptype))
530546
return self
531547

@@ -596,7 +612,7 @@ def acceptPreformatted(self, node, memo):
596612
return acceptPreformatted
597613

598614
acceptArrayElementAccess = makeNodePreformattedExpr(FS.l + '[' + FS.r + ']')
599-
acceptCastExpr = makeNodePreformattedExpr(FS.l + '(' + FS.r + ')' ) # wrong.
615+
acceptCastExpr = makeNodePreformattedExpr(FS.l + '(' + FS.r + ')' ) # problem?
600616
acceptDiv = makeNodePreformattedExpr(FS.l + ' / ' + FS.r)
601617
acceptLogicalAnd = makeNodePreformattedExpr(FS.l + ' and ' + FS.r)
602618
acceptLogicalNot = makeNodePreformattedExpr('not ' + FS.l)
@@ -655,11 +671,11 @@ def acceptBitShiftRightAssign(self, node, memo):
655671

656672
def acceptClassConstructorCall(self, node, memo):
657673
""" Accept and process a class constructor call. """
658-
self.acceptMethodCall(node, memo) # probably wrong
674+
self.acceptMethodCall(node, memo)
659675
typeIdent = node.firstChildOfType(tokens.QUALIFIED_TYPE_IDENT)
660676
if typeIdent and typeIdent.children:
661-
ids = [self.altIdent(child.text) for child in typeIdent.children]
662-
self.left = '.'.join(ids) # wrong
677+
names = [self.altIdent(child.text) for child in typeIdent.children]
678+
self.left = '.'.join(names)
663679

664680
def acceptDot(self, node, memo):
665681
""" Accept and process a dotted expression. """
@@ -674,7 +690,7 @@ def acceptExpr(self, node, memo):
674690

675691
def acceptIdent(self, node, memo):
676692
""" Accept and process an ident expression. """
677-
self.left = name = self.altIdent(node.text)
693+
self.left = self.altIdent(node.text)
678694

679695
def acceptInstanceof(self, node, memo):
680696
""" Accept and process an instanceof expression. """

java2python/config/default.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,18 @@
5656
basic.simpleDocString,
5757
]
5858

59+
5960
interfaceHeadHandlers = [
6061
basic.simpleDocString,
6162
'__metaclass__ = ABCMeta',
6263
]
6364

6465

66+
interfacePostWalkMutators = [
67+
basic.zopeInterfaceMethodMutator,
68+
]
69+
70+
6571
methodHeadHandlers = [
6672
basic.simpleDocString,
6773
]

java2python/mod/basic.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def commentedImports(module, expr):
2323
def simpleImports(module, expr):
2424
module.factory.expr(parent=module, left=expr, fs='import {left}')
2525

26+
2627
def commentedPackages(module, expr):
2728
module.factory.comment(parent=module, left=expr, fs='package: {left}')
2829

@@ -39,7 +40,7 @@ def namespacePackages(module, expr):
3940
with open(initname, 'w') as initfile:
4041
initfile.write('from pkgutil import extend_path\n')
4142
initfile.write('__path__ = extend_path(__path__, __name__)\n')
42-
## wrong
43+
# wrong
4344
initfile.write('\nfrom {0} import {0}\n'.format(module.name))
4445
info('created __init__.py file for package %s.', expr)
4546

@@ -124,15 +125,12 @@ def maybeBsr(module):
124125
yield line
125126

126127

127-
# this function implies that there should be a separate modification
128-
# stage where client code like this can mutate the templates generated
129-
# by the compiler. this works, but it not really what the prologue
130-
# handlers are meant to do. the various interface functions fall into
131-
# the category of mutators also.
132-
133-
# also, the output handers seem to be a special case of this
134-
# desired mutator-function.
135-
136128
def classContentSort(obj):
137129
obj.children.sort(lambda x, y:-1 if x.isClass else 1)
138130

131+
132+
def zopeInterfaceMethodMutator(obj):
133+
for method in [c for c in obj.children if c.isMethod]:
134+
if method.parameters and method.parameters[0]['name'] == 'self':
135+
method.parameters.pop(0)
136+

0 commit comments

Comments
 (0)