Fix stdlib import aliasing and launch captures

This commit is contained in:
Sergey Chernov 2026-04-11 20:24:44 +03:00
parent 6171b0d95f
commit eefa4c8f1a
2 changed files with 20 additions and 3 deletions

View File

@ -19,6 +19,8 @@ package net.sergeych.lyng
import net.sergeych.lyng.bytecode.BytecodeFrame import net.sergeych.lyng.bytecode.BytecodeFrame
import net.sergeych.lyng.bytecode.CmdFunction import net.sergeych.lyng.bytecode.CmdFunction
import net.sergeych.lyng.obj.ObjClass
import net.sergeych.lyng.obj.ObjExternCallable
import net.sergeych.lyng.obj.ObjRecord import net.sergeych.lyng.obj.ObjRecord
import net.sergeych.lyng.obj.ObjString import net.sergeych.lyng.obj.ObjString
import net.sergeych.lyng.pacman.ImportProvider import net.sergeych.lyng.pacman.ImportProvider
@ -33,6 +35,20 @@ class ModuleScope(
override val packageName: String override val packageName: String
) : Scope(importProvider.rootScope, Arguments.EMPTY, pos) { ) : Scope(importProvider.rootScope, Arguments.EMPTY, pos) {
private fun ObjRecord.isEquivalentStdlibAlias(other: ObjRecord): Boolean {
val leftOrigin = importedFrom?.packageName
val rightOrigin = other.importedFrom?.packageName
val origins = setOf(leftOrigin, rightOrigin)
val rootStdlibAlias =
"lyng.stdlib" in origins &&
origins.all { it == null || it == "<anonymous package>" || it == "lyng.stdlib" }
if (!rootStdlibAlias) return false
if (value !== other.value) return false
if (receiver !== other.receiver || delegate !== other.delegate) return false
if (memberName != other.memberName || fieldId != other.fieldId || methodId != other.methodId) return false
return value is ObjExternCallable || value is ObjClass
}
constructor(importProvider: ImportProvider, source: Source) : this(importProvider, source.startPos, source.fileName) constructor(importProvider: ImportProvider, source: Source) : this(importProvider, source.startPos, source.fileName)
internal var importedModules: List<ModuleScope> = emptyList() internal var importedModules: List<ModuleScope> = emptyList()
@ -96,8 +112,8 @@ class ModuleScope(
if (existing != null) { if (existing != null) {
val sameBinding = val sameBinding =
existing === record || existing === record ||
existing.importedFrom == record.importedFrom || existing.importedFrom == record.importedFrom ||
existing.value === record.value existing.isEquivalentStdlibAlias(record)
if (!sameBinding) if (!sameBinding)
scope.raiseError("symbol ${existing.importedFrom?.packageName}.$newName already exists, redefinition on import is not allowed") scope.raiseError("symbol ${existing.importedFrom?.packageName}.$newName already exists, redefinition on import is not allowed")
// already imported // already imported

View File

@ -3784,6 +3784,7 @@ class BytecodeLambdaCallable(
override val pos: Pos, override val pos: Pos,
) : Statement(), BytecodeCallable { ) : Statement(), BytecodeCallable {
private fun freezeRecord(record: ObjRecord): ObjRecord { private fun freezeRecord(record: ObjRecord): ObjRecord {
if (record.isMutable) return record
val frozenValue = when (val raw = record.value) { val frozenValue = when (val raw = record.value) {
is net.sergeych.lyng.FrameSlotRef -> raw.read() is net.sergeych.lyng.FrameSlotRef -> raw.read()
is net.sergeych.lyng.RecordSlotRef -> raw.read() is net.sergeych.lyng.RecordSlotRef -> raw.read()
@ -3808,7 +3809,7 @@ class BytecodeLambdaCallable(
return BytecodeLambdaCallable( return BytecodeLambdaCallable(
fn = fn, fn = fn,
closureScope = newClosureScope, closureScope = newClosureScope,
captureRecords = resolveCaptureRecords(newClosureScope) ?: captureRecords, captureRecords = captureRecords ?: resolveCaptureRecords(newClosureScope),
captureNames = captureNames, captureNames = captureNames,
paramSlotPlan = paramSlotPlan, paramSlotPlan = paramSlotPlan,
argsDeclaration = argsDeclaration, argsDeclaration = argsDeclaration,