// joycub V2 - an interpeter for the programming language Joy
// (c) 2004-2006 Sergey Zubkov 
// prototype.cc - prototype module to test out the new design considerations
static char RCSID[] ="$Id: main.cc,v 1.9 2006/02/27 18:44:01 cubbi Exp $";

// used by print_banner() and JC_object::debug_print()
#include <iostream>
// used by main()
#include <vector>

#include "globals.h"
#include "object.h"
#include "bool.h"
#include "int.h"
#include "op.h"
#include "float.h"
#include "char.h"
#include "string.h"
#include "pool.h"
#include "program.h"
#include "reference.h"
#include "exceptions.h"
#include "token_list.h"
#include "symtab.h"

using namespace std;

// The global tables
std::vector<Pool> POOL(LAST_TYPE);
JC_symtab* SYMTAB;
int ARGC;
char** ARGV;

const char * LIBRARY_PREFIX="lib/";
int ECHO_SETTING=0;
int LINENUM=0;

// Print a banner at the start of the interpreter
void print_banner(void) {
	cout << "joycub V2 - an interpeter for the programming language Joy" << endl;
	cout << "(c) 2004-2006 Sergey Zubkov " << endl;
	cout << "$Date: 2006/02/27 18:44:01 $" << endl;
}

/*
// print out the pools
void pool_dump(void) {
	cout << "pool dump: " << endl;
	cout << "POOL[BOOL]: [ ";
    for( Pool::const_iterator it = POOL[BOOL].begin();
		 it != POOL[BOOL].end(); it++ ) {
//		(*it).second->debug_print();
		cout << " ";
	}
	cout << " ]" << endl;
	cout << "POOL[INT]: [ ";
    for( Pool::const_iterator it = POOL[INT].begin();
		 it != POOL[INT].end(); it++ ) {
//		(*it).second->debug_print();
		cout << " ";
	}
	cout << " ]" << endl;
	cout << "POOL[FLOAT]: [ ";
    for( Pool::const_iterator it = POOL[FLOAT].begin();
		 it != POOL[FLOAT].end(); it++ ) {
//		(*it).second->debug_print();
		cout << " ";
	}
	cout << " ]" << endl;
	cout << "POOL[OP]: [ ";
    for( Pool::const_iterator it = POOL[OPERATOR].begin();
		 it != POOL[OPERATOR].end(); it++ ) {
//		(*it).second->debug_print();
		cout << " ";
	}
	cout << " ]" << endl;
}
*/

/*
void refcount_dump(void) {
	cout << " Total bool objects " << bool_type_count << endl;
	cout << " Total int objects " << int_type_count << endl;
	cout << " Total float objects " << float_type_count << endl;
	cout << " Total char objects " << char_type_count << endl;
	cout << " Total string objects " << string_type_count << endl;
	cout << " Total ref objects " << ref_type_count << endl;
}
*/

int main(int argc, char** argv) {
    print_banner();

	SYMTAB = new JC_symtab(); // symbol table
	ARGC=argc;
	ARGV=argv;
	JC_Program * iprog = new JC_Program();
	Token_list iline=Token_list("\"sz_inilib.joy\" include \"inilib.joy\" include .");
//	Token_list iline;
	while(true) {
		try {
			while(!iline.has_dot()) { // incomplete input: continue reading
			// Read and tokenize input string
				Token_list iline_temp = Token_list(cin, iline.get_last_state());
				iline.concat(iline_temp);
//cerr << "Tokenized: ";
//iline.debug_print();
			}
		} catch (const char* e) {
			if (e == string("EOF")) break;
		} catch (runtime_error e) {
			cout << "SYNTAX ERR:" << e.what() << endl;
			break;
		}
//cout << " (last state = " << iline.get_last_state() << endl;
//		if(!iline.has_dot() ) continue; // incomplete input: continue read

		// Turn the token list into a list of joycub objects
	   	try {
			iprog = new JC_Program(iline);
		} catch (runtime_error e) {
			cout << "COMPILE ERR:" << e.what() << endl;
			iprog->erase();
			iline.erase();
			continue;
		}
		iline.erase();

		// Execute!
		JC_Stack STACK; // data stack
//		cout << "Execution begins, stack=" << STACK.to_string() << endl;
	   	try {
			iprog->execute(STACK);
		} catch (runtime_error e) {
			cout << "RUNTIME ERR:" << e.what() << endl;
			iprog->erase(); STACK.erase(); continue;
		}
//		cout << "Execution complete. stack=" << STACK.to_string() << endl;
		iprog->erase();
	}

	// destroy the pools
	POOL[BOOL].erase( POOL[BOOL].begin(), POOL[BOOL].end() );
	POOL[INT].erase( POOL[INT].begin(), POOL[INT].end() );

//	refcount_dump();
}

