// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//

// 
// $Log: LazyPS.c,v $

#ifndef OpTable_h_
#define OpTable_h_

#include "ia.h"
#include "Array.h"

template <class A, class B, class C>
class IA_BinaryOperationsTable {
private:
    typedef A (*function)(B&,C&);

    // data members
#if 1
    // CFront 3.0.3 pukes on IA_Array<IA::Type>
    IA_Array<IA::Type>	known_types;
#else
    IA::Type	*known_types;
    int		num_known_types;
#endif
    function	*table;

    int num_types() const { return known_types.len()+1; }

    void resize_table(int newcount);

    int lookup_maybe_add(IA::Type);
    int lookup(IA::Type) const;

    function & access_table(int row, int column);
    function access_table(int row, int column) const;

    IA_BinaryOperationsTable & operator=(const IA_BinaryOperationsTable &) {
	abort();
	return *this;
    }

    IA_BinaryOperationsTable(const IA_BinaryOperationsTable &) {
	abort();
    }

public:
    IA_BinaryOperationsTable(function catchall) {
	table = new function[1];
	table[0] = catchall;
    }
    ~IA_BinaryOperationsTable() {
	delete[] table;
    }

    void add_operation(IA::Type a, IA::Type b, function f);
    function lookup_operation(IA::Type a, IA::Type b) const;
};

template <class T>
class IA_HomogenousBinaryOperationsTable
: public IA_BinaryOperationsTable<T*,T,T> {
    typedef T* (*function)(T&,T&);
public:
    IA_HomogenousBinaryOperationsTable(function catchall)
	:IA_BinaryOperationsTable<T*,T,T>(catchall) { }
};


template <class A, class B>
class IA_UnaryOperationsTable {
private:
    typedef A (*function)(B&);


    IA_Array<IA::Type>	known_types;
    function	*table;

    int num_types() const { return known_types.len()+1; }

    void resize_table(int newcount);

    int lookup_maybe_add(IA::Type);
    int lookup(IA::Type) const;

    function & access_table(int column);
    function access_table(int column) const;

    IA_UnaryOperationsTable & operator=(const IA_UnaryOperationsTable &) {
	abort();
	return *this;
    }

    IA_UnaryOperationsTable(const IA_UnaryOperationsTable &) {
	abort();
    }

public:
    IA_UnaryOperationsTable(function catchall) {
	table = new function[1];
	table[0] = catchall;
    }
    ~IA_UnaryOperationsTable() {
	delete[] table;
    }

    void add_operation(IA::Type a, function f);
    function lookup_operation(IA::Type a) const;
};

template <class T>
class IA_HomogenousUnaryOperationsTable
: public IA_UnaryOperationsTable<T*,T> {
    typedef T* (*function)(T&);
public:
    IA_HomogenousUnaryOperationsTable(function catchall)
	:IA_UnaryOperationsTable<T*,T>(catchall) { }
};

#endif // OpTable_h_
