//genMethods "-g" "-t" "int*" "-h" "Collection" "-I" "LINK/basic/SetFuncs.h" "-I" "LINK/basic/Collection.h" "-d" "basic" 

#include <stk.h>
#include <LINK/stkWrapper/LINK_STk.h>

#include <LINK/basic/SetFuncs.h>

#include <LINK/basic/Collection.h>

#include <LINK/stkWrapper/Wrapper.h>
#include <LINK/stkWrapper/Register.h>
#include <LINK/stkWrapper/CollectionWrapper.h>


typedef int* _int_;
typedef Collection<int* > _Collection_int__;

#define _Collection_int__DATA(x) ((Collection<int* >*) (EXTDATA(x)))
#define _Collection_int__IS_DATA(x) (TYPEP(x, tc_CXXwrapper) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Collection<int* > >::type))
#define _Collection_int__ISNT_DATA(x) (!IS_DATA(x))

#define _Collection_int__CXX_DATA(x) (*(Collection<int* >*) (EXTDATA(VAL(x))))
#define _Collection_int__CXX_IS_DATA(x) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Collection<int* > >::type))
#define _Collection_int__CXX_ISNT_DATA(x) (!CXX_IS_DATA(x))

// the following specializations of CollectionWrapper methods
// allow   (mset-int 1 2 3) style in addition to the
// standard (mset-int (make-int 1) (make-int 2) (make-int 3))
#include <iostream.h>

static PRIMITIVE buildMSetInt(SCM l)
{
	SCM tmp, nl = NIL;
	SCM ne;
	SCM z;
        int len=0;      // to avoid having to call STK_length(& go thru l again)

	if (NCONSP(l)) 
		Err("mset-int: bad argument", l);
	if (NNULLP(l)) {
		for (tmp=l; tmp != NIL; tmp = CDR(tmp))  {
			ne = MakeIntCmd(CAR(tmp));
			NEWCELL(z, tc_cons);
			CAR(z) = ne;
			CDR(z) = nl;
			nl = z;
			len++;
		}
		nl = STk_reverse(nl);
		return	CollectionWrapper<int*>::buildMSet(nl);
	}
	return	CollectionWrapper<int*>::buildMSet(NIL);
}

static PRIMITIVE buildSetInt(SCM l, int len)
{
	SCM tmp, nl = NIL;
	SCM ne;
	SCM z;

	if (NNULLP(l)) {
		for (tmp=l; tmp != NIL; tmp = CDR(tmp))  {
			ne = MakeIntCmd(CAR(tmp));
			NEWCELL(z, tc_cons);
			CAR(z) = ne;
			CDR(z) = nl;
			nl = z;
		}
		nl = STk_reverse(nl);
		return	CollectionWrapper<int*>::buildSet(nl);
	}
	return	CollectionWrapper<int*>::buildSet(NIL);
}

static PRIMITIVE buildSequenceInt(SCM l, int len)
{
	SCM tmp, nl = NIL;
	SCM ne;
	SCM z;

	if (NNULLP(l)) {
		for (tmp=l; tmp != NIL; tmp = CDR(tmp))  {
			ne = MakeIntCmd(CAR(tmp));	// catches errors
			NEWCELL(z, tc_cons);
			CAR(z) = ne;
			CDR(z) = nl;
			nl = z;
		}
		nl = STk_reverse(nl);
		return	CollectionWrapper<int*>::buildSequence(nl);
	}
	return	CollectionWrapper<int*>::buildSequence(NIL);
}

PRIMITIVE intCollection2STkList(SCM l)
{
	SCM z;

	if (!CollectionWrapper<int*>::isCollection(l))
		Err("typed-collection-convert: wrong type of argument", l);
	Collection<int*> *cp = CollectionWrapper<int*>::getCollection(l);
	Iterator<int*> get_next(cp);
	int* e;
	if (get_next(e)) {
		SCM new_el = STk_makeinteger(*e);
		SCM tail, head;
		NEWCELL(tail, tc_cons);
		CAR(tail) = new_el;
		CDR(tail) = NIL;
		head = tail;
		SCM z;
		while (get_next(e)) {
			SCM new_el  = STk_makeinteger(*e);
			NEWCELL(z, tc_cons);
			CAR(z) = new_el;
			CDR(z) = NIL;
			CDR(tail) = z;
			tail = z;
		}
		return head;
	}
	return NIL;
}

