open Ast
open Printf
open Exception

let out = stdout;;

let rec string_indent layer =
if layer > 0 then 
    "" ^ string_indent (layer-1)
else
    "";;

let rec string_type = function
| Wild_Card(i) -> "Wild_Card"
| Int -> "int"
| Bits(i) -> "bits#" ^ (string_of_int i)
| String -> "string"
| Vector(t, int_list)
    -> List.fold_left (fun s i -> s ^ "[" ^ (string_of_int i)
        ^ "]") (string_type t) int_list
| Fun(x, y, z) -> "fun"
| Special(s) -> "fun-"^s
;;

let string_idt idt =
sprintf "%s(%s)" idt.id (string_type idt.t);;

let rec string_vector_help = function
| [] -> ""
| hd::tl -> ", " ^ string_expr 0 hd ^ string_vector_help tl

and string_vector vec =
    "{" ^ string_expr 0 (List.hd vec) ^ string_vector_help (List.tl vec) ^ "}"

and string_expr layer exp =
    string_indent layer ^
    match exp with
    | Int_Lit(s) -> s
    | Bin_Lit(s) -> s
    | Hex_Lit(s) -> s
    | Bit_Binary_Lit(s) -> "'" ^ s
    | Bit_Hex_Lit(s) -> "'x" ^ s
    | String_Lit(s) -> "\"" ^ s ^ "\""
    | Vector_Lit(v) -> string_vector v
    | Id(s) -> s
    | Idd(s, v) -> s ^ string_vector v
    | Vec_Dimension(i) -> sprintf "[@]%d" i
    | Lambda(idt_list, exp) -> "[Lambda]"
    | Let(let_arg_list, exp) -> "[Let]"
    (*
    fprintf out "[Let]";
    List.fold_left (fun () () -> ()) ()
    (List.map (fun (idt, exp) ->
    fprintf out "%s = " (string_idt idt); print_expr 0 exp) let_arg_list);
    fprintf out "\n";
    print_expr (layer+1) exp
    *)
    | Make_Vector(c_type, exp) -> "[Make_Vector]"
    | Funcall(exp, exps) ->
        (List.fold_left
            (fun s1 s2 -> s1 ^ s2)
            ("(" ^ string_expr 0 exp)
            (List.map (fun e -> sprintf " " ^ string_expr (1+layer) e) exps))
        ^ ")"
;;

let string_clip c =
match c with
| Expr(exp, _) -> string_expr 0 exp ^ "\n"
| Defvar(defv) -> "Defvar\n"
| Defun(def) -> "Defun\n";;

let rec string_clips p =
match p with
| [] -> ""
| x::y -> string_clip x ^ string_clips y;;

let print_ast p =
    fprintf out "============= program start =============\n";
    fprintf out "%s" (string_clips p);
    fprintf out "============== program end ==============\n";;
