//#####################################################################
// Copyright 2022.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYREGHT.txt.
//#####################################################################
// Class EXECUTABLE_PROGRAM
//#####################################################################
#ifndef __EXECUTABLE_PROGRAM__
#define __EXECUTABLE_PROGRAM__

#include <Core/Data_Structures/HASHTABLE.h>
#include <Core/Symbolics/CODE_BLOCK.h>
#include <Core/Symbolics/INSTRUCTION.h>
#include <Core/Symbolics/PROGRAM.h>
#include <Core/Symbolics/PROGRAM_CONTEXT.h>
#include <Core/Symbolics/PROGRAM_PARSE_NODE.h>
#include <Core/Vectors/VECTOR.h>
#include <map>
#include <string>
namespace PhysBAM{

namespace NS_PROGRAM_SCALAR{template<class T> class PROGRAM_SCALAR;}
using NS_PROGRAM_SCALAR::PROGRAM_SCALAR;
template<class TV> class GRID;

template<class U>
class EXECUTABLE_PROGRAM
{
    typedef typename SCALAR_POLICY<U>::TYPE T;
    PROGRAM<T>& prog;
    PROGRAM_CONTEXT<T>& context;

    static PROGRAM_SCALAR<T> Get_Type(T*);
    template<int d> static VECTOR<PROGRAM_SCALAR<T>,d> Get_Type(VECTOR<T,d>*);
    template<int d> static MATRIX<PROGRAM_SCALAR<T>,d> Get_Type(MATRIX<T,d>*);

    typedef decltype(Get_Type((U*)nullptr)) T_PROGRAM_SCALAR;

public:
    EXECUTABLE_PROGRAM();
    EXECUTABLE_PROGRAM(const T_PROGRAM_SCALAR& ps);
    ~EXECUTABLE_PROGRAM();
    
    U Eval(const ARRAY<T,MEM_IN>& in);

    void Set(const T_PROGRAM_SCALAR& ps);
    void Print() const;
};
}
#endif
