/* Theoretic - Graph Theoretic Byte Code RuntimeEngineering
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "stdafx.h"

#include "RuntimeEngine.h"
#include "theoretic/Instruction.h"

#define FUCKING_A { wout << L"Fucking-A!" << std::endl; }

namespace Theoretic {

RuntimeEngine::RuntimeEngine(const std::wstring &set) :
	set(set),
	liaison(support)
{
	XPathEvaluator::initialize();
	support.setParserLiaison(&liaison);

	engine = liaison.parseXMLStream(LocalFileInputSource((L"engines/" + set + L".xml").c_str()));
	opcodes = xpath.selectSingleNode(support, engine->getDocumentElement(), L"opcodes", NULL);

	/*NodeRefList datatypes = xpath.selectNodeList(support, engine->getDocumentElement(), L"datatypes/type", NULL);
	for (NodeRefList::size_type i(0); i < datatypes.getLength(); ++i) {
		XalanNode *type = datatypes.item(i);
		const XalanNamedNodeMap *attrs = type->getAttributes();

		std::wstring name = attrs->getNamedItem(XalanDOMString(L"name"))->getNodeValue().c_str();
		std::wstring stored = attrs->getNamedItem(XalanDOMString(L"stored"))->getNodeValue().c_str();

		typeNames.insert(TypeName(name, i));
		types.push_back(Type(name, coreTypes.lookup(stored)));
	}*/
}

RuntimeEngine::~RuntimeEngine() {
	XPathEvaluator::terminate();
}

void RuntimeEngine::Parse(uint8_t *data, uint32_t length, std::wostream &wout) {
	XalanSourceTreeInit theSourceTreeInit;

	typedef std::vector<Operation *> Stream;

	Instruction::OffsetMap offsets;
	Stream stream;

	wchar_t hex[3];

	XalanNode *strata = opcodes;
	//wout << L"Parsing..." << std::endl << std::endl;

	for (uint8_t *begin = data, *end = data + length; data < end; ) {
		if (strata == NULL) {
			FUCKING_A
			return;
		}

		int start(data - begin);
		uint8_t code = *data++;

		_itow(code, hex, 16);
		//wout << start << L"(" << hex << L"): ";
		std::wstring check = L"[@code = '" + std::wstring(hex) + L"']";

		XalanNode *op = xpath.selectSingleNode(support, strata, (L"op" + check).c_str(), NULL);

		if (op == NULL) {
			strata = xpath.selectSingleNode(support, strata, (L"strata" + check).c_str(), NULL);
		} else {
			strata = opcodes;

			Instruction *code = new Instruction(op, start, data, *this);
			offsets.insert(Instruction::OffsetPair(start, code));
			stream.push_back(code);
		}
	}

	/* XXX! for (Instruction::OffsetMap::iterator i_offset = offsets.begin(); i_offset != offsets.end(); ++i_offset)
		i_offset->second->Resolve(offsets); */
}

}