package TP2.asd;

import TP2.asd.Program.*;
import TP2.llvm.ProgramLLVM.*;

public interface Interface{
    //PROGRAM
    public interface ProgramI {
        public <H,S> S accept(ProgramVisitor<H,S> v, H h);
        public String prettyprinter();
        public ProgramLLVMImp toLLVM();
    }

    public interface ProgramVisitor<H,S> {
        public S visitProgram(ProgramImp prog, H h);
    }
    

    //FUNCTION
    public interface Function {
        public <H,S> S accept(FunctionVisitor<H,S> v, H h);
    }

    public interface FunctionVisitor<H,S> {
        public S visitFunction(FunctionImp fun, H h);
        public S visitPrototype(PrototypeImp proto, H h);
    }

    //DECLARATION

    public interface Declaration{
        public <H,S> S accept(DeclVisitor<H,S> v, H h);
    }

    public interface DeclVisitor<H,S>{
        public S visitDeclaration(DeclarationImp instr,H h);
        public S visitVarDecl(VarDeclImp instr, H h);
    }

    //INSTRUCTION

    public interface Instruction {
        public <H,S> S accept(InstrVisitor<H,S> v, H h);
    }


    public interface InstrVisitor<H,S>{
        public S visitReturn(Return_instrImp instr, H h);
        public S visitBloc(BlocImp instr, H h);
        public S visitBlocDec (BlocDecImp instr, H h);
        public S visitAssign(AssignImp instr, H h);
        public S visitPrint(PrintImp instr, H h);
        public S visitRead(ReadImp instr,H h);
        public S visitIfThen(IfThenImp instr, H h);
        public S visitIfThenElse(IfThenElseImp instr, H h);
        public S visitWhile(WhileImp instr, H h);
        public S visitVoidFunction(VoidFunctionImp instr, H h);
    }

    //EXPRESSION

    public interface Expression {
        public <H,S> S accept(ExprVisitor<H,S> v, H h);
    }


    public interface ExprVisitor<H,S> {
        public S visitConst(ConstImp e,H h);
        public S visitBinOp(BinopExpressionImp e, H h);
        public S visitVar(VarImp e,H h);
        public S visitCall(CallImp instr, H h);
    }

    public interface Type{
        public <H,S> S accept(TypeVisitor<H,S> v, H h);
    }

    public interface TypeVisitor<H,S>{
        public S visitInt(Type_intImp t, H h);
        public S visitVoid(Type_voidImp t, H h);
    }

    public enum Op {PLUS, MINUS, TIMES, DIV, MOD}
}