ΓDocsInteractiveNet

Ainet 语法 v0.1(draft)

权威语法以本文件为准;docs/05-ainet-language.md 的示例必须能通过这里的解析器。 采用 EBNF;{ x } 表示 0+,[ x ] 表示可选,| 表示选择。

1. 词法

program     ::= { item } EOF ;

item        ::= importDecl | typeDecl | effectDecl | agentDecl | ruleDecl | flowDecl ;

importDecl  ::= "import" string ";" ;

ident       ::= /[A-Za-z_][A-Za-z0-9_]*/ ;
string      ::= '"' { /[^"\\]/ | escape } '"' ;
number      ::= /-?[0-9]+(\.[0-9]+)?/ ;
duration    ::= number ("ms" | "s" | "m" | "h" | "d") ;
money       ::= number ;              // 单位:USD;精度 1e-6
comment     ::= "//" { /[^\n]/ } | "/*" { /[\s\S]/ } "*/" ;

关键字:import type effect agent rule flow input output budget stage par race join branch supervise with timeout as state send recv end rec choice offer rec let in if else true false null。

保留但暂未使用:module export match case for while return async await move new drop.

2. 类型

type        ::= unionType ;
unionType   ::= productType { "|" productType } ;
productType ::= primaryType { "*" primaryType } ;
primaryType ::= ident [ "<" type { "," type } ">" ]
              | "{" [ field { "," field } ] "}"
              | "[" type "]"
              | "(" type { "," type } ")"
              | "!" type
              | "?" type
              | "session" "{" sessionItem { ";" sessionItem } [ ";" ] "}"
              | "(" ")" ;

field       ::= ident ":" type ;

sessionItem ::= "send" type
              | "recv" type
              | "end"
              | "rec" ident "." sessionItem
              | "choice" "{" variant { "|" variant } "}"
              | "offer" "{" variant { "|" variant } "}" ;

variant     ::= ident [ "(" type { "," type } ")" ] ;

说明:

  • !T / ?T 是端口方向;session { ... } 是协议糖。
  • List<T>、Result<T, E>、Option<T> 是内建泛型(stdlib 提供)。
  • 类型别名:type Task = { id: Text, prompt: Text };
  • 递归类型通过 session/List 表达;v1 不支持任意递归 ADT(后续)。

3. Effect

effectDecl ::= "effect" ident "{" "input" type "output" type "}" ;

示例:

effect LLM {
  input  { model: Text, prompt: Text, max_tokens: Nat }
  output { text: Text, tokens: Nat, usd: Float }
}

4. Agent

agentDecl  ::= "agent" ident
               [ "<" ident ">" ]
               [ "effects" "{" [ ident { "," ident } ] "}" ]
               [ "budget" "{" [ budgetField { "," budgetField } ] "}" ]
               "{" { portDecl } [ stateDecl ] "}" ;

portDecl   ::= ident ":" portType ";" ;
portType   ::= ("!" | "?") type ;

stateDecl  ::= "state" variant { "|" variant } ;
variant    ::= ident [ "{" [ field { "," field } ] "}" ] ;

budgetField ::= ident ":" ( number | duration | money ) ;

示例:

agent Researcher {
  ports { inbox: ?Message; out: !Draft; llm: !LLM; search: !Search }
  state Idle | Searching { prompt: Text } | Done
}

ports { ... } 与直接写 portDecl* 等价;前者可读性更好。

5. 规则

ruleDecl   ::= "rule" pattern "<>" pattern "=>" net ";" ;

pattern    ::= ident [ "[" statePattern "]" ] "(" [ ident { "," ident } ] ")" ;
statePattern ::= ident [ "{" [ ident { "," ident } ] "}" ] | "_" ;

net        ::= cell { "|" cell } ;
cell       ::= ident [ "[" statePattern "]" ] "(" [ arg { "," arg } ] ")" ;
arg        ::= [ ident ":" ] expr ;

expr       ::= literal | ident | call | object | list | expr "." ident ;
call       ::= ident [ "." ident ] "(" [ arg { "," arg } ] ")" ;
object     ::= "{" [ field { "," field } ] "}" ;
list       ::= "[" [ expr { "," expr } ] "]" ;
literal    ::= string | number | "true" | "false" | "null" ;

约定:

  • LHS 两个 pattern 的 principal 端口相连;RHS 的 free ports 必须与 LHS 的 aux 端口一一对应。
  • Send(port, value) 是内建 cell;把 value 送到 port。
  • EffectCall(cap, op, input, reply) 是内建 cell;cap 是能力端口。
  • 变量绑定:pattern 中的 ident 绑定到消息字段;state 的 { field } 绑定状态字段。

6. Flow

flowDecl   ::= "flow" ident "{" { flowItem } "}" ;

flowItem   ::= "input" ident ":" type
             | "output" ident ":" type
             | "budget" "{" [ budgetField { "," budgetField } ] "}"
             | "agent" ident "=" call
             | "stage" ident "=" call
             | "par" "{" { branch } "}" "->" "join" "{" ident { "," ident } "}" [ "as" ident ]
             | "race" "{" { call } "}" "->" ident
             | "supervise" ident "{" { flowItem } "}"
             | "with" "timeout" "(" duration ")" "{" { flowItem } "}"
             | "if" expr "{" { flowItem } "}" [ "else" "{" { flowItem } "}" ]
             | portChain ;

branch     ::= "branch" ident "=" call ;
portChain  ::= ident "->" ident { "->" ident } ;

说明:

  • stage 是 let + 连接的糖;-> 表示把左侧输出接到右侧输入。
  • par/race/supervise/timeout 都是 lowering 到 AIN 的语法糖;语义见 docs/05 与 specs/ain-sync.md。
  • if 条件必须是 Bool;两个分支都必须产出相同的输出类型。

7. 模块与包

// ainet.toml(不是 .ain 语法)
[package]
name = "..."
version = "..."
edition = "2026"

[dependencies]
ainet-std = "0.1"

.ain 文件内:

import "std/llm";
import "./agents/researcher";

v1 只支持相对路径与 stdlib;registry 在 v2。

8. 语义检查清单(编译器必须实现)

  1. 名称解析:类型/agent/effect/flow/变量。
  2. 线性:每个端口恰好消费一次。
  3. Session 对偶:发送/接收匹配;end 对齐。
  4. Effect row:调用的 effect 已声明;handler 覆盖。
  5. 预算:每个 effect 调用有预算来源(或显式 unbounded)。
  6. 状态覆盖:每个 (state, message) 组合有规则,或有默认 Error<Unhandled>。
  7. 规则接口:RHS free ports 与 LHS aux 类型/顺序一致。
  8. 死锁(保守):Join/Select/Barrier 无明显环等待。
  9. 端口类型:方向/类型一致;不能把 !T 接到 !T(需要 ?T 对偶)。
  10. 布局:每个 wire 两个端点;free port 不与 wire 冲突。

9. 兼容性

  • 语法版本随 edition;v1 接受 edition = "2026"。
  • 新增关键字属于破坏性变更;用 @ident 或 r#ident 转义。
  • 格式化器(ain fmt)在 M2 提供;解析器必须保留注释/位置用于诊断。

在 GitHub 编辑本文