Rio 语言简介

Rio 是一门为编程初学者设计的通用型编程语言,结合了动态语言的灵活性和静态类型系统的可靠性。通过 RVM 虚拟机实现真正的跨平台运行。

简单易学

清晰的语法,直观的类型系统,让编程初学者能够快速上手

动静结合

享受动态类型灵活性的同时,通过类型注解获得更好的代码提示

跨平台运行

基于 RVM 虚拟机,一次编写,到处运行

hello.rio
// 简单的Rio程序
import(io="io", prog="prog")

fun main(): void {
    var name: str = io.sin("你好!我是 Rio,你叫什么名字?")
    io.sout("很高兴认识你!", name,
        ",和我一起描绘 “Real” 的世界吧!", end="^_^!\n")
}

prog.entry((*args, **kwargs) - > {
    main()
})

安装指南

Rio 支持多种安装方式,请根据你的操作系统选择合适的方法。

Windows

URL
https://riolang.cn/prepare-download/Rio_Setup.exe

macOS

...
暂不支持

Linux

...
暂不支持
注意: 安装完成后,请在终端运行
RCC --v
RVM --v
REM ls
确认安装成功。

快速开始

让我们通过一个简单的示例来了解 Rio 的基本用法。

1. 创建 Rio 文件

创建一个名为 fibonacci.rio 的文件,并输入以下代码:

fibonacci.rio
import(io="io", prog="prog", ds="ds")

fun fib(n: int): list {
    var sequence: list = []
    var a: int = 0
    var b: int = 1
    var i: int = 0
    while i < n {
        sequence += a
        var next = a + b
        a = b
        b = next
        i + +
    }
    ret sequence
}

fun main(): void {
    var numbers: list = fib(10)
    var i: int = 0
    while i < ds.size(numbers) {
        io.sout(numbers[i])
        i + +
    }
}

prog.entry((*args, **kwargs) - > {
    main()
})

2. 编译程序

terminal
RCC --i fibonacci.rio --o output.ra

3. 运行程序

terminal
RVM --r --t output.ra

运行结果

terminal
0
1
1
2
3
5
8
13
21
34

提示: 确保 ~/Rio/bin/Lib/builtin 目录中的文件完整,至少应该包含上面导入的三个内置扩展文件:‘io’、‘prog’、‘ds’和‘datatype’

基本语法

Rio 的语法设计简洁直观,让初学者能够快速上手。

变量声明

在 Rio 语言中,变量定义使用var关键字,其相关规则与特性如下:

