🍋 Rex 编程语言

Rex 编程语言语法参考(二):库语法

本文档覆盖 Rex 标准库与运行时库函数:按命名空间组织的内置标准库(mathiofileospathstringrandomcollectionsdatetimetimethreadrememmapset)以及 FFI 扩展库(lib/json.rexlib/http.rexlib/crypto.rex)。 语言核心语法(类型、运算符、控制流、函数、数组、错误处理、泛型等)见《Rex 编程语言语法参考(一):语言基础语法》。 实战陷阱、性能优化、AOT、包管理、LSP、DAP、CLI 等工具与实现内容见《Rex 编程语言工具与实现参考》。

1. 标准库总览

标准库以命名空间形式内置在编译器中,无需 import,直接以 namespace.func(...) 调用:

命名空间说明示例
math数学运算math.sin(1.0)math.sqrt(16.0)
io输入输出io.read_line()io.write("hi")
file文件操作file.exists("a.txt")file.read("a.txt")
os操作系统os.getenv("PATH")os.get_pid()
path路径处理path.join("dir", "file.txt")
string字符串操作string.upper("hi")string.len("hi")
re正则表达式re.match("^h", "hi")re.replace("\\d", "#", s)
random随机数random.random()random.int(100)
collections集合操作collections.sort_int(arr, len)
datetime日期计算datetime.date()datetime.from_ymd(2025, 7, 29)
time时间函数time.now()time.sleep(100)
thread线程并发thread.spawn(fn, ...)thread.join(h)thread.atomic_add(c, 1)
mem裸指针读写mem.read_i32(p, 0)mem.write_float(p, 8, 3.14)
map字典操作map.set(m, "k", v)map.get(m, "k")map.len(m)
set集合操作set.create()set.add(s, x)set.has(s, x)set.len(s)

内存语义约定:返回 str 的运行时函数每次调用都会分配新字符串内存, 生命周期绑定当前函数栈帧,函数返回时自动释放(详见语言基础语法文档第 12 章「字符串内存管理」)。

2. 数学函数(Math)

通过 math. 命名空间使用,例如:math.sin(x: float) -> float

基础数学函数

函数签名描述
math.abs_int(int) -> int整数绝对值
math.abs_float(float) -> float浮点数绝对值
math.floor(float) -> int向下取整
math.ceil(float) -> int向上取整
math.round(float) -> int四舍五入
math.trunc(float) -> int截断小数部分

幂运算与对数

函数签名描述
math.pow(float, float) -> float幂运算 base^exp
math.sqrt(float) -> float平方根
math.cbrt(float) -> float立方根
math.exp(float) -> floate 的 x 次幂
math.log(float) -> float自然对数 ln(x)
math.log10(float) -> float以 10 为底的对数
math.log2(float) -> float以 2 为底的对数
math.log_base(float, float) -> float以 base 为底的对数

三角函数

函数签名描述
math.sin(float) -> float正弦函数(弧度)
math.cos(float) -> float余弦函数(弧度)
math.tan(float) -> float正切函数(弧度)
math.asin(float) -> float反正弦函数
math.acos(float) -> float反余弦函数
math.atan(float) -> float反正切函数
math.atan2(float, float) -> float双参数反正切函数

双曲函数

函数签名描述
math.sinh(float) -> float双曲正弦
math.cosh(float) -> float双曲余弦
math.tanh(float) -> float双曲正切
math.asinh(float) -> float反双曲正弦
math.acosh(float) -> float反双曲余弦
math.atanh(float) -> float反双曲正切

角度转换

函数签名描述
math.degrees(float) -> float弧度转角度
math.radians(float) -> float角度转弧度

符号与比较

函数签名描述
math.sign(float) -> int返回符号 (-1, 0, 1)
math.min(float, float) -> float返回较小值
math.max(float, float) -> float返回较大值
math.clamp(float, float, float) -> float将值限制在 [lo, hi] 范围内

数学常数

函数签名描述
math.pi() -> float圆周率 π
math.e() -> float自然常数 e
math.inf() -> float正无穷
math.nan() -> floatNaN

判断函数

函数签名描述
math.isfinite(float) -> int检查是否为有限数
math.isinf(float) -> int检查是否为无穷大
math.isnan(float) -> int检查是否为 NaN

其他数学函数

函数签名描述
math.modf(float) -> float返回小数部分
math.fmod(float, float) -> float浮点数取模
math.hypot(float, float) -> float欧几里得距离 sqrt(x² + y²)
math.ldexp(float, int) -> floatx * 2^exp
math.frexp(float) -> float返回尾数
math.factorial(int) -> int阶乘
math.gcd(int, int) -> int最大公约数
math.lcm(int, int) -> int最小公倍数
math.gamma(float) -> floatGamma 函数
math.lgamma(float) -> floatGamma 函数的自然对数
math.erf(float) -> float误差函数
math.erfc(float) -> float互补误差函数

入门示例:

rex
fn main() {
    // 基础:绝对值 / 取整
    print(math.abs_int(-5))            // 5
    print(math.floor(3.7))             // 3
    print(math.ceil(3.2))              // 4
    print(math.round(3.5))             // 4

    // 幂运算与对数
    print(math.sqrt(16.0))             // 4.0
    print(math.pow(2.0, 10.0))         // 1024.0
    print(math.log(math.e()))          // 1.0

    // 比较与限制
    print(math.max(1.0, 5.0))          // 5.0
    print(math.clamp(7.0, 0.0, 5.0))   // 5.0

    // 整数运算
    print(math.factorial(5))           // 120
    print(math.gcd(12, 18))            // 6
    print(math.pi())                   // 3.141592653589793
}

提示:math 函数参数多为 float,传入整数字面量会自动转换;返回 int 的函数(floor/ceil/round/abs_int/factorial/gcd/lcm)可直接用于整数运算。

3. 字符串函数(String)

内存语义:返回 str 的字符串函数(upper/lower/strip/lstrip/rstrip/reverse/replace/substr/repeat/concat/from_char/from_int/from_float/dup)每次调用都会分配新字符串内存,生命周期绑定当前函数栈帧,函数返回时自动释放(详见语言基础语法文档第 12 章「字符串内存管理」)。 例外:find_char/find_sub 返回源字符串内部指针(不分配新内存);copy/cat 写入调用方提供的缓冲区;len/find/count/char_at 等返回数值,不涉及内存管理。

