From 130d3eb32eedce78bfd5e596c5c90d7fbe9d495b Mon Sep 17 00:00:00 2001 From: Halid Odat Date: Thu, 10 Nov 2022 17:04:21 +0100 Subject: [PATCH] Add CLI option for generating flowgraphs --- boa_cli/src/main.rs | 42 ++++++++++++++++++++++++++++++++- boa_engine/src/vm/code_block.rs | 6 +---- boa_engine/src/vm/graph.rs | 3 +-- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/boa_cli/src/main.rs b/boa_cli/src/main.rs index 82da7c5cf8c..d128a6ed7df 100644 --- a/boa_cli/src/main.rs +++ b/boa_cli/src/main.rs @@ -60,7 +60,12 @@ )] use boa_ast::StatementList; -use boa_engine::Context; +use boa_engine::{ + vm::{ + graph::{Direction, Graph}, + }, + Context, JsResult, +}; use clap::{Parser, ValueEnum, ValueHint}; use colored::{Color, Colorize}; use rustyline::{config::Config, error::ReadlineError, EditMode, Editor}; @@ -104,6 +109,10 @@ struct Opt { #[arg(long, short)] trace: bool, + /// Generate instruction flowgraph. Default is Graphviz. + #[arg(long, value_name = "FORMAT", ignore_case = true, value_enum)] + flowgraph: Option>, + /// Use vi mode in the REPL #[arg(long = "vi")] vi_mode: bool, @@ -136,6 +145,14 @@ enum DumpFormat { JsonPretty, } +#[derive(Debug, Clone, Copy, ValueEnum)] +enum FlowgraphFormat { + /// Generates in graphviz format. + Graphviz, + /// Generates in mermaid format. + Mermaid, +} + /// Parses the the token stream into an AST and returns it. /// /// Returns a error of type String with a message, @@ -184,6 +201,19 @@ where Ok(()) } +fn generate_flowgraph(context: &mut Context, src: &[u8], flowgraph: FlowgraphFormat) -> JsResult { + let ast = context.parse(src)?; + let code = context.compile(&ast)?; + + let mut graph = Graph::new(Direction::TopToBottom); + code.to_graph(context.interner(), graph.subgraph(String::default())); + let result = match flowgraph { + FlowgraphFormat::Graphviz => graph.to_graphviz_format(), + FlowgraphFormat::Mermaid => graph.to_mermaid_format(), + }; + Ok(result) +} + pub fn main() -> Result<(), io::Error> { let args = Opt::parse(); @@ -199,6 +229,11 @@ pub fn main() -> Result<(), io::Error> { if let Err(e) = dump(&buffer, &args, &mut context) { eprintln!("{e}"); } + } else if let Some(flowgraph) = args.flowgraph { + match generate_flowgraph(&mut context, &buffer, flowgraph.unwrap_or(FlowgraphFormat::Graphviz)) { + Ok(v) => println!("{}", v), + Err(v) => eprintln!("Uncaught {v}"), + } } else { match context.eval(&buffer) { Ok(v) => println!("{}", v.display()), @@ -245,6 +280,11 @@ pub fn main() -> Result<(), io::Error> { if let Err(e) = dump(&line, &args, &mut context) { eprintln!("{e}"); } + } else if let Some(flowgraph) = args.flowgraph { + match generate_flowgraph(&mut context, line.trim_end().as_bytes(), flowgraph.unwrap_or(FlowgraphFormat::Graphviz)) { + Ok(v) => println!("{}", v), + Err(v) => eprintln!("Uncaught {v}"), + } } else { match context.eval(line.trim_end()) { Ok(v) => println!("{}", v.display()), diff --git a/boa_engine/src/vm/code_block.rs b/boa_engine/src/vm/code_block.rs index 5c0741d5a13..a8444e20725 100644 --- a/boa_engine/src/vm/code_block.rs +++ b/boa_engine/src/vm/code_block.rs @@ -20,7 +20,7 @@ use crate::{ }, property::PropertyDescriptor, vm::call_frame::GeneratorResumeKind, - vm::{call_frame::FinallyReturn, graph::Graph, CallFrame, Opcode}, + vm::{call_frame::FinallyReturn, CallFrame, Opcode}, Context, JsResult, JsString, JsValue, }; use boa_ast::{expression::Identifier, function::FormalParameterList}; @@ -465,10 +465,6 @@ impl ToInternedString for CodeBlock { } } - let mut graph = Graph::new(crate::vm::graph::Direction::TopToBottom); - self.to_graph(interner, graph.subgraph(String::default())); - println!("\n{}\n", graph.to_mermaid_format()); - f } } diff --git a/boa_engine/src/vm/graph.rs b/boa_engine/src/vm/graph.rs index 678eb589651..40cfb9ab742 100644 --- a/boa_engine/src/vm/graph.rs +++ b/boa_engine/src/vm/graph.rs @@ -236,8 +236,7 @@ impl SubGraph { }; let style = match edge.style { EdgeStyle::Line => "-->", - EdgeStyle::Dotted => "-.->", - EdgeStyle::Dashed => "-.->", + EdgeStyle::Dotted | EdgeStyle::Dashed => "-.->", }; result.push_str(&format!( " {}_i_{} {style}| {}| {}_i_{}\n",