Quick actions

cmd+k|ctrl+k

Navigation

Languages

Generate_FOLD

Snippet info

Language

C

Visibility

public

Author

evine

Created

2016-05-06T12:13:01Z

Updated

2016-05-06T20:44:00Z

#include <stdio.h>
#include <assert.h>

void Generate_FOLD(int RecursionCount, int SafetyBuffer)
{
    assert(RecursionCount >= 2);
    assert(SafetyBuffer >= RecursionCount);
    
    printf("#define FOLD(...) FOLD_(NUM_ARGS(__VA_ARGS__), FIRST_ARG(__VA_ARGS__), REST_ARG(__VA_ARGS__))\n");
    printf("#define FOLD_(N, M, ...) FOLD__(N, M, __VA_ARGS__)\n");
    printf("#define FOLD__(N, M, ...) FOLD_##N(M, FIRST_ARG(__VA_ARGS__), REST_ARG(__VA_ARGS__))\n");
    
    printf("#define FOLD_1(F, ...)\n");
    printf("#define FOLD_2(F, ...) FIRST_ARG(__VA_ARGS__)\n");
    printf("#define FOLD_3_(F, R) EXPAND(F R)\n");
    printf("#define FOLD_3(F, R, L) FOLD_3_(F, (R, L))\n");
    
    for(int i = 4; i <= RecursionCount + 1; ++i)
    {
        printf("#define FOLD_%i_(F, R, ...) FOLD_%i(F, F R, __VA_ARGS__)\n",i,i-1);
        printf("#define FOLD_%i(F, R, ...) FOLD_%i_(F, (R, FIRST_ARG(__VA_ARGS__)), REST_ARG(__VA_ARGS__))\n",i,i);
    }
    
    for(int i = RecursionCount + 2; i <= SafetyBuffer + 1; ++i)
    {
        printf("#define FOLD_%i(...) -----\"Over Max (%i) arguments to FOLD vararg passed (%i)\"-----\n",i,RecursionCount,i-1);
    }
}

void Generate_FOLDR(int RecursionCount, int SafetyBuffer)
{
    assert(RecursionCount >= 2);
    assert(SafetyBuffer >= RecursionCount);
    
    printf("#define BEGIN_ARG_1(...)\n");
    printf("#define LAST_ARG_1(...)\n");
    for(int i = 2; i <= RecursionCount + 1; ++i)
    {
        printf("#define BEGIN_ARG_%i(",i);
        for(int j = 1; j < i - 1; ++j)
        {
            printf("a%i,",j);
        }
        printf("...) ");
        for(int j = 1; j < i - 1; ++j)
        {
            printf("a%i",j);
            if(!(j < i - 2)) break;
            printf(",");
        }
        printf("\n");
        printf("#define LAST_ARG_%i(",i);
        for(int j = 1; j < i - 1; ++j)
        {
            printf("a%i,",j);
        }
        printf("...) __VA_ARGS__\n");
    }
    
    printf("#define FOLDR(...) FOLDR_(NUM_ARGS(__VA_ARGS__), FIRST_ARG(__VA_ARGS__), REST_ARG(__VA_ARGS__))\n");
    printf("#define FOLDR_(N, F, ...) FOLDR__(N, F, __VA_ARGS__)\n");
    printf("#define FOLDR__(N, F, ...) FOLDR_##N(F, LAST_ARG_##N(__VA_ARGS__), BEGIN_ARG_##N(__VA_ARGS__))\n");
    
    printf("#define FOLDR_1(F, ...)\n");
    printf("#define FOLDR_2(F, ...) EXPAND(FIRST_ARG(__VA_ARGS__))\n");
    printf("#define FOLDR_3_(F, R) EXPAND(F R)\n");
    printf("#define FOLDR_3(F, R, L) FOLDR_3_(F, (L, R))\n");
    
    for(int i = 4; i <= RecursionCount + 1; ++i)
    {
        printf("#define FOLDR_%i_(F, R, ...) FOLDR_%i(F, F R, __VA_ARGS__)\n",i,i-1);
        printf("#define FOLDR_%i(F, R, ...) FOLDR_%i_(F, (LAST_ARG_%i(__VA_ARGS__), R), BEGIN_ARG_%i(__VA_ARGS__))\n",i,i,i-1,i-1);
    }
    
    for(int i = RecursionCount + 2; i <= SafetyBuffer + 1; ++i)
    {
        printf("#define FOLDR_%i(...) -----\"Over Max (%i) arguments to FOLDR vararg passed (%i)\"-----\n",i,RecursionCount,i-1);
    }
}

void Generate_NUM_ARG(int Count)
{
    assert(Count > 0);
    
    printf("#define NUM_ARGS_(");
    for(int i = Count; i > 0; --i)
    {
        printf("a%i,",i);
    }
    printf("N,...) N\n");
    
    printf("#define NUM_ARGS(...) EXPAND(NUM_ARGS_(__VA_ARGS__");
    for(int i = Count; i > 0; --i)
    {
        printf(",%i",i);
    }
    printf("))\n");
}


int main()
{
    printf("/* General Utility Macros */\n");
    printf("#define EXPAND(a) a\n");
    printf("#define FIRST_ARG(a, ...) a\n");
    printf("#define REST_ARG(a, ...) __VA_ARGS__\n");
    Generate_NUM_ARG(73);
    printf("\n");
    
    printf("/* FOLD Macros */\n");
    printf("#define FOLD_VERSION 2\n");
    Generate_FOLD(32, 51);
    printf("\n");
    
    printf("/* FOLDR Macros */\n");
    Generate_FOLDR(32, 51);
    
    return 0;
}

INFO