adding more type checking
This commit is contained in:
parent
00ad474881
commit
894f73ca35
|
@ -695,7 +695,7 @@ example := fn(): void {
|
|||
loop {
|
||||
random_x := @inline(random.integer, 0, 1024)
|
||||
random_y := random.integer(0, 768)
|
||||
a := @inline(screenidx, random_x, random_y)
|
||||
a := @inline(screenidx, random_x)
|
||||
break
|
||||
}
|
||||
return
|
||||
|
@ -725,3 +725,15 @@ integer := fn(min: int, max: int): int {
|
|||
return rng
|
||||
}
|
||||
```
|
||||
|
||||
#### some_generic_code
|
||||
```hb
|
||||
some_func := fn($Elem: type): void {
|
||||
return
|
||||
}
|
||||
|
||||
main := fn(): void {
|
||||
some_func(0)
|
||||
return
|
||||
}
|
||||
```
|
||||
|
|
|
@ -110,7 +110,7 @@ fn gen_instrs() -> Result<(), Box<dyn std::error::Error>> {
|
|||
generated.pop();
|
||||
writeln!(generated, " => {{")?;
|
||||
if iter_args(ty).count() != 0 {
|
||||
writeln!(generated, " let data = unsafe {{ std::ptr::read(bytes.take(..std::mem::size_of::<{ty}>())?.as_ptr() as *const {ty}) }};")?;
|
||||
writeln!(generated, " let data = crate::decode::<{ty}>(bytes)?;")?;
|
||||
writeln!(
|
||||
generated,
|
||||
" buf.extend([{}]);",
|
||||
|
@ -119,7 +119,7 @@ fn gen_instrs() -> Result<(), Box<dyn std::error::Error>> {
|
|||
)
|
||||
)?;
|
||||
} else {
|
||||
writeln!(generated, " bytes.take(..std::mem::size_of::<{ty}>())?;")?;
|
||||
writeln!(generated, " crate::decode::<{ty}>(bytes)?;")?;
|
||||
}
|
||||
|
||||
writeln!(generated, " }}")?;
|
||||
|
|
|
@ -8,7 +8,7 @@ use {
|
|||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||
HashMap,
|
||||
},
|
||||
std::{ops::Range, rc::Rc, u32},
|
||||
std::{fmt::Display, ops::Range, rc::Rc},
|
||||
};
|
||||
|
||||
type Offset = u32;
|
||||
|
@ -1438,7 +1438,7 @@ impl Codegen {
|
|||
let mut base_val = self.expr(base)?;
|
||||
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
||||
let index_val = self.expr(index)?;
|
||||
_ = self.assert_ty(index.pos(), index_val.ty, ty::INT.into());
|
||||
_ = self.assert_ty(index.pos(), index_val.ty, ty::INT.into(), "subsctipt");
|
||||
|
||||
if let ty::Kind::Ptr(ty) = base_val.ty.expand() {
|
||||
base_val.ty = self.tys.ptrs[ty as usize].base;
|
||||
|
@ -1501,6 +1501,8 @@ impl Codegen {
|
|||
let scope = self.ci.vars.len();
|
||||
let sig = self.compute_signature(&mut func, func_ast.pos(), args)?;
|
||||
|
||||
self.assert_arg_count(expr.pos(), args.len(), cargs.len(), "inline function call");
|
||||
|
||||
if scope == self.ci.vars.len() {
|
||||
for ((arg, ty), carg) in
|
||||
args.iter().zip(sig.args.view(&self.tys.args).to_owned()).zip(cargs)
|
||||
|
@ -1881,7 +1883,10 @@ impl Codegen {
|
|||
let mut values = Vec::with_capacity(args.len());
|
||||
let mut sig_args = sig.args.range();
|
||||
let mut should_momize = !args.is_empty() && sig.ret == ty::Id::from(ty::TYPE);
|
||||
for (arg, carg) in args.iter().zip(cargs) {
|
||||
|
||||
self.assert_arg_count(expr.pos(), args.len(), cargs.len(), "function call");
|
||||
|
||||
for (i, (arg, carg)) in args.iter().zip(cargs).enumerate() {
|
||||
let ty = self.tys.args[sig_args.next().unwrap()];
|
||||
let sym = parser::find_symbol(&ast.symbols, carg.id);
|
||||
if sym.flags & idfl::COMPTIME != 0 {
|
||||
|
@ -1891,6 +1896,7 @@ impl Codegen {
|
|||
|
||||
// TODO: pass the arg as dest
|
||||
let varg = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
||||
_ = self.assert_ty(arg.pos(), varg.ty, ty, format_args!("argument({i})"));
|
||||
self.pass_arg(&varg, &mut parama);
|
||||
values.push(varg.loc);
|
||||
should_momize = false;
|
||||
|
@ -1966,7 +1972,7 @@ impl Codegen {
|
|||
|
||||
match self.ci.ret {
|
||||
None => self.ci.ret = Some(ty),
|
||||
Some(ret) => _ = self.assert_ty(pos, ty, ret),
|
||||
Some(ret) => _ = self.assert_ty(pos, ty, ret, "return type"),
|
||||
}
|
||||
|
||||
self.ci.ret_relocs.push(Reloc::new(self.local_offset(), 1, 4));
|
||||
|
@ -1979,8 +1985,21 @@ impl Codegen {
|
|||
}
|
||||
Some(Value::void())
|
||||
}
|
||||
E::Number { value, .. } => Some(Value {
|
||||
ty: ctx.ty.map(ty::Id::strip_pointer).unwrap_or(ty::INT.into()),
|
||||
E::Number { value, pos, .. } => Some(Value {
|
||||
ty: {
|
||||
let ty = ctx.ty.map(ty::Id::strip_pointer).unwrap_or(ty::INT.into());
|
||||
if !ty.is_integer() && !ty.is_pointer() {
|
||||
self.report(
|
||||
pos,
|
||||
format_args!(
|
||||
"this integer was inferred to be '{}' \
|
||||
which does not make sense",
|
||||
self.ty_display(ty)
|
||||
),
|
||||
);
|
||||
}
|
||||
ty
|
||||
},
|
||||
loc: Loc::ct(value as u64),
|
||||
}),
|
||||
E::If { cond, then, else_, .. } => {
|
||||
|
@ -2090,7 +2109,7 @@ impl Codegen {
|
|||
|
||||
if let ty::Kind::Struct(_) = left.ty.expand() {
|
||||
let right = self.expr_ctx(right, Ctx::default().with_ty(left.ty))?;
|
||||
_ = self.assert_ty(expr.pos(), left.ty, right.ty);
|
||||
_ = self.assert_ty(expr.pos(), right.ty, left.ty, "right struct operand");
|
||||
return self.struct_op(op, left.ty, ctx, left.loc, right.loc);
|
||||
}
|
||||
|
||||
|
@ -2100,7 +2119,7 @@ impl Codegen {
|
|||
let right = self.expr_ctx(right, Ctx::default().with_ty(left.ty))?;
|
||||
let rsize = self.tys.size_of(right.ty);
|
||||
|
||||
let ty = self.assert_ty(expr.pos(), left.ty, right.ty);
|
||||
let ty = self.assert_ty(expr.pos(), right.ty, left.ty, "right sclalar operand");
|
||||
let size = self.tys.size_of(ty);
|
||||
let signed = ty.is_signed();
|
||||
|
||||
|
@ -2181,7 +2200,7 @@ impl Codegen {
|
|||
}?;
|
||||
|
||||
if let Some(ty) = ctx.ty {
|
||||
_ = self.assert_ty(expr.pos(), value.ty, ty);
|
||||
_ = self.assert_ty(expr.pos(), value.ty, ty, "a thing");
|
||||
}
|
||||
|
||||
Some(match ctx.loc {
|
||||
|
@ -3300,13 +3319,20 @@ impl Codegen {
|
|||
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
fn assert_ty(&self, pos: Pos, ty: ty::Id, expected: ty::Id) -> ty::Id {
|
||||
fn assert_ty(&self, pos: Pos, ty: ty::Id, expected: ty::Id, hint: impl Display) -> ty::Id {
|
||||
if let Some(res) = ty.try_upcast(expected) {
|
||||
res
|
||||
} else {
|
||||
let ty = self.ty_display(ty);
|
||||
let expected = self.ty_display(expected);
|
||||
self.report(pos, format_args!("expected {expected}, got {ty}"));
|
||||
self.report(pos, format_args!("expected {hint} of type {expected}, got {ty}"));
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_arg_count(&self, pos: Pos, got: usize, expected: usize, hint: impl Display) {
|
||||
if got != expected {
|
||||
let s = if expected != 1 { "s" } else { "" };
|
||||
self.report(pos, format_args!("{hint} expected {expected} argument{s}, got {got}"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3523,5 +3549,6 @@ mod tests {
|
|||
comptime_function_from_another_file => README;
|
||||
inline => README;
|
||||
inline_test => README;
|
||||
some_generic_code => README;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ use {
|
|||
parser::Ast,
|
||||
std::{
|
||||
collections::{hash_map, VecDeque},
|
||||
default,
|
||||
io::{self, Read},
|
||||
path::{Path, PathBuf},
|
||||
sync::Mutex,
|
||||
|
@ -131,6 +130,11 @@ unsafe fn encode<T>(instr: T) -> (usize, [u8; instrs::MAX_SIZE]) {
|
|||
(std::mem::size_of::<T>(), buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode<T>(binary: &mut &[u8]) -> Option<T> {
|
||||
unsafe { Some(std::ptr::read(binary.take(..std::mem::size_of::<T>())?.as_ptr() as *const T)) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[derive(Clone, Copy)]
|
||||
enum DisasmItem {
|
||||
|
|
|
@ -1220,6 +1220,16 @@ impl ExprRef {
|
|||
// allocations
|
||||
Some(unsafe { { self.0 }.as_ref() })
|
||||
}
|
||||
|
||||
pub fn dangling() -> Self {
|
||||
Self(NonNull::dangling())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ExprRef {
|
||||
fn default() -> Self {
|
||||
Self::dangling()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Ast {}
|
||||
|
|
1066
hblang/src/son.rs
1066
hblang/src/son.rs
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,5 @@
|
|||
0: Start
|
||||
2: Tuple { index: 0 }
|
||||
7: return [2] 0
|
||||
1: End
|
||||
Start.1
|
Loading…
Reference in a new issue