Skip to content

Commit

Permalink
🦄 refactor: Redesign ast 14
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Nov 30, 2024
1 parent 8b94791 commit 976bb71
Show file tree
Hide file tree
Showing 5 changed files with 420 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Copyright (c) 2024. caoccao.com Sam Cao
*
* 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 com.caoccao.javet.buddy.ts2java.ast.enums;

import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaException;
import com.caoccao.javet.swc4j.ast.enums.Swc4jAstBinaryOp;
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.*;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;

public final class Ts2JavaAstBinaryOp {
public static final String JAVA_LANG_MATH = "java/lang/Math";

private Ts2JavaAstBinaryOp() {
}

private static Addition getAddition(TypeDescription type) {
if (type.represents(int.class)) {
return Addition.INTEGER;
} else if (type.represents(long.class)) {
return Addition.LONG;
} else if (type.represents(float.class)) {
return Addition.FLOAT;
} else if (type.represents(double.class)) {
return Addition.DOUBLE;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in addition.",
SimpleMap.of("type", type.getName())));
}

public static StackManipulation getArithmeticStackManipulation(Swc4jAstBinaryOp binaryOp, TypeDescription type) {
switch (binaryOp) {
case Add:
return getAddition(type);
case Div:
return getDivision(type);
case LShift:
return getShiftLeft(type);
case Mod:
return getRemainder(type);
case Mul:
return getMultiplication(type);
case RShift:
return getShiftRight(type);
case Sub:
return getSubtraction(type);
case ZeroFillRShift:
return getZeroFillShiftRight(type);
case Exp:
return getExp();
default:
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Binary op ${op} is not supported.",
SimpleMap.of("op", binaryOp.name())));
}
}

private static Division getDivision(TypeDescription type) {
if (type.represents(int.class)) {
return Division.INTEGER;
} else if (type.represents(long.class)) {
return Division.LONG;
} else if (type.represents(float.class)) {
return Division.FLOAT;
} else if (type.represents(double.class)) {
return Division.DOUBLE;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in division.",
SimpleMap.of("type", type.getName())));
}

private static StackManipulation getExp() {
return new StackManipulation.Simple((
MethodVisitor methodVisitor,
Implementation.Context implementationContext) -> {
methodVisitor.visitMethodInsn(
Opcodes.INVOKESTATIC,
JAVA_LANG_MATH,
"pow",
"(DD)D",
false);
return new StackManipulation.Size(-2, 0);
});
}

private static Multiplication getMultiplication(TypeDescription type) {
if (type.represents(int.class)) {
return Multiplication.INTEGER;
} else if (type.represents(long.class)) {
return Multiplication.LONG;
} else if (type.represents(float.class)) {
return Multiplication.FLOAT;
} else if (type.represents(double.class)) {
return Multiplication.DOUBLE;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in multiplication.",
SimpleMap.of("type", type.getName())));
}

private static Remainder getRemainder(TypeDescription type) {
if (type.represents(int.class)) {
return Remainder.INTEGER;
} else if (type.represents(long.class)) {
return Remainder.LONG;
} else if (type.represents(float.class)) {
return Remainder.FLOAT;
} else if (type.represents(double.class)) {
return Remainder.DOUBLE;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in mod.",
SimpleMap.of("type", type.getName())));
}

private static ShiftLeft getShiftLeft(TypeDescription type) {
if (type.represents(int.class)) {
return ShiftLeft.INTEGER;
} else if (type.represents(long.class)) {
return ShiftLeft.LONG;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in left shift.",
SimpleMap.of("type", type.getName())));
}

private static ShiftRight getShiftRight(TypeDescription type) {
if (type.represents(int.class)) {
return ShiftRight.INTEGER;
} else if (type.represents(long.class)) {
return ShiftRight.LONG;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in right shift.",
SimpleMap.of("type", type.getName())));
}

private static Subtraction getSubtraction(TypeDescription type) {
if (type.represents(int.class)) {
return Subtraction.INTEGER;
} else if (type.represents(long.class)) {
return Subtraction.LONG;
} else if (type.represents(float.class)) {
return Subtraction.FLOAT;
} else if (type.represents(double.class)) {
return Subtraction.DOUBLE;
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in subtraction.",
SimpleMap.of("type", type.getName())));
}

