Skip to content

Commit d48c30a

Browse files
committed
Fix switch problems. Fix issue natural#30.
1 parent 4a8f286 commit d48c30a

File tree

2 files changed

+140
-38
lines changed

2 files changed

+140
-38
lines changed

java2python/lib/sourcetypes.py

Lines changed: 115 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ def __init__(self, parent=None, name=None):
104104
self.epilogue = []
105105
self.lines = []
106106
self.type = None
107-
self.variables = set()
107+
self.variables = list()
108+
self.methods = list()
108109

109110
self.postIncDecInExprFixed = False
110111
self.postIncDecVars = []
@@ -166,17 +167,22 @@ def addSource(self, value):
166167

167168
def addSourceBefore(self, value, stat=None):
168169
""" add source code to the end of this block, before the last line
170+
or the specified statement
169171
170172
@param value string, instance of Source (or subclass), or two-tuple
173+
@param stat Statement, insert source before this statement
171174
@return None
172175
"""
173176
if len(self.lines) > 0:
174-
idx = -2 if stat == None else self.lines.index(stat)
177+
if isinstance(stat, int):
178+
idx = stat
179+
else:
180+
idx = -2 if stat == None else self.lines.index(stat)
175181
self.lines.insert(idx, value)
176182
else:
177183
self.lines.append(value)
178184

179-
def addVariable(self, name, force=False):
185+
def addVariable(self, var, force=False):
180186
""" add variable name to set for tracking
181187
182188
Variables are only added to Class instances unless the force
@@ -186,8 +192,11 @@ def addVariable(self, name, force=False):
186192
@keyparam force=False, if True, always add to set
187193
@return None
188194
"""
189-
if force or (name and self.isClass):
190-
self.variables.add(name)
195+
if force or (var.name and self.isClass):
196+
self.variables.append(var)
197+
198+
def addMethod(self, meth):
199+
self.methods.append(meth)
191200

192201
@property
193202
def allParents(self):
@@ -208,10 +217,39 @@ def allVars(self):
208217
"""
209218
for obj in [self, ] + list(self.allParents):
210219
for v in obj.variables:
211-
yield v
220+
yield v.name
221+
for v in obj.methods:
222+
yield v.name
212223
for v in obj.extraVars:
213224
yield v
214225

226+
@property
227+
def allMembers(self):
228+
""" all member variables in this class
229+
230+
@return yields all member names from this class
231+
"""
232+
for obj in [self, ] + list(self.allParents):
233+
if isinstance(obj, Class):
234+
for v in obj.variables:
235+
yield v.name
236+
for v in obj.methods:
237+
yield v.name
238+
for v in obj.extraVars:
239+
yield v
240+
241+
@property
242+
def staticMembers(self):
243+
""" all static member variable in this class
244+
245+
@return yields static member names from this class
246+
"""
247+
for obj in [self, ] + list(self.allParents):
248+
if isinstance(obj, Class):
249+
for v in obj.variables:
250+
if v.isStatic:
251+
yield v.name
252+
215253
@property
216254
def extraVars(self):
217255
""" extra variable names; subclasses can and should reimplement
@@ -267,19 +305,32 @@ def declFormat(self):
267305
return 'self.%s'
268306
return '%s ## ERROR'
269307

