beeware / voc

A transpiler that converts Python code into Java bytecode

Home Page:http://beeware.org/voc

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expression statement inside a loop throws incompatible stack heights AnalyzerException

patiences opened this issue · comments

Python program:

for i in range(10):
    "abc" == "def"

Exception from ASM:

org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 67: Incompatible stack heights
	at org.objectweb.asm.tree.analysis.Analyzer.analyze(Unknown Source)
	at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source)
	at org.objectweb.asm.util.CheckClassAdapter.verify(Unknown Source)
	at org.objectweb.asm.util.CheckClassAdapter.main(Unknown Source)
Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Incompatible stack heights
	at org.objectweb.asm.tree.analysis.Frame.merge(Unknown Source)
	at org.objectweb.asm.tree.analysis.Analyzer.merge(Unknown Source)
	... 4 more
module$import()V
00000 example . . .  :      :     ACONST_NULL
00001 example . . .  : Lnull;  :     ASTORE 1
00002 example Lnull; . .  :  :     ACONST_NULL
00003 example Lnull; . .  : Lnull;  :     ASTORE 2
00004 example Lnull; Lnull; .  :  :     ACONST_NULL
00005 example Lnull; Lnull; .  : Lnull;  :     ASTORE 3
00006 example Lnull; Lnull; Lnull;  :  :     GETSTATIC python/sys.modules : Lorg/python/types/Dict;
00007 example Lnull; Lnull; Lnull;  : Dict  :     NEW org/python/types/Str
00008 example Lnull; Lnull; Lnull;  : Dict Str  :     DUP
00009 example Lnull; Lnull; Lnull;  : Dict Str Str  :     LDC "example"
00010 example Lnull; Lnull; Lnull;  : Dict Str Str String  :     INVOKESPECIAL org/python/types/Str.<init> (Ljava/lang/String;)V
00011 example Lnull; Lnull; Lnull;  : Dict Str  :     INVOKEINTERFACE org/python/Object.__getitem__ (Lorg/python/Object;)Lorg/python/Object;
00012 example Lnull; Lnull; Lnull;  : Object  :     CHECKCAST org/python/types/Module
00013 example Lnull; Lnull; Lnull;  : Module  :     ASTORE 1
00014 example Module Lnull; Lnull;  :  :     ALOAD 1
00015 example Module Lnull; Lnull;  : Module  :     LDC "range"
00016 example Module Lnull; Lnull;  : Module String  :     INVOKEINTERFACE org/python/Object.__getattribute__ (Ljava/lang/String;)Lorg/python/Object;
00017 example Module Lnull; Lnull;  : Object  :     CHECKCAST org/python/Callable
00018 example Module Lnull; Lnull;  : Callable  :     ICONST_1
00019 example Module Lnull; Lnull;  : Callable I  :     ANEWARRAY org/python/Object
00020 example Module Lnull; Lnull;  : Callable Object  :     DUP
00021 example Module Lnull; Lnull;  : Callable Object Object  :     ICONST_0
00022 example Module Lnull; Lnull;  : Callable Object Object I  :     LDC 10
00023 example Module Lnull; Lnull;  : Callable Object Object I J  :     INVOKESTATIC org/python/types/Int.getInt (J)Lorg/python/types/Int;
00024 example Module Lnull; Lnull;  : Callable Object Object I Int  :     AASTORE
00025 example Module Lnull; Lnull;  : Callable Object  :     NEW java/util/HashMap
00026 example Module Lnull; Lnull;  : Callable Object HashMap  :     DUP
00027 example Module Lnull; Lnull;  : Callable Object HashMap HashMap  :     INVOKESPECIAL java/util/HashMap.<init> ()V
00028 example Module Lnull; Lnull;  : Callable Object HashMap  :     INVOKEINTERFACE org/python/Callable.invoke ([Lorg/python/Object;Ljava/util/Map;)Lorg/python/Object;
00029 example Module Lnull; Lnull;  : Object  :     INVOKEINTERFACE org/python/Object.__iter__ ()Lorg/python/Object;
00030 example Module Lnull; Lnull;  : Object  :     ICONST_1
00031 example Module Lnull; Lnull;  : Object I  :     ISTORE 2
00032 example Module I Lnull;  : Object  :     ASTORE 3
00033 example Module I Object  :  :     ALOAD 1
00034 example Module I Object  : Module  :     ALOAD 3
00035 example Module I Object  : Module Object  :     LDC "#for-iter-10d8fbf28"
00036 example Module I Object  : Module Object String  :     SWAP
00037 example Module I Object  : Module String Object  :     INVOKEINTERFACE org/python/Object.__setattr__ (Ljava/lang/String;Lorg/python/Object;)V
00038 example Module I Object  :  :    L0
00039 example Module I Object  :  :     ALOAD 1
00040 example Module I Object  : Module  :     LDC "#for-iter-10d8fbf28"
00041 example Module I Object  : Module String  :     INVOKEINTERFACE org/python/Object.__getattribute__ (Ljava/lang/String;)Lorg/python/Object;
00042 example Module I Object  : Object  :     INVOKEINTERFACE org/python/Object.__next__ ()Lorg/python/Object;
00043 example Module I Object  : Object  :    L1
00044 example Module I Object  : Object  :     GOTO L2
00045 example Module I Object  : StopIteration  :    L3
00046 example Module I Object  : StopIteration  :     POP
00047 example Module I Object  :  :     GOTO L4
00048 example Module I Object  : Object  :    L2
00049 example Module I Object  : Object  :     ASTORE 3
00050 example Module I Object  :  :     ALOAD 1
00051 example Module I Object  : Module  :     ALOAD 3
00052 example Module I Object  : Module Object  :     LDC "i"
00053 example Module I Object  : Module Object String  :     SWAP
00054 example Module I Object  : Module String Object  :     INVOKEINTERFACE org/python/Object.__setattr__ (Ljava/lang/String;Lorg/python/Object;)V
00055 example Module I Object  :  :     NEW org/python/types/Str
00056 example Module I Object  : Str  :     DUP
00057 example Module I Object  : Str Str  :     LDC "abc"
00058 example Module I Object  : Str Str String  :     INVOKESPECIAL org/python/types/Str.<init> (Ljava/lang/String;)V
00059 example Module I Object  : Str  :     NEW org/python/types/Str
00060 example Module I Object  : Str Str  :     DUP
00061 example Module I Object  : Str Str Str  :     LDC "def"
00062 example Module I Object  : Str Str Str String  :     INVOKESPECIAL org/python/types/Str.<init> (Ljava/lang/String;)V
00063 example Module I Object  : Str Str  :     LDC "=="
00064 example Module I Object  : Str Str String  :     LDC "__eq__"
00065 example Module I Object  : Str Str String String  :     LDC "__eq__"
00066 example Module I Object  : Str Str String String String  :     INVOKESTATIC org/python/types/Object.__cmp__ (Lorg/python/Object;Lorg/python/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/python/Object;
00067 example Module I Object  : Object  :     GOTO L0
00068 example Module I Object  :  :    L4
00069 example Module I Object  :  :     ALOAD 1
00070 example Module I Object  : Module  :     LDC "#for-iter-10d8fbf28"
00071 example Module I Object  : Module String  :     INVOKEINTERFACE org/python/Object.__delattr__ (Ljava/lang/String;)V
00072 example Module I Object  :  :     RETURN
     TRYCATCHBLOCK L0 L1 L3 org/python/exceptions/StopIteration

@freakboy3742 The bug I mentioned to you yesterday seems to be related to this issue as well. It appears that not only for for-loop, expression statement in while-loop and try-catch suite will throw the same incompatible stack heights error.

My gut feeling tells me that it has to do with this part of code in visit_Expr:

# If the expression is a call, we need to ignore
# any return value from the function.
if isinstance(node.value, (ast.Call, ast.Attribute, ast.Str)):
    self.context.add_opcodes(
        JavaOpcodes.POP()
    )

I removed the isinstance check from the condition so it will always pop the expression off the stack and after that no more incompatible stack heights error 😄 .

I'm currently running local test suite to see if this fix introduces any regression and submit a PR if all is well.

Merged, so closing! Thanks @BPYap!