// Corre un programa de Mini desde un archivo: mini archivo.mini
#include <stdio.h>
#include <stdlib.h>

#include "interp.h"
#include "parser.h"

// Lee el archivo completo a un bloque nuevo, terminado en '\0'. Quien llama lo libera.
// Devuelve NULL si no pudo abrirlo o si no hay memoria.
static char *read_file(const char *path) {
    FILE *file = fopen(path, "r");
    if (file == NULL) {
        return NULL;
    }
    size_t capacity = 1024;
    size_t length = 0;
    char *text = malloc(capacity);
    while (text != NULL) {
        length += fread(text + length, 1, capacity - length - 1, file);
        if (length < capacity - 1) {
            text[length] = '\0';
            break;
        }
        capacity *= 2;
        char *grown = realloc(text, capacity);
        if (grown == NULL) {
            free(text);
        }
        text = grown;
    }
    fclose(file);
    return text;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "uso: %s archivo.mini\n", argv[0]);
        return 2;
    }
    char *source = read_file(argv[1]);
    if (source == NULL) {
        fprintf(stderr, "%s: no se pudo leer el archivo\n", argv[1]);
        return 2;
    }
    ParseError syntax;
    Stmt *program = parse_program(source, &syntax);
    int status = 0;
    if (program == NULL && syntax.message[0] != '\0') {
        fprintf(stderr, "%s:%d:%d: error de sintaxis: %s\n", argv[1], syntax.line, syntax.column, syntax.message);
        status = 1;
    } else {
        RunError error;
        if (!run_program(program, stdout, &error)) {
            // Primero lo que ya escribieron los print, para que salga en orden.
            fflush(stdout);
            fprintf(stderr, "%s: error de ejecución: %s\n", argv[1], error.message);
            status = 1;
        }
    }
    stmt_free(program);
    free(source);
    return status;
}
