mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Fix mutate_ident bug, improve diagnostics
This commit is contained in:
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user