JWebAssembly/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java
2020-05-27 21:21:50 +02:00

638 lines
17 KiB
Java

/*
* Copyright 2018 - 2020 Volker Berlin (i-net software)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.inetsoftware.jwebassembly.runtime;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.ClassRule;
import org.junit.runners.Parameterized.Parameters;
import de.inetsoftware.jwebassembly.ScriptEngine;
import de.inetsoftware.jwebassembly.WasmRule;
import de.inetsoftware.jwebassembly.api.annotation.Export;
public class ControlFlowOperators extends AbstractBaseTest {
@ClassRule
public static WasmRule rule = new WasmRule( TestClass.class );
public ControlFlowOperators( ScriptEngine script, String method, Object[] params ) {
super( rule, script, method, params );
}
@Parameters( name = "{0}-{1}" )
public static Collection<Object[]> data() {
ArrayList<Object[]> list = new ArrayList<>();
for( ScriptEngine script : ScriptEngine.testEngines() ) {
addParam( list, script, "ifeq" );
addParam( list, script, "ifne" );
addParam( list, script, "iflt" );
addParam( list, script, "ifMultiple" );
addParam( list, script, "ifMultipleDouble" );
addParam( list, script, "ifCompare" );
addParam( list, script, "switchDirect" );
addParam( list, script, "endlessLoop" );
addParam( list, script, "doWhileLoop" );
addParam( list, script, "doWhileLoopTwoConditions" );
addParam( list, script, "doWhileLoopWithBreak" );
addParam( list, script, "whileLoop" );
addParam( list, script, "forLoop" );
addParam( list, script, "conditionalOperator" );
addParam( list, script, "conditionalOperator2" );
addParam( list, script, "redifineVariable" );
addParam( list, script, "ifAnd_0" );
addParam( list, script, "ifAnd_3" );
addParam( list, script, "ifAnd_6" );
addParam( list, script, "if4And_6" );
addParam( list, script, "if4And_7" );
addParam( list, script, "ifOr0" );
addParam( list, script, "ifOr1" );
addParam( list, script, "ifOr3" );
addParam( list, script, "ifOr5" );
addParam( list, script, "ifOr7" );
addParam( list, script, "ifAndOr0" );
addParam( list, script, "ifAndOr2" );
addParam( list, script, "ifAndOr4" );
addParam( list, script, "ifAndOr6" );
addParam( list, script, "ifAndOr8" );
addParam( list, script, "ifAndOrComplex" );
addParam( list, script, "ifWithoutElseAndLoop" );
addParam( list, script, "ifOrWithMulti" );
addParam( list, script, "ifMultipleInsideThen" );
addParam( list, script, "stringSwitchNormalFoo" );
addParam( list, script, "stringSwitchNormalBar" );
addParam( list, script, "stringSwitchNormalDefault" );
addParam( list, script, "stringSwitchReverseFoo" );
addParam( list, script, "stringSwitchReverseBar" );
addParam( list, script, "stringSwitchReverseDefault" );
addParam( list, script, "stringSwitchContinue1" );
addParam( list, script, "stringSwitchContinue2" );
addParam( list, script, "stringSwitchContinueDefault" );
}
rule.setTestParameters( list );
return list;
}
static class TestClass {
@Export
static int ifeq() {
int condition = 0;
if( condition != 0 ) {
return 13;
} else {
return 76;
}
}
@Export
static int ifne() {
int condition = 3;
if( condition == 0 ) {
return 13;
} else {
return 76;
}
}
@Export
static int iflt() {
int condition = 3;
if( condition >= 0 ) {
condition = 13;
} else {
condition = 76;
}
return condition;
}
@Export
static int ifMultiple() {
int condition = 3;
if( condition <= 0 ) {
if( condition < 0 ) {
condition = 13;
}
} else {
if( condition > 0 ) {
condition++;
} else {
condition--;
}
}
if( condition > 2 ) {
condition++;
} else {
condition = 0;
}
if( condition >= 2 ) {
condition++;
} else {
condition = 0;
}
if( condition <= 123 ) {
condition++;
} else {
condition = 0;
}
if( condition < 123 ) {
condition++;
} else {
condition = 0;
}
if( condition != 123 ) {
condition++;
} else {
condition = 0;
}
return condition;
}
@Export
static int ifMultipleDouble() {
double condition = 3;
if( condition <= 0 ) {
if( condition < 0 ) {
condition = 13;
}
} else {
if( condition > 0 ) {
condition++;
} else {
condition--;
}
}
if( condition > 2 ) {
condition *= 2;
} else {
condition = 0;
}
if( condition >= 2 ) {
condition *= 2;
} else {
condition = 0;
}
if( condition <= 123 ) {
condition *= 2;
} else {
condition = 0;
}
if( condition < 123 ) {
condition *= 2;
} else {
condition = 0;
}
if( condition != 123 ) {
condition *= 2;
} else {
condition = 0;
}
if( condition == 123 ) {
condition = 0;
} else {
condition *= 2;
}
int x = (int)(25 / condition); // prevent 0 as value
return (int)condition;
}
@Export
static int ifCompare() {
double condition = 3.0;
int result;
if( condition >= 3.5 ) {
result = 13;
} else {
result = 76;
}
return result;
}
@Export
static int switchDirect() {
return tableSwitch(10) + (tableSwitch( 9 ) * 10) + (tableSwitch( -1 ) * 100) + (lookupSwitch(Integer.MAX_VALUE) * 1000) + (lookupSwitch(0) * 10000 );
}
private static int tableSwitch( int a ) {
int b;
switch( 1 + a - 1 ){
case 8:
case 9:
b = 2;
break;
case 10:
case 11:
b = 1;
break;
default:
b = 9;
}
return b;
}
private static int lookupSwitch( int a ) {
int b;
switch(a){
case 1:
b = 1;
break;
case 1000:
case 1001:
if( a == 1000 ) {
b = 2;
break;
} else {
b = 0;
}
//$FALL-THROUGH$
case Integer.MAX_VALUE:
b = 3;
break;
default:
b = 9;
}
return b;
}
@Export
static int endlessLoop() {
int a = 0;
int b = 0;
do {
if( a < 10 ) {
b++;
} else {
return a;
}
a++;
} while( true );
}
@Export
static double doWhileLoop() {
int a = 0;
double d = 1.01;
do {
d *= 2;
a++;
} while( a < 10 );
return d;
}
@Export
static int doWhileLoopTwoConditions() {
int val = 42;
int shift = 1;
do {
val >>>= shift;
} while (val > 7 && shift > 0);
return val;
}
@Export
static double doWhileLoopWithBreak() {
int a = 0;
double d = 1.01;
do {
a++;
if( a == 5 ) {
break;
}
d *= 2;
} while( a < 10 );
return a * d;
}
@Export
static int whileLoop() {
float a = 0;
int b = 1;
while( a < 10 ) {
b *= 2;
a++;
}
return b;
}
@Export
static int forLoop() {
int a = 0;
for( int i = 0; i < 10; i++ ) {
a += i;
}
return a;
}
@Export
static int conditionalOperator () {
int condition = 4;
return condition >= 4 ? condition < 4 ? 1 : 2 : condition == 4 ? 3 : 4;
}
@Export
static int conditionalOperator2() {
int val = 42;
int result = 3 + (val == 1 ? 1 : (val == 2 ? 2 : (val == 3 ? 3 : 4)));
return result;
}
@Export
static double redifineVariable() {
int x = 42;
if( x > 0 ) {
double a = 1;
double b = 2.5;
return a + b;
} else {
int a = 1;
int b = 3;
return a + b;
}
}
@Export
static int ifAnd_0() {
return ifAnd( 0 );
}
@Export
static int ifAnd_3() {
return ifAnd( 3 );
}
@Export
static int ifAnd_6() {
return ifAnd( 6 );
}
private static int ifAnd( int condition ) {
int result;
if( condition > 0 && condition < 5 ) {
result = 42;
} else {
result = 76;
}
return result;
}
@Export
static int if4And_6() {
return if4And( 6 );
}
@Export
static int if4And_7() {
return if4And( 7 );
}
private static int if4And( int condition ) {
int result;
if( condition > 1 && condition > 3 && condition > 5 && condition > 7 ) {
result = 42;
} else {
result = 76;
}
return result;
}
@Export
static int ifOr0() {
return ifOr( 0 );
}
@Export
static int ifOr1() {
return ifOr( 1 );
}
@Export
static int ifOr3() {
return ifOr( 3 );
}
@Export
static int ifOr5() {
return ifOr( 5 );
}
@Export
static int ifOr7() {
return ifOr( 7 );
}
private static int ifOr( int condition ) {
int result;
if( condition == 1 || condition == 3 || condition == 5 || condition == 7 ) {
result = 42;
} else {
result = 76;
}
return result;
}
@Export
static int ifAndOr0() {
return ifAndOr( 0 );
}
@Export
static int ifAndOr2() {
return ifAndOr( 2 );
}
@Export
static int ifAndOr4() {
return ifAndOr( 4 );
}
@Export
static int ifAndOr6() {
return ifAndOr( 6 );
}
@Export
static int ifAndOr8() {
return ifAndOr( 8 );
}
private static int ifAndOr( int condition ) {
int result;
if( (condition >= 1 && condition <= 3) || (condition >= 5 && condition <= 7) ) {
result = 42;
} else {
result = 76;
}
return result;
}
@Export
private static int ifAndOrComplex() {
int b1 = 0;
int b2 = 0;
int result;
if( (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
(b2 & 0xc0) != 0x80) {
result = 13;
} else {
result = 42;
}
return result;
}
private static int ifWithoutElseAndLoop;
@Export
static int ifWithoutElseAndLoop() {
int n = 1;
// because some compiler (Eclipse) move the loop condition to the end of the loop. Then there can be an optimization that the if jump to the end of the loop.
if( ifWithoutElseAndLoop != 1 ) {
ifWithoutElseAndLoop = 1;
}
while( n < 10 ) {
ifWithoutElseAndLoop *= n++;
}
return ifWithoutElseAndLoop;
}
@Export
static int ifOrWithMulti() {
int len = 4;
// the GOTO before the ELSE is not related to the main IF condition
if( (len == 4 || len == 9) ) {
if( len == 9 ) {
len = 13;
} else {
len = 42;
}
}
return len;
}
@Export
static int ifMultipleInsideThen() {
int result = 0;
if( (result == 7) || (result == 13) ) {
// multiple IF inside the primary IF
if( result == -1 ) {
result = 1;
} else {
result = 2;
}
if( result > result ) {
result = 3;
}
} else {
result = 4;
}
return result;
}
@Export
static int stringSwitchNormalFoo() {
return stringSwitchNormal( "foo" );
}
@Export
static int stringSwitchNormalBar() {
return stringSwitchNormal( "bar" );
}
@Export
static int stringSwitchNormalDefault() {
return stringSwitchNormal( "default" );
}
private static int stringSwitchNormal( String tagName ) {
switch( tagName ) {
case "foo":
return 1;
case "bar":
return 2;
default:
return 3;
}
}
@Export
static int stringSwitchReverseFoo() {
return stringSwitchReverse( "foo" );
}
@Export
static int stringSwitchReverseBar() {
return stringSwitchReverse( "bar" );
}
@Export
static int stringSwitchReverseDefault() {
return stringSwitchReverse( "default" );
}
private static int stringSwitchReverse( String tagName ) {
switch( tagName ) {
default:
return 3;
case "bar":
return 2;
case "foo":
return 1;
}
}
@Export
static int stringSwitchContinue1() {
return stringSwitchContinue( "1" );
}
@Export
static int stringSwitchContinue2() {
return stringSwitchContinue( "2" );
}
@Export
static int stringSwitchContinueDefault() {
return stringSwitchContinue( "8" );
}
/**
* Strings have continue hash codes that a compiler could use a tableswitch.
*/
private static int stringSwitchContinue( String tagName ) {
switch( tagName ) {
case "1":
return 1;
case "2":
return 2;
case "3":
return 3;
case "4":
return 4;
case "5":
return 5;
case "6":
return 7;
default:
return 8;
}
}
}
}