/* 
 * File:   interpretationpass.h
 * Author: pgess
 *
 * Created on July 5, 2016, 5:21 PM
 */

#ifndef INTERPRETATIONPASS_H
#define INTERPRETATIONPASS_H

#include "abstractpass.h"
#include <map>

namespace xreate {
    
    enum InterpretationResolution{ANY, INTR_ONLY, CMPL_ONLY, FUNC_POSTPONED};
    enum InterpretationOperator{NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, SWITCH_INTERPRET_CONDITION, CALL_INTERPRET_PARTIAL};
    
    struct InterpretationData{
        InterpretationResolution resolution;
        InterpretationOperator  op;
        
        bool isDefault() const;
    };
    
    template<>
    InterpretationResolution 
    defaultValue<InterpretationResolution>();

    struct FunctionInterpretationData{
        typedef std::vector<InterpretationResolution> Signature;
        Signature signature;
        bool flagPartialInterpretation;
    };

    template<>
    struct AttachmentsDict<FunctionInterpretationData>
    {
        typedef FunctionInterpretationData Data;
        static const unsigned int key = 5;
    };
    
    class FunctionInterpretationHelper {
    public:
        static const FunctionInterpretationData
        getSignature(ManagedFnPtr function);
        
        static bool needPartialInterpretation(ManagedFnPtr function);
        
    private:    
        static FunctionInterpretationData recognizeSignature(ManagedFnPtr function);
    };
    
    template<>
    struct AttachmentsDict<InterpretationData>
    {
        typedef InterpretationData Data;
        static const unsigned int key = 3;
    };
    
    class InterpretationPass: public AbstractPass<InterpretationResolution> {
        typedef AbstractPass<InterpretationResolution> Parent;
    
    public:
        InterpretationResolution process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
        InterpretationResolution process(ManagedFnPtr function);
        InterpretationResolution processFnCall(ManagedFnPtr function, PassContext context);
        
        InterpretationPass(PassManager* manager);
        void run();
    };
    
    namespace details {
        InterpretationResolution recognizeTags(const std::map<std::string, Expression>& tags);
    }
}


#endif /* INTERPRETATIONPASS_H */

