/*package TP2.Error;

import TP2.asd.SymTable;
import TP2.asd.Program.*;
import TP2.asd.Interface.*;

public class TypeChecking {

    public class TypeCheckProg implements ProgramVisitor<SymTable, TypeCheckExprDiag>{
        private TypeCheckFunction func_check;
        @Override
        public TypeCheckExprDiag visitProgram(ProgramImp prog, SymTable h) {
            SymTable st= new SymTable();
            for (Function f : prog.fonctions()) {
                TypeCheckExprDiag diag = f.accept(func_check, h);
                if (!diag.get_check()) return diag;
            }
            return TypeCheckExprDiag.checked(null);
        }
    }

    public class TypeCheckFunction implements FunctionVisitor<SymTable, TypeCheckExprDiag>{
        private TypeCheckInstr instr_check;
        @Override
        public TypeCheckExprDiag visitFunction(FunctionImp f, SymTable h) {
           return f.instruction().accept(instr_check,h);
        }
        @Override
        public TypeCheckExprDiag visitPrototype(PrototypeImp proto, SymTable h) {
            // TODO Auto-generated method stub
            throw new UnsupportedOperationException("Unimplemented method 'visitPrototype'");
        }
    }

    public class TypeCheckInstr implements InstrVisitor<SymTable, TypeCheckExprDiag> {
        private TypeCheckExpr expr_check; 
        @Override
        public TypeCheckExprDiag visitReturn(Return_instrImp instr, SymTable h) {
            return instr.e().accept(expr_check, h);
        }

        @Override
        public TypeCheckExprDiag visitBloc(BlocImp instr, SymTable h) {
            for(Instruction i: instr.instrs()){
                TypeCheckExprDiag diag= i.accept(this, h);
                if(!diag.get_check()) return diag;
            }
            return TypeCheckExprDiag.checked(null);
        }

        @Override
        public TypeCheckExprDiag visitBlocDec(BlocDecImp instr, SymTable h) {
            // TODO Auto-generated method stub
            throw new UnsupportedOperationException("Unimplemented method 'visitBlocDec'");
        }

        @Override
        public TypeCheckExprDiag visitAssign(AssignImp instr, SymTable h) {
            if(!h.isPresentVar(instr.t())){
                return TypeCheckExprDiag.error("Variable "+instr.t()+" n'existe pas");
            }
            Type t_type=h.getvar_Type(instr.t());
            TypeCheckExprDiag expr= instr.e().accept(expr_check, h);

            if (!expr.get_check()) return expr;
            //Verify type t = Type expr
            if(!t_type.getClass().equals(expr.get_type().getClass())){
                return TypeCheckExprDiag.error("Type d'expression est different que le type de variable");
            }
            return TypeCheckExprDiag.checked(t_type);
        }

        @Override
        public TypeCheckExprDiag visitPrint(PrintImp instr, SymTable h) {
           for(Object o :instr.t()){
            //We have string and expression
            if(o instanceof Expression e){
                TypeCheckExprDiag result = e.accept(expr_check, h);
                if (!result.get_check()) return result;
            }
           }
           return TypeCheckExprDiag.checked(null);
        }

        @Override
        public TypeCheckExprDiag visitRead(ReadImp instr, SymTable h) {
            for(VarImp v: instr.t()){
                if(!h.isPresentVar(v.name())){
                    return TypeCheckExprDiag.error("Variable "+v.name()+" n'existe pas");
                }
            }
            return TypeCheckExprDiag.checked(null);
        }

        @Override
        public TypeCheckExprDiag visitIfThen(IfThenImp instr, SymTable h) {
            TypeCheckExprDiag cond =instr.e().accept(expr_check, h);
            if(!cond.get_check()) return cond;
            if (!(cond.get_type() instanceof Type_intImp)){
                return TypeCheckExprDiag.error("Condition n'est pas un int");
            }
            return instr.i1().accept(this, h);
        }

        @Override
        public TypeCheckExprDiag visitIfThenElse(IfThenElseImp instr, SymTable h) {
            TypeCheckExprDiag cond =instr.e().accept(expr_check, h);
            if(!cond.get_check()) return cond;
            if (!(cond.get_type() instanceof Type_intImp)){
                return TypeCheckExprDiag.error("Condition n'est pas un int");
            }
            
            TypeCheckExprDiag then= instr.i1().accept(this, h);
            if (!then.get_check()) return then;
            return instr.i2().accept(this, h);
        }

        @Override
        public TypeCheckExprDiag visitWhile(WhileImp instr, SymTable h) {
            TypeCheckExprDiag cond =instr.e().accept(expr_check, h);
            if(!cond.get_check()) return cond;
            if (!(cond.get_type() instanceof Type_intImp)){
                return TypeCheckExprDiag.error("Condition n'est pas un int");
            }
            return instr.i1().accept(this, h);
        } 
    }

    public class TypeCheckExpr implements ExprVisitor<SymTable ,TypeCheckExprDiag>{
        @Override
        public TypeCheckExprDiag visitConst(ConstImp e, SymTable h) {
            return TypeCheckExprDiag.checked(new Type_intImp());
        }

        @Override
        public TypeCheckExprDiag visitVar(VarImp e, SymTable h) {
            if(!h.isPresentVar(e.name())){
                return TypeCheckExprDiag.error("Cette variable n'existe pas");
            }
            Type e_type= h.getvar_Type(e.name());
            return TypeCheckExprDiag.checked(e_type);
        }

        @Override
        public TypeCheckExprDiag visitBinOp(BinopExpressionImp e, SymTable h) {
            TypeCheckExprDiag tce1 = e.e1().accept(this, h);
            TypeCheckExprDiag tce2 = e.e2().accept(this, h);
            
            // Check if not ok then return its error
            if(!tce1.get_check()) return tce1;
            if(!tce2.get_check()) return tce2;

            // Check int + int
            if (!(tce1.get_type() instanceof Type_intImp) || !(tce2.get_type() instanceof Type_intImp) ){
                return TypeCheckExprDiag.error("Ses types sont different");
            }
            return TypeCheckExprDiag.checked(tce1.get_type());
        }

        @Override
        public TypeCheckExprDiag visitAppeal(AppealImp instr, SymTable h) {
            // TODO Auto-generated method stub
            throw new UnsupportedOperationException("Unimplemented method 'visitAppeal'");
        }
    }
}
*/