/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.dsl.test;
import static org.junit.Assert.assertEquals;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.dsl.test.ExecuteGroupingTestFactory.ExecuteGrouping1NodeGen;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
/*
* This test aims to test the reuse of execute methods with evaluated parameters as much as possible.
*/
@RunWith(Theories.class)
public class ExecuteGroupingTest {
@DataPoints public static final Object[] parameters = new Object[]{1, 2};
static final class ExecuteGroupingChild extends Node {
int invocationCount = 0;
private final Object returnValue;
ExecuteGroupingChild(Object returnValue) {
this.returnValue = returnValue;
}
Object execute() {
invocationCount++;
return returnValue;
}
}
@Theory
public void testExecuteGrouping1Node(Object a, Object b, Object c) throws UnexpectedResultException {
ExecuteGroupingChild child0 = new ExecuteGroupingChild(a);
ExecuteGroupingChild child1 = new ExecuteGroupingChild(b);
ExecuteGroupingChild child2 = new ExecuteGroupingChild(c);
int result = ((int) a) + ((int) b) + ((int) c);
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(child0, child1, child2)).execute());
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(child0, child1, child2)).execute((VirtualFrame) null));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, child1, child2)).execute(a));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, child1, child2)).executeInt(a));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute(a, b));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute((int) a, b));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute(a, (int) b));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute((int) a, (int) b));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).executeInt((int) a, (int) b));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute(a, b, c));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute((int) a, (int) b, c));
assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute((int) a, (int) b, (int) c));
}
@NodeChild(type = ExecuteGroupingChild.class)
@NodeChild(type = ExecuteGroupingChild.class)
@NodeChild(type = ExecuteGroupingChild.class)
abstract static class ExecuteGrouping1Node extends Node {
abstract Object execute();
int executeInt() throws UnexpectedResultException {
Object value = execute();
if (value instanceof Integer) {
return (int) value;
}
throw new UnexpectedResultException(value);
}
abstract double executeDouble() throws UnexpectedResultException;
abstract Object execute(VirtualFrame frame);
abstract Object execute(Object o1);
abstract int executeInt(Object o1) throws UnexpectedResultException;
abstract Object execute(Object o1, Object o2);
abstract Object execute(int o1, int o2);
abstract Object execute(int o1, int o2, Object o3);
abstract int executeInt(int o1, int o2) throws UnexpectedResultException;
abstract Object execute(Object o1, int o2);
abstract Object execute(int o1, Object o2);
abstract Object execute(Object o1, Object o2, Object o3);
abstract Object execute(int o1, int o2, int o3);
@Specialization
int s1(int a, int b, int c) {
return a + b + c;
}
@Specialization
int s2(Object a, Object b, Object c) {
return ((int) a) + ((int) b) + ((int) c);
}
}
abstract static class StrangeReturnCase extends Node {
// we don't know how to implement executeDouble
public abstract double executeDouble();
public int executeInt() {
return 42;
}
@Specialization(rewriteOn = RuntimeException.class)
double s1() {
return 42;
}
@Specialization
double s2() {
return 42;
}
}
@ExpectError("Incompatible abstract execute methods found %")
abstract static class IncompatibleAbstract1 extends Node {
// we don't know how to implement executeDouble
abstract double executeDouble();
abstract int executeInt();
@Specialization
double s1() {
return 42;
}
}
abstract static class IncompatibleAbstract2 extends Node {
abstract double executeDouble();
// we can resolve duplicate path errors by making an execute method final
@SuppressWarnings("static-method")
public final int executeInt() {
return 42;
}
@ExpectError("The provided return type \"int\" does not match expected return type \"double\".%")
@Specialization(rewriteOn = RuntimeException.class)
int s1() {
return 42;
}
@Specialization
double s2() {
return 42;
}
}
}