#include "functions.hh"
#include <map>
#include <cassert>
using namespace std;

// FIXME: this stuff should be read from some configuration file.

namespace functions {

    class MinWrapper : public FunctionWrapper {
    public:
	virtual string neutral_element()
	{ return "INT_MAX"; }
	virtual string combine(string acc, string newval)
	{ return "std::min("+acc+", "+newval+")"; }
    };

    class MaxWrapper : public FunctionWrapper {
    public:
	virtual string neutral_element()
	{ return "INT_MIN"; }
	virtual string combine(string acc, string newval)
	{ return "std::max("+acc+", "+newval+")"; }
    };

    class SumWrapper : public FunctionWrapper {
    public:
	virtual string neutral_element()
	{ return "0"; }
	virtual string combine(string acc, string newval)
	{ return acc+"+"+newval; }
    };

    class ProdWrapper : public FunctionWrapper {
    public:
	virtual string neutral_element()
	{ return "1"; }
	virtual string combine(string acc, string newval)
	{ return acc+"*"+newval; }
    };


    struct FunEntry {
	string name;
	FunctionWrapper *wrapper;
    };

    static FunEntry fun_table[] = {
	{ "min", new MinWrapper() },
	{ "max", new MaxWrapper() },

	{ "sum", new SumWrapper() },
	{ "prod", new ProdWrapper() },

	{ "__none__", 0},
    };
};

using namespace functions;

typedef map<string, FunctionWrapper*> wrapper_table_t;

static wrapper_table_t*
build_wrapper_table()
{
    wrapper_table_t *table = new wrapper_table_t;
    for (int i = 0; fun_table[i].wrapper != 0; ++i)
	{
	    (*table)[fun_table[i].name] = fun_table[i].wrapper;
	}
    return table;
}

static  wrapper_table_t *table = build_wrapper_table();

bool
functions::defined(const char *name)
{
    assert(name != 0);
    string sname(name);
    FunctionWrapper *w = (*table)[sname];
    return w != 0;
}


functions::FunctionWrapper *
functions::get_function(const char *name)
{
    assert(name != 0);
    assert(defined(name));

    string sname(name);
    return (*table)[sname];
}


syntax highlighted by Code2HTML, v. 0.9.1