大小写转换

函数签名描述
string.upper(str) -> str转换为大写
string.lower(str) -> str转换为小写

去除空白

函数签名描述
string.strip(str) -> str去除首尾空白
string.lstrip(str) -> str去除前导空白
string.rstrip(str) -> str去除尾部空白

字符串操作

函数签名描述
string.reverse(str) -> str反转字符串
string.replace(str, str, str) -> str替换所有匹配子串
string.substr(str, int, int) -> str截取子串
string.repeat(str, int) -> str重复字符串 n 次
string.concat(str, str) -> str连接两个字符串

StringBuilder(高效循环拼接)

实战要点string.concat 每次调用都全量 strdup 拷贝,循环拼接是严格的 O(n²)(文档已明确警告)。 需要循环组装大字符串(日志、JSON 响应、CSV 等)时,务必使用 StringBuilder: 追加过程零分配,仅在 tostr 时一次性分配结果,循环拼接降为 O(n)。

函数签名描述
string.builder_create() -> int创建构建器,返回句柄(i64)
string.builder_append(int, str) -> void向构建器追加字符串(字节级追加,不产生中间分配)
string.builder_tostr(int) -> str取构建器当前内容,strdup 为帧管理字符串(后续 append 不影响已返回结果)
string.builder_free(int) -> void释放构建器
rex
fn build_json() -> str {
    let b: int = string.builder_create()
    defer string.builder_free(b)      // defer 保证释放
    string.builder_append(b, "{\"items\": [")
    var i: int = 0
    while i < 10000 {
        string.builder_append(b, string.from_int(i))
        string.builder_append(b, ",")
        i = i + 1
    }
    string.builder_append(b, "]}")
    return string.builder_tostr(b)    // 仅此处分配一次,O(n)
}

字符串查找

函数签名描述
string.find(str, str) -> int查找子串位置(未找到返回 -1);返回 Unicode 码点索引(非字节偏移),UTF-8 中文按 1 个码点计
string.rfind(str, str) -> int从右向左查找子串位置(返回码点索引)
string.count(str, str) -> int统计子串出现次数
string.contains(str, str) -> int检查是否包含子串

索引单位陷阱string.find/rfind/char_at 的索引是 Unicode 码点索引,与 string.substr(按码点截取)一致; 但 string.len 返回的是字节数(strlen)。两者单位不同,不能混用——string.substr(s, string.find(s, x), string.len(x)) 在含中文时长度会算错 (字节数 > 码点数)。涉及非 ASCII 文本,长度统一用 string.codepoint_len,勿用 string.len 作为索引/长度参数。

字符串判断

函数签名描述
string.isalpha(str) -> int检查是否只包含字母
string.isdigit(str) -> int检查是否只包含数字
string.isalnum(str) -> int检查是否只包含字母和数字
string.isspace(str) -> int检查是否只包含空白字符
string.isupper(str) -> int检查是否全为大写
string.islower(str) -> int检查是否全为小写
string.isempty(str) -> int检查是否为空
string.startswith(str, str) -> int检查是否以指定前缀开头
string.endswith(str, str) -> int检查是否以指定后缀结尾

字符串比较

函数签名描述
string.len(str) -> int获取字符串字节长度(strlen,不含结尾空字符);UTF-8 中文每字 3 字节
string.codepoint_len(str) -> int获取字符串的 Unicode 码点数量(UTF-8 解码后);"中文" 返回 2
string.compare(str, str) -> int比较两个字符串(返回 -1, 0, 1)
string.equals(str, str) -> int检查两个字符串是否相等
string.cmp(str, str) -> intC 风格字符串比较(strcmp)
string.find_char(str, int) -> str查找字符,返回从该字符开始的子串指针
string.find_sub(str, str) -> str查找子串,返回从子串开始的指针
string.copy(str, str) -> str复制字符串到目标缓冲区(strcpy)
string.cat(str, str) -> str追加字符串到目标缓冲区(strcat)
string.dup(str) -> str复制字符串(动态分配,strdup)

字符操作

函数签名描述
string.char_at(str, int) -> int获取指定位置(码点索引)的字符码点;越界返回 0
string.from_char(int) -> str从字符码创建单字符字符串
string.first(str) -> int获取第一个字符
string.last(str) -> int获取最后一个字符

类型转换

函数签名描述
string.toint(str) -> int字符串转整数
string.tofloat(str) -> float字符串转浮点数
string.from_int(int) -> str整数转字符串
string.from_float(float) -> str浮点数转字符串

入门示例:

rex
fn main() {
    // 大小写与去除空白
    print(string.upper("hello"))          // HELLO
    print(string.lower("WORLD"))          // world
    print(string.strip("  hi  "))         // hi

    // 截取 / 替换 / 重复
    print(string.substr("hello", 1, 3))   // ell
    print(string.replace("a-b-c", "-", "+")) // a+b+c
    print(string.repeat("ab", 3))         // ababab

    // 查找与判断(返回 1/0)
    print(string.find("hello", "ll"))     // 2
    print(string.contains("hello", "ell")) // 1
    print(string.startswith("hello", "he")) // 1

    // 类型转换
    print(string.toint("42") + 1)         // 43
    print(string.from_int(7))             // 7
    print(string.from_float(3.5))         // 3.5
}

提示:find/rfind/char_at/substr 使用 Unicode 码点索引,而 string.len 返回字节数;涉及中文时统一用 string.codepoint_len 取长度(见上方「索引单位陷阱」)。

4. I/O 函数(IO)

标准输入

函数签名描述
io.read_line() -> str从标准输入读取一行
io.read_int() -> int从标准输入读取整数
io.read_float() -> float从标准输入读取浮点数
io.read_char() -> int从标准输入读取一个字符
io.read_all() -> str从标准输入读取所有内容

标准输出

函数签名描述
io.write_line(str) -> int写入一行到标准输出
io.write(str) -> int写入到标准输出(不带换行)
io.write_int(int) -> int写入整数到标准输出
io.write_float(float) -> int写入浮点数到标准输出
io.write_char(int) -> int写入字符到标准输出

标准错误

函数签名描述
io.error_line(str) -> int写入一行到标准错误
io.error(str) -> int写入到标准错误(不带换行)

流式文件操作

