feat: M3 단위 1 — Handler 계약 타입(quad-types 소유) + Quad.Dispatch 필드(H-25)
- quad-types: `Handler`(isHandlable/priority/process→retractor 3종) / `Dispatch`(getHandler/process/retractFrom/addHandler/listHandlers/drive + HANDLER_PRIORITY_* 밴드) export type 신설, `Quad`에 `Dispatch` 필드 (H-25 — 닫힌 레코드라 없으면 quad.Dispatch 접근이 analyze 타입에러) - quad-base/src/Dispatch/Handler.luau: 타입 전용 잎(§6 계획) — quad-types 재export만, Dispatch 되참조 없음(단방향 의존) - H-165 예고대로 pesde shim 재생성 필요했음 — `pesde install` 재실행으로 해소 Co-authored-by: qwreey <me@qwreey.moe> Claude-Session: https://claude.ai/code/session_01LF78pXeFGD1ZSVD3ifteYG
This commit is contained in:
parent
f14ba09cd6
commit
590b0fe6a1
3 changed files with 64 additions and 0 deletions
30
quad-base/src/Dispatch/Handler.luau
Normal file
30
quad-base/src/Dispatch/Handler.luau
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
--[[
|
||||||
|
Handler — the handler contract, types only. `.claude/base/dispatch-core-plan.md`
|
||||||
|
"핸들러 계약" section, as-is:
|
||||||
|
|
||||||
|
isHandlable(inst, key, value) -> boolean -- pure, fast predicate (no side
|
||||||
|
-- effects; validation happens
|
||||||
|
-- *after* selection, inside process)
|
||||||
|
priority: number -- open numeric space; use the
|
||||||
|
-- HANDLER_PRIORITY_* band constants
|
||||||
|
-- (`Dispatch/init.luau`) ± offsets
|
||||||
|
process(inst, key, value, index) -> retractor
|
||||||
|
-- does the work and returns the 1-arg closure that undoes exactly what
|
||||||
|
-- this call did. Returning nil is a contract violation (Dispatch errors
|
||||||
|
-- immediately); return `Void` when there is nothing to undo (`H-162`).
|
||||||
|
-- The retractor's argument is either nil (plain retract) or a new value
|
||||||
|
-- this same handler is about to process — nothing else can arrive
|
||||||
|
-- (descending diff, "Dispatch 체인" section).
|
||||||
|
|
||||||
|
This file is a leaf on purpose: concrete handlers and `Dispatch/init.luau`
|
||||||
|
both depend on it, never the other way around ("Dispatch는 프리미티브가
|
||||||
|
아니다" — the dependency is one-way). The type itself is owned by
|
||||||
|
`quad-types` (so `Quad.Dispatch.addHandler` and backends share it) and only
|
||||||
|
re-exported here.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local QuadTypes = require("../../roblox_packages/quad_types")
|
||||||
|
|
||||||
|
export type Handler = QuadTypes.Handler
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
@ -126,6 +126,35 @@ export type Source<T> = State<T> & {
|
||||||
Emit: (self: Source<T>) -> Source<T>,
|
Emit: (self: Source<T>) -> Source<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- ── 디스패치 엔진(M3 단위 1) ──────────────────────────────────────────
|
||||||
|
-- `Handler` — 핸들러 계약 **3종**(`.claude/base/dispatch-core-plan.md` "핸들러
|
||||||
|
-- 계약"): `isHandlable`은 부작용 없는 순수 판별(inst도 받음), `process`는 자기
|
||||||
|
-- 자신을 무르는 1-인자 retractor를 반환(생략 불가 — 정리할 게 없어도 `Void`).
|
||||||
|
-- retractor 인자는 `nil`(단순 철거)이거나 같은 핸들러가 처리할 새 값, 둘뿐.
|
||||||
|
export type Handler = {
|
||||||
|
isHandlable: (inst: any, key: any, value: any) -> boolean,
|
||||||
|
priority: number,
|
||||||
|
process: (inst: any, key: any, value: any, index: number) -> (nextValue: any?) -> (),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- `Dispatch` — 스캔/실행 엔진(`dispatch-core-plan.md` "Dispatch 체인" /
|
||||||
|
-- "우선순위 동률/매치 실패 처리"). 프리미티브가 아니라 모듈 인스턴스별
|
||||||
|
-- 네임스페이스(`InitDispatch(module)`가 설치, 멤버는 lowercase 네임스페이스
|
||||||
|
-- 규칙 — `architecture.md` "코드 스타일"). `HANDLER_PRIORITY_*`는 열린 숫자
|
||||||
|
-- 공간 위의 밴드 상수(`+ 1` 미세 조정 가능).
|
||||||
|
export type Dispatch = {
|
||||||
|
getHandler: (inst: any, key: any, value: any) -> Handler?,
|
||||||
|
process: (inst: any, key: any, value: any, index: number) -> (),
|
||||||
|
retractFrom: (inst: any, key: any, index: number) -> (),
|
||||||
|
addHandler: (handler: Handler) -> (),
|
||||||
|
listHandlers: () -> { Handler },
|
||||||
|
drive: (inst: any, flattened: { [any]: any }) -> (),
|
||||||
|
HANDLER_PRIORITY_HIGH: number,
|
||||||
|
HANDLER_PRIORITY_NORMAL: number,
|
||||||
|
HANDLER_PRIORITY_LOW: number,
|
||||||
|
HANDLER_PRIORITY_FALLBACK: number,
|
||||||
|
}
|
||||||
|
|
||||||
-- 예약 키 진단 — `keyof<T>`(키 싱글톤 유니온)만 받는다(`H-112`). `error()`는 못 쓴다
|
-- 예약 키 진단 — `keyof<T>`(키 싱글톤 유니온)만 받는다(`H-112`). `error()`는 못 쓴다
|
||||||
-- (타입 함수 자체가 실패로 판정) — `print` + `types.never`. 목록은 quad-base
|
-- (타입 함수 자체가 실패로 판정) — `print` + `types.never`. 목록은 quad-base
|
||||||
-- `Store.luau`의 `RESERVED` 테이블의 사본이라 이름을 바꿀 땐 둘을 같이.
|
-- `Store.luau`의 `RESERVED` 테이블의 사본이라 이름을 바꿀 땐 둘을 같이.
|
||||||
|
|
@ -171,6 +200,11 @@ export type Quad = {
|
||||||
-- 단위 4.
|
-- 단위 4.
|
||||||
Blocker: () -> Blocker,
|
Blocker: () -> Blocker,
|
||||||
|
|
||||||
|
-- 디스패치 엔진(M3 단위 1, `H-25` — 마일스톤마다 서브시스템 필드를 여기
|
||||||
|
-- 같이 갱신하는 규칙의 M3 몫). 닫힌 레코드라 이 필드가 없으면
|
||||||
|
-- `quad.Dispatch` 접근이 런타임엔 되는데 `luau-analyze`에선 타입에러다.
|
||||||
|
Dispatch: Dispatch,
|
||||||
|
|
||||||
-- 생명주기 4종 — quad-base는 인터페이스(에러 스텁)만, 백엔드가 주입
|
-- 생명주기 4종 — quad-base는 인터페이스(에러 스텁)만, 백엔드가 주입
|
||||||
-- (`.claude/base/lifecycle-pattern.md`). `canBound(v) == not canExecute(v)`.
|
-- (`.claude/base/lifecycle-pattern.md`). `canBound(v) == not canExecute(v)`.
|
||||||
bindLifetime: (inst: any, value: any) -> (),
|
bindLifetime: (inst: any, value: any) -> (),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue