Skip to content

Instantly share code, notes, and snippets.

@machuidel
Last active December 6, 2018 14:44
Show Gist options
  • Save machuidel/d7cc099ddc4970c6ddf4 to your computer and use it in GitHub Desktop.
Save machuidel/d7cc099ddc4970c6ddf4 to your computer and use it in GitHub Desktop.
Option Type Macro
#pragma once
#ifndef _XOPTION_TYPE_H_
#define _XOPTION_TYPE_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include<stdio.h>
#include<stdlib.h>
/* Option */
typedef enum {
Option_some,
Option_none
} option_status_t;
#define Func_name(out_type, name, ...) name
#define Func_out_type(out_type, name, ...) out_type
#define Option(type) option ## _ ## type ## _t
#define Option_define(type) \
typedef struct { \
option_status_t status; \
type value; \
} Option(type)
#define Option_unwrap(x) (x.value)
#define Option_flatten(x) Option_unwrap(x)
#define Option_is_some(x) (x.status == Option_some)
#define Option_is_none(x) (x.status == Option_none)
#define Option_none(type) ((Option(type)){Option_none, 0})
#define Option_some(type, value) ((Option(type)){Option_some, value})
/* cmap can be used with stdc functions, but you need to specify the type */
#define Option_cmap(type, f, x) ((Option_is_some(x)) ? Option_some(type, f(x.value)) : Option_none(type))
/* fmap can only be used with an abstract X macro in which you define the type and stdc function */
#define Option_fmap(f, x) Option_cmap(f(Func_out_type), f(Func_name), x)
/* cflatmap can be used with stdc functions, but you need to specify the type */
#define Option_cflatmap(type, f, x) Option_flatten(Option_cmap(type, f, x))
/* fflatmap can only be used with an abstract X macro in which you define the type and stdc function */
#define Option_fflatmap(f, x) Option_cflatmap(f(Func_out_type), f(Func_name), x)
#ifdef __cplusplus
}
#endif
#endif // _XOPTION_TYPE_H_
#include <stdio.h>
#include <stdlib.h>
#include "option_type.h"
/* Define option */
Option_define(float);
Option_define(Option(float));
/* Define functions */
float _add2(float x) {
return x + 2.0f;
}
#define add2(_) _(float, _add2)
float _mul4(float x) {
return x * 4.0f;
}
#define mul4(_) _(float, _mul4)
Option(float) _madd2(float x) {
return Option_some(float, x + 2.0f);
}
#define madd2(_) _(Option(float), _madd2)
Option(float) _mmul4(float x) {
return Option_some(float, x * 4.0f);
}
#define mmul4(_) _(Option(float), _mmul4)
/* Test routine */
int main(int argc, char **argv) {
Option(float) result1 = Option_some(float, 2.0f);
Option(float) result2 = Option_fmap(mul4, Option_fmap(add2, result1));
Option(float) result3 = Option_some(float, 2.0f);
Option(float) result4 = Option_fflatmap(mmul4, Option_fflatmap(madd2, result3));
if(Option_is_some(result2)) {
printf("MAP: Some(%f)\n", Option_unwrap(result2));
} else {
printf("MAP: None\n");
}
if(Option_is_some(result4)) {
printf("FLATMAP: Some(%f)\n", Option_unwrap(result4));
} else {
printf("FLATMAP: None\n");
}
exit(EXIT_SUCCESS);
}
@machuidel
Copy link
Author

machuidel commented Dec 4, 2018

@solvingj

I would like to work with you on continuing this implementation. I would like to align your Macro's style and convention with the one used by Daan from Microsoft here:
https://github.com/koka-lang/libhandler

Please contact me if you are interested.

The goals also include implementing a Result type to Mimic Rust's as well, and then couple it all with libhandler (referenced above).

I noticed your comment just now after a year. Libhandler seems like an interesting project. Did you already finish the implementation / changes you mentioned? I did not continue this way I did above. My idea was to create a functional / higher order programming library in C to generate code for my game engine which I figured would be possible with a lot of C preprocessor hackery. Instead I now generate code using a code generator I wrote that reads annotation attributes from the C code using libclang and transform scripts written in Lua. Will release this and several other projects (cross platform build system using Lua etc.) as open source soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment