avoid suspend lambdas in var declaration statements
This commit is contained in:
parent
062f9e7866
commit
9b580bafb6
@ -3472,89 +3472,140 @@ class Compiler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return statement(start) { context ->
|
return object : Statement() {
|
||||||
if (extTypeName != null) {
|
override val pos: Pos = start
|
||||||
val prop = if (getter != null || setter != null) {
|
override suspend fun execute(context: Scope): Obj {
|
||||||
ObjProperty(name, getter, setter)
|
if (extTypeName != null) {
|
||||||
} else {
|
val prop = if (getter != null || setter != null) {
|
||||||
// Simple val extension with initializer
|
ObjProperty(name, getter, setter)
|
||||||
val initExpr = initialExpression ?: throw ScriptError(start, "Extension val must be initialized")
|
} else {
|
||||||
ObjProperty(name, statement(initExpr.pos) { scp -> initExpr.execute(scp) }, null)
|
// Simple val extension with initializer
|
||||||
|
val initExpr = initialExpression ?: throw ScriptError(start, "Extension val must be initialized")
|
||||||
|
ObjProperty(
|
||||||
|
name,
|
||||||
|
object : Statement() {
|
||||||
|
override val pos: Pos = initExpr.pos
|
||||||
|
override suspend fun execute(scp: Scope): Obj = initExpr.execute(scp)
|
||||||
|
},
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val type = context[extTypeName]?.value ?: context.raiseSymbolNotFound("class $extTypeName not found")
|
||||||
|
if (type !is ObjClass) context.raiseClassCastError("$extTypeName is not the class instance")
|
||||||
|
|
||||||
|
context.addExtension(
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
ObjRecord(
|
||||||
|
prop,
|
||||||
|
isMutable = false,
|
||||||
|
visibility = visibility,
|
||||||
|
writeVisibility = setterVisibility,
|
||||||
|
declaringClass = null,
|
||||||
|
type = ObjRecord.Type.Property
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return prop
|
||||||
|
}
|
||||||
|
// In true class bodies (not inside a function), store fields under a class-qualified key to support MI collisions
|
||||||
|
// Do NOT infer declaring class from runtime thisObj here; only the compile-time captured
|
||||||
|
// ClassBody qualifies for class-field storage. Otherwise, this is a plain local.
|
||||||
|
isProperty = getter != null || setter != null
|
||||||
|
val declaringClassName = declaringClassNameCaptured
|
||||||
|
if (declaringClassName == null) {
|
||||||
|
if (context.containsLocal(name))
|
||||||
|
throw ScriptError(start, "Variable $name is already defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
val type = context[extTypeName]?.value ?: context.raiseSymbolNotFound("class $extTypeName not found")
|
// Register the local name so subsequent identifiers can be emitted as fast locals
|
||||||
if (type !is ObjClass) context.raiseClassCastError("$extTypeName is not the class instance")
|
if (!isStatic) declareLocalName(name)
|
||||||
|
|
||||||
context.addExtension(type, name, ObjRecord(prop, isMutable = false, visibility = visibility, writeVisibility = setterVisibility, declaringClass = null, type = ObjRecord.Type.Property))
|
if (isDelegate) {
|
||||||
|
val declaringClassName = declaringClassNameCaptured
|
||||||
return@statement prop
|
if (declaringClassName != null) {
|
||||||
}
|
val storageName = "$declaringClassName::$name"
|
||||||
// In true class bodies (not inside a function), store fields under a class-qualified key to support MI collisions
|
val isClassScope = context.thisObj is ObjClass && (context.thisObj !is ObjInstance)
|
||||||
// Do NOT infer declaring class from runtime thisObj here; only the compile-time captured
|
if (isClassScope) {
|
||||||
// ClassBody qualifies for class-field storage. Otherwise, this is a plain local.
|
val cls = context.thisObj as ObjClass
|
||||||
isProperty = getter != null || setter != null
|
cls.createField(
|
||||||
val declaringClassName = declaringClassNameCaptured
|
name,
|
||||||
if (declaringClassName == null) {
|
ObjUnset,
|
||||||
if (context.containsLocal(name))
|
isMutable,
|
||||||
throw ScriptError(start, "Variable $name is already defined")
|
visibility,
|
||||||
}
|
setterVisibility,
|
||||||
|
start,
|
||||||
// Register the local name so subsequent identifiers can be emitted as fast locals
|
isTransient = isTransient,
|
||||||
if (!isStatic) declareLocalName(name)
|
type = ObjRecord.Type.Delegated,
|
||||||
|
isAbstract = isAbstract,
|
||||||
if (isDelegate) {
|
isClosed = isClosed,
|
||||||
val declaringClassName = declaringClassNameCaptured
|
isOverride = isOverride
|
||||||
if (declaringClassName != null) {
|
)
|
||||||
val storageName = "$declaringClassName::$name"
|
cls.instanceInitializers += object : Statement() {
|
||||||
val isClassScope = context.thisObj is ObjClass && (context.thisObj !is ObjInstance)
|
override val pos: Pos = start
|
||||||
if (isClassScope) {
|
override suspend fun execute(scp: Scope): Obj {
|
||||||
val cls = context.thisObj as ObjClass
|
val initValue = initialExpression!!.execute(scp)
|
||||||
cls.createField(
|
val accessTypeStr = if (isMutable) "Var" else "Val"
|
||||||
name,
|
val accessType = scp.resolveQualifiedIdentifier("DelegateAccess.$accessTypeStr")
|
||||||
ObjUnset,
|
val finalDelegate = try {
|
||||||
isMutable,
|
initValue.invokeInstanceMethod(
|
||||||
visibility,
|
scp,
|
||||||
setterVisibility,
|
"bind",
|
||||||
start,
|
Arguments(ObjString(name), accessType, scp.thisObj)
|
||||||
isTransient = isTransient,
|
)
|
||||||
type = ObjRecord.Type.Delegated,
|
} catch (e: Exception) {
|
||||||
isAbstract = isAbstract,
|
initValue
|
||||||
isClosed = isClosed,
|
}
|
||||||
isOverride = isOverride
|
scp.addItem(
|
||||||
)
|
storageName, isMutable, ObjUnset, visibility, setterVisibility,
|
||||||
cls.instanceInitializers += statement(start) { scp ->
|
recordType = ObjRecord.Type.Delegated,
|
||||||
val initValue = initialExpression!!.execute(scp)
|
isAbstract = isAbstract,
|
||||||
|
isClosed = isClosed,
|
||||||
|
isOverride = isOverride,
|
||||||
|
isTransient = isTransient
|
||||||
|
).apply {
|
||||||
|
delegate = finalDelegate
|
||||||
|
}
|
||||||
|
return ObjVoid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ObjVoid
|
||||||
|
} else {
|
||||||
|
val initValue = initialExpression!!.execute(context)
|
||||||
val accessTypeStr = if (isMutable) "Var" else "Val"
|
val accessTypeStr = if (isMutable) "Var" else "Val"
|
||||||
val accessType = scp.resolveQualifiedIdentifier("DelegateAccess.$accessTypeStr")
|
val accessType = context.resolveQualifiedIdentifier("DelegateAccess.$accessTypeStr")
|
||||||
val finalDelegate = try {
|
val finalDelegate = try {
|
||||||
initValue.invokeInstanceMethod(scp, "bind", Arguments(ObjString(name), accessType, scp.thisObj))
|
initValue.invokeInstanceMethod(
|
||||||
|
context,
|
||||||
|
"bind",
|
||||||
|
Arguments(ObjString(name), accessType, context.thisObj)
|
||||||
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
initValue
|
initValue
|
||||||
}
|
}
|
||||||
scp.addItem(
|
val rec = context.addItem(
|
||||||
storageName, isMutable, ObjUnset, visibility, setterVisibility,
|
storageName, isMutable, ObjUnset, visibility, setterVisibility,
|
||||||
recordType = ObjRecord.Type.Delegated,
|
recordType = ObjRecord.Type.Delegated,
|
||||||
isAbstract = isAbstract,
|
isAbstract = isAbstract,
|
||||||
isClosed = isClosed,
|
isClosed = isClosed,
|
||||||
isOverride = isOverride,
|
isOverride = isOverride,
|
||||||
isTransient = isTransient
|
isTransient = isTransient
|
||||||
).apply {
|
)
|
||||||
delegate = finalDelegate
|
rec.delegate = finalDelegate
|
||||||
}
|
return finalDelegate
|
||||||
ObjVoid
|
|
||||||
}
|
}
|
||||||
return@statement ObjVoid
|
|
||||||
} else {
|
} else {
|
||||||
val initValue = initialExpression!!.execute(context)
|
val initValue = initialExpression!!.execute(context)
|
||||||
val accessTypeStr = if (isMutable) "Var" else "Val"
|
val accessTypeStr = if (isMutable) "Var" else "Val"
|
||||||
val accessType = context.resolveQualifiedIdentifier("DelegateAccess.$accessTypeStr")
|
val accessType = context.resolveQualifiedIdentifier("DelegateAccess.$accessTypeStr")
|
||||||
val finalDelegate = try {
|
val finalDelegate = try {
|
||||||
initValue.invokeInstanceMethod(context, "bind", Arguments(ObjString(name), accessType, context.thisObj))
|
initValue.invokeInstanceMethod(context, "bind", Arguments(ObjString(name), accessType, ObjNull))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
initValue
|
initValue
|
||||||
}
|
}
|
||||||
val rec = context.addItem(
|
val rec = context.addItem(
|
||||||
storageName, isMutable, ObjUnset, visibility, setterVisibility,
|
name, isMutable, ObjUnset, visibility, setterVisibility,
|
||||||
recordType = ObjRecord.Type.Delegated,
|
recordType = ObjRecord.Type.Delegated,
|
||||||
isAbstract = isAbstract,
|
isAbstract = isAbstract,
|
||||||
isClosed = isClosed,
|
isClosed = isClosed,
|
||||||
@ -3562,95 +3613,78 @@ class Compiler(
|
|||||||
isTransient = isTransient
|
isTransient = isTransient
|
||||||
)
|
)
|
||||||
rec.delegate = finalDelegate
|
rec.delegate = finalDelegate
|
||||||
return@statement finalDelegate
|
return finalDelegate
|
||||||
}
|
}
|
||||||
} else {
|
} else if (getter != null || setter != null) {
|
||||||
val initValue = initialExpression!!.execute(context)
|
val declaringClassName = declaringClassNameCaptured!!
|
||||||
val accessTypeStr = if (isMutable) "Var" else "Val"
|
val storageName = "$declaringClassName::$name"
|
||||||
val accessType = context.resolveQualifiedIdentifier("DelegateAccess.$accessTypeStr")
|
val prop = ObjProperty(name, getter, setter)
|
||||||
val finalDelegate = try {
|
|
||||||
initValue.invokeInstanceMethod(context, "bind", Arguments(ObjString(name), accessType, ObjNull))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
initValue
|
|
||||||
}
|
|
||||||
val rec = context.addItem(
|
|
||||||
name, isMutable, ObjUnset, visibility, setterVisibility,
|
|
||||||
recordType = ObjRecord.Type.Delegated,
|
|
||||||
isAbstract = isAbstract,
|
|
||||||
isClosed = isClosed,
|
|
||||||
isOverride = isOverride,
|
|
||||||
isTransient = isTransient
|
|
||||||
)
|
|
||||||
rec.delegate = finalDelegate
|
|
||||||
return@statement finalDelegate
|
|
||||||
}
|
|
||||||
} else if (getter != null || setter != null) {
|
|
||||||
val declaringClassName = declaringClassNameCaptured!!
|
|
||||||
val storageName = "$declaringClassName::$name"
|
|
||||||
val prop = ObjProperty(name, getter, setter)
|
|
||||||
|
|
||||||
// If we are in class scope now (defining instance field), defer initialization to instance time
|
// If we are in class scope now (defining instance field), defer initialization to instance time
|
||||||
val isClassScope = context.thisObj is ObjClass && (context.thisObj !is ObjInstance)
|
val isClassScope = context.thisObj is ObjClass && (context.thisObj !is ObjInstance)
|
||||||
if (isClassScope) {
|
if (isClassScope) {
|
||||||
val cls = context.thisObj as ObjClass
|
val cls = context.thisObj as ObjClass
|
||||||
// Register in class members for reflection/MRO/satisfaction checks
|
// Register in class members for reflection/MRO/satisfaction checks
|
||||||
if (isProperty) {
|
if (isProperty) {
|
||||||
cls.addProperty(
|
cls.addProperty(
|
||||||
name,
|
name,
|
||||||
visibility = visibility,
|
visibility = visibility,
|
||||||
writeVisibility = setterVisibility,
|
writeVisibility = setterVisibility,
|
||||||
isAbstract = isAbstract,
|
|
||||||
isClosed = isClosed,
|
|
||||||
isOverride = isOverride,
|
|
||||||
pos = start,
|
|
||||||
prop = prop
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
cls.createField(
|
|
||||||
name,
|
|
||||||
ObjNull,
|
|
||||||
isMutable = isMutable,
|
|
||||||
visibility = visibility,
|
|
||||||
writeVisibility = setterVisibility,
|
|
||||||
isAbstract = isAbstract,
|
|
||||||
isClosed = isClosed,
|
|
||||||
isOverride = isOverride,
|
|
||||||
isTransient = isTransient,
|
|
||||||
type = ObjRecord.Type.Field
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the property/field initialization thunk
|
|
||||||
if (!isAbstract) {
|
|
||||||
cls.instanceInitializers += statement(start) { scp ->
|
|
||||||
scp.addItem(
|
|
||||||
storageName,
|
|
||||||
isMutable,
|
|
||||||
prop,
|
|
||||||
visibility,
|
|
||||||
setterVisibility,
|
|
||||||
recordType = ObjRecord.Type.Property,
|
|
||||||
isAbstract = isAbstract,
|
isAbstract = isAbstract,
|
||||||
isClosed = isClosed,
|
isClosed = isClosed,
|
||||||
isOverride = isOverride
|
isOverride = isOverride,
|
||||||
|
pos = start,
|
||||||
|
prop = prop
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
cls.createField(
|
||||||
|
name,
|
||||||
|
ObjNull,
|
||||||
|
isMutable = isMutable,
|
||||||
|
visibility = visibility,
|
||||||
|
writeVisibility = setterVisibility,
|
||||||
|
isAbstract = isAbstract,
|
||||||
|
isClosed = isClosed,
|
||||||
|
isOverride = isOverride,
|
||||||
|
isTransient = isTransient,
|
||||||
|
type = ObjRecord.Type.Field
|
||||||
)
|
)
|
||||||
ObjVoid
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register the property/field initialization thunk
|
||||||
|
if (!isAbstract) {
|
||||||
|
cls.instanceInitializers += object : Statement() {
|
||||||
|
override val pos: Pos = start
|
||||||
|
override suspend fun execute(scp: Scope): Obj {
|
||||||
|
scp.addItem(
|
||||||
|
storageName,
|
||||||
|
isMutable,
|
||||||
|
prop,
|
||||||
|
visibility,
|
||||||
|
setterVisibility,
|
||||||
|
recordType = ObjRecord.Type.Property,
|
||||||
|
isAbstract = isAbstract,
|
||||||
|
isClosed = isClosed,
|
||||||
|
isOverride = isOverride
|
||||||
|
)
|
||||||
|
return ObjVoid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ObjVoid
|
||||||
|
} else {
|
||||||
|
// We are in instance scope already: perform initialization immediately
|
||||||
|
context.addItem(
|
||||||
|
storageName, isMutable, prop, visibility, setterVisibility,
|
||||||
|
recordType = ObjRecord.Type.Property,
|
||||||
|
isAbstract = isAbstract,
|
||||||
|
isClosed = isClosed,
|
||||||
|
isOverride = isOverride,
|
||||||
|
isTransient = isTransient
|
||||||
|
)
|
||||||
|
return prop
|
||||||
}
|
}
|
||||||
ObjVoid
|
|
||||||
} else {
|
} else {
|
||||||
// We are in instance scope already: perform initialization immediately
|
|
||||||
context.addItem(
|
|
||||||
storageName, isMutable, prop, visibility, setterVisibility,
|
|
||||||
recordType = ObjRecord.Type.Property,
|
|
||||||
isAbstract = isAbstract,
|
|
||||||
isClosed = isClosed,
|
|
||||||
isOverride = isOverride,
|
|
||||||
isTransient = isTransient
|
|
||||||
)
|
|
||||||
prop
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val isLateInitVal = !isMutable && initialExpression == null
|
val isLateInitVal = !isMutable && initialExpression == null
|
||||||
if (declaringClassName != null && !isStatic) {
|
if (declaringClassName != null && !isStatic) {
|
||||||
val storageName = "$declaringClassName::$name"
|
val storageName = "$declaringClassName::$name"
|
||||||
@ -3675,28 +3709,32 @@ class Compiler(
|
|||||||
|
|
||||||
// Defer: at instance construction, evaluate initializer in instance scope and store under mangled name
|
// Defer: at instance construction, evaluate initializer in instance scope and store under mangled name
|
||||||
if (!isAbstract) {
|
if (!isAbstract) {
|
||||||
val initStmt = statement(start) { scp ->
|
val initStmt = object : Statement() {
|
||||||
val initValue =
|
override val pos: Pos = start
|
||||||
initialExpression?.execute(scp)?.byValueCopy()
|
override suspend fun execute(scp: Scope): Obj {
|
||||||
?: if (isLateInitVal) ObjUnset else ObjNull
|
val initValue =
|
||||||
// Preserve mutability of declaration: do NOT use addOrUpdateItem here, as it creates mutable records
|
initialExpression?.execute(scp)?.byValueCopy()
|
||||||
scp.addItem(
|
?: if (isLateInitVal) ObjUnset else ObjNull
|
||||||
storageName, isMutable, initValue, visibility, setterVisibility,
|
// Preserve mutability of declaration: do NOT use addOrUpdateItem here, as it creates mutable records
|
||||||
recordType = ObjRecord.Type.Field,
|
scp.addItem(
|
||||||
isAbstract = isAbstract,
|
storageName, isMutable, initValue, visibility, setterVisibility,
|
||||||
isClosed = isClosed,
|
recordType = ObjRecord.Type.Field,
|
||||||
isOverride = isOverride,
|
isAbstract = isAbstract,
|
||||||
isTransient = isTransient
|
isClosed = isClosed,
|
||||||
)
|
isOverride = isOverride,
|
||||||
ObjVoid
|
isTransient = isTransient
|
||||||
|
)
|
||||||
|
return ObjVoid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cls.instanceInitializers += initStmt
|
cls.instanceInitializers += initStmt
|
||||||
}
|
}
|
||||||
ObjVoid
|
return ObjVoid
|
||||||
} else {
|
} else {
|
||||||
// We are in instance scope already: perform initialization immediately
|
// We are in instance scope already: perform initialization immediately
|
||||||
val initValue =
|
val initValue =
|
||||||
initialExpression?.execute(context)?.byValueCopy() ?: if (isLateInitVal) ObjUnset else ObjNull
|
initialExpression?.execute(context)?.byValueCopy()
|
||||||
|
?: if (isLateInitVal) ObjUnset else ObjNull
|
||||||
// Preserve mutability of declaration: create record with correct mutability
|
// Preserve mutability of declaration: create record with correct mutability
|
||||||
context.addItem(
|
context.addItem(
|
||||||
storageName, isMutable, initValue, visibility, setterVisibility,
|
storageName, isMutable, initValue, visibility, setterVisibility,
|
||||||
@ -3706,14 +3744,15 @@ class Compiler(
|
|||||||
isOverride = isOverride,
|
isOverride = isOverride,
|
||||||
isTransient = isTransient
|
isTransient = isTransient
|
||||||
)
|
)
|
||||||
initValue
|
return initValue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not in class body: regular local/var declaration
|
// Not in class body: regular local/var declaration
|
||||||
val initValue = initialExpression?.execute(context)?.byValueCopy() ?: ObjNull
|
val initValue = initialExpression?.execute(context)?.byValueCopy() ?: ObjNull
|
||||||
context.addItem(name, isMutable, initValue, visibility, recordType = ObjRecord.Type.Other, isTransient = isTransient)
|
context.addItem(name, isMutable, initValue, visibility, recordType = ObjRecord.Type.Other, isTransient = isTransient)
|
||||||
initValue
|
return initValue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user