// Lo que hace una llamada de Mini con los marcos, escrito a mano con Env.
//
//     let rate = 2
//     def scale(n) = n * rate
//     def outer(n) = scale(n + 1)
//     print outer(4)
#include <stdio.h>

#include "env.h"

// Busca name desde ese marco y escribe lo que encuentra.
static void show(const char *where, const Env *frame, const char *name) {
    double value;
    if (env_get(frame, name, &value)) {
        printf("%-10s %-5s = %g\n", where, name, value);
    } else {
        printf("%-10s %-5s no existe\n", where, name);
    }
}

int main(void) {
    Env *global = env_new(NULL);
    Env *outer = env_new(global);
    Env *scale = env_new(global);       // cuelga del global, no de outer
    Env *wrong = env_new(outer);        // lo que NO hace Mini: colgar del marco de quien llama
    if (global == NULL || outer == NULL || scale == NULL || wrong == NULL) {
        fprintf(stderr, "no hay memoria\n");
        env_free(wrong);
        env_free(scale);
        env_free(outer);
        env_free(global);
        return 1;
    }
    if (!env_set(global, "rate", 2) || !env_set(outer, "n", 4) || !env_set(scale, "n", 5)) {
        fprintf(stderr, "no hay memoria\n");
        env_free(wrong);
        env_free(scale);
        env_free(outer);
        env_free(global);
        return 1;
    }

    show("global", global, "rate");
    show("global", global, "n");
    show("outer", outer, "n");
    show("outer", outer, "rate");
    show("scale", scale, "n");
    show("scale", scale, "rate");
    show("wrong", wrong, "n");

    // Primero los marcos hijos, aunque Env no libera al padre: el orden de la pila.
    env_free(wrong);
    env_free(scale);
    env_free(outer);
    env_free(global);
    return 0;
}
