GEUL 流是以 Meta Node 开始和结束的数据包序列,构成一个完整的 GEUL 文档。

核心特征

  • 边界明示: STREAM_START / STREAM_END (Meta Node)
  • TID 作用域: 仅在流内有效
  • 前向引用: 只能引用已声明的 TID
  • Big Endian: Network Byte Order

流结构

┌─────────────────────────────────────┐
│          STREAM_START               │  ← 必需 (Meta Node)
│          (TID 宽度声明)              │     0xC000 (16位 TID)
├─────────────────────────────────────┤
│          元数据 (可选)               │
│          - VERSION    (0xC014)      │
│          - CREATED_AT (0xC008)      │
│          - CREATOR    (0xC010)      │
├─────────────────────────────────────┤
│          正文数据包                   │
│          - Entity Node              │
│          - Quantity Node            │
│          - Verb Edge                │
│          - Triple Edge              │
│          - Event6 Edge              │
│          - Clause Edge              │
│          - Context Edge             │
│          - Group Edge               │
│          - Faber Edge               │
├─────────────────────────────────────┤
│          STREAM_END                 │  ← 可选(建议)
└─────────────────────────────────────┘

最小流为 STREAM_START(1字)+ STREAM_END(1字)= 2字(4字节),空流也是有效的。

TID 分配原则

规则说明
必要性流内所有 Edge/Node 都拥有 TID
唯一性流内 TID 唯一
作用域TID 仅在该流内有效
前向引用时只能引用已声明的 TID

TID 位置

类型TID 位置引用位置
Meta Node
Entity Node最后一个字
Quantity Node最后一个字
Tiny Verb Edge无(内联)
Verb EdgeHeader 区域Payload 之后
Triple EdgeHeader 区域Payload 之后
Event6 EdgeHeader 区域Payload 之后
Clause EdgeHeader 区域Payload 之后
Context EdgeHeader 区域Payload 之后
Group Edge第2字第3+字

Node 仅定义自身所以 TID 在末尾,Edge 引用其他 TID 所以 TID 在引用之前。

保留 TID

TID用途
0x0000终止标记分组边等)
0xFFFF保留(16位标准)

数据包顺序规则

声明-引用顺序

正确:
  [Entity: 小明, TID=0x0001]
  [Entity: 小红, TID=0x0002]
  [Verb Edge: 见面, Subject=0x0001, Object=0x0002]

错误:
  [Verb Edge: 见面, Subject=0x0001, Object=0x0002]  ← 0x0001 未声明
  [Entity: 小明, TID=0x0001]
  [Entity: 小红, TID=0x0002]

建议顺序

1. STREAM_START
2. 元数据 (VERSION, CREATED_AT, CREATOR)
3. Entity Node (实体声明)
4. Quantity Node (数量/字面量)
5. Group Edge (分组定义)
6. Tiny Verb Edge (内联谓述)
7. Verb Edge (一般谓述)
8. Triple Edge (属性/关系)
9. Event6 Edge (事件)
10. Clause Edge (篇章关系)
11. Context Edge (语境)
12. Faber Edge (代码/AST)
13. STREAM_END

这仅是建议顺序,只要遵守声明-引用规则即可自由排列。

禁止循环引用

A → B → A 形式的循环引用不允许。如需循环关系则用单独的 Edge 表达。

可以:
  [Entity A, TID=0x0001]
  [Entity B, TID=0x0002]
  [Edge: A→B, TID=0x0003]
  [Edge: B→A, TID=0x0004]

流示例

“小明见了小红”

1. STREAM_START (TID 16位)
   0xC0 0x00

2. Entity: 小明 (TID=0x0001)
   [Entity 数据包...] 0x00 0x01

3. Entity: 小红 (TID=0x0002)
   [Entity 数据包...] 0x00 0x02

4. Verb Edge: meet (TID=0x0100)
   Subject: 0x0001
   Object: 0x0002

5. STREAM_END
   0xC0 0x04

“小明和小红在学校见面了”

1. STREAM_START
   0xC0 0x00

2. Entity: 小明 (TID=0x0001)
3. Entity: 小红 (TID=0x0002)
4. Entity: 学校 (TID=0x0003)

5. Group Edge: AND (TID=0x0010)
   成员: 0x0001, 0x0002, 0x0000 (终止)

6. Verb Edge: meet (TID=0x0100)
   Subject: 0x0010 (分组)
   Location: 0x0003

7. STREAM_END
   0xC0 0x04

流验证

必须验证

项目验证
起始是否以 STREAM_START 开始?
TID 唯一性是否存在重复 TID?
引用有效性引用的 TID 是否全部已声明?
前向性引用时 TID 是否已声明?

验证代码

def validate_stream(packets: list) -> dict:
    """流有效性验证"""
    errors = []
    declared_tids = set()

    # 起始验证
    if not packets or packets[0].type != "STREAM_START":
        errors.append("流未以 STREAM_START 开始")

    for packet in packets:
        # TID 唯一性验证
        if packet.tid is not None:
            if packet.tid in declared_tids:
                errors.append(f"重复 TID: {packet.tid}")
            declared_tids.add(packet.tid)

        # 引用有效性验证
        for ref_tid in packet.references:
            if ref_tid not in declared_tids:
                errors.append(f"引用未声明 TID: {ref_tid}")

    return {
        "valid": len(errors) == 0,
        "errors": errors,
        "tid_count": len(declared_tids)
    }

多流

各流独立,TID 作用域按流分离。Stream A 的 TID=0x0001 与 Stream B 的 TID=0x0001 是不同实体。

流间引用(Cross-reference)目前不支持,未来可通过引入流 ID 和 Import/Export 机制进行扩展。