类型
FunC 文档最初由 @akifoq 编写。
FunC 有以下内置类型。
原子类型
int
是 257 位有符号整数的类型。默认情况下,启用溢出检查,会导致整数溢出异常。cell
是 TVM cell的类型。TON 区块链中的所有持久数据都存储在cell树中。每个cell最多有 1023 位任意数据和最多四个对其他cell的引用。cell在基于堆栈的 TVM 中用作内存。slice
是cell切片的类型。cell可以转换成切片,然后可以通过从切片加载数据位和对其他cell的引用来获得cell中的数据。builder
是cell构建器的类型。数据位和对其他cell的引用可以存储在构建器中,然后构建器可以最终化为新cell。tuple
是 TVM 元组的类型。元组是有序集合,最多包含 255 个组件,这些组件的值类型可能不同。cont
是 TVM continuation的类型。Continuations 用于控制 TVM 程序执行的流程。从 FunC 的角度来看,它是相当低层级的对象,尽管从概念上讲相当通用。
请注意,上述任何类型都只占用 TVM 堆栈中的单个条目。
没有布尔类型
在 FunC 中,布尔值被表示为整数;false
表示为 0
,true
表示为 -1
(二进制表示为 257 个一)。逻辑运算作为位运算执行。当检查条件时,每个非零整数都被视为 true
值。
Null值
通过 TVM 类型 Null
的值 null
,FunC 表示某些原子类型的值缺失。标准库中的一些原语可能被类型化为返回原子类型,并在某些情况下实际返回 null
。其他原语可能被类型化为接受原子类型的值,但也可以与 null
值一起正常工作。这种行为在原语规范中明确说明。默认情况下,禁止 null
值,这会导致运行时异常。
这样,原子类型 A
可能被隐式转换为类型 A^?
,也就是 Maybe A
(类型检查器对这种转换无感知)。
Hole类型
FunC 支持类型推断。类型 _
和 var
表示类型“holes”,稍后可以在类型检查期间用某些实际类型填充。例如,var x = 2;
是变量 x
等于 2
的定义。类型检查器可以推断出 x
的类型为 int
,因为 2
的类型为 int
,赋值的左右两边必须类型相等。
复合类型
类型可以组合成更复杂的类型。
函数类型
形式为 A -> B
的类型表示具有指定域和陪域的函数。例如,int -> cell
是一个函数类型,它接受一个整数参数并返回一个 TVM cell。
在内部,这种类型的值被表示为continuations。
张量类型
形式为 (A, B, ...)
的类型本质上表示有序的值集合,这些值的类型为 A
、B
、...
,它们一起占用多个 TVM 堆栈条目。
例如,如果函数 foo
的类型为 int -> (int, int)
,这意味着该函数接受一个整数并返回一对整数。
调用此函数可能看起来像 (int a, int b) = foo(42);
。在内部,该函数消耗一个堆栈条目并留下两个。
请注意,从低层级角度来看,类型 (int, (int, int))
的值 (2, (3, 9))
和类型 (int, int, int)
的值 (2, 3, 9)
,在内部以三个堆栈条目 2
、3
和 9
的形式表示。对于 FunC 类型检查器,它们是不同类型的值。例如,代码 (int a, int b, int c) = (2, (3, 9));
将无法编译。
张量类型的特殊情况是cell类型 ()
。它通常用于表示函数不返回任何值或没有参数。例如,函数 print_int
的类型将为 int -> ()
,而函数 random
的类型为 () -> int
。它有一个唯一的inhabitant ()
,它占用 0 个堆栈条目。
类型 (A)
被类型检查器视为与 A
相同的类型。
元组类型
形式为 [A, B, ...]
的类型表示在编译时已知长度和组件类型的 TVM 元组。例如,[int, cell]
是一个元组类型,其长度恰好为 2,其中第一个组件是整数,第二个是cell。[]
是空元组的类型(具有唯一的inhabitant——空元组)。请注意,与cell类型 ()
相反,[]
的值占用一个堆栈条目。
带有类型变量的多态
FunC拥有支持多态函数的 Miller-Rabin 类型系统。例如,以下是一个函数:
forall X -> (X, X) duplicate(X value) {
return (value, value);
}
是一个多态函数,它接受一个(单堆栈条目)值并返回这个值的两个副本。duplicate(6)
将产生值 6 6
,而 duplicate([])
将产生两个空元组 [] []
的副本。
在这个例子中,X
是一个类型变量。
有关此主题的更多信息,请参阅函数部分。
用户定义类型
目前,FunC 不支持定义除上述类型构造之外的类型。
类型宽度
您可能已经注意到,每种类型的值都占用一定数量的堆栈条目。如果所有该类型的值都占用相同数量的条目,则该数字称为类型宽度(type width)。目前只能为具有固定且预先知道的类型宽度的类型定义多态函数。