// Analiza una expresión, escribe el árbol y lo evalúa con x = 2 e y = 3.
// Si hay un error de sintaxis, muestra la línea y marca la columna.
#include <stdio.h>

#include "env.h"
#include "expr.h"
#include "parser.h"

// Escribe la línea número line de source, y debajo una marca en la columna.
static void show_position(const char *source, int line, int column) {
    const char *start = source;
    for (int current = 1; current < line && *start != '\0'; start++) {
        if (*start == '\n') {
            current++;
        }
    }
    for (const char *c = start; *c != '\0' && *c != '\n'; c++) {
        putchar(*c);
    }
    putchar('\n');
    for (int i = 1; i < column; i++) {
        putchar(' ');
    }
    puts("^");
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "uso: %s 'expresión'\n", argv[0]);
        return 1;
    }
    ParseError error;
    Expr *tree = parse_expression(argv[1], &error);
    if (tree == NULL) {
        show_position(argv[1], error.line, error.column);
        printf("línea %d, columna %d: %s\n", error.line, error.column, error.message);
        return 1;
    }
    printf("árbol: ");
    expr_print(tree, stdout);
    putchar('\n');

    int status = 1;
    Env *env = env_new(NULL);
    if (env != NULL && env_set(env, "x", 2.0) && env_set(env, "y", 3.0)) {
        double value;
        if (expr_eval(tree, env, &value)) {
            printf("valor: %g\n", value);
        } else {
            puts("no se pudo evaluar: variable desconocida o división entre cero");
        }
        status = 0;
    }
    env_free(env);
    expr_free(tree);
    return status;
}
