package com.oracle.truffle.js.test.instrumentation;
import org.junit.Test;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.BinaryOperationTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.LiteralTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ReadElementTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ReadPropertyTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.WriteElementTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.WritePropertyTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.LiteralTag.Type;
public class AssignmentExpressions extends FineGrainedAccessTest {
@Test
public void plusEqual() {
assertDesugaredOperation("+=", "+", 39, 3, 42);
}
@Test
public void minEqual() {
assertDesugaredOperation("-=", "-", 45, 3, 42);
}
@Test
public void mulEqual() {
assertDesugaredOperation("*=", "*", 21, 2, 42);
}
@Test
public void divEqual() {
assertDesugaredOperation("/=", "/", 84, 2, 42);
}
@Test
public void andEqual() {
assertDesugaredOperation("&=", "&", 42, 42, 42);
}
@Test
public void orEqual() {
assertDesugaredOperation("^=", "^", 42, 0, 42);
}
@Test
public void lshiftEqual() {
assertDesugaredOperation("<<=", "<<", 42, 0, 42);
}
@Test
public void rshiftEqual() {
assertDesugaredOperation(">>=", ">>", 42, 0, 42);
}
@Test
public void plusEqualElem() {
evalAllTags("var a = [42]; a[0] += 1;");
enter(WritePropertyTag.class, (e, write) -> {
assertAttribute(e, KEY, "a");
write.input(assertGlobalObjectInput);
enter(LiteralTag.class, (e2) -> {
assertAttribute(e2, LITERAL_TYPE, Type.ArrayLiteral.name());
}).exit();
write.input(assertJSArrayInput);
}).exit();
enter(WriteElementTag.class, (e, write) -> {
enter(ReadPropertyTag.class).input().exit();
write.input(assertJSArrayInput);
enter(LiteralTag.class).exit(assertReturnValue(0));
write.input(0);
enter(BinaryOperationTag.class, (e1, bin) -> {
assertAttribute(e1, "operator", "+");
enter(ReadElementTag.class, (e2, p) -> {
p.input(assertJSArrayInput);
p.input(0);
}).exit();
bin.input(42);
enter(LiteralTag.class).exit(assertReturnValue(1));
bin.input(1);
}).exit(assertReturnValue(43));
write.input(43);
}).exit(assertReturnValue(43));
}
@Test
public void assignExpr() {
evalWithTags("var a = 42;", new Class[]{WritePropertyTag.class, LiteralTag.class});
enter(WritePropertyTag.class, (e, write) -> {
write.input(assertGlobalObjectInput);
enter(LiteralTag.class).exit(assertReturnValue(42));
write.input(42);
}).exit();
}
private void assertDesugaredOperation(String operation, String desugaredOperator, int initial, int operand, int result) {
evalAllTags("var a = " + initial + "; a " + operation + " " + operand + ";");
assertGlobalVarDeclaration("a", initial);
enter(WritePropertyTag.class, (e, write) -> {
assertAttribute(e, KEY, "a");
write.input(assertGlobalObjectInput);
enter(BinaryOperationTag.class, (e1, bin) -> {
assertAttribute(e1, "operator", desugaredOperator);
enter(ReadPropertyTag.class, (e2, p) -> {
assertAttribute(e2, KEY, "a");
p.input(assertGlobalObjectInput);
}).exit();
bin.input(initial);
enter(LiteralTag.class).exit(assertReturnValue(operand));
bin.input(operand);
}).exit(assertReturnValue(result));
write.input(result);
}).exit();
}
}