Skip to content

Commit

Permalink
🦄 refactor: Redesign local variables
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Oct 30, 2024
1 parent 8400086 commit 21f2db2
Show file tree
Hide file tree
Showing 15 changed files with 266 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import com.caoccao.javet.buddy.ts2java.compiler.JavaClassCast;
import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext;
import com.caoccao.javet.buddy.ts2java.compiler.JavaStackObject;
import com.caoccao.javet.buddy.ts2java.compiler.JavaLocalVariable;
import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaAstException;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstBinExpr;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstIdent;
Expand All @@ -38,28 +38,27 @@ public final class Ts2JavaAstBinExpr implements ITs2JavaAstStackManipulation<Swc
@Override
public Optional<TypeDescription> manipulate(JavaFunctionContext functionContext, Swc4jAstBinExpr ast) {
List<ISwc4jAstExpr> expressions = SimpleList.of(ast.getLeft(), ast.getRight());
List<JavaStackObject> stackObjects = expressions.stream()
List<JavaLocalVariable> localVariables = expressions.stream()
.map(expression -> {
switch (expression.getType()) {
case Ident:
String name = expression.as(Swc4jAstIdent.class).getSym();
return functionContext.getStackObject(name);
return functionContext.getLocalVariable(name);
default:
throw new Ts2JavaAstException(
expression,
SimpleFreeMarkerFormat.format("BinExpr expr type ${exprType} is not supported",
SimpleFreeMarkerFormat.format("BinExpr expr type ${exprType} is not supported.",
SimpleMap.of("exprType", expression.getType().name())));
}
})
.collect(Collectors.toList());
TypeDescription upCaseType = JavaClassCast.getUpCastTypeForMathOp(
stackObjects.stream().map(JavaStackObject::getType).toArray(TypeDescription[]::new));
stackObjects.forEach(stackObject -> {
functionContext.getStackManipulations().add(
MethodVariableAccess.of(stackObject.getType())
.loadFrom(stackObject.getOffset()));
JavaClassCast.getUpCastStackManipulation(stackObject.getType(), upCaseType)
.ifPresent(functionContext.getStackManipulations()::add);
localVariables.stream().map(JavaLocalVariable::getType).toArray(TypeDescription[]::new));
localVariables.forEach(localVariable -> {
MethodVariableAccess methodVariableAccess = MethodVariableAccess.of(localVariable.getType());
functionContext.addStackManipulation(methodVariableAccess.loadFrom(localVariable.getOffset()));
JavaClassCast.getUpCastStackManipulation(localVariable.getType(), upCaseType)
.ifPresent(functionContext::addStackManipulation);
});
StackManipulation stackManipulation;
switch (ast.getOp()) {
Expand Down Expand Up @@ -87,10 +86,10 @@ public Optional<TypeDescription> manipulate(JavaFunctionContext functionContext,
default:
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("BinExpr op ${op} is not supported",
SimpleFreeMarkerFormat.format("BinExpr op ${op} is not supported.",
SimpleMap.of("op", ast.getOp().name())));
}
functionContext.getStackManipulations().add(stackManipulation);
functionContext.addStackManipulation(stackManipulation);
return Optional.of(upCaseType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext;
import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaAstException;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstStmt;
import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstBlockStmt;
import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstReturnStmt;
import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstVarDecl;
import com.caoccao.javet.utils.SimpleFreeMarkerFormat;
import com.caoccao.javet.utils.SimpleMap;
import net.bytebuddy.description.type.TypeDescription;
Expand All @@ -29,18 +31,22 @@
public final class Ts2JavaAstBlockStmt implements ITs2JavaAstStackManipulation<Swc4jAstBlockStmt> {
@Override
public Optional<TypeDescription> manipulate(JavaFunctionContext functionContext, Swc4jAstBlockStmt ast) {
ast.getStmts().forEach(stmt -> {
Optional<TypeDescription> returnType = Optional.empty();
for (ISwc4jAstStmt stmt : ast.getStmts()) {
switch (stmt.getType()) {
case VarDecl:
returnType = new Ts2JavaAstVarDecl().manipulate(functionContext, stmt.as(Swc4jAstVarDecl.class));
break;
case ReturnStmt:
new Ts2JavaAstReturnStmt().manipulate(functionContext, stmt.as(Swc4jAstReturnStmt.class));
returnType = new Ts2JavaAstReturnStmt().manipulate(functionContext, stmt.as(Swc4jAstReturnStmt.class));
break;
default:
throw new Ts2JavaAstException(
stmt,
SimpleFreeMarkerFormat.format("BlockStmt type ${type} is not supported",
SimpleFreeMarkerFormat.format("BlockStmt type ${type} is not supported.",
SimpleMap.of("type", stmt.getType().name())));
}
});
return Optional.empty();
}
return returnType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
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;
Expand All @@ -27,10 +25,8 @@
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public final class Ts2JavaAstClassFunction implements ITs2JavaAstTranspile<Swc4jAstFunction> {
private final boolean _static;
Expand Down Expand Up @@ -63,20 +59,17 @@ public DynamicType.Builder<?> transpile(
final TypeDescription returnType = ast.getReturnType()
.map(Ts2JavaAstTsTypeAnn::getTypeDescription)
.orElse(TypeDescription.ForLoadedType.of(Object.class));
final List<JavaStackFrame> stackFrames = new ArrayList<>();
final List<JavaStackObject> 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(_static, stackFrames, returnType);
functionContext.syncOffset();
final JavaFunctionContext functionContext = new JavaFunctionContext(_static, returnType);
ast.getParams().stream()
.map(Ts2JavaAstParam::getLocalVariable)
.forEach(functionContext::addLocalVariable);
final List<TypeDescription> parameters = functionContext.getParameters();
functionContext.addStackFrame();
ast.getBody().ifPresent(blockStmt -> new Ts2JavaAstBlockStmt().manipulate(functionContext, blockStmt));
final TypeDescription[] parameters = functionContext.getParameters();
final StackManipulation[] stackManipulations =
functionContext.getStackManipulations().toArray(new StackManipulation[0]);
builder = builder.defineMethod(name, returnType, visibility)
.withParameters(parameters)
.withParameters(parameters.toArray(new TypeDescription[0]))
.intercept(new Implementation.Simple(stackManipulations));
return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ public DynamicType.Builder<?> transpile(
if (ast.getKind() != Swc4jAstMethodKind.Method) {
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("ClassMethod kind ${kind} is not supported",
SimpleFreeMarkerFormat.format("ClassMethod kind ${kind} is not supported.",
SimpleMap.of("kind", ast.getKind().name())));
}
if (!(ast.getKey() instanceof Swc4jAstIdentName)) {
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("ClassMethod key type ${keyType} is not supported",
SimpleFreeMarkerFormat.format("ClassMethod key type ${keyType} is not supported.",
SimpleMap.of("keyType", ast.getKey().getClass().getSimpleName())));

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

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

import com.caoccao.javet.buddy.ts2java.compiler.JavaStackObject;
import com.caoccao.javet.buddy.ts2java.compiler.JavaLocalVariable;
import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaAstException;
import com.caoccao.javet.swc4j.ast.clazz.Swc4jAstParam;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstPat;
Expand All @@ -29,18 +29,18 @@ public final class Ts2JavaAstParam {
private Ts2JavaAstParam() {
}

public static JavaStackObject getStackObject(Swc4jAstParam ast) {
public static JavaLocalVariable getLocalVariable(Swc4jAstParam ast) {
ISwc4jAstPat pat = ast.getPat();
switch (pat.getType()) {
case BindingIdent:
String ident = pat.as(Swc4jAstBindingIdent.class).getId().getSym();
TypeDescription typeDescription =
Ts2JavaAstBindingIdent.getTypeDescription(pat.as(Swc4jAstBindingIdent.class));
return new JavaStackObject(ident, typeDescription);
return new JavaLocalVariable(ident, typeDescription);
default:
throw new Ts2JavaAstException(
pat,
SimpleFreeMarkerFormat.format("Param pat type ${patType} is not supported",
SimpleFreeMarkerFormat.format("Param pat type ${patType} is not supported.",
SimpleMap.of("patType", pat.getType().name())));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,29 @@
public final class Ts2JavaAstReturnStmt implements ITs2JavaAstStackManipulation<Swc4jAstReturnStmt> {
@Override
public Optional<TypeDescription> manipulate(JavaFunctionContext functionContext, Swc4jAstReturnStmt ast) {
Optional<TypeDescription> fromType = Optional.empty();
Optional<TypeDescription> optionalFromType = Optional.empty();
if (ast.getArg().isPresent()) {
ISwc4jAstExpr arg = ast.getArg().get();
switch (arg.getType()) {
case BinExpr:
fromType = new Ts2JavaAstBinExpr().manipulate(functionContext, arg.as(Swc4jAstBinExpr.class));
optionalFromType = new Ts2JavaAstBinExpr().manipulate(functionContext, arg.as(Swc4jAstBinExpr.class));
break;
default:
throw new Ts2JavaAstException(
arg,
SimpleFreeMarkerFormat.format("ReturnStmt arg type ${argType} is not supported",
SimpleFreeMarkerFormat.format("ReturnStmt arg type ${argType} is not supported.",
SimpleMap.of("argType", arg.getType().name())));
}
}
if (!fromType.isPresent()) {
if (!optionalFromType.isPresent()) {
throw new Ts2JavaAstException(ast, "ReturnStmt type is unknown");
}
TypeDescription fromType = optionalFromType.get();
TypeDescription returnType = functionContext.getReturnType();
JavaClassCast.getUpCastStackManipulation(fromType.get(), returnType)
.ifPresent(functionContext.getStackManipulations()::add);
JavaClassCast.getUpCastStackManipulation(fromType, returnType)
.ifPresent(functionContext::addStackManipulation);
StackManipulation stackManipulation = MethodReturn.of(returnType);
functionContext.getStackManipulations().add(stackManipulation);
functionContext.addStackManipulation(stackManipulation);
return Optional.of(returnType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static String getName(ISwc4jAstTsEntityName ast) {
default:
throw new Ts2JavaAstException(
ast,
SimpleFreeMarkerFormat.format("TsEntityName type ${type} is not supported",
SimpleFreeMarkerFormat.format("TsEntityName type ${type} is not supported.",
SimpleMap.of("type", ast.getType().name())));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2024-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;

import com.caoccao.javet.buddy.ts2java.compiler.JavaClassCast;
import com.caoccao.javet.buddy.ts2java.compiler.JavaFunctionContext;
import com.caoccao.javet.buddy.ts2java.compiler.JavaLocalVariable;
import com.caoccao.javet.buddy.ts2java.exceptions.Ts2JavaAstException;
import com.caoccao.javet.swc4j.ast.expr.Swc4jAstIdent;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstExpr;
import com.caoccao.javet.swc4j.ast.interfaces.ISwc4jAstPat;
import com.caoccao.javet.swc4j.ast.pat.Swc4jAstBindingIdent;
import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstVarDecl;
import com.caoccao.javet.swc4j.ast.stmt.Swc4jAstVarDeclarator;
import com.caoccao.javet.swc4j.ast.ts.Swc4jAstTsTypeAnn;
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.MethodVariableAccess;

import java.util.Optional;

public final class Ts2JavaAstVarDecl implements ITs2JavaAstStackManipulation<Swc4jAstVarDecl> {
@Override
public Optional<TypeDescription> manipulate(JavaFunctionContext functionContext, Swc4jAstVarDecl ast) {
for (Swc4jAstVarDeclarator varDeclarator : ast.getDecls()) {
Optional<TypeDescription> optionalFromType = Optional.empty();
if (varDeclarator.getInit().isPresent()) {
ISwc4jAstExpr expression = varDeclarator.getInit().get();
switch (expression.getType()) {
case Ident: {
String name = expression.as(Swc4jAstIdent.class).getSym();
JavaLocalVariable localVariable = functionContext.getLocalVariable(name);
MethodVariableAccess methodVariableAccess = MethodVariableAccess.of(localVariable.getType());
StackManipulation stackManipulation = methodVariableAccess.loadFrom(localVariable.getOffset());
functionContext.addStackManipulation(stackManipulation);
optionalFromType = Optional.of(localVariable.getType());
break;
}
default:
throw new Ts2JavaAstException(
expression,
SimpleFreeMarkerFormat.format("VarDecl init type ${type} is not supported.",
SimpleMap.of("type", expression.getType().name())));
}
}
ISwc4jAstPat pat = varDeclarator.getName();
switch (pat.getType()) {
case BindingIdent: {
Swc4jAstBindingIdent bindingIdent = pat.as(Swc4jAstBindingIdent.class);
String name = bindingIdent.getId().getSym();
if (bindingIdent.getTypeAnn().isPresent()) {
Swc4jAstTsTypeAnn tsTypeAnn = bindingIdent.getTypeAnn().get();
TypeDescription toType = Ts2JavaAstTsTypeAnn.getTypeDescription(tsTypeAnn);
if (optionalFromType.isPresent()) {
TypeDescription fromType = optionalFromType.get();
JavaClassCast.getUpCastStackManipulation(fromType, toType)
.ifPresent(functionContext::addStackManipulation);
}
JavaLocalVariable localVariable = new JavaLocalVariable(name, toType);
MethodVariableAccess methodVariableAccess = MethodVariableAccess.of(localVariable.getType());
StackManipulation stackManipulation = methodVariableAccess.storeAt(functionContext.getMaxLocals());
functionContext.addStackManipulation(stackManipulation);
functionContext.addLocalVariable(localVariable);
} else {
throw new Ts2JavaAstException(
bindingIdent,
SimpleFreeMarkerFormat.format("VarDecl name ${name} type annotation is missing.",
SimpleMap.of("name", name)));
}
break;
}
default:
throw new Ts2JavaAstException(
pat,
SimpleFreeMarkerFormat.format("VarDecl name type ${type} is not supported.",
SimpleMap.of("type", pat.getType().name())));
}
}
return Optional.empty();
}
}
Loading

0 comments on commit 21f2db2

Please sign in to comment.