Skip to content

Commit

Permalink
Refactor backtracing for error line to be much simpler
Browse files Browse the repository at this point in the history
  • Loading branch information
Ernest1338 committed Jan 27, 2025
1 parent 43e80ff commit 9d1d52a
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 257 deletions.
55 changes: 29 additions & 26 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

use crate::{
args::AppArgs,
parser::{
expr_to_line_number, type_check, Ast, BinExpr, FuncCall, Variable, VariableDeclaration,
},
parser::{type_check, Ast, BinExpr, FuncCall, Variable, VariableDeclaration},
utils::{
dbg, dbg_file_if_env, dbg_plain, escape_string, get_tmp_fname, map_line_nr, measure_time,
ErrorInner, ErrorType,
dbg, dbg_file_if_env, dbg_plain, errstr_to_errtype, escape_string, get_tmp_fname,
measure_time, ErrorType,
},
Expr,
};
Expand Down Expand Up @@ -60,6 +58,22 @@ pub struct Compiler {
}

impl Compiler {
/// TODO
pub fn new() -> Self {
Self {
ast: Vec::new(),
ir: String::new(),
data: String::new(),
pk: 0,
variables: HashMap::new(),
}
}

/// TODO
pub fn load_ast(&mut self, ast: Ast) {
self.ast = ast;
}

/// Creates a new `Compiler` instance from the given AST, initializing necessary fields
pub fn from_ast(ast: Ast) -> Self {
Self {
Expand Down Expand Up @@ -252,30 +266,23 @@ impl Compiler {
}

/// Generates the intermediate representation (IR) for the AST and returns it as a string
pub fn generate_ir(&mut self, source_code: &str) -> Result<String, ErrorType> {
pub fn generate_ir(&mut self) -> Result<String, ErrorType> {
self.ir.push_str("export function w $main() {\n@start\n");

let ast = self.ast.clone();

for node in &ast {
match node {
Expr::FuncCall(func_call) => {
map_line_nr(self.handle_func_call(func_call), node, source_code)?
}
Expr::FuncCall(func_call) => errstr_to_errtype(self.handle_func_call(func_call))?,

Expr::VariableDeclaration(variable_declaration) => map_line_nr(
self.handle_var_decl(variable_declaration),
node,
source_code,
)?,
Expr::VariableDeclaration(variable_declaration) => {
errstr_to_errtype(self.handle_var_decl(variable_declaration))?
}

_ => {
return Err(ErrorType::Generic(ErrorInner {
message: format!(
"Expression `{node:?}` in this context is not yet implemented"
),
line_number: expr_to_line_number(node, source_code),
}));
return Err(ErrorType::Generic(format!(
"Expression `{node:?}` in this context is not yet implemented"
)));
}
}
}
Expand All @@ -287,12 +294,8 @@ impl Compiler {

/// Compiles the AST by generating IR, running it through the `qbe` compiler, and then
/// assembling and linking the output with `cc` to produce the final executable
pub fn compile(&mut self, args: &AppArgs, source_code: &str) -> Result<(), ErrorType> {
let ir = format!(
"{}{}",
include_str!("ext.ssa"),
self.generate_ir(source_code)?
);
pub fn compile(&mut self, args: &AppArgs) -> Result<(), ErrorType> {
let ir = format!("{}{}", include_str!("ext.ssa"), self.generate_ir()?);

dbg("Variables", &self.variables);
dbg_plain("Compiled IR", &ir);
Expand Down
30 changes: 10 additions & 20 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use crate::{
parser::{
expr_to_line_number, type_check, Ast, BinExpr, BinOpKind, FuncCall, Variable,
VariableDeclaration,
},
utils::{map_line_nr, ErrorInner, ErrorType},
parser::{type_check, Ast, BinExpr, BinOpKind, FuncCall, Variable, VariableDeclaration},
utils::{errstr_to_errtype, ErrorType},
Expr,
};
use std::{collections::HashMap, fmt};
Expand Down Expand Up @@ -43,33 +40,26 @@ impl Interpreter {
}

/// Runs the interpreter, processing each expression in the AST
pub fn run(&mut self, source_code: &str) -> Result<(), ErrorType> {
pub fn run(&mut self) -> Result<(), ErrorType> {
let ast = self.ast.clone();

for node in &ast {
match node {
Expr::FuncCall(func_call) => {
map_line_nr(self.handle_func_call(func_call), node, source_code)?
Expr::FuncCall(func_call) => errstr_to_errtype(self.handle_func_call(func_call))?,
Expr::VariableDeclaration(variable_declaration) => {
errstr_to_errtype(self.handle_var_decl(variable_declaration))?
}
Expr::VariableDeclaration(variable_declaration) => map_line_nr(
self.handle_var_decl(variable_declaration),
node,
source_code,
)?,
Expr::Identifier(id) => {
// If it's a valid variable, print it
// Probably only useful in the interactive mode
// Should we only restrict this code to such condition?
let var = map_line_nr(self.get_var(id), node, source_code)?;
let var = self.get_var(id).unwrap();
println!("{var}");
}
_ => {
return Err(ErrorType::Generic(ErrorInner {
message: format!(
"Expression `{node:?}` in this context is not yet implemented"
),
line_number: expr_to_line_number(node, source_code),
}))
return Err(ErrorType::Generic(format!(
"Expression `{node:?}` in this context is not yet implemented"
)))
}
}
}
Expand Down
39 changes: 17 additions & 22 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::{
compiler::Compiler,
interpreter::Interpreter,
parser::get_parser_line_number,
utils::{display_error, ErrorInner, ErrorType, Output},
utils::{display_error, ErrorType, Output},
};
use std::{
fs::{canonicalize, read_to_string},
Expand Down Expand Up @@ -84,15 +83,15 @@ fn main() {
let tokens = match lexer(&code) {
Ok(tokens) => tokens,
Err(err) => {
display_error(err, Output::Stdout);
display_error(err, &code, Output::Stdout);
continue;
}
};
let mut parser = Parser::new(&tokens);
let ast = match parser.parse() {
Ok(ast) => ast,
Err(err) => {
display_error(err, Output::Stdout);
display_error(err, &code, Output::Stdout);
continue;
}
};
Expand All @@ -101,9 +100,9 @@ fn main() {
// Clear last line
print!("\x1b[1A\x1b[2K");

let res = interpreter.run(&input);
let res = interpreter.run();
if let Err(err) = res {
display_error(err, Output::Stdout);
display_error(err, &code, Output::Stdout);
}
}
}
Expand All @@ -116,10 +115,8 @@ fn main() {
Ok(input) => input,
Err(_) => {
display_error(
ErrorType::Generic(ErrorInner {
message: "Could not read source code file".to_string(),
line_number: None,
}),
ErrorType::Generic("Could not read source code file".to_string()),
"",
Output::Stderr,
);
exit(1);
Expand All @@ -139,7 +136,7 @@ fn main() {
let tokens = measure_time("Lexical Analysis", || match lexer(&source_code) {
Ok(tokens) => tokens,
Err(err) => {
display_error(err, Output::Stderr);
display_error(err, &orig_source_code, Output::Stderr);
exit(1);
}
});
Expand All @@ -153,14 +150,12 @@ fn main() {
Ok(ast) => ast,
Err(err) => {
let message = match err {
ErrorType::SyntaxError(e) => e.message,
ErrorType::SyntaxError(e) => e,
_ => "".to_string(),
};
display_error(
ErrorType::SyntaxError(ErrorInner {
message,
line_number: get_parser_line_number(&orig_source_code),
}),
ErrorType::SyntaxError(message),
&orig_source_code,
Output::Stderr,
);
exit(1);
Expand All @@ -174,8 +169,8 @@ fn main() {
// -----------
let mut interpreter = Interpreter::from_ast(ast);
measure_time("Interpreter Execution", || {
if let Err(err) = interpreter.run(&orig_source_code) {
display_error(err, Output::Stderr);
if let Err(err) = interpreter.run() {
display_error(err, &orig_source_code, Output::Stderr);
exit(1);
}
});
Expand All @@ -185,8 +180,8 @@ fn main() {
// ---------------
let mut compiler = Compiler::from_ast(ast);
measure_time("Full Compiler Execution", || {
if let Err(err) = compiler.compile(&args, &orig_source_code) {
display_error(err, Output::Stderr);
if let Err(err) = compiler.compile(&args) {
display_error(err, &orig_source_code, Output::Stderr);
exit(1);
}
});
Expand All @@ -206,8 +201,8 @@ fn main() {
// --------
let mut compiler = Compiler::from_ast(ast);
measure_time("Full Compiler Execution", || {
if let Err(err) = compiler.compile(&args, &orig_source_code) {
display_error(err, Output::Stderr);
if let Err(err) = compiler.compile(&args) {
display_error(err, &orig_source_code, Output::Stderr);
exit(1);
}
});
Expand Down
Loading

0 comments on commit 9d1d52a

Please sign in to comment.