Use assert for type checking

This commit is contained in:
lumi 2025-06-19 21:38:34 +10:00
parent 1c821d8804
commit 1ebeaa9e95
Signed by: luaneko
GPG Key ID: 406809B8763FF07A
4 changed files with 23 additions and 31 deletions

View File

@ -434,7 +434,7 @@ impl<'r, 'm> MetatypeMethodBuilder<'r, 'm> {
write!(self.prelude, "local __{name}_len = 0; ").unwrap(); write!(self.prelude, "local __{name}_len = 0; ").unwrap();
write!( write!(
self.prelude, self.prelude,
r#"if {name} ~= nil then assert(type({name}) == "string", "expected string in argument '{name}', got " .. type({name})); __{name}_len = #{name}; end; "# r#"if {name} ~= nil then assert(type({name}) == "string", "string expected in argument '{name}', got " .. type({name})); __{name}_len = #{name}; end; "#
) )
.unwrap(); .unwrap();
self self
@ -520,7 +520,7 @@ macro_rules! impl_copy_primitive {
type FromValue = $rtype; type FromValue = $rtype;
fn prelude(arg: &str) -> impl Display { fn prelude(arg: &str) -> impl Display {
display!(r#"assert(type({arg}) == "{0}", "expected {0} in argument '{arg}', got " .. type({arg})); "#, $ltype) display!(r#"assert(type({arg}) == "{0}", "{0} expected in argument '{arg}', got " .. type({arg})); "#, $ltype)
} }
fn convert(from: Self::From) -> Self { fn convert(from: Self::From) -> Self {

View File

@ -24,7 +24,7 @@ unsafe impl FromFfi for *const [u8] {
let ct = lua_buf::name(); let ct = lua_buf::name();
write!( write!(
f, f,
r#"if {arg} ~= nil then assert(type({arg}) == "string", "expected string in argument '{arg}', got " .. type({arg})); "# r#"if {arg} ~= nil then assert(type({arg}) == "string", "string expected in argument '{arg}', got " .. type({arg})); "#
)?; )?;
write!(f, "{arg} = {ct}({arg}, #{arg}); end; ") write!(f, "{arg} = {ct}({arg}, #{arg}); end; ")
}) })
@ -55,7 +55,7 @@ unsafe impl FromFfi for &str {
let ct = lua_buf::name(); let ct = lua_buf::name();
write!( write!(
f, f,
r#"assert(type({arg}) == "string", "expected string in argument '{arg}', got " .. type({arg})); "# r#"assert(type({arg}) == "string", "string expected in argument '{arg}', got " .. type({arg})); "#
)?; )?;
write!( write!(
f, f,

View File

@ -146,14 +146,14 @@ impl Visitor {
// //
if let Expr::Cast(cast) = expr { if let Expr::Cast(cast) = expr {
let arg = (*cast.expr).clone(); let arg = (*cast.expr).clone();
let mut init: Option<Stmt> = None; let mut prelude: Option<Stmt> = None;
let ty: LuaType = (&*cast.ty).try_into()?; let ty: LuaType = (&*cast.ty).try_into()?;
let ty_str = format!("{ty}"); let ty_str = format!("{ty}");
let (ident, msg) = match unwrap_expr_ident(&arg).ok() { let (ident, msg) = match unwrap_expr_ident(&arg).ok() {
Some(ident) => (ident.clone(), format!("{ty} expected in '{ident}', got ")), Some(ident) => (ident.clone(), format!("{ty} expected in '{ident}', got ")),
None => { None => {
let ident = Ident::new("_", arg.span()); let ident = Ident::new("_", arg.span());
init = Some(parse_quote! { let #ident = #arg; }); prelude = Some(parse_quote! { let #ident = #arg; });
(ident, format!("{ty} expected, got ")) (ident, format!("{ty} expected, got "))
} }
}; };
@ -163,40 +163,32 @@ impl Visitor {
*expr = match ty { *expr = match ty {
LuaType::Any => parse_quote_spanned!(span => {}), LuaType::Any => parse_quote_spanned!(span => {}),
LuaType::Nil => parse_quote_spanned!(span => { LuaType::Nil => parse_quote_spanned!(span => {
#init #prelude
if #ident != () { assert(#ident == (), concat!(#msg, r#type(#ident)));
return error(concat!(#msg, r#type(#ident)));
}
}), }),
LuaType::Number => parse_quote_spanned!(span => { LuaType::Number => parse_quote_spanned!(span => {
#init #prelude
let #tmp = #ident; let #tmp = #ident;
#ident = tonumber(#ident); #ident = tonumber(#ident);
if #ident == () { assert(#ident != (), concat!(#msg, r#type(#tmp)));
return error(concat!(#msg, r#type(#tmp)));
}
}), }),
LuaType::Integer => parse_quote_spanned!(span => { LuaType::Integer => parse_quote_spanned!(span => {
#init #prelude
let #tmp = #ident; let #tmp = #ident;
#ident = tonumber(#ident); #ident = tonumber(#ident);
if #ident == () || math::floor(#ident) != #ident { assert(#ident != () && math::floor(#ident) == #ident, concat!(#msg, r#type(#tmp)));
return error(concat!(#msg, r#type(#tmp)));
}
}), }),
LuaType::String => parse_quote_spanned!(span => { LuaType::String => parse_quote_spanned!(span => {
#init #prelude
if r#type(#ident) == "number" { if r#type(#ident) == "number" {
#ident = tostring(#ident); #ident = tostring(#ident);
} else if r#type(#ident) != "string" { } else {
return error(concat!(#msg, r#type(#ident))); assert(r#type(#ident) == "string", concat!(#msg, r#type(#ident)));
} }
}), }),
_ => parse_quote_spanned!(span => { _ => parse_quote_spanned!(span => {
#init #prelude
if r#type(#ident) != #ty_str { assert(r#type(#ident) == #ty_str, concat!(#msg, r#type(#ident)));
return error(concat!(#msg, r#type(#ident)));
}
}), }),
} }
} }

View File

@ -81,7 +81,7 @@ fn local_fn() {
fn check(self: string, arg: number) {} fn check(self: string, arg: number) {}
inner inner
}), }),
r#"function()local function check(self,arg)do if type(self)=="number"then self=tostring(self);elseif type(self)~="string"then return error("string expected in \'self\', got "..type(self));end;end;do local _arg=arg;arg=tonumber(arg);if arg==nil then return error("number expected in \'arg\', got "..type(_arg));end;end;end;return inner;end"# r#"function()local function check(self,arg)do if type(self)=="number"then self=tostring(self);else assert(type(self)=="string","string expected in \'self\', got "..type(self));end;end;do local _arg=arg;arg=tonumber(arg);assert(arg~=nil,"number expected in \'arg\', got "..type(_arg));end;end;return inner;end"#
); );
} }
@ -212,19 +212,19 @@ fn type_checks() {
assert_eq!(luaify!(|s| {}), r#"function(s)end"#); assert_eq!(luaify!(|s| {}), r#"function(s)end"#);
assert_eq!( assert_eq!(
luaify!(|s: table| {}), luaify!(|s: table| {}),
r#"function(s)do if type(s)~="table"then return error("table expected in \'s\', got "..type(s));end;end;end"# r#"function(s)do assert(type(s)=="table","table expected in \'s\', got "..type(s));end;end"#
); );
assert_eq!( assert_eq!(
luaify!(|s| { s as string }), luaify!(|s| { s as string }),
r#"function(s)do if type(s)=="number"then s=tostring(s);elseif type(s)~="string"then return error("string expected in \'s\', got "..type(s));end;end;end"# r#"function(s)do if type(s)=="number"then s=tostring(s);else assert(type(s)=="string","string expected in \'s\', got "..type(s));end;end;end"#
); );
assert_eq!( assert_eq!(
luaify!(|s| { s as number }), luaify!(|s| { s as number }),
r#"function(s)do local _s=s;s=tonumber(s);if s==nil then return error("number expected in \'s\', got "..type(_s));end;end;end"# r#"function(s)do local _s=s;s=tonumber(s);assert(s~=nil,"number expected in \'s\', got "..type(_s));end;end"#
); );
assert_eq!( assert_eq!(
luaify!(|s| { s as nil }), luaify!(|s| { s as nil }),
r#"function(s)do if s~=nil then return error("nil expected in \'s\', got "..type(s));end;end;end"# r#"function(s)do assert(s==nil,"nil expected in \'s\', got "..type(s));end;end"#
); );
assert_eq!(luaify!(|s| { s as any }), r#"function(s)do end;end"#); assert_eq!(luaify!(|s| { s as any }), r#"function(s)do end;end"#);
@ -234,7 +234,7 @@ fn type_checks() {
ok as boolean; ok as boolean;
res as nil; res as nil;
}), }),
r#"function(s)local ok,res=coroutine.yield(thread);do if type(ok)~="boolean"then return error("boolean expected in \'ok\', got "..type(ok));end;end;do if res~=nil then return error("nil expected in \'res\', got "..type(res));end;end;end"# r#"function(s)local ok,res=coroutine.yield(thread);do assert(type(ok)=="boolean","boolean expected in \'ok\', got "..type(ok));end;do assert(res==nil,"nil expected in \'res\', got "..type(res));end;end"#
); );
} }