Update executable x-lint

This commit is contained in:
Guojie Luo 2022-02-19 17:43:44 +08:00
parent 43ce73e5e2
commit cda478df3e
5 changed files with 98 additions and 15 deletions

View File

@ -44,7 +44,7 @@ fn main_inner() -> Result<(), String> {
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST); assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
let module_list = DescriptionList::codegen(json_tree); let module_list = DescriptionList::codegen(json_tree);
for module in module_list { for (module, _) in module_list {
println!("{}", module.dump()); println!("{}", module.dump());
} }

View File

@ -3,7 +3,7 @@ extern crate clap;
extern crate json; extern crate json;
use clap::Arg; use clap::Arg;
use cst_to_llhd::cst::{DescriptionList, Tag}; use cst_to_llhd::cst::{CodeReporter, DescriptionList, Tag, Tools};
use std::{ use std::{
process::{Command, Stdio}, process::{Command, Stdio},
result::Result, result::Result,
@ -77,22 +77,45 @@ fn main_inner() -> Result<(), std::io::Error> {
assert!(json_top.len() == 1); assert!(json_top.len() == 1);
let sv_file_name = json_top.entries().next().unwrap().0; let sv_file_name = json_top.entries().next().unwrap().0;
println!(r#"codegen from CST to LLHD for "{}" ..."#, sv_file_name);
println!(""); let code_reporter = CodeReporter::new(sv_file_name);
let json_tree = &json_top[sv_file_name]["tree"]; let json_tree = &json_top[sv_file_name]["tree"];
assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST); assert!(json_tree["tag"] == Tag::DESCRIPTION_LIST);
let module_list = DescriptionList::codegen(json_tree); let module_list = DescriptionList::codegen(json_tree);
for module in module_list { for (module, json_module) in module_list {
for entity in module.entities() { for entity in module.entities() {
println!( if entity.input_args().count() == 0 || entity.output_args().count() == 0 {
r#"entity "{}" has {} input ports and {} output ports"#, let json_terminal = Tools::match_tags(
entity.name(), vec![json_module],
entity.input_args().count(), vec![
entity.output_args().count() Tag::MODULE_DECLARATION,
); Tag::MODULE_HEADER,
println!(""); Tag::SYMBOL_IDENTIFIER,
],
);
assert_eq!(json_terminal.len(), 1);
let start = json_terminal[0]["start"]
.to_string()
.parse::<usize>()
.unwrap();
let line_no = code_reporter.line_no(start);
println!(
"{}:{} | {}",
sv_file_name,
line_no + 1,
code_reporter.line(line_no)
);
println!(
r#"[warning] missing ports: entity "{}" has {} input ports and {} output ports"#,
entity.name(),
entity.input_args().count(),
entity.output_args().count()
);
println!("");
}
} }
} }

View File

@ -5,13 +5,13 @@ use llhd::ir::Module;
pub struct DescriptionList {} pub struct DescriptionList {}
impl DescriptionList { impl DescriptionList {
pub fn codegen(json: &JsonValue) -> Vec<Module> { pub fn codegen(json: &JsonValue) -> Vec<(Module, &JsonValue)> {
Tools::match_tags( Tools::match_tags(
vec![json], vec![json],
vec![Tag::DESCRIPTION_LIST, Tag::MODULE_DECLARATION], vec![Tag::DESCRIPTION_LIST, Tag::MODULE_DECLARATION],
) )
.iter() .iter()
.map(|&x| ModuleDeclaration::codegen(x)) .map(|&x| (ModuleDeclaration::codegen(x), x))
.collect() .collect()
} }
} }

View File

@ -12,4 +12,4 @@ pub use description_list::DescriptionList;
use module_declaration::ModuleDeclaration; use module_declaration::ModuleDeclaration;
use procedural_timing_control_statement::ProceduralTimingControlStatement; use procedural_timing_control_statement::ProceduralTimingControlStatement;
pub use tags::Tag; pub use tags::Tag;
use tools::Tools; pub use tools::{CodeReporter, Tools};

View File

@ -1,4 +1,8 @@
use json::JsonValue; use json::JsonValue;
use std::{
fs::File,
io::{BufRead, BufReader},
};
pub struct Tools {} pub struct Tools {}
@ -15,3 +19,59 @@ impl Tools {
.collect() .collect()
} }
} }
pub struct CodeReporter {
file_name: String,
line_breakers: Vec<usize>,
}
impl CodeReporter {
pub fn new(file_name: &str) -> Self {
Self {
file_name: file_name.to_string(),
line_breakers: Self::read_line_breakers(file_name),
}
}
pub fn line_no(&self, key: usize) -> usize {
self.line_no_rec(key, 0, self.line_breakers.len() - 1)
}
pub fn line(&self, line_no: usize) -> String {
let reader = BufReader::new(
File::open(self.file_name.as_str())
.expect(format!(r#"file "{}" not found"#, self.file_name.as_str()).as_str()),
);
reader.lines().nth(line_no).unwrap().unwrap()
}
fn read_line_breakers(file_name: &str) -> Vec<usize> {
let reader = BufReader::new(
File::open(file_name).expect(format!(r#"file "{}" not found"#, file_name).as_str()),
);
let mut line_breakers = Vec::new();
line_breakers.push(0);
for line in reader.lines() {
let line_no = 1 + line_breakers.last().unwrap() + line.unwrap().len();
line_breakers.push(line_no);
}
line_breakers
}
fn line_no_rec(&self, key: usize, left: usize, right: usize) -> usize {
if left + 1 >= right {
left
} else {
let mid = (left + right) / 2;
if key < self.line_breakers[mid] {
self.line_no_rec(key, left, mid)
} else {
self.line_no_rec(key, mid, right)
}
}
}
}