diff options
Diffstat (limited to 'tvix/eval/src/pretty_ast.rs')
-rw-r--r-- | tvix/eval/src/pretty_ast.rs | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/tvix/eval/src/pretty_ast.rs b/tvix/eval/src/pretty_ast.rs new file mode 100644 index 000000000000..5ac115e21c89 --- /dev/null +++ b/tvix/eval/src/pretty_ast.rs @@ -0,0 +1,468 @@ +//! Pretty-printed format for the rnix AST representation. +//! +//! The AST is serialised into a JSON structure that can then be +//! printed in either minimised or well-formatted style. + +use rnix::ast::{self, AstToken, HasEntry}; +use serde::{ser::SerializeMap, Serialize, Serializer}; + +pub fn pretty_print_expr(expr: &ast::Expr) -> String { + serde_json::ser::to_string_pretty(&SerializeAST(expr)) + .expect("serializing AST should always succeed") +} + +#[repr(transparent)] +struct SerializeAST<S>(S); + +impl<'a> Serialize for SerializeAST<&'a ast::Apply> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "apply")?; + map.serialize_entry("fn", &SerializeAST(&self.0.lambda().unwrap()))?; + map.serialize_entry("arg", &SerializeAST(&self.0.argument().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Assert> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "assert")?; + map.serialize_entry("condition", &SerializeAST(&self.0.condition().unwrap()))?; + map.serialize_entry("body", &SerializeAST(&self.0.body().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Error> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "error")?; + map.serialize_entry("node", &self.0.to_string())?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::IfElse> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(4))?; + map.serialize_entry("kind", "if_else")?; + map.serialize_entry("condition", &SerializeAST(&self.0.condition().unwrap()))?; + map.serialize_entry("then_body", &SerializeAST(&self.0.body().unwrap()))?; + map.serialize_entry("else_body", &SerializeAST(&self.0.else_body().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Select> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let size = match self.0.default_expr() { + Some(_) => 4, + None => 3, + }; + + let mut map = serializer.serialize_map(Some(size))?; + map.serialize_entry("kind", "select")?; + map.serialize_entry("set", &SerializeAST(&self.0.expr().unwrap()))?; + map.serialize_entry("path", &SerializeAST(self.0.attrpath().unwrap()))?; + + if let Some(default) = self.0.default_expr() { + map.serialize_entry("default", &SerializeAST(&default))?; + } + + map.end() + } +} + +impl Serialize for SerializeAST<ast::InterpolPart<String>> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match &self.0 { + ast::InterpolPart::Literal(s) => Serialize::serialize(s, serializer), + ast::InterpolPart::Interpolation(node) => { + Serialize::serialize(&SerializeAST(&node.expr().unwrap()), serializer) + } + } + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Str> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "string")?; + + map.serialize_entry( + "parts", + &self + .0 + .normalized_parts() + .into_iter() + .map(SerializeAST) + .collect::<Vec<_>>(), + )?; + + map.end() + } +} + +impl Serialize for SerializeAST<ast::InterpolPart<ast::PathContent>> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match &self.0 { + ast::InterpolPart::Literal(p) => Serialize::serialize(p.syntax().text(), serializer), + ast::InterpolPart::Interpolation(node) => { + Serialize::serialize(&SerializeAST(&node.expr().unwrap()), serializer) + } + } + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Path> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "path")?; + + map.serialize_entry( + "parts", + &self.0.parts().map(SerializeAST).collect::<Vec<_>>(), + )?; + + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Literal> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "literal")?; + + match self.0.kind() { + ast::LiteralKind::Float(val) => map.serialize_entry("float", &val.value().unwrap()), + ast::LiteralKind::Integer(val) => map.serialize_entry("int", &val.value().unwrap()), + ast::LiteralKind::Uri(val) => map.serialize_entry("uri", val.syntax().text()), + }?; + + map.end() + } +} + +impl Serialize for SerializeAST<ast::PatEntry> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(None)?; + map.serialize_entry("ident", &SerializeAST(&self.0.ident().unwrap()))?; + + if let Some(default) = self.0.default() { + map.serialize_entry("default", &SerializeAST(&default))?; + } + + map.end() + } +} + +impl Serialize for SerializeAST<ast::Param> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match &self.0 { + ast::Param::Pattern(pat) => { + let mut map = serializer.serialize_map(None)?; + map.serialize_entry("kind", "formals")?; + + map.serialize_entry( + "entries", + &pat.pat_entries().map(SerializeAST).collect::<Vec<_>>(), + )?; + + if let Some(bind) = pat.pat_bind() { + map.serialize_entry("bind", &SerializeAST(&bind.ident().unwrap()))?; + } + + map.serialize_entry("ellipsis", &pat.ellipsis_token().is_some())?; + + map.end() + } + + ast::Param::IdentParam(node) => { + Serialize::serialize(&SerializeAST(&node.ident().unwrap()), serializer) + } + } + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Lambda> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "lambda")?; + map.serialize_entry("param", &SerializeAST(self.0.param().unwrap()))?; + map.serialize_entry("body", &SerializeAST(self.0.body().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::LegacyLet> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "legacy_let")?; + + map.serialize_entry( + "entries", + &self + .0 + .attrpath_values() + .map(SerializeAST) + .collect::<Vec<_>>(), + )?; + + map.serialize_entry( + "inherits", + &self.0.inherits().map(SerializeAST).collect::<Vec<_>>(), + )?; + + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::LetIn> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "let")?; + + map.serialize_entry( + "entries", + &self + .0 + .attrpath_values() + .map(SerializeAST) + .collect::<Vec<_>>(), + )?; + + map.serialize_entry( + "inherits", + &self.0.inherits().map(SerializeAST).collect::<Vec<_>>(), + )?; + + map.serialize_entry("body", &SerializeAST(&self.0.body().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::List> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let list = self.0.items().map(SerializeAST).collect::<Vec<_>>(); + + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "list")?; + map.serialize_entry("items", &list)?; + + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::BinOp> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(4))?; + map.serialize_entry("kind", "binary_op")?; + + map.serialize_entry( + "operator", + match self.0.operator().unwrap() { + ast::BinOpKind::Concat => "concat", + ast::BinOpKind::Update => "update", + ast::BinOpKind::Add => "add", + ast::BinOpKind::Sub => "sub", + ast::BinOpKind::Mul => "mul", + ast::BinOpKind::Div => "div", + ast::BinOpKind::And => "and", + ast::BinOpKind::Equal => "equal", + ast::BinOpKind::Implication => "implication", + ast::BinOpKind::Less => "less", + ast::BinOpKind::LessOrEq => "less_or_eq", + ast::BinOpKind::More => "more", + ast::BinOpKind::MoreOrEq => "more_or_eq", + ast::BinOpKind::NotEqual => "not_equal", + ast::BinOpKind::Or => "or", + }, + )?; + + map.serialize_entry("lhs", &SerializeAST(&self.0.lhs().unwrap()))?; + map.serialize_entry("rhs", &SerializeAST(&self.0.rhs().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Paren> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "paren")?; + map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Root> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "root")?; + map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; + map.end() + } +} + +impl Serialize for SerializeAST<ast::AttrpathValue> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("name", &SerializeAST(self.0.attrpath().unwrap()))?; + map.serialize_entry("value", &SerializeAST(self.0.value().unwrap()))?; + map.end() + } +} + +impl Serialize for SerializeAST<ast::Inherit> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(None)?; + + if let Some(from) = self.0.from() { + map.serialize_entry("namespace", &SerializeAST(&from.expr().unwrap()))?; + } + + map.serialize_entry( + "names", + &self.0.attrs().map(SerializeAST).collect::<Vec<_>>(), + )?; + + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::AttrSet> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(None)?; + map.serialize_entry("kind", "attrset")?; + map.serialize_entry("recursive", &self.0.rec_token().is_some())?; + + map.serialize_entry( + "entries", + &self + .0 + .attrpath_values() + .map(SerializeAST) + .collect::<Vec<_>>(), + )?; + + map.serialize_entry( + "inherits", + &self.0.inherits().map(SerializeAST).collect::<Vec<_>>(), + )?; + + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::UnaryOp> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "unary_op")?; + + map.serialize_entry( + "operator", + match self.0.operator().unwrap() { + ast::UnaryOpKind::Invert => "invert", + ast::UnaryOpKind::Negate => "negate", + }, + )?; + + map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Ident> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "ident")?; + map.serialize_entry("ident", self.0.ident_token().unwrap().text())?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::With> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "with")?; + map.serialize_entry("with", &SerializeAST(&self.0.namespace().unwrap()))?; + map.serialize_entry("body", &SerializeAST(&self.0.body().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Dynamic> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "dynamic")?; + map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; + map.end() + } +} + +impl Serialize for SerializeAST<ast::Attr> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match &self.0 { + ast::Attr::Ident(ident) => Serialize::serialize(&SerializeAST(ident), serializer), + ast::Attr::Dynamic(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Attr::Str(node) => Serialize::serialize(&SerializeAST(node), serializer), + } + } +} + +impl Serialize for SerializeAST<ast::Attrpath> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("kind", "attrpath")?; + + map.serialize_entry( + "path", + &self.0.attrs().map(SerializeAST).collect::<Vec<_>>(), + )?; + + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::HasAttr> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("kind", "has_attr")?; + map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; + map.serialize_entry("attrpath", &SerializeAST(self.0.attrpath().unwrap()))?; + map.end() + } +} + +impl<'a> Serialize for SerializeAST<&'a ast::Expr> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match self.0 { + ast::Expr::Apply(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Assert(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Error(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::IfElse(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Select(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Str(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Path(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Literal(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Lambda(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::LegacyLet(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::LetIn(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::List(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::BinOp(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Paren(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Root(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::AttrSet(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::UnaryOp(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::Ident(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::With(node) => Serialize::serialize(&SerializeAST(node), serializer), + ast::Expr::HasAttr(node) => Serialize::serialize(&SerializeAST(node), serializer), + } + } +} + +impl Serialize for SerializeAST<ast::Expr> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + SerializeAST(&self.0).serialize(serializer) + } +} |