Skip to content

Commit

Permalink
Start fleshing out a Bindings API
Browse files Browse the repository at this point in the history
  • Loading branch information
ggiraldez committed Jun 12, 2024
1 parent 766284b commit 2c41a75
Show file tree
Hide file tree
Showing 32 changed files with 637 additions and 455 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions crates/codegen/runtime/cargo/src/runtime/bindings.rs.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::bindings_support::Bindings;
use crate::language::Language;

pub fn create_for(language: Language) -> Bindings {
{%- if model.bindings.graph_builder_path -%}
Bindings::create(language, GRAPH_BUILDER_SOURCE)
{%- else -%}
_ = language;
{%- if rendering_in_stubs -%}
unreachable!("Bindings not available in stubs");
{%- else -%}
unreachable!("Language does not define binding rules");
{%- endif -%}
{%- endif -%}
}

{%- if model.bindings.graph_builder_path -%}
const GRAPH_BUILDER_SOURCE: &'static str = include_str!("{{ model.bindings.graph_builder_path }}");
{%- else -%}
mod supress_dependencies {
use { stack_graphs as _ };
}
{%- endif -%}
20 changes: 0 additions & 20 deletions crates/codegen/runtime/cargo/src/runtime/bindings/mod.rs

This file was deleted.

This file was deleted.

98 changes: 98 additions & 0 deletions crates/codegen/runtime/cargo/src/runtime/bindings_support/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
pub mod stack_graph {
use metaslang_graph_builder::stack_graph;
pub use metaslang_graph_builder::stack_graph::{
BuildError, NoCancellation, FILE_PATH_VAR, ROOT_PATH_VAR,
};

use super::super::metaslang_cst::KindTypes;

pub type Builder<'a> = stack_graph::Builder<'a, KindTypes>;
pub type StackGraphLanguage = stack_graph::StackGraphLanguage<KindTypes>;
}

use std::fs;
use std::io;
use std::path::Path;
use thiserror::Error;
use stack_graphs::graph::StackGraph;

use crate::language::Language;
use crate::graph_builder::File as GraphBuilderFile;
use crate::graph_builder::Variables;
use crate::parse_error::ParseError;

use self::stack_graph::StackGraphLanguage;

