Skip to content

Commit

Permalink
Use a generic Exception type to make handling easier (#1109)
Browse files Browse the repository at this point in the history
Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
  • Loading branch information
jsturtevant authored Dec 19, 2024
1 parent ad6dbc5 commit c2e7892
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 46 deletions.
24 changes: 20 additions & 4 deletions crates/csharp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,14 @@ impl WorldGenerator for CSharp {
NestingLevel = level;
}}
}}
{access} class WitException<T>: WitException {{
{access} T TypedValue {{ get {{ return (T)this.Value;}} }}
{access} WitException(T v, uint level) : base(v!, level)
{{
}}
}}
"#,
)
}
Expand Down Expand Up @@ -2889,6 +2897,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
if !self.results.is_empty() {
self.gen.gen.needs_wit_exception = true;
let cases = cases.join("\n");
// r#"}} catch (WitException<{err_ty}> e) {{
uwriteln!(
self.src,
r#"}} catch (WitException e) {{
Expand Down Expand Up @@ -2952,10 +2961,9 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1 => {
let mut payload_is_void = false;
let mut previous = operands[0].clone();
let mut vars = Vec::with_capacity(self.results.len());
let mut vars: Vec::<(String, Option<String>)> = Vec::with_capacity(self.results.len());
if let Direction::Import = self.gen.direction {
for ty in &self.results {
vars.push(previous.clone());
let tmp = self.locals.tmp("tmp");
uwrite!(
self.src,
Expand All @@ -2964,21 +2972,29 @@ impl Bindgen for FunctionBindgen<'_, '_> {
var {tmp} = {previous}.AsOk;
"
);
previous = tmp;
let TypeDefKind::Result(result) = &self.gen.resolve.types[*ty].kind else {
unreachable!();
};
let exception_name = result.err
.map(|ty| self.gen.type_name_with_qualifier(&ty, true));
vars.push((previous.clone(), exception_name));
payload_is_void = result.ok.is_none();
previous = tmp;
}
}
uwriteln!(self.src, "return {};", if payload_is_void { "" } else { &previous });
for (level, var) in vars.iter().enumerate().rev() {
self.gen.gen.needs_wit_exception = true;
let (var_name, exception_name) = var;
let exception_name = match exception_name {
Some(type_name) => &format!("WitException<{}>",type_name),
None => "WitException",
};
uwrite!(
self.src,
"\
}} else {{
throw new WitException({var}.AsErr!, {level});
throw new {exception_name}({var_name}.AsErr!, {level});
}}
"
);
Expand Down
61 changes: 19 additions & 42 deletions tests/runtime/results/wasm.cs
Original file line number Diff line number Diff line change
@@ -1,77 +1,54 @@
using ResultsWorld.wit.imports.test.results;

namespace ResultsWorld.wit.exports.test.results
{
public class TestImpl : ITest
{
public static float StringError(float a)
{
return ResultsWorld.wit.imports.test.results.TestInterop.StringError(a);
return imports.test.results.TestInterop.StringError(a);
}

public static float EnumError(float a)
{
try {
return ResultsWorld.wit.imports.test.results.TestInterop.EnumError(a);
} catch (WitException e) {
switch ((ResultsWorld.wit.imports.test.results.ITest.E) e.Value) {
case ResultsWorld.wit.imports.test.results.ITest.E.A:
throw new WitException(ITest.E.A, 0);
case ResultsWorld.wit.imports.test.results.ITest.E.B:
throw new WitException(ITest.E.B, 0);
case ResultsWorld.wit.imports.test.results.ITest.E.C:
throw new WitException(ITest.E.C, 0);
default:
throw new Exception("unreachable");
}
return imports.test.results.TestInterop.EnumError(a);
} catch (WitException<imports.test.results.ITest.E> e) {
throw new WitException(e.TypedValue, 0);
}
}

public static float RecordError(float a)
{
try {
return ResultsWorld.wit.imports.test.results.TestInterop.RecordError(a);
} catch (WitException e) {
var value = (ResultsWorld.wit.imports.test.results.ITest.E2) e.Value;
throw new WitException(new ITest.E2(value.line, value.column), 0);
return imports.test.results.TestInterop.RecordError(a);
} catch (WitException<imports.test.results.ITest.E2> e) {
throw new WitException(new ITest.E2(e.TypedValue.line, e.TypedValue.column), 0);
}
}

public static float VariantError(float a)
{
try {
return ResultsWorld.wit.imports.test.results.TestInterop.VariantError(a);
} catch (WitException e) {
var value = (ResultsWorld.wit.imports.test.results.ITest.E3) e.Value;
switch (value.Tag) {
case ResultsWorld.wit.imports.test.results.ITest.E3.Tags.E1:
switch (value.AsE1) {
case ResultsWorld.wit.imports.test.results.ITest.E.A:
throw new WitException(ITest.E3.E1(ITest.E.A), 0);
case ResultsWorld.wit.imports.test.results.ITest.E.B:
throw new WitException(ITest.E3.E1(ITest.E.B), 0);
case ResultsWorld.wit.imports.test.results.ITest.E.C:
throw new WitException(ITest.E3.E1(ITest.E.C), 0);
default:
throw new Exception("unreachable");
}
case ResultsWorld.wit.imports.test.results.ITest.E3.Tags.E2: {
throw new WitException(ITest.E3.E2(new ITest.E2(value.AsE2.line, value.AsE2.column)), 0);
}
default:
throw new Exception("unreachable");
}
return imports.test.results.TestInterop.VariantError(a);
} catch (WitException<imports.test.results.ITest.E3> e)
when (e.TypedValue.Tag == imports.test.results.ITest.E3.Tags.E1) {
throw new WitException(ITest.E3.E1((ITest.E)Enum.Parse(typeof(ITest.E), e.TypedValue.AsE1.ToString())), 0);
} catch (WitException<imports.test.results.ITest.E3> e)
when (e.TypedValue.Tag == imports.test.results.ITest.E3.Tags.E2) {
throw new WitException(ITest.E3.E2(new ITest.E2(e.TypedValue.AsE2.line, e.TypedValue.AsE2.column)), 0);
}
catch {
throw new Exception("unreachable");
}
}

public static uint EmptyError(uint a)
{
return ResultsWorld.wit.imports.test.results.TestInterop.EmptyError(a);
return imports.test.results.TestInterop.EmptyError(a);
}

public static void DoubleError(uint a)
{
ResultsWorld.wit.imports.test.results.TestInterop.DoubleError(a);
imports.test.results.TestInterop.DoubleError(a);
}
}
}

0 comments on commit c2e7892

Please sign in to comment.