private static StackManipulation getZeroFillShiftRight(TypeDescription type) {
if (type.represents(int.class)) {
return new StackManipulation.Simple(
(MethodVisitor methodVisitor, Implementation.Context implementationContext) -> {
methodVisitor.visitInsn(Opcodes.IUSHR);
return new StackManipulation.Size(-1, 0);
});
} else if (type.represents(long.class)) {
return new StackManipulation.Simple(
(MethodVisitor methodVisitor, Implementation.Context implementationContext) -> {
methodVisitor.visitInsn(Opcodes.L2I);
methodVisitor.visitInsn(Opcodes.LUSHR);
return new StackManipulation.Size(-2, 0);
});
}
throw new Ts2JavaException(
SimpleFreeMarkerFormat.format("Unsupported type ${type} in zero fill right shift.",
SimpleMap.of("type", type.getName())));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2024. caoccao.com Sam Cao
*
* 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 com.caoccao.javet.buddy.ts2java.ast.expr;

import com.caoccao.javet.buddy.ts2java.ast.BaseTs2JavaAst;
import com.caoccao.javet.buddy.ts2java.ast.enums.Ts2JavaAstBinaryOp;
import com.caoccao.javet.buddy.ts2java.ast.interfaces.ITs2JavaAst;
import com.caoccao.javet.buddy.ts2java.ast.interfaces.ITs2JavaAstExpr;
import com.caoccao.javet.buddy.ts2java.ast.memo.Ts2JavaMemoFunction;
import com.caoccao.javet.buddy.ts2java.compiler.JavaClassCast;
import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaAstException;
import com.caoccao.javet.swc4j.ast.enums.Swc4jAstBinaryOp;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstBinExpr;
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;

public class Ts2JavaAstBinExpr
extends BaseTs2JavaAst<Swc4jAstBinExpr, Ts2JavaMemoFunction>
implements ITs2JavaAstExpr<Swc4jAstBinExpr, Ts2JavaMemoFunction> {
protected final ITs2JavaAstExpr<?, ?> left;
protected final ITs2JavaAstExpr<?, ?> right;
protected Swc4jAstBinaryOp op;

public Ts2JavaAstBinExpr(
ITs2JavaAst<?, ?> parent,
Swc4jAstBinExpr ast,
TypeDescription type,
Ts2JavaMemoFunction memo) {
super(parent, ast, memo);
op = ast.getOp();
if (op.isArithmeticOperator()) {
this.type = type;
} else if (op.isLogicalCompareOperator()) {
this.type = TypeDescription.ForLoadedType.of(void.class);
} else if (op.isLogicalConditionOperator()) {
this.type = TypeDescription.ForLoadedType.of(boolean.class);
}
left = ITs2JavaAstExpr.cast(parent, ast.getLeft(), this.type, memo);
right = ITs2JavaAstExpr.cast(parent, ast.getRight(), this.type, memo);
}

@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context context) {
visitLineNumber(methodVisitor);
Size sizeLoadLeft = left.apply(methodVisitor, context);
Size sizeCastLeft = JavaClassCast.getUpCastStackManipulation(left.getType(), type)
.map(s -> s.apply(methodVisitor, context))
.orElse(Size.ZERO);
Size sizeLoadRight = right.apply(methodVisitor, context);
Size sizeCastRight = JavaClassCast.getUpCastStackManipulation(right.getType(), type)
.map(s -> s.apply(methodVisitor, context))
.orElse(Size.ZERO);
Size sizeLoadAndCast = aggregateSize(sizeLoadLeft, sizeCastLeft, sizeLoadRight, sizeCastRight);
StackManipulation stackManipulation;
if (op.isArithmeticOperator()) {
stackManipulation = Ts2JavaAstBinaryOp.getArithmeticStackManipulation(op, type);
} else {
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("Bin expr op ${op} is not supported.",
SimpleMap.of("op", op.name())));
}
Size sizeOp = stackManipulation.apply(methodVisitor, context);
return aggregateSize(sizeLoadAndCast, sizeOp);
}

@Override
public void compile() {
left.compile();
right.compile();
}

public ITs2JavaAstExpr<?, ?> getLeft() {
return left;
}

public Swc4jAstBinaryOp getOp() {
return op;
}

public ITs2JavaAstExpr<?, ?> getRight() {
return right;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

package com.caoccao.javet.buddy.ts2java.ast.interfaces;

import com.caoccao.javet.buddy.ts2java.ast.expr.Ts2JavaAstBinExpr;
import com.caoccao.javet.buddy.ts2java.ast.expr.Ts2JavaAstIdent;
import com.caoccao.javet.buddy.ts2java.ast.expr.Ts2JavaAstUnaryExpr;
import com.caoccao.javet.buddy.ts2java.ast.expr.lit.Ts2JavaAstBool;
import com.caoccao.javet.buddy.ts2java.ast.expr.lit.Ts2JavaAstNumber;
import com.caoccao.javet.buddy.ts2java.ast.memo.Ts2JavaMemo;
import com.caoccao.javet.buddy.ts2java.ast.memo.Ts2JavaMemoFunction;
import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaAstException;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstBinExpr;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstIdent;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstParenExpr;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstUnaryExpr;
Expand All @@ -42,6 +44,8 @@ public interface ITs2JavaAstExpr<AST extends ISwc4jAstExpr, Memo extends Ts2Java
TypeDescription type,
Ts2JavaMemoFunction memo) {
switch (ast.getType()) {
case BinExpr:
return new Ts2JavaAstBinExpr(parent, ast.as(Swc4jAstBinExpr.class), type, memo);
case Bool:
return new Ts2JavaAstBool(parent, ast.as(Swc4jAstBool.class), type, memo);
case Ident:
Expand All @@ -52,7 +56,6 @@ public interface ITs2JavaAstExpr<AST extends ISwc4jAstExpr, Memo extends Ts2Java
return cast(parent, ast.as(Swc4jAstParenExpr.class).unParenExpr(), type, memo);
case UnaryExpr:
return new Ts2JavaAstUnaryExpr(parent, ast.as(Swc4jAstUnaryExpr.class), type, memo);
case BinExpr:
default:
throw new Ts2JavaAstException(
ast,
Expand Down
Loading

0 comments on commit 976bb71

Please sign in to comment.