From 63c606d17095e336ee0deeedb30f94a490ec4059 Mon Sep 17 00:00:00 2001 From: Akshay Date: Fri, 11 Oct 2024 08:25:31 +0530 Subject: add analysis phase --- src/eval/analysis.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/eval/analysis.rs (limited to 'src/eval/analysis.rs') diff --git a/src/eval/analysis.rs b/src/eval/analysis.rs new file mode 100644 index 0000000..b3a0083 --- /dev/null +++ b/src/eval/analysis.rs @@ -0,0 +1,108 @@ +use crate::{ast, Wrap}; + +#[derive(Debug, PartialEq, Eq)] +pub struct Analysis { + diagnostics: Vec, +} + +impl Analysis { + pub fn print(&self) { + for Diagnostic { level, kind } in &self.diagnostics { + eprintln!("{level} {kind}"); + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Diagnostic { + level: Level, + kind: Kind, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum Level { + Warning, + Error, +} + +impl std::fmt::Display for Level { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Level::Warning => write!(f, "[warning]"), + Level::Error => write!(f, "[error]"), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum Kind { + Pattern { + invalid_node_kind: String, + full_pattern: ast::Pattern, + }, +} + +impl std::fmt::Display for Kind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Pattern { + invalid_node_kind, + full_pattern, + } => { + write!( + f, + "invalid node kind `{invalid_node_kind}` in pattern `{full_pattern}`" + ) + } + } + } +} + +pub fn run(ctx: &super::Context) -> Analysis { + [validate_patterns(ctx)] + .into_iter() + .flatten() + .collect::>() + .wrap(|diagnostics| Analysis { diagnostics }) +} + +fn validate_patterns(ctx: &super::Context) -> Vec { + fn validate_pattern( + pattern: &ast::TreePattern, + language: &tree_sitter::Language, + ) -> Option { + match pattern { + ast::TreePattern::Atom(a) => { + if language.id_for_node_kind(a, true) == 0 { + Some(a.to_owned()) + } else { + None + } + } + ast::TreePattern::List(items) => { + for item in items { + validate_pattern(item, language)?; + } + None + } + } + } + + ctx.program + .stanzas + .iter() + .flat_map(|s| match &s.pattern { + ast::Pattern::Begin | ast::Pattern::End => None, + ast::Pattern::Tree { matcher, .. } => { + validate_pattern(matcher, &ctx.language).map(|invalid_node_kind| Kind::Pattern { + invalid_node_kind, + full_pattern: s.pattern.clone(), + }) + } + }) + .map(|kind| Diagnostic { + level: Level::Error, + kind, + }) + .collect() +} -- cgit v1.2.3