函数签名描述
io.open(str, str) -> int打开文件,返回文件句柄
io.close(int) -> int关闭文件
io.file_read_line(int) -> str从文件读取一行
io.file_read_all(int) -> str读取文件全部内容
io.file_write(int, str) -> int写入文件
io.file_write_line(int, str) -> int写入一行到文件
io.file_eof(int) -> int检查是否到达文件末尾
io.file_flush(int) -> int刷新文件缓冲区

批量操作

函数签名描述
io.read_lines(str) -> str读取文件所有行
io.write_lines(str, str) -> int写入多行到文件
io.count_lines(str) -> int统计文件行数

入门示例(命令行问答小程序):

rex
fn main() {
    io.write_line("请输入你的名字:")
    let name: str = io.read_line()
    io.write("你好, ")
    io.write_line(name)                        // 输出到标准输出

    io.write_line("请输入一个整数:")
    let n: int = io.read_int()
    io.write_line(string.concat("n * 2 = ", string.from_int(n * 2)))

    io.error_line("这是一条错误信息")            // 写入标准错误
}

提示:io.write 不带换行、io.write_line 自动追加换行;read_int/read_float 会跳过空白直接解析数值。流式文件句柄操作(io.open/file_read_line/close)适合逐行处理大文件,见下节 file 的整读整写用法。

5. 文件函数(File)

文件读写

函数签名描述
file.read(str) -> str读取文件全部内容
file.read_bytes(str, ptr, int) -> int读取文件到缓冲区
file.write(str, str) -> int写入文件(覆盖)
file.append(str, str) -> int追加写入文件
file.write_bytes(str, ptr, int) -> int写入字节数组

文件信息

函数签名描述
file.exists(str) -> int检查文件是否存在
file.size(str) -> int获取文件大小
file.is_dir(str) -> int检查是否为目录
file.is_file(str) -> int检查是否为文件

文件操作

函数签名描述
file.delete(str) -> int删除文件
file.copy(str, str) -> int复制文件
file.move(str, str) -> int移动文件
file.rename(str, str) -> int重命名文件

目录操作

函数签名描述
file.mkdir(str) -> int创建目录
file.rmdir(str) -> int删除空目录
file.list(str) -> str列出目录内容
file.list_files(str) -> str列出目录中的文件
file.list_dirs(str) -> str列出目录中的子目录

路径操作

函数签名描述
file.getcwd() -> str获取当前工作目录
file.chdir(str) -> int切换工作目录
file.abs_path(str) -> str获取绝对路径
file.join(str, str) -> str连接路径
file.basename(str) -> str获取文件名
file.dirname(str) -> str获取目录名
file.extname(str) -> str获取扩展名

入门示例:

rex
fn main() {
    // 写入 / 读取
    file.write("data.txt", "hello rex")
    print(file.exists("data.txt"))            // 1
    print(file.read("data.txt"))              // hello rex

    // 追加与信息
    file.append("data.txt", "\nline2")
    print(file.size("data.txt"))              // 字节数(含换行)
    print(file.is_file("data.txt"))           // 1

    // 文件操作
    file.rename("data.txt", "data2.txt")
    file.delete("data2.txt")

    // 目录操作
    file.mkdir("mydir")
    print(file.is_dir("mydir"))               // 1
    file.rmdir("mydir")

    // 路径操作
    print(file.basename("a/b/c.txt"))         // c.txt
    print(file.extname("a/b/c.txt"))          // .txt
}

提示:file.read/file.write 一次读写整个文件,适合配置文件、小文本;大文件逐行处理用 io.open + io.file_read_line(见第 4 章)。返回的字符串由帧自动管理,无需手动释放。

6. 操作系统函数(OS)

环境变量

函数签名描述
os.getenv(str) -> str获取环境变量
os.setenv(str, str) -> int设置环境变量
os.unsetenv(str) -> int删除环境变量
os.getenv_keys() -> str获取所有环境变量名

用户信息

函数签名描述
os.get_username() -> str获取当前用户名
os.get_homedir() -> str获取用户主目录
os.get_user_cache_dir() -> str获取用户缓存目录
os.get_user_config_dir() -> str获取用户配置目录
os.get_user_data_dir() -> str获取用户数据目录

系统信息

函数签名描述
os.get_platform() -> str获取操作系统平台名称
os.get_system() -> str获取操作系统名称
os.get_release() -> str获取操作系统版本
os.get_version() -> str获取操作系统详细版本
os.get_machine() -> str获取机器架构
os.get_processor() -> str获取处理器信息
os.get_hostname() -> str获取主机名
os.get_cpu_count() -> int获取 CPU 核心数
os.get_loadavg() -> str获取系统负载平均值

进程管理

函数签名描述
os.get_pid() -> int获取当前进程 ID
os.get_ppid() -> int获取父进程 ID
os.exec(str) -> int执行系统命令并返回退出码
os.exec_output(str) -> str执行系统命令并返回输出
os.sleep(int) -> int休眠指定毫秒数
os.exit(int) -> void退出程序

临时文件

函数签名描述
os.temp_dir() -> str获取临时目录路径
os.temp_filename() -> str生成临时文件名
os.temp_dirname() -> str生成临时目录名

磁盘空间

函数签名描述
os.disk_free(str) -> int获取磁盘剩余空间
os.disk_total(str) -> int获取磁盘总空间
os.disk_used(str) -> int获取磁盘已用空间

路径扩展

函数签名描述
os.expanduser(str) -> str扩展路径中的 ~
os.expandvars(str) -> str扩展路径中的环境变量

权限与属性

函数签名描述
os.chmod(str, int) -> int修改文件权限
os.get_modtime(str) -> int获取文件修改时间
os.set_modtime(str, int) -> int设置文件修改时间

命令行参数

函数签名描述
os.get_argc() -> int获取命令行参数数量
os.get_arg(int) -> str获取指定索引的命令行参数
os.get_args() -> str获取所有命令行参数

实用函数

函数签名描述
os.get_random_bytes(int) -> str获取随机字节(十六进制)
os.is_admin() -> int检查是否以管理员权限运行

入门示例:

rex
fn main() {
    // 环境变量
    os.setenv("MY_VAR", "123")
    print(os.getenv("MY_VAR"))               // 123

    // 系统信息
    print(os.get_platform())                 // 例如 win32
    print(os.get_cpu_count())                // 例如 8
    print(os.get_pid())                      // 当前进程 ID

    // 执行系统命令
    let out: str = os.exec_output("echo hello")
    print(out)                               // hello
}