1. 标识符命名规范

    ● 允许包含字母、数字和下划线,首字符只能是字母或下划线

    ● 命名风格建议:

        ○ 变量名、函数名:采用小写驼峰(如userName)或全小写加下划线(如user_name

        ○ 类名:采用大写驼峰(如UserAccount

2. 变量类型规则

    ● 定义时可在标识符后加:指定类型(如var age: int

    ● 不指定类型时默认为any(动态类型),支持自动类型切换

    ● 显式指定类型的变量为静态类型,不可自动切换类型

    ● 动态类型与静态类型可通过显式重新设置类型实现相互转换

example
// 显式类型声明
var name: str = "Rio"
var age: int = 1
var scores: list = [1, 2.01, true, "string"]

// 类型系统
// 默认为 any 类型,any 类型可以自动切换为其他数据类型
var message = "Hello"
message = 0
// 也可手动切换至具体类型,切换后将取消自动切换功能,需手动切回 'any' 类型才能恢复自动切换。
message: str = "world"
// 手动切换回 'any' 类型
message: any = true

控制流

Rio 语言的控制流结构包含以下类型,具体规则如下:

1. if-elif-else 判断控制结构

    ● if、elif 后跟的判断表达式可省略括号

    ● 整体采用多分支递进判断逻辑

2. while 循环控制结构

    ● 循环条件表达式支持省略括号

    ● 满足条件时持续执行循环体代码

3. for 循环控制结构

    ● 语法结构与常规形式不同,需在紧跟的圆括号中包含三段语句:

        ○ 第一句:初始化语句(循环开始前执行)

        ○ 第二句:循环判断语句(每次迭代前检查,决定是否继续)

        ○ 第三句:迭代执行语句(每次循环体结束后执行)

    ● 圆括号表达式后直接衔接循环体代码块

example
import(io="io")

// if-elif-else 条件判断
if age < 18 {
    io.sout("未成年人")
} else {
    io.sout("未成年人")
}

// while 循环
var i: int = 0
while i < 5 {
    io.sout("计数: ", i)
    i + +
}

// for 循环
for ({var i = 0; i < 5; i + +}) {
    io.sout("计数:", i)
}

函数定义

在 Rio 语言中,函数定义使用 fun 关键字,函数标识符的命名规则与变量定义中的标识符命名规则一致。函数参数、返回值及相关规则如下:

1. 参数类型分类

    ● 位置参数(positional argument):可通过 : 限制参数类型(推荐做法)

    ● 关键字参数(keyword argument):使用 = 设置参数默认值,可通过位置传递,但推荐使用关键字传递

    ● 变长位置参数(variable-length positional argument):在参数名前加 * 标识

    ● 变长关键字参数(variable-length keyword argument):在参数名前加 ** 标识

2. 参数处理与排序规则

    ● 函数调用时,编译器会先收集所有传递的参数,按位置参数和关键字参数分类

    ● 实参中的位置参数和关键字参数顺序,不影响形参中位置参数的解析与匹配,会按函数参数签名依次配对

    ● 推荐的函数形参顺序为:位置参数、变长位置参数、关键字参数、变长关键字参数

3. 返回值规则

    ● 通过参数表后加 : 指定返回类型,不指定时默认为 any 类型,默认返回值为 null

    ● 特殊返回类型 void:返回类型为 void 的函数类型标签为 func,其他返回类型的函数标签为 funi

    ● 类型区别func 类型函数明确无返回值,其调用表达式不能作为右值传递,仅能作为独立的函数调用语句使用;funi 类型函数则可返回指定类型的值并参与表达式运算

example
import(io="io", ds="ds", prog="prog")

// func 类型函数定义
fun print(role: str, *msgs, end="\n"): void {
    io.sout(ds.joins("[", role, "]: ", ds.join(msgs, "")), end=end)
}

// funi 类型函数定义
fun max(a: int, b: int): int {
    if a > = b {
        ret a
    } else {
        ret b
    }
}

// 定义接收函数作为参数的函数
fun call(callable: func, arg, msg="Hello world", end="\n"): void {
    callable(arg, msg, end=end)
}

fun main(*args, **kwargs): int {
    // 调用 print 函数
    print("System", "Hello world from Rio!", " ", "How are you", end="?\n")
    // 将 max 函数的调用表达加入其他表达式参与运算
    io.sout("The max number of [5, 10, 20] is ", max(10, max(5, 20)))
    // 调用接收函数为参数的函数
    call(print, "System")
    ret 0
}

// 将函数作为参数进行传递
prog.entry(main)

数据类型

Rio语言提供了丰富的数据类型,包括基本类型和复合类型,同时支持动态类型与静态类型结合的特性。

基本数据类型

整数 (int)

表示整数类型,支持任意长度的整数运算

浮点数 (float)

表示带小数点的数值,支持单精度和双精度运算

布尔值 (bool)

表示真或假,取值为true或false

字符类型 (char)

表示单个字符的数据类型,字符串类型由多个字符类型组成

字符串 (str)

表示文本序列,支持单引号和双引号定义

空值 (nul)

表示不存在的值,仅可赋值为null

basic_types.rio
import(dt="datatype")
// 基本数据类型示例
var age: int = 25
var height: float = 1.75
var is_student: bool = true
var identifier: str = "A"
identifier = dt.setType(identifier, "char")
var name: str = "Rio"
var empty_value: nul = null // 注意:nul 类型的标签为 nul,字面量为 null
var dynamic_var: any = 100
dynamic_var = "now I'm a string" // 动态类型允许切换

特殊数据类型

特殊数据类型:任意类型 (any) 是动态数据类型,它可以根据设置的值类型进行自动类型转换

any_example.rio
var test1: any = 0 // 显示设置变量类型为 any 类型
var test2 = 0 // 若不指定变量类型则默认为 any 类型

// any 类型变量可以根据赋值的类型自动切换自身存储的值类型
test1 = "Hello Rio!"

// any 类型变量也可以通过显示设置具体类型将其降级为指定的数据类型
test2: str = "Hello Rio!"

复合数据类型

复合类型是由基本类型组合而成的数据结构:

列表 (list)

有序可变的元素集合,支持不同类型元素共存:

list_example.rio
import(ds="ds")

// 定义列表
var mixed_list: list = [0, true, 2.01, "3"]

// 列表操作
mixed_list += 42 // 添加元素
var length = ds.size(mixed_list) // 获取长度
var first_item = mixed_list[0] // 访问元素
mixed_list[2] = 2.02 // 修改元素

字典 (dict)

无序的键值对集合,键必须唯一:

dict_example.rio
import(ds="ds")

// 定义字典
var person: dict = {
    "name": "Rio",
    "age": 1,
    "features": ["simple", "powerful"]
}

// 字典操作
person["version"] = "1.0.0" // 添加键值对
var person_name = person["name"] // 访问值
ds.dictRemove(person, "age") // 删除键值对
注意:所有复合类型都可以通过 ds 扩展提供的函数进行操作,包括添加、删除、查找等常用操作。