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