diff --git a/lang/README.md b/lang/README.md index 638343b..1e114e6 100644 --- a/lang/README.md +++ b/lang/README.md @@ -527,6 +527,23 @@ main := fn(): uint { ### Purely Testing Examples +#### nonexistent_ident_import +```hb +main := @use("foo.hb").main +// in module: foo.hb +foo := fn(): void { + return +} +foo := fn(): void { + return +} +main := @use("bar.hb").mian +// in module: bar.hb +main := fn(): void { + return +} +``` + #### big_array_crash ```hb SIN_TABLE := [int].(0, 174, 348, 523, 697, 871, 1045, 1218, 1391, 1564, 1736, 1908, 2079, 2249, 2419, 2588, 2756, 2923, 3090, 3255, 3420, 3583, 3746, 3907, 4067, 4226, 4384, 4540, 4695, 4848, 5000, 5150, 5299, 5446, 5591, 5735, 5877, 6018, 6156, 6293, 6427, 6560, 6691, 6819, 6946, 7071, 7193, 7313, 7431, 7547, 7660, 7771, 7880, 7986, 8090, 8191, 8290, 8386, 8480, 8571, 8660, 8746, 8829, 8910, 8987, 9063, 9135, 9205, 9271, 9335, 9396, 9455, 9510, 9563, 9612, 9659, 9702, 9743, 9781, 9816, 9848, 9877, 9902, 9925, 9945, 9961, 9975, 9986, 9993, 9998, 10000) diff --git a/lang/src/codegen.rs b/lang/src/codegen.rs index 42054c3..61bf40f 100644 --- a/lang/src/codegen.rs +++ b/lang/src/codegen.rs @@ -12,7 +12,7 @@ use { TypeParser, TypedReloc, Types, }, alloc::{string::String, vec::Vec}, - core::{assert_matches::debug_assert_matches, fmt::Display}, + core::{assert_matches::debug_assert_matches, fmt::Display, usize}, }; type Offset = u32; @@ -756,8 +756,9 @@ impl TypeParser for Codegen { ty::Kind::Global(gid).compress() } - fn report(&self, pos: Pos, msg: impl Display) -> ty::Id { - self.report(pos, msg) + fn report(&self, file: FileId, pos: Pos, msg: impl Display) -> ty::Id { + log::error!("{}", self.files[file as usize].report(pos, msg)); + unreachable!() } fn find_local_ty(&mut self, name: Ident) -> Option { @@ -785,7 +786,7 @@ impl Codegen { pub fn generate(&mut self, root: FileId) { self.ci.emit_entry_prelude(); self.ci.file = root; - self.find_type(0, root, Err("main"), &self.files.clone()); + self.find_type(0, root, root, Err("main"), &self.files.clone()); self.make_func_reachable(0); self.complete_call_graph(); } @@ -1253,7 +1254,13 @@ impl Codegen { match self.ty(target).expand() { ty::Kind::Module(idx) => { match self - .find_type(pos, idx, Err(field), &self.files.clone()) + .find_type( + pos, + self.ci.file, + idx, + Err(field), + &self.files.clone(), + ) .expand() { ty::Kind::Global(idx) => self.handle_global(idx), @@ -1448,7 +1455,10 @@ impl Codegen { Some(Value { ty: self.ci.vars[var_index].value.ty, loc }) } E::Ident { id, pos, .. } => { - match self.find_type(pos, self.ci.file, Ok(id), &self.files.clone()).expand() { + match self + .find_type(pos, self.ci.file, self.ci.file, Ok(id), &self.files.clone()) + .expand() + { ty::Kind::Global(id) => self.handle_global(id), tk => Some(Value::ty(tk.compress())), } diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 560ba31..49ffc80 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -992,11 +992,12 @@ trait TypeParser { fn eval_const(&mut self, file: FileId, expr: &Expr, ty: ty::Id) -> u64; fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id; fn infer_type(&mut self, expr: &Expr) -> ty::Id; - fn report(&self, pos: Pos, msg: impl Display) -> ty::Id; + fn report(&self, file: FileId, pos: Pos, msg: impl Display) -> ty::Id; fn find_type( &mut self, pos: Pos, + from_file: FileId, file: FileId, id: Result, files: &[parser::Ast], @@ -1017,10 +1018,11 @@ trait TypeParser { let Some((Expr::BinOp { left, right, .. }, name)) = f.find_decl(id) else { return match id { Ok(name) => { - let name = f.ident_str(name); - self.report(pos, format_args!("undefined indentifier: {name}")) + let name = files[from_file as usize].ident_str(name); + self.report(from_file, pos, format_args!("undefined indentifier: {name}")) } Err("main") => self.report( + from_file, pos, format_args!( "missing main function in '{}', compiler can't \ @@ -1028,7 +1030,9 @@ trait TypeParser { f.path ), ), - Err(name) => self.report(pos, format_args!("undefined indentifier: {name}")), + Err(name) => { + self.report(from_file, pos, format_args!("undefined indentifier: {name}")) + } }; }; @@ -1083,12 +1087,12 @@ trait TypeParser { self.tys().make_ptr(base) } Expr::Ident { id, .. } if ident::is_null(id) => id.into(), - Expr::Ident { id, pos, .. } => self.find_type(pos, file, Ok(id), files), + Expr::Ident { id, pos, .. } => self.find_type(pos, file, file, Ok(id), files), Expr::Field { target, pos, name } - if let ty::Kind::Module(file) = + if let ty::Kind::Module(inside) = self.parse_ty(file, target, None, files).expand() => { - self.find_type(pos, file, Err(name), files) + self.find_type(pos, file, inside, Err(name), files) } Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr), Expr::Slice { size: None, item, .. } => { @@ -1159,7 +1163,7 @@ trait TypeParser { } let Some(args) = self.tys().pack_args(arg_base) else { - return self.report(pos, "function has too many argumnets"); + return self.report(file, pos, "function has too many argumnets"); }; let ret = self.parse_ty(file, ret, None, files); diff --git a/lang/src/son.rs b/lang/src/son.rs index 3985335..3983868 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -2041,7 +2041,10 @@ impl<'a> Codegen<'a> { } pub fn generate(&mut self, entry: FileId) { - self.find_type(0, entry, Err("main"), self.files); + self.find_type(0, entry, entry, Err("main"), self.files); + if self.tys.ins.funcs.is_empty() { + return; + } self.make_func_reachable(0); self.complete_call_graph(); } @@ -2107,7 +2110,7 @@ impl<'a> Codegen<'a> { Some(Value::var(index).ty(var.ty)) } Expr::Ident { id, pos, .. } => { - let decl = self.find_type(pos, self.ci.file, Ok(id), self.files); + let decl = self.find_type(pos, self.ci.file, self.ci.file, Ok(id), self.files); match decl.expand() { ty::Kind::Builtin(ty::NEVER) => Value::NEVER, ty::Kind::Global(global) => { @@ -2203,7 +2206,10 @@ impl<'a> Codegen<'a> { let tty = vtarget.ty; if let ty::Kind::Module(m) = tty.expand() { - return match self.find_type(pos, m, Err(name), self.files).expand() { + return match self + .find_type(pos, self.ci.file, m, Err(name), self.files) + .expand() + { ty::Kind::Builtin(ty::NEVER) => Value::NEVER, ty::Kind::Global(global) => { let gl = &self.tys.ins.globals[global as usize]; @@ -3645,8 +3651,9 @@ impl TypeParser for Codegen<'_> { ty.compress() } - fn report(&self, pos: Pos, msg: impl Display) -> ty::Id { - self.report(pos, msg); + fn report(&self, file: FileId, pos: Pos, msg: impl Display) -> ty::Id { + let mut buf = self.errors.borrow_mut(); + write!(buf, "{}", self.files[file as usize].report(pos, msg)).unwrap(); ty::Id::NEVER } @@ -4677,6 +4684,7 @@ mod tests { fb_driver; // Purely Testing Examples; + nonexistent_ident_import; big_array_crash; returning_global_struct; small_struct_bitcast; diff --git a/lang/tests/son_tests_nonexistent_ident_import.txt b/lang/tests/son_tests_nonexistent_ident_import.txt new file mode 100644 index 0000000..85fe9fd --- /dev/null +++ b/lang/tests/son_tests_nonexistent_ident_import.txt @@ -0,0 +1,7 @@ +foo.hb:4:1: redeclaration of identifier: foo +foo := fn(): void { +^ + +foo.hb:7:23: undefined indentifier: mian +main := @use("bar.hb").mian + ^