提示:os.exec 返回命令退出码、os.exec_output 返回命令输出文本;os.sleep(ms)time.sleep(ms) 等价。注意 os.setenv 只影响当前进程的环境变量。

7. 随机数函数(Random)

基础随机数

函数签名描述
random.random() -> float返回 [0.0, 1.0) 范围内的随机浮点数
random.int(int) -> int返回 [0, max) 范围内的随机整数
random.range(int, int) -> int返回 [min, max) 范围内的随机整数

范围随机数

函数签名描述
random.uniform(float, float) -> float返回 [min, max) 范围内的随机浮点数
random.int_range(int, int) -> int返回 [min, max] 范围内的随机整数(包含两端)

随机种子

函数签名描述
random.seed(int) -> void设置随机数生成器种子

特殊分布

函数签名描述
random.gauss(float, float) -> float生成高斯分布随机数
random.expovariate(float) -> float生成指数分布随机数
random.triangular(float, float, float) -> float生成三角分布随机数

入门示例:

rex
fn main() {
    random.seed(42)                          // 固定种子,结果可复现
    print(random.random())                   // [0.0, 1.0) 随机浮点
    print(random.int(100))                   // [0, 100) 随机整数
    print(random.range(10, 20))              // [10, 20) 随机整数
    print(random.int_range(1, 6))            // [1, 6],掷骰子
    print(random.uniform(0.0, 1.0))          // [0.0, 1.0) 均匀浮点
}

提示:不调用 random.seed 时以系统熵初始化,每次运行结果不同;需要可复现的测试数据(如单元测试)时先 random.seed(n)

8. 日期函数(Datetime)

所有日期函数使用 Unix 时间戳(秒)作为日期表示。

日期创建

函数签名描述
datetime.date() -> int获取当前日期时间戳
datetime.from_ymd(int, int, int) -> int从年月日创建日期
datetime.from_timestamp(int) -> int从时间戳创建日期

日期加法

函数签名描述
datetime.add_days(int, int) -> int日期加天数
datetime.add_weeks(int, int) -> int日期加周数
datetime.add_months(int, int) -> int日期加月数(自动处理月末)
datetime.add_years(int, int) -> int日期加年数

日期减法

函数签名描述
datetime.sub_days(int, int) -> int日期减天数
datetime.sub_weeks(int, int) -> int日期减周数
datetime.sub_months(int, int) -> int日期减月数
datetime.sub_years(int, int) -> int日期减年数

日期差计算

函数签名描述
datetime.diff_days(int, int) -> int计算两个日期之间的天数差
datetime.diff_weeks(int, int) -> int计算两个日期之间的周数差
datetime.diff_months(int, int) -> int计算两个日期之间的月数差

日期比较

函数签名描述
datetime.compare(int, int) -> int比较两个日期(返回 -1, 0, 1)
datetime.is_before(int, int) -> int判断 date1 是否在 date2 之前
datetime.is_after(int, int) -> int判断 date1 是否在 date2 之后
datetime.is_same(int, int) -> int判断两个日期是否相同
datetime.is_between(int, int, int) -> int判断日期是否在范围内

日期范围判断

函数签名描述
datetime.is_weekend(int) -> int判断是否为周末
datetime.is_weekday(int) -> int判断是否为工作日
datetime.is_leap_year_for(int) -> int判断指定年份是否为闰年
datetime.days_in_month(int, int) -> int获取指定月份的天数
datetime.is_last_day_of_month(int) -> int判断是否为当月最后一天
datetime.is_first_day_of_month(int) -> int判断是否为当月第一天

日期获取

函数签名描述
datetime.get_year(int) -> int获取年份
datetime.get_month(int) -> int获取月份
datetime.get_day(int) -> int获取日期
datetime.get_weekday(int) -> int获取星期几 (1=周一, 7=周日)
datetime.get_yearday(int) -> int获取年份第几天
datetime.get_week_of_year(int) -> int获取年份第几周
datetime.get_quarter(int) -> int获取季度

日期边界

函数签名描述
datetime.start_of_week(int) -> int获取本周周一
datetime.end_of_week(int) -> int获取本周周日
datetime.start_of_month(int) -> int获取本月第一天
datetime.end_of_month(int) -> int获取本月最后一天
datetime.start_of_year(int) -> int获取本年第一天
datetime.end_of_year(int) -> int获取本年最后一天

特殊日期判断

函数签名描述
datetime.is_today(int) -> int判断是否为今天
datetime.is_yesterday(int) -> int判断是否为昨天
datetime.is_tomorrow(int) -> int判断是否为明天
datetime.days_until(int, int) -> int计算距离目标日期还有多少天
datetime.days_since(int, int) -> int计算从目标日期已过多少天

入门示例:

rex
fn main() {
    // 创建日期(内部为 Unix 时间戳,秒)
    let d: int = datetime.from_ymd(2025, 7, 29)
    print(datetime.get_year(d))              // 2025
    print(datetime.get_month(d))             // 7
    print(datetime.get_day(d))               // 29
    print(datetime.get_weekday(d))           // 2(2025-07-29 是周二)

    // 日期运算
    let next: int = datetime.add_days(d, 7)
    print(datetime.diff_days(next, d))       // 7

    // 判断与边界
    print(datetime.is_weekend(d))            // 0(周二)
    print(datetime.is_leap_year_for(2024))   // 1
    print(datetime.days_in_month(2024, 2))   // 29(闰年 2 月)
    print(datetime.get_quarter(d))           // 3(第三季度)
}

提示:所有日期函数都以秒级时间戳(int)表示日期,读取字段用 get_year/get_month/get_day 等;需要格式化输出字符串用 time.format_datetime()(见第 10 章)。

9. 集合函数(Collections)

数组排序

函数签名描述
collections.sort_int(ptr, int) -> void原地排序整数数组(升序)
collections.sort_desc_int(ptr, int) -> void原地排序整数数组(降序)
collections.sort_float(ptr, int) -> void原地排序浮点数数组
collections.sorted_int(ptr, int) -> ptr返回排序后的新数组

数组反转

函数签名描述
collections.reverse_int(ptr, int) -> void原地反转整数数组
collections.reversed_int(ptr, int) -> ptr返回反转后的新数组

数组填充