308+
@property
309+
def className(self):
310+
if isinstance(self, Class):
311+
return self.name
312+
elif self.parent is not None:
313+
return self.parent.className
314+
else:
315+
return 'ERROR'
316+
270317
def fixDecl(self, *args):
271318
""" fixes variable names that are class members
272319
273320
@varparam args names to fix
274321
@return fixed name or names
275322
"""
276323
fixed = list(args)
277-
allvars = list(self.allVars)
324+
allvars = list(self.allMembers)
325+
staticvars = list(self.staticMembers)
278326
mapping = self.config.combined('variableNameMapping')
279327
format = self.declFormat
280328
if not self.isClass:
281329
for i, arg in enumerate(args):
282-
if arg in allvars:
330+
if arg in staticvars:
331+
arg = mapping.get(arg, arg)
332+
fixed[i] = "%s.%s" % (self.className, arg)
333+
elif arg in allvars:
283334
arg = mapping.get(arg, arg)
284335
fixed[i] = format % (arg, )
285336
else:
@@ -317,6 +368,7 @@ def newMethod(self, name=None):
317368
@return Method instance
318369
"""
319370
m = Method(parent=self, name=name)
371+
self.addMethod(m)
320372
self.addSource(m)
321373
return m
322374

@@ -325,10 +377,13 @@ def newSwitch(self):
325377
326378
@return Statement instance
327379
"""
328-
s = Statement(self, 'if')
380+
while_stat = Statement(self, 'while')
381+
while_stat.setExpression('True')
382+
self.addSource(while_stat)
383+
s = Statement(while_stat, 'if')
329384
s.expr = 'False'
330-
self.addSource(s)
331-
return s
385+
while_stat.addSource(s)
386+
return while_stat, s
332387

333388
def newStatement(self, name):
334389
""" creates a new Statement as a child of this block
@@ -342,15 +397,21 @@ def newStatement(self, name):
342397

343398
def newStatementBefore(self, name, stat=None):
344399
""" creates a new Statement as a child of this block before the last
400+
or the specified statement.
345401
346402
@param name name of statement
347-
@param stat add statement before stat
403+
@param stat add statement before this one
348404
@return Statement instance
349405
"""
350406
s = Statement(parent=self, name=name)
351407
self.addSourceBefore(s, stat)
352408
return s
353409

410+
def newVariable(self, name=None):
411+
var = Variable(self)
412+
self.addVariable(var, True)
413+
return var
414+
354415
def formatExpression(self, expr):
355416
""" format an expression set by the tree walker
356417
@@ -398,13 +459,13 @@ def setName(self, name):
398459
"""
399460
self.name = name
400461

401-
def fixSwitch(self, block):
462+
def fixSwitch(self, while_block, block):
402463
""" fixes the first clause in an generated switch statement
403464
404465
@param block Statement instance and child of this block
405466
@return None
406467
"""
407-
lines = self.lines
468+
lines = while_block.lines
408469
if (not block in lines) or (block.name != 'if'):
409470
return
410471
i = lines.index(block)
@@ -666,6 +727,20 @@ def F_0(...)
666727
method.preamble.append('@%s.register(%s)' % (firstname, params))
667728
method.name = '%s_%s' % (method.name, index)
668729

730+
def declVars(self):
731+
"""Declare class member vars in init method
732+
733+
"""
734+
meth = None
735+
if "__init__" in list(self.allMembers):
736+
meth = self.newMethod("__init_vars__")
737+
elif len(self.variables) > 0:
738+
meth = self.newMethod("__init__")
739+
if meth:
740+
for v in self.variables:
741+
if not v.isStatic:
742+
meth.addSource(("self.%s = %s", (("%s", v.name), v.expr)))
743+
669744
def writeTo(self, output, indent):
670745
""" writes the string representation of this block
671746
@@ -877,3 +952,29 @@ def writeTo(self, output, indent):
877952
if (not lines) and name not in ('break', 'continue', 'raise'):
878953
self.addSource('pass')
879954
Source.writeTo(self, output, indent+1)
955+
956+
class Variable(Source):
957+
"""Variable is a defined class member variable or auto variable of the
958+
method.
959+
960+
"""
961+
962+
def __init__(self, parent, name=None, expr=None):
963+
Source.__init__(self, parent=parent, name=name)
964+
self.expr = expr
965+
966+
def setExpression(self, expr):
967+
""" sets the value of the expression for this Variable
968+
969+
@param value expression (see formatExpression in Source class).
970+
@return None
971+
"""
972+
self.expr = expr
973+
974+
@property
975+
def isStatic(self):
976+
"""Check is this variable a static variable
977+
978+
@return if the variable is static return True
979+
"""
980+
return 'static' in self.modifiers

