/*
 * list processor module program copyright (C) 2009 - 2011 H.Niwa
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <errno.h>
#include <setjmp.h>
#include <sys/time.h>
#include <math.h>
#include <libgen.h>
#include <setjmp.h>

#include <string>
#include <complex>

#include "syserr.h"

#include "bin_node.h"
#include "gc.h"
#include "var.h"
#include "pred.h"
#include "context.h"
#include "unify.h"
#include "builtin.h"
#include "sysmodule.h"
#include "lisp.h"

extern void PushStack(Context* cx, Node* goals, Node* md, Node* env);
extern int PopStack(Context* cx, Node* &goals, Node* &md, Node* &env);

int Car(Context* cx, Node* goalscar, List* module);
int Cdr(Context* cx, Node* goalscar, List* module);
int Cons(Context* cx, Node* goalscar, List* module);
int Nth(Context* cx, Node* goalscar, List* module);
int SetNth(Context* cx, Node* goalscar, List* module);

int Caar(Context* cx, Node* goalscar, List* module);
int Cadr(Context* cx, Node* goalscar, List* module);
int Cdar(Context* cx, Node* goalscar, List* module);
int Cddr(Context* cx, Node* goalscar, List* module);

int Caaar(Context* cx, Node* goalscar, List* module);
int Caadr(Context* cx, Node* goalscar, List* module);
int Cadar(Context* cx, Node* goalscar, List* module);
int Caddr(Context* cx, Node* goalscar, List* module);
int Cdaar(Context* cx, Node* goalscar, List* module);
int Cdadr(Context* cx, Node* goalscar, List* module);
int Cddar(Context* cx, Node* goalscar, List* module);
int Cdddr(Context* cx, Node* goalscar, List* module);

int Caaaar(Context* cx, Node* goalscar, List* module);
int Caaadr(Context* cx, Node* goalscar, List* module);
int Caadar(Context* cx, Node* goalscar, List* module);
int Caaddr(Context* cx, Node* goalscar, List* module);
int Cadaar(Context* cx, Node* goalscar, List* module);
int Cadadr(Context* cx, Node* goalscar, List* module);
int Caddar(Context* cx, Node* goalscar, List* module);
int Cadddr(Context* cx, Node* goalscar, List* module);
int Cdaaar(Context* cx, Node* goalscar, List* module);
int Cdaadr(Context* cx, Node* goalscar, List* module);
int Cdadar(Context* cx, Node* goalscar, List* module);
int Cdaddr(Context* cx, Node* goalscar, List* module);
int Cddaar(Context* cx, Node* goalscar, List* module);
int Cddadr(Context* cx, Node* goalscar, List* module);
int Cdddar(Context* cx, Node* goalscar, List* module);
int Cddddr(Context* cx, Node* goalscar, List* module);



int Car(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <car VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("car: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <car VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("car: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 

	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;

}

int Cdr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 

	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;

}

int Cons(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage : <cons VAR LIST1 LIST2> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag1 = goalscar->Cdr()->Cdr()->Car()->Val();
	Node* ag2 = goalscar->Cdr()->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cons: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cons VAR LIST1 LIST2> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag1, goalscar, module)) <= 0) {
		syserr("cons: failed in the evaluation of the argument. \n");
		return 0;
	}

	if ((FuncArg(cx, ag2, goalscar, module)) <= 0) {
		syserr("cons: failed in the evaluation of the argument. \n");
		return 0;
	}

	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(Cons(ag1, ag2));
	PushStack(cx, Nil, Nil, env);
		
	return 1;

}

int Nth(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage : <nth VAR LIST NUM> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();
	Node* n = goalscar->Cdr()->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("nth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <nth VAR LIST NUM> \n");
		return 0;
	}

	if ((FuncArg(cx, n, goalscar, module)) <= 0) {
		syserr("nth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (n->kind() != ATOM) {
		syserr("usage : <nth VAR LIST NUM> \n");
		return 0;
	}
	long long nn;
	if (!((Atom*)n)->toInt(nn)) {
		syserr("usage : <nth VAR LIST NUM> \n");
		return 0;
	}

	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("nth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if ((ag->kind() != LIST) && (ag != Nil)) {
		syserr("usage : <nth VAR LIST NUM> \n");
		return 0;
	}
	
	if ((nn < 0) || (ListLength(ag) <= nn)) {
		syserr("nth: the range of the list is exceeded\n");
		return 0;
	}

	for (int i = 0; i < nn; i++) {
		ag = ag->Cdr();
	}
	ag = ag->Car();
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;

}

int SetNth(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage : <setnth VAR LIST NUM VAL> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();
	Node* n = goalscar->Cdr()->Cdr()->Cdr()->Car()->Val();
	Node* val = goalscar->Cdr()->Cdr()->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("setnth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <setnth VAR LIST NUM VAL> \n");
		return 0;
	}

	if ((FuncArg(cx, n, goalscar, module)) <= 0) {
		syserr("setnth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (n->kind() != ATOM) {
		syserr("usage : <setnth VAR LIST NUM VAL> \n");
		return 0;
	}
	long long nn;
	if (!((Atom*)n)->toInt(nn)) {
		syserr("usage : <setnth VAR LIST NUM VAL> \n");
		return 0;
	}

	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("setnth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if ((ag->kind() != LIST) && (ag != Nil)) {
		syserr("usage : <setnth VAR LIST NUM VAL> \n");
		return 0;
	}

	if ((FuncArg(cx, val, goalscar, module)) <= 0) {
		syserr("setnth: failed in the evaluation of the argument. \n");
		return 0;
	}

	if ((nn < 0) || (ListLength(ag) <= nn)) {
		syserr("setnth: the range of the list is exceeded\n");
		return 0;
	}

	Node* nlist = Nil;	
	for (int i = 0; i < nn; i++) {
		nlist = Cons(ag->Car(), nlist);
		ag = ag->Cdr();
	}

	Node* rval = Append(Cons(val, Nil), ag->Cdr());
	for (int i = 0; i < nn; i++) {
		rval = Cons(nlist->Car(),  rval);
		nlist = nlist->Cdr();
	}

	ag = ag->Car();
	

	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(rval);
	PushStack(cx, Nil, Nil, env);
		
	return 1;

}

int Caar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cdar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Caaar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caaar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caaar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Caadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cadar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cadar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cadar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cadar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cadar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Caddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cdaar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdaar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdaar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cdadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

int Cddar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cddar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cddar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cddar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cddar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cdddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Caaaar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caaaar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caaaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caaaar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caaaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Caaadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caaadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caaadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caaadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caaadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Caadar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caadar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caadar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caadar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caadar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Caaddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caaddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caaddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caaddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caaddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cadaar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cadaar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cadaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cadaar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cadaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cadadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cadadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cadadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cadadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cadadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Caddar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <caddar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("caddar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <caddar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("caddar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cadddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cadddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cadddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cadddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cadddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cdaaar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdaaar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdaaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdaaar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdaaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cdaadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdaadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdaadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdaadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdaadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cdadar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdadar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdada: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdadar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdada: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cdaddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdaddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cdaddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdaddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cdaddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cddaar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cddaar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cddaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cddaar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cddaar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cddadr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cddadr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cddadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cddadr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cddadr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cdddar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cdddar VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cddar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cdddar VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cddar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Car();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}


int Cddddr(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage : <cddddr VAR LIST> \n");
		return 0;
	}

	Node* v = goalscar->Cdr()->Car()->Val();
	Node* ag = goalscar->Cdr()->Cdr()->Car()->Val();

	if ((FuncArg(cx, v, goalscar, module)) <= 0) {
		syserr("cddddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (v->kind() != UNDEF) {
		syserr("usage : <cddddr VAR LIST> \n");
		return 0;
	}
	
	if ((FuncArg(cx, ag, goalscar, module)) <= 0) {
		syserr("cddddr: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	} 
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	if (ag->kind() == LIST) {
		ag = ag->Cdr();	
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, v);
	((Undef*)v)->Set(ag);
	PushStack(cx, Nil, Nil, env);
		
	return 1;
}

