minor codegen refactoring

* cleanup after yesterday
* remove BindingContext stack in GenerationState
* use more power and strength of di

TODO: also initialize GenerationState by DI
This commit is contained in:
Stepan Koltsov
2012-03-29 19:47:50 +04:00
parent d76454ce08
commit e6fda5b3d3
16 changed files with 247 additions and 139 deletions
@@ -20,23 +20,34 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.FqName;
import javax.inject.Inject;
import java.util.*;
/**
* @author max
*/
public class ClassFileFactory {
private final ClassBuilderFactory builderFactory;
private ClassBuilderFactory builderFactory;
public GenerationState state;
private final Map<FqName, NamespaceCodegen> ns2codegen = new HashMap<FqName, NamespaceCodegen>();
private final Map<String, ClassBuilder> generators = new LinkedHashMap<String, ClassBuilder>();
private boolean isDone = false;
public final GenerationState state;
public ClassFileFactory(ClassBuilderFactory builderFactory, GenerationState state) {
@Inject
public void setBuilderFactory(ClassBuilderFactory builderFactory) {
this.builderFactory = builderFactory;
}
@Inject
public void setState(GenerationState state) {
this.state = state;
}
ClassBuilder newVisitor(String filePath) {
state.getProgress().log("Emitting: " + filePath);
final ClassBuilder answer = builderFactory.newClassBuilder();
@@ -24,11 +24,8 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.di.InjectorForJvmCodegen;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
@@ -36,58 +33,50 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzeExhaust;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.utils.Progress;
import java.util.Collections;
import java.util.List;
public class GenerationState {
@NotNull
private final ClassFileFactory factory;
private final Project project;
private final Stack<BindingContext> bindingContexts = new Stack<BindingContext>();
private final Progress progress;
@NotNull
private final AnalyzeExhaust analyzeExhaust;
@NotNull
private final List<JetFile> files;
@NotNull
private final InjectorForJvmCodegen injector;
// initialized after analyze
private InjectorForJvmCodegen injector;
public GenerationState(Project project, ClassBuilderFactory builderFactory) {
this(project, builderFactory, Progress.DEAF);
public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List<JetFile> files) {
this(project, builderFactory, Progress.DEAF, analyzeExhaust, files);
}
public GenerationState(Project project, ClassBuilderFactory builderFactory, Progress progress) {
public GenerationState(Project project, ClassBuilderFactory builderFactory, Progress progress, @NotNull AnalyzeExhaust exhaust, @NotNull List<JetFile> files) {
this.project = project;
this.progress = progress;
this.factory = new ClassFileFactory(builderFactory, this);
this.analyzeExhaust = exhaust;
this.files = files;
this.injector = new InjectorForJvmCodegen(analyzeExhaust.getStandardLibrary(), analyzeExhaust.getBindingContext(), this.files, project, this, builderFactory);
}
@NotNull
public ClassFileFactory getFactory() {
return factory;
return getInjector().getClassFileFactory();
}
public Progress getProgress() {
return progress;
}
public Project getProject() {
return project;
}
public InjectorForJvmCodegen getInjector() {
return injector;
}
public BindingContext getBindingContext() {
return bindingContexts.peek();
return analyzeExhaust.getBindingContext();
}
public ClassCodegen forClass() {
@@ -95,73 +84,42 @@ public class GenerationState {
}
public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
return factory.newVisitor(injector.getJetTypeMapper().mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + ".class");
return getFactory().newVisitor(getInjector().getJetTypeMapper().mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + ".class");
}
public ClassBuilder forTraitImplementation(ClassDescriptor aClass) {
return factory.newVisitor(injector.getJetTypeMapper().mapType(aClass.getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName() + ".class");
return getFactory().newVisitor(getInjector().getJetTypeMapper().mapType(aClass.getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName() + ".class");
}
public Pair<String, ClassBuilder> forAnonymousSubclass(JetExpression expression) {
String className = injector.getJetTypeMapper().getClosureAnnotator().classNameForAnonymousClass(expression);
return Pair.create(className, factory.forAnonymousSubclass(className));
String className = getInjector().getJetTypeMapper().getClosureAnnotator().classNameForAnonymousClass(expression);
return Pair.create(className, getFactory().forAnonymousSubclass(className));
}
public NamespaceCodegen forNamespace(JetFile namespace) {
return factory.forNamespace(namespace);
return getFactory().forNamespace(namespace);
}
public BindingContext compile(JetFile file) {
final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY);
AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
compileCorrectFiles(analyzeExhaust, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true);
return analyzeExhaust.getBindingContext();
// NamespaceCodegen codegen = forNamespace(namespace);
// bindingContexts.push(bindingContext);
// typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
// try {
// AnalyzingUtils.throwExceptionOnErrors(bindingContext);
//
// codegen.generate(namespace);
// }
// finally {
// bindingContexts.pop();
// typeMapper = null;
// }
}
public void compileCorrectFiles(AnalyzeExhaust bindingContext, List<JetFile> files, boolean annotate) {
compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION, annotate);
}
public void compileCorrectFiles(AnalyzeExhaust analyzeExhaust, List<JetFile> files, @NotNull CompilationErrorHandler errorHandler, boolean annotate) {
injector = new InjectorForJvmCodegen(analyzeExhaust.getStandardLibrary(), analyzeExhaust.getBindingContext(), files, project);
bindingContexts.push(analyzeExhaust.getBindingContext());
try {
for (JetFile file : files) {
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
VirtualFile vFile = file.getVirtualFile();
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
progress.log("For source: " + path);
try {
generateNamespace(file);
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
errorHandler.reportException(e, vFile == null ? "no file" : vFile.getUrl());
DiagnosticUtils.throwIfRunningOnServer(e);
if (ApplicationManager.getApplication().isInternal()) {
e.printStackTrace();
}
public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) {
for (JetFile file : this.files) {
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
VirtualFile vFile = file.getVirtualFile();
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
progress.log("For source: " + path);
try {
generateNamespace(file);
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
errorHandler.reportException(e, vFile == null ? "no file" : vFile.getUrl());
DiagnosticUtils.throwIfRunningOnServer(e);
if (ApplicationManager.getApplication().isInternal()) {
e.printStackTrace();
}
}
}
finally {
bindingContexts.pop();
}
}
protected void generateNamespace(JetFile namespace) {
@@ -175,11 +133,12 @@ public class GenerationState {
closure.cv = nameAndVisitor.getSecond();
closure.name = nameAndVisitor.getFirst();
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, injector.getJetTypeMapper());
final CodegenContext objectContext = closure.context.intoAnonymousClass(
closure, analyzeExhaust.getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, injector.getJetTypeMapper());
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
ConstructorDescriptor constructorDescriptor = analyzeExhaust.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
CallableMethod callableMethod = injector.getJetTypeMapper().mapToCallableMethod(
constructorDescriptor, OwnerKind.IMPLEMENTATION, injector.getJetTypeMapper().hasThis0(constructorDescriptor.getContainingDeclaration()));
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(), objectContext.outerWasUsed, null);
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2012 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.di;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.ClosureAnnotator;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.annotations.NotNull;
/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */
public class InjectorForJetTypeMapper {
private JetTypeMapper jetTypeMapper;
public InjectorForJetTypeMapper(
@NotNull JetStandardLibrary jetStandardLibrary,
@NotNull BindingContext bindingContext,
@NotNull List<JetFile> listOfJetFile
) {
this.jetTypeMapper = new JetTypeMapper();
ClosureAnnotator closureAnnotator = new ClosureAnnotator();
this.jetTypeMapper.setBindingContext(bindingContext);
this.jetTypeMapper.setClosureAnnotator(closureAnnotator);
this.jetTypeMapper.setStandardLibrary(jetStandardLibrary);
closureAnnotator.setBindingContext(bindingContext);
closureAnnotator.setFiles(listOfJetFile);
jetTypeMapper.init();
closureAnnotator.init();
}
public JetTypeMapper getJetTypeMapper() {
return this.jetTypeMapper;
}
}
@@ -22,32 +22,43 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.ClosureAnnotator;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.annotations.NotNull;
/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */
public class InjectorForJvmCodegen {
private final JetStandardLibrary jetStandardLibrary;
private final GenerationState generationState;
private JetTypeMapper jetTypeMapper;
private IntrinsicMethods intrinsics;
private ClassFileFactory classFileFactory;
public InjectorForJvmCodegen(
@NotNull JetStandardLibrary jetStandardLibrary,
@NotNull BindingContext bindingContext,
@NotNull List<JetFile> listOfJetFile,
@NotNull Project project
@NotNull Project project,
@NotNull GenerationState generationState,
@NotNull ClassBuilderFactory classBuilderFactory
) {
this.jetStandardLibrary = jetStandardLibrary;
this.generationState = generationState;
this.jetTypeMapper = new JetTypeMapper();
this.intrinsics = new IntrinsicMethods();
this.classFileFactory = new ClassFileFactory();
ClosureAnnotator closureAnnotator = new ClosureAnnotator();
this.jetTypeMapper.setBindingContext(bindingContext);
@@ -57,6 +68,9 @@ public class InjectorForJvmCodegen {
this.intrinsics.setMyProject(project);
this.intrinsics.setMyStdLib(jetStandardLibrary);
this.classFileFactory.setBuilderFactory(classBuilderFactory);
this.classFileFactory.setState(generationState);
closureAnnotator.setBindingContext(bindingContext);
closureAnnotator.setFiles(listOfJetFile);
@@ -72,6 +86,10 @@ public class InjectorForJvmCodegen {
return this.jetStandardLibrary;
}
public GenerationState getGenerationState() {
return this.generationState;
}
public JetTypeMapper getJetTypeMapper() {
return this.jetTypeMapper;
}
@@ -80,4 +98,8 @@ public class InjectorForJvmCodegen {
return this.intrinsics;
}
public ClassFileFactory getClassFileFactory() {
return this.classFileFactory;
}
}