From 4ec0537e2c998093c88e34136ca91c6b60362b85 Mon Sep 17 00:00:00 2001 From: Sam Cao Date: Mon, 28 Oct 2024 10:37:20 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20Replace=20Class=20wi?= =?UTF-8?q?th=20TypeDescription?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/ts/test/test.assignments.ts | 20 +++ scripts/ts/test/test.basic.operations.ts | 10 +- scripts/ts/test/test.sum.ts | 11 -- scripts/ts/test/test.type.aliases.ts | 2 + .../buddy/ts2java/ast/Ts2JavaAstBinExpr.java | 27 ++-- .../ts2java/ast/Ts2JavaAstBindingIdent.java | 7 +- .../ts2java/ast/Ts2JavaAstClassFunction.java | 17 +-- .../buddy/ts2java/ast/Ts2JavaAstParam.java | 8 +- .../ts2java/ast/Ts2JavaAstReturnStmt.java | 4 +- .../ts2java/ast/Ts2JavaAstTsTypeAnn.java | 23 +-- .../JavaByteCodeMethodVariableAccess.java | 36 ----- .../buddy/ts2java/compiler/JavaClassCast.java | 132 +++++++++--------- .../ts2java/compiler/JavaFunctionContext.java | 27 +++- .../ts2java/compiler/JavaStackObject.java | 25 ++-- .../javet/buddy/ts2java/TestAssignments.java | 99 +++++++++++++ .../buddy/ts2java/TestBasicOperations.java | 4 +- 16 files changed, 278 insertions(+), 174 deletions(-) create mode 100644 scripts/ts/test/test.assignments.ts delete mode 100644 scripts/ts/test/test.sum.ts delete mode 100644 src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaByteCodeMethodVariableAccess.java create mode 100644 src/test/java/com/caoccao/javet/buddy/ts2java/TestAssignments.java diff --git a/scripts/ts/test/test.assignments.ts b/scripts/ts/test/test.assignments.ts new file mode 100644 index 0000000..d96bb46 --- /dev/null +++ b/scripts/ts/test/test.assignments.ts @@ -0,0 +1,20 @@ +import { type float, double, int, long } from "./test.type.aliases.ts"; + +class Test { + // public sum(n: int): int { + // let sum: int = 0; + // for (let i: int = 0; i < n; i++) { + // sum += i; + // } + // return sum; + // } + + public assignAndCast(a: int, b: long): double { + let c: long = a; + let d: long = b; + return c + d; + } +} + +// console.log(new Test().sum(10)); +console.log(new Test().assignAndCast(1, 2)); diff --git a/scripts/ts/test/test.basic.operations.ts b/scripts/ts/test/test.basic.operations.ts index 247d5b5..3d4a585 100644 --- a/scripts/ts/test/test.basic.operations.ts +++ b/scripts/ts/test/test.basic.operations.ts @@ -1,4 +1,4 @@ -import { type int, type long } from "./test.type.aliases.ts"; +import { type int, long } from "./test.type.aliases.ts"; class Test { public add_II_I(a: int, b: int): int { @@ -21,11 +21,11 @@ class Test { return a * b; } - public shift_left_II_I(a: int, b: int): int { + public shiftLeft_II_I(a: int, b: int): int { return a << b; } - public shift_right_II_I(a: int, b: int): int { + public shiftRight_II_I(a: int, b: int): int { return a >> b; } @@ -39,6 +39,6 @@ console.log(new Test().add_IL_L(1, 2)); console.log(new Test().divide_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().shift_left_II_I(3, 2)); -console.log(new Test().shift_right_II_I(3, 1)); +console.log(new Test().shiftLeft_II_I(3, 2)); +console.log(new Test().shiftRight_II_I(3, 1)); console.log(new Test().subtract_II_I(3, 2)); diff --git a/scripts/ts/test/test.sum.ts b/scripts/ts/test/test.sum.ts deleted file mode 100644 index 137bd28..0000000 --- a/scripts/ts/test/test.sum.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type int } from "./test.type.aliases.ts"; - -function sum(n: int): int { - let sum: int = 0; - for (let i: int = 0; i < n; i++) { - sum += i; - } - return sum; -} - -console.log(sum(10)); diff --git a/scripts/ts/test/test.type.aliases.ts b/scripts/ts/test/test.type.aliases.ts index 942d38d..38be73f 100644 --- a/scripts/ts/test/test.type.aliases.ts +++ b/scripts/ts/test/test.type.aliases.ts @@ -1,2 +1,4 @@ +export type float = number; +export type double = number; export type int = number; export type long = number; diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBinExpr.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBinExpr.java index 2086e49..f22edaf 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBinExpr.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBinExpr.java @@ -16,7 +16,6 @@ package com.caoccao.javet.buddy.ts2java.ast; -import com.caoccao.javet.buddy.ts2java.compiler.JavaByteCodeMethodVariableAccess; import com.caoccao.javet.buddy.ts2java.compiler.JavaClassCast; import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext; import com.caoccao.javet.buddy.ts2java.compiler.JavaStackObject; @@ -27,7 +26,9 @@ import com.caoccao.javet.utils.SimpleFreeMarkerFormat; import com.caoccao.javet.utils.SimpleList; import com.caoccao.javet.utils.SimpleMap; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.bytecode.StackManipulation; +import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; import java.util.List; import java.util.stream.Collectors; @@ -50,35 +51,37 @@ public void manipulate(JavaFunctionContext functionContext, Swc4jAstBinExpr ast) } }) .collect(Collectors.toList()); - Class upCastClass = JavaClassCast.getUpCastClassForMathOp( - stackObjects.stream().map(JavaStackObject::getType).toArray(Class[]::new)); + TypeDescription upCaseType = JavaClassCast.getUpCastTypeForMathOp( + stackObjects.stream().map(JavaStackObject::getType).toArray(TypeDescription[]::new)); stackObjects.forEach(stackObject -> { - functionContext.getStackManipulations().add(JavaByteCodeMethodVariableAccess.load(stackObject)); - JavaClassCast.getUpCastStackManipulation(stackObject.getType(), upCastClass) + functionContext.getStackManipulations().add( + MethodVariableAccess.of(stackObject.getType()) + .loadFrom(stackObject.getOffset())); + JavaClassCast.getUpCastStackManipulation(stackObject.getType(), upCaseType) .ifPresent(functionContext.getStackManipulations()::add); }); StackManipulation stackManipulation; switch (ast.getOp()) { case Add: - stackManipulation = JavaClassCast.getAddition(upCastClass); + stackManipulation = JavaClassCast.getAddition(upCaseType); break; case Div: - stackManipulation = JavaClassCast.getDivision(upCastClass); + stackManipulation = JavaClassCast.getDivision(upCaseType); break; case LShift: - stackManipulation = JavaClassCast.getShiftLeft(upCastClass); + stackManipulation = JavaClassCast.getShiftLeft(upCaseType); break; case Mod: - stackManipulation = JavaClassCast.getRemainder(upCastClass); + stackManipulation = JavaClassCast.getRemainder(upCaseType); break; case Mul: - stackManipulation = JavaClassCast.getMultiplication(upCastClass); + stackManipulation = JavaClassCast.getMultiplication(upCaseType); break; case RShift: - stackManipulation = JavaClassCast.getShiftRight(upCastClass); + stackManipulation = JavaClassCast.getShiftRight(upCaseType); break; case Sub: - stackManipulation = JavaClassCast.getSubtraction(upCastClass); + stackManipulation = JavaClassCast.getSubtraction(upCaseType); break; default: throw new Ts2JavaAstException( diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBindingIdent.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBindingIdent.java index 7f7f85d..a7f6578 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBindingIdent.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBindingIdent.java @@ -17,14 +17,15 @@ package com.caoccao.javet.buddy.ts2java.ast; import com.caoccao.javet.swc4j.ast.pat.Swc4jAstBindingIdent; +import net.bytebuddy.description.type.TypeDescription; public final class Ts2JavaAstBindingIdent { private Ts2JavaAstBindingIdent() { } - public static Class getClass(Swc4jAstBindingIdent ast) { + public static TypeDescription getTypeDescription(Swc4jAstBindingIdent ast) { return ast.getTypeAnn() - .map(Ts2JavaAstTsTypeAnn::getClass) - .orElse((Class) Object.class); + .map(Ts2JavaAstTsTypeAnn::getTypeDescription) + .orElse(TypeDescription.ForLoadedType.of(Object.class)); } } diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstClassFunction.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstClassFunction.java index 0e48661..3597b3a 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstClassFunction.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstClassFunction.java @@ -22,6 +22,7 @@ import com.caoccao.javet.swc4j.ast.clazz.Swc4jAstFunction; import com.caoccao.javet.swc4j.ast.enums.Swc4jAstAccessibility; import net.bytebuddy.description.modifier.Visibility; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.Implementation; import net.bytebuddy.implementation.bytecode.StackManipulation; @@ -30,7 +31,6 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -import java.util.stream.IntStream; public final class Ts2JavaAstClassFunction implements ITs2JavaAstTranspile { private final boolean _static; @@ -60,18 +60,19 @@ public DynamicType.Builder transpile( DynamicType.Builder builder, Swc4jAstFunction ast) { final Visibility visibility = Ts2JavaAstAccessibility.getVisibility(accessibility); - final Class returnType = ast.getReturnType() - .map(Ts2JavaAstTsTypeAnn::getClass) - .orElse((Class) Object.class); + final TypeDescription returnType = ast.getReturnType() + .map(Ts2JavaAstTsTypeAnn::getTypeDescription) + .orElse(TypeDescription.ForLoadedType.of(Object.class)); final List stackFrames = new ArrayList<>(); - final List stackObjects = IntStream.range(0, ast.getParams().size()) - .mapToObj(i -> Ts2JavaAstParam.getStackObject(i + (_static ? 0 : 1), ast.getParams().get(i))) + final List stackObjects = ast.getParams().stream() + .map(Ts2JavaAstParam::getStackObject) .collect(Collectors.toList()); final JavaStackFrame initialStackFrame = new JavaStackFrame(0, stackObjects); stackFrames.add(initialStackFrame); - final JavaFunctionContext functionContext = new JavaFunctionContext(stackFrames, returnType); + final JavaFunctionContext functionContext = new JavaFunctionContext(_static, stackFrames, returnType); + functionContext.syncOffset(); ast.getBody().ifPresent(blockStmt -> new Ts2JavaAstBlockStmt().manipulate(functionContext, blockStmt)); - final Class[] parameters = functionContext.getParameters(); + final TypeDescription[] parameters = functionContext.getParameters(); final StackManipulation[] stackManipulations = functionContext.getStackManipulations().toArray(new StackManipulation[0]); builder = builder.defineMethod(name, returnType, visibility) diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstParam.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstParam.java index 37ca858..9bbb873 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstParam.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstParam.java @@ -23,18 +23,20 @@ import com.caoccao.javet.swc4j.ast.pat.Swc4jAstBindingIdent; import com.caoccao.javet.utils.SimpleFreeMarkerFormat; import com.caoccao.javet.utils.SimpleMap; +import net.bytebuddy.description.type.TypeDescription; public final class Ts2JavaAstParam { private Ts2JavaAstParam() { } - public static JavaStackObject getStackObject(int index, Swc4jAstParam ast) { + public static JavaStackObject getStackObject(Swc4jAstParam ast) { ISwc4jAstPat pat = ast.getPat(); switch (pat.getType()) { case BindingIdent: String ident = pat.as(Swc4jAstBindingIdent.class).getId().getSym(); - Class type = Ts2JavaAstBindingIdent.getClass(pat.as(Swc4jAstBindingIdent.class)); - return new JavaStackObject(index, ident, type); + TypeDescription typeDescription = + Ts2JavaAstBindingIdent.getTypeDescription(pat.as(Swc4jAstBindingIdent.class)); + return new JavaStackObject(ident, typeDescription); default: throw new Ts2JavaAstException( pat, diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstReturnStmt.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstReturnStmt.java index e0b8c91..520238a 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstReturnStmt.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstReturnStmt.java @@ -22,7 +22,6 @@ import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstReturnStmt; import com.caoccao.javet.utils.SimpleFreeMarkerFormat; import com.caoccao.javet.utils.SimpleMap; -import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.bytecode.StackManipulation; import net.bytebuddy.implementation.bytecode.member.MethodReturn; @@ -41,8 +40,7 @@ public void manipulate(JavaFunctionContext functionContext, Swc4jAstReturnStmt a SimpleMap.of("argType", arg.getType().name()))); } }); - TypeDescription typeDescription = TypeDescription.ForLoadedType.of(functionContext.getReturnType()); - StackManipulation stackManipulation = MethodReturn.of(typeDescription); + StackManipulation stackManipulation = MethodReturn.of(functionContext.getReturnType()); functionContext.getStackManipulations().add(stackManipulation); } } diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstTsTypeAnn.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstTsTypeAnn.java index 8c6ad9f..5eaa71c 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstTsTypeAnn.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstTsTypeAnn.java @@ -21,25 +21,26 @@ import com.caoccao.javet.swc4j.ast.ts.Swc4jAstTsTypeAnn; import com.caoccao.javet.swc4j.ast.ts.Swc4jAstTsTypeRef; import com.caoccao.javet.utils.SimpleMap; +import net.bytebuddy.description.type.TypeDescription; import java.util.Map; public final class Ts2JavaAstTsTypeAnn { - private static final Map> TYPE_MAP = SimpleMap.of( - "boolean", boolean.class, - "byte", byte.class, - "char", char.class, - "double", double.class, - "float", float.class, - "int", int.class, - "long", long.class, - "short", short.class + private static final Map TYPE_MAP = SimpleMap.of( + "boolean", TypeDescription.ForLoadedType.of(boolean.class), + "byte", TypeDescription.ForLoadedType.of(byte.class), + "char", TypeDescription.ForLoadedType.of(char.class), + "double", TypeDescription.ForLoadedType.of(double.class), + "float", TypeDescription.ForLoadedType.of(float.class), + "int", TypeDescription.ForLoadedType.of(int.class), + "long", TypeDescription.ForLoadedType.of(long.class), + "short", TypeDescription.ForLoadedType.of(short.class) ); private Ts2JavaAstTsTypeAnn() { } - public static Class getClass(Swc4jAstTsTypeAnn ast) { + public static TypeDescription getTypeDescription(Swc4jAstTsTypeAnn ast) { ISwc4jAstTsType tsType = ast.getTypeAnn(); switch (tsType.getType()) { case TsTypeRef: @@ -47,7 +48,7 @@ public static Class getClass(Swc4jAstTsTypeAnn ast) { ISwc4jAstTsEntityName tsEntityName = tsTypeRef.getTypeName(); return TYPE_MAP.get(Ts2JavaAstTsEntityName.getName(tsEntityName)); default: - return Object.class; + return TypeDescription.ForLoadedType.of(Object.class); } } } diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaByteCodeMethodVariableAccess.java b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaByteCodeMethodVariableAccess.java deleted file mode 100644 index 25778c8..0000000 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaByteCodeMethodVariableAccess.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.compiler; - -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.StackManipulation; -import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; - -public final class JavaByteCodeMethodVariableAccess { - private JavaByteCodeMethodVariableAccess() { - } - - public static StackManipulation load(JavaStackObject stackObject) { - return MethodVariableAccess.of(TypeDescription.ForLoadedType.of(stackObject.getType())) - .loadFrom(stackObject.getIndex()); - } - - public static StackManipulation store(JavaStackObject stackObject) { - return MethodVariableAccess.of(TypeDescription.ForLoadedType.of(stackObject.getType())) - .storeAt(stackObject.getIndex()); - } -} diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaClassCast.java b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaClassCast.java index e15ad25..3e16412 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaClassCast.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaClassCast.java @@ -29,134 +29,134 @@ public final class JavaClassCast { private JavaClassCast() { } - public static Addition getAddition(Class clazz) { - if (clazz == int.class) { + public static Addition getAddition(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return Addition.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return Addition.LONG; - } else if (clazz == float.class) { + } else if (type.isAssignableTo(float.class)) { return Addition.FLOAT; - } else if (clazz == double.class) { + } else if (type.isAssignableTo(double.class)) { return Addition.DOUBLE; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in addition", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in addition", + SimpleMap.of("type", type.getName()))); } - public static Division getDivision(Class clazz) { - if (clazz == int.class) { + public static Division getDivision(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return Division.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return Division.LONG; - } else if (clazz == float.class) { + } else if (type.isAssignableTo(float.class)) { return Division.FLOAT; - } else if (clazz == double.class) { + } else if (type.isAssignableTo(double.class)) { return Division.DOUBLE; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in division", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in division", + SimpleMap.of("type", type.getName()))); } - public static Multiplication getMultiplication(Class clazz) { - if (clazz == int.class) { + public static Multiplication getMultiplication(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return Multiplication.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return Multiplication.LONG; - } else if (clazz == float.class) { + } else if (type.isAssignableTo(float.class)) { return Multiplication.FLOAT; - } else if (clazz == double.class) { + } else if (type.isAssignableTo(double.class)) { return Multiplication.DOUBLE; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in multiplication", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in multiplication", + SimpleMap.of("type", type.getName()))); } - public static Remainder getRemainder(Class clazz) { - if (clazz == int.class) { + public static Remainder getRemainder(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return Remainder.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return Remainder.LONG; - } else if (clazz == float.class) { + } else if (type.isAssignableTo(float.class)) { return Remainder.FLOAT; - } else if (clazz == double.class) { + } else if (type.isAssignableTo(double.class)) { return Remainder.DOUBLE; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in mod", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in mod", + SimpleMap.of("type", type.getName()))); } - public static ShiftLeft getShiftLeft(Class clazz) { - if (clazz == int.class) { + public static ShiftLeft getShiftLeft(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return ShiftLeft.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return ShiftLeft.LONG; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in left shift", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in left shift", + SimpleMap.of("type", type.getName()))); } - public static ShiftRight getShiftRight(Class clazz) { - if (clazz == int.class) { + public static ShiftRight getShiftRight(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return ShiftRight.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return ShiftRight.LONG; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in right shift", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in right shift", + SimpleMap.of("type", type.getName()))); } - public static Subtraction getSubtraction(Class clazz) { - if (clazz == int.class) { + public static Subtraction getSubtraction(TypeDescription type) { + if (type.isAssignableTo(int.class)) { return Subtraction.INTEGER; - } else if (clazz == long.class) { + } else if (type.isAssignableTo(long.class)) { return Subtraction.LONG; - } else if (clazz == float.class) { + } else if (type.isAssignableTo(float.class)) { return Subtraction.FLOAT; - } else if (clazz == double.class) { + } else if (type.isAssignableTo(double.class)) { return Subtraction.DOUBLE; } throw new Ts2JavaException( - SimpleFreeMarkerFormat.format("Unsupported class ${class} in subtraction", - SimpleMap.of("class", clazz.getName()))); + SimpleFreeMarkerFormat.format("Unsupported type ${type} in subtraction", + SimpleMap.of("type", type.getName()))); } - public static Class getUpCastClassForMathOp(Class... classes) { - final int length = classes.length; + public static Optional getUpCastStackManipulation( + TypeDescription fromTypeDescription, + TypeDescription toTypeDescription + ) { + if (fromTypeDescription.isPrimitive() && toTypeDescription.isPrimitive()) { + return Optional.of(PrimitiveWideningDelegate.forPrimitive(fromTypeDescription).widenTo(toTypeDescription)) + .filter(StackManipulation::isValid); + } + return Optional.empty(); + } + + public static TypeDescription getUpCastTypeForMathOp(TypeDescription... types) { + final int length = types.length; if (length <= 1) { throw new Ts2JavaException("Cannot get up cast class for less than 2 classes"); } - for (Class c : classes) { - if (!c.isPrimitive()) { + for (TypeDescription type : types) { + if (!type.isPrimitive()) { throw new Ts2JavaException( SimpleFreeMarkerFormat.format( "Cannot get up cast class for ${class}", - SimpleMap.of("class", c.getName()))); + SimpleMap.of("class", type.getName()))); } } - Class clazz = classes[0]; + TypeDescription returnType = types[0]; for (int i = 1; i < length; i++) { - Class c = classes[i]; - if (PrimitiveWideningDelegate.forPrimitive(TypeDescription.ForLoadedType.of(clazz)) - .widenTo(TypeDescription.ForLoadedType.of(c)).isValid()) { - clazz = c; + TypeDescription type = types[i]; + if (PrimitiveWideningDelegate.forPrimitive(returnType).widenTo(type).isValid()) { + returnType = type; } } - return clazz; - } - - public static Optional getUpCastStackManipulation(Class clazz, Class upCastClass) { - if (clazz.isPrimitive() && upCastClass.isPrimitive()) { - return Optional.of( - PrimitiveWideningDelegate.forPrimitive(TypeDescription.ForLoadedType.of(clazz)) - .widenTo(TypeDescription.ForLoadedType.of(upCastClass))) - .filter(StackManipulation::isValid); - } - return Optional.empty(); + return returnType; } } diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaFunctionContext.java b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaFunctionContext.java index 925e2e0..af1756e 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaFunctionContext.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaFunctionContext.java @@ -19,6 +19,7 @@ import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaException; import com.caoccao.javet.utils.SimpleFreeMarkerFormat; import com.caoccao.javet.utils.SimpleMap; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.bytecode.StackManipulation; import java.util.ArrayList; @@ -27,23 +28,25 @@ import java.util.stream.IntStream; public final class JavaFunctionContext { - private final Class returnType; + private final boolean _static; + private final TypeDescription returnType; private final List stackFrames; private final List stackManipulations; - public JavaFunctionContext(List stackFrames, Class returnType) { + public JavaFunctionContext(boolean _static, List stackFrames, TypeDescription returnType) { + this._static = _static; this.stackFrames = Objects.requireNonNull(stackFrames); this.returnType = Objects.requireNonNull(returnType); this.stackManipulations = new ArrayList<>(); } - public Class[] getParameters() { + public TypeDescription[] getParameters() { return stackFrames.get(0).getObjects().stream() .map(JavaStackObject::getType) - .toArray(Class[]::new); + .toArray(TypeDescription[]::new); } - public Class getReturnType() { + public TypeDescription getReturnType() { return returnType; } @@ -76,4 +79,18 @@ public JavaStackObject getStackObject(String name) { SimpleFreeMarkerFormat.format("The variable ${name} is not defined", SimpleMap.of("name", name))); } + + public boolean isStatic() { + return _static; + } + + public void syncOffset() { + int offset = _static ? 0 : 1; + for (JavaStackFrame stackFrame : stackFrames) { + for (JavaStackObject stackObject : stackFrame.getObjects()) { + stackObject.setOffset(offset); + offset += stackObject.getType().getStackSize().getSize(); + } + } + } } diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaStackObject.java b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaStackObject.java index 45155c8..abe27dc 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaStackObject.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaStackObject.java @@ -16,26 +16,33 @@ package com.caoccao.javet.buddy.ts2java.compiler; +import net.bytebuddy.description.type.TypeDescription; + public final class JavaStackObject { - private final int index; private final String name; - private final Class type; + private final TypeDescription type; + private int offset; - public JavaStackObject(int index, String name, Class type) { - this.index = index; + public JavaStackObject(String name, TypeDescription type) { this.name = name; + this.offset = 0; this.type = type; } - public int getIndex() { - return index; - } - public String getName() { return name; } - public Class getType() { + public int getOffset() { + return offset; + } + + public TypeDescription getType() { return type; } + + public JavaStackObject setOffset(int offset) { + this.offset = offset; + return this; + } } diff --git a/src/test/java/com/caoccao/javet/buddy/ts2java/TestAssignments.java b/src/test/java/com/caoccao/javet/buddy/ts2java/TestAssignments.java new file mode 100644 index 0000000..9d7bb9a --- /dev/null +++ b/src/test/java/com/caoccao/javet/buddy/ts2java/TestAssignments.java @@ -0,0 +1,99 @@ +/* + * 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; + +import org.junit.jupiter.api.Test; + +public class TestAssignments extends BaseTestTs2Java { + protected static Class clazz = null; + + public TestAssignments() { + super(); + init(); + } + + /* + public assignAndCast(IJ)D + L0 + LINENUMBER 30 L0 + ILOAD 1 + I2L + LSTORE 4 + L1 + LINENUMBER 31 L1 + LLOAD 2 + LSTORE 6 + L2 + LINENUMBER 32 L2 + LLOAD 4 + LLOAD 6 + LADD + L2D + DRETURN + */ + public double assignAndCast(int a, long b) { + long c = a; + long d = b; + return c + d; + } + + protected void init() { + } + + /* + public sum(I)I + L0 + LINENUMBER 42 L0 + ICONST_0 + ISTORE 2 + L1 + LINENUMBER 43 L1 + ICONST_0 + ISTORE 3 + L2 + FRAME APPEND [I I] + ILOAD 3 + ILOAD 1 + IF_ICMPGE L3 + L4 + LINENUMBER 44 L4 + ILOAD 2 + ILOAD 3 + IADD + ISTORE 2 + L5 + LINENUMBER 43 L5 + IINC 3 1 + GOTO L2 + L3 + LINENUMBER 46 L3 + FRAME CHOP 1 + ILOAD 2 + IRETURN + */ + public int sum(int a) { + int sum = 0; + for (int i = 0; i < a; i++) { + sum += i; + } + return sum; + } + + @Test + public void testAssignAndCast() throws Exception { + } +} diff --git a/src/test/java/com/caoccao/javet/buddy/ts2java/TestBasicOperations.java b/src/test/java/com/caoccao/javet/buddy/ts2java/TestBasicOperations.java index 240f98a..d5ce1ad 100644 --- a/src/test/java/com/caoccao/javet/buddy/ts2java/TestBasicOperations.java +++ b/src/test/java/com/caoccao/javet/buddy/ts2java/TestBasicOperations.java @@ -147,7 +147,7 @@ public void testMultiply_II_I() throws Exception { @Test public void testShiftLeft_II_I() throws Exception { - Method method = clazz.getMethod("shift_left_II_I", int.class, int.class); + Method method = clazz.getMethod("shiftLeft_II_I", int.class, int.class); assertNotNull(method); assertEquals(int.class, method.getReturnType()); assertEquals(2, method.getParameterCount()); @@ -159,7 +159,7 @@ public void testShiftLeft_II_I() throws Exception { @Test public void testShiftRight_II_I() throws Exception { - Method method = clazz.getMethod("shift_right_II_I", int.class, int.class); + Method method = clazz.getMethod("shiftRight_II_I", int.class, int.class); assertNotNull(method); assertEquals(int.class, method.getReturnType()); assertEquals(2, method.getParameterCount());