Ich möchte Funktionen höherer Ordnung (HOFs) in C als syntaktischen Zucker mit minimalem Aufwand implementieren. Zum Beispiel für den folgenden CodeFunktionen höherer Ordnung in C als syntaktischer Zucker mit minimalem Aufwand
function add(int x) {
return int(int y) {
return x + y;
};
}
int main() {
function add1 = add(1);
return add1(2);
}
es in reines C als
transcompiled ist#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);
}
Ich habe diese (manuell) laufen transcompiled Version und es funktioniert gut. Für die Implementierung glaube ich, dass einige AST-Manipulation und Lambda-Anhebung ausreichen würden.
Gibt es mögliche Fehler in meinem Ansatz? Gibt es leichtere Methoden für HOFs, oder kann ich meinen Ansatz verbessern, um die Implementierung zu erleichtern?
Ich stimme völlig mit Ihrem zweiten Punkt und +1 für Boehm GC :-). Aber könntest du mir bitte beibringen, wie nichtig * irgendwann brechen würde?Ich glaube, sie würden gut funktionieren, weil sie automatisch generiert werden. –
@XiaoJia: Das Problem mit 'void *' liegt in 'function $ 1'. Was ist, wenn der Typ von x + y größer als void ist? In diesem Beispiel würde das bedeuten "sizeof (int)> sizeof (void *)", was eine seltsame C-Implementierung wäre, aber nicht so seltsam, wenn 'x' den Typ' long long' anstelle von 'int' hätte. Dann verliert der Cast zu "void *" Informationen. –
Nun, Sie können immer sagen, dass Ihr automatischer Übersetzer sich irgendwie darum kümmern wird (solange Sie den Algorithmus nicht beschreiben, sondern nur eine Beispielübersetzung liefern). Aber ich schaue nur auf (void *) 2 und sehe, dass es Informationen verlieren würde, wenn es einen breiteren als Zeiger-Wert anstelle von 2 gibt. (Und das Umwandeln nach/aus void * funktioniert überhaupt nicht für Strukturen, die nach Wert übergeben werden; Lehnen Sie es ab, sie überhaupt zu unterstützen, oder werden Sie solche Funktionen anders übersetzen? –