数字字面量
FunC 支持十进制和十六进制整数字面量(允许前导零)。
例如,
0
、123
、-17
、00987
、0xef
、0xEF
、0x0
、-0xfFAb
、0x0001
、-0
、-0x0
都是有效的数字字面量。字符串字面量
FunC 中的字符串使用双引号
"
包裹,如 "this is a string"
。不支持特殊符号如 \n
和多行字符串。 可选地,字符串字面量后可以指定类型,如 "string"u
。支持以下字符串类型:
- 无类型 —— 用于 asm 函数定义和通过 ASCII 字符串定义 slice 常量
s
—— 通过其内容(十六进制编码并可选地位填充)定义原始 slice 常量
a
—— 从指定地址创建包含MsgAddressInt
结构的 slice 常量
u
—— 创建对应于提供的 ASCII 字符串的十六进制值的 int 常量
h
—— 创建字符串的 SHA256 哈希的前 32 位的 int 常量
H
—— 创建字符串的 SHA256 哈希的所有 256 位的 int 常量
c
—— 创建字符串的 crc32 值的 int 常量
例如,以下值会生成对应的常量:
"string"
变成x{737472696e67}
slice 常量
"abcdef"s
变成x{abcdef}
slice 常量
"Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF"a
变成x{9FE6666666666666666666666666666666666666666666666666666666666666667_}
slice 常量(addr_std$10 anycast:none$0 workchain_id:int8=0xFF address:bits256=0x33...33
)
"NstK"u
变成0x4e73744b
int 常量
"transfer(slice, int)"h
变成0x7a62e8a8
int 常量
"transfer(slice, int)"H
变成0x7a62e8a8ebac41bd6de16c65e7be363bc2d2cbc6a0873778dead4795c13db979
int 常量
"transfer(slice, int)"c
变成2235694568
int 常量
1. 无类型(默认):
用于汇编函数定义或定义 slice 常量,主要是将字符串按 ASCII 编码存储。例如,使用字符串表示指令或直接存储 ASCII 值的情况。
- 场景:编写低级汇编代码或定义硬编码的字符串常量。
- 示例:
"transfer"
用于表示某个硬编码的汇编指令。
2. s 类型:
用于将字符串的十六进制编码值存储为 slice。可以选择对字符串进行位填充。
- 场景:需要存储原始数据或进行位级别操作时,例如加密协议中,数据以十六进制形式存储或传递。
- 示例:
"abcdef"s
将会存储为x{abcdef}
。
3. a 类型:
将字符串解释为一个地址,并生成一个包含
MsgAddressInt
结构的切片。这种类型用于处理区块链地址。- 场景:在区块链智能合约中操作和存储地址信息时使用。
- 示例:从给定的地址创建一个标准格式的切片,用于指定消息的接收者地址。
4. u 类型:
将 ASCII 字符串转换为其对应的十六进制整数值。这种转换方便在编译时处理字符串的数值表示。
- 场景:需要快速计算字符串的十六进制值或需要用整数形式存储字符串时。
- 示例:
"NstK"u
变为0x4e73744b
,ASCII 转换为整数常量。
5. h 类型:
生成字符串的SHA256 哈希值的前 32 位,并将其存储为整数。这通常用于加密操作和哈希校验。
- 场景:需要为较短的数据生成哈希摘要,以供后续加密操作或校验使用。
- 示例:
"transfer(slice, int)"h
生成0x7a62e8a8
。
6. H 类型:
生成字符串的完整 256 位 SHA256 哈希值,并将其存储为整数。适用于全局唯一标识符或需要全哈希的场景。
- 场景:需要完整哈希值时,尤其是在数据签名、哈希函数或密码学应用中使用。
- 示例:
"transfer(slice, int)"H
生成256 位
完整的 SHA256 哈希。
7. c 类型:
计算字符串的crc32 校验值并将其存储为整数。这在数据完整性校验中常用。
- 场景:需要快速验证数据完整性时,通常用于文件传输、校验和生成等场景。
- 示例:
"transfer(slice, int)"c
生成2235694568
的 crc32 校验值。
总结
这些类型标识符的使用主要集中在区块链合约、加密操作、低级编程等场景中,帮助开发者灵活处理和转换字符串,满足不同的存储、加密和校验需求。
标识符
FunC 允许使用非常广泛的标识符类别(函数和变量名)。具体来说,任何不包含特殊符号
;
、,
、(
、)
、
(空格或制表符)、~
和 .
,不以注释或字符串字面量(以 "
开头)开始,不是数字字面量,不是下划线 _
,也不是关键字的单行字符串都是有效的标识符(唯一的例外是,如果它以 `
开头,则必须以相同的 `
结尾,并且不能包含除这两个外的任何其他 `
)。此外,函数定义中的函数名可以以
.
或 ~
开头。例如,以下是有效的标识符:
query
、query'
、query''
elem0
、elem1
、elem2
CHECK
_internal_value
message_found?
get_pubkeys&signatures
dict::udict_set_builder
_+_
(标准加法运算符,类型为(int, int) -> int
,虽然已被定义)
fatal!
变量名末尾的
'
通常用于表示某个旧值的修改版本。例如,几乎所有用于 hashmap 操作的内置修改原语(除了以 ~
为前缀的原语)都会接收一个 hashmap 并返回新版本的 hashmap 及必要时的其他数据。将这些值命名为相同名称后加 '
很方便。后缀
?
通常用于布尔变量(TVM 没有内置的 bool 类型;bools 由整数表示:0 为 false,-1 为 true)或返回某些标志位的函数,通常表示操作的成功(如 stdlib.fc 中的 udict_get?
)。以下是无效的标识符:
take(first)Entry
"not_a_string
msg.sender
send_message,then_terminate
_
一些不太常见的有效标识符示例:
123validname
2+2=2*2
alsovalidname
0xefefefhahaha
{hehehe}
pa{--}in"`aaa`"
这些也是无效的标识符:
pa;;in"`aaa`"
(因为禁止使用;
)
{-aaa-}
aa(bb
123
(它是一个数字)
此外,FunC 有一种特殊类型的标识符,用反引号
`
引用。 在引号内,任何符号都是允许的,除了 \n
和引号本身。例如,
`I'm a variable too`
是一个有效的标识符,`any symbols ; ~ () are allowed here...`
也是。常量
FunC 允许定义编译时的常量,这些常量在编译期间被替换和预计算。
常量的定义格式为
const optional-type identifier = value-or-expression;
optional-type
可用于强制指定常量的特定类型,也用于更好的可读性。目前,支持
int
和 slice
类型。value-or-expression
可以是字面量或由字面量和常量组成的可预计算表达式。例如,可以这样定义常量:
const int101 = 101;
定义等同于数字字面量101
的int101
常量
const str1 = "const1", str2 = "aabbcc"s;
定义两个等于其对应字符串的常量
const int int240 = ((int1 + int2) * 10) << 3;
定义等于计算结果的int240
常量
const slice str2r = str2;
定义等于str2
常量值的str2r
常量
由于数字常量在编译期间被替换,所有在编译期间进行的优化和预计算都能成功执行(与旧方法通过内联 asm
PUSHINT
定义常量不同)。