Skip to content

Stemt/AFPP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AFPP

The Anonymous Function Pre-Processor for C.

Simple Example

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.c

Essentially 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 ---

Build AFPP and example

For building you only need a C compiler that supports C23.

cc -o nob nob.c && ./nob

Source files generated by AFPP however are C99 compatible.

Limitations

These are NOT Lambdas

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.

Text Only Processing

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

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.

FAQ

Is this production ready?

Haha no, this was a hobby project slapped together in a weekend, use this at your own risk.

Can you nest anonymous functions?

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);
  };

Can you fix the indentation of function implementations?

no (am lazy)

About

A very simple C source preprocessor that implements anonoymous functions for C.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages