mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
163 lines
4.8 KiB
C
163 lines
4.8 KiB
C
// #target: macos-x64
|
|
module demo;
|
|
import libc;
|
|
import std::io;
|
|
|
|
fault MathError
|
|
{
|
|
DIVISION_BY_ZERO
|
|
}
|
|
|
|
fn int foo() { return 123; }
|
|
fn int bar() { return 0; }
|
|
|
|
fn double! divide(int a, int b)
|
|
{
|
|
if (b == 0) return MathError.DIVISION_BY_ZERO!;
|
|
return (double)(a) / (double)(b);
|
|
|
|
}
|
|
|
|
// Rethrowing an error uses "?" suffix
|
|
fn void! testMayError()
|
|
{
|
|
divide(foo(), bar())?;
|
|
}
|
|
|
|
fn void main()
|
|
{
|
|
// ratio has a failable type.
|
|
double! ratio = divide(foo(), bar());
|
|
|
|
// Handle the error
|
|
if (catch err = ratio)
|
|
{
|
|
case MathError.DIVISION_BY_ZERO:
|
|
libc::printf("Division by zero\n");
|
|
return;
|
|
default:
|
|
libc::printf("Unexpected error!");
|
|
return;
|
|
}
|
|
// Flow typing makes "ratio"
|
|
// have the type double here.
|
|
libc::printf("Ratio was %f\n", ratio);
|
|
}
|
|
|
|
/* #expect: demo.ll
|
|
|
|
|
|
define i64 @demo_divide(double* %0, i32 %1, i32 %2) #0 {
|
|
entry:
|
|
%reterr = alloca i64, align 8
|
|
%eq = icmp eq i32 %2, 0
|
|
br i1 %eq, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %entry
|
|
ret i64 ptrtoint (%.fault* @"demo_MathError$DIVISION_BY_ZERO" to i64)
|
|
|
|
if.exit: ; preds = %entry
|
|
%sifp = sitofp i32 %1 to double
|
|
%sifp1 = sitofp i32 %2 to double
|
|
%fdiv = fdiv double %sifp, %sifp1
|
|
store double %fdiv, double* %0, align 8
|
|
ret i64 0
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define i64 @demo_testMayError() #0 {
|
|
entry:
|
|
%error_var = alloca i64, align 8
|
|
%retparam = alloca double, align 8
|
|
%reterr = alloca i64, align 8
|
|
%0 = call i32 @demo_foo()
|
|
%1 = call i32 @demo_bar()
|
|
%2 = call i64 @demo_divide(double* %retparam, i32 %0, i32 %1)
|
|
%not_err = icmp eq i64 %2, 0
|
|
br i1 %not_err, label %after_check, label %assign_optional
|
|
|
|
assign_optional: ; preds = %entry
|
|
store i64 %2, i64* %error_var, align 8
|
|
br label %guard_block
|
|
|
|
after_check: ; preds = %entry
|
|
br label %noerr_block
|
|
|
|
guard_block: ; preds = %assign_optional
|
|
%3 = load i64, i64* %error_var, align 8
|
|
ret i64 %3
|
|
|
|
noerr_block: ; preds = %after_check
|
|
ret i64 0
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define void @demo_main() #0 {
|
|
entry:
|
|
%ratio = alloca double, align 8
|
|
%ratio.f = alloca i64, align 8
|
|
%retparam = alloca double, align 8
|
|
%err = alloca i64, align 8
|
|
%switch = alloca i64, align 8
|
|
%0 = call i32 @demo_foo()
|
|
%1 = call i32 @demo_bar()
|
|
%2 = call i64 @demo_divide(double* %retparam, i32 %0, i32 %1)
|
|
%not_err = icmp eq i64 %2, 0
|
|
br i1 %not_err, label %after_check, label %assign_optional
|
|
|
|
assign_optional: ; preds = %entry
|
|
store i64 %2, i64* %ratio.f, align 8
|
|
br label %after_assign
|
|
|
|
after_check: ; preds = %entry
|
|
%3 = load double, double* %retparam, align 8
|
|
store double %3, double* %ratio, align 8
|
|
store i64 0, i64* %ratio.f, align 8
|
|
br label %after_assign
|
|
|
|
after_assign: ; preds = %after_check, %assign_optional
|
|
br label %testblock
|
|
|
|
testblock: ; preds = %after_assign
|
|
%optval = load i64, i64* %ratio.f, align 8
|
|
%not_err1 = icmp eq i64 %optval, 0
|
|
br i1 %not_err1, label %after_check3, label %assign_optional2
|
|
|
|
assign_optional2: ; preds = %testblock
|
|
store i64 %optval, i64* %err, align 8
|
|
br label %end_block
|
|
|
|
after_check3: ; preds = %testblock
|
|
store i64 0, i64* %err, align 8
|
|
br label %end_block
|
|
|
|
end_block: ; preds = %after_check3, %assign_optional2
|
|
%4 = load i64, i64* %err, align 8
|
|
%neq = icmp ne i64 %4, 0
|
|
br i1 %neq, label %if.then, label %if.exit
|
|
|
|
if.then: ; preds = %end_block
|
|
store i64 %4, i64* %switch, align 8
|
|
br label %switch.entry
|
|
|
|
switch.entry: ; preds = %if.then
|
|
%5 = load i64, i64* %switch, align 8
|
|
%eq = icmp eq i64 ptrtoint (%.fault* @"demo_MathError$DIVISION_BY_ZERO" to i64), %5
|
|
br i1 %eq, label %switch.case, label %next_if
|
|
|
|
switch.case: ; preds = %switch.entry
|
|
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str, i32 0, i32 0))
|
|
ret void
|
|
|
|
next_if: ; preds = %switch.entry
|
|
br label %switch.default
|
|
|
|
switch.default: ; preds = %next_if
|
|
%7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i32 0, i32 0))
|
|
ret void
|
|
|
|
if.exit: ; preds = %end_block
|
|
%8 = load double, double* %ratio, align 8
|
|
%9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.2, i32 0, i32 0), double %8)
|
|
ret void
|
|
}
|