#语义 #建模 #符号 # #数据 #名称 #smodel

nightly smodel-proc

Rust的符号语义建模:过程宏

12个稳定版本

1.0.11 2024年5月6日
1.0.10 2024年5月2日
1.0.8 2024年5月1日
1.0.3 2024年4月30日
0.1.0 2024年4月29日

#693 in 过程宏

23每月下载量
4个crate中使用(通过smodel

Apache-2.0

72KB
1.5K SLoC

SModel

SModel(语义建模)为Rust提供了一种使用动态分派和层次定义以及允许循环引用的存储区来描述语言语义符号的便捷方式。

定义顺序

定义顺序很重要。在定义子类型之前,使用struct关键字定义其继承的数据类型。

如果你以任何顺序定义struct,可能会导致宏终止的未找到错误。

示例

最基本的数据类型是最先出现的。你可以根据自己的喜好来命名它。通常可以称之为symbolthingy(根据Microsoft Roslyn工程师的说法,symbol应该被称为thingy)。

use smodel::smodel;

smodel! {
    type Arena = Arena;

    struct Thingy {
        let x: f64 = 0.0;
        let ref y: String = "".into();

        pub fn Thingy() {
            super();
            println!("{}", self.m());
        }

        pub fn m(&self) -> String {
            "".into()
        }

        pub fn m1(&self) {
            println!("base");
        }
    }

    struct Foo: Thingy {
        pub fn Foo() {
            super();
        }

        pub override fn m(&self) -> String {
            "Foo".into()
        }

        pub override fn m1(&self) {
            if true {
                super.m1();
            }
        }
    }
}

fn main() {
    let arena = Arena::new();
    let thingy = Foo::new(&arena);
    println!("{}", thingy.m());
}

存储区

存储区的名称由第一个type Arena = ArenaName1;指令的右侧定义。

字段

字段(一个let声明)有一个可选的ref修饰符,表示是否使用RefCellCell。对于所有类型,都是在读取时克隆或复制。对于堆分配的资源,如String,请使用ref

字段都有一个getter(fieldname())和一个setter(set_fieldname(value))。

对于可变的哈希表或向量,建议使用共享容器(见下文),该容器通过引用克隆而不是通过内容克隆。

字段始终是封装模块的内部字段,因此没有属性;字段定义始终以let关键字开始,没有RustDoc注释。

建议字段始终以下划线_或私有前缀如m_开头,并相应地使用如_x()set__x(v)m_x()set_m_x()的访问方式。

然后,您可以为基类型实现可能被子类型重写的方法,从而允许一个统一的数据类型支持操作多个变体的方法。

共享容器

该包提供了两种通过引用克隆的容器数据类型,SharedArraySharedMap,以及shared_array!shared_map!字面量。

  • SharedArray是由引用计数管理的可变向量。
  • SharedMap是由引用计数管理的可变哈希表。

有关用法详情,请参阅包文档。

构造函数

构造函数是一个其名称与数据类型名称匹配的方法。将arena参数隐式地添加到形式参数列表的开头。

构造函数被转换为静态的new方法。

构造函数包含一个局部self变量,其数据类型是封装数据类型的实例。

子类型

  • symbol.is::<T>()检查symbol是否是T子类型。
  • symbol.to::<T>()转换为T子类型,返回Ok(m)Err。它可能是一个逆变转换。
  • symbol.into()是协变转换。

超表达式

支持通过预处理方法令牌序列并将它转换成其他Rust代码来支持super.f()表达式;因此,它可以在实例方法的任何地方使用。

super.f()按照降序顺序在基本数据类型的方法列表中进行查找。

继承文档

使用#[inheritdoc]属性来继承被覆盖方法的RustDoc注释。

#[inheritdoc]
pub override fn m(&self) {
    // Action
}

方法参数

目前,被覆盖方法中方法参数的名称应与子类型方法中的名称匹配,否则可能会出现宏卫生错误,指示该参数在子类型的方法中不存在。

许可证

Apache 2.0,版权所有 © Hydroper

依赖项

约290-740KB
约18K SLoC