ScriptCodegen refactoring: unsingleton

This commit is contained in:
Mikhael Bogdanov
2013-06-28 16:31:43 +04:00
parent 08a90ba7d4
commit d4b84a8809
21 changed files with 286 additions and 219 deletions
@@ -83,7 +83,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
} }
private void generateClassBody() { private void generateClassBody() {
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state, this);
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this); PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
if (kind != OwnerKind.TRAIT_IMPL) { if (kind != OwnerKind.TRAIT_IMPL) {
@@ -184,7 +184,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(), clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false); Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false);
clInitCodegen = new ExpressionCodegen(method, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state); clInitCodegen = new ExpressionCodegen(method, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
} }
return clInitCodegen; return clInitCodegen;
} }
@@ -51,7 +51,7 @@ import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.isConst; import static org.jetbrains.jet.codegen.CodegenUtil.isConst;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
public class ClosureCodegen extends GenerationStateAware { public class ClosureCodegen extends ParentCodegenAwareImpl {
private final PsiElement fun; private final PsiElement fun;
private final FunctionDescriptor funDescriptor; private final FunctionDescriptor funDescriptor;
private final ClassDescriptor samInterface; private final ClassDescriptor samInterface;
@@ -71,9 +71,10 @@ public class ClosureCodegen extends GenerationStateAware {
@NotNull Type closureSuperClass, @NotNull Type closureSuperClass,
@NotNull CodegenContext context, @NotNull CodegenContext context,
@NotNull LocalLookup localLookup, @NotNull LocalLookup localLookup,
@NotNull FunctionGenerationStrategy strategy @NotNull FunctionGenerationStrategy strategy,
@Nullable MemberCodegen parentCodegen
) { ) {
super(state); super(state, parentCodegen);
this.fun = fun; this.fun = fun;
this.funDescriptor = funDescriptor; this.funDescriptor = funDescriptor;
@@ -89,7 +90,6 @@ public class ClosureCodegen extends GenerationStateAware {
this.asmType = asmTypeForAnonymousClass(bindingContext, funDescriptor); this.asmType = asmTypeForAnonymousClass(bindingContext, funDescriptor);
} }
public void gen() { public void gen() {
ClassBuilder cv = state.getFactory().newVisitor(asmType, fun.getContainingFile()); ClassBuilder cv = state.getFactory().newVisitor(asmType, fun.getContainingFile());
@@ -120,7 +120,7 @@ public class ClosureCodegen extends GenerationStateAware {
JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(interfaceFunction.getName(), funDescriptor); JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(interfaceFunction.getName(), funDescriptor);
FunctionCodegen fc = new FunctionCodegen(context, cv, state); FunctionCodegen fc = new FunctionCodegen(context, cv, state, getParentCodegen());
fc.generateMethod(fun, jvmMethodSignature, funDescriptor, strategy); fc.generateMethod(fun, jvmMethodSignature, funDescriptor, strategy);
this.constructor = generateConstructor(cv); this.constructor = generateConstructor(cv);
@@ -131,9 +131,11 @@ public class ClosureCodegen extends GenerationStateAware {
genClosureFields(closure, cv, typeMapper); genClosureFields(closure, cv, typeMapper);
FunctionCodegen.generateDefaultIfNeeded(context.intoFunction(funDescriptor), state, cv, fc.generateDefaultIfNeeded(context.intoFunction(funDescriptor),
typeMapper.mapSignature(Name.identifier("invoke"), funDescriptor), funDescriptor, typeMapper.mapSignature(Name.identifier("invoke"), funDescriptor),
context.getContextKind(), DefaultParameterValueLoader.DEFAULT); funDescriptor,
context.getContextKind(),
DefaultParameterValueLoader.DEFAULT);
cv.done(); cv.done();
} }
@@ -78,7 +78,7 @@ import static org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.TH
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup { public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup, ParentCodegenAware {
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException"; private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException"; private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
@@ -101,6 +101,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
private final Collection<String> localVariableNames = new HashSet<String>(); private final Collection<String> localVariableNames = new HashSet<String>();
@Nullable
private final MemberCodegen parentCodegen;
/* /*
* When we create a temporary variable to hold some value not to compute it many times * When we create a temporary variable to hold some value not to compute it many times
* we put it into this map to emit access to that variable instead of evaluating the whole expression * we put it into this map to emit access to that variable instead of evaluating the whole expression
@@ -161,9 +164,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@NotNull FrameMap myMap, @NotNull FrameMap myMap,
@NotNull Type returnType, @NotNull Type returnType,
@NotNull MethodContext context, @NotNull MethodContext context,
@NotNull GenerationState state @NotNull GenerationState state,
@Nullable MemberCodegen parentCodegen
) { ) {
this.myFrameMap = myMap; this.myFrameMap = myMap;
this.parentCodegen = parentCodegen;
this.typeMapper = state.getTypeMapper(); this.typeMapper = state.getTypeMapper();
this.returnType = returnType; this.returnType = returnType;
this.state = state; this.state = state;
@@ -219,6 +224,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return localVariableNames; return localVariableNames;
} }
@Nullable
@Override
public MemberCodegen getParentCodegen() {
return parentCodegen;
}
public StackValue genQualified(StackValue receiver, JetElement selector) { public StackValue genQualified(StackValue receiver, JetElement selector) {
return genQualified(receiver, selector, this); return genQualified(receiver, selector, this);
} }
@@ -1311,7 +1322,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
Type closureSuperClass = samInterfaceClass == null ? getFunctionImplType(descriptor) : OBJECT_TYPE; Type closureSuperClass = samInterfaceClass == null ? getFunctionImplType(descriptor) : OBJECT_TYPE;
ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context, ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context,
this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration)); this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), parentCodegen);
closureCodegen.gen(); closureCodegen.gen();
@@ -2218,7 +2229,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
else { else {
Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor()); Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor());
String fieldName = state.getScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); String fieldName = getParentScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor());
result.put(currentScriptType, v); result.put(currentScriptType, v);
StackValue.field(classType, currentScriptType, fieldName, false).put(classType, v); StackValue.field(classType, currentScriptType, fieldName, false).put(classType, v);
} }
@@ -2434,14 +2445,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override @Override
public ExpressionCodegen initializeExpressionCodegen( public ExpressionCodegen initializeExpressionCodegen(
JvmMethodSignature signature, MethodContext context, MethodVisitor mv, JvmMethodSignature signature, MethodContext context, MethodVisitor mv,
Type returnType Type returnType,
MemberCodegen parentCodegen
) { ) {
FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
JetType returnJetType = referencedFunction.getReturnType(); JetType returnJetType = referencedFunction.getReturnType();
assert returnJetType != null : "Return type can't be null: " + referencedFunction; assert returnJetType != null : "Return type can't be null: " + referencedFunction;
return super.initializeExpressionCodegen(signature, context, return super.initializeExpressionCodegen(signature, context,
mv, typeMapper.mapReturnType(returnJetType)); mv, typeMapper.mapReturnType(returnJetType), parentCodegen);
} }
@Override @Override
@@ -2564,8 +2576,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return new ExpressionReceiver(receiverExpression, receiver.getType()); return new ExpressionReceiver(receiverExpression, receiver.getType());
} }
} },
); getParentCodegen());
closureCodegen.gen(); closureCodegen.gen();
@@ -3809,4 +3821,16 @@ The "returned" value of try expression with no finally is either the last expres
public String toString() { public String toString() {
return context.getContextDescriptor().toString(); return context.getContextDescriptor().toString();
} }
@NotNull
private ScriptCodegen getParentScriptCodegen() {
MemberCodegen codegen = parentCodegen;
while (codegen != null) {
if (codegen instanceof ScriptCodegen) {
return (ScriptCodegen) codegen;
}
codegen = codegen.getParentCodegen();
}
throw new IllegalStateException("Script codegen should be present in codegen tree");
}
} }
@@ -57,12 +57,13 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isFunctionLiteral;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.fqNameByClass; import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.fqNameByClass;
public class FunctionCodegen extends GenerationStateAware { public class FunctionCodegen extends ParentCodegenAwareImpl {
private final CodegenContext owner; private final CodegenContext owner;
private final ClassBuilder v; private final ClassBuilder v;
public FunctionCodegen(CodegenContext owner, ClassBuilder v, GenerationState state) { public FunctionCodegen(@NotNull CodegenContext owner, @NotNull ClassBuilder v, @NotNull GenerationState state, MemberCodegen parentCodegen) {
super(state); super(state, parentCodegen);
this.owner = owner; this.owner = owner;
this.v = v; this.v = v;
} }
@@ -80,7 +81,7 @@ public class FunctionCodegen extends GenerationStateAware {
new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function)); new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function));
} }
generateDefaultIfNeeded(owner.intoFunction(functionDescriptor), state, v, method, functionDescriptor, kind, generateDefaultIfNeeded(owner.intoFunction(functionDescriptor), method, functionDescriptor, kind,
DefaultParameterValueLoader.DEFAULT); DefaultParameterValueLoader.DEFAULT);
} }
@@ -267,7 +268,7 @@ public class FunctionCodegen extends GenerationStateAware {
genNotNullAssertionsForParameters(new InstructionAdapter(mv), state, functionDescriptor, frameMap); genNotNullAssertionsForParameters(new InstructionAdapter(mv), state, functionDescriptor, frameMap);
} }
strategy.generateBody(mv, signature, context); strategy.generateBody(mv, signature, context, getParentCodegen());
localVariableNames.addAll(strategy.getLocalVariableNames()); localVariableNames.addAll(strategy.getLocalVariableNames());
} }
@@ -518,10 +519,8 @@ public class FunctionCodegen extends GenerationStateAware {
} }
} }
static void generateDefaultIfNeeded( void generateDefaultIfNeeded(
@NotNull MethodContext owner, @NotNull MethodContext owner,
@NotNull GenerationState state,
@NotNull ClassBuilder v,
@NotNull JvmMethodSignature signature, @NotNull JvmMethodSignature signature,
@NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionDescriptor functionDescriptor,
@NotNull OwnerKind kind, @NotNull OwnerKind kind,
@@ -565,17 +564,17 @@ public class FunctionCodegen extends GenerationStateAware {
descriptor = descriptor.replace("(", "(" + ownerType.getDescriptor()); descriptor = descriptor.replace("(", "(" + ownerType.getDescriptor());
} }
MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC), MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC),
isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX,
descriptor, null, null); descriptor, null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generateDefaultImpl(owner, state, signature, functionDescriptor, isStatic, mv, loadStrategy); generateDefaultImpl(owner, signature, functionDescriptor, isStatic, mv, loadStrategy);
} }
} }
private static void generateDefaultImpl( private void generateDefaultImpl(
@NotNull MethodContext methodContext, @NotNull MethodContext methodContext,
@NotNull GenerationState state,
@NotNull JvmMethodSignature signature, @NotNull JvmMethodSignature signature,
@NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionDescriptor functionDescriptor,
boolean aStatic, boolean aStatic,
@@ -591,7 +590,7 @@ public class FunctionCodegen extends GenerationStateAware {
} }
Method jvmSignature = signature.getAsmMethod(); Method jvmSignature = signature.getAsmMethod();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), methodContext, state); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), methodContext, state, getParentCodegen());
Type[] argTypes = jvmSignature.getArgumentTypes(); Type[] argTypes = jvmSignature.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.context.MethodContext; import org.jetbrains.jet.codegen.context.MethodContext;
@@ -38,7 +39,8 @@ public abstract class FunctionGenerationStrategy {
public abstract void generateBody( public abstract void generateBody(
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature, @NotNull JvmMethodSignature signature,
@NotNull MethodContext context @NotNull MethodContext context,
@Nullable MemberCodegen parentCodegen
); );
protected void addLocalVariableName(@NotNull String name) { protected void addLocalVariableName(@NotNull String name) {
@@ -97,9 +99,10 @@ public abstract class FunctionGenerationStrategy {
public void generateBody( public void generateBody(
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature, @NotNull JvmMethodSignature signature,
@NotNull MethodContext context @NotNull MethodContext context,
@Nullable MemberCodegen parentCodegen
) { ) {
ExpressionCodegen codegen = initializeExpressionCodegen(signature, context, mv, signature.getAsmMethod().getReturnType()); ExpressionCodegen codegen = initializeExpressionCodegen(signature, context, mv, signature.getAsmMethod().getReturnType(), parentCodegen);
doGenerateBody(codegen, signature); doGenerateBody(codegen, signature);
generateLocalVarNames(codegen); generateLocalVarNames(codegen);
} }
@@ -111,9 +114,10 @@ public abstract class FunctionGenerationStrategy {
JvmMethodSignature signature, JvmMethodSignature signature,
MethodContext context, MethodContext context,
MethodVisitor mv, MethodVisitor mv,
Type returnType Type returnType,
MemberCodegen parentCodegen
) { ) {
return new ExpressionCodegen(mv, getFrameMap(state.getTypeMapper(), context), returnType, context, state); return new ExpressionCodegen(mv, getFrameMap(state.getTypeMapper(), context), returnType, context, state, parentCodegen);
} }
public void generateLocalVarNames(@NotNull ExpressionCodegen codegen) { public void generateLocalVarNames(@NotNull ExpressionCodegen codegen) {
@@ -98,7 +98,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
) { ) {
super(aClass, context, v, state, parentCodegen); super(aClass, context, v, state, parentCodegen);
this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL); this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
this.functionCodegen = new FunctionCodegen(context, v, state); this.functionCodegen = new FunctionCodegen(context, v, state, this);
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this); this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this);
} }
@@ -819,13 +819,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JvmMethodSignature signature = typeMapper.mapSignature(function); JvmMethodSignature signature = typeMapper.mapSignature(function);
FunctionCodegen fc = new FunctionCodegen(context, v, state); functionCodegen.generateMethod(myClass, signature, function, new FunctionGenerationStrategy() {
fc.generateMethod(myClass, signature, function, new FunctionGenerationStrategy() {
@Override @Override
public void generateBody( public void generateBody(
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature, @NotNull JvmMethodSignature signature,
@NotNull MethodContext context @NotNull MethodContext context,
@Nullable MemberCodegen parentCodegen
) { ) {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
if (!componentType.equals(Type.VOID_TYPE)) { if (!componentType.equals(Type.VOID_TYPE)) {
@@ -843,13 +843,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType()); final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType());
FunctionCodegen fc = new FunctionCodegen(context, v, state); functionCodegen.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() {
fc.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() {
@Override @Override
public void generateBody( public void generateBody(
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature, @NotNull JvmMethodSignature signature,
@NotNull MethodContext context @NotNull MethodContext context,
@Nullable MemberCodegen parentCodegen
) { ) {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -884,7 +884,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}); });
MethodContext functionContext = context.intoFunction(function); MethodContext functionContext = context.intoFunction(function);
FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature, function, OwnerKind.IMPLEMENTATION,
functionCodegen.generateDefaultIfNeeded(functionContext, methodSignature, function, OwnerKind.IMPLEMENTATION,
new DefaultParameterValueLoader() { new DefaultParameterValueLoader() {
@Override @Override
public void putValueOnStack( public void putValueOnStack(
@@ -904,7 +905,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
.put(propertyType, codegen.v); .put(propertyType, codegen.v);
} }
}); });
}
}
private void generateEnumMethodsAndConstInitializers() { private void generateEnumMethodsAndConstInitializers() {
if (!myEnumConstants.isEmpty()) { if (!myEnumConstants.isEmpty()) {
@@ -1171,7 +1173,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
); );
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorSignature, constructorDescriptor, functionCodegen.generateDefaultIfNeeded(constructorContext, constructorSignature, constructorDescriptor,
OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT); OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, closure); CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, closure);
@@ -1483,7 +1485,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitCode(); mv.visitCode();
FrameMap frameMap = context.prepareFrame(typeMapper); FrameMap frameMap = context.prepareFrame(typeMapper);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state, this);
codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it? codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it?
Type[] argTypes = methodToGenerate.getArgumentTypes(); Type[] argTypes = methodToGenerate.getArgumentTypes();
@@ -48,8 +48,6 @@ public class KotlinCodegenFacade {
} }
} }
state.getScriptCodegen().registerEarlierScripts(Collections.<Pair<ScriptDescriptor, Type>>emptyList());
state.beforeCompile(); state.beforeCompile();
MultiMap<FqName, JetFile> namespaceGrouping = new MultiMap<FqName, JetFile>(); MultiMap<FqName, JetFile> namespaceGrouping = new MultiMap<FqName, JetFile>();
@@ -23,26 +23,16 @@ import org.jetbrains.jet.codegen.context.ClassContext;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
public class MemberCodegen extends GenerationStateAware { public class MemberCodegen extends ParentCodegenAwareImpl {
@Nullable
private MemberCodegen parentCodegen;
public MemberCodegen(@NotNull GenerationState state, @Nullable MemberCodegen parentCodegen) { public MemberCodegen(@NotNull GenerationState state, @Nullable MemberCodegen parentCodegen) {
super(state); super(state, parentCodegen);
this.parentCodegen = parentCodegen;
}
@Nullable
public MemberCodegen getParentCodegen() {
return parentCodegen;
} }
public void genFunctionOrProperty( public void genFunctionOrProperty(
@@ -50,7 +40,7 @@ public class MemberCodegen extends GenerationStateAware {
@NotNull JetTypeParameterListOwner functionOrProperty, @NotNull JetTypeParameterListOwner functionOrProperty,
@NotNull ClassBuilder classBuilder @NotNull ClassBuilder classBuilder
) { ) {
FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state); FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state, this);
if (functionOrProperty instanceof JetNamedFunction) { if (functionOrProperty instanceof JetNamedFunction) {
try { try {
functionCodegen.gen((JetNamedFunction) functionOrProperty); functionCodegen.gen((JetNamedFunction) functionOrProperty);
@@ -102,7 +92,7 @@ public class MemberCodegen extends GenerationStateAware {
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) { if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile()); ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile());
new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state) new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state, this)
.generate(); .generate();
traitBuilder.done(); traitBuilder.done();
} }
@@ -178,7 +178,7 @@ public class NamespaceCodegen extends MemberCodegen {
} }
} }
else if (declaration instanceof JetScript) { else if (declaration instanceof JetScript) {
state.getScriptCodegen().generate((JetScript) declaration); ScriptCodegen.createScriptCodegen((JetScript) declaration, state, CodegenContext.STATIC.intoNamespace(descriptor)).generate();
} }
} }
@@ -280,7 +280,7 @@ public class NamespaceCodegen extends MemberCodegen {
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(), clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false); Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context.intoFunction(clInit), state); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context.intoFunction(clInit), state, this);
for (JetDeclaration declaration : properties) { for (JetDeclaration declaration : properties) {
ImplementationBodyCodegen. ImplementationBodyCodegen.
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* 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 org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
public interface ParentCodegenAware {
@Nullable
MemberCodegen getParentCodegen();
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* 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 org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
public class ParentCodegenAwareImpl extends GenerationStateAware implements ParentCodegenAware {
@Nullable private final MemberCodegen parentCodegen;
public ParentCodegenAwareImpl(@NotNull GenerationState state, @Nullable MemberCodegen parentCodegen) {
super(state);
this.parentCodegen = parentCodegen;
}
@Nullable
@Override
public MemberCodegen getParentCodegen() {
return parentCodegen;
}
}
@@ -43,7 +43,7 @@ public class SamWrapperClasses {
new Factory<Type>() { new Factory<Type>() {
@Override @Override
public Type create() { public Type create() {
return new SamWrapperCodegen(state, samInterface).genWrapper(file); return new SamWrapperCodegen(state, samInterface, null).genWrapper(file);
} }
}); });
} }
@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
@@ -42,13 +43,17 @@ import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.NO_FLAG_PACKAGE_PRIVATE; import static org.jetbrains.jet.codegen.AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
public class SamWrapperCodegen extends GenerationStateAware { public class SamWrapperCodegen extends ParentCodegenAwareImpl {
private static final String FUNCTION_FIELD_NAME = "function"; private static final String FUNCTION_FIELD_NAME = "function";
@NotNull private final ClassDescriptorFromJvmBytecode samInterface; @NotNull private final ClassDescriptorFromJvmBytecode samInterface;
public SamWrapperCodegen(@NotNull GenerationState state, @NotNull ClassDescriptorFromJvmBytecode samInterface) { public SamWrapperCodegen(
super(state); @NotNull GenerationState state,
@NotNull ClassDescriptorFromJvmBytecode samInterface,
@Nullable MemberCodegen parentCodegen
) {
super(state, parentCodegen);
this.samInterface = samInterface; this.samInterface = samInterface;
} }
@@ -121,7 +126,7 @@ public class SamWrapperCodegen extends GenerationStateAware {
) { ) {
// using static context to avoid creating ClassDescriptor and everything else // using static context to avoid creating ClassDescriptor and everything else
FunctionCodegen codegen = new FunctionCodegen(CodegenContext.STATIC, cv, state); FunctionCodegen codegen = new FunctionCodegen(CodegenContext.STATIC, cv, state, getParentCodegen());
FunctionDescriptor invokeFunction = functionJetType.getMemberScope() FunctionDescriptor invokeFunction = functionJetType.getMemberScope()
.getFunctions(Name.identifier("invoke")).iterator().next().getOriginal(); .getFunctions(Name.identifier("invoke")).iterator().next().getOriginal();
@@ -16,13 +16,11 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.context.MethodContext; import org.jetbrains.jet.codegen.context.MethodContext;
@@ -35,7 +33,6 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import javax.inject.Inject;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -45,35 +42,50 @@ import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
public class ScriptCodegen extends MemberCodegen { public class ScriptCodegen extends MemberCodegen {
@NotNull public static ScriptCodegen createScriptCodegen(
private ClassFileFactory classFileFactory; @NotNull JetScript declaration,
@NotNull GenerationState state,
private List<ScriptDescriptor> earlierScripts; @NotNull CodegenContext parentContext
private Method scriptConstructorMethod; ) {
ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, declaration);
public ScriptCodegen(@NotNull GenerationState state) {
super(state, null);
}
@Inject
public void setClassFileFactory(@NotNull ClassFileFactory classFileFactory) {
this.classFileFactory = classFileFactory;
}
public void generate(JetScript scriptDeclaration) {
ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration);
assert scriptDescriptor != null; assert scriptDescriptor != null;
ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
ClassDescriptor classDescriptorForScript = state.getBindingContext().get(CLASS_FOR_SCRIPT, scriptDescriptor);
assert classDescriptorForScript != null; assert classDescriptorForScript != null;
ScriptContext context = (ScriptContext) CodegenContext.STATIC.intoScript(scriptDescriptor, classDescriptorForScript); ScriptContext scriptContext = parentContext.intoScript(scriptDescriptor, classDescriptorForScript);
return new ScriptCodegen(declaration, state, scriptContext, state.getEarlierScriptsForReplInterpreter());
}
@NotNull
private JetScript scriptDeclaration;
@NotNull
private final ScriptContext context;
@NotNull
private List<ScriptDescriptor> earlierScripts;
private ScriptCodegen(
@NotNull JetScript scriptDeclaration,
@NotNull GenerationState state,
@NotNull ScriptContext context,
@Nullable List<ScriptDescriptor> earlierScripts
) {
super(state, null);
this.scriptDeclaration = scriptDeclaration;
this.context = context;
this.earlierScripts = earlierScripts == null ? Collections.<ScriptDescriptor>emptyList() : earlierScripts;
}
public void generate() {
ScriptDescriptor scriptDescriptor = context.getScriptDescriptor();
ClassDescriptor classDescriptorForScript = context.getContextDescriptor();
Type classType = bindingContext.get(ASM_TYPE, classDescriptorForScript); Type classType = bindingContext.get(ASM_TYPE, classDescriptorForScript);
assert classType != null; assert classType != null;
ClassBuilder classBuilder = classFileFactory.newVisitor(classType, scriptDeclaration.getContainingFile()); ClassBuilder classBuilder = state.getFactory().newVisitor(classType, scriptDeclaration.getContainingFile());
classBuilder.defineClass(scriptDeclaration, classBuilder.defineClass(scriptDeclaration,
V1_6, V1_6,
ACC_PUBLIC, ACC_PUBLIC,
@@ -82,22 +94,19 @@ public class ScriptCodegen extends MemberCodegen {
"java/lang/Object", "java/lang/Object",
new String[0]); new String[0]);
genMembers(scriptDeclaration, context, classBuilder); genMembers(context, classBuilder);
genFieldsForParameters(scriptDescriptor, classBuilder); genFieldsForParameters(scriptDescriptor, classBuilder);
genConstructor(scriptDeclaration, scriptDescriptor, classDescriptorForScript, classBuilder, genConstructor(scriptDescriptor, classDescriptorForScript, classBuilder,
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()), context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()));
earlierScripts);
classBuilder.done(); classBuilder.done();
} }
private void genConstructor( private void genConstructor(
@NotNull JetScript scriptDeclaration,
@NotNull ScriptDescriptor scriptDescriptor, @NotNull ScriptDescriptor scriptDescriptor,
@NotNull ClassDescriptor classDescriptorForScript, @NotNull ClassDescriptor classDescriptorForScript,
@NotNull ClassBuilder classBuilder, @NotNull ClassBuilder classBuilder,
@NotNull MethodContext context, @NotNull MethodContext context
@NotNull List<ScriptDescriptor> importedScripts
) { ) {
Type blockType = typeMapper.mapType(scriptDescriptor.getReturnType()); Type blockType = typeMapper.mapType(scriptDescriptor.getReturnType());
@@ -105,9 +114,7 @@ public class ScriptCodegen extends MemberCodegen {
classBuilder.newField(null, ACC_PUBLIC | ACC_FINAL, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, classBuilder.newField(null, ACC_PUBLIC | ACC_FINAL, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME,
blockType.getDescriptor(), null, null); blockType.getDescriptor(), null, null);
JvmMethodSignature jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, importedScripts); JvmMethodSignature jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, earlierScripts);
state.getScriptCodegen().setScriptConstructorMethod(jvmSignature.getAsmMethod());
MethodVisitor mv = classBuilder.newMethod( MethodVisitor mv = classBuilder.newMethod(
scriptDeclaration, ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), scriptDeclaration, ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
@@ -127,7 +134,7 @@ public class ScriptCodegen extends MemberCodegen {
FrameMap frameMap = context.prepareFrame(typeMapper); FrameMap frameMap = context.prepareFrame(typeMapper);
for (ScriptDescriptor importedScript : importedScripts) { for (ScriptDescriptor importedScript : earlierScripts) {
frameMap.enter(importedScript, OBJECT_TYPE); frameMap.enter(importedScript, OBJECT_TYPE);
} }
@@ -140,14 +147,14 @@ public class ScriptCodegen extends MemberCodegen {
} }
ImplementationBodyCodegen.generateInitializers( ImplementationBodyCodegen.generateInitializers(
new ExpressionCodegen(instructionAdapter, frameMap, Type.VOID_TYPE, context, state), new ExpressionCodegen(instructionAdapter, frameMap, Type.VOID_TYPE, context, state, this),
scriptDeclaration.getDeclarations(), scriptDeclaration.getDeclarations(),
bindingContext, bindingContext,
state); state);
int offset = 1; int offset = 1;
for (ScriptDescriptor earlierScript : importedScripts) { for (ScriptDescriptor earlierScript : earlierScripts) {
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript); Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
instructionAdapter.load(0, classType); instructionAdapter.load(0, classType);
instructionAdapter.load(offset, earlierClassType); instructionAdapter.load(offset, earlierClassType);
@@ -164,7 +171,7 @@ public class ScriptCodegen extends MemberCodegen {
} }
StackValue stackValue = StackValue stackValue =
new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression()); new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state, this).gen(scriptDeclaration.getBlockExpression());
if (stackValue.type != Type.VOID_TYPE) { if (stackValue.type != Type.VOID_TYPE) {
stackValue.put(stackValue.type, instructionAdapter); stackValue.put(stackValue.type, instructionAdapter);
instructionAdapter.putfield(classType.getInternalName(), ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, instructionAdapter.putfield(classType.getInternalName(), ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME,
@@ -190,29 +197,13 @@ public class ScriptCodegen extends MemberCodegen {
} }
} }
private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull FieldOwnerContext context, @NotNull ClassBuilder classBuilder) { private void genMembers(@NotNull FieldOwnerContext context, @NotNull ClassBuilder classBuilder) {
for (JetDeclaration decl : scriptDeclaration.getDeclarations()) { for (JetDeclaration decl : scriptDeclaration.getDeclarations()) {
genFunctionOrProperty(context, (JetTypeParameterListOwner) decl, classBuilder); genFunctionOrProperty(context, (JetTypeParameterListOwner) decl, classBuilder);
} }
} }
public void registerEarlierScripts(List<Pair<ScriptDescriptor, Type>> earlierScripts) { private int getScriptIndex(@NotNull ScriptDescriptor scriptDescriptor) {
for (Pair<ScriptDescriptor, Type> t : earlierScripts) {
ScriptDescriptor earlierDescriptor = t.first;
Type earlierClassName = t.second;
registerClassNameForScript(state.getBindingTrace(), earlierDescriptor, earlierClassName);
}
List<ScriptDescriptor> earlierScriptDescriptors = Lists.newArrayList();
for (Pair<ScriptDescriptor, Type> t : earlierScripts) {
ScriptDescriptor earlierDescriptor = t.first;
earlierScriptDescriptors.add(earlierDescriptor);
}
this.earlierScripts = earlierScriptDescriptors;
}
protected int getScriptIndex(@NotNull ScriptDescriptor scriptDescriptor) {
int index = earlierScripts.indexOf(scriptDescriptor); int index = earlierScripts.indexOf(scriptDescriptor);
if (index < 0) { if (index < 0) {
throw new IllegalStateException("Unregistered script: " + scriptDescriptor); throw new IllegalStateException("Unregistered script: " + scriptDescriptor);
@@ -223,29 +214,4 @@ public class ScriptCodegen extends MemberCodegen {
public String getScriptFieldName(@NotNull ScriptDescriptor scriptDescriptor) { public String getScriptFieldName(@NotNull ScriptDescriptor scriptDescriptor) {
return "script$" + getScriptIndex(scriptDescriptor); return "script$" + getScriptIndex(scriptDescriptor);
} }
public void setScriptConstructorMethod(Method scriptConstructorMethod) {
this.scriptConstructorMethod = scriptConstructorMethod;
}
public Method getScriptConstructorMethod() {
return scriptConstructorMethod;
}
public void compileScript(
@NotNull JetScript script,
@NotNull Type classType,
@NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts,
@NotNull CompilationErrorHandler errorHandler
) {
registerEarlierScripts(earlierScripts);
registerClassNameForScript(state.getBindingTrace(), script, classType);
state.beforeCompile();
KotlinCodegenFacade.generateNamespace(
state,
JetPsiUtil.getFQName((JetFile) script.getContainingFile()),
Collections.singleton((JetFile) script.getContainingFile()),
errorHandler);
}
} }
@@ -16,6 +16,8 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.context.ClassContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapperMode; import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
@@ -24,8 +26,15 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
public class TraitImplBodyCodegen extends ClassBodyCodegen { public class TraitImplBodyCodegen extends ClassBodyCodegen {
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state, null); public TraitImplBodyCodegen(
@NotNull JetClassOrObject aClass,
@NotNull ClassContext context,
@NotNull ClassBuilder v,
@NotNull GenerationState state,
@Nullable MemberCodegen parentCodegen
) {
super(aClass, context, v, state, parentCodegen);
} }
@Override @Override
@@ -40,6 +49,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
v.visitSource(myClass.getContainingFile().getName(), null); v.visitSource(myClass.getContainingFile().getName(), null);
} }
@NotNull
private String jvmName() { private String jvmName() {
return typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.TRAIT_IMPL).getInternalName(); return typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.TRAIT_IMPL).getInternalName();
} }
@@ -187,7 +187,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
} }
@NotNull @NotNull
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) { public ScriptContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) {
return new ScriptContext(script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure); return new ScriptContext(script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
} }
@@ -18,10 +18,12 @@ package org.jetbrains.jet.codegen.state;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.di.InjectorForJvmCodegen; import org.jetbrains.jet.di.InjectorForJvmCodegen;
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -47,9 +49,6 @@ public class GenerationState {
@NotNull @NotNull
private final ClassFileFactory classFileFactory; private final ClassFileFactory classFileFactory;
@NotNull
private final ScriptCodegen scriptCodegen;
@NotNull @NotNull
private final Project project; private final Project project;
@@ -71,6 +70,9 @@ public class GenerationState {
private final boolean generateDeclaredClasses; private final boolean generateDeclaredClasses;
@Nullable
private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
public GenerationState(Project project, ClassBuilderFactory builderFactory, BindingContext bindingContext, List<JetFile> files) { public GenerationState(Project project, ClassBuilderFactory builderFactory, BindingContext bindingContext, List<JetFile> files) {
this(project, builderFactory, Progress.DEAF, bindingContext, files, true, false, true); this(project, builderFactory, Progress.DEAF, bindingContext, files, true, false, true);
} }
@@ -97,7 +99,6 @@ public class GenerationState {
InjectorForJvmCodegen injector = new InjectorForJvmCodegen(typeMapper, this, builderFactory, project); InjectorForJvmCodegen injector = new InjectorForJvmCodegen(typeMapper, this, builderFactory, project);
this.scriptCodegen = injector.getScriptCodegen();
this.intrinsics = injector.getIntrinsics(); this.intrinsics = injector.getIntrinsics();
this.classFileFactory = injector.getClassFileFactory(); this.classFileFactory = injector.getClassFileFactory();
@@ -131,11 +132,6 @@ public class GenerationState {
return files; return files;
} }
@NotNull
public ScriptCodegen getScriptCodegen() {
return scriptCodegen;
}
@NotNull @NotNull
public BindingTrace getBindingTrace() { public BindingTrace getBindingTrace() {
return bindingTrace; return bindingTrace;
@@ -189,4 +185,13 @@ public class GenerationState {
public void destroy() { public void destroy() {
} }
@Nullable
public List<ScriptDescriptor> getEarlierScriptsForReplInterpreter() {
return earlierScriptsForReplInterpreter;
}
public void setEarlierScriptsForReplInterpreter(@Nullable List<ScriptDescriptor> earlierScriptsForReplInterpreter) {
this.earlierScriptsForReplInterpreter = earlierScriptsForReplInterpreter;
}
} }
@@ -23,7 +23,6 @@ import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.codegen.ClassBuilderMode; import org.jetbrains.jet.codegen.ClassBuilderMode;
import org.jetbrains.jet.codegen.ScriptCodegen;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -39,7 +38,6 @@ public class InjectorForJvmCodegen {
private final BindingTrace bindingTrace; private final BindingTrace bindingTrace;
private final BindingContext bindingContext; private final BindingContext bindingContext;
private final ClassBuilderMode classBuilderMode; private final ClassBuilderMode classBuilderMode;
private final ScriptCodegen scriptCodegen;
private final IntrinsicMethods intrinsics; private final IntrinsicMethods intrinsics;
private final ClassFileFactory classFileFactory; private final ClassFileFactory classFileFactory;
@@ -56,12 +54,9 @@ public class InjectorForJvmCodegen {
this.bindingTrace = jetTypeMapper.getBindingTrace(); this.bindingTrace = jetTypeMapper.getBindingTrace();
this.bindingContext = bindingTrace.getBindingContext(); this.bindingContext = bindingTrace.getBindingContext();
this.classBuilderMode = classBuilderFactory.getClassBuilderMode(); this.classBuilderMode = classBuilderFactory.getClassBuilderMode();
this.scriptCodegen = new ScriptCodegen(getGenerationState());
this.intrinsics = new IntrinsicMethods(); this.intrinsics = new IntrinsicMethods();
this.classFileFactory = new ClassFileFactory(getGenerationState()); this.classFileFactory = new ClassFileFactory(getGenerationState());
this.scriptCodegen.setClassFileFactory(classFileFactory);
this.classFileFactory.setBuilderFactory(classBuilderFactory); this.classFileFactory.setBuilderFactory(classBuilderFactory);
intrinsics.init(); intrinsics.init();
@@ -84,10 +79,6 @@ public class InjectorForJvmCodegen {
return this.project; return this.project;
} }
public ScriptCodegen getScriptCodegen() {
return this.scriptCodegen;
}
public IntrinsicMethods getIntrinsics() { public IntrinsicMethods getIntrinsics() {
return this.intrinsics; return this.intrinsics;
} }
@@ -38,6 +38,7 @@ import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.ClassBuilderFactories;
import org.jetbrains.jet.codegen.CompilationErrorHandler; import org.jetbrains.jet.codegen.CompilationErrorHandler;
import org.jetbrains.jet.codegen.KotlinCodegenFacade;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.config.CompilerConfiguration; import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
@@ -46,6 +47,8 @@ import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceLikeBuilderDummy; import org.jetbrains.jet.lang.descriptors.impl.NamespaceLikeBuilderDummy;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.psi.JetScript;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
@@ -67,7 +70,9 @@ import java.net.URLClassLoader;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses; import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.registerClassNameForScript;
public class ReplInterpreter { public class ReplInterpreter {
@@ -232,8 +237,9 @@ public class ReplInterpreter {
BindingContext bindingContext = AnalyzeExhaust.success(trace.getBindingContext(), module).getBindingContext(); BindingContext bindingContext = AnalyzeExhaust.success(trace.getBindingContext(), module).getBindingContext();
GenerationState generationState = new GenerationState(psiFile.getProject(), ClassBuilderFactories.BINARIES, GenerationState generationState = new GenerationState(psiFile.getProject(), ClassBuilderFactories.BINARIES,
bindingContext, Collections.singletonList(psiFile)); bindingContext, Collections.singletonList(psiFile));
generationState.getScriptCodegen().compileScript(psiFile.getScript(), scriptClassType, earlierScripts,
CompilationErrorHandler.THROW_EXCEPTION); compileScript(psiFile.getScript(), scriptClassType, earlierScripts, generationState,
CompilationErrorHandler.THROW_EXCEPTION);
for (String file : generationState.getFactory().files()) { for (String file : generationState.getFactory().files()) {
classLoader.addClass(JvmClassName.byInternalName(file.replaceFirst("\\.class$", "")), generationState.getFactory().asBytes(file)); classLoader.addClass(JvmClassName.byInternalName(file.replaceFirst("\\.class$", "")), generationState.getFactory().asBytes(file));
@@ -317,4 +323,41 @@ public class ReplInterpreter {
public void dumpClasses(@NotNull PrintWriter out) { public void dumpClasses(@NotNull PrintWriter out) {
classLoader.dumpClasses(out); classLoader.dumpClasses(out);
} }
private static void registerEarlierScripts(
@NotNull GenerationState state,
@NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts
) {
for (Pair<ScriptDescriptor, Type> t : earlierScripts) {
ScriptDescriptor earlierDescriptor = t.first;
Type earlierClassType = t.second;
registerClassNameForScript(state.getBindingTrace(), earlierDescriptor, earlierClassType);
}
List<ScriptDescriptor> earlierScriptDescriptors = Lists.newArrayList();
for (Pair<ScriptDescriptor, Type> t : earlierScripts) {
ScriptDescriptor earlierDescriptor = t.first;
earlierScriptDescriptors.add(earlierDescriptor);
}
state.setEarlierScriptsForReplInterpreter(earlierScriptDescriptors);
}
public static void compileScript(
@NotNull JetScript script,
@NotNull Type classType,
@NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts,
@NotNull GenerationState state,
@NotNull CompilationErrorHandler errorHandler
) {
registerEarlierScripts(state, earlierScripts);
registerClassNameForScript(state.getBindingTrace(), script, classType);
state.beforeCompile();
KotlinCodegenFacade.generateNamespace(
state,
JetPsiUtil.getFQName((JetFile) script.getContainingFile()),
Collections.singleton((JetFile) script.getContainingFile()),
errorHandler);
}
} }
@@ -61,7 +61,7 @@ public class ScriptGenTest extends CodegenTestCase {
try { try {
Class<?> scriptClass = loader.loadClass(scriptClassName); Class<?> scriptClass = loader.loadClass(scriptClassName);
Constructor constructor = getConstructor(scriptClass, factory.getState().getScriptCodegen().getScriptConstructorMethod()); Constructor constructor = getConstructor(scriptClass);
scriptInstance = constructor.newInstance(myFiles.getScriptParameterValues().toArray()); scriptInstance = constructor.newInstance(myFiles.getScriptParameterValues().toArray());
assertFalse("expecting at least one expectation", myFiles.getExpectedValues().isEmpty()); assertFalse("expecting at least one expectation", myFiles.getExpectedValues().isEmpty());
@@ -92,43 +92,12 @@ public class ScriptGenTest extends CodegenTestCase {
} }
} }
protected Constructor getConstructor(@NotNull Class<?> clazz, org.jetbrains.asm4.commons.Method method) { protected Constructor getConstructor(@NotNull Class<?> clazz) {
if (!method.getName().equals("<init>")) { Constructor [] constructors = clazz.getConstructors();
throw new IllegalArgumentException("not constructor: " + method); if (constructors == null || constructors.length != 1) {
} throw new IllegalArgumentException("Script class should have one constructor: " + clazz);
Class[] classes = new Class[method.getArgumentTypes().length];
for (int i = 0; i < classes.length; ++i) {
classes[i] = loadClassFromType(method.getArgumentTypes()[i]);
}
try {
return clazz.getConstructor(classes);
}
catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
@NotNull
private Class<?> loadClassFromType(@NotNull Type type) {
try {
switch (type.getSort()) {
case Type.OBJECT:
return Class.forName(type.getClassName());
case Type.INT:
return int.class;
case Type.LONG:
return long.class;
default:
// AFAIK there is no way to create array class from class
if (type.getDescriptor().equals("[Ljava/lang/String;")) {
return String[].class;
}
throw new IllegalStateException("not implemented: " + type.getDescriptor());
}
}
catch (Exception e) {
throw ExceptionUtils.rethrow(e);
} }
return constructors[0];
} }
public void testHelloWorld() { public void testHelloWorld() {
@@ -17,10 +17,7 @@
package org.jetbrains.jet.generators.injectors; package org.jetbrains.jet.generators.injectors;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.ClassBuilderMode;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.ScriptCodegen;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapper;
@@ -233,7 +230,6 @@ public class GenerateInjectors {
new GivenExpression("bindingTrace.getBindingContext()")); new GivenExpression("bindingTrace.getBindingContext()"));
generator.addField(false, ClassBuilderMode.class, "classBuilderMode", generator.addField(false, ClassBuilderMode.class, "classBuilderMode",
new GivenExpression("classBuilderFactory.getClassBuilderMode()")); new GivenExpression("classBuilderFactory.getClassBuilderMode()"));
generator.addPublicField(ScriptCodegen.class);
generator.addField(true, IntrinsicMethods.class, "intrinsics", null); generator.addField(true, IntrinsicMethods.class, "intrinsics", null);
generator.addPublicField(ClassFileFactory.class); generator.addPublicField(ClassFileFactory.class);