From 5e3265c15d6303749e890d360f2b5b2fe83b54ba Mon Sep 17 00:00:00 2001 From: Sam Cao Date: Sat, 26 Oct 2024 11:40:18 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20Change=20ByteCodeApp?= =?UTF-8?q?ender=20to=20StackManipulation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/ts/test.add.ts | 4 +- ...java => ITs2JavaAstStackManipulation.java} | 7 ++-- .../buddy/ts2java/ast/Ts2JavaAstBinExpr.java | 33 ++++++---------- .../ts2java/ast/Ts2JavaAstBlockStmt.java | 9 +++-- .../ts2java/ast/Ts2JavaAstClassFunction.java | 10 +++-- .../ts2java/ast/Ts2JavaAstReturnStmt.java | 14 +++++-- .../ts2java/compiler/JavaFunctionContext.java | 35 +++++++++++++++++ .../caoccao/javet/buddy/ts2java/TestAdd.java | 38 ++++++++++++++----- 8 files changed, 103 insertions(+), 47 deletions(-) rename src/main/java/com/caoccao/javet/buddy/ts2java/ast/{ITs2JavaAstAppend.java => ITs2JavaAstStackManipulation.java} (69%) create mode 100644 src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaFunctionContext.java diff --git a/scripts/ts/test.add.ts b/scripts/ts/test.add.ts index 7295467..a8121e8 100644 --- a/scripts/ts/test.add.ts +++ b/scripts/ts/test.add.ts @@ -1,9 +1,9 @@ import { type int } from "./type.aliases"; class Test { - public add(a: int, b: int): int { + public add_II_I(a: int, b: int): int { return a + b; } } -console.log(new Test().add(1, 2)); +console.log(new Test().add_II_I(1, 2)); diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/ITs2JavaAstAppend.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/ITs2JavaAstStackManipulation.java similarity index 69% rename from src/main/java/com/caoccao/javet/buddy/ts2java/ast/ITs2JavaAstAppend.java rename to src/main/java/com/caoccao/javet/buddy/ts2java/ast/ITs2JavaAstStackManipulation.java index 8c389f9..573cfe9 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/ITs2JavaAstAppend.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/ITs2JavaAstStackManipulation.java @@ -16,11 +16,12 @@ package com.caoccao.javet.buddy.ts2java.ast; +import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext; import com.caoccao.javet.swc4j.ast.Swc4jAst; -import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import net.bytebuddy.implementation.bytecode.StackManipulation; import java.util.List; -public interface ITs2JavaAstAppend { - void append(List appenders, AST ast); +public interface ITs2JavaAstStackManipulation { + void manipulate(JavaFunctionContext functionContext, List stackManipulations, AST ast); } 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 125ea79..fffb19d 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,36 +16,27 @@ package com.caoccao.javet.buddy.ts2java.ast; +import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext; import com.caoccao.javet.swc4j.ast.expr.Swc4jAstBinExpr; import net.bytebuddy.implementation.Implementation; -import net.bytebuddy.implementation.bytecode.ByteCodeAppender; import net.bytebuddy.implementation.bytecode.StackManipulation; -import net.bytebuddy.implementation.bytecode.member.MethodReturn; import net.bytebuddy.jar.asm.MethodVisitor; import net.bytebuddy.jar.asm.Opcodes; import java.util.List; -public final class Ts2JavaAstBinExpr implements ITs2JavaAstAppend { +public final class Ts2JavaAstBinExpr implements ITs2JavaAstStackManipulation { @Override - public void append(List appenders, Swc4jAstBinExpr ast) { + public void manipulate(JavaFunctionContext functionContext, List stackManipulations, Swc4jAstBinExpr ast) { // TODO - appenders.add((methodVisitor, implementationContext, instrumentedMethod) -> { - StackManipulation.Size size = new StackManipulation.Compound( - new StackManipulation.Simple(( - MethodVisitor simpleMethodVisitor, - Implementation.Context simpleImplementationContext) -> { - simpleMethodVisitor.visitVarInsn(Opcodes.ILOAD, 1); - simpleMethodVisitor.visitVarInsn(Opcodes.ILOAD, 2); - simpleMethodVisitor.visitInsn(Opcodes.IADD); - return new StackManipulation.Size(2, 0); - }), - MethodReturn.INTEGER - ).apply(methodVisitor, implementationContext); - return new ByteCodeAppender.Size( - size.getMaximalSize(), - instrumentedMethod.getStackSize()); - } - ); + StackManipulation stackManipulation = new StackManipulation.Simple(( + MethodVisitor simpleMethodVisitor, + Implementation.Context simpleImplementationContext) -> { + simpleMethodVisitor.visitVarInsn(Opcodes.ILOAD, 1); + simpleMethodVisitor.visitVarInsn(Opcodes.ILOAD, 2); + simpleMethodVisitor.visitInsn(Opcodes.IADD); + return new StackManipulation.Size(2, 0); + }); + stackManipulations.add(stackManipulation); } } diff --git a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBlockStmt.java b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBlockStmt.java index 6fd88bd..a7d6966 100644 --- a/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBlockStmt.java +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/ast/Ts2JavaAstBlockStmt.java @@ -17,19 +17,20 @@ package com.caoccao.javet.buddy.ts2java.ast; import com.caoccao.javet.buddy.ts2java.Ts2JavaException; +import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext; import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstBlockStmt; import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstReturnStmt; -import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import net.bytebuddy.implementation.bytecode.StackManipulation; import java.util.List; -public final class Ts2JavaAstBlockStmt implements ITs2JavaAstAppend { +public final class Ts2JavaAstBlockStmt implements ITs2JavaAstStackManipulation { @Override - public void append(List appenders, Swc4jAstBlockStmt ast) { + public void manipulate(JavaFunctionContext functionContext, List stackManipulations, Swc4jAstBlockStmt ast) { ast.getStmts().forEach(stmt -> { switch (stmt.getType()) { case ReturnStmt: - new Ts2JavaAstReturnStmt().append(appenders, stmt.as(Swc4jAstReturnStmt.class)); + new Ts2JavaAstReturnStmt().manipulate(functionContext, stackManipulations, stmt.as(Swc4jAstReturnStmt.class)); break; default: throw new Ts2JavaException(stmt.getType().name() + " is not supported"); 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 b06ed5f..e9ea066 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 @@ -16,6 +16,7 @@ package com.caoccao.javet.buddy.ts2java.ast; +import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext; import com.caoccao.javet.buddy.ts2java.compiler.JavaStackFrame; import com.caoccao.javet.buddy.ts2java.compiler.JavaStackObject; import com.caoccao.javet.swc4j.ast.clazz.Swc4jAstFunction; @@ -23,7 +24,7 @@ import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.Implementation; -import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import net.bytebuddy.implementation.bytecode.StackManipulation; import java.util.ArrayList; import java.util.List; @@ -65,11 +66,12 @@ public DynamicType.Builder transpile( final Class[] parameters = stackFrame.getObjects().stream() .map(JavaStackObject::getType) .toArray(Class[]::new); - final List appenders = new ArrayList<>(); - ast.getBody().ifPresent(blockStmt -> new Ts2JavaAstBlockStmt().append(appenders, blockStmt)); + final List stackManipulations = new ArrayList<>(); + final JavaFunctionContext functionContext = new JavaFunctionContext(parameters, returnType); + ast.getBody().ifPresent(blockStmt -> new Ts2JavaAstBlockStmt().manipulate(functionContext, stackManipulations, blockStmt)); builder = builder.defineMethod(name, returnType, visibility) .withParameters(parameters) - .intercept(new Implementation.Simple(appenders.toArray(new ByteCodeAppender[0]))); + .intercept(new Implementation.Simple(stackManipulations.toArray(new StackManipulation[0]))); return builder; } } 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 c65ebec..435b088 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 @@ -17,23 +17,29 @@ package com.caoccao.javet.buddy.ts2java.ast; import com.caoccao.javet.buddy.ts2java.Ts2JavaException; +import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext; import com.caoccao.javet.swc4j.ast.expr.Swc4jAstBinExpr; import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstReturnStmt; -import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.implementation.bytecode.StackManipulation; +import net.bytebuddy.implementation.bytecode.member.MethodReturn; import java.util.List; -public final class Ts2JavaAstReturnStmt implements ITs2JavaAstAppend { +public final class Ts2JavaAstReturnStmt implements ITs2JavaAstStackManipulation { @Override - public void append(List appenders, Swc4jAstReturnStmt ast) { + public void manipulate(JavaFunctionContext functionContext, List stackManipulations, Swc4jAstReturnStmt ast) { ast.getArg().ifPresent(arg -> { switch (arg.getType()) { case BinExpr: - new Ts2JavaAstBinExpr().append(appenders, arg.as(Swc4jAstBinExpr.class)); + new Ts2JavaAstBinExpr().manipulate(functionContext, stackManipulations, arg.as(Swc4jAstBinExpr.class)); break; default: throw new Ts2JavaException(arg.getType().name() + " is not supported"); } }); + TypeDescription typeDescription = TypeDescription.ForLoadedType.of(functionContext.getReturnType()); + StackManipulation stackManipulation = MethodReturn.of(typeDescription); + stackManipulations.add(stackManipulation); } } 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 new file mode 100644 index 0000000..fe31e91 --- /dev/null +++ b/src/main/java/com/caoccao/javet/buddy/ts2java/compiler/JavaFunctionContext.java @@ -0,0 +1,35 @@ +/* + * 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; + +public final class JavaFunctionContext { + private final Class[] parameters; + private final Class returnType; + + public JavaFunctionContext(Class[] parameters, Class returnType) { + this.parameters = parameters; + this.returnType = returnType; + } + + public Class[] getParameters() { + return parameters; + } + + public Class getReturnType() { + return returnType; + } +} diff --git a/src/test/java/com/caoccao/javet/buddy/ts2java/TestAdd.java b/src/test/java/com/caoccao/javet/buddy/ts2java/TestAdd.java index e0b922c..3250158 100644 --- a/src/test/java/com/caoccao/javet/buddy/ts2java/TestAdd.java +++ b/src/test/java/com/caoccao/javet/buddy/ts2java/TestAdd.java @@ -16,15 +16,23 @@ package com.caoccao.javet.buddy.ts2java; +import com.caoccao.javet.swc4j.exceptions.Swc4jCoreException; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.lang.reflect.Method; import java.util.List; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; public class TestAdd extends BaseTestTs2Java { + protected Class clazz; + + public TestAdd() { + super(); + init(); + } + /* public add(II)I L0 @@ -38,19 +46,31 @@ public int add(int a, int b) { return a + b; } - @Test - public void testAdd() throws Exception { - assertEquals(3, add(1, 2)); - String tsCode = getTsCode("test.add.ts"); + protected void init() { + String tsCode = null; + try { + tsCode = getTsCode("test.add.ts"); + } catch (IOException e) { + fail(e); + } assertNotNull(tsCode); Ts2Java ts2Java = new Ts2Java("com.test", tsCode); - ts2Java.transpile(); + try { + ts2Java.transpile(); + } catch (Swc4jCoreException e) { + fail(e); + } List> classes = ts2Java.getClasses(); assertEquals(1, classes.size()); - Class clazz = classes.get(0); + clazz = classes.get(0); assertEquals("Test", clazz.getSimpleName()); assertEquals("com.test.Test", clazz.getName()); - Method method = clazz.getMethod("add", int.class, int.class); + } + + @Test + public void testAdd_II_I() throws Exception { + assertEquals(3, add(1, 2)); + Method method = clazz.getMethod("add_II_I", int.class, int.class); assertNotNull(method); assertEquals(int.class, method.getReturnType()); assertEquals(2, method.getParameterCount());