PRIMITIVE memberLinkIntCollection(SCM e, SCM l)
{
	SCM ne = MakeIntCmd(e);
	return CollectionWrapper<int*>::memberLinkCollection(ne, l);
}

PRIMITIVE insertLinkIntCollection(SCM e, SCM l)
{
	SCM ne = MakeIntCmd(e);
	return CollectionWrapper<int*>::insertLinkCollection(ne, l);
}

PRIMITIVE appendLinkIntCollection(SCM e, SCM l)
{
	SCM ne = MakeIntCmd(e);
	return CollectionWrapper<int*>::appendLinkCollection(ne, l);
}

PRIMITIVE removeLinkIntCollection(SCM e, SCM l)
{
	SCM ne = MakeIntCmd(e);
	return CollectionWrapper<int*>::removeLinkCollection(ne, l);
}

PRIMITIVE occurrencesLinkIntCollection(SCM e, SCM l)
{
	SCM ne = MakeIntCmd(e);
	return CollectionWrapper<int*>::occurrencesLinkCollection(ne, l);
}

// define your new methods above 
// and register them using STk_add_new_cpp_primitive() below

void genExtra_Collection_int__Methods() 
{
        STk_add_new_cpp_primitive("mset-int2", tc_subr_1,
        (PRIMITIVE (*)(...))  buildMSetInt);
        STk_add_new_cpp_primitive("set-int2", tc_subr_1,
        (PRIMITIVE (*)(...))  buildSetInt);
        STk_add_new_cpp_primitive("sequence-int2", tc_subr_1,
        (PRIMITIVE (*)(...))  buildSequenceInt);
        STk_add_new_cpp_primitive("Collection-int-member2", tc_subr_2,
        (PRIMITIVE (*)(...))  memberLinkIntCollection);
        STk_add_new_cpp_primitive("Collection-int-insert2!", tc_subr_2,
        (PRIMITIVE (*)(...))  insertLinkIntCollection);
        STk_add_new_cpp_primitive("Collection-int-append2!", tc_subr_2,
        (PRIMITIVE (*)(...))  appendLinkIntCollection);
        STk_add_new_cpp_primitive("Collection-int-remove2!", tc_subr_2,
        (PRIMITIVE (*)(...))  removeLinkIntCollection);
        STk_add_new_cpp_primitive("Collection-int-occurrences2", tc_subr_2,
        (PRIMITIVE (*)(...))  occurrencesLinkIntCollection);
        STk_add_new_cpp_primitive("Collection-int->list2", tc_subr_1,
        (PRIMITIVE (*)(...))  intCollection2STkList);

        addIntListMethod("mset-int", "mset-int1",  "mset-int2", LINK_OVL);
        addIntListMethod("set-int", "set-int1",  "set-int2", LINK_OVL);
        addIntListMethod("sequence-int", "sequence-int1",  "sequence-int2", 
							LINK_OVL);
        addOneArgMethod("list->mset-int",
                "<pair>",
                "mset-int2", LINK_OVL);
        addOneArgMethod("list->set-int",
                "<pair>",
                "set-int2", LINK_OVL);
        addOneArgMethod("list->sequence-int",
                "<pair>",
                "sequence-int2", LINK_OVL);

        addOneArgMethod("mset-int->list",
                Wrapper<_Collection_int__ >::name,
                "Collection-int->list2", LINK_OVL);

        addOneArgMethod("set-int->list",
                Wrapper<_Collection_int__ >::name,
                "Collection-int->list2", LINK_OVL);

        addOneArgMethod("sequence-int->list",
                Wrapper<_Collection_int__ >::name,
                "Collection-int->list2", LINK_OVL);

        addTwoArgMethod("member",
                "<integer>",
                Wrapper<_Collection_int__ >::name,
                "Collection-int-member2", LINK_OVL);
        addTwoArgMethod("insert!",
                "<integer>",
                Wrapper<_Collection_int__ >::name,
                "Collection-int-insert2!", LINK_OVL);
        addTwoArgMethod("append!",
                "<integer>",
                Wrapper<_Collection_int__ >::name,
                "Collection-int-append2!", LINK_NEW);
        addTwoArgMethod("remove!",
                "<integer>",
                Wrapper<_Collection_int__ >::name,
                "Collection-int-remove2!", LINK_NEW);
        addTwoArgMethod("occurrences",
                "<integer>",
                Wrapper<_Collection_int__ >::name,
                "Collection-int-occurrences2", LINK_NEW);
}
