docs: establish Endorphin language documentation baseline

This commit is contained in:
2026-10-07 22:04:09 +08:00
commit a33f80903c
20 changed files with 1344 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
# Local editor state and machine-specific files
.obsidian/
.DS_Store
# Credentials and local environment files must not be published
.env
.env.*
!.env.example
*.pem
*.key
+33
View File
@@ -0,0 +1,33 @@
# 文档维护约定
适用于本目录及所有子目录。
## 文档组织
- 正文放在 guide,按概念依赖顺序编号;术语、文法、设计状态和补充说明放在 appendices。
- README 作为读者入口,提供顺序目录与查询索引,不用核心约定清单替代语言介绍。
- 每章先定义概念,再说明语法、示例和行为。内容应在未阅读讨论历史的情况下独立成立。
- 使用技术文档陈述句,不使用对话回应、提问清单、讨论过程或开发日志作为正文。
- 不在各章重复说明全书目标、全部约束和设计过程;未定规则集中维护在规范状态附录,必要的局部提案保留短注。
- 每个概念指定主要说明章节,其余章节使用引用;完整 EBNF 集中在形式文法附录。
- 修改章节位置时同步更新目录、相邻导航、术语索引、正文链接与文法。外部读者正文使用中文。
## 语言边界
- 只使用语言名称 Endorphin,不出现开发软件代称、版本或实现兼容说明。
- 文档定义源码与可观察效果,不以开发实现进度定义语言规则。
- 构建阶段固定为 Preflight,运行阶段固定为 inflight,保持大小写;定义见 guide/05-preflight-and-inflight.md。
- 两个阶段名称不自动成为源码关键字。新增语法说明必要的 Preflight 检查和 inflight 效果。
- 不设计云端实体、持久化类或自动建表。数据读取只是逻辑调用用法,不引入通信、缓存、部署与编排方案。
- 普通调用不要求业务代码额外定义 RPC 服务、监听器、协议客户端或接口描述文件。
## 示例与状态
- key 采用用户名:namespace路径,用户名唯一,路径至少一级;各层 namespace 语义一致。
- 归属通过外部 key 与索引提供,正文不声明自身 namespace。
- use 只引用完整 key,不附加选择性名称列表。
- 官方 UI 组件不列为示例用户库的内容;未定的官方引用方式不可写成免导入默认能力。
- 示例围绕商品定价展开,标明外部归属与片段位置;局部片段不能混写为完整程序。
- 名称查找、可见性和数据读取成员的假设明确说明,不虚构未确认 API。
- 已确定约定、语法提案和未定义边界统一记录在 appendices/specification-status.md;文档重构不代表语法提案被确认。
- 共用程序和表达式文法;UI 单根限制仅约束 render,不限制全语言。
+48
View File
@@ -0,0 +1,48 @@
# Endorphin 语言文档
Endorphin 是一门面向云原生应用的编程语言,使用统一的语言模型描述前端界面、数据结构和后端业务逻辑。开发者编写声明、表达式与调用关系,系统负责组织这些逻辑的执行。
## 阅读指南
正文按概念的依赖顺序编排。首次阅读从第 1 章开始;查询具体写法时,可以直接进入相应章节。每章包含概念定义、语法、示例和行为说明。
本书为语言设计稿。用户身份、namespace key、use 形式和阶段命名等基础约定已经确定;函数、类型、数据读取与 UI 的具体写法以本文收录的草案为准。各主题的确定程度统一记录在[规范状态](appendices/specification-status.md),正文不反复叙述设计过程。
## 正文
### 第一部分:语言与程序模型
1. [语言概览](guide/01-overview.md) — 语言用途、核心概念与应用模型。
2. [用户身份](guide/02-user-identity.md) — 唯一用户名、显示名、代码归属与访问身份。
3. [namespace](guide/03-namespaces.md) — key、层级和可见代码视图。
4. [程序结构与导入](guide/04-program-structure.md) — 声明组织、外部上下文和 use。
5. [Preflight 与 inflight](guide/05-preflight-and-inflight.md) — 构建与执行阶段的职责。
### 第二部分:基础语法
6. [词法结构](guide/06-lexical-structure.md) — 标识符、字面量、符号、标点和注释。
7. [类型与类](guide/07-types-and-classes.md) — 类型标注、class 与字段。
8. [表达式与绑定](guide/08-expressions-and-bindings.md) — 求值、运算、成员访问和 let。
9. [函数与调用](guide/09-functions-and-calls.md) — 函数声明、返回值和跨 namespace 组合。
### 第三部分:应用用法
10. [数据读取](guide/10-data-access.md) — 通过类型取得数据及结果状态。
11. [场景与渲染树](guide/11-scenes-and-render-trees.md) — scene、render、节点与嵌套。
12. [UI 组件](guide/12-ui-components.md) — Column、Row、Spacer 和 Text 的参数与效果。
## 附录
- [术语表](appendices/glossary.md) — 语言术语的简要定义与章节索引。
- [形式文法](appendices/formal-grammar.md) — 集中查询 EBNF 产生式。
- [代码存储与视图](appendices/code-storage-and-views.md) — 独立代码段、S3 与索引的组织约定。
- [应用领域](appendices/application-domains.md) — UI、业务逻辑、数据访问和 Agent 的适用范围。
- [规范状态](appendices/specification-status.md) — 已确定约定、语法提案及未定义的边界。
## 记法
源码以 `endorphin` 代码块展示,文法以 `ebnf` 代码块展示。源码中的关键字和名称区分大小写;语言阶段名称固定为 `Preflight` 和 `inflight`。
“代码归属”写在代码块之前,用于说明外部上下文,不属于源码。函数体片段和渲染节点片段会注明使用位置。示例中的用户和 namespace 为示意名称。
正文的函数示例围绕商品定价展开:`alice:shop.pricing` 提供定价逻辑,`bob:shop.checkout` 组合它,`bob:shop.ui` 表达界面;数据读取示例使用 `alice:shop.data`。这些路径表示代码组织,不指定执行位置。
+30
View File
@@ -0,0 +1,30 @@
# 应用领域
各应用领域共用身份、namespace、类型、表达式、调用以及 Preflight / inflight 阶段模型。领域划分用于说明用途,不为每个领域建立不同的语言基础。
| 领域 | 语言中的内容 | 参考章节 |
| --- | --- | --- |
| UI | 场景、渲染树、组件及展示效果 | [场景与渲染树](../guide/11-scenes-and-render-trees.md)、[UI 组件](../guide/12-ui-components.md) |
| 业务逻辑 | 函数、结果、调用组合及业务效果 | [函数与调用](../guide/09-functions-and-calls.md) |
| 数据结构与访问 | class、共享类型、读取与字段使用 | [类型与类](../guide/07-types-and-classes.md)、[数据读取](../guide/10-data-access.md) |
| Agent | 后续的能力、上下文、任务及行为模型 | [规范状态](specification-status.md#agent) |
## 跨领域调用
普通调用是共有语义。UI、业务逻辑或后续 Agent 代码可以在允许访问的前提下使用相应逻辑,而不为跨领域调用建立独立的 RPC 协议声明。
类似 RPC 的体验指“调用逻辑并取得结果”。输入、输出、依赖和失败需要在语言中明确,传输客户端、连接方式和缓存由系统承担。
## 领域与 namespace
`alice:shop.ui`、`alice:shop.pricing`、`alice:shop.data` 和 `alice:shop.agents` 是组织示例,不是强制目录或具有特殊行为的保留路径。
namespace 的名称不自动决定逻辑在何处执行。一个 namespace 也不必只包含一种声明类别。
## Agent 范围
Agent 尚无具体源码语法。需要独立定义的内容包括能力、工具、上下文、任务、生命周期、权限,以及确定性代码和模型驱动行为的边界。
本书不为尚未定义的领域提供虚构关键字或 API;其扩展仍应共用语言已有的组织与调用模型。
[目录](../README.md)
+38
View File
@@ -0,0 +1,38 @@
# 代码存储与视图
本附录说明无源码文件模型中的代码组织约定。它补充 namespace 的逻辑视图,不定义业务数据的存储方式。
## 独立代码段
代码分别存储为独立代码段,每段关联一个唯一用户和至少一级 namespace。S3 承担代码内容的存储职责,索引维护 namespace key 与代码段的成员关系。
源码文件不作为代码身份或 module 边界。本书中的 Markdown 文件是文档章节,不对应语言中的源码组织单位。
代码段的具体语法粒度尚未定义,不能将一个场景、一条声明或一个 S3 对象直接规定为同一种单位。
## 索引与视图
```text
完整 namespace key
→ 索引中的成员关系
→ S3 中的独立代码段
→ namespace 的可见代码视图
```
视图是逻辑上的代码集合。它的归属来自 key 与索引,不由对象名或物理目录确定。
S3 对象键不是语言中的 namespace key。bucket 名、对象键和存储接口不属于业务源码语法。
## 视图与程序结构
程序结构描述视图内导入与声明的语法关系,见[程序结构与导入](../guide/04-program-structure.md)。这一结构不要求将物理对象按文件顺序机械拼接。
视图成员范围、下级 namespace 是否纳入、导入作用范围、声明顺序、版本一致性与编辑映射尚未定义,统一记录在[规范状态](specification-status.md#引用与代码视图)。
## namespace 制
namespace 同时表达归属与查找位置,使业务函数、类型、场景和后续 Agent 代码遵循一致的组织模型。第一级与后续层级具有相同语义。
这一组织选择不自动决定构建边界、执行位置、权限继承或业务数据存储。相关语义需要由各自规则定义,而不是从 S3 物理布局推导。
[相关章节:namespace](../guide/03-namespaces.md) · [目录](../README.md)
+124
View File
@@ -0,0 +1,124 @@
# 形式文法
本附录集中列出正文采用的文法草案。文法说明可表达的源码结构;名称、类型、可见性与执行效果由相应章节定义。各主题的确定程度见[规范状态](specification-status.md)。
## EBNF 记法
| 记法 | 含义 |
| --- | --- |
| `=` | 定义产生式 |
| `;` | 结束产生式 |
| `|` | 选择 |
| `,` | 顺序连接 |
| `[ ... ]` | 可选项 |
| `{ ... }` | 零次或多次重复 |
| `( ... )` | 产生式分组 |
| 引号中的文本 | 源码终结符 |
产生式中的逗号和分号属于 EBNF 记法,不要求源码在相同位置包含分隔符。任意词法单元之间可出现空白或行注释。EOF 表示输入结束。
## 程序与导入
```ebnf
program = { use-decl }, declaration, { declaration }, EOF ;
declaration = class-decl | function-decl | scene-decl ;
use-decl = "use", namespace-key ;
namespace-key = user-handle, ":", namespace-path ;
namespace-path = identifier, { ".", identifier } ;
```
user-handle 是系统认可的唯一用户名,由身份规则提供,不等同于源码 identifier。代码自身的归属通过外部上下文提供,程序文法中没有自身 namespace 声明。
相关说明:[namespace](../guide/03-namespaces.md)、[程序结构与导入](../guide/04-program-structure.md)。
## 类与类型
```ebnf
class-decl = "class", identifier, "{", { field-decl }, "}" ;
field-decl = identifier, ":", type-name ;
type-name = identifier ;
```
相关说明:[类型与类](../guide/07-types-and-classes.md)。
## 函数与绑定
```ebnf
function-decl = "function", identifier, "(", [ parameters ], ")",
":", type-name, block ;
parameters = parameter, { ",", parameter } ;
parameter = identifier, ":", type-name ;
block = "{", { binding }, return-stmt, "}" ;
binding = "let", identifier, "=", expression ;
return-stmt = "return", expression ;
```
本基本函数体文法只包含绑定和末尾返回,不覆盖完整控制流或独立表达式语句。
相关说明:[表达式与绑定](../guide/08-expressions-and-bindings.md)、[函数与调用](../guide/09-functions-and-calls.md)。
## 表达式
```ebnf
expression = sum ;
sum = product, { ("+" | "-"), product } ;
product = unary, { ("*" | "/"), unary } ;
unary = "-", unary | postfix ;
postfix = primary, { member-access | call-arguments } ;
member-access = ".", identifier ;
call-arguments = "(", [ expression-list ], ")" ;
expression-list = expression, { ",", expression } ;
primary = identifier | string | number | symbol
| "(", expression, ")" ;
```
成员访问与调用先于一元负号,一元负号先于乘除,乘除先于加减。正文采用同级二元算术运算从左到右组合的规则。
此处能表达成员调用,不代表某个类型自动拥有相应成员。数据读取提案使用同一套表达式文法,没有单独的 get 关键字。
相关说明:[表达式与绑定](../guide/08-expressions-and-bindings.md)、[数据读取](../guide/10-data-access.md)。
## 场景与渲染节点
```ebnf
scene-decl = "export", "scene", identifier, "{", render-decl, "}" ;
render-decl = "render", "{", node, "}" ;
node = identifier, [ arguments ], [ children ] ;
arguments = "(", [ argument, { ",", argument } ], ")" ;
argument = [ identifier, ":" ], expression ;
children = "{", { node }, "}" ;
```
render 内单根结构由产生式表达。组件是否接受子节点、参数是否合法以及 render 内可使用哪些表达式效果,属于语义规则。
相关说明:[场景与渲染树](../guide/11-scenes-and-render-trees.md)、[UI 组件](../guide/12-ui-components.md)。
## 词法
```ebnf
identifier = identifier-start, { identifier-continue } ;
identifier-start = "_" | unicode-letter ;
identifier-continue = "_" | unicode-letter | unicode-number ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
number = digit, { digit }, [ ".", digit, { digit } ] ;
symbol = ".", identifier ;
string = '"', { string-character | escape }, '"' ;
escape = "\\n" | "\\t" | '\\"' | "\\\\" ;
line-comment = "//", { character-except-line-feed }, [ line-feed ] ;
```
unicode-letter、unicode-number、string-character、character-except-line-feed 和 line-feed 为词法字符类别。string-character 不包括未转义的双引号、反斜杠和换行;负号不属于 number。
Unicode 分类边界及源码中的换行字符规则列于[规范状态](specification-status.md#词法与表达式)。
相关说明:[词法结构](../guide/06-lexical-structure.md)。
[目录](../README.md)
+27
View File
@@ -0,0 +1,27 @@
# 术语表
| 术语 | 定义 | 详见 |
| --- | --- | --- |
| Endorphin | 用统一声明与调用模型描述前后端应用的云原生编程语言 | [语言概览](../guide/01-overview.md) |
| 用户名 / handle | 在系统内唯一标识用户并参与代码定位的名称 | [用户身份](../guide/02-user-identity.md) |
| 显示名 | 用于界面展示、可重复的姓名或昵称 | [用户身份](../guide/02-user-identity.md) |
| 归属用户 | namespace key 指定的代码所属用户 | [用户身份](../guide/02-user-identity.md) |
| 操作用户 | 发起本次读取、修改或执行的身份 | [用户身份](../guide/02-user-identity.md) |
| namespace | 代码归属、组织与检索的单位 | [namespace](../guide/03-namespaces.md) |
| namespace key | 用户名与非空 namespace 路径组成的定位标识 | [namespace](../guide/03-namespaces.md) |
| 代码段 | 独立存储、具有明确归属的代码内容单位 | [代码存储与视图](code-storage-and-views.md) |
| 可见代码视图 | 由索引成员关系获得的 namespace 逻辑代码集合 | [代码存储与视图](code-storage-and-views.md) |
| use | 引用完整 namespace key 的声明 | [程序结构与导入](../guide/04-program-structure.md) |
| Preflight | 理解、检查和准备程序的构建阶段 | [Preflight 与 inflight](../guide/05-preflight-and-inflight.md) |
| inflight | 使用实际输入执行逻辑并产生可观察结果的运行阶段 | [Preflight 与 inflight](../guide/05-preflight-and-inflight.md) |
| 类型 | 描述值的结构及其允许用法的定义 | [类型与类](../guide/07-types-and-classes.md) |
| class | 数据结构声明 | [类型与类](../guide/07-types-and-classes.md) |
| 表达式 | 描述计算并产生值的源码形式 | [表达式与绑定](../guide/08-expressions-and-bindings.md) |
| 绑定 | 将表达式结果关联到局部名称 | [表达式与绑定](../guide/08-expressions-and-bindings.md) |
| 函数 | 定义输入、结果和执行逻辑的可调用声明 | [函数与调用](../guide/09-functions-and-calls.md) |
| 数据依赖 | 后续计算需要前一计算结果的关系 | [函数与调用](../guide/09-functions-and-calls.md) |
| 场景 / scene | 描述一个 UI 视图的声明 | [场景与渲染树](../guide/11-scenes-and-render-trees.md) |
| 渲染树 | render 块内由组件节点组成的树 | [场景与渲染树](../guide/11-scenes-and-render-trees.md) |
| 符号字面量 | 以点号和标识符表达的命名值,如 `.title` | [词法结构](../guide/06-lexical-structure.md) |
[目录](../README.md)
+111
View File
@@ -0,0 +1,111 @@
# 规范状态
本附录记录语言设计的确定程度与尚未定义的边界。它用于理解设计稿,不代表软件实现进度或可执行性保证。
## 已确定约定
| 主题 | 已确定内容 |
| --- | --- |
| 语言定位 | 前后端共用的云原生编程语言,UI 是应用领域之一 |
| 代码归属 | 每段代码属于唯一用户名和至少一级 namespace |
| 用户身份 | 使用唯一 handle 定位,不用显示名替代 |
| namespace | 各层语义一致;以外部 key 检索,不在正文声明自身归属 |
| key 形式 | `用户名:namespace路径`,冒号分隔用户与路径,点号分隔层级 |
| use | 引用完整 namespace,不附加选择性名称列表 |
| 代码组织 | 独立代码段存储在 S3,由索引组装可见代码视图,不采用源码文件 module 制 |
| 数据结构目标 | 用 class 表达共享结构,通过类取得数据的具体形式另行定义 |
| 调用目标 | 普通逻辑调用表达输入、结果与依赖,系统组织执行 |
| 官方组件 | 官方 UI 组件与用户库内容分别定义 |
| 阶段命名 | 构建阶段为 Preflight,运行阶段为 inflight;名称本身不增加源码关键字 |
## 收录的语法提案
| 提案 | 正文位置 | 说明 |
| --- | --- | --- |
| 词法与字面量 | [第 6 章](../guide/06-lexical-structure.md) | 本书统一采用的标识符、字符串、数字和符号形式 |
| 类字段与类型标注 | [第 7 章](../guide/07-types-and-classes.md) | class 目标已确定,字段和类型体系仍为具体写法提案 |
| 表达式与 let | [第 8 章](../guide/08-expressions-and-bindings.md) | 基础运算、成员访问与局部绑定 |
| function 与 return | [第 9 章](../guide/09-functions-and-calls.md) | 函数签名、基本函数体与调用组合 |
| Product.get | [第 10 章](../guide/10-data-access.md) | 读取体验提案,不是 class 自动附带的 API |
| 场景与组件 | [第 11、12 章](../guide/11-scenes-and-render-trees.md) | scene、render、参数、布局与默认值 |
程序声明组合与[形式文法](formal-grammar.md)同样属于设计稿。正文中的陈述定义这些提案内部的用法,不将其确定程度提升为最终规范。
## 身份与权限
尚未定义:
- 用户名的字符、长度、大小写、Unicode 归一化及身份范围扩展。
- handle 改名、旧名称复用、历史引用稳定性及账号生命周期。
- 代码的默认公开性、读取与执行权限,以及 namespace 权限继承。
- 协作、Agent 委托、操作身份记录与归属转移。
定位信息不构成授权,是这些规则必须保留的边界。
## 引用与代码视图
尚未定义:
- 代码段的语法边界、视图成员范围和下级 namespace 的纳入方式。
- use 的作用范围、声明可见性、限定名、别名与同名冲突。
- 视图顺序、版本选择、成员一致性及编辑操作映射。
- key 的传递编码和索引关联机制。
正文跨 namespace 示例采用目标声明可见、名称可直接解析且无冲突的条件;该条件不代替正式名称查找规则。
## 声明与类型
尚未定义:
- 程序入口、空代码视图、多个场景的选择与顶层绑定。
- 完整基础类型、数值范围、可选值、泛型及类型转换。
- 类构造、方法、默认值、继承和字段可见性。
- 重复声明、完整控制流、可变性、赋值和作用域细节。
本文简单函数体仅收录 let 与末尾 return,不意味着整门语言只允许这两种语句。
## 词法与表达式
尚未定义:
- 完整保留字集合、Unicode 版本与字符类别边界。
- 换行字符、字符串扩展转义、更多字面量和运算符。
- 数值溢出、除法、隐式转换与所有调用参数的求值顺序。
正文中同级二元算术运算的组合顺序属于表达式提案,不规定所有调用的执行顺序。
## 调用与数据
尚未定义:
- 显式等待、失败处理、缺失值、取消和超时的源码形式。
- 数据读取成员的声明、参数与结果类型。
- 一次结果、持续结果及其更新语义。
- 带业务修改的调用顺序、重复执行限制与失败行为。
- 更新代码时已有调用使用哪个版本。
正常结果必须符合声明,未就绪或失败不能伪造为成功结果。Product.get 示例只展示成功路径。
## UI
尚未定义:
- 官方组件库的 key、显式引用形式与名称可见性。
- 命名参数和位置参数的完整绑定规则及重复传参处理。
- 渲染中的调用、状态、数据绑定、事件与更新。
- 布局单位、参数范围、负数、显式尺寸、约束与溢出。
- 主题、样式、文字测量和其他组件。
正文的官方组件示例省略未定义的依赖部分,不承诺免导入使用。
## Agent
Agent 是规划应用领域。声明、能力、工具、上下文、任务、生命周期、权限及模型驱动行为的边界尚未定义。
## 规范范围
本文定义源码及应有的语言效果。云端实体、持久化类、自动建表、通信、缓存、部署和编排实现不在本阶段规范中。
S3 约定仅用于代码存储,不规定业务数据后端。Preflight 与 inflight 的职责不要求特定机器码、执行图或部署产物。
[目录](../README.md)
+64
View File
@@ -0,0 +1,64 @@
# 1. 语言概览
Endorphin 是一门兼顾前端与后端的云原生编程语言。它用共享的数据结构和普通逻辑调用连接应用的不同部分,使开发者可以直接表达业务输入、计算过程和结果。
一段业务逻辑可以由其他 namespace 引用和调用。调用方使用逻辑的名称、参数和结果类型;通信、缓存和执行组织由系统承担,不要求业务代码另行编写协议客户端或服务接口。
## 1.1 应用模型
Endorphin 应用由相互引用的声明组成:
| 声明 | 描述的内容 | 典型用途 |
| --- | --- | --- |
| 类 | 数据结构与字段类型 | 前后端共同理解商品数据 |
| 函数 | 输入、计算和输出 | 计算价格、组合业务步骤 |
| 场景 | 界面与渲染树 | 展示文本和排列界面元素 |
Agent 是后续扩展的应用领域;其声明与行为语法尚未定义,见[应用领域](../appendices/application-domains.md)。
## 1.2 代码组织
每段代码属于一个用户和至少一级 namespace。用户通过唯一用户名标识,namespace 通过完整 key 定位,例如:
```text
alice:shop.pricing
```
`alice` 是用户名,`shop.pricing` 是 namespace 路径。代码归属保存在外部上下文与索引中,正文无需声明自己的 namespace。
代码以独立代码段存储,通过索引形成 namespace 的可见代码视图。namespace 是语言的代码组织单位,源码文件不承担这一职责。
## 1.3 声明与调用
代码归属:`alice:shop.pricing`。该 namespace 定义价格计算函数:
```endorphin
function discountedPrice(price: Int, discount: Int): Int {
return price - discount
}
```
函数接收原价和优惠额,返回两者之差。应用的另一部分可以引用其 namespace,再用调用表达式计算价格:
```text
discountedPrice(100, 10) → 90
```
这里展示的是本书采用的函数写法。关键字、类型标注和调用规则会在基础语法部分逐项说明;完整跨 namespace 示例见[函数与调用](09-functions-and-calls.md)。
## 1.4 执行阶段
Endorphin 将程序处理划分为两个阶段:
- **Preflight**:理解声明与引用,检查名称、类型和程序结构,准备执行。
- **inflight**:使用实际输入执行逻辑,交付结果,并产生界面或其他业务效果。
阶段与前端、后端是不同概念。前端界面与后端逻辑都可以经过 Preflight,并在 inflight 中产生效果。namespace 的路径名称不决定阶段或执行位置。
## 1.5 本书范围
本书描述源码写法及其可观察行为,包括代码归属、声明、类型、表达式、调用、数据读取和 UI。通信协议、数据库绑定、缓存、部署和编排机制属于系统实现,不在语言介绍中展开。
下一章首先说明参与代码定位的用户身份,再介绍 namespace 与程序结构。
[下一章:用户身份](02-user-identity.md) · [目录](../README.md)
+77
View File
@@ -0,0 +1,77 @@
# 2. 用户身份
用户身份是代码归属与 namespace 定位的基础。每个代码段必须关联一个归属用户,该用户以系统内唯一的用户名标识。
## 2.1 用户名与显示名
用户名(handle)是用于定位用户的唯一名称,其作用类似社交平台的 `@` 名。显示名是用于界面展示的姓名或昵称,不承担唯一定位职责。
| 属性 | 用户名 | 显示名 |
| ---------------- | ------------------ | -------- |
| 用途 | 唯一定位用户及其 namespace | 面向读者展示名称 |
| 唯一性 | 在本系统内唯一 | 可以重复 |
| 参与 namespace key | 是 | 否 |
| 示例 | `alice` | `林` |
两个用户可以同时使用显示名“林”,但其用户名必须不同。检索代码时使用用户名,不能以显示名替代。
用户名的唯一性限定在本系统的身份范围内。其他系统中相同的用户名不自动表示同一用户。
## 2.2 key 中的用户部分
完整 namespace key 由用户名与非空 namespace 路径组成:
```text
用户名:namespace路径
alice:shop.ui
```
冒号前的 `alice` 是用户名,不带 `@` 前缀;冒号后的 `shop.ui` 定位该用户名下的 namespace。
| key | 归属用户 | namespace 路径 |
| --- | --- | --- |
| `alice:shop` | `alice` | `shop` |
| `bob:shop` | `bob` | `shop` |
| `alice:shop.ui` | `alice` | `shop.ui` |
`alice:shop` 与 `bob:shop` 是不同的 namespace,即使它们具有相同的路径或相同的代码内容。
只有用户名不能构成代码归属地址。代码必须同时属于至少一级 namespace,完整格式见[namespace](03-namespaces.md)。
## 2.3 归属上下文
用户身份通过代码之外的 key 与索引成员关系关联。读取、编辑和处理代码时,系统使用该归属上下文。
场景名、变量名、注释、字符串和存储对象名均不定义归属用户。两段内容相同的代码分别关联不同用户时,其归属上下文仍然不同。
正文中的 `use alice:shop.pricing` 表示引用目标,不表示当前代码属于 alice。例如,`bob:shop.checkout` 可以引用 alice 的逻辑,其自身归属仍是 bob。
## 2.4 归属用户、操作用户与作者
三种身份承担不同职责:
| 身份 | 含义 | 关联对象 |
| --- | --- | --- |
| 归属用户 | 代码位于谁的 namespace | namespace key 与代码成员关系 |
| 操作用户 | 谁发起读取、修改或执行 | 本次操作的身份上下文 |
| 作者或修改者 | 谁编写或修改了代码 | 编辑或历史记录 |
在协作授权存在的情况下,操作用户可以与归属用户不同。例如 bob 获得修改 `alice:shop` 的权限后,修改行为不会将目标自动改归 `bob:shop`。
Agent 或服务代用户操作时同样需要区分操作身份与目标归属。协作、委托和历史记录的具体规则参见[规范状态](../appendices/specification-status.md#身份与权限)。
## 2.5 身份与访问权限
namespace key 是定位信息,不是访问凭据。知道用户名或 key,不等于获得读取、修改或调用其中声明的权限。
代码归属与访问控制分别处理:归属确定目标,授权确定本次操作是否允许。代码默认公开性、跨用户可见性及权限继承规则不由 key 的结构推导。
## 2.6 名称比较与生命周期
注册、检索与改名必须使用一致的用户名相等判定。两个被判定为相同的用户名不能同时指向不同用户。
显示名不参与 key,修改显示名不改变代码归属。handle 的变更涉及既有 key 与引用的定位;旧名称复用还涉及历史引用是否继续指向原用户。
用户名字符集合、大小写、Unicode 处理、改名、名称复用、账号停用和归属转移的具体规则集中列于[规范状态](../appendices/specification-status.md#身份与权限)。本书示例使用简单的小写用户名说明结构,不据此限定最终字符集。
[上一章:语言概览](01-overview.md) · [下一章:namespace](03-namespaces.md) · [目录](../README.md)
+65
View File
@@ -0,0 +1,65 @@
# 3. namespace
namespace 是代码归属、组织与检索的单位。系统使用 namespace key 查找索引,取得对应代码段,并形成可见代码视图。
## 3.1 key 格式
```text
用户名:第一级namespace.后续namespace
```
key 由一个用户名、一个冒号和至少一个 namespace 路径段组成。路径段之间用点号连接:
| key | 结构 |
| --- | --- |
| `alice:shop` | 用户名与一级 namespace |
| `alice:shop.pricing` | 用户名与两级 namespace |
| `alice:shop.backend.orders` | 用户名与三级 namespace |
key 中的用户名规则见[用户身份](02-user-identity.md)。namespace 路径段在本文词法草案中使用标识符,详见[词法结构](06-lexical-structure.md)。
## 3.2 最小归属
代码必须同时具有用户和非空 namespace 路径。下列形式缺少必要信息:
| 形式 | 缺少的内容 |
| --- | --- |
| `alice` 或 `alice:` | namespace 路径 |
| `:shop` | 用户名 |
| `alice.shop.ui` | 用户名与 namespace 的分隔冒号 |
显示名不能替代用户名。代码也不能直接归属于没有 namespace 的用户根层级。
## 3.3 层级语义
用户之下的第一级 namespace 与所有后续层级具有相同语义。`shop` 在位置上类似 repository 那一层,但不构成独立的 repository 或特殊 module 类型。
namespace 路径表示组织关系。路径段名 `ui`、`backend`、`data` 或 `agents` 不自动决定执行位置、数据存储、通信方式或语言阶段。
父子 namespace 的可见性与成员范围需要独立规则;仅凭路径前缀不能认定读取父级一定包含全部子级代码。
## 3.4 可见代码视图
代码以独立代码段存储,索引关联完整 key 与代码段。可见代码视图是根据这些成员关系获得的逻辑代码集合:
```text
alice:shop.pricing
→ namespace 索引
→ 对应的独立代码段
→ 可见代码视图
```
视图可以用于阅读和程序处理,不依赖源码文件的物理路径。S3 承担代码段的存储职责;对象键与语言中的 namespace key 是不同概念,详细约定见[代码存储与视图](../appendices/code-storage-and-views.md)。
## 3.5 归属与引用
归属 key 定位当前代码,use key 定位它引用的代码。两者使用同一 key 格式,但承担不同职责:
```text
当前代码:bob:shop.checkout
引用目标:alice:shop.pricing
```
当前代码的 key 由外部上下文提供;引用目标写入正文的 `use` 声明。引用不改变归属,也不自动授予访问权限。下一章说明声明与导入的组织方式。
[上一章:用户身份](02-user-identity.md) · [下一章:程序结构与导入](04-program-structure.md) · [目录](../README.md)
+65
View File
@@ -0,0 +1,65 @@
# 4. 程序结构与导入
一个 namespace 的代码视图由导入和声明组成。声明描述类型、逻辑或界面;导入使代码能够引用其他 namespace 中允许使用的声明。
## 4.1 正文结构
本文采用的程序结构为:
```text
零个或多个 use 声明
一个或多个 class、function 或 export scene 声明
```
声明之间不使用逗号或分号。正文不含自身 namespace 声明,其归属来自外部 key 与索引。
这是一份逻辑代码视图的语法结构,不规定独立代码段的存储粒度或物理排列。代码段边界及视图组装规则见[代码存储与视图](../appendices/code-storage-and-views.md)。
## 4.2 use 声明
代码归属:`bob:shop.checkout`。导入声明:
```endorphin
use alice:shop.pricing
```
`use` 后跟一个完整 namespace key。用户名与路径用冒号分隔,路径层级用点号分隔。每个 `use` 引用一个 namespace,不附加类名、函数名或选择性名称列表。
引用整个 namespace 表示指定依赖来源,不表示获得访问权限或自动执行其中的函数。
## 4.3 声明组合
代码归属:`alice:shop.data`。
```endorphin
class Product {
name: String
price: Int
}
function listedPrice(product: Product): Int {
return product.price
}
```
同一视图可以同时包含类和函数,也可以包含场景。类与函数不需要依附 UI 场景;只有业务逻辑的 namespace 无需声明 render。
类、函数和场景的内部结构分别在[类型与类](07-types-and-classes.md)、[函数与调用](09-functions-and-calls.md)和[场景与渲染树](11-scenes-and-render-trees.md)中定义。
## 4.4 名称引用
导入后的声明必须依据可见性和名称查找规则使用。跨 namespace 示例采用“导入的名称可直接查找且没有冲突”的简化条件,用于展示调用含义;这不是对全部声明自动进入作用域的承诺。
名称限定、别名、同名冲突与可见性规则列于[规范状态](../appendices/specification-status.md#引用与代码视图)。官方 UI 组件的来源单独说明,不属于示例用户库。
## 4.5 程序与局部片段
本书区分三类示例:
- 声明示例:展示可以出现在代码视图中的类、函数或场景。
- 函数体片段:展示 let、return 或局部表达式。
- 渲染节点片段:展示 render 内的组件树。
局部片段用于查询语法,不自动成为程序顶层入口。入口选择、空视图与多个场景的选择规则仍列于[规范状态](../appendices/specification-status.md#声明与类型)。
[上一章:namespace](03-namespaces.md) · [下一章:Preflight 与 inflight](05-preflight-and-inflight.md) · [目录](../README.md)
+63
View File
@@ -0,0 +1,63 @@
# 5. Preflight 与 inflight
Endorphin 将构建阶段称为 **Preflight**,将运行阶段称为 **inflight**。这两个名称表示程序处理职责,不是源码关键字。
## 5.1 Preflight
Preflight 读取代码视图及其归属上下文,理解声明和引用,为程序执行做好准备。
其语言职责包括:
- 按词法和语法规则理解类、函数、场景与表达式。
- 解析 use 指向的 namespace 及允许使用的声明。
- 检查名称、字段、参数与返回类型。
- 检查场景结构及组件用法。
- 识别逻辑调用与结果使用之间的依赖。
- 报告可以静态确定的错误。
声明函数不表示在 Preflight 中执行函数体,声明类也不表示读取业务数据。导入 namespace 用于理解依赖,而不是执行其所有逻辑。
## 5.2 inflight
inflight 使用实际输入执行程序,产生程序可以观察到的结果。
其语言职责包括:
- 按函数定义计算并返回结果。
- 取得调用所请求的数据。
- 向后续表达式提供成功结果。
- 保持代码定义的数据依赖与业务效果。
- 根据场景和程序结果产生 UI。
- 表达执行中出现的失败或其他结果状态。
通信、缓存和执行组织方式可以由系统安排,但必须保持语言定义的值、类型、依赖和效果。
## 5.3 阶段边界
| 程序内容 | Preflight | inflight |
| --- | --- | --- |
| class 声明 | 理解字段及类型 | 在数据使用中遵守该结构 |
| function 声明 | 检查参数、函数体与返回类型 | 调用发生时执行逻辑 |
| use 声明 | 理解依赖并解析可用声明 | 在调用中使用相应逻辑 |
| 调用表达式 | 检查目标与输入类型 | 使用实际输入并取得结果 |
| 场景声明 | 检查渲染树与组件约束 | 呈现内容和排列关系 |
实际业务调用属于 inflight。Preflight 的准备与检查不改变调用发生时应有的语义;若引入构建阶段求值,需要另外定义相应规则。
## 5.4 诊断与执行失败
语法错误、未定义名称和可静态判断的类型错误由 Preflight 报告。数据不存在、调用无法完成等执行情况由 inflight 表达。
静态检查通过不保证业务调用一定成功。诊断应能定位相关声明或表达式;错误处理、取消和持续结果的具体写法见[规范状态](../appendices/specification-status.md#调用与数据)。
## 5.5 阶段与执行角色
阶段、应用角色和代码归属是不同维度:
- Preflight 与 inflight 表示处理阶段。
- 前端、后端与 Agent 表示应用角色。
- namespace key 表示代码归属与引用位置。
它们不要求一一对应,也不要求位于不同进程或机器。`alice:shop.ui` 的名称不会自动将其中所有代码限定在某个阶段或某类设备。
[上一章:程序结构与导入](04-program-structure.md) · [下一章:词法结构](06-lexical-structure.md) · [目录](../README.md)
+111
View File
@@ -0,0 +1,111 @@
# 6. 词法结构
词法规则将源码划分为标识符、关键字、字面量、运算符和标点。源码使用 UTF-8;空白与注释用于分隔词法单元。
本章代码块展示局部词法形式,使用位置由后续表达式和声明规则决定,不是独立程序。
## 6.1 标识符
标识符以 `_` 或 Unicode 字母开头,后续可以包含 `_`、Unicode 字母或数字。名称区分大小写。
```text
Product
discountedPrice
price
product_1
```
namespace 路径段使用标识符。用户名属于系统身份规则,不直接使用源码标识符的定义。
## 6.2 关键字
本文语法使用以下关键字:
| 关键字 | 用途 |
| --- | --- |
| `use` | 引用 namespace |
| `class` | 声明数据结构 |
| `function` | 声明函数 |
| `let` | 绑定局部结果 |
| `return` | 返回函数结果 |
| `export`、`scene` | 声明导出的 UI 场景 |
| `render` | 定义场景的渲染树 |
这些关键字在相应产生式的位置出现。完整保留字集合见[规范状态](../appendices/specification-status.md#词法与表达式)。
## 6.3 数字
数字字面量采用十进制,至少包含一位数字。小数点两侧均须有数字:
```endorphin
0
100
1.5
```
负号是运算符,而不是数字词法单元。`-4` 是对 `4` 使用一元负号,详见[表达式与绑定](08-expressions-and-bindings.md)。
本文数字语法不包含科学计数法、前导正号或省略小数点一侧数字的形式。数字类型、精度和范围由类型规则定义,而不是由字面量的字符形式决定。
## 6.4 字符串
字符串由双引号包围,可以直接包含 Unicode 字符:
```endorphin
"Product"
"商品"
"First\nSecond"
```
| 转义 | 含义 |
| --- | --- |
| `\n` | 换行 |
| `\t` | 水平制表符 |
| `\"` | 双引号 |
| `\\` | 反斜杠 |
双引号、反斜杠和换行在字符串内使用上述转义。未闭合字符串和本文未定义的转义在 Preflight 中产生诊断。
## 6.5 符号字面量
点号后接标识符表示符号字面量:
```endorphin
.title
```
符号表达命名值,例如 UI 的标题角色。不带点号的 `title` 是名称引用,`product.name` 是成员访问,二者均不等同于 `.title`。
符号可用于哪些参数,由对应声明的类型与取值约定决定。
## 6.6 标点与运算符
| 字符 | 用途 |
| --- | --- |
| `{`、`}` | 声明体、函数体和子节点块 |
| `(`、`)` | 参数、调用和表达式分组 |
| `:` | key 分隔、类型标注和命名参数 |
| `,` | 分隔参数 |
| `.` | namespace 层级、成员访问和符号前缀 |
| `=` | let 绑定 |
| `+`、`-`、`*`、`/` | 算术运算 |
冒号的含义由语法位置确定:`alice:shop.data` 中分隔用户与路径,`price: Int` 中标注类型,`gap: 12` 中指定参数名。
## 6.7 空白与注释
空格、制表符和换行可出现在词法单元之间。缩进不构成代码块,代码块由花括号界定。
行注释以 `//` 开始,持续到下一行或源码结束。函数体片段:
```endorphin
// 计算优惠后的金额
let amount = 100 - 10
return amount
```
注释不参与求值。本文语法不包含块注释。
词法产生式集中列于[形式文法](../appendices/formal-grammar.md#词法)。
[上一章:Preflight 与 inflight](05-preflight-and-inflight.md) · [下一章:类型与类](07-types-and-classes.md) · [目录](../README.md)
+64
View File
@@ -0,0 +1,64 @@
# 7. 类型与类
类型描述值的结构及其允许的用法。类型标注用于字段、函数参数和返回值,使不同应用部分能够依据同一声明理解数据。
## 7.1 类型标注
类型标注采用 `名称: 类型` 的形式:
```text
price: Int
name: String
```
本文示例使用:
| 类型名 | 表达的值 |
| --- | --- |
| `Int` | 整数 |
| `String` | 字符串 |
| 用户声明的类名 | 具有该类字段结构的数据 |
数值范围、其他基础类型、可选类型和转换规则尚未构成完整类型体系,范围见[规范状态](../appendices/specification-status.md#声明与类型)。
## 7.2 class 声明
代码归属:`alice:shop.data`。
```endorphin
class Product {
name: String
price: Int
}
```
该声明定义名为 `Product` 的数据结构,含有两个字段:`name` 为字符串,`price` 为整数。使用 Product 数据的代码依据同一结构读取字段,不需要为前端另写一份对应结构。
类名是标识符。类体由字段声明组成,每个字段写出名称和类型,字段之间不使用逗号或分号。
## 7.3 类型与值
`Product` 表示数据的类型;符合 Product 结构的某个值,才包含本次业务数据。
类声明本身不取得某件商品,也不指定数据库、表或连接。通过类型取得数据的用法在[数据读取](10-data-access.md)中说明;构造、方法与默认值属于独立的类型规则。
## 7.4 字段访问
函数体片段;局部名称 `product` 表示已取得的 Product 值:
```endorphin
let name = product.name
let price = product.price
```
成员访问使用点号。第一行取得字符串字段,第二行取得整数字段。字段使用的类型由声明决定;读取不存在的字段不是有效的 Product 用法。
成员访问和 let 的表达式规则见下一章。
## 7.5 类型检查与共享
Preflight 理解类和字段声明,检查字段访问、函数参数与返回值的类型关系。inflight 中取得和使用的数据必须遵守对应结构。
跨 namespace 引用类时,引用的是定义该结构的声明,不改变调用方代码的归属。声明是否可访问取决于可见性和权限规则,见[程序结构与导入](04-program-structure.md)。
[上一章:词法结构](06-lexical-structure.md) · [下一章:表达式与绑定](08-expressions-and-bindings.md) · [目录](../README.md)
+68
View File
@@ -0,0 +1,68 @@
# 8. 表达式与绑定
表达式描述计算并产生值。let 将表达式结果绑定到局部名称,后续表达式可以使用这个结果。
## 8.1 表达式形式
本文语法包含以下表达式:
| 形式 | 示例 | 含义 |
| --- | --- | --- |
| 字面量 | `100`、`"商品"`、`.title` | 直接表达一个值 |
| 名称引用 | `amount` | 使用已解析的名称 |
| 一元表达式 | `-4` | 对值使用一元负号 |
| 算术表达式 | `100 - 10` | 计算数值 |
| 成员访问 | `product.price` | 使用字段或成员 |
| 调用 | `discountedPrice(100, 10)` | 调用逻辑并取得结果 |
| 分组 | `(100 - 10) * 2` | 改变表达式组合方式 |
具体名称和成员必须存在并符合类型要求。调用的参数和返回规则见[函数与调用](09-functions-and-calls.md)。
## 8.2 运算与优先级
从高到低的组合顺序为:
| 顺序 | 形式 |
| --- | --- |
| 1 | 分组中的表达式 |
| 2 | 成员访问与调用 |
| 3 | 一元负号 |
| 4 | 乘法、除法 |
| 5 | 加法、减法 |
同级二元算术运算在本文草案中按从左到右组合。`100 - 10 * 2` 先做乘法,结果为 `80`;`(100 - 10) * 2` 的结果为 `180`。
数值溢出、除法、隐式转换和其他运算符的规则见[规范状态](../appendices/specification-status.md#词法与表达式)。
## 8.3 let 绑定
函数体片段:
```endorphin
let amount = 100 - 10
let payable = amount - 5
```
第一行将结果 `90` 绑定到 amount,第二行使用它得到 `85`。每个绑定包含关键字 `let`、局部名称、等号和表达式。
let 是结果绑定,不是 namespace 声明。本文函数文法将绑定放在函数体内;顶层绑定、重新赋值与可变性不由该语句推导。
## 8.4 成员访问
`值.成员名` 访问该值的字段或其他可用成员。类型检查决定访问是否合法。
`product.price` 使用 Product 的字段。`Product.get(...)` 则在形式上是先找到类成员,再调用;成员调用的形式不会自动为 Product 创建 get 方法,详见[数据读取](10-data-access.md)。
## 8.5 结果依赖
当一个表达式使用前一个调用的结果时,存在数据依赖:
```text
第一次调用 → 结果绑定 → 使用该结果的第二次调用
```
inflight 必须在结果可用后使用它,不能将未就绪状态替换为伪造成功值。Preflight 检查表达式结构与类型,不能据此保证所有实际调用成功。
表达式是否带有业务修改效果,以及失败、等待与取消的表示方式,由调用语义定义。算术的组合顺序不自动确定所有调用参数的求值顺序。
[上一章:类型与类](07-types-and-classes.md) · [下一章:函数与调用](09-functions-and-calls.md) · [目录](../README.md)
+90
View File
@@ -0,0 +1,90 @@
# 9. 函数与调用
函数定义可调用的逻辑,包括名称、输入参数、结果类型和函数体。调用表达式提供输入,并取得函数定义的结果。
## 9.1 函数声明
代码归属:`alice:shop.pricing`。
```endorphin
function discountedPrice(price: Int, discount: Int): Int {
return price - discount
}
```
声明的组成如下:
| 部分 | 含义 |
| --- | --- |
| `function` | 函数声明关键字 |
| `discountedPrice` | 函数名 |
| `price: Int, discount: Int` | 两个输入参数及其类型 |
| 参数列表后的 `: Int` | 返回类型 |
| 花括号内的内容 | 函数体 |
参数按逗号分隔,每个参数都有名称与类型。本文基本函数体由零个或多个 let 绑定和一个末尾 return 组成;完整控制流另列于[规范状态](../appendices/specification-status.md#声明与类型)。
## 9.2 返回值
`return 表达式` 产生函数结果。表达式的类型必须符合返回类型。
discountedPrice 返回两个整数的差值。对于输入 `100` 与 `10`,成功结果为 `90`。定义函数不立即执行它;执行发生在 inflight 调用中。
## 9.3 跨 namespace 调用
代码归属:`bob:shop.checkout`。
```endorphin
use alice:shop.pricing
function payable(price: Int, discount: Int): Int {
let amount = discountedPrice(price, discount)
return discountedPrice(amount, 5)
}
```
payable 引用定价 namespace,先使用原价与优惠额计算 amount,再从 amount 中扣除 `5`。对于输入 `100` 与 `10`,两次成功结果依次为 `90` 和 `85`。
该例采用第 4 章所述的无名称冲突、被引用函数可见的条件。use 定位依赖来源,函数调用使用其中的逻辑;二者分别承担引用和执行职责。
## 9.4 调用组合
代码归属:`bob:shop.ui`。业务函数声明:
```endorphin
use bob:shop.checkout
function checkoutAmount(): Int {
return payable(100, 10)
}
```
checkoutAmount 的成功结果为 `85`。它不需要重复实现价格计算,也不需要为跨 namespace 调用另写客户端、网络请求或编排配置。
相同的普通调用形式用于本地逻辑和跨执行位置的逻辑。执行位置和通信方式不改变输入、结果类型与数据依赖。
## 9.5 Preflight 检查
在名称和类型规则确定的范围内,Preflight 检查:
- 调用目标是否存在且允许使用。
- 参数数量和类型是否符合声明。
- return 表达式是否符合返回类型。
- 使用调用结果的后续表达式是否合法。
例如,discountedPrice 需要两个整数参数。`discountedPrice(100)` 数量不符;`discountedPrice("100", 10)` 在本文不进行隐式字符串到整数转换的示例条件下类型不符。
## 9.6 inflight 行为
inflight 使用实际参数执行函数,并把成功结果交给调用表达式。依赖关系必须保留:payable 的第二次优惠计算使用第一次调用的 amount。
| 情况 | 行为要求 |
| --- | --- |
| 调用成功 | 结果的值和类型符合函数定义 |
| 结果未就绪 | 依赖该结果的代码不能提前将它作为成功值使用 |
| 调用失败 | 失败可被观察,不伪造成功结果 |
| 执行位置变化 | 已定义的值、类型、依赖与业务效果保持一致 |
函数不默认被视为纯计算。对带业务修改效果的调用,系统不能为了执行组织而任意重复或并行执行;相关顺序、失败和取消语义见[规范状态](../appendices/specification-status.md#调用与数据)。
[上一章:表达式与绑定](08-expressions-and-bindings.md) · [下一章:数据读取](10-data-access.md) · [目录](../README.md)
+66
View File
@@ -0,0 +1,66 @@
# 10. 数据读取
数据读取是逻辑调用的一种用法:代码引用数据结构,发起读取,并按声明的字段使用取得的结果。调用方处理业务数据,不处理传输响应或缓存连接。
## 10.1 数据结构
代码归属:`alice:shop.data`。商品结构沿用第 7 章的 Product:
```endorphin
class Product {
name: String
price: Int
}
```
结构使调用方能够共同理解商品名称和价格。它不定义数据库表、持久化实体或自动建表行为。
## 10.2 读取形式
> 语法提案:本节用 `Product.get(...)` 表达“通过类取得数据”。get 的存在与声明方式尚未定义,该写法不是所有 class 自动拥有的成员。
代码归属:`bob:shop.checkout`。读取函数示例,采用 Product 与读取成员均可访问的条件;成功路径中,读取成员接收一个 String 标识并返回 Product,其正式声明语法仍未定义:
```endorphin
use alice:shop.data
function productPrice(id: String): Int {
let product = Product.get(id)
return product.price
}
```
调用参数 id 表达所需数据的标识,不是 namespace key。`alice:shop.data` 定位数据结构与逻辑来源,id 指定本次业务对象。
成功调用 productPrice 后,返回值应为取得商品的 price 字段。结果已经具有 Product 结构,调用方无需先解析 HTTP 响应或手动转换传输数据。
## 10.3 读取与字段使用
读取结果可用后,才可读取它的字段。函数中的 product.price 依赖 Product.get 的成功结果;系统必须保持这一依赖。
Preflight 理解结构、引用和成员调用的类型关系,inflight 取得本次数据并交付结果。声明 Product 本身不在 Preflight 中读取商品。
具体读取成员必须在最终规则中具有可检查的参数与返回定义。仅有前面的字段声明不足以证明 get 调用合法。
## 10.4 结果状态
| 状态 | 调用方需要获知的内容 |
| --- | --- |
| 成功 | 符合 Product 结构的结果 |
| 缺失 | 目标数据不存在 |
| 失败 | 本次读取无法完成 |
| 未就绪 | 成功结果尚未可用 |
上述函数只展示成功路径。缺失、失败和未就绪不能自动当作合法 Product,也不能默认替换成空字符串或零。
状态的类型与处理语法,以及是否需要显式等待,集中列于[规范状态](../appendices/specification-status.md#调用与数据)。
## 10.5 一次读取与持续结果
本节 get 提案按一次读取说明。持续跟随数据变化与一次读取具有不同的可观察行为;是否使用不同表达式或结果类型仍未定义。
UI 可以使用成功取得的字段展示内容,但加载、缺失、失败与后续更新需要对应的界面语义。正文不将未定义的数据绑定或读取调用直接混入 render 示例。
数据读取的协议、缓存和后端绑定不影响上述源码目标,也不在本章选择。
[上一章:函数与调用](09-functions-and-calls.md) · [下一章:场景与渲染树](11-scenes-and-render-trees.md) · [目录](../README.md)
+101
View File
@@ -0,0 +1,101 @@
# 11. 场景与渲染树
场景声明描述一个 UI 视图。render 块包含该视图的渲染树,树中的节点表示组件、参数和子节点。
## 11.1 场景声明
代码归属:`bob:shop.ui`。
```endorphin
export scene Main {
render {
Column(gap: 12, padding: 24) {
Text("Shop", role: .title)
Row(gap: 8) {
Text("Price")
Spacer(size: 4)
Text("90")
}
}
}
}
```
Main 是场景名。Column 是根节点,包含一个标题和一个横向排列的 Row。
本章使用[UI 组件](12-ui-components.md)中的官方组件。官方库的 key 和引用形式未定义,示例仅省略这一依赖部分,不表示官方组件属于任何示例用户库或必然免导入可用。
## 11.2 render 与单根结构
本文场景文法要求一个场景包含一个 render 块,render 中恰好包含一个根节点。
多个同级节点放入同一个布局根节点。下面是 render 内的有效节点片段:
```endorphin
Column {
Text("First")
Text("Second")
}
```
两个 Text 是 Column 的子节点,不是两个 render 根节点。单根规则仅约束 render 内部,不限制 namespace 只能有一个声明。
## 11.3 节点形式
节点包含组件名、可选参数列表和可选子节点块:
```text
组件名
组件名(参数列表)
组件名(参数列表) { 子节点 }
```
组件名是标识符。省略参数列表与空参数列表都表示没有显式参数;默认值由组件约定决定。
渲染节点片段:
```endorphin
Column {}
Spacer(size: 16)
Text("Product")
```
这三行分别展示空容器、带命名参数的节点和带位置参数的节点,不是一个具有三个根的完整 render 块。
## 11.4 参数
位置参数按参数位置表达输入,命名参数用 `参数名: 表达式`:
```endorphin
Text("Product", role: .title)
```
字符串为第一个位置参数,role 为命名参数。参数按逗号分隔,不使用尾随逗号。命名参数与位置参数可以在节点形式中共存,具体绑定与重复传参规则见[规范状态](../appendices/specification-status.md#ui)。
参数引用通用表达式文法,但 render 中允许哪些调用、状态读取和修改效果,需要另外规定;文法可以表达一种形式不等于该形式在所有渲染上下文中合法。
## 11.5 子节点与嵌套
子节点由花括号包围,相邻节点不使用逗号或分号。布局组件可以递归嵌套:
```endorphin
Column(gap: 12) {
Text("Shop", role: .title)
Row(gap: 8) {
Text("Left")
Text("Right")
}
}
```
Column 从上到下排列标题与 Row,Row 从左到右排列两段文本。结构文法允许子节点块,组件语义决定具体组件是否接受子节点;Text 和 Spacer 的用法不接受子节点。
## 11.6 检查与展示
Preflight 检查场景结构、单根约束、组件名称、参数和子节点是否合法。不合法节点或参数应得到诊断,而不是静默替换为别的组件或默认参数。
inflight 展示声明的内容与排列关系。渲染树不指定绘制协议、字体引擎或某个布局计算必须发生在哪一阶段。
数据绑定、事件、加载状态和界面更新的具体语法见[规范状态](../appendices/specification-status.md#ui)。
[上一章:数据读取](10-data-access.md) · [下一章:UI 组件](12-ui-components.md) · [目录](../README.md)
+89
View File
@@ -0,0 +1,89 @@
# 12. UI 组件
本章是官方基础组件的用法参考,定义本文 UI 草案中的参数、默认值和展示效果。示例是 `bob:shop.ui` 场景 render 内的节点片段。
官方库的 key 和引用形式尚未定义,来源约定见[场景与渲染树](11-scenes-and-render-trees.md)。用户库提供的组件则以其实际声明为准。
## 12.1 Column
Column 从上到下排列子节点。
```endorphin
Column(gap: 12, padding: 24) {
Text("First")
Text("Second")
}
```
| 参数 | 值类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `gap` | 数字 | `0` | 相邻子节点的垂直间距 |
| `padding` | 数字 | `0` | 四个方向的内边距 |
**子节点:** 接受零个或多个节点。
**布局效果:** 在本文简单内容布局模型中,宽度为最宽子节点宽度加左右内边距;高度为子节点高度、相邻间距和上下内边距之和。空容器没有子节点间距。
## 12.2 Row
Row 从左到右排列子节点。
```endorphin
Row(gap: 8, padding: 4) {
Text("Left")
Text("Right")
}
```
| 参数 | 值类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `gap` | 数字 | `0` | 相邻子节点的水平间距 |
| `padding` | 数字 | `0` | 四个方向的内边距 |
**子节点:** 接受零个或多个节点。
**布局效果:** 在本文简单内容布局模型中,宽度为子节点宽度、相邻间距和左右内边距之和;高度为最高子节点高度加上下内边距。空容器没有子节点间距。
## 12.3 Spacer
Spacer 占据布局空间,不显示可见内容。
```endorphin
Spacer(size: 16)
```
| 参数 | 值类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `size` | 数字 | `0` | 占位宽度与高度 |
**子节点:** 不接受。
**布局效果:** 在父组件的排列中占据指定空间。它不是间距参数本身,而是树中的一个节点。
## 12.4 Text
Text 显示字符串内容。
```endorphin
Text("Product")
Text("Shop", role: .title)
```
| 参数 | 值类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| 第一个位置参数 | 字符串 | `""` | 显示的文本 |
| `role` | 符号值 | 普通文本角色 | `.title` 表示标题视觉角色 |
**子节点:** 不接受。
**展示效果:** 内容按字符串显示;role 表达文本的视觉角色,不指定固定字号、颜色、字符宽度或缩放比例。
## 12.5 尺寸与参数检查
数字布局参数表达逻辑尺寸,本文不将其等同于设备像素。单位、数值范围、负数、显式尺寸、溢出、主题与文字测量规则列于[规范状态](../appendices/specification-status.md#ui)。
Preflight 检查组件名称、参数数量与类型、子节点约束;inflight 保持组件规定的内容和排列效果。未知参数、错误类型或不支持的子节点不能通过静默忽略获得有效语义。
本章组件参数与默认值属于 UI 提案,确定程度与其他语言主题一起记录在规范状态附录。
[上一章:场景与渲染树](11-scenes-and-render-trees.md) · [附录:形式文法](../appendices/formal-grammar.md) · [目录](../README.md)