Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 31 additions & 22 deletions crates/moonbit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1183,15 +1183,15 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
deriviation.push("Eq")
}
let declaration = if self.gen.opts.derive_error && name.contains("Error") {
"type!"
"suberror"
} else {
"type"
"struct"
};

uwrite!(
self.src,
r#"
pub(all) {declaration} {name} Int derive({})
pub(all) {declaration} {name}(Int) derive({})
"#,
deriviation.join(", "),
);
Expand Down Expand Up @@ -1227,14 +1227,14 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
fn wasmExportResourceNew{name}(rep : Int) -> Int = "[export]{module}" "[resource-new]{type_name}"

/// Drops a resource handle.
pub fn {name}::drop(self : {name}) -> Unit {{
pub fn {name}::drop(self : Self) -> Unit {{
let {name}(resource) = self
wasmExportResourceDrop{name}(resource)
}}
fn wasmExportResourceDrop{name}(resource : Int) = "[export]{module}" "[resource-drop]{type_name}"

/// Gets the `Int` representation of the resource pointed to the given handle.
pub fn {name}::rep(self : {name}) -> Int {{
pub fn {name}::rep(self : Self) -> Int {{
let {name}(resource) = self
wasmExportResourceRep{name}(resource)
}}
Expand Down Expand Up @@ -1324,15 +1324,15 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
deriviation.push("Eq")
}
let declaration = if self.gen.opts.derive_error && name.contains("Error") {
"type!"
"suberror"
} else {
"type"
"struct"
};

uwrite!(
self.src,
"
pub(all) {declaration} {name} {ty} derive({})
pub(all) {declaration} {name}({ty}) derive({})
pub fn {name}::default() -> {name} {{
{}
}}
Expand All @@ -1344,15 +1344,15 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
{map_to_int}
}}
}}
pub fn {name}::set(self : {name}, other: {name}Flag) -> {name} {{
pub fn {name}::set(self : Self, other: {name}Flag) -> {name} {{
let {name}(flag) = self
flag.lor(other.value())
}}
pub fn {name}::unset(self : {name}, other: {name}Flag) -> {name} {{
pub fn {name}::unset(self : Self, other: {name}Flag) -> {name} {{
let {name}(flag) = self
flag.land(other.value().lnot())
}}
pub fn {name}::is_set(self : {name}, other: {name}Flag) -> Bool {{
pub fn {name}::is_set(self : Self, other: {name}Flag) -> Bool {{
let {name}(flag) = self
(flag.land(other.value()) == other.value())
}}
Expand Down Expand Up @@ -1399,7 +1399,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
deriviation.push("Eq")
}
let declaration = if self.gen.opts.derive_error && name.contains("Error") {
"type!"
"suberror"
} else {
"enum"
};
Expand Down Expand Up @@ -1444,7 +1444,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
deriviation.push("Eq")
}
let declaration = if self.gen.opts.derive_error && name.contains("Error") {
"type!"
"suberror"
} else {
"enum"
};
Expand Down Expand Up @@ -1785,7 +1785,9 @@ impl Bindgen for FunctionBindgen<'_, '_> {
Instruction::F32FromCoreF32 => results.push(operands[0].clone()),
Instruction::CoreF32FromF32 => results.push(operands[0].clone()),

Instruction::CharFromI32 => results.push(format!("Char::from_int({})", operands[0])),
Instruction::CharFromI32 => {
results.push(format!("Int::unsafe_to_char({})", operands[0]))
}
Instruction::I32FromChar => results.push(format!("({}).to_int()", operands[0])),

Instruction::I32FromU8 => results.push(format!("({}).to_int()", operands[0])),
Expand Down Expand Up @@ -2874,14 +2876,21 @@ impl ToMoonBitIdent for str {
fn to_moonbit_ident(&self) -> String {
// Escape MoonBit keywords and reserved keywords
match self {
"module" | "move" | "ref" | "static" | "super" | "unsafe" | "use" | "where"
| "await" | "dyn" | "abstract" | "do" | "final" | "macro" | "override" | "typeof"
| "virtual" | "yield" | "local" | "method" | "alias" | "assert" | "as" | "else"
| "extern" | "fn" | "if" | "let" | "const" | "match" | "mut" | "type" | "typealias"
| "struct" | "enum" | "trait" | "traitalias" | "derive" | "while" | "break"
| "continue" | "import" | "return" | "throw" | "raise" | "try" | "catch" | "pub"
| "priv" | "readonly" | "true" | "false" | "_" | "test" | "loop" | "for" | "in"
| "impl" | "with" | "guard" | "async" | "is" | "init" | "main" => {
// Keywords
"as" | "else" | "extern" | "fn" | "fnalias" | "if" | "let" | "const" | "match" | "using"
| "mut" | "type" | "typealias" | "struct" | "enum" | "trait" | "traitalias" | "derive"
| "while" | "break" | "continue" | "import" | "return" | "throw" | "raise" | "try" | "catch"
| "pub" | "priv" | "readonly" | "true" | "false" | "_" | "test" | "loop" | "for" | "in" | "impl"
| "with" | "guard" | "async" | "is" | "suberror" | "and" | "letrec" | "enumview" | "noraise"
| "defer" | "init" | "main"
// Reserved keywords
| "module" | "move" | "ref" | "static" | "super" | "unsafe" | "use" | "where" | "await"
| "dyn" | "abstract" | "do" | "final" | "macro" | "override" | "typeof" | "virtual" | "yield"
| "local" | "method" | "alias" | "assert" | "package" | "recur" | "isnot" | "define" | "downcast"
| "inherit" | "member" | "namespace" | "upcast" | "void" | "lazy" | "include" | "mixin"
| "protected" | "sealed" | "constructor" | "atomic" | "volatile" | "anyframe" | "anytype"
| "asm" | "comptime" | "errdefer" | "export" | "opaque" | "orelse" | "resume" | "threadlocal"
| "unreachable" | "dynclass" | "dynobj" | "dynrec" | "var" | "finally" | "noasync" => {
format!("{self}_")
}
_ => self.to_snake_case(),
Expand Down
2 changes: 1 addition & 1 deletion crates/test/src/moonbit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl LanguageMethods for MoonBit {
.arg("embed")
.args(["--encoding", "utf16"])
.args(["-o", artifact.to_str().unwrap()])
.args(["-w", &compile.component.kind.to_string()])
.args(["-w", &compile.component.bindgen.world])
.arg(manifest_dir)
.arg(&artifact);
runner.run_command(&mut cmd)?;
Expand Down
142 changes: 142 additions & 0 deletions tests/runtime/flavorful/test.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//@ [lang]
//@ path = 'gen/interface/test_/flavorful/toTest/stub.mbt'

///|
pub fn f_list_in_record1(_a : ListInRecord1) -> Unit {
try {
assert_eq(_a.a, "list_in_record1")
} catch {
_ => panic()
}
}

///|
pub fn f_list_in_record2() -> ListInRecord2 {
{ a: "list_in_record2" }
}

///|
pub fn f_list_in_record3(_a : ListInRecord3) -> ListInRecord3 {
{ a: "list_in_record3 output" }
}

///|
pub fn f_list_in_record4(_a : ListInRecord4) -> ListInRecord4 {
{ a: "result4".to_string() }
}

///|
pub fn f_list_in_variant1(
_a : String?,
_b : Result[Unit, String],
) -> Unit {
try {
assert_eq(_a.unwrap(), "foo")
assert_eq(_b.unwrap_err(), "bar")
} catch {
_ => panic()
}
}

///|
pub fn f_list_in_variant2() -> String? {
Some("list_in_variant2".to_string())
}

///|
pub fn f_list_in_variant3(_a : String?) -> String? {
try {
assert_eq(_a.unwrap(), "input3")
} catch {
_ => panic()
}
Some("output3".to_string())
}

let first : Ref[Bool] = Ref::new(true);

///|
pub fn errno_result() -> Result[Unit, MyErrno] {
if first.val {
first.val = false;
Err(MyErrno::B)
} else {
Ok(())
}
}

pub fn write_utf8_char(buf : @buffer.T, value : Char) -> Unit {
let code = value.to_uint()
match code {
_..<0x80 => {
let b0 = ((code & 0x7F) | 0x00).to_byte()
buf.write_byte(b0)
}
_..<0x0800 => {
let b0 = (((code >> 6) & 0x1F) | 0xC0).to_byte()
let b1 = ((code & 0x3F) | 0x80).to_byte()
buf.write_byte(b0)
buf.write_byte(b1)
}
_..<0x010000 => {
let b0 = (((code >> 12) & 0x0F) | 0xE0).to_byte()
let b1 = (((code >> 6) & 0x3F) | 0x80).to_byte()
let b2 = ((code & 0x3F) | 0x80).to_byte()
buf.write_byte(b0)
buf.write_byte(b1)
buf.write_byte(b2)
}
_..<0x110000 => {
let b0 = (((code >> 18) & 0x07) | 0xF0).to_byte()
let b1 = (((code >> 12) & 0x3F) | 0x80).to_byte()
let b2 = (((code >> 6) & 0x3F) | 0x80).to_byte()
let b3 = ((code & 0x3F) | 0x80).to_byte()
buf.write_byte(b0)
buf.write_byte(b1)
buf.write_byte(b2)
buf.write_byte(b3)
}
_ => abort("Char out of range")
}
}

pub fn encode_to_utf8(
src : String,
) -> Bytes{
let buf = @buffer.new(size_hint=src.length() * 4)
for c in src {
write_utf8_char(buf, c);
}
buf.to_bytes()
}

///|
pub fn list_typedefs(
_a : String,
_c : Array[String],
) -> (FixedArray[Byte], Array[String]) {
try {
assert_eq(_a, "typedef1")
assert_eq(_c.length(), 1)
assert_eq(_c[0], "typedef2")
} catch {
_ => panic()
}
(encode_to_utf8("typedef3").to_fixedarray(), ["typedef4".to_string()])
}

///|
pub fn list_of_variants(
_a : Array[Bool],
_b : Array[Result[Unit, Unit]],
_c : Array[MyErrno],
) -> (Array[Bool], Array[Result[Unit, Unit]], Array[MyErrno]) {
try {
assert_eq(_a, [true, false])
assert_eq(_b, [Ok(()), Err(())])
assert_eq(_c, [MyErrno::SUCCESS, MyErrno::A])
} catch {
_ => panic()
}
([false, true], [Err(()), Ok(())], [MyErrno::A, MyErrno::B])
}
42 changes: 42 additions & 0 deletions tests/runtime/many-arguments/test.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//@ [lang]
//@ path = 'gen/interface/test_/many_arguments/toTest/stub.mbt'
///|
pub fn many_arguments(
_a1 : UInt64,
_a2 : UInt64,
_a3 : UInt64,
_a4 : UInt64,
_a5 : UInt64,
_a6 : UInt64,
_a7 : UInt64,
_a8 : UInt64,
_a9 : UInt64,
_a10 : UInt64,
_a11 : UInt64,
_a12 : UInt64,
_a13 : UInt64,
_a14 : UInt64,
_a15 : UInt64,
_a16 : UInt64,
) -> Unit {
try {
assert_eq(_a1, 1)
assert_eq(_a2, 2)
assert_eq(_a3, 3)
assert_eq(_a4, 4)
assert_eq(_a5, 5)
assert_eq(_a6, 6)
assert_eq(_a7, 7)
assert_eq(_a8, 8)
assert_eq(_a9, 9)
assert_eq(_a10, 10)
assert_eq(_a11, 11)
assert_eq(_a12, 12)
assert_eq(_a13, 13)
assert_eq(_a14, 14)
assert_eq(_a15, 15)
assert_eq(_a16, 16)
} catch {
_ => panic()
}
}
63 changes: 63 additions & 0 deletions tests/runtime/results/leaf.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//@ [lang]
//@ path = 'gen/interface/test_/results/test/stub.mbt'

///|
pub fn string_error(_a : Float) -> Result[Float, String] {
if _a == 0.0 {
return Err("zero")
}
Ok(_a)

}

///|
pub fn enum_error(_a : Float) -> Result[Float, E] {
if _a == 0.0 {
return Err(E::A)
}
Ok(_a)
}

///|
pub fn record_error(_a : Float) -> Result[Float, E2] {
if _a == 0.0 {
return Err({ line: 420, column: 0 })
} else if _a == 1.0 {
return Err({ line: 77, column: 2 })
}
Ok(_a)
}

///|
pub fn variant_error(_a : Float) -> Result[Float, E3] {
if _a == 0.0 {
return Err(E3::E2({ line: 420, column: 0 }))
} else if _a == 1.0 {
return Err(E3::E1(B))
} else if _a == 2.0 {
return Err(E3::E1(C))
}
Ok(_a)
}

///|
pub fn empty_error(_a : UInt) -> Result[UInt, Unit] {
if _a == 0 {
Err(())
} else if _a == 1 {
Ok(42)
} else {
Ok(_a)
}
}

///|
pub fn double_error(_a : UInt) -> Result[Result[Unit, String], String] {
if _a == 0 {
Ok(Ok(()))
} else if _a == 1 {
Ok(Err("one"))
} else {
Err("two")
}
}
Loading