/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   targetstatic.h
 * Author: pgess
 *
 * Created on July 2, 2016, 1:25 PM
 */

#ifndef TARGETSTATIC_H
#define TARGETSTATIC_H

#include "ast.h"
#include "compilation/targets.h"
#include "transformations.h"
#include "pass/interpretationpass.h"

namespace xreate{ namespace compilation {

class TargetInterpretation;
class InterpretationScope;
class InterpretatonFunction;

    template <>
    struct TargetInfo<TargetInterpretation> {
        typedef Expression Result;
        typedef InterpretationScope Scope;
        typedef InterpretatonFunction Function;
    };
    
    template<> 
    struct TransformerInfo<TargetInterpretation> {
        static const int id = 1;
    };

class InterpretationScope: public  Scope<TargetInterpretation>{
    typedef Scope<TargetInterpretation> Parent;
    
public:
    InterpretationScope(CodeScope* scope, Function<TargetInterpretation>* f): Parent(scope, f) {}
    Expression process(const Expression& expression) override;
    
    llvm::Value* compile(const Expression& expression, const Context& context);
    
private:
    llvm::Value* compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context);
    //llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
    
    CodeScope* processOperatorIf(const Expression& expression);
    CodeScope* processOperatorSwitch(const Expression& expression);
};

class InterpretatonFunction: public Function<TargetInterpretation>{
public:
    InterpretatonFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target);
    Expression process(const std::vector<Expression>& args);
};

/*
 * Partially interpreted function signature
 */
struct PIFSignature{
    ManagedFnPtr declaration;
    std::vector<Expression> bindings;
};

class PIFunctionUnit;

class PIFunction: public InterpretatonFunction{
public:
    PIFunctionUnit* functionUnit;
    PIFSignature signatureInstance;
    
    PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target);
    llvm::Function* compile();
};

bool operator<(const PIFSignature& lhs, PIFunction* const rhs);
bool operator<(PIFunction* const lhs, const PIFSignature& rhs);

class TargetInterpretation: public Target<TargetInterpretation>, public Transformer{
public:    
    TargetInterpretation(AST* root, CompilePass* passCompilation): Target<TargetInterpretation>(root), pass(passCompilation){}

        //transformer:
public:
    virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
    virtual Expression transform(const Expression& expression, const Context& ctx) override;
    virtual bool isAcceptable(const Expression& expression) override;
    
        //target:
public:
   InterpretatonFunction* getFunction(FunctionUnit* unit);
   PIFunction* getFunction(PIFSignature&& sig);
   
private:
   std::set<PIFunction*, std::less<>> __pifunctions;
   std::map<FunctionUnit*, InterpretatonFunction*> __dictFunctionsByUnit;

        //self:
public:
    CompilePass* pass;
    llvm::Value* compile(const Expression& expression, const Context& ctx);
private:
    InterpretationScope* transformContext(const Context& c);
};



}}

#endif /* TARGETSTATIC_H */

