mz_walkabout/lib.rs
1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Visitor generation for Rust structs and enums.
11//!
12//! Usage documentation is a work in progress, but for an example of the
13//! generated visitor, see the [`sqlparser::ast::visit`] module.
14//!
15//! Some of our ASTs, which we represent with a tree of Rust structs and enums,
16//! are sufficiently complicated that maintaining a visitor by hand is onerous.
17//! This crate provides a generalizable framework for parsing Rust struct and
18//! enum definitions from source code and automatically generating tree
19//! traversal ("visitor") code.
20//!
21//! Note that the desired structure of the `Visit` and `VisitMut` traits
22//! precludes the use of a custom derive procedural macro. We need to consider
23//! the entire AST at once to build the `Visit` and `VisitMut` traits, and
24//! derive macros only allow you to see one struct at a time.
25//!
26//! The design of the visitors is modeled after the visitors provided by the
27//! [`syn`] crate. See: <https://github.com/dtolnay/syn/tree/master/codegen>
28//!
29//! The name of this crate is an homage to CockroachDB's
30//! [Go package of the same name][crdb-walkabout].
31//!
32//! [`sqlparser::ast::visit`]: ../sql_parser/ast/visit/
33//! [crdb-walkabout]: https://github.com/cockroachdb/walkabout
34
35use std::path::Path;
36
37use anyhow::Result;
38
39mod generated;
40mod parse;
41
42pub mod ir;
43
44pub use generated::{gen_fold, gen_visit, gen_visit_mut};
45
46/// Loads type definitions from the specified module.
47///
48/// Returns an intermediate representation (IR) that can be fed to the
49/// generation functions, like [`gen_visit`].
50///
51/// Note that parsing a Rust module is complicated. While most of the heavy
52/// lifting is performed by [`syn`], syn does not understand the various options
53/// for laying out a crate—and there are many attributes and edition settings
54/// that control how modules can be laid out on the file system. This function
55/// does not attempt to be fully general and only handles the file layout
56/// currently required by Materialize.
57///
58/// Analyzing Rust types is also complicated. This function only handles basic
59/// Rust containers, like [`Option`] and [`Vec`]. It does, however, endeavor to
60/// produce understandable error messages when it encounters a type it does not
61/// know how to handle.
62pub fn load<P>(path: P) -> Result<ir::Ir>
63where
64 P: AsRef<Path>,
65{
66 let items = parse::parse_mod(path)?;
67 ir::analyze(&items)
68}