forked from koniifer/ableos
adding more type checking
This commit is contained in:
parent
1c29fdf8f0
commit
0bf647174c
|
@ -695,7 +695,7 @@ example := fn(): void {
|
||||||
loop {
|
loop {
|
||||||
random_x := @inline(random.integer, 0, 1024)
|
random_x := @inline(random.integer, 0, 1024)
|
||||||
random_y := random.integer(0, 768)
|
random_y := random.integer(0, 768)
|
||||||
a := @inline(screenidx, random_x, random_y)
|
a := @inline(screenidx, random_x)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -725,3 +725,15 @@ integer := fn(min: int, max: int): int {
|
||||||
return rng
|
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();
|
generated.pop();
|
||||||
writeln!(generated, " => {{")?;
|
writeln!(generated, " => {{")?;
|
||||||
if iter_args(ty).count() != 0 {
|
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!(
|
writeln!(
|
||||||
generated,
|
generated,
|
||||||
" buf.extend([{}]);",
|
" buf.extend([{}]);",
|
||||||
|
@ -119,7 +119,7 @@ fn gen_instrs() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
)
|
)
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(generated, " bytes.take(..std::mem::size_of::<{ty}>())?;")?;
|
writeln!(generated, " crate::decode::<{ty}>(bytes)?;")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(generated, " }}")?;
|
writeln!(generated, " }}")?;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use {
|
||||||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||||
HashMap,
|
HashMap,
|
||||||
},
|
},
|
||||||
std::{ops::Range, rc::Rc, u32},
|
std::{fmt::Display, ops::Range, rc::Rc},
|
||||||
};
|
};
|
||||||
|
|
||||||
type Offset = u32;
|
type Offset = u32;
|
||||||
|
@ -1438,7 +1438,7 @@ impl Codegen {
|
||||||
let mut base_val = self.expr(base)?;
|
let mut base_val = self.expr(base)?;
|
||||||
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
base_val.loc = self.make_loc_owned(base_val.loc, base_val.ty);
|
||||||
let index_val = self.expr(index)?;
|
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() {
|
if let ty::Kind::Ptr(ty) = base_val.ty.expand() {
|
||||||
base_val.ty = self.tys.ptrs[ty as usize].base;
|
base_val.ty = self.tys.ptrs[ty as usize].base;
|
||||||
|
@ -1501,6 +1501,8 @@ impl Codegen {
|
||||||
let scope = self.ci.vars.len();
|
let scope = self.ci.vars.len();
|
||||||
let sig = self.compute_signature(&mut func, func_ast.pos(), args)?;
|
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() {
|
if scope == self.ci.vars.len() {
|
||||||
for ((arg, ty), carg) in
|
for ((arg, ty), carg) in
|
||||||
args.iter().zip(sig.args.view(&self.tys.args).to_owned()).zip(cargs)
|
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 values = Vec::with_capacity(args.len());
|
||||||
let mut sig_args = sig.args.range();
|
let mut sig_args = sig.args.range();
|
||||||
let mut should_momize = !args.is_empty() && sig.ret == ty::Id::from(ty::TYPE);
|
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 ty = self.tys.args[sig_args.next().unwrap()];
|
||||||
let sym = parser::find_symbol(&ast.symbols, carg.id);
|
let sym = parser::find_symbol(&ast.symbols, carg.id);
|
||||||
if sym.flags & idfl::COMPTIME != 0 {
|
if sym.flags & idfl::COMPTIME != 0 {
|
||||||
|
@ -1891,6 +1896,7 @@ impl Codegen {
|
||||||
|
|
||||||
// TODO: pass the arg as dest
|
// TODO: pass the arg as dest
|
||||||
let varg = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
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);
|
self.pass_arg(&varg, &mut parama);
|
||||||
values.push(varg.loc);
|
values.push(varg.loc);
|
||||||
should_momize = false;
|
should_momize = false;
|
||||||
|
@ -1966,7 +1972,7 @@ impl Codegen {
|
||||||
|
|
||||||
match self.ci.ret {
|
match self.ci.ret {
|
||||||
None => self.ci.ret = Some(ty),
|
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));
|
self.ci.ret_relocs.push(Reloc::new(self.local_offset(), 1, 4));
|
||||||
|
@ -1979,8 +1985,21 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
Some(Value::void())
|
Some(Value::void())
|
||||||
}
|
}
|
||||||
E::Number { value, .. } => Some(Value {
|
E::Number { value, pos, .. } => Some(Value {
|
||||||
ty: ctx.ty.map(ty::Id::strip_pointer).unwrap_or(ty::INT.into()),
|
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),
|
loc: Loc::ct(value as u64),
|
||||||
}),
|
}),
|
||||||
E::If { cond, then, else_, .. } => {
|
E::If { cond, then, else_, .. } => {
|
||||||
|
@ -2090,7 +2109,7 @@ impl Codegen {
|
||||||
|
|
||||||
if let ty::Kind::Struct(_) = left.ty.expand() {
|
if let ty::Kind::Struct(_) = left.ty.expand() {
|
||||||
let right = self.expr_ctx(right, Ctx::default().with_ty(left.ty))?;
|
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);
|
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 right = self.expr_ctx(right, Ctx::default().with_ty(left.ty))?;
|
||||||
let rsize = self.tys.size_of(right.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 size = self.tys.size_of(ty);
|
||||||
let signed = ty.is_signed();
|
let signed = ty.is_signed();
|
||||||
|
|
||||||
|
@ -2181,7 +2200,7 @@ impl Codegen {
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if let Some(ty) = ctx.ty {
|
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 {
|
Some(match ctx.loc {
|
||||||
|
@ -3300,13 +3319,20 @@ impl Codegen {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[track_caller]
|
#[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) {
|
if let Some(res) = ty.try_upcast(expected) {
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
let ty = self.ty_display(ty);
|
let ty = self.ty_display(ty);
|
||||||
let expected = self.ty_display(expected);
|
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;
|
comptime_function_from_another_file => README;
|
||||||
inline => README;
|
inline => README;
|
||||||
inline_test => README;
|
inline_test => README;
|
||||||
|
some_generic_code => README;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ use {
|
||||||
parser::Ast,
|
parser::Ast,
|
||||||
std::{
|
std::{
|
||||||
collections::{hash_map, VecDeque},
|
collections::{hash_map, VecDeque},
|
||||||
default,
|
|
||||||
io::{self, Read},
|
io::{self, Read},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
|
@ -131,6 +130,11 @@ unsafe fn encode<T>(instr: T) -> (usize, [u8; instrs::MAX_SIZE]) {
|
||||||
(std::mem::size_of::<T>(), buf)
|
(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)]
|
#[cfg(test)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum DisasmItem {
|
enum DisasmItem {
|
||||||
|
|
|
@ -1220,6 +1220,16 @@ impl ExprRef {
|
||||||
// allocations
|
// allocations
|
||||||
Some(unsafe { { self.0 }.as_ref() })
|
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 {}
|
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