326 lines
8.1 KiB
Rust
326 lines
8.1 KiB
Rust
//! CNNL抽象语法树(AST)定义
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
/// 程序(顶层节点)
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub struct Program {
|
||
pub clauses: Vec<Clause>,
|
||
/// 测试块(test "..." { assert ... })
|
||
#[serde(default)]
|
||
pub tests: Vec<TestBlock>,
|
||
}
|
||
|
||
/// 宪法条款
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub struct Clause {
|
||
/// 条款标识符(全大写)
|
||
pub id: String,
|
||
/// 条款层级
|
||
pub level: ClauseLevel,
|
||
/// 条款标题
|
||
pub title: String,
|
||
/// 条款名称(name: 字段,可选)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub name: Option<String>,
|
||
/// 版本号(version: 字段,可选)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub version: Option<String>,
|
||
/// 描述(description: 字段,可选)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub description: Option<String>,
|
||
/// 依赖的其他条款
|
||
pub depends_on: Vec<String>,
|
||
/// 参数列表
|
||
pub parameters: Vec<Parameter>,
|
||
/// 谓词列表
|
||
pub predicates: Vec<Predicate>,
|
||
/// 义务列表
|
||
pub obligations: Vec<Obligation>,
|
||
}
|
||
|
||
/// 条款层级
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum ClauseLevel {
|
||
/// 永恒条款(不可修改)
|
||
Eternal,
|
||
/// 战略条款(需要超级多数修改)
|
||
Strategic,
|
||
/// 战术条款(普通多数修改)
|
||
Tactical,
|
||
}
|
||
|
||
impl std::fmt::Display for ClauseLevel {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||
match self {
|
||
ClauseLevel::Eternal => write!(f, "eternal"),
|
||
ClauseLevel::Strategic => write!(f, "strategic"),
|
||
ClauseLevel::Tactical => write!(f, "tactical"),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 参数
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub struct Parameter {
|
||
pub name: String,
|
||
/// 参数类型
|
||
pub ty: Type,
|
||
pub value: Literal,
|
||
/// 参数描述(可选)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub description: Option<String>,
|
||
}
|
||
|
||
/// 谓词
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub struct Predicate {
|
||
pub name: String,
|
||
pub params: Vec<(String, Type)>,
|
||
pub return_type: Type,
|
||
/// 函数体(AST 表达式)
|
||
pub body: Expression,
|
||
}
|
||
|
||
/// 义务
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub struct Obligation {
|
||
pub name: String,
|
||
pub frequency: ObligationFrequency,
|
||
pub enforcer: String,
|
||
pub penalty: String,
|
||
/// 义务描述(可选)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub description: Option<String>,
|
||
}
|
||
|
||
/// 义务频率
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum ObligationFrequency {
|
||
Continuous, // 持续
|
||
Periodic, // 周期性
|
||
OnDemand, // 按需
|
||
}
|
||
|
||
impl std::fmt::Display for ObligationFrequency {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||
match self {
|
||
ObligationFrequency::Continuous => write!(f, "continuous"),
|
||
ObligationFrequency::Periodic => write!(f, "periodic"),
|
||
ObligationFrequency::OnDemand => write!(f, "on_demand"),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 类型
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum Type {
|
||
Bool,
|
||
U64,
|
||
U32,
|
||
U128,
|
||
F64,
|
||
String,
|
||
}
|
||
|
||
impl std::fmt::Display for Type {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||
match self {
|
||
Type::Bool => write!(f, "bool"),
|
||
Type::U64 => write!(f, "u64"),
|
||
Type::U32 => write!(f, "u32"),
|
||
Type::U128 => write!(f, "u128"),
|
||
Type::F64 => write!(f, "f64"),
|
||
Type::String => write!(f, "string"),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 字面量
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub enum Literal {
|
||
Bool(bool),
|
||
Int(u64),
|
||
Float(f64),
|
||
String(String),
|
||
}
|
||
|
||
impl std::fmt::Display for Literal {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||
match self {
|
||
Literal::Bool(b) => write!(f, "{}", b),
|
||
Literal::Int(n) => write!(f, "{}", n),
|
||
Literal::Float(n) => write!(f, "{}", n),
|
||
Literal::String(s) => write!(f, "\"{}\"", s),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 表达式
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub enum Expression {
|
||
// 字面量
|
||
Literal(Literal),
|
||
|
||
// 变量引用
|
||
Variable(String),
|
||
|
||
// 二元运算
|
||
Binary {
|
||
op: BinaryOp,
|
||
left: Box<Expression>,
|
||
right: Box<Expression>,
|
||
},
|
||
|
||
// 一元运算
|
||
Unary {
|
||
op: UnaryOp,
|
||
operand: Box<Expression>,
|
||
},
|
||
|
||
// 函数调用
|
||
Call {
|
||
name: String,
|
||
args: Vec<Expression>,
|
||
},
|
||
|
||
// if表达式
|
||
If {
|
||
condition: Box<Expression>,
|
||
then_branch: Box<Expression>,
|
||
else_branch: Option<Box<Expression>>,
|
||
},
|
||
|
||
// 代码块
|
||
Block(Vec<Statement>),
|
||
|
||
// 原始字符串(解析器无法完整解析时的降级表示)
|
||
Raw(String),
|
||
}
|
||
|
||
/// 二元运算符
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum BinaryOp {
|
||
// 算术运算
|
||
Add,
|
||
Sub,
|
||
Mul,
|
||
Div,
|
||
Mod,
|
||
|
||
// 比较运算
|
||
Eq,
|
||
Ne,
|
||
Lt,
|
||
Le,
|
||
Gt,
|
||
Ge,
|
||
|
||
// 逻辑运算
|
||
And,
|
||
Or,
|
||
}
|
||
|
||
impl std::fmt::Display for BinaryOp {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||
match self {
|
||
BinaryOp::Add => write!(f, "+"),
|
||
BinaryOp::Sub => write!(f, "-"),
|
||
BinaryOp::Mul => write!(f, "*"),
|
||
BinaryOp::Div => write!(f, "/"),
|
||
BinaryOp::Mod => write!(f, "%"),
|
||
BinaryOp::Eq => write!(f, "=="),
|
||
BinaryOp::Ne => write!(f, "!="),
|
||
BinaryOp::Lt => write!(f, "<"),
|
||
BinaryOp::Le => write!(f, "<="),
|
||
BinaryOp::Gt => write!(f, ">"),
|
||
BinaryOp::Ge => write!(f, ">="),
|
||
BinaryOp::And => write!(f, "&&"),
|
||
BinaryOp::Or => write!(f, "||"),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 一元运算符
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum UnaryOp {
|
||
Not,
|
||
Neg,
|
||
}
|
||
|
||
impl std::fmt::Display for UnaryOp {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||
match self {
|
||
UnaryOp::Not => write!(f, "!"),
|
||
UnaryOp::Neg => write!(f, "-"),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 语句
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub enum Statement {
|
||
// 表达式语句
|
||
Expression(Expression),
|
||
|
||
// 返回语句
|
||
Return(Expression),
|
||
|
||
// 变量声明
|
||
Let {
|
||
name: String,
|
||
ty: Option<Type>,
|
||
value: Expression,
|
||
},
|
||
}
|
||
|
||
/// 测试块
|
||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
pub struct TestBlock {
|
||
pub description: String,
|
||
pub assertions: Vec<String>,
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_clause_creation() {
|
||
let clause = Clause {
|
||
id: "XTZH_GOLD_COVERAGE".to_string(),
|
||
level: ClauseLevel::Eternal,
|
||
title: "黄金储备覆盖率底线".to_string(),
|
||
name: None,
|
||
version: None,
|
||
description: None,
|
||
depends_on: vec![],
|
||
parameters: vec![Parameter {
|
||
name: "XTZH_GOLD_COVERAGE_MIN".to_string(),
|
||
ty: Type::F64,
|
||
value: Literal::Float(1.25),
|
||
description: Some("最低黄金覆盖率".to_string()),
|
||
}],
|
||
predicates: vec![],
|
||
obligations: vec![],
|
||
};
|
||
|
||
assert_eq!(clause.id, "XTZH_GOLD_COVERAGE");
|
||
assert_eq!(clause.level, ClauseLevel::Eternal);
|
||
assert_eq!(clause.parameters.len(), 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_expression_creation() {
|
||
let expr = Expression::Binary {
|
||
op: BinaryOp::Ge,
|
||
left: Box::new(Expression::Variable("coverage".to_string())),
|
||
right: Box::new(Expression::Literal(Literal::Float(1.25))),
|
||
};
|
||
|
||
match expr {
|
||
Expression::Binary { op, .. } => assert_eq!(op, BinaryOp::Ge),
|
||
_ => panic!("Expected Binary expression"),
|
||
}
|
||
}
|
||
}
|