#include typedef char* str; #define GENERATE_OPTION_TYPES(Option) \ Option(int) \ Option(str) #define GENERATE_RESULT_TYPES(Result) \ Result(str, int) \ Result(long, int) #define GENERATE_RESULT_OK_TYPES(Ok, x) \ Ok(str, x) \ Ok(long, x) #define GENERATE_RESULT_ERR_TYPES(Err, x) \ Err(x, int) ///////////////////////// /** Returns type struct `Option(T)` for the specified "generic" type. * * @param T the value type. */ #define Option(T) struct Option_ ## T /** Returns name of constructor function for `Option(T)` of variant `Some(T)`. * * @param T the value type. */ #define OptionSome(T) option_some_ ## T /** Defines struct `Option(T)` and constructor function `OptionSome(T)` for * the specified "generic" type. * * @param T the value type. */ #define DEFINE_OPTION_TYPE(T) \ Option(T) { \ bool tag; \ T value; \ }; \ static inline Option(T) OptionSome(T)(T value) { \ return (Option(T)) { .tag = true, .value = value }; \ } #ifdef GENERATE_OPTION_TYPES /** Creates struct `Option(T)` in variant `Some(T)` with the given value * of type `T`. * * @param value the value to be wrapped in `Some(T)`. */ #define Some(value) _Generic((value) \ GENERATE_OPTION_TYPES(OPTION_SOME_GENERIC_ENTRY) \ )(value) #define OPTION_SOME_GENERIC_ENTRY(T) , T: (OptionSome(T)) /** Creates struct `Option(T)` in variant `None`. * * @param T type of `Option(T)`. */ #define None(T) (Option(T)) { .tag = false } GENERATE_OPTION_TYPES(DEFINE_OPTION_TYPE) #endif #define is_some(option) ((option).tag) #define is_none(option) (!(option).tag) //////////////// /** Returns type struct `Result(T, E)` for the specified "generic" types. * * @param T the value type. * @param E the error type. */ #define Result(T, E) struct Result_ ## T ## __ ## E /** Returns name of constructor function for struct `Result(T, E)` in variant * `Ok(T)` for the specified "generic" types. * * @param T the value type. * @param E the error type. */ #define ResultOk(T, E) result_ok_ ## T ## __ ## E /** Returns name of constructor function for struct `Result(T, E)` in variant * `Err(E)` for the specified "generic" types. * * @param T the value type. * @param E the error type. */ #define ResultErr(T, E) result_err_ ## T ## __ ## E /** Defines struct `Result(T, E)` and constructor functions `ResultOk(T, E)` * and `ResultErr(T, E)` for the specified "generic" types. * * @param T the value type. * @param E the error type. */ #define DEFINE_RESULT_TYPE(T, E) \ Result(T, E) { \ bool tag; \ union { \ T value; \ E err; \ }; \ }; \ static inline Result(T, E) ResultOk(T, E) (T value) { \ return (Result(T, E)) { .tag = true, .value = value }; \ } \ static inline Result(T, E) ResultErr(T, E) (E err) { \ return (Result(T, E)) { .tag = false, .err = err }; \ } #ifdef GENERATE_RESULT_TYPES /** Creates struct `Result(T, E)` in variant `Ok(T)` with the given value * of "generic" type `T`. * * @param ok_value the value to be wrapped. * @param E the error type. */ #define Ok(ok_value, E) _Generic((ok_value) \ GENERATE_RESULT_OK_TYPES(RESULT_OK_GENERIC_ENTRY, E) \ )(ok_value) #define RESULT_OK_GENERIC_ENTRY(T, E) , T: (ResultOk(T, E)) /** Creates struct `Result(T, E)` in variant `Err(E)` with the given value * of "generic" type `E`. * * @param T the value type. * @param err_value the error value to be wrapped. */ #define Err(T, err_value) _Generic((err_value) \ GENERATE_RESULT_ERR_TYPES(RESULT_ERR_GENERIC_ENTRY, T) \ )(err_value) #define RESULT_ERR_GENERIC_ENTRY(T, E) , E: (ResultErr(T, E)) GENERATE_RESULT_TYPES(DEFINE_RESULT_TYPE) #endif #define is_ok(result) ((result).tag) #define is_err(result) (!(result).tag) ////// /** A statement expression that returns the contained value or a default. * * Option(T): * @code * unwrap_or(Some(42), 100) # => 42 * unwrap_or(None(int), 100) # => 100 * @endcode * * Result(T, E): * @code * unwrap_or(Ok(42, str), 100) # => 42 * unwrap_or(Err(int, "NaN"), 100) # => 100 * @endcode * * @param cont container object (struct with `.tag` and `.value`). * @param default_value the default value to be returned. */ #define unwrap_or(cont, default_value) ({ \ __typeof__(cont) _cont_##__LINE__ = (cont); \ _cont_##__LINE__.tag ? _cont_##__LINE__.value : (default_value); \ })