The Anonymous Function Pre-Processor for C.
Using AFPP one can define an anonymous function like so.
#include <stdio.h>
typedef int(*Callback)(int a, int b);
int main(void){
Callback sub = []<int>(int a, int b){
return a - b;
};
printf("sub: %d\n", sub(1,2));
return 0;
}Then to compile this example you first have to pass the file through AFPP and then compile the output file named like <og_name>.afpp.c.
mkdir build && afpp -d build example.c && cc -o build/example build/example.c.afpp.cEssentially what AFPP does is it scans for the pattern []< return-type >( function-args ){ function-body } and seperates it into a prototype, reference and implementation.
All generated prototypes are appended at the beginning or 'head' of the file, references are replaced inline in the 'body' of the file and implementations are appended at the end or 'tail' of the file.
The resulting output looks like this:
// +++ AFPP HEAD +++
int afpp__example_c_anon_func_0(int a, int b);
// --- AFPP HEAD ---
#include <stdio.h>
typedef int(*Callback)(int a, int b);
int main(void){
Callback sub = afpp__example_c_anon_func_0;
printf("sub: %d\n", sub(1,2));
return 0;
}
// +++ AFPP TAIL +++
int afpp__example_c_anon_func_0(int a, int b){
return a - b;
}
// --- AFPP TAIL ---For building you only need a C compiler that supports C23.
cc -o nob nob.c && ./nobSource files generated by AFPP however are C99 compatible.
The syntax was purely chosen because the pattern is easy to identify in normal C code.
So unlike in C++ capturing variables is not supported.
Because AFPP is a preprocessor purely working by searching and replacing text patterns the scope of its error reporting is limited. This also why you need to specify the return type for the anonymous function, as the preprocessor does not have the type information that a proper compiler would have.
I've also not tested much how AFPP interacts with the normal C pre-processor, AFPP tries to leave everything apart from the anonoymous function syntax alone, but since AFPP is applied before the normal preprocessor if they do interact the results are likely to be unexpected.
Language servers won't understand what you're doing. So if you're using AFPP, your IDE will likely report an error on every place an anonymous function is defined.
Though with clangd I've noticed that if you assign it to a function pointer variable you'll only get an error on the assignment and not in the other places of your code.
Trust the AFPP error/warnings and your compiler and everything should be good.
Haha no, this was a hobby project slapped together in a weekend, use this at your own risk.
Hell yeah brother!
Callback add = []<int>(int a, int b){
Callback nested_add = []<int>(int a, int b){
Callback nested_nested_add = []<int>(int a, int b){
return a + b;
};
return nested_nested_add(a,b);
};
return nested_add(a,b);
};no (am lazy)