/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * File:   interpretationpass.h
 * Author: pgess <v.melnychenko@xreate.org>
 *
 * Created on July 5, 2016, 5:21 PM
 */

#ifndef INTERPRETATIONPASS_H
#define INTERPRETATIONPASS_H

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


#ifndef FRIENDS_INTERPRETATION_TESTS
#define FRIENDS_INTERPRETATION_TESTS
#endif

//TODO refactor interpretation. Get rid of InterpretationOperator, put only one operator - Hybrid/Late. 

namespace xreate{ namespace interpretation{
    enum InterpretationResolution{ANY, INTR_ONLY, CMPL_ONLY, FUNC_POSTPONED};
    enum InterpretationOperator{
        NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, QUERY_LATE,
        SWITCH_INTERPRET_CONDITION, SWITCH_VARIANT, SWITCH_LATE,
        CALL_INTERPRET_PARTIAL
    };
        
    struct InterpretationData{
        InterpretationResolution resolution;
        InterpretationOperator  op;
        
        bool isDefault() const;
    };
    
    struct FunctionInterpretationData{
        typedef std::vector<InterpretationResolution> Signature;
        Signature signature;
        bool flagPartialInterpretation;
    };

    class FunctionInterpretationHelper {
    public:
        static const FunctionInterpretationData
        getSignature(ManagedFnPtr function);
        
        static bool needPartialInterpretation(ManagedFnPtr function);
        
    private:    
        static FunctionInterpretationData recognizeSignature(ManagedFnPtr function);
    };

/** \brief Determines parts of program eligible for Interpretation. */    
    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);
    }
}   //end of namespace interpretation 

template<>
interpretation::InterpretationResolution   
defaultValue<interpretation::InterpretationResolution>();

template<>
struct AttachmentsDict<interpretation::FunctionInterpretationData>
{
    typedef interpretation::FunctionInterpretationData Data;
    static const unsigned int key = 5;
};

template<>
struct AttachmentsDict<interpretation::InterpretationData>
{
    typedef interpretation::InterpretationData Data;
    static const unsigned int key = 3;
};
    
} //end of namespace xreate


#endif /* INTERPRETATIONPASS_H */

