open Ast
open Sast
open Translate
open Printast
open Printsast
open Semantic
open Exception
open Printf

let err_pre = "~~Error~~";;
let bug_out = open_out "debug.cc";;

let _ =
    try
    let input =
        if Array.length Sys.argv > 1 then
            open_in Sys.argv.(1)
        else stdin in
    
    let lexbuf = Lexing.from_channel input in
    let ast = Parser.program Scanner.token lexbuf in
    (* Printast.print_ast ast; *)
    let sast = Semantic.check_ast ast in
    (* Printsast.print_sast sast *)
    let result = Translate.translate_to_c sast in
    fprintf stdout "%s" result
    with
    | Illegal_Char(c) ->
        fprintf stderr "%s Illegal character %c.\n" err_pre c
    | Illegal_Id(s) ->
        fprintf stderr "%s Identifier cannot contain %s.\n" err_pre s

    | Parsing.Parse_error ->
        fprintf stderr "%s Parse error.\n" err_pre
    | Invalid_Vector(s) ->
        fprintf stderr "%s Invalid vector %s.\n" err_pre s
    | Indefined_Id(s) ->
        fprintf stderr "%s %s is not defined.\n" err_pre s
    | Vector_Dim(s, i) ->
        fprintf stderr "%s %s has only %d dimension.\n" err_pre s i
    | Invalid_Ind(s) ->
        fprintf stderr "%s Invalid index in %s\n" err_pre s
    | Not_Vector(s) ->
        fprintf stderr "%s %s is not a vector.\n" err_pre s
    | Make_Vec_Bound(i) ->
        fprintf stderr "%s @%d is out of bound.\n" err_pre i
    | Wrong_Argu_Len(s) ->
        fprintf stderr "%s Wrong number of arguments in function call %s.\n"
        err_pre s
    | Wrong_Argu_Type(s) ->
        fprintf stderr "%s Wrong argument types in function call %s.\n" err_pre s
    | Bind_Wrong_Type(s) ->
        fprintf stderr "%s Cannot bind %s (wrong type).\n" err_pre s
    | Eval_Fail(s) ->
        fprintf stderr "%s Cannot evaluate %s.\n" err_pre s
    | Not_Function(s) ->
        fprintf stderr "%s %s is not a function.\n" err_pre s
    | Bind_Twice(s) ->
        fprintf stderr "%s Cannot define %s twice.\n" err_pre s
    | Defun_Wrong_Type(s) ->
        fprintf stderr "%s Return types in definition of %s are inconsistent.\n"
        err_pre s

    | Failure(s) ->
        fprintf stderr "Not yet implemented - %s\n" s
    | Dev_Error(s) ->
        fprintf stderr "Dev error ... %s\n" s
    (*| _ -> fprintf stderr "unexpected error ...\n"*)
;;