函数签名描述
collections.fill_int(ptr, int, int) -> void用指定值填充数组
collections.fill_range_int(ptr, int, int, int) -> void填充指定范围

数组复制

函数签名描述
collections.copy_int(ptr, int) -> ptr复制数组
collections.copy_range_int(ptr, int, int) -> ptr复制指定范围

数组去重

函数签名描述
collections.unique_int(ptr, int) -> ptr返回去重后的新数组
collections.unique_count_int(ptr, int) -> int返回唯一元素个数

数组查找

函数签名描述
collections.find_int(ptr, int, int) -> int查找值,返回索引
collections.find_last_int(ptr, int, int) -> int从右查找值,返回索引
collections.count_int(ptr, int, int) -> int统计值出现次数
collections.contains_int(ptr, int, int) -> int检查是否包含值

二分查找

函数签名描述
collections.binary_search_int(ptr, int, int) -> int二分查找,返回索引
collections.lower_bound_int(ptr, int, int) -> int返回第一个不小于 value 的索引
collections.upper_bound_int(ptr, int, int) -> int返回第一个大于 value 的索引

数组统计

函数签名描述
collections.min_int(ptr, int) -> int返回最小值
collections.max_int(ptr, int) -> int返回最大值
collections.sum_int(ptr, int) -> int返回元素之和
collections.avg_int(ptr, int) -> float返回平均值

数组变换

函数签名描述
collections.map_int(ptr, int, int) -> ptr每个元素乘以因子
collections.filter_positive_int(ptr, int) -> ptr过滤出正数
collections.filter_negative_int(ptr, int) -> ptr过滤出负数

数组合并

函数签名描述
collections.merge_int(ptr, int, ptr, int) -> ptr合并两个数组
collections.merge_sorted_int(ptr, int, ptr, int) -> ptr合并两个已排序数组

数组切片

函数签名描述
collections.slice_int(ptr, int, int) -> ptr返回数组切片

数组比较

函数签名描述
collections.equals_int(ptr, int, ptr, int) -> int比较两个数组是否相等

计数器功能

函数签名描述
collections.counter_most_common(ptr, int, int) -> ptr返回出现次数最多的前 n 个元素
collections.counter_count(ptr, int, int) -> int统计指定值出现次数

入门示例:

rex
fn main() {
    var arr: int[] = [64, 34, 25, 12, 22, 11]

    // 原地排序(升序),结果写回原数组
    collections.sort_int(arr, 6)
    print(arr[0])                            // 11(最小值)
    print(arr[5])                            // 64(最大值)

    // 查找与统计
    print(collections.find_int(arr, 6, 25))  // 2
    print(collections.min_int(arr, 6))       // 11
    print(collections.max_int(arr, 6))       // 64
    print(collections.sum_int(arr, 6))       // 168
}

提示:collections 的入参是「数组 + 元素个数」两个参数(数组按指针传递);sort_*/reverse_*/fill_* 为原地操作,sorted_*/reversed_*/slice_*/unique_* 返回新数组(由帧自动管理)。

10. 时间函数(Time)

函数签名描述
time.now() -> int当前时间戳(毫秒)
time.clock() -> float高精度时钟(秒)
time.elapsed(int) -> int从 start 开始的已过毫秒数
time.sleep(int) -> void休眠指定毫秒数
time.sleep_seconds(float) -> void休眠指定秒数
time.unix() -> intUnix 时间戳(秒)
time.unix_nano() -> intUnix 时间戳(纳秒)
time.from_unix(int) -> intUnix 秒转毫秒
time.to_unix(int) -> int毫秒转 Unix 秒
time.year() -> int当前年份
time.month() -> int当前月份
time.day() -> int当前日
time.hour() -> int当前小时
time.minute() -> int当前分钟
time.second() -> int当前秒
time.millisecond() -> int当前毫秒
time.weekday() -> int当前星期几
time.yearday() -> int当前年内第几天
time.is_leap_year() -> int当前年是否为闰年
time.timezone_offset() -> int时区偏移
time.utc_offset() -> intUTC 偏移
time.stopwatch_start() -> float启动秒表
time.stopwatch_elapsed(float) -> float秒表已过秒数
time.stopwatch_elapsed_ms(float) -> int秒表已过毫秒数
time.cpu_time() -> floatCPU 时间
time.thread_time() -> float线程时间
time.millis_to_seconds(int) -> float毫秒转秒
time.seconds_to_millis(float) -> int秒转毫秒
time.format_date() -> str格式化日期
time.format_time() -> str格式化时间
time.format_datetime() -> str格式化日期时间

入门示例:

rex
fn main() {
    let start: int = time.now()              // 毫秒时间戳
    print(time.year())                       // 当前年份
    print(time.hour())                       // 当前小时
    print(time.format_datetime())            // 如 2026-08-05 14:30:00
    time.sleep(100)                          // 休眠 100 毫秒
    print(time.elapsed(start))               // >= 100
}

提示:time.now() 返回毫秒时间戳、time.unix() 返回秒时间戳,time.elapsed(start) 是常见的耗时统计组合(见基础语法文档第 24 章「斐波那契数列」示例);秒表用 stopwatch_start() + stopwatch_elapsed_ms()

11. 线程并发函数(Thread)

Rex 的并发模型是真实操作系统线程thread.spawn 在 OS 线程中执行 JIT 编译的 Rex 函数, 配合 thread.join 回收结果、互斥锁保证临界区互斥、原子计数器做无锁累加。

通过 thread. 命名空间使用,无需 import

线程创建与回收

函数签名描述
thread.spawn(fn, args...) -> int创建 OS 线程执行 fn,返回线程句柄;编译器自动生成线程入口包装函数(帧管理、参数搬运、结果写回)
thread.join(int) -> int等待线程结束并返回返回值(int/boolvoid 返回 0)
thread.join_float(int) -> float等待线程结束并返回 float 返回值
thread.sleep(int) -> void当前线程休眠(毫秒)
thread.current_id() -> int返回当前线程标识
rex
fn worker(a: int, b: int) -> int {
    return a * 1000 + b
}

fn float_worker(x: float) -> float {
    return x * 2.5
}