#[derive(Error, Debug)]
pub enum BindingsError {
#[error(transparent)]
Io(#[from] std::io::Error),

#[error("Parsing source file failed")]
ParseError(Vec<ParseError>),

#[error(transparent)]
BuildError(#[from] metaslang_graph_builder::stack_graph::BuildError),
}

pub struct Bindings {
language: Language,
stack_graph: StackGraph,
sgl: StackGraphLanguage,
}

impl Bindings {
#[allow(dead_code)]
pub(crate) fn create(language: Language, msgb_source: &str) -> Self {
let graph_builder_file = GraphBuilderFile::from_str(msgb_source)
.expect("Bindings stack graph builder parse error");
let sgl = StackGraphLanguage::new(graph_builder_file);
let stack_graph = StackGraph::new();

Self {
language,
stack_graph,
sgl,
}
}

pub fn add_file(&mut self, source_file_path: &Path) -> Result<(), BindingsError> {
let input = fs::read_to_string(source_file_path)?;
let parse_output = self.language.parse(Language::ROOT_KIND, &input);
if !parse_output.is_valid() {
return Err(BindingsError::ParseError(parse_output.errors))
}
let tree_cursor = parse_output.create_tree_cursor();

let root_path = source_file_path
.parent()
.ok_or(io::Error::from(io::ErrorKind::InvalidData))?;
let file_name = source_file_path
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("<unknown>");
let file = self.stack_graph.get_or_create_file(file_name);

let mut globals = Variables::new();
// TODO: add the Language version as well to allow semantic changes between versions
globals
.add(
stack_graph::ROOT_PATH_VAR.into(),
root_path.to_str().unwrap().into(),
)
.expect("failed to add ROOT_PATH variable");
globals
.add(
stack_graph::FILE_PATH_VAR.into(),
source_file_path.to_str().unwrap().into(),
)
.expect("failed to add FILE_PATH variable");

let mut builder =
self.sgl
.builder_into_stack_graph(&mut self.stack_graph, file, tree_cursor);
builder.build(&globals, &stack_graph::NoCancellation)?;

Ok(())
}
}
78 changes: 78 additions & 0 deletions crates/codegen/runtime/cargo/src/runtime/cli/commands/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use semver::Version;
use std::path::PathBuf;

use crate::bindings;
use crate::language::Language;
use super::CommandError;

pub fn execute(
file_path_string: &str,
version: Version,
) -> Result<(), super::CommandError> {
let language = Language::new(version)?;
let mut bindings = bindings::create_for(language);

let file_path = PathBuf::from(&file_path_string)
.canonicalize()
.map_err(|_| CommandError::FileNotFound(file_path_string.to_string()))?;

bindings.add_file(&file_path)?;

// print_defs_and_refs(&bindings);
// resolve_refs(&bindings);

Ok(())
}

// fn print_defs_and_refs(bindings: &Bindings) {
// let stack_graph = &bindings.stack_graph;
// for handle in stack_graph.iter_nodes() {
// let node = &stack_graph[handle];
// let syntax_node_ref = bindings.node_handle_to_syntax_ref(handle);

// if node.is_definition() {
// println!(
// "Node #{node} is definition",
// node = node.display(stack_graph),
// );
// } else if node.is_reference() {
// println!(
// "Node #{node} is reference",
// node = node.display(stack_graph)
// );
// }
// if let Some(syntax_ref) = syntax_node_ref {
// let cursor = &bindings.graph[*syntax_ref];
// println!("{:?}", cursor.text_range());
// }
// }
// }

// fn resolve_refs(stack_graph: &StackGraph) {
// let mut paths = PartialPaths::new();
// let mut results = BTreeSet::new();
// let references = stack_graph
// .iter_nodes()
// .filter(|handle| stack_graph[*handle].is_reference())
// .collect::<Vec<_>>();
// for reference in &references {
// println!(
// "Found ref: {reference}",
// reference = reference.display(stack_graph)
// );
// }
// ForwardPartialPathStitcher::find_all_complete_partial_paths(
// &mut GraphEdgeCandidates::new(stack_graph, &mut paths, None),
// references,
// StitcherConfig::default(),
// &stack_graphs::NoCancellation,
// |graph, paths, path| {
// results.insert(path.display(graph, paths).to_string());
// },
// )
// .expect("should never be cancelled");

// for result in &results {
// println!("Found path: {result}");
// }
// }

This file was deleted.

8 changes: 6 additions & 2 deletions crates/codegen/runtime/cargo/src/runtime/cli/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use thiserror::Error;
#[cfg(feature = "__graph_builder")]
pub mod build_graph;
#[cfg(feature = "__graph_builder")]
pub mod build_stack_graph;
pub mod bindings;
pub mod parse;

#[derive(Debug, Error)]
Expand All @@ -26,5 +26,9 @@ pub enum CommandError {

#[cfg(feature = "__graph_builder")]
#[error(transparent)]
BuildError(#[from] crate::bindings::stack_graph::BuildError),
BuildError(#[from] metaslang_graph_builder::stack_graph::BuildError),

#[cfg(feature = "__graph_builder")]
#[error(transparent)]
BindingsError(#[from] crate::bindings_support::BindingsError),
}
10 changes: 3 additions & 7 deletions crates/codegen/runtime/cargo/src/runtime/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,13 @@ pub enum Commands {

// This is only intended for internal development
#[cfg(feature = "__graph_builder")]
BuildStackGraph {
Bindings {
/// File path to the source file to parse
file_path: String,

/// The language version to use for parsing
#[arg(short, long)]
version: Version,

/// The graph buider (.msgb) file to use
msgb_path: String,
},
}

Expand All @@ -76,11 +73,10 @@ impl Commands {
debug,
} => commands::build_graph::execute(&file_path, version, &msgb_path, json, debug),
#[cfg(feature = "__graph_builder")]
Commands::BuildStackGraph {
Commands::Bindings {
file_path,
version,
msgb_path,
} => commands::build_stack_graph::execute(&file_path, version, &msgb_path),
} => commands::bindings::execute(&file_path, version),
};
match command_result {
Ok(()) => ExitCode::SUCCESS,
Expand Down
Loading

0 comments on commit 2c41a75

Please sign in to comment.