// MoonDatalog —— 可读渲染(把 AST 转回 Datalog 文本)
//
// 供 CLI 与测试复用,保持输出与输入语法一致的显示风格。
///|
/// 渲染一条查询为可读文本。
pub fn render_query(q : Query) -> String {
let b = StringBuilder::new()
let mut first = true
for item in q.body {
if first {
first = false
} else {
b.write_string(", ")
}
b.write_string(render_body_item(item))
}
b.to_string()
}
///|
/// 渲染一条规则(含事实)为可读文本。
pub fn render_rule(r : Rule) -> String {
let b = StringBuilder::new()
b.write_string(render_atom(r.head))
if !r.body.is_empty() {
b.write_string(" :- ")
let mut first = true
for item in r.body {
if first {
first = false
} else {
b.write_string(", ")
}
b.write_string(render_body_item(item))
}
}
b.write_string(".")
b.to_string()
}
///|
/// 渲染一个规则体项。
pub fn render_body_item(item : BodyItem) -> String {
match item {
Pos(a) => render_atom(a)
Neg(a) => "not " + render_atom(a)
Cmp(c) => render_cmp(c)
Agg(agg) => render_agg(agg)
}
}
///|
/// 渲染一个原子。
pub fn render_atom(a : Atom) -> String {
let b = StringBuilder::new()
b.write_string(a.pred)
b.write_string("(")
let args : Array[String] = []
for t in a.args {
args.push(render_term(t))
}
b.write_string(args.join(", "))
b.write_string(")")
b.to_string()
}
///|
/// 渲染一个项。
pub fn render_term(t : Term) -> String {
match t {
Const(v) => v.to_string()
Var(name) => name
Neg(inner) => "-" + render_term(inner)
Arith(op, l, r) =>
"(" + render_term(l) + " " + render_binop(op) + " " + render_term(r) + ")"
}
}
///|
fn render_binop(op : BinOp) -> String {
match op {
BinOp::Add => "+"
BinOp::Sub => "-"
BinOp::Mul => "*"
BinOp::Div => "/"
BinOp::Mod => "%"
}
}
///|
/// 渲染一个比较约束。
pub fn render_cmp(c : Cmp) -> String {
let op = match c.op {
CmpOp::Eq => "="
CmpOp::Ne => "!="
CmpOp::Lt => "<"
CmpOp::Le => "<="
CmpOp::Gt => ">"
CmpOp::Ge => ">="
}
render_term(c.lhs) + " " + op + " " + render_term(c.rhs)
}
///|
/// 渲染一个聚合项。
pub fn render_agg(agg : Aggregate) -> String {
let func = match agg.func {
AggFunc::Count => "count"
AggFunc::Sum => "sum"
AggFunc::Min => "min"
AggFunc::Max => "max"
AggFunc::Avg => "avg"
}
agg.agg_var + " = " + func + " : { " + agg.agg_vars.join(", ") + " }"
}