
/*
	Virtual class to dynamically load and exec
	step-by-step a (basic) reactive program
*/


enum RPExeStatus {
   RPS_writen,      //calculée et stockée
   RPS_unwriten,    //pas calculée
   RPS_nil,         //indéterminée
   RPS_div0,        //division par zéro
	RPS_false_assert //assertion violée
};

class RPExe {
	void Error(const char* msg){
		fprintf(stderr, "%s", msg);
		exit(1);
	}
public:
	virtual ~RPExe(){}
	RPExe();
	
	//name, profile and direct access to in/out vars
	virtual const char* name();
	virtual int nb_inputs();
	virtual const char* input_ident(int i);
	virtual const char* input_type(int i);
	virtual int nb_outputs();
	virtual const char* output_ident(int i);
	virtual const char* output_type(int i);
	virtual void* input_loc(int);    //direct access to mem loc
	virtual void* output_loc(int);   //direct access to mem loc

	//basic exec interface, usage:
	//set inputs (via input_loc); step(); get outputs (via output_loc)
	//(output_status cam be checked if needed)
	virtual int step();
	virtual RPExeStatus output_status(int);
	virtual void reset_history();

	//extended exec interface, typically for ecexe
	virtual int nb_assertions();
	virtual RPExeStatus assert_status(int);
	virtual int nb_locals();
	virtual const char* local_ident(int i);
	virtual const char* local_type(int i);
	virtual void* local_loc(int);
	virtual RPExeStatus local_status(int);
	virtual bool allows_eval_outputs();
	virtual int eval_outputs();
	virtual void init_step();
	virtual void end_step();
};
/*
Struct necessary for building a DRO archive
(Dynamically linkable Reactive Object)
Such an archive can be loaded by simec/luciole.

Notes:
* version 1 only support basic reactive execution (step/reset)
* The version used to BUILD the .dro must be compatible with
  the one used to LOAD the .dro (actally, equal !)
* a .dro is simply a dynamic library (.so) that MUST contain
  a single global var of type 'dro_desc_t', properly intialized, 
  WITH THE NAME 'dro_desc'
*/
#define DROVERSION "1.1"
#define xstr(s) str(s)  /* converts macro to string */
#define str(s) #s
/* should be of type type dro_desc_t */
#define DRO_DESC_NAME  dro_desc
struct dro_var_t {
	const char* ident;
	const char* type;
	void* valptr;
};

struct dro_desc_t {
	const char* version;
	const char* name;
	int nbins;
	struct dro_var_t* intab;
	int nbouts;
	struct dro_var_t* outab;
	int ( *step )();
	void ( *reset )();
	void ( *init )();
}; 


class DROLoad : public RPExe {
	void* _handle;
	char* _dlerr;
	struct dro_desc_t* _desc;

public:
	
	DROLoad();
	const char* load(const char* fn);
	
	//implements only the basic RPExe interface
	virtual const char* name();
	virtual int nb_inputs();
	virtual const char* input_ident(int i);
	virtual const char* input_type(int i);
	virtual int nb_outputs();
	virtual const char* output_ident(int i);
	virtual const char* output_type(int i);
	virtual void* input_loc(int);
	virtual void* output_loc(int);
	virtual int step();
	virtual RPExeStatus output_status(int);
	virtual void reset_history();
};
