Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drive-by tweaks and docs #561

Merged
merged 13 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sharp-garlics-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"changelog": patch
---

Add preliminary documentation for the `solidity_language` Rust package
1 change: 1 addition & 0 deletions crates/codegen/ebnf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "codegen_ebnf"
description = "EBNF snippet serializer for language definitions"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/codegen/ebnf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Provides an [`EbnfSerializer`], which allows to serialize a [`LanguageDefinition`](`codegen_schema::types::LanguageDefinition`)
//! into EBNF snippets.
//!
//! Used for documentation and for comments in the generated parser code.
mod nodes;
mod parser;
mod precedence_parser;
Expand Down
10 changes: 9 additions & 1 deletion crates/codegen/ebnf/src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::nodes::EbnfNode;

const MAX_LINE_WIDTH: usize = 80;

/// Serializes [`LanguageDefinition`](`codegen_schema::types::LanguageDefinition`) into EBNF snippets.
pub struct EbnfSerializer {
language: LanguageDefinitionRef,
outputs: IndexMap<String, String>,
Expand All @@ -17,7 +18,7 @@ pub struct EbnfSerializer {
impl EbnfSerializer {
/// Returns `None` if version is not found.
/// Otherwise, returns a map of LHS names to EBNF snippets.
/// Some productions (like `PrecedenceParser`) generate more than one statement.
/// Some productions (like ([`PrecedenceParser`](`ProductionDefinition::PrecedenceParser`)) generate more than one statement.
pub fn serialize_version(
language: &LanguageDefinitionRef,
production: &ProductionRef,
Expand Down Expand Up @@ -57,6 +58,12 @@ impl EbnfSerializer {
return Some(instance.outputs);
}

/// Serializes a single EBNF statement.
///
/// Example:
/// ```ebnf
/// UNSIGNED_INTEGER_TYPE = "uint" «INTEGER_TYPE_SIZE»?;
/// ```
pub fn serialize_statement(&mut self, name: &str, root_node: &EbnfNode) {
let mut buffer = String::new();

Expand Down Expand Up @@ -116,6 +123,7 @@ impl EbnfSerializer {
return choices.join(&format!("\n{padding} | ", padding = " ".repeat(name_width)));
}

/// Serialize and append an EBNF node to the buffer.
pub fn serialize_node(&mut self, top_node: &EbnfNode, buffer: &mut String) {
match top_node {
EbnfNode::Choice { nodes } => {
Expand Down
1 change: 1 addition & 0 deletions crates/codegen/spec/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "codegen_spec"
description = "Language specification generator"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
Expand Down
12 changes: 12 additions & 0 deletions crates/codegen/spec/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//! Generates a human-readable specification for the [`LanguageDefinitionRef`].
//!
//! At the time of writing, the generated pages include:
//! - A list of supported versions
//! - A grammar page for each version
//! - A reference page for each version
//!
//! and the auxiliary snippet files included by the grammar mkdocs pages.
//!
//! Exposes a [`SpecGeneratorExtensions`] trait that generates all the pages in a given [`CodegenContext`].
mod grammar;
mod markdown;
mod navigation;
Expand All @@ -17,7 +27,9 @@ use crate::{
snippets::Snippets,
};

/// Extension trait for [`LanguageDefinitionRef`] that generates the specification files.
pub trait SpecGeneratorExtensions {
/// Generates the specification files in `output_dir`.
fn generate_spec(&self, output_dir: &Path) -> Result<()>;
}

Expand Down
3 changes: 1 addition & 2 deletions crates/solidity/inputs/language/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "solidity_language"
description = "Solidity language definition compilation"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
Expand All @@ -15,6 +16,4 @@ infra_utils = { workspace = true }
[dependencies]
anyhow = { workspace = true }
bson = { workspace = true }
cargo-emit = { workspace = true }
codegen_schema = { workspace = true }
infra_utils = { workspace = true }
3 changes: 2 additions & 1 deletion crates/solidity/inputs/language/build.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

use anyhow::Result;
use cargo_emit::rustc_env;
use cargo_emit::{rerun_if_changed, rustc_env};
use codegen_schema::types::{LanguageDefinition, LanguageDefinitionRef};
use infra_utils::{cargo::CargoWorkspace, paths::PathExtensions};

Expand All @@ -20,6 +20,7 @@ fn main() -> Result<()> {
"{}",
bin_file_path.unwrap_str()
);
rerun_if_changed!(bin_file_path.unwrap_str());

return Ok(());
}
Expand Down
25 changes: 12 additions & 13 deletions crates/solidity/inputs/language/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
use std::path::PathBuf;

//! This crate is responsible for compiling the language definition and exposing it to downstream crates.
//!
//! While it's possible to directly compile the language, we do it here once, to ensure that:
//! 1. Expensive parsing and validation is done only once.
//! 2. Errors are reported only once, instead of repeating for every crate.
//!
//! Call the [`SolidityLanguageExtensions::load_solidity`] method to load the precompiled language definition.
use anyhow::Result;
use cargo_emit::rerun_if_changed;
use codegen_schema::types::{LanguageDefinition, LanguageDefinitionRef};
use infra_utils::paths::PathExtensions;

pub trait SolidityLanguageExtensions {
/// Loads the precompiled Solidity language definition.
fn load_solidity() -> Result<LanguageDefinitionRef>;
}

// Set by the build script.
static LANGUAGE_DEFINITION_BIN: &'static str = env!("COMPILED_SOLIDITY_LANGUAGE_DEFINITION_BIN");

impl SolidityLanguageExtensions for LanguageDefinition {
/// We compile the language definition only once, and then expose it here to all downstream crates.
/// This ensures that:
/// 1. Expensive parsing and validation is done only once.
/// 2. Errors are reported only once, instead of repeating for every crate.
fn load_solidity() -> Result<LanguageDefinitionRef> {
let bin_file_path = PathBuf::from(env!("COMPILED_SOLIDITY_LANGUAGE_DEFINITION_BIN"));

rerun_if_changed!(bin_file_path.unwrap_str());

let buffer = std::fs::read(&bin_file_path)?;
let buffer = std::fs::read(LANGUAGE_DEFINITION_BIN)?;
let language: LanguageDefinition = bson::from_slice(&buffer)?;

return Ok(LanguageDefinitionRef::new(language));
Expand Down