96 lines
3.8 KiB
Kotlin
96 lines
3.8 KiB
Kotlin
/*
|
|
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
|
*
|
|
* 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 net.sergeych.lyng
|
|
|
|
import net.sergeych.lyng.obj.ObjRecord
|
|
import net.sergeych.lyng.obj.ObjString
|
|
import net.sergeych.lyng.pacman.ImportProvider
|
|
|
|
/**
|
|
* Module scope supports importing and contains the [importProvider]; it should be the same
|
|
* used in [Compiler];
|
|
*/
|
|
class ModuleScope(
|
|
var importProvider: ImportProvider,
|
|
pos: Pos = Pos.builtIn,
|
|
override val packageName: String
|
|
) : Scope(importProvider.rootScope, Arguments.EMPTY, pos) {
|
|
|
|
constructor(importProvider: ImportProvider, source: Source) : this(importProvider, source.startPos, source.fileName)
|
|
|
|
/**
|
|
* Import symbols into the scope. It _is called_ after the module is imported by [ImportProvider.prepareImport]
|
|
* which checks symbol availability and accessibility prior to execution.
|
|
* @param scope where to copy symbols from this module
|
|
* @param symbols symbols to import, ir present, only symbols keys will be imported renamed to corresponding values
|
|
*/
|
|
override suspend fun importInto(scope: Scope, symbols: Map<String, String>?) {
|
|
val symbolsToImport = symbols?.keys?.toMutableSet()
|
|
for ((symbol, record) in this.objects) {
|
|
if (record.visibility.isPublic) {
|
|
val newName = symbols?.let { ss: Map<String, String> ->
|
|
ss[symbol]
|
|
?.also { symbolsToImport!!.remove(symbol) }
|
|
?: return@let null
|
|
} ?: if (symbols == null) symbol else null
|
|
|
|
if (newName != null) {
|
|
val existing = scope.objects[newName]
|
|
if (existing != null) {
|
|
if (existing.importedFrom != record.importedFrom)
|
|
scope.raiseError("symbol ${existing.importedFrom?.packageName}.$newName already exists, redefinition on import is not allowed")
|
|
// already imported
|
|
} else {
|
|
// when importing records, we keep track of its package (not otherwise needed)
|
|
if (record.importedFrom == null) record.importedFrom = this
|
|
scope.objects[newName] = record
|
|
scope.updateSlotFor(newName, record)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for ((cls, map) in this.extensions) {
|
|
for ((symbol, record) in map) {
|
|
if (record.visibility.isPublic) {
|
|
val newName = symbols?.let { ss: Map<String, String> ->
|
|
ss[symbol]
|
|
?.also { symbolsToImport!!.remove(symbol) }
|
|
?: return@let null
|
|
} ?: if (symbols == null) symbol else null
|
|
|
|
if (newName != null) {
|
|
scope.addExtension(cls, newName, record)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!symbolsToImport.isNullOrEmpty())
|
|
scope.raiseSymbolNotFound("symbols $packageName.{$symbolsToImport} are.were not found")
|
|
}
|
|
|
|
val packageNameObj by lazy { ObjString(packageName).asReadonly }
|
|
|
|
override fun get(name: String): ObjRecord? {
|
|
return if (name == "__PACKAGE__")
|
|
packageNameObj
|
|
else
|
|
super.get(name)
|
|
}
|
|
}
|
|
|