Fix mutate_ident bug, improve diagnostics

This commit is contained in:
Andrew Morris
2023-02-20 12:09:00 +11:00
parent b03102227c
commit b4ed80b307
4 changed files with 80 additions and 33 deletions

View File

@@ -31,7 +31,7 @@ pub fn command(args: &Vec<String>) {
let program = parse(&args[2]);
let compiler_output = compile(&program);
handle_diagnostics_cli(&compiler_output.diagnostics);
handle_diagnostics_cli(&args[2], &compiler_output.diagnostics);
let mut file = File::create("out.vsm").expect("Couldn't create out.vsm");

View File

@@ -1,7 +1,21 @@
use std::fmt;
pub enum DiagnosticLevel {
Lint,
Error,
InternalError,
CompilerDebug,
}
impl fmt::Display for DiagnosticLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DiagnosticLevel::Lint => write!(f, "Lint"),
DiagnosticLevel::Error => write!(f, "Error"),
DiagnosticLevel::InternalError => write!(f, "Internal Error"),
DiagnosticLevel::CompilerDebug => write!(f, "Compiler Debug"),
}
}
}
pub struct Diagnostic {
@@ -10,22 +24,25 @@ pub struct Diagnostic {
pub span: swc_common::Span,
}
pub fn handle_diagnostics_cli(diagnostics: &Vec<Diagnostic>) {
pub fn handle_diagnostics_cli(file_path: &String, diagnostics: &Vec<Diagnostic>) {
let mut has_error = false;
let text = std::fs::read_to_string(file_path).unwrap();
for diagnostic in diagnostics {
let (line, col) = pos_to_line_col(&text, diagnostic.span.lo.0);
println!(
"{}:{}:{}: {}: {}",
file_path, line, col, diagnostic.level, diagnostic.message
);
match diagnostic.level {
DiagnosticLevel::Lint => {
println!("Lint: {}", diagnostic.message);
}
DiagnosticLevel::Error => {
println!("Error: {}", diagnostic.message);
has_error = true;
}
DiagnosticLevel::InternalError => {
println!("Internal Error: {}", diagnostic.message);
DiagnosticLevel::Error | DiagnosticLevel::InternalError => {
has_error = true;
}
DiagnosticLevel::Lint => {}
DiagnosticLevel::CompilerDebug => {}
}
}
@@ -33,3 +50,23 @@ pub fn handle_diagnostics_cli(diagnostics: &Vec<Diagnostic>) {
std::process::exit(1);
}
}
fn pos_to_line_col(text: &String, pos: u32) -> (u32, u32) {
let mut line = 1u32;
let mut col = 1u32;
for (i, c) in text.chars().enumerate() {
if i as u32 == pos {
break;
}
if c == '\n' {
line += 1;
col = 1;
} else {
col += 1;
}
}
return (line, col);
}

View File

@@ -92,7 +92,7 @@ fn to_bytecode(format: RunFormat, file_path: &String) -> Rc<Vec<u8>> {
RunFormat::TypeScript => {
let ast = parse(file_path);
let compiler_output = compile(&ast);
handle_diagnostics_cli(&compiler_output.diagnostics);
handle_diagnostics_cli(file_path, &compiler_output.diagnostics);
let mut assembly = String::new();

View File

@@ -121,24 +121,24 @@ impl ScopeAnalysis {
}
fn insert_capture(&mut self, captor_id: &OwnerId, name_id: &NameId, ref_: swc_common::Span) {
self
.captures
.entry(captor_id.clone())
.or_insert_with(HashSet::new)
.insert(ref_);
let name = match self.names.get_mut(name_id) {
Some(name) => name,
None => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::InternalError,
message: format!("Internal: expected name_id in names: {:?}", name_id),
message: format!("Expected name_id in names: {:?}", name_id),
span: ref_,
});
return;
}
};
self
.captures
.entry(captor_id.clone())
.or_insert_with(HashSet::new)
.insert(ref_);
name.captures.push(Capture {
ref_,
captor_id: captor_id.clone(),
@@ -601,7 +601,7 @@ impl ScopeAnalysis {
match expr {
Expr::Ident(ident) => {
self.mutate_ident(ident);
self.mutate_ident(scope, ident);
}
Expr::Member(member) => {
self.mutate_expr(scope, &member.obj);
@@ -834,7 +834,7 @@ impl ScopeAnalysis {
match pat {
Pat::Ident(ident) => {
self.mutate_ident(&ident.id);
self.mutate_ident(scope, &ident.id);
}
Pat::Array(array_pat) => {
for elem in &array_pat.elems {
@@ -855,7 +855,7 @@ impl ScopeAnalysis {
swc_ecma_ast::ObjectPatProp::Assign(assign) => {
// TODO: How is `({ y: x = 3 } = { y: 4 })` handled?
self.mutate_ident(&assign.key);
self.mutate_ident(scope, &assign.key);
if let Some(value) = &assign.value {
// Note: Generally mutate_* only processes the mutation aspect
@@ -893,13 +893,25 @@ impl ScopeAnalysis {
}
}
fn mutate_ident(&mut self, ident: &swc_ecma_ast::Ident) {
let name = match self.names.get_mut(&NameId::Span(ident.span)) {
Some(name) => name,
fn mutate_ident(&mut self, scope: &XScope, ident: &swc_ecma_ast::Ident) {
let name_id = match scope.get(&ident.sym) {
Some(name_id) => name_id,
None => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::Error,
message: "Unresolved reference".to_string(),
message: "Unresolved reference (mutate_ident)".to_string(),
span: ident.span,
});
return;
}
};
let name = match self.names.get_mut(&name_id) {
Some(name) => name,
None => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::InternalError,
message: "Expected name_id in names".to_string(),
span: ident.span,
});
return;
@@ -915,7 +927,7 @@ impl ScopeAnalysis {
None => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::Error,
message: "Unresolved reference".to_string(),
message: "Unresolved reference (ident)".to_string(),
span: ident.span,
});
return;
@@ -927,7 +939,7 @@ impl ScopeAnalysis {
None => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::InternalError,
message: "Internal: expected name_id in names".to_string(),
message: "Expected name_id in names".to_string(),
span: ident.span,
});
return;
@@ -1015,11 +1027,9 @@ impl ScopeAnalysis {
});
}
Stmt::Return(return_) => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::Error,
message: "Invalid: module level return statement".to_string(),
span: return_.span,
});
if let Some(arg) = &return_.arg {
self.expr(&scope, arg);
}
}
Stmt::Labeled(labeled_stmt) => {
self.stmt(&scope, &labeled_stmt.body);