fn main() {
    let h1: int = thread.spawn(worker, 1, 2)
    let r1: int = thread.join(h1)   // 1002

    // 多线程并行
    let ha: int = thread.spawn(worker, 1, 1)
    let hb: int = thread.spawn(worker, 2, 2)
    let total: int = thread.join(ha) + thread.join(hb)  // 3003

    // float 返回值用 join_float
    let hf: int = thread.spawn(float_worker, 3.5)
    let rf: float = thread.join_float(hf)   // 8.75

    // 线程内休眠(必须 join,见下方注意事项)
    let hs: int = thread.spawn(worker, 9, 9)
    thread.sleep(100)
    thread.join(hs)
}

互斥锁

函数签名描述
thread.mutex_create() -> int创建互斥锁,返回句柄
thread.mutex_lock(int) -> void加锁(阻塞等待;等待期间释放 GIL,其他线程可并行)
thread.mutex_unlock(int) -> void解锁
thread.mutex_destroy(int) -> void销毁互斥锁
rex
let mid: int = thread.mutex_create()
let h1: int = thread.spawn(mutex_worker, mid)
let h2: int = thread.spawn(mutex_worker, mid)
thread.join(h1)
thread.join(h2)
thread.mutex_destroy(mid)

原子计数器(无锁累加)

函数签名描述
thread.counter_create() -> ptr分配一个 8 字节原子计数器,返回指针
thread.atomic_add(ptr, int) -> int原子加(LLVM atomicrmw),返回旧值
thread.atomic_get(ptr) -> int原子读取当前值
thread.counter_free(ptr) -> void释放计数器
rex
fn counter_worker(n: int, counter: ptr) -> int {
    var i: int = 0
    while i < n {
        thread.atomic_add(counter, 1)
        i = i + 1
    }
    return 0
}

let counter: ptr = thread.counter_create()
let h1: int = thread.spawn(counter_worker, 1000, counter)
let h2: int = thread.spawn(counter_worker, 1000, counter)
let h3: int = thread.spawn(counter_worker, 1000, counter)
thread.join(h1)
thread.join(h2)
thread.join(h3)
print(thread.atomic_get(counter))   // 3000
thread.counter_free(counter)

限制与注意事项

参数仅限 int/float/bool/ptr一维标量数组int[]/float[]/bool[]), 返回值仅限 int/float/bool/void,最多 8 个参数。 字符串、多维数组、结构体数组等帧管理内存禁止跨线程传递(编译期报错)。

编译器在 spawn 调用点深拷贝一份数组快照,子线程读写的是自己的副本, 与主线程数据完全隔离,天然线程安全;子线程返回后快照自动释放。 大数组拷贝有 O(n) 开销,适合分片并行(map-reduce)等"只读分发给子线程"场景; 需要跨线程共享可变数据的场景请改用 ptr + 原子计数器/互斥锁。

push/pop,互不干扰。线程内未捕获异常与主线程行为一致(打印回溯并终止进程)。

JIT 模块可能被回收,导致仍在运行的线程崩溃。

有效(如 counter_free 在所有线程 join 之后再调用)。

线程内调用 Python 侧运行时函数(字符串操作等)时会短暂重获 GIL。

12. 正则表达式函数(Regex)

对标 Python re 模块的核心功能。通过 re. 命名空间使用,无需 import。 底层基于 Python 的 re 模块实现,支持标准正则语法(\d\w[]() 等)。

内存语义:返回 str 的正则函数(find/findall/replace/split/escape)每次调用都会 分配新字符串内存,生命周期绑定当前函数栈帧,函数返回时自动释放(见语言基础语法文档第 12 章)。 findall/split 返回多个结果时以换行符 \n 分隔(约定同 file.list)。

匹配判断(返回 1/0)

