diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ImportBinding.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ImportBinding.kt new file mode 100644 index 0000000..77d7daf --- /dev/null +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ImportBinding.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2026 Sergey S. Chernov + * + * 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 + +sealed class ImportBindingSource { + data class Module(val name: String, val pos: Pos) : ImportBindingSource() + object Root : ImportBindingSource() + object Seed : ImportBindingSource() +} + +data class ImportBinding( + val symbol: String, + val source: ImportBindingSource, +) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt index b188c89..4b19eff 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt @@ -33,6 +33,7 @@ class Script( override val pos: Pos, private val statements: List = emptyList(), private val moduleSlotPlan: Map = emptyMap(), + private val importBindings: Map = emptyMap(), // private val catchReturn: Boolean = false, ) : Statement() { @@ -48,7 +49,11 @@ class Script( return lastResult } - private fun seedModuleSlots(scope: Scope) { + private suspend fun seedModuleSlots(scope: Scope) { + if (importBindings.isNotEmpty()) { + seedImportBindings(scope) + return + } val parent = scope.parent ?: return for (name in moduleSlotPlan.keys) { if (scope.objects.containsKey(name)) { @@ -70,6 +75,32 @@ class Script( } } + private suspend fun seedImportBindings(scope: Scope) { + val provider = scope.currentImportProvider + for ((name, binding) in importBindings) { + val record = when (val source = binding.source) { + is ImportBindingSource.Module -> { + val module = provider.prepareImport(source.pos, source.name, null) + module.objects[binding.symbol]?.takeIf { it.visibility.isPublic } + ?: scope.raiseSymbolNotFound("symbol ${source.name}.${binding.symbol} not found") + } + ImportBindingSource.Root -> { + provider.rootScope.objects[binding.symbol]?.takeIf { it.visibility.isPublic } + ?: scope.raiseSymbolNotFound("symbol ${binding.symbol} not found") + } + ImportBindingSource.Seed -> { + findSeedRecord(scope, binding.symbol) + ?: scope.raiseSymbolNotFound("symbol ${binding.symbol} not found") + } + } + if (name == "Exception" && record.value !is ObjClass) { + scope.updateSlotFor(name, ObjRecord(ObjException.Root, isMutable = false)) + } else { + scope.updateSlotFor(name, record) + } + } + } + private fun findSeedRecord(scope: Scope?, name: String): ObjRecord? { var s = scope var hops = 0