2026-04-01 21:44:20 +08:00
|
|
|
|
import {Context} from "./context";
|
2026-04-01 13:36:16 +08:00
|
|
|
|
import {Command} from "../utils/command";
|
|
|
|
|
|
import {effect} from "@preact/signals-core";
|
|
|
|
|
|
|
|
|
|
|
|
export type RuleContext<T> = Context & {
|
|
|
|
|
|
actions: Command[];
|
|
|
|
|
|
handledActions: number;
|
|
|
|
|
|
invocations: RuleContext<unknown>[];
|
|
|
|
|
|
resolution?: T;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-01 17:34:21 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 调用规则生成器并管理其上下文
|
|
|
|
|
|
* @param pushContext - 用于推送上下文到上下文栈的函数
|
|
|
|
|
|
* @param type - 规则类型
|
|
|
|
|
|
* @param rule - 规则生成器函数
|
|
|
|
|
|
* @returns 规则执行结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function invokeRuleContext<T>(
|
2026-04-01 21:44:20 +08:00
|
|
|
|
pushContext: (context: Context) => void,
|
|
|
|
|
|
type: string,
|
2026-04-01 17:34:21 +08:00
|
|
|
|
rule: Generator<string, T, Command>
|
|
|
|
|
|
): RuleContext<T> {
|
2026-04-01 13:36:16 +08:00
|
|
|
|
const ctx: RuleContext<T> = {
|
|
|
|
|
|
type,
|
|
|
|
|
|
actions: [],
|
|
|
|
|
|
handledActions: 0,
|
|
|
|
|
|
invocations: [],
|
|
|
|
|
|
resolution: undefined,
|
2026-04-01 17:34:21 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-01 21:44:20 +08:00
|
|
|
|
let disposed = false;
|
|
|
|
|
|
|
2026-04-01 17:34:21 +08:00
|
|
|
|
const executeRule = () => {
|
2026-04-01 21:44:20 +08:00
|
|
|
|
if (disposed || ctx.resolution !== undefined) return;
|
|
|
|
|
|
|
2026-04-01 17:34:21 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const result = rule.next();
|
2026-04-01 21:44:20 +08:00
|
|
|
|
|
2026-04-01 17:34:21 +08:00
|
|
|
|
if (result.done) {
|
|
|
|
|
|
ctx.resolution = result.value;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const actionType = result.value;
|
2026-04-01 21:44:20 +08:00
|
|
|
|
|
|
|
|
|
|
if (actionType) {
|
|
|
|
|
|
// 暂停于 yield 点,等待外部处理动作
|
|
|
|
|
|
// 当外部更新 actions 后,effect 会重新触发
|
2026-04-01 17:34:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-01 13:36:16 +08:00
|
|
|
|
const dispose = effect(() => {
|
2026-04-01 17:34:21 +08:00
|
|
|
|
if (ctx.resolution !== undefined) {
|
2026-04-01 13:36:16 +08:00
|
|
|
|
dispose();
|
2026-04-01 21:44:20 +08:00
|
|
|
|
disposed = true;
|
2026-04-01 13:36:16 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-04-01 17:34:21 +08:00
|
|
|
|
executeRule();
|
2026-04-01 13:36:16 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-01 17:34:21 +08:00
|
|
|
|
pushContext(ctx);
|
|
|
|
|
|
|
|
|
|
|
|
return ctx;
|
2026-04-01 13:36:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-01 17:34:21 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 创建一个规则生成器辅助函数
|
|
|
|
|
|
* @param type - 规则类型
|
|
|
|
|
|
* @param fn - 规则逻辑函数
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function createRule<T>(
|
|
|
|
|
|
type: string,
|
|
|
|
|
|
fn: (ctx: RuleContext<T>) => Generator<string, T, Command>
|
2026-04-01 21:44:20 +08:00
|
|
|
|
): (ctx: RuleContext<T>) => Generator<string, T, Command> {
|
|
|
|
|
|
return fn;
|
2026-04-01 17:34:21 +08:00
|
|
|
|
}
|