mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add @try Builtin (#2333)
* Add @try macro * Add @try_catch. Update release notes. --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
@@ -410,6 +410,7 @@ macro swizzle2(v, v2, ...) @builtin
|
||||
{
|
||||
return $$swizzle2(v, v2, $vasplat);
|
||||
}
|
||||
|
||||
<*
|
||||
Return the excuse in the Optional if it is Empty, otherwise
|
||||
return a null fault.
|
||||
@@ -434,6 +435,67 @@ macro bool @ok(#expr) @builtin
|
||||
return true;
|
||||
}
|
||||
|
||||
<*
|
||||
Check if an Optional expression evaluates to a fault. If so, return it;
|
||||
else, assign the result to an expression.
|
||||
|
||||
@require $defined(#v = #v) : "#v must be a variable"
|
||||
@require $defined(#expr!) : "Expected an optional expression"
|
||||
@require @assignable_to(#expr!!, $typeof(#v)) : `Type of #expr must be an optional of #v's type`
|
||||
*>
|
||||
macro void? @try(#v, #expr) @builtin
|
||||
{
|
||||
var res = #expr;
|
||||
if (catch err = res) return err?;
|
||||
#v = res;
|
||||
}
|
||||
|
||||
<*
|
||||
Check if an Optional expression evaluates to a fault. If so, return true if it is the
|
||||
expected fault, the optional if it is unexpected, or false if there was no fault and
|
||||
the assign happened.
|
||||
|
||||
This can be used in like this:
|
||||
|
||||
while (true)
|
||||
{
|
||||
char[] data;
|
||||
// Read until end of file
|
||||
if (@try_catch(data, load_line(), io::EOF)) break;
|
||||
.. use data ..
|
||||
}
|
||||
|
||||
In this example we read until we reach an EOF, which is expected. However, if we encounter some other
|
||||
fault, we rethrow is. Without this macro, the code is instead written like:
|
||||
|
||||
while (true)
|
||||
{
|
||||
char[]? data;
|
||||
data = load_line();
|
||||
if (catch err = data)
|
||||
{
|
||||
if (err = io::EOF) break;
|
||||
return err?
|
||||
}
|
||||
.. use data ..
|
||||
}
|
||||
|
||||
@require $defined(#v = #v) : "#v must be a variable"
|
||||
@require $defined(#expr!) : "Expected an optional expression"
|
||||
@require @assignable_to(#expr!!, $typeof(#v)) : `Type of #expr must be an optional of #v's type`
|
||||
@return "True if it was the expected fault, false if the variable was assigned, otherwise returns an optional."
|
||||
*>
|
||||
macro bool? @try_catch(#v, #expr, fault expected_fault) @builtin
|
||||
{
|
||||
var res = #expr;
|
||||
if (catch err = res)
|
||||
{
|
||||
return err == expected_fault ? true : err?;
|
||||
}
|
||||
#v = res;
|
||||
return false;
|
||||
}
|
||||
|
||||
<*
|
||||
@require $defined(&#value, (char*)&#value) : "This must be a value that can be viewed as a char array"
|
||||
*>
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
- Add `thread::fence` providing a thread fence.
|
||||
- Place output in `out` by default for projects. Use temp folder for building at the command line.
|
||||
- Allow absolute paths for `$embed`.
|
||||
- Add `@try` and `@try_catch`.
|
||||
|
||||
### Fixes
|
||||
- mkdir/rmdir would not work properly with substring paths on non-windows platforms.
|
||||
|
||||
@@ -28,6 +28,41 @@ fn void test_enum_by_name()
|
||||
assert(@catch(enum_by_name(Tester, "GHI")) == NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
faultdef SOME_FAULT, ABC_FAULT;
|
||||
|
||||
fn void test_try_catch()
|
||||
{
|
||||
int val;
|
||||
int? x = ABC_FAULT?;
|
||||
assert(@try_catch(val, x, ABC_FAULT)!!);
|
||||
assert(val == 0);
|
||||
assert(!@catch(@try_catch(val, x, ABC_FAULT)));
|
||||
x = SOME_FAULT?;
|
||||
assert(@catch(@try_catch(val, x, ABC_FAULT)) == SOME_FAULT);
|
||||
x = 3;
|
||||
assert(!@try_catch(val, x, ABC_FAULT)!!);
|
||||
assert(val == 3);
|
||||
}
|
||||
|
||||
fn void test_try_set()
|
||||
{
|
||||
assert(enum_by_name(Tester, "ABC")!! == Tester.ABC);
|
||||
|
||||
Tester val;
|
||||
if (catch @try(val, enum_by_name(Tester, "ABC"))) abort("Test failure");
|
||||
assert(val == Tester.ABC);
|
||||
|
||||
Tester another;
|
||||
if (catch err = @try(another, enum_by_name(Tester, "GHI")))
|
||||
{
|
||||
assert(err == NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
abort("Test failure");
|
||||
}
|
||||
|
||||
fn void test_likely()
|
||||
{
|
||||
int a = 2;
|
||||
|
||||
Reference in New Issue
Block a user