From 7289903fa5e0be0702a930aeb13ed2b4e5cd4b17 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 21 Mar 2017 15:04:19 +0300 Subject: [PATCH] Introduce SymbolTable as a symbol factory and unbound symbols tracker --- .../psi2ir/generators/GeneratorContext.kt | 2 + .../kotlin/psi2ir/generators/SymbolTable.kt | 178 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SymbolTable.kt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt index a0ccfdc7011..43610576d78 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt @@ -33,6 +33,8 @@ class GeneratorContext( ) : IrGeneratorContext(IrBuiltIns(moduleDescriptor.builtIns)) { val sourceManager = PsiSourceManager() + val symbolTable = SymbolTable() + // TODO: inject a correct StorageManager instance, or store NotFoundClasses inside ModuleDescriptor val reflectionTypes = ReflectionTypes(moduleDescriptor, NotFoundClasses(LockBasedStorageManager.NO_LOCKS, moduleDescriptor)) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SymbolTable.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SymbolTable.kt new file mode 100644 index 00000000000..c3c13be7c11 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SymbolTable.kt @@ -0,0 +1,178 @@ +/* + * Copyright 2010-2017 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.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.symbols.impl.* + +class SymbolTable { + private class SpecializedSymbolTable> { + val descriptorToSymbol = linkedMapOf() + val unboundSymbols = linkedSetOf() + + inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { + val symbol = declared(d, createSymbol) + val owner = createOwner(symbol) + symbol.bind(owner) + return owner + } + + inline fun declared(d: D, createSymbol: () -> S): S { + val existing = descriptorToSymbol[d] + return if (existing == null) { + val new = createSymbol() + descriptorToSymbol[d] = new + new + } + else { + assert(unboundSymbols.remove(existing)) { + "Symbol for $d is already bound" + } + existing + } + } + + inline fun referenced(d: D, createSymbol: () -> S): S = + descriptorToSymbol.getOrPut(d) { + createSymbol().also { + unboundSymbols.add(it) + } + } + } + + private val classSymbolTable = SpecializedSymbolTable() + private val constructorSymbolTable = SpecializedSymbolTable() + private val enumEntrySymbolTable = SpecializedSymbolTable() + private val fieldSymbolTable = SpecializedSymbolTable() + private val simpleFunctionSymbolTable = SpecializedSymbolTable() + private val typeParameterSymbolTable = SpecializedSymbolTable() + private val valueParameterSymbolTable = SpecializedSymbolTable() + private val variableSymbolTable = SpecializedSymbolTable() + + fun declareFile(fileEntry: SourceManager.FileEntry, packageFragmentDescriptor: PackageFragmentDescriptor): IrFile = + IrFileImpl( + fileEntry, packageFragmentDescriptor, + IrFileSymbolImpl(packageFragmentDescriptor) + ) + + fun declareAnonymousInitializer(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrAnonymousInitializer = + IrAnonymousInitializerImpl( + startOffset, endOffset, origin, descriptor, + IrAnonymousInitializerSymbolImpl(descriptor) + ) + + fun declareClass(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrClass = + classSymbolTable.declare( + descriptor, + { IrClassSymbolImpl(descriptor) }, + { IrClassImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + + fun referenceClass(descriptor: ClassDescriptor) = + classSymbolTable.referenced(descriptor) { IrClassSymbolImpl(descriptor) } + + val unboundClasses: Set get() = classSymbolTable.unboundSymbols + + fun declareConstructor(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassConstructorDescriptor): IrConstructor = + constructorSymbolTable.declare( + descriptor, + { IrConstructorSymbolImpl(descriptor) }, + { IrConstructorImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceConstructor(descriptor: ClassConstructorDescriptor) = + constructorSymbolTable.referenced(descriptor) { IrConstructorSymbolImpl(descriptor) } + + val unboundConstructors: Set get() = constructorSymbolTable.unboundSymbols + + fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrEnumEntry = + enumEntrySymbolTable.declare( + descriptor, + { IrEnumEntrySymbolImpl(descriptor) }, + { IrEnumEntryImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceEnumEntry(descriptor: ClassDescriptor) = + enumEntrySymbolTable.referenced(descriptor) { IrEnumEntrySymbolImpl(descriptor) } + + val unboundEnumEntries: Set get() = enumEntrySymbolTable.unboundSymbols + + fun declareField(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: PropertyDescriptor): IrField = + fieldSymbolTable.declare( + descriptor, + { IrFieldSymbolImpl(descriptor) }, + { IrFieldImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceField(descriptor: PropertyDescriptor) = + fieldSymbolTable.referenced(descriptor) { IrFieldSymbolImpl(descriptor) } + + val unboundFields: Set get() = fieldSymbolTable.unboundSymbols + + fun declareSimpleFunction(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: FunctionDescriptor): IrSimpleFunction = + simpleFunctionSymbolTable.declare( + descriptor, + { IrSimpleFunctionSymbolImpl(descriptor) }, + { IrFunctionImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceSimpleFunction(descriptor: FunctionDescriptor) = + simpleFunctionSymbolTable.referenced(descriptor) { IrSimpleFunctionSymbolImpl(descriptor) } + + val unboundSimpleFunctions: Set get() = simpleFunctionSymbolTable.unboundSymbols + + fun declareTypeParameter(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: TypeParameterDescriptor) : IrTypeParameter = + typeParameterSymbolTable.declare( + descriptor, + { IrTypeParameterSymbolImpl(descriptor) }, + { IrTypeParameterImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceTypeParameter(descriptor: TypeParameterDescriptor) = + typeParameterSymbolTable.referenced(descriptor) { IrTypeParameterSymbolImpl(descriptor) } + + val unboundTypeParameters: Set get() = typeParameterSymbolTable.unboundSymbols + + fun declareValueParameter(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ParameterDescriptor): IrValueParameter = + valueParameterSymbolTable.declare( + descriptor, + { IrValueParameterSymbolImpl(descriptor) }, + { IrValueParameterImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceValueParameter(descriptor: ParameterDescriptor) = + valueParameterSymbolTable.referenced(descriptor) { IrValueParameterSymbolImpl(descriptor) } + + val unboundValueParameters: Set get() = valueParameterSymbolTable.unboundSymbols + + fun declareVariable(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: VariableDescriptor): IrVariable = + variableSymbolTable.declare( + descriptor, + { IrVariableSymbolImpl(descriptor) }, + { IrVariableImpl(startOffset, endOffset, origin, descriptor, it) } + ) + + fun referenceVariable(descriptor: VariableDescriptor) = + variableSymbolTable.referenced(descriptor) { IrVariableSymbolImpl(descriptor) } + + val unboundVariables: Set get() = variableSymbolTable.unboundSymbols +} \ No newline at end of file