Desidero implementare le funzioni di ordine superiore (HOF) in C come zucchero sintattico con il minimo sforzo. Ad esempio, il codice seguenteFunzioni di ordine superiore in C come zucchero sintattico con il minimo sforzo
function add(int x) {
return int(int y) {
return x + y;
};
}
int main() {
function add1 = add(1);
return add1(2);
}
è transcompiled in puro C come
#include <stdlib.h>
typedef struct {
void *ctx;
void* (*fun)(void *arg, void *ctx);
} function;
function new_function(void *ctx, void* (*fun)(void *, void *)) {
function f = {.ctx=ctx, .fun=fun};
return f;
}
void* apply(function f, void *arg) {
return (*(f.fun))(arg, f.ctx);
}
typedef struct {
int x;
} context$1;
void* new_context$1(int x) {
context$1 *ctx = malloc(sizeof(context$1));
ctx->x = x;
return ctx;
}
void* function$1(void *arg, void *ctx) {
int y = (int)arg;
int x = ((context$1*)ctx)->x;
return (void*)(x + y);
}
function add(int x) {
return new_function(new_context$1(x), function$1);
}
int main() {
function add1 = add(1);
return (int)apply(add1, (void*)2);
}
Ho eseguire questa versione (manualmente) transcompiled e funziona bene. Per l'implementazione, credo che alcune manipolazioni AST e il sollevamento di lambda sarebbero sufficienti.
Ci sono dei potenziali difetti nel mio approccio? Esistono metodi più semplici per HOF o posso migliorare il mio approccio per renderlo più facile da implementare?
Sono totalmente d'accordo con il tuo secondo punto e +1 per Boehm GC :-). Ma potrebbe per favore istruirmi come si annullerebbe alla fine?Credo che funzionerebbero bene perché sono generati automaticamente. –
@XiaoJia: il problema con 'void *' è in 'function $ 1'. Cosa succede se il tipo di 'x + y' è più grande di' void * '? In questo esempio significherebbe 'sizeof (int)> sizeof (void *)', che sarebbe una strana implementazione in C, ma non così strano se 'x' avesse tipo' long long' invece di 'int'. Quindi il cast di "void *" perde informazioni. –
Beh, puoi sempre dire che il tuo traduttore automatico si prenderà cura di esso in qualche modo (purché tu non descriva l'algoritmo ma fornisca solo una traduzione di esempio). Ma guardo (void *) 2 e vedo che perderebbe informazioni se ci fosse un valore più ampio del pointer invece di 2. (E il cast verso/da void * non funzionerebbe affatto per le strutture passate per valore; ti stai rifiutando di supportarli o tradurrai tali funzioni in modo diverso?) –