#ifndef AST_H
#define AST_H

typedef enum {
    EXPR_INT,
    EXPR_VAR,
    EXPR_BINOP,
} ExprType;

typedef struct Expr {
    ExprType type;
    long long int_val;
    char *var_name;
    int op;
    struct Expr *left;
    struct Expr *right;
} Expr;

typedef enum {
    WORD_LITERAL,
    WORD_VAR,
} WordType;

typedef struct {
    WordType type;
    char *text;
} Word;

typedef enum {
    TEST_FILE,
    TEST_NUM,
    TEST_STR,
} TestType;

typedef struct {
    TestType type;
    int op;
    char *file_path;
    Expr *num_left;
    Expr *num_right;
    Word *str_left;
    Word *str_right;
} Test;

typedef enum {
    STMT_ASSIGN,
    STMT_ECHO,
    STMT_IF,
    STMT_FOR,
    STMT_WHILE,
    STMT_EXEC,
    STMT_EXIT,
} StmtType;

typedef struct Stmt {
    StmtType type;
    struct Stmt *next;

    char *var_name;
    Expr *arith_val;
    char *str_val;

    Word **echo_args;
    int echo_argc;

    Test *cond;
    struct Stmt *then_body;
    struct Stmt *else_body;

    char *for_var;
    char **for_list;
    int for_list_count;
    struct Stmt *body;

    char **exec_argv;
    int exec_argc;

    Expr *exit_expr;
} Stmt;

Stmt* ast_parse(const char *source);
void ast_free(Stmt *stmt);
Expr* expr_new_int(long long val);
Expr* expr_new_var(const char *name);
Expr* expr_new_binop(int op, Expr *left, Expr *right);
void expr_free(Expr *e);
Test* test_new_file(int op, const char *path);
Test* test_new_num(int op, Expr *left, Expr *right);
Test* test_new_str(int op, Word *left, Word *right);
void test_free(Test *t);
Word* word_new_literal(const char *text);
Word* word_new_var(const char *name);
void word_free(Word *w);
Stmt* stmt_new(StmtType type);

#endif
