/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
package stdx.effect
internal abstract class ImmediateEffectHandlerEarlyExit {}
// This class is used internally when an Exception occurs within an immediate
// handler case
class ImmediateFrameExceptionWrapper <: ImmediateEffectHandlerEarlyExit {
ImmediateFrameExceptionWrapper(let frame: Option<HandlerFrame>, let exception: Exception) {}
}
// This class is used internally when an Error occurs within an immediate
// handler case
class ImmediateFrameErrorWrapper <: ImmediateEffectHandlerEarlyExit {
ImmediateFrameErrorWrapper(let frame: Option<HandlerFrame>, let error: Error) {}
}
// This class is used internally when an immediate handler case finishes
// execution without resuming
//
// Note: there's an issue with generics in Cangjie that don't allow us to
// have the type of result be generic
class ImmediateEarlyReturn <: ImmediateEffectHandlerEarlyExit {
ImmediateEarlyReturn(let frame: Option<HandlerFrame>, let result: Any) {}
}
class ImmediateHandlerCase<Cmd, Res, Ret> <: HandlerCase {
ImmediateHandlerCase(let frame: HandlerFrame, let h: (Cmd) -> ImmediateHandlerReturn<Res>) {}
protected override func tryHandle<R1>(maybeCmd: Command<R1>, box!: FrameBox): Option<R1> {
match (maybeCmd as Cmd) {
case Some(cmd) =>
let oldFrame = box.ref
try {
box.ref = frame.parent
match (this.h(cmd)) {
case Result(v) => v as R1
case Exc(e) => throw e
case Err(e) => throw e
}
} finally {
box.ref = oldFrame
}
case None => None
}
}
}
class ImmediateFrame<Ret> <: HandlerFrame {
public ImmediateFrame(let fn: () -> Ret) {}
public func start(): Ret {
let box = HandlerFrame.getActiveFrameBox()
let previous = box.ref
this.parent = previous
try {
box.ref = this
fn()
} finally {
box.ref = previous
this.finalizer()
}
}
}