函数签名描述
re.match(str, str) -> int从字符串开头匹配,成功返回 1,失败返回 0(对标 re.match
re.search(str, str) -> int在字符串任意位置搜索,成功返回 1,失败返回 0(对标 re.search
re.fullmatch(str, str) -> int整个字符串必须完全匹配,成功返回 1,失败返回 0(对标 re.fullmatch
rex
re.match("Hello", "Hello World")               // 1
re.match("World", "Hello World")               // 0(match 只从头匹配)
re.search("World", "Hello World")              // 1
re.fullmatch("Hello World", "Hello World")     // 1
re.fullmatch("Hello", "Hello World")           // 0

匹配提取

函数签名描述
re.find(str, str) -> str返回第一个匹配的子串,未找到返回空字符串
re.findall(str, str) -> str返回所有匹配的子串,以 \n 分隔(对标 re.findall
re.replace(str, str, str) -> str将文本中所有匹配替换为指定文本(对标 re.sub
re.split(str, str) -> str按正则表达式分割字符串,各段以 \n 分隔(对标 re.split
rex
re.find("\\d+", "abc123def456")      // "123"
re.findall("\\d+", "a1b22c333")      // "1\n22\n333"
re.replace("\\d+", "#", "a1b22c333") // "a#b#c#"
re.split("[,\\s]+", "a, b,c  d")     // "a\nb\nc\nd"

工具函数

函数签名描述
re.escape(str) -> str转义正则表达式中的特殊字符,使其按字面量匹配(对标 re.escape
re.is_valid(str) -> int检查模式是否合法,合法返回 1,非法(如未闭合 [)返回 0
rex
re.escape("a.b+c")   // "a\.b\+c"
re.is_valid("\\d+")  // 1
re.is_valid("[")     // 0

与 Python re 的差异

13. 内存读写函数(mem)

实战要点:Rex 的 ptr 是裸 i8*,语言内无法解引用 C 结构体字段。 mem 命名空间提供按偏移读写裸指针内存的能力,简单 C 结构体字段访问 无需再编写 C shim(配合语言基础语法文档第 17 章 FFI 使用)。

函数签名描述
mem.read_i32(ptr, int) -> int读取 ptr+offset 处的 32 位有符号整数
mem.read_i64(ptr, int) -> int读取 ptr+offset 处的 64 位有符号整数
mem.read_float(ptr, int) -> float读取 ptr+offset 处的 64 位双精度浮点数
mem.read_str(ptr) -> str读取以 \0 结尾的 C 字符串(strdup 到帧池,自动管理)
mem.read_bytes(ptr, int) -> str读取 len 字节(strdup 到帧池)
mem.write_i32(ptr, int, int) -> void写入 32 位有符号整数
mem.write_i64(ptr, int, int) -> void写入 64 位有符号整数
mem.write_float(ptr, int, float) -> void写入 64 位双精度浮点数

辅助转换:整数地址与 ptr 互相转换用 asinttoptr/ptrtoint): mem.read_str(name_ptr as ptr)let addr: int = some_ptr as int

rex
// 读取 cJSON 节点(C 结构体)的 type 字段:next=0, prev=8, child=16, type=24
let root: ptr = json_parse(text)
let type_field: int = mem.read_i32(root, 24)

// 读取字符串节点的 valuestring(char* 指针,偏移 32)
let name_node: ptr = json_get(root, "name")
let name_ptr: int = mem.read_i64(name_node, 32)   // char* 地址
let name_val: str = mem.read_str(name_ptr as ptr)  // 读取 C 字符串

偏移量以字节为单位;读写不会做边界检查,越界访问属于未定义行为(C 语义), 仅应在已知布局的 C 结构体/缓冲区上使用。read_str/read_bytes 返回的字符串 参与帧管理,函数返回时自动释放。

14. Map 字典函数(map)

Map[str, V] 的运行时操作通过 map. 命名空间调用(无需 import)。 编译器按 Map 变量的声明值类型(V)自动分派到底层实现,用户无需关心。 (Map 类型的声明、生命周期与所有权语义见语言基础语法文档第 13 章。)

函数签名描述
map.create() -> int创建空 Map,返回句柄(等价于 {} 字面量)
map.set(Map, str, V) -> void写入键值(V 为 Map 声明的值类型;字符串值拷贝存储)
map.get(Map, str) -> V读取值;缺键返回默认值(int→0、float→0.0、str→空串)
map.has(Map, str) -> bool检查键是否存在
map.len(Map) -> int返回键值对数量
map.delete(Map, str) -> bool删除键,返回是否删除成功
map.keys(Map) -> str返回所有键(换行分隔的帧管理字符串)
map.clear(Map) -> void清空所有键值对
map.free(Map) -> void提前释放 Map(可省略,函数返回时帧自动释放)
rex
var m: Map[str, int] = {}
map.set(m, "a", 1)
map.set(m, "b", 2)
if map.has(m, "a") {
    print(map.get(m, "a"))   // 1
}
print(map.len(m))            // 2
map.free(m)

值类型约束Map[str, int] / Map[str, float] / Map[str, str] 三种组合可用; 使用 Map[int, ...](非字符串键)或其他值类型会得到编译错误。 缺键语义map.get 对缺键返回默认值,需要区分"缺键"与"值为默认值"时先 map.has内存语义:见语言基础语法文档第 13 章「Map 字典」(帧生命周期 + 单所有者隐式移动 + 返回值自动移交)。

15. Set 集合函数(set)

Set[T] 的运行时操作通过 set. 命名空间调用(无需 import)。 编译器按 Set 变量的声明元素类型(T)自动分派到底层实现,用户无需关心。 所有操作均支持方法糖(s.add(x)set.add(s, x))。 (Set 类型的声明、生命周期与所有权语义见语言基础语法文档第 14 章。)

函数签名描述
set.create() -> int创建空 Set,返回句柄
set.add(Set, T) -> void添加元素(T 为 Set 声明的元素类型;重复添加不生效)
set.remove(Set, T) -> bool删除元素,返回是否原本存在
set.has(Set, T) -> bool检查元素是否存在
set.len(Set) -> int返回元素数量
set.clear(Set) -> void清空所有元素
set.free(Set) -> void提前释放 Set(可省略,函数返回时帧自动释放)
rex
var s: Set[int] = set.create()
set.add(s, 10)
if set.has(s, 10) {
    print(set.len(s))   // 1
}
set.free(s)

元素类型约束Set[int] / Set[float] / Set[str] 三种组合可用; 其他元素类型会得到编译错误。 内存语义:见语言基础语法文档第 14 章「Set 集合」(帧生命周期 + 单所有者隐式移动 + 返回值自动移交)。

16. JSON、HTTP 与加密库(FFI 扩展库)

以下库是用户级 Rex 库(非编译器内置),通过 FFI 绑定成熟的 C 库/纯 C shim 实现:

  • lib/json.rex:绑定 cJSON(C 语言 JSON 库)
  • lib/http.rex:绑定 libcurl(C 语言 HTTP 客户端库,Windows 上经 Schannel 原生 TLS 支持 https)
  • lib/crypto.rex:绑定 crypto_helper.dll(纯 C 自实现的哈希/HMAC/AES/Base64/Hex,无外部依赖)

原生依赖(native/ 目录):cjson.dlllibcurl.dllcurl_helper.dllcrypto_helper.dll,由 gcc 编译。 使用前提(JIT 模式):当前工作目录包含 native/ 目录(DLL 通过相对路径 native/<库名> 加载)。

AOT 模式(rex build:三个库全部静态链接进 exe,无需任何 DLL—— cJSON 由 native/cJSON.c + native/json_helper.c、crypto 由 native/crypto_helper.c、 http 由 native/curl_helper.c + 静态 libcurl_static.a(Schannel TLS,支持 https) 提供;AOT exe 可独立分发。

16.1 导入方式

rex
// 必须整模块导入!
// selective import(如 import json_parse from "lib/json.rex")会过滤掉 extern 声明,导致链接失败
import "lib/json.rex"
import "lib/http.rex"

16.2 JSON 库(lib/json.rex)

所有函数以 json_ 前缀命名。节点类型统一为 ptr

分类函数说明
解析/释放json_parse(text: str) -> ptr解析 JSON,失败返回 null(用 json_error() 查原因)
json_free(node: ptr)释放整棵 JSON 树
json_error() -> str最近一次解析出错的位置描述
序列化json_print(node: ptr) -> str格式化输出(带缩进)
json_print_min(node: ptr) -> str紧凑输出
类型判断json_is_object/array/string/number/bool/null/true/false(node: ptr) -> int类型检查
json_type(node: ptr) -> int类型位掩码(json_type_object() 等常量函数)
读取json_get(obj: ptr, key: str) -> ptr取对象键对应的子节点(不存在返回 null)
json_get_at(arr: ptr, index: int) -> ptr取数组元素(越界返回 null)
json_size(arr: ptr) -> int数组元素个数
json_string(node: ptr) -> str字符串节点的值
json_number(node: ptr) -> float数字节点的值
json_bool_value(node: ptr) -> int布尔节点的值(1/0)
遍历json_child(node: ptr) -> ptr / json_next(node: ptr) -> ptr遍历子节点链表
json_key(node: ptr) -> str节点键名(对象成员名)
构建json_obj()/json_arr()/json_str()/json_num()/json_bool()/json_null() -> ptr创建节点
json_add_obj(obj, key, item) -> int / json_add_arr(arr, item) -> int挂载子节点(所有权转移给父节点)

内存规则

示例

rex
import "lib/json.rex"

fn main() {
    // 解析
    let root: ptr = json_parse("{\"name\": \"Rex\", \"age\": 30, \"tags\": [\"a\", \"b\"]}")
    if root == null {
        print("解析失败:", json_error())
        return
    }
    print(json_string(json_get(root, "name")))       // Rex
    print(json_number(json_get(root, "age")) as int) // 30

    // 遍历数组
    let tags: ptr = json_get(root, "tags")
    for i in range(0, json_size(tags)) {
        print(json_string(json_get_at(tags, i)))
    }

    // 构建
    let obj: ptr = json_obj()
    json_add_obj(obj, "id", json_num(1.0))
    json_add_obj(obj, "ok", json_bool(1))
    print(json_print_min(obj))                        // {"id":1,"ok":true}

    json_free(root)
    json_free(obj)
}

16.3 HTTP 库(lib/http.rex)

所有函数以 http_ 前缀命名。请求失败时抛出异常(消息为 curl 错误描述),可用 try/catch 捕获。

函数说明
http_get(url: str, timeout_ms: int) -> strGET 请求,返回响应体
http_post(url: str, body: str, content_type: str, timeout_ms: int) -> strPOST 请求(content_type 可传 null)
http_request(method: str, url: str, body: str, headers: str, timeout_ms: int) -> str通用请求;headers 为换行分隔的 "Key: Value"(可传 null)
http_status() -> int最近一次请求的 HTTP 状态码
http_response_headers() -> str最近一次请求的原始响应头
http_error_str(code: int) -> strcurl 错误码转错误描述

注意事项

示例

rex
import "lib/http.rex"
import "lib/json.rex"

fn main() {
    // GET + JSON 解析
    let body: str = http_get("https://httpbin.org/get", 10000)
    let root: ptr = json_parse(body)
    if root != null {
        print(json_string(json_get(root, "url")))
        json_free(root)
    }

    // POST JSON
    let resp: str = http_post("https://httpbin.org/post",
                              "{\"hello\": \"world\"}",
                              "application/json", 10000)
    print("status =", http_status())

    // 错误处理
    try {
        http_get("http://127.0.0.1:9/", 2000)
    } catch err {
        print("请求失败:", err)
    }
}

16.4 加密/编码库(lib/crypto.rex)

所有函数以 crypto_ 前缀命名。由 native/crypto_helper.c 纯 C 自实现(无 OpenSSL 等外部依赖),gcc 编译为 crypto_helper.dll

分类函数说明
哈希摘要crypto_md5(text: str) -> strMD5,返回小写 hex(32 字符)
crypto_sha1(text: str) -> strSHA-1,返回小写 hex(40 字符)
crypto_sha256(text: str) -> strSHA-256,返回小写 hex(64 字符)
crypto_sha512(text: str) -> strSHA-512,返回小写 hex(128 字符)
HMACcrypto_hmac_sha1(key: str, msg: str) -> strHMAC-SHA1 摘要(hex)
crypto_hmac_sha256(key: str, msg: str) -> strHMAC-SHA256 摘要(hex),常用于 API 签名
crypto_hmac_sha512(key: str, msg: str) -> strHMAC-SHA512 摘要(hex)
AES 加密crypto_aes_encrypt_ecb_128(key_hex, data) -> strAES-128 ECB 加密,返回 Base64 密文
crypto_aes_encrypt_ecb_256(key_hex, data) -> strAES-256 ECB 加密
crypto_aes_encrypt_cbc_128(key_hex, iv_hex, data) -> strAES-128 CBC 加密
crypto_aes_encrypt_cbc_256(key_hex, iv_hex, data) -> strAES-256 CBC 加密
AES 解密crypto_aes_decrypt_ecb_128(key_hex, b64) -> strAES-128 ECB 解密(输入 Base64 密文)
crypto_aes_decrypt_ecb_256(key_hex, b64) -> strAES-256 ECB 解密
crypto_aes_decrypt_cbc_128(key_hex, iv_hex, b64) -> strAES-128 CBC 解密
crypto_aes_decrypt_cbc_256(key_hex, iv_hex, b64) -> strAES-256 CBC 解密
编码crypto_base64_encode(data: str) -> strBase64 编码
crypto_base64_decode(b64: str) -> strBase64 解码
crypto_hex_encode(data: str) -> str十六进制编码(小写)
crypto_hex_decode(hex: str) -> str十六进制解码

约定与限制

示例

rex
import "lib/crypto.rex"

fn main() {
    // 哈希摘要(API 签名常用)
    print(crypto_sha256("hello"))            // 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

    // HMAC 签名
    print(crypto_hmac_sha256("secret", "message"))

    // AES-256-CBC 加解密(密钥/IV 为 hex)
    let key: str = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
    let iv: str  = "101112131415161718191a1b1c1d1e1f"
    let cipher: str = crypto_aes_encrypt_cbc_256(key, iv, "Hello, Rex!")
    print("密文:", cipher)                     // Base64
    print("明文:", crypto_aes_decrypt_cbc_256(key, iv, cipher))

    // Base64 / Hex 编码
    print(crypto_base64_encode("Hello"))       // SGVsbG8=
    print(crypto_base64_decode("SGVsbG8="))    // Hello
    print(crypto_hex_encode("AB"))             // 4142
    print(crypto_hex_decode("4142"))           // AB
}

17. 完整代码示例

使用标准库命名空间

rex
// 标准库函数内置,直接以命名空间调用,无需 import、无需 extern
fn main() {
    let pi: float = math.pi()
    print("π =", pi)
    print("sin(π/2) =", math.sin(pi / 2.0))
    print("cos(0) =", math.cos(0.0))
}

fn main() {
    let path: str = "test.txt"
    if file.exists(path) == 1 {
        let content: str = file.read(path)
        print("Content:", content)
    }
}

fn main() {
    random.seed(42)
    for i in range(0, 5) {
        print("Random:", random.int(100))
    }
}