added LaunchPool

This commit is contained in:
sergeych committed 2026-04-18 23:37:21 +03:00
1 parent 145c3ae34a
commit a8f73dc8bd
9 files changed
+533 -30

No files matched your search

@@ -1,5 +1,5 @@
/*
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
* Copyright 2026 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.
@@ -24,7 +24,10 @@ sealed class CodeContext {
val implicitThisMembers: Boolean = false,
val implicitThisTypeName: String? = null,
val typeParams: Set<String> = emptySet(),
val typeParamDecls: List<TypeDecl.TypeParam> = emptyList()
val typeParamDecls: List<TypeDecl.TypeParam> = emptyList(),
/** True for static methods and top-level functions: they have no implicit `this`,
* so class-body field initializers inside them should not inherit the class name. */
val noImplicitThis: Boolean = false
): CodeContext()
class ClassBody(val name: String, val isExtern: Boolean = false): CodeContext() {
var typeParams: Set<String> = emptySet()
@@ -812,8 +812,18 @@ class Compiler(
private fun currentImplicitThisTypeName(): String? {
for (ctx in codeContexts.asReversed()) {
val fn = ctx as? CodeContext.Function ?: continue
if (fn.implicitThisTypeName != null) return fn.implicitThisTypeName
when (ctx) {
is CodeContext.Function -> {
if (ctx.implicitThisTypeName != null) return ctx.implicitThisTypeName
// A static method or top-level function explicitly has no implicit `this`.
// Stop here — do not fall through to an enclosing ClassBody.
if (ctx.noImplicitThis) return null
}
// Class field initializers are compiled directly under ClassBody with no wrapping
// Function. Lambdas inside those initializers must still see `this` as the class.
is CodeContext.ClassBody -> return ctx.name
else -> {}
}
}
return null
}
@@ -9214,13 +9224,17 @@ class Compiler(
parentContext is CodeContext.ClassBody && !isStatic -> parentContext.name
else -> null
}
// Static methods and top-level functions have no implicit `this`; mark them so that
// currentImplicitThisTypeName() does not fall through to an enclosing ClassBody.
val noImplicitThis = implicitThisTypeName == null && extTypeName == null
return inCodeContext(
CodeContext.Function(
name,
implicitThisMembers = implicitThisMembers,
implicitThisTypeName = implicitThisTypeName,
typeParams = typeParams,
typeParamDecls = typeParamDecls
typeParamDecls = typeParamDecls,
noImplicitThis = noImplicitThis
)
) {
cc.labels.add(name)
@@ -5869,17 +5869,22 @@ class BytecodeCompiler(
}
private fun compileCatchClassSlot(name: String): CompiledValue? {
val ref = LocalVarRef(name, Pos.builtIn)
val compiled = compileRef(ref)
if (compiled != null) {
return ensureObjSlot(compiled)
// resolveTypeNameClass always returns the correct Lyng class for built-in type names.
// nameObjClass[name] tracks variable type inference — for class declarations it stores
// ObjClassType (the "Class" meta-type), NOT the actual class object. Using nameObjClass
// for catch clause matching would cause CHECK_IS to compare against the wrong class,
// silently failing to catch exceptions. Always prefer resolveTypeNameClass first.
val cls = resolveTypeNameClass(name) ?: nameObjClass[name]?.takeIf { it != ObjClassType }
if (cls != null) {
val id = builder.addConst(BytecodeConst.ObjRef(cls))
val slot = allocSlot()
builder.emit(Opcode.CONST_OBJ, id, slot)
updateSlotType(slot, SlotType.OBJ)
return CompiledValue(slot, SlotType.OBJ)
}
val cls = nameObjClass[name] ?: resolveTypeNameClass(name) ?: return null
val id = builder.addConst(BytecodeConst.ObjRef(cls))
val slot = allocSlot()
builder.emit(Opcode.CONST_OBJ, id, slot)
updateSlotType(slot, SlotType.OBJ)
return CompiledValue(slot, SlotType.OBJ)
val ref = LocalVarRef(name, Pos.builtIn)
val compiled = compileRef(ref) ?: return null
return ensureObjSlot(compiled)
}
private fun emitInlineStatements(statements: List<Statement>, needResult: Boolean): CompiledValue? {