#semantic #modeling #macro #data #name #arena #smodel

nightly macro hydroperfox-smodel-proc

Rust语义建模:进程宏

2个稳定版本

1.0.1 2024年7月23日

1064进程宏

Download history 218/week @ 2024-07-20 61/week @ 2024-07-27

每月下载量279次
4 个crate中使用(通过 hydroperfox-smodel

Apache-2.0

73KB
1.5K SLoC

SModel

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

定义顺序

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

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

示例

最基本的数据类型是最先出现的。您可以根据个人喜好命名它。通常可以称为 symbolthingy(根据Microsoft Roslyn的一位工程师,symbol 应该被称为 thingy)。

use hydroperfox_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

字段有一对获取器(fieldname())和设置器(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() 是一个协变转换。

超级表达式

super.f() 表达式通过预处理方法标记序列并将其转换为其他 Rust 代码得到支持;因此,它可以在实例方法内的任何位置使用。

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

继承文档

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

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

方法参数

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

依赖项

~260–700KB
~17K SLoC