adding better error reporting when compiler crashes errors are now sent trough out buffer
This commit is contained in:
parent
0374848b28
commit
455f70db6e
|
@ -482,15 +482,6 @@ pub mod test {
|
|||
|
||||
let mut ctx = Ctx::default();
|
||||
let ast = parser::Ast::new(ident, minned, &mut ctx, &mut parser::no_loader);
|
||||
//log::error!(
|
||||
// "{} / {} = {} | {} / {} = {}",
|
||||
// ast.mem.size(),
|
||||
// input.len(),
|
||||
// ast.mem.size() as f32 / input.len() as f32,
|
||||
// ast.mem.size(),
|
||||
// ast.file.len(),
|
||||
// ast.mem.size() as f32 / ast.file.len() as f32
|
||||
//);
|
||||
let mut output = String::new();
|
||||
write!(output, "{ast}").unwrap();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use {
|
||||
crate::{
|
||||
parser::{self, Ast, Ctx, FileKind},
|
||||
parser::{Ast, Ctx, FileKind},
|
||||
son::{self, hbvm::HbvmBackend},
|
||||
},
|
||||
alloc::{string::String, vec::Vec},
|
||||
|
@ -42,10 +42,10 @@ pub struct Options {
|
|||
}
|
||||
|
||||
impl Options {
|
||||
pub fn from_args(args: &[&str]) -> std::io::Result<Self> {
|
||||
pub fn from_args(args: &[&str], out: &mut Vec<u8>) -> std::io::Result<Self> {
|
||||
if args.contains(&"--help") || args.contains(&"-h") {
|
||||
log::error!("Usage: hbc [OPTIONS...] <FILE>");
|
||||
log::error!(include_str!("../command-help.txt"));
|
||||
writeln!(out, "Usage: hbc [OPTIONS...] <FILE>")?;
|
||||
writeln!(out, include_str!("../command-help.txt"))?;
|
||||
return Err(std::io::ErrorKind::Other.into());
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,9 @@ impl Options {
|
|||
.position(|&a| a == "--threads")
|
||||
.map(|i| {
|
||||
args[i + 1].parse::<NonZeroUsize>().map_err(|e| {
|
||||
std::io::Error::other(format!("--threads expects non zero integer: {e}"))
|
||||
writeln!(out, "--threads expects non zero integer: {e}")
|
||||
.err()
|
||||
.unwrap_or(std::io::ErrorKind::Other.into())
|
||||
})
|
||||
})
|
||||
.transpose()?
|
||||
|
@ -71,32 +73,22 @@ impl Options {
|
|||
pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std::io::Result<()> {
|
||||
let parsed = parse_from_fs(options.extra_threads, root_file)?;
|
||||
|
||||
fn format_ast(ast: parser::Ast) -> std::io::Result<()> {
|
||||
let mut output = String::new();
|
||||
write!(output, "{ast}").unwrap();
|
||||
if ast.file.deref().trim() != output.as_str().trim() {
|
||||
std::fs::write(&*ast.path, output)?;
|
||||
}
|
||||
Ok(())
|
||||
if (options.fmt || options.fmt_stdout) && !parsed.errors.is_empty() {
|
||||
*out = parsed.errors.into_bytes();
|
||||
return Err(std::io::Error::other("fmt fialed (errors are in out)"));
|
||||
}
|
||||
|
||||
if options.fmt {
|
||||
if !parsed.errors.is_empty() {
|
||||
*out = parsed.errors.into_bytes();
|
||||
return Err(std::io::Error::other("parsing fialed"));
|
||||
}
|
||||
|
||||
for parsed in parsed.ast {
|
||||
format_ast(parsed)?;
|
||||
let mut output = String::new();
|
||||
for ast in parsed.ast {
|
||||
write!(output, "{ast}").unwrap();
|
||||
if ast.file.deref().trim() != output.as_str().trim() {
|
||||
std::fs::write(&*ast.path, &output)?;
|
||||
}
|
||||
output.clear();
|
||||
}
|
||||
} else if options.fmt_stdout {
|
||||
if !parsed.errors.is_empty() {
|
||||
*out = parsed.errors.into_bytes();
|
||||
return Err(std::io::Error::other("parsing fialed"));
|
||||
}
|
||||
|
||||
let ast = parsed.ast.into_iter().next().unwrap();
|
||||
write!(out, "{ast}").unwrap();
|
||||
write!(out, "{}", &parsed.ast[0])?;
|
||||
} else {
|
||||
let mut backend = HbvmBackend::default();
|
||||
let mut ctx = crate::son::CodegenCtx::default();
|
||||
|
@ -107,8 +99,9 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
|
|||
codegen.generate(0);
|
||||
|
||||
if !codegen.errors.borrow().is_empty() {
|
||||
log::error!("{}", codegen.errors.borrow());
|
||||
return Err(std::io::Error::other("compilation faoled"));
|
||||
drop(codegen);
|
||||
*out = ctx.parser.errors.into_inner().into_bytes();
|
||||
return Err(std::io::Error::other("compilation faoled (errors are in out)"));
|
||||
}
|
||||
|
||||
codegen.assemble(out);
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
#[cfg(feature = "std")]
|
||||
fn main() -> std::io::Result<()> {
|
||||
fn main() {
|
||||
use std::io::Write;
|
||||
|
||||
log::set_logger(&hblang::Logger).unwrap();
|
||||
log::set_max_level(log::LevelFilter::Info);
|
||||
fn run(out: &mut Vec<u8>) -> std::io::Result<()> {
|
||||
let args = std::env::args().collect::<Vec<_>>();
|
||||
let args = args.iter().map(String::as_str).collect::<Vec<_>>();
|
||||
|
||||
let args = std::env::args().collect::<Vec<_>>();
|
||||
let args = args.iter().map(String::as_str).collect::<Vec<_>>();
|
||||
let opts = hblang::Options::from_args(&args, out)?;
|
||||
let file = args.iter().filter(|a| !a.starts_with('-')).nth(1).copied().unwrap_or("main.hb");
|
||||
|
||||
let opts = hblang::Options::from_args(&args)?;
|
||||
let file = args.iter().filter(|a| !a.starts_with('-')).nth(1).copied().unwrap_or("main.hb");
|
||||
hblang::run_compiler(file, opts, out)
|
||||
}
|
||||
|
||||
let mut out = Vec::new();
|
||||
hblang::run_compiler(file, opts, &mut out)?;
|
||||
std::io::stdout().write_all(&out)
|
||||
match run(&mut out) {
|
||||
Ok(_) => std::io::stdout().write_all(&out).unwrap(),
|
||||
Err(_) => std::io::stderr().write_all(&out).unwrap(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -282,6 +282,14 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
|
||||
fn unit_expr(&mut self) -> Option<Expr<'a>> {
|
||||
use {Expr as E, TokenKind as T};
|
||||
|
||||
if matches!(
|
||||
self.token.kind,
|
||||
T::RParen | T::RBrace | T::RBrack | T::Comma | T::Semi | T::Else
|
||||
) {
|
||||
self.report(self.token.start, "expected expression")?;
|
||||
}
|
||||
|
||||
let frame = self.ctx.idents.len();
|
||||
let token @ Token { start: pos, .. } = self.next();
|
||||
let prev_boundary = self.ns_bound;
|
||||
|
|
|
@ -17,7 +17,7 @@ use {
|
|||
CompState, FTask, Func, Global, Ident, Offset, OffsetIter, OptLayout, Sig, StringRef,
|
||||
SymKey, TypeParser, Types,
|
||||
},
|
||||
alloc::{string::String, vec::Vec},
|
||||
alloc::{rc::Rc, string::String, vec::Vec},
|
||||
core::{
|
||||
assert_matches::debug_assert_matches,
|
||||
cell::{Cell, RefCell},
|
||||
|
@ -2017,6 +2017,7 @@ impl Scope {
|
|||
#[derive(Default, Clone)]
|
||||
pub struct ItemCtx {
|
||||
file: FileId,
|
||||
pos: Vec<Pos>,
|
||||
ret: Option<ty::Id>,
|
||||
task_base: usize,
|
||||
inline_var_base: usize,
|
||||
|
@ -2195,27 +2196,9 @@ impl CodegenCtx {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Errors<'a>(&'a RefCell<String>);
|
||||
|
||||
impl Deref for Errors<'_> {
|
||||
type Target = RefCell<String>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Errors<'_> {
|
||||
fn drop(&mut self) {
|
||||
if debug::panicking() && !self.0.borrow().is_empty() {
|
||||
log::error!("{}", self.0.borrow());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Codegen<'a> {
|
||||
pub files: &'a [parser::Ast],
|
||||
pub errors: Errors<'a>,
|
||||
pub errors: &'a RefCell<String>,
|
||||
tys: &'a mut Types,
|
||||
ci: ItemCtx,
|
||||
pool: &'a mut Pool,
|
||||
|
@ -2224,6 +2207,20 @@ pub struct Codegen<'a> {
|
|||
backend: &'a mut dyn Backend,
|
||||
}
|
||||
|
||||
impl Drop for Codegen<'_> {
|
||||
fn drop(&mut self) {
|
||||
if debug::panicking() {
|
||||
if let Some(&pos) = self.ci.pos.last() {
|
||||
self.report(pos, "panic occured here");
|
||||
}
|
||||
|
||||
if !self.errors.borrow().is_empty() {
|
||||
log::error!("{}", self.errors.borrow());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Codegen<'a> {
|
||||
pub fn new(
|
||||
backend: &'a mut dyn Backend,
|
||||
|
@ -2232,7 +2229,7 @@ impl<'a> Codegen<'a> {
|
|||
) -> Self {
|
||||
Self {
|
||||
files,
|
||||
errors: Errors(&ctx.parser.errors),
|
||||
errors: &ctx.parser.errors,
|
||||
tys: &mut ctx.tys,
|
||||
ci: Default::default(),
|
||||
pool: &mut ctx.pool,
|
||||
|
@ -2427,7 +2424,14 @@ impl<'a> Codegen<'a> {
|
|||
self.raw_expr_ctx(expr, Ctx::default())
|
||||
}
|
||||
|
||||
fn raw_expr_ctx(&mut self, expr: &Expr, mut ctx: Ctx) -> Option<Value> {
|
||||
fn raw_expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option<Value> {
|
||||
self.ci.pos.push(expr.pos());
|
||||
let res = self.raw_expr_ctx_low(expr, ctx);
|
||||
self.ci.pos.pop().unwrap();
|
||||
res
|
||||
}
|
||||
|
||||
fn raw_expr_ctx_low(&mut self, expr: &Expr, mut ctx: Ctx) -> Option<Value> {
|
||||
// ordered by complexity of the expression
|
||||
match *expr {
|
||||
Expr::Null { pos } => {
|
||||
|
|
Loading…
Reference in a new issue