2025-06-17 11:23:59 +10:00

373 lines
11 KiB
Rust

use luaify::luaify;
#[test]
fn raw_ident() {
assert_eq!(luaify!(r#ref), r#"ref"#);
assert_eq!(luaify!(x.r#ref), r#"x.ref"#);
assert_eq!(luaify!(r#mut::r#ref), r#"mut.ref"#);
assert_eq!(luaify!(x.r#ref()), r#"x:ref()"#);
assert_eq!(luaify!(r#mut.r#ref()), r#"mut:ref()"#);
assert_eq!(luaify!(r#mut::r#ref()), r#"mut.ref()"#);
}
#[test]
fn indexing() {
assert_eq!(luaify!(table.0), r#"table[0]"#);
assert_eq!(luaify!(table[0]), r#"table[0]"#);
assert_eq!(luaify!(table["0"]), r#"table["0"]"#);
assert_eq!(luaify!(table.field), r#"table.field"#);
assert_eq!(luaify!(table.field.nested), r#"table.field.nested"#);
assert_eq!(luaify!(table::field.nested), r#"table.field.nested"#);
assert_eq!(luaify!(table::field::nested), r#"table.field.nested"#);
assert_eq!(luaify!(table::field["nested"]), r#"table.field["nested"]"#);
assert_eq!(luaify!(table.0.nested), r#"table[0].nested"#);
assert_eq!(luaify!(table.0["nested"]), r#"table[0]["nested"]"#);
assert_eq!(luaify!(table[0].nested), r#"table[0].nested"#);
assert_eq!(luaify!(table[0]["nested"]), r#"table[0]["nested"]"#);
assert_eq!(luaify!(table["field"].nested), r#"table["field"].nested"#);
assert_eq!(luaify!(table[field]), r#"table[field]"#);
assert_eq!(luaify!(table[x.y]), r#"table[x.y]"#);
assert_eq!(luaify!(table[x.1.y.2]), r#"table[x[1].y[2]]"#);
assert_eq!(luaify!(table[x.1.y[2]]), r#"table[x[1].y[2]]"#);
assert_eq!(luaify!(table[x[1].y.2]), r#"table[x[1].y[2]]"#);
assert_eq!(luaify!(table[x[1].y[2]]), r#"table[x[1].y[2]]"#);
assert_eq!(luaify!((x.y)[z.w]), r#"(x.y)[z.w]"#);
assert_eq!(luaify!((x[y])[z.w]), r#"(x[y])[z.w]"#);
assert_eq!(luaify!((x["y"])[z.w]), r#"(x["y"])[z.w]"#);
}
#[test]
fn locals() {
assert_eq!(
luaify!(|| {
let x = 30;
}),
r#"function()local x=30;end"#
);
assert_eq!(
luaify!(|| {
let (x, y, z) = (1, 2, 3);
}),
r#"function()local x,y,z=1,2,3;end"#
);
assert_eq!(
luaify!(|| {
let (a, b, c) = (1, call(), call2(), 4);
return (a, b, c);
}),
r#"function()local a,b,c=1,call(),call2(),4;return a,b,c;end"#
);
}
#[test]
fn local_fn() {
assert_eq!(
luaify!(|a, b| {
fn inner(c: _, d: _) {}
inner
}),
r#"function(a,b)local function inner(c,d)end;return inner;end"#
);
assert_eq!(
luaify!(|| {
fn check(self: string, arg: number) {}
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"#
);
}
#[test]
fn call() {
assert_eq!(luaify!(table.field()), r#"table:field()"#);
assert_eq!(luaify!(table::field()), r#"table.field()"#);
assert_eq!(luaify!(table[field]()), r#"table[field]()"#);
assert_eq!(luaify!(a::b.c.field()), r#"a.b.c:field()"#);
assert_eq!(luaify!(a::b::c.field()), r#"a.b.c:field()"#);
assert_eq!(luaify!(a::b::c::field()), r#"a.b.c.field()"#);
assert_eq!(
luaify!(coroutine::r#yield("string")),
r#"coroutine.yield("string")"#
);
assert_eq!(luaify!(call(a(), (b)(), c.d())), r#"call(a(),(b)(),c:d())"#);
}
#[test]
fn closure() {
assert_eq!(luaify!(|| hello), r#"function()return hello;end"#);
assert_eq!(luaify!(|| { hello }), r#"function()return hello;end"#);
assert_eq!(
luaify!(|| {
return hello;
}),
r#"function()return hello;end"#
);
assert_eq!(
luaify!(|| { { hello } }),
r#"function()do return hello;end;end"#
);
assert_eq!(
luaify!(|a, b| |c, d| hello),
r#"function(a,b)return function(c,d)return hello;end;end"#
);
}
#[test]
fn labels() {
assert_eq!(
luaify!(|| {
'label: {
break 'label;
a();
b()
}
}),
r#"function()do goto label_brk;a();return b();::label_cnt::end::label_brk::;end"#
);
assert_eq!(
luaify!(|| {
'label: {
continue 'label;
a();
b()
}
}),
r#"function()do goto label_cnt;a();return b();::label_cnt::end::label_brk::;end"#
);
}
#[test]
fn loops() {
assert_eq!(
luaify!(|| {
loop {
break;
}
}),
r#"function()while true do break;end;end"#
);
assert_eq!(
luaify!(|| {
'label: loop {
break;
break 'label;
continue 'label;
a();
b()
}
}),
r#"function()while true do break;goto label_brk;goto label_cnt;a();b();::label_cnt::end::label_brk::;end"#
);
assert_eq!(
luaify!(|| { while cond {} }),
r#"function()while cond do end;end"#
);
assert_eq!(
luaify!(|| {
'label: while cond {
continue 'label;
break 'label;
a();
b()
}
}),
r#"function()while cond do goto label_cnt;goto label_brk;a();b();::label_cnt::end::label_brk::;end"#
);
assert_eq!(
luaify!(|| {
for (k, v) in pairs(table) {
print(k, v);
a();
b()
}
}),
r#"function()for k,v in pairs(table)do print(k,v);a();b();end;end"#
);
assert_eq!(
luaify!(|| {
for i in 0..=5 {
print(i)
}
for i in ..10 {
print(i)
}
}),
r#"function()for i=0,5 do print(i);end;for i=0,10-1 do print(i);end;end"#
);
}
#[test]
fn type_checks() {
assert_eq!(luaify!(|s| {}), r#"function(s)end"#);
assert_eq!(
luaify!(|s: table| {}),
r#"function(s)do if type(s)~="table"then return error("table expected in \'s\', got "..type(s));end;end;end"#
);
assert_eq!(
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"#
);
assert_eq!(
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"#
);
assert_eq!(
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"#
);
assert_eq!(luaify!(|s| { s as any }), r#"function(s)do end;end"#);
assert_eq!(
luaify!(|s| {
let (ok, res) = coroutine::r#yield(thread);
ok as boolean;
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"#
);
}
#[test]
fn concat() {
assert_eq!(luaify!(concat!(a)), r#"a"#);
assert_eq!(luaify!(concat!(a, b)), r#"a..b"#);
assert_eq!(luaify!(concat!(a, b, c)), r#"a..b..c"#);
assert_eq!(
luaify!(|a, b, c| concat!(a, b, c)),
r#"function(a,b,c)return a..b..c;end"#
);
}
#[test]
fn blocks() {
assert_eq!(
luaify!(|| { { "result" } }),
r#"function()do return"result";end;end"#
);
assert_eq!(
luaify!(|| {
{}
{ "result" }
}),
r#"function()do end;do return"result";end;end"#
);
assert_eq!(
luaify!(|| { { { { "result" } } } }),
r#"function()do do do return"result";end;end;end;end"#
);
}
#[test]
fn ops() {
assert_eq!(luaify!(|| a = b), r#"function()a=b;end"#);
assert_eq!(luaify!(|| a + b), r#"function()return a+b;end"#);
assert_eq!(luaify!(|| a += b), r#"function()a=a+b;end"#);
assert_eq!(luaify!(|| a - b), r#"function()return a-b;end"#);
assert_eq!(luaify!(|| a -= b), r#"function()a=a-b;end"#);
assert_eq!(luaify!(|| a * b), r#"function()return a*b;end"#);
assert_eq!(luaify!(|| a *= b), r#"function()a=a*b;end"#);
assert_eq!(luaify!(|| a / b), r#"function()return a/b;end"#);
assert_eq!(luaify!(|| a /= b), r#"function()a=a/b;end"#);
assert_eq!(luaify!(|| a = b % c), r#"function()a=math.fmod(b,c);end"#);
assert_eq!(luaify!(|| a = b << c), r#"function()a=bit.lshift(b,c);end"#);
assert_eq!(
luaify!(|| a <<= b << c),
r#"function()a=bit.lshift(a,bit.lshift(b,c));end"#
);
assert_eq!(
luaify!(|| a = b >> c),
r#"function()a=bit.arshift(b,c);end"#
);
assert_eq!(
luaify!(|| a >>= b >> c),
r#"function()a=bit.arshift(a,bit.arshift(b,c));end"#
);
assert_eq!(luaify!(|| a && b), r#"function()return a and b;end"#);
assert_eq!(luaify!(|| a || b), r#"function()return a or b;end"#);
assert_eq!(
luaify!(|| (a && b) || c),
r#"function()return(a and b)or c;end"#
);
assert_eq!(
luaify!(|| (a || b) && c),
r#"function()return(a or b)and c;end"#
);
assert_eq!(
luaify!(|| a && (b || c)),
r#"function()return a and(b or c);end"#
);
assert_eq!(
luaify!(|| a || (b && c)),
r#"function()return a or(b and c);end"#
);
assert_eq!(
luaify!(|| -a || !--b && c >> d),
r#"function()return-a or not-(-b)and bit.arshift(c,d);end"#
);
assert_eq!(
luaify!(|| -a || !(--b && c) >> d),
r#"function()return-a or bit.arshift(not(-(-b)and c),d);end"#
);
assert_eq!(
luaify!(|| a >> b << c >> d),
r#"function()return bit.arshift(bit.lshift(bit.arshift(a,b),c),d);end"#
);
}
#[test]
fn ifs() {
assert_eq!(
luaify!(|| {
if a == b {
c
}
}),
r#"function()if a==b then return c;end;end"#
);
assert_eq!(
luaify!(|| { if a == b { c } else { d } }),
r#"function()if a==b then return c;else return d;end;end"#
);
assert_eq!(
luaify!(|| {
if a == b {
c()
} else if b == c {
a()
} else {
d()
};
}),
r#"function()if a==b then c();elseif b==c then a();else d();end;end"#
);
assert_eq!(
luaify!(|| {
if a == b {
c()
} else if b == c {
a()
} else {
d()
}
}),
r#"function()if a==b then return c();elseif b==c then return a();else return d();end;end"#
);
assert_eq!(
luaify!(|| {
if a == b {
c();
} else if b == c {
a()
} else {
d();
}
}),
r#"function()if a==b then c();elseif b==c then return a();else d();end;end"#
);
}