java2python/lib/walker.g

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ returns [clause = None]
154154
interface_block [block]
155155
: #(OBJBLOCK
156156
(method_decl[block]
157-
| variable_def[block]
157+
| variable_def[block, False]
158158
| typ = type_def[block]
159159
)*
160160
)
@@ -165,12 +165,13 @@ obj_block [block]
165165
: #(OBJBLOCK
166166
(ctor_def[block]
167167
| method_def[block]
168-
| variable_def[block]
168+
| variable_def[block, False]
169169
| typ = type_def[block]
170170
| #(STATIC_INIT statement_list[block])
171171
| #(INSTANCE_INIT statement_list[block])
172172
)*
173173
)
174+
{ block.declVars() }
174175
;
175176

176177

@@ -179,6 +180,9 @@ ctor_def [block]
179180
meth = block.newMethod()
180181
}
181182
#(CTOR_DEF
183+
{
184+
meth.addSource("self.__init_vars__()")
185+
}
182186
modifiers[meth]
183187
method_head[meth, "__init__"]
184188
(statement_list[meth])?
@@ -206,7 +210,6 @@ method_head [meth, name=None]
206210
: ident = identifier[meth]
207211
{
208212
meth.setName(name if name else ident)
209-
meth.parent.addVariable(meth.name)
210213
}
211214
#(PARAMETERS (parameter_def[meth])*)
212215
(throws_clause[meth])?
@@ -229,18 +232,23 @@ method_def [block]
229232
;
230233

231234

232-
variable_def [block]
233-
: #(VARIABLE_DEF
234-
modifiers[block]
235-
typ = type_spec[block]
236-
dec = var_decl[block]
237-
val = var_init[block]
235+
variable_def [block, append = True]
236+
: {
237+
var = block.newVariable()
238+
}
239+
#(VARIABLE_DEF
240+
modifiers[var]
241+
typ = type_spec[var]
242+
dec = var_decl[var]
243+
val = var_init[var]
238244
)
239245
{
240-
block.addVariable(dec[1])
241246
if val == block.emptyAssign:
242247
val = ("%s", block.config.combined("typeValueMap").get(typ, "%s()" % typ))
243-
block.addSource( ("%s = %s", (dec, val)) )
248+
var.setName(dec[1])
249+
var.setExpression(val)
250+
if append or var.isStatic:
251+
block.addSource( ("%s = %s", (dec, val)) )
244252
}
245253
;
246254

@@ -463,13 +471,14 @@ statement [block]
463471

464472

465473
| {
466-
switch_block = block.newSwitch()
474+
while_block, switch_block = block.newSwitch()
467475
}
468476
#("switch" switch_expr = expression[block, False]
469-
(c:case_group[block, switch_expr])*
477+
(c:case_group[while_block, switch_expr])*
470478
)
471479
{
472-
block.fixSwitch(switch_block)
480+
while_block.newStatement("break")
481+
block.fixSwitch(while_block, switch_block)
473482
}
474483

475484
| {
@@ -489,7 +498,7 @@ statement [block]
489498

490499
case_group [block, switch_expr]
491500
: {
492-
other = block.newStatement("elif")
501+
other = block.newStatement("if")
493502
right = None
494503
}
495504
#(CASE_GROUP
@@ -506,19 +515,11 @@ case_group [block, switch_expr]
506515
)
507516
{
508517
if right is block.emptyAssign:
509-
other.setName("else")
510-
other.setExpression(None)
518+
other.setExpression("True")
511519
elif right[0] == "%s":
512520
other.setExpression(("%s == %s", (switch_expr, right)))
513521
else:
514522
other.setExpression(("%s in (%s)", (switch_expr, right)))
515-
516-
/* if only one break statement in the elif block, delete it, then
517-
a pass statement will be generated */
518-
if len(other.lines) == 1 and \
519-
hasattr(other.lines[0], "name") and \
520-
other.lines[0].name == "break":
521-
del other.lines[0]
522523
}
523524
;
524525

0 commit comments

Comments
 (0)