跳转到内容
查看源码

类型与 Field

Entelechy 只有一种资源:类型化的 Field。图片、声音、几何、骨骼、游戏状态,都是“某种元素按某种形状排列”的 Field。这让任何 Kernel 都能读写任何数据,也让 Host 保持极简(设计理由见仓库 docs/TYPED-FIELD-ARCHITECTURE.md)。

形状 地址 size(f) 图中的 domain =
Rows<T> Int Int 256
Grid<T> Vec2 Vec2 vec2(w, h)
Volume<T> Vec3 Vec3 vec3(w, h, d)

Kernel 可以声明任意多个端口;GPU 后端会拒绝输入输出总数超过其适配器一次能绑定数量的 Kernel,并说明具体数字。

元素可以是标量、向量、结构体或数组;它的布局就是按顺序排列的标量,整数和布尔精确保存。

类别 类型
标量 Float、Int、Bool、Double、Long
浮点向量 Vec2、Vec3、Vec4
整数向量 IVec2、IVec3、IVec4
矩阵(按列) Mat2、Mat3、Mat4
64 位 DVec2..4、LVec2、LVec3、DMat2..4
复合 struct、数组 [T; N]、enum(命名的 Int)

Image 是内置别名,等于 Grid<Vec4>:一个 Grid<Vec4> 输出会显示在窗口里,在任何需要 Image 的地方都按像素读取。

type Name = Shape<Element>; 声明别名。别名是透明的:一条 Rows<Vec2> 连线可以接到 type Stereo = Rows<Vec2>; 的端口上。类型不匹配按结构报告,而不是按名字。绑定要求形状和元素布局一致,不管两边叫什么。

节点输出的范围称为定义域:

  • 没有输入的节点必须写 domain = …;。
  • 有输入的节点默认取它的 Kernel 遍历的那个输入(over)的范围,或者 map 的第一个输入的范围。
  • domain 可以是一个关于结构的表达式:size(port)、count(port)、value(port)、图参数、数字、vec2/vec3、+ - * / <<、max、min、floor、ceil、window()、scale()。例如 domain = size(map) * tile;、domain = 4 * count(faces);、domain = window();(窗口变化时以新尺寸重新运行)。

完整的 domain 函数见场景语法。

场景(或 Kernel 库)里的 input name: Type; 是由调用者提供的 Field。加上来源后,Host 会相对于文档读取它,并在文件变化时重新读取:

写法 读入方式
input atlas: Image = "atlas.ppm"; .png / .ppm 读作像素(Grid<Float> 时读作亮度);.pgm 读作 Grid<Float>;.wav 读作一或两个 float 的行;.mid 读作音符行;.ies 读作光度数据;.field 是 Host 自己的格式,可保存任意 Field
input skills: Rows<Skill> = "data/skills.csv"; .csv 或 .json 数据表,按读取它的 Kernel 声明的元素布局读入;#name 列可以被其他表以 table:name 引用
input title: Rows<Int> = text "ENTELECHY"; 字符的码点
input level: Rows<Int> = bytes "level.bin"; 文件的字节,每个元素 0–255
input clip: Image = frames "clip/" at 30; 按名字顺序的一系列帧,按时间播放并循环
input problems: Rows<Int> = checks "src/"; 目录中文档的诊断文本(与 entelechy check 相同)
input defined: Rows<Int> = outline "src/"; 目录中文档定义了什么(函数、Kernel、结构体……)
input disk: Rows<Int> = files "project/"; 目录下每个文件的路径与字节
input pasted: Rows<Int> = clipboard; 剪贴板文本(Player 中需要 --allow clipboard.read)
input work: Rows<Int> = progress; 正在准备的 Kernel 的进度
input saved: Rows<Tally> = "saves/tally.field" else fresh.result; 文件不存在(或布局不同)时读取 fresh.result 作为回退

通过包名的路径("world.entpkg/data/rules.csv")读取包内的文件。场景写出的文件只会写到它的路径所指的位置,从不写进包里。

  • entelechy run --save <节点.端口>=<文件>:把任意节点的输出写成文件,格式由扩展名决定。
  • output kept <- state.result to "saves/state.field";:场景输出在每次成功求值后写入文件,需要 --allow file.write=<目录>。
  • to files "project/":一组文件操作(写、删、重命名),删除和重命名还需要 --allow file.delete。
  • 输出也可以交给 Host 设备:to sound、to pointer、to pointer_tip、to clipboard。

详见文件、导入与导出。