package com.oracle.truffle.js.test.instrumentation;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.BinaryOperationTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.FunctionCallTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.LiteralTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ReadPropertyTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.UnaryOperationTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.WritePropertyTag;
import com.oracle.truffle.js.runtime.objects.JSDynamicObject;
import com.oracle.truffle.js.runtime.objects.Undefined;
public class UnaryOperationTest extends FineGrainedAccessTest {
@Test
public void typeof() {
evalAllTags("var b = typeof Uint8Array;");
enter(WritePropertyTag.class, (e, write) -> {
assertAttribute(e, KEY, "b");
write.input(assertGlobalObjectInput);
enter(UnaryOperationTag.class, (e2, unary) -> {
assertAttribute(e2, OPERATOR, "typeof");
enter(ReadPropertyTag.class, (e3, prop) -> {
assertAttribute(e3, KEY, "Uint8Array");
prop.input((e4) -> {
assertTrue(JSDynamicObject.isJSDynamicObject(e4.val));
});
}).exit();
unary.input(assertJSFunctionInput);
}).exit();
write.input("function");
}).exit();
}
@Test
public void voidMethod() {
evalAllTags("void function foo() {}();");
enter(UnaryOperationTag.class, (e2, unary) -> {
assertAttribute(e2, OPERATOR, "void");
enter(FunctionCallTag.class, (e3, call) -> {
enter(LiteralTag.class).exit();
call.input(assertUndefinedInput);
enter(LiteralTag.class).exit();
call.input(assertJSFunctionInput);
}).exit(assertReturnValue(Undefined.instance));
unary.input(Undefined.instance);
}).exit();
}
@Test
public void bitwiseNot() {
assertBasicUnaryOperation("var x = true; var b = ~x;", true, true, -2, "~");
}
@Test
public void not() {
assertBasicUnaryOperation("var x = true; var b = !x;", true, true, false, "!");
}
@Test
public void minus() {
assertBasicUnaryOperation("var x = true; var b = -x;", true, true, -1, "-");
}
@Test
public void plus() {
assertBasicUnaryOperation("var x = true; var b = +x;", true, true, 1, "+");
}
private void assertBasicUnaryOperation(String src, Object expectedLiteralValue, Object expectedPreUnaryOpValue, Object expectedPostUnaryOpValue, String operator) {
evalAllTags(src);
assertGlobalVarDeclaration("x", true);
enter(WritePropertyTag.class, (e, write) -> {
assertAttribute(e, KEY, "b");
write.input(assertGlobalObjectInput);
enter(UnaryOperationTag.class, (e2, unary) -> {
assertAttribute(e2, OPERATOR, operator);
enter(ReadPropertyTag.class, (e3, prop) -> {
assertAttribute(e3, KEY, "x");
prop.input(assertGlobalObjectInput);
}).exit(assertReturnValue(expectedLiteralValue));
unary.input(expectedPreUnaryOpValue);
}).exit();
write.input(expectedPostUnaryOpValue);
}).exit();
}
@Test
public void complement() {
evalAllTags("0 & (~-1073741824);");
enter(BinaryOperationTag.class, (e, b) -> {
enter(LiteralTag.class).exit(assertReturnValue(0));
b.input(0);
enter(UnaryOperationTag.class, (e2, u) -> {
enter(LiteralTag.class).exit(assertReturnValue(-1073741824));
u.input(-1073741824);
}).exit(assertReturnValue(1073741823));
b.input(1073741823);
}).exit();
}
}