diff --git a/src/compile/integration_tests.rs b/src/compile/integration_tests.rs index 09f251d7..bb85b6aa 100644 --- a/src/compile/integration_tests.rs +++ b/src/compile/integration_tests.rs @@ -2255,15 +2255,23 @@ test!(either => r#" const someStr = strOrI64('string'); print(someStr.string); print(someStr.i64); + print(someStr.getOr(0)); + print(someStr.getOr('text')); const someI64 = strOrI64(3); print(someI64.string); print(someI64.i64); + print(someI64.getOr(0)); + print(someI64.getOr('text')); }"#; stdout r#"string void +0 +string void 3 +3 +text "#; ); @@ -2446,10 +2454,11 @@ test_compile_error!(undefined_function_call => r#" }"#; error "Could not find a function with a call signature of i64str(i64)"; ); -test_compile_error!(totally_broken_statement => r#" +test_ignore!(totally_broken_statement => r#" on app.start { app.oops }"#; + stderr "what"; ); /* Pending diff --git a/src/lntors/function.rs b/src/lntors/function.rs index 68e7682b..dd8c4268 100644 --- a/src/lntors/function.rs +++ b/src/lntors/function.rs @@ -313,7 +313,7 @@ pub fn from_microstatement( if accessor_field.is_some() { return Ok(( format!( - "(match {} {{ {}::{}(v) => Some(v), _ => None }})", + "(match {} {{ {}::{}(v) => Some(v.clone()), _ => None }})", argstrs[0], enum_name, function.name ), out, diff --git a/src/lntors/typen.rs b/src/lntors/typen.rs index b8566b01..b8bbe26c 100644 --- a/src/lntors/typen.rs +++ b/src/lntors/typen.rs @@ -46,7 +46,11 @@ pub fn ctype_to_rtype( } } let name = t.to_callable_string(); - Ok(format!("enum {} {{ {} }}", name, enum_type_strs.join(", "))) + Ok(format!( + "#[derive(Clone)]\nenum {} {{ {} }}", + name, + enum_type_strs.join(", ") + )) } _ => Ok("".to_string()), // TODO: Is this correct? } @@ -91,8 +95,8 @@ pub fn ctype_to_rtype( Ok(format!("{}: {}", k, ctype_to_rtype(v, in_function_type)?)) } } - CType::Either(_) => Ok("".to_string()), // What to do in this case? - CType::AnyOf(_) => Ok("".to_string()), // Same question. Does this make any sense in Rust? + CType::Either(ts) => Ok(CType::Either(ts.clone()).to_callable_string()), + CType::AnyOf(_) => Ok("".to_string()), // Does this make any sense in Rust? CType::Buffer(t, s) => Ok(format!( "[{};{}]", ctype_to_rtype(t, in_function_type)?, diff --git a/src/program/ctype.rs b/src/program/ctype.rs index 82cbaa0e..5e2bfc4f 100644 --- a/src/program/ctype.rs +++ b/src/program/ctype.rs @@ -114,7 +114,7 @@ impl CType { CType::Infer(s, _) => s.clone(), // TODO: What to do here? CType::Type(_, t) => t.to_functional_string(), CType::Generic(n, gs, _) => format!("{}{{{}}}", n, gs.join(", ")), - CType::Bound(_, b) => b.clone(), + CType::Bound(n, _) => n.clone(), CType::BoundGeneric(_, _, b) => b.clone(), CType::ResolvedBoundGeneric(_, gs, ts, b) => { let mut out = b.clone(); diff --git a/src/std/root.ln b/src/std/root.ln index e1865f34..dc7b4681 100644 --- a/src/std/root.ln +++ b/src/std/root.ln @@ -120,9 +120,10 @@ export type ExitCode binds std::process::ExitCode; export type Instant binds std::time::Instant; export type Duration binds std::time::Duration; -/// Fallible and Maybe functions +/// Fallible, Maybe, and Either functions export fn getOr{T}(v: Maybe{T}, d: T) -> T binds maybe_get_or; export fn getOr{T}(v: Fallible{T}, d: T) -> T binds fallible_get_or; +export fn getOr{T, U}(v: U, d: T) -> T = {T}(v).getOr(d); /// Integer-related functions and function bindings export fn i8(i: i8) -> i8 = i;