@@ -40,12 +40,163 @@ import com.github.jonathanxd.codeapi.bytecode.util.CodePartUtil
4040import com.github.jonathanxd.codeapi.bytecode.util.IfUtil
4141import com.github.jonathanxd.codeapi.bytecode.util.OperatorUtil
4242import com.github.jonathanxd.codeapi.common.Data
43+ import com.github.jonathanxd.codeapi.common.IfGroup
4344import com.github.jonathanxd.codeapi.gen.visit.VisitorGenerator
4445import com.github.jonathanxd.codeapi.literal.Literals
46+ import com.github.jonathanxd.codeapi.operator.Operator
4547import com.github.jonathanxd.codeapi.operator.Operators
4648import org.objectweb.asm.Label
4749import org.objectweb.asm.Opcodes
4850
51+ fun visit (expressions : List <CodePart >,
52+ ifStart : Label ,
53+ ifBody : Label ,
54+ outOfIf : Label ,
55+ isWhile : Boolean ,
56+ extraData : Data ,
57+ visitorGenerator : VisitorGenerator <BytecodeClass >,
58+ mvData : MVData ,
59+ nextIsOr : Boolean = false) {
60+
61+ val visitor = mvData.methodVisitor
62+
63+ var index = 0
64+
65+ fun hasOr () =
66+ index + 1 < expressions.size
67+ && expressions.slice((index + 1 ).. (expressions.size - 1 )).takeWhile { it !is IfGroup }.any { it is Operator && it.name == Operators .OR .name }
68+
69+ fun nextIsOr () =
70+ if (index + 1 < expressions.size)
71+ (expressions[index + 1 ]).let { it is Operator && it.name == Operators .OR .name }
72+ else nextIsOr // fix for ifGroup
73+
74+ var orLabel: Label ? = null
75+
76+ while (index < expressions.size) {
77+ val expr = expressions[index]
78+
79+ val inverse = ! nextIsOr() || isWhile
80+
81+ val jumpLabel = if (hasOr() && ! nextIsOr()) {
82+ if (orLabel == null ) {
83+ orLabel = Label ()
84+ }
85+ orLabel
86+ } else if (isWhile) ifStart else if (inverse) outOfIf else ifBody
87+
88+ if (expr is IfExpr ) {
89+ if (index - 1 > 0 && expressions[index - 1 ].let { it is Operator && it.name == Operators .OR .name } )
90+ orLabel?.let { visitor.visitLabel(it) }
91+
92+ val expr1 = expr.expr1
93+ val operation = expr.operation
94+ val expr2 = expr.expr2
95+
96+ genBranch(expr1, expr2, operation, jumpLabel, inverse, extraData, visitorGenerator, mvData)
97+ }
98+
99+ if (expr is IfGroup ) {
100+ visit(expr.expressions, ifStart, ifBody, outOfIf, isWhile, extraData, visitorGenerator, mvData, nextIsOr())
101+ }
102+
103+ ++ index
104+ }
105+
106+ }
107+
108+ fun genBranch (expr1_ : CodePart , expr2_ : CodePart , operation : Operator .Conditional , target : Label , inverse : Boolean , extraData : Data , visitorGenerator : VisitorGenerator <BytecodeClass >, mvData : MVData ) {
109+
110+ var expr1 = expr1_
111+ var expr2 = expr2_
112+
113+ val expr1Type = CodePartUtil .getType(expr1)
114+ val expr2Type = CodePartUtil .getType(expr2)
115+
116+ val expr1Primitive = CodePartUtil .isPrimitive(expr1)
117+ val expr2Primitive = CodePartUtil .isPrimitive(expr2)
118+
119+ val firstIsBoolean = expr1Primitive && CodePartUtil .isBoolean(expr1)
120+ val secondIsBoolean = expr2Primitive && CodePartUtil .isBoolean(expr2)
121+
122+ if (firstIsBoolean || secondIsBoolean) {
123+ val operatorIsEq = operation == = Operators .EQUAL_TO
124+ val value = if (firstIsBoolean) CodePartUtil .getBooleanValue(expr1) else CodePartUtil .getBooleanValue(expr2)
125+ var opcode = IfUtil .getIfNeEqOpcode(value)
126+
127+ if (! operatorIsEq)
128+ opcode = IfUtil .invertIfNeEqOpcode(opcode)
129+
130+ if (inverse)
131+ opcode = IfUtil .invertIfNeEqOpcode(opcode)
132+
133+ if (firstIsBoolean) {
134+ visitorGenerator.generateTo(expr2::class .java, expr2, extraData, null , mvData)
135+ mvData.methodVisitor.visitJumpInsn(opcode, target)
136+ } else {
137+ visitorGenerator.generateTo(expr1::class .java, expr1, extraData, null , mvData)
138+ mvData.methodVisitor.visitJumpInsn(opcode, target)
139+ }
140+
141+ } else {
142+ // Old Code ->
143+ // TODO: Rewrite
144+
145+ if (expr1Primitive != expr2Primitive) {
146+
147+ if (expr2Primitive) {
148+ expr1 = CodeAPI .cast(expr1Type, expr2Type, expr1)
149+ } else {
150+ expr2 = CodeAPI .cast(expr2Type, expr1Type, expr2)
151+ }
152+ }
153+
154+ visitorGenerator.generateTo(expr1::class .java, expr1, extraData, null , mvData)
155+
156+ if (expr2 == = Literals .NULL ) {
157+ mvData.methodVisitor.visitJumpInsn(OperatorUtil .nullCheckToAsm(operation, inverse), target)
158+ } else if (CodePartUtil .isPrimitive(expr1) && CodePartUtil .isPrimitive(expr2)) {
159+ visitorGenerator.generateTo(expr2::class .java, expr2, extraData, null , mvData)
160+
161+ val firstType = CodePartUtil .getType(expr1)
162+ val secondType = CodePartUtil .getType(expr2)
163+
164+ if (! firstType.`is `(secondType))
165+ throw IllegalArgumentException (" '$expr1 ' and '$expr2 ' have different types, cast it to correct type." )
166+
167+ var generateCMPCheck = false
168+
169+ if (expr1Type.`is `(Types .LONG )) {
170+ mvData.methodVisitor.visitInsn(Opcodes .LCMP )
171+ generateCMPCheck = true
172+ } else if (expr1Type.`is `(Types .DOUBLE )) {
173+ mvData.methodVisitor.visitInsn(Opcodes .DCMPG )
174+ generateCMPCheck = true
175+ } else if (expr1Type.`is `(Types .FLOAT )) {
176+ mvData.methodVisitor.visitInsn(Opcodes .FCMPG )
177+ generateCMPCheck = true
178+ }
179+
180+ var check = OperatorUtil .primitiveToAsm(operation, inverse)
181+
182+ if (generateCMPCheck) {
183+ check = OperatorUtil .convertToSimpleIf(check)
184+ }
185+
186+ mvData.methodVisitor.visitJumpInsn(check, target)
187+ } else {
188+ visitorGenerator.generateTo(expr2::class .java, expr2, extraData, null , mvData)
189+
190+ mvData.methodVisitor.visitJumpInsn(OperatorUtil .referenceToAsm(operation, inverse), target)
191+ }
192+ }
193+ }
194+
195+ @Deprecated(
196+ message = " Too much bugs, don't supports IfGroup, generate incorrect if bytecode, the source of the devil... Deprecated since: 3.2. Will be removed in 4.0" ,
197+ level = DeprecationLevel .ERROR ,
198+ replaceWith = ReplaceWith (" visit(ifStatement.expressions, ifStartLabel, ifBody, outOfIfLabel, jumpToStart, extraData, visitorGenerator, mvData)" )
199+ )
49200fun visit (ifStatement : IfStatement ,
50201 ifStartLabel : Label ,
51202 outOfIfLabel : Label ,
@@ -79,7 +230,8 @@ fun visit(ifStatement: IfStatement,
79230 if (current is IfExpr ) {
80231 val isInverse = ! revert == (next == null || next != = Operators .OR )
81232
82- val lbl = if (ifStatement is SwitchVisitor .SwitchIfStatement ) { // Workaround ?
233+ val lbl = if (ifStatement is SwitchVisitor .SwitchIfStatement ) {
234+ // Workaround ?
83235 extraData.getRequired<Flow >(ConstantDatas .FLOW_TYPE_INFO ).insideEnd
84236 } else {
85237 if (jumpToStart) ifStartLabel else if (! isInverse) inIfLabel else elseLabel ? : outOfIfLabel // Jump to else if exists
0 commit comments