#define TO(x) (x(arg_node) = TRAVopt(x(arg_node), arg_info))

#define OUT_CONTINUE(format, ...) fprintf(global.outfileptr, format, ##__VA_ARGS__)
#define OUT(format, ...)                                                                           \
    fprintf(global.outfileptr, "%s" format,                                                        \
            ((format[__builtin_strlen(format) - 2] == ':' || format[0] == '.') ? "" : "    "),     \
            ##__VA_ARGS__)

#define IS_ARITH_OP(x) ((bool)(x & _BO_arith))
#define IS_LOG_OP(x) ((bool)(x & _BO_log))
#define IS_REL_OP(x) ((bool)(x & _BO_rel))

#define GET_INFERRED_TYPE_NODE(x) (TRAVopt(x, arg_info), arg_info->inferred_type)

#define GET_INFERRED_TYPE(x)                                                                       \
    (x(arg_node) = TRAVopt((x(arg_node)), arg_info), arg_info->inferred_type)

#define ERR(x, ...) CTIerrorLine(NODE_LINE(arg_node), x, ##__VA_ARGS__)

#define MAX(x, y) (((x) > (y)) ? (x) : (y))

#define IS_GLOBAL_SYMBOL_TABLE(x) (!(x)->parent)

#define TY_IS_ARRAY(ty) ((ty) & TY_arr)
#define TY_ARRAY_ELEMENT_TYPE(ty) ((ty) & ~TY_arr)

#define TY_IS_CONST(ty) ((ty) & TY_const)
#define TY_CONSTLESS_TYPE(ty) ((ty) & ~TY_const)

#define TY_FUNDAMENTAL_TYPE(ty) ((ty) & ~(TY_const | TY_arr))

#define GLOBALDEF_TY_IS_ARRAY(x) (GLOBALDEF_STLINK(x)->type & TY_arr)
#define GLOBALDEF_IS_ARRAY(x) (GLOBALDEF_DIMS(x) != NULL)
#define VARDECL_IS_ARRAY(x) (VARDECL_TYPE(x) & TY_arr)
#define VAR_IS_ARRAYIDX(x) (VAR_INDICES(x) != NULL)
#define VARLET_IS_ARRAYIDX(x) (VARLET_INDICES(x) != NULL)
#define PARAM_IS_ARRAY(x) (PARAM_TYPE(x) & TY_arr)
#define EXPR_IS_ARREXPR(x) (NODE_TYPE(x) == N_arrexpr)

#define AS_ARRAY(ste) ((struct st_entry_arr*)ste)
#define AS_FUNCTION(ste) ((struct st_entry_fn*)ste)
#define AS_VAR(ste) ((struct st_entry*)ste)