Skip to content

Commit

Permalink
✨ feat: Add - for bin expr
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Nov 2, 2024
1 parent 3af82ed commit 687ee63
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 14 deletions.
5 changes: 5 additions & 0 deletions scripts/ts/test/test.basic.operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class Test {
return a / b;
}

public minus_II_I(a: int, b: int): int {
return -(a + b);
}

public mod_II_I(a: int, b: int): int {
return a % b;
}
Expand Down Expand Up @@ -57,6 +61,7 @@ console.log(new Test().add_II_L(1, 2));
console.log(new Test().add_IL_L(1, 2));
console.log(new Test().add_LI_L(1, 2));
console.log(new Test().divide_II_I(3, 2));
console.log(new Test().minus_II_I(3, 2));
console.log(new Test().mod_II_I(3, 2));
console.log(new Test().multiply_II_I(3, 2));
console.log(new Test().shiftLeft_II_I(3, 2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
import net.bytebuddy.implementation.bytecode.constant.LongConstant;

public final class Ts2JavaAstNumber implements ITs2JavaAstStackManipulation<Swc4jAstNumber> {
private final TypeDescription valueType;
private boolean negative;
private TypeDescription valueType;

public Ts2JavaAstNumber() {
this(null);
Expand All @@ -52,8 +52,9 @@ public boolean isNegative() {
@Override
public TypeDescription manipulate(JavaFunctionContext functionContext, Swc4jAstNumber ast) {
StackManipulation stackManipulation;
if (valueType == null) {
valueType = ast.getRaw()
TypeDescription type = valueType;
if (type == null) {
type = ast.getRaw()
.map(raw -> {
if (StringUtils.isNotEmpty(raw)) {
if (raw.contains(".")) {
Expand All @@ -72,22 +73,22 @@ public TypeDescription manipulate(JavaFunctionContext functionContext, Swc4jAstN
})
.orElse(TypeDescription.ForLoadedType.of(int.class));
}
if (valueType.represents(int.class) || valueType.represents(short.class) || valueType.represents(byte.class)) {
if (type.represents(int.class) || type.represents(short.class) || type.represents(byte.class)) {
stackManipulation = IntegerConstant.forValue(negative ? -ast.asInt() : ast.asInt());
} else if (valueType.represents(long.class)) {
} else if (type.represents(long.class)) {
stackManipulation = LongConstant.forValue(negative ? -ast.asLong() : ast.asLong());
} else if (valueType.represents(float.class)) {
} else if (type.represents(float.class)) {
stackManipulation = FloatConstant.forValue(negative ? -ast.asFloat() : ast.asFloat());
} else if (valueType.represents(double.class)) {
} else if (type.represents(double.class)) {
stackManipulation = DoubleConstant.forValue(negative ? -ast.asDouble() : ast.asDouble());
} else {
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("Number type ${type} is not supported.",
SimpleMap.of("type", valueType.getName())));
SimpleMap.of("type", type.getName())));
}
functionContext.getStackManipulations().add(stackManipulation);
return valueType;
return type;
}

public Ts2JavaAstNumber setNegative(boolean negative) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,75 @@
import com.caoccao.javet.utils.SimpleFreeMarkerFormat;
import com.caoccao.javet.utils.SimpleMap;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;

public final class Ts2JavaAstUnaryExpr implements ITs2JavaAstStackManipulation<Swc4jAstUnaryExpr> {
private int getOpcodeNegative(Swc4jAstUnaryExpr ast, TypeDescription type) {
if (type.represents(int.class)
|| type.represents(byte.class)
|| type.represents(char.class)
|| type.represents(short.class)) {
return Opcodes.INEG;
} else if (type.represents(long.class)) {
return Opcodes.LNEG;
} else if (type.represents(float.class)) {
return Opcodes.FNEG;
} else if (type.represents(double.class)) {
return Opcodes.DNEG;
} else {
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("Minus cannot be applied to type ${type}.",
SimpleMap.of("type", type.getName())));
}
}

@Override
public TypeDescription manipulate(JavaFunctionContext functionContext, Swc4jAstUnaryExpr ast) {
ISwc4jAstExpr arg = ast.getArg().unParenExpr();
switch (ast.getOp()) {
case Bang:
switch (arg.getType()) {
case BinExpr:
return new Ts2JavaAstBinExpr().setLogicalNot(true).manipulate(
functionContext, arg.as(Swc4jAstBinExpr.class));
return new Ts2JavaAstBinExpr()
.setLogicalNot(true)
.manipulate(functionContext, arg.as(Swc4jAstBinExpr.class));
default:
throw new Ts2JavaAstException(
arg,
SimpleFreeMarkerFormat.format("UnaryExpr arg type ${argType} for ! is not supported.",
SimpleMap.of("argType", arg.getType().name())));
}
case Minus:
case Minus: {
TypeDescription returnType;
switch (arg.getType()) {
case BinExpr:
returnType = new Ts2JavaAstBinExpr()
.manipulate(functionContext, arg.as(Swc4jAstBinExpr.class));
break;
case Number:
return new Ts2JavaAstNumber().setNegative(true).manipulate(
functionContext, arg.as(Swc4jAstNumber.class));
return new Ts2JavaAstNumber()
.setNegative(true)
.manipulate(functionContext, arg.as(Swc4jAstNumber.class));
default:
throw new Ts2JavaAstException(
arg,
SimpleFreeMarkerFormat.format("UnaryExpr arg type ${argType} for - is not supported.",
SimpleMap.of("argType", arg.getType().name())));
}
final int opcode = getOpcodeNegative(ast, returnType);
StackManipulation stackManipulation = new StackManipulation.Simple((
MethodVisitor methodVisitor,
Implementation.Context implementationContext) -> {
methodVisitor.visitInsn(opcode);
return StackManipulation.Size.ZERO;
});
functionContext.getStackManipulations().add(stackManipulation);
return returnType;
}
default:
throw new Ts2JavaAstException(
ast,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ protected void init() {
}
}

/*
public minus(II)I
L0
LINENUMBER 89 L0
ILOAD 1
ILOAD 2
IADD
INEG
IRETURN
L1
LOCALVARIABLE this Lcom/caoccao/javet/buddy/ts2java/ast/TestBasicOperations; L0 L1 0
LOCALVARIABLE a I L0 L1 1
LOCALVARIABLE b I L0 L1 2
MAXSTACK = 2
MAXLOCALS = 3
*/
public int minus(int a, int b) {
return -(a + b);
}

@Test
public void testAdd_DD_I() throws Exception {
Method method = clazz.getMethod("add_DD_I", double.class, double.class);
Expand All @@ -98,6 +118,19 @@ public void testAdd_DD_I() throws Exception {
assertEquals(1.23D + 2D - 1D, (double) method.invoke(object, 1.23D, 2D), 0.001D);
}

@Test
public void testAdd_FF_I() throws Exception {
Method method = clazz.getMethod("add_FF_I", float.class, float.class);
assertNotNull(method);
assertEquals(float.class, method.getReturnType());
assertEquals(2, method.getParameterCount());
assertEquals(float.class, method.getParameters()[0].getType());
assertEquals(float.class, method.getParameters()[1].getType());
Object object = clazz.getConstructor().newInstance();
assertEquals(1F + 2F - 1F, (float) method.invoke(object, 1F, 2F), 0.001F);
assertEquals(1.23F + 2F - 1F, (float) method.invoke(object, 1.23F, 2F), 0.001F);
}

@Test
public void testAdd_II_I() throws Exception {
assertEquals(3, add(1, 2));
Expand Down Expand Up @@ -162,6 +195,19 @@ public void testDivide_II_I() throws Exception {
assertEquals(3 / 2, method.invoke(object, 3, 2));
}

@Test
public void testMinus_II_I() throws Exception {
assertEquals(-5, minus(3, 2));
Method method = clazz.getMethod("minus_II_I", int.class, int.class);
assertNotNull(method);
assertEquals(int.class, method.getReturnType());
assertEquals(2, method.getParameterCount());
assertEquals(int.class, method.getParameters()[0].getType());
assertEquals(int.class, method.getParameters()[1].getType());
Object object = clazz.getConstructor().newInstance();
assertEquals(-5, method.invoke(object, 3, 2));
}

@Test
public void testMod_II_I() throws Exception {
Method method = clazz.getMethod("mod_II_I", int.class, int.class);
Expand Down

0 comments on commit 687ee63

Please sign in to comment.