diff --git a/lang/README.md b/lang/README.md index f3f0cea0a..c3be9401f 100644 --- a/lang/README.md +++ b/lang/README.md @@ -427,6 +427,9 @@ $SOME_CONST := 34 foo := @use("foo.hb") main := fn(): uint { + if false { + @error("unexpected '\0", u8, "', wah now?\0") + } byte := @as(u8, 10) _ = sum(byte, byte) same_type_as_byte := @as(@TypeOf(byte), 30) @@ -474,6 +477,7 @@ arbitrary text - `@len()`: reports a length of the type of indexing purposes or length ot a string constant - `@kindof()`: gives an u8 integer describing the kind of type as an index to array `[Builtin, Struct, Enum, Union, Ptr, Slice, Opt, Func, Template, Global, Const, Module]` - `@Any()`: generic parameter based on inference, TBD: this will ake arguments in the future that restrict what is accepted +- `@error(...)`: emit compiler error, if reachable, and use arguments to construct a message, can display strings and types #### c_strings ```hb diff --git a/lang/src/son.rs b/lang/src/son.rs index 99542c786..78200b348 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -1482,6 +1482,35 @@ impl<'a> Codegen<'a> { self.assert_ty(expr.pos(), &mut val, ty, "hinted expr"); Some(val) } + Expr::Directive { pos, name: "error", args } => { + let mut error_msg = String::new(); + for arg in args { + let Some(val) = self.expr(arg) else { + self.error(arg.pos(), "unreachable argument"); + continue; + }; + match self.ci.nodes[val.id].kind { + Kind::Global { global } + if let Ok(str) = core::str::from_utf8( + &self.tys.ins.globals[global].data + [..self.tys.ins.globals[global].data.len() - 1], + ) => + { + error_msg.push_str(str) + } + Kind::CInt { value } if val.ty == ty::Id::TYPE => { + _ = write!( + error_msg, + "{}", + ty::Display::new(self.tys, self.files, ty::Id::from(value as u64)) + ) + } + _ => _ = self.error(arg.pos(), "expression can not (yet) be displayed"), + } + } + self.error(pos, error_msg); + None + } Expr::Directive { pos, name: "eca", args } => { inference!(ty, ctx, self, pos, "return type", "@as(, @eca(...))");