Skip to content

Commit

Permalink
🦄 refactor: Change ByteCodeAppender to StackManipulation
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Oct 26, 2024
1 parent 5fd7751 commit 5e3265c
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 47 deletions.
4 changes: 2 additions & 2 deletions scripts/ts/test.add.ts
Original file line number Diff line number Diff line change
@@ -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));
Original file line number Diff line number Diff line change
Expand Up @@ -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<AST extends Swc4jAst> {
void append(List<ByteCodeAppender> appenders, AST ast);
public interface ITs2JavaAstStackManipulation<AST extends Swc4jAst> {
void manipulate(JavaFunctionContext functionContext, List<StackManipulation> stackManipulations, AST ast);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Swc4jAstBinExpr> {
public final class Ts2JavaAstBinExpr implements ITs2JavaAstStackManipulation<Swc4jAstBinExpr> {
@Override
public void append(List<ByteCodeAppender> appenders, Swc4jAstBinExpr ast) {
public void manipulate(JavaFunctionContext functionContext, List<StackManipulation> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Swc4jAstBlockStmt> {
public final class Ts2JavaAstBlockStmt implements ITs2JavaAstStackManipulation<Swc4jAstBlockStmt> {
@Override
public void append(List<ByteCodeAppender> appenders, Swc4jAstBlockStmt ast) {
public void manipulate(JavaFunctionContext functionContext, List<StackManipulation> 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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@

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;
import com.caoccao.javet.swc4j.ast.enums.Swc4jAstAccessibility;
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;
Expand Down Expand Up @@ -65,11 +66,12 @@ public DynamicType.Builder<?> transpile(
final Class<?>[] parameters = stackFrame.getObjects().stream()
.map(JavaStackObject::getType)
.toArray(Class[]::new);
final List<ByteCodeAppender> appenders = new ArrayList<>();
ast.getBody().ifPresent(blockStmt -> new Ts2JavaAstBlockStmt().append(appenders, blockStmt));
final List<StackManipulation> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Swc4jAstReturnStmt> {
public final class Ts2JavaAstReturnStmt implements ITs2JavaAstStackManipulation<Swc4jAstReturnStmt> {
@Override
public void append(List<ByteCodeAppender> appenders, Swc4jAstReturnStmt ast) {
public void manipulate(JavaFunctionContext functionContext, List<StackManipulation> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
38 changes: 29 additions & 9 deletions src/test/java/com/caoccao/javet/buddy/ts2java/TestAdd.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Class<?>> 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());
Expand Down

0 comments on commit 5e3265c

Please sign in to comment.