/* Dialect - Code Output Formatter
 * 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 "CSharpDialect.h"

void Dialect::CSharpDialect::Perform(const Metallurgy::Element *element, std::wstring &builder, Metallurgy::ModDeque &mods) {
	switch (element->getIntrinsic()) {
		case Chordata::Element::Void:		builder.insert(0, L"void");				break;
		case Chordata::Element::Boolean:	builder.insert(0, L"bool");				break;
		case Chordata::Element::Char:		builder.insert(0, L"char");				break;
		case Chordata::Element::I1:			builder.insert(0, L"sbyte");			break;
		case Chordata::Element::U1:			builder.insert(0, L"byte");				break;
		case Chordata::Element::I2:			builder.insert(0, L"short");			break;
		case Chordata::Element::U2:			builder.insert(0, L"ushort");			break;
		case Chordata::Element::I4:			builder.insert(0, L"int");				break;
		case Chordata::Element::U4:			builder.insert(0, L"uint");				break;
		case Chordata::Element::I8:			builder.insert(0, L"long");				break;
		case Chordata::Element::U8:			builder.insert(0, L"ulong");			break;
		case Chordata::Element::R4:			builder.insert(0, L"float");			break;
		case Chordata::Element::R8:			builder.insert(0, L"double");			break;
		case Chordata::Element::String:		builder.insert(0, L"string");			break;
		case Chordata::Element::Object:		builder.insert(0, L"object");			break;

		case Chordata::Element::I:			builder.insert(0, L"IntPtr");			break;
		case Chordata::Element::U:			builder.insert(0, L"UIntPtr");			break;
		case Chordata::Element::TypedByRef:	builder.insert(0, L"TypedReference");	break;

		case Chordata::Element::ByRef:
			element->getExtra()->Render(builder);
			builder.insert(0, L"ref ");
		break;

		case Chordata::Element::Ptr:
			element->getExtra()->Render(builder);
			builder.append(L" *");
		break;

		case Chordata::Element::Class:
		case Chordata::Element::ValueType:
		{
			const Metallurgy::Type *defref = dynamic_cast<const Metallurgy::Type *>(element->getType());

			if (defref == NULL)
				element->getType()->getElement()->Render(builder);
			else {
				std::wstring name = defref->getName().getShort();
				if (name == L"System.String")
					builder.insert(0, L"string");
				else
					builder.insert(0, name.c_str());
			}
		} break;

		case Chordata::Element::SZArray:
			builder.insert(0, L"[]");
			element->getExtra()->Render(builder);
		break;

		case Chordata::Element::Array: {
			wchar_t buff[16];
			element->getExtra()->Render(builder);

			const Metallurgy::Element::DimensionVector *array = element->getArray();
			builder.append(L"[");
			for (uint32_t i(0); i < array->size(); i++) {
				if (i != 0) builder.append(L",");
				uint32_t size = (*array)[i].size;
				if (size != 0)
					builder.append(_itow(size, buff, 10));
			}
			builder.append(L"]");
		} break;

		default:
			std::wostringstream serr;
			serr << L"unable to render element: [" << std::setbase(16) << element->getIntrinsic() << std::setbase(10) << L"]";
			throw SimpleException(serr.str());
		break;
	}
}
