<commit_before>#include "instanciate.h"

using namespace Yuni;

namespace Nany
{
namespace Pass
{
namespace Instanciate
{

	void SequenceBuilder::pragmaBodyStart()
	{
		assert(frame != nullptr);
		assert(not signatureOnly);
		assert(codeGenerationLock == 0 and "any good reason to not generate code ?");

		auto& atom = frame->atom;
		if (not atom.isFunction())
			return;

		bool generateCode = canGenerateCode();
		uint32_t count = atom.parameters.size();
		atom.parameters.each([&](uint32_t i, const AnyString& name, const Vardef& vardef)
		{
			// lvid for the given parameter
			uint32_t lvid  = i + 1 + 1; // 1: return type, 2: first parameter
			assert(lvid < frame->lvids.size());
			// Obviously, the parameters are not synthetic objects
			// but real variables
			frame->lvids[lvid].synthetic = false;

			//
			// Parameters Deep copy (if required)
			//
			if (name[0] != '^')
			{
				// normal input parameter (not captured - does not start with '^')
				// clone it if necessary (only non-ref parameters)

				if (not cdeftable.classdef(vardef.clid).qualifiers.ref)
				{
					if (debugmode and generateCode)
						out->emitComment(String{"----- deep copy parameter "} << i << " aka " << name);

					// a register has already been reserved for cloning parameters
					uint32_t clone = 2 + count + i; // 1: return type, 2: first parameter
					assert(clone < frame->lvids.size());
					// the new value is not synthetic
					frame->lvids[clone].synthetic = false;

					bool r = instanciateAssignment(*frame, clone, lvid, false, false, true);
					if (unlikely(not r))
						frame->invalidate(clone);

					if (canBeAcquired(lvid))
					{
						frame->lvids[lvid].autorelease = true;
						frame->lvids[clone].autorelease = false;
					}

					if (generateCode)
					{
						out->emitStore(lvid, clone); // register swap
						if (debugmode)
							out->emitComment("--\n");
					}
				}
			}
		});

		// generating some code on the fly
		if (atom.isSpecial() /*ctor, operators...*/ and generateCode)
		{
			// variables initialization (for a ctor)
			if (generateClassVarsAutoInit)
			{
				generateClassVarsAutoInit = false;
				generateMemberVarDefaultInitialization();
			}

			// variables destruction (for dtor)
			if (generateClassVarsAutoRelease)
			{
				generateClassVarsAutoRelease = false;
				generateMemberVarDefaultDispose();
			}

			// variables cloning (copy a ctor)
			if (generateClassVarsAutoClone)
			{
				generateClassVarsAutoClone = false;
				generateMemberVarDefaultClone();
			}
		}
	}

	void SequenceBuilder::visit(const IR::ISA::Operand<IR::ISA::Op::pragma>& operands)
	{
		assert(static_cast<uint32_t>(operands.pragma) < IR::ISA::PragmaCount);

		auto pragma = static_cast<IR::ISA::Pragma>(operands.pragma);
		switch (pragma)
		{
			case IR::ISA::Pragma::codegen:
			{
				if (operands.value.codegen != 0)
				{
					if (codeGenerationLock > 0) // re-enable code generation
						--codeGenerationLock;
				}
				else
					++codeGenerationLock;
				break;
			}

			case IR::ISA::Pragma::bodystart:
			{
				// In 'signature only' mode, we only care about the
				// parameter user types. Everything from this point in unrelevant
				if (signatureOnly)
					return currentSequence.invalidateCursor(*cursor);

				// parameters Deep copy, implicit var auto-init...
				pragmaBodyStart();
				break;
			}

			case IR::ISA::Pragma::blueprintsize:
			{
				if (0 == layerDepthLimit)
				{
					// ignore the current blueprint
					//*cursor += operands.value.blueprintsize;
					assert(frame != nullptr);
					assert(frame->offsetOpcodeBlueprint != (uint32_t) -1);
					auto startOffset = frame->offsetOpcodeBlueprint;
					uint32_t count = operands.value.blueprintsize;

					if (unlikely(count < 3))
					{
						ice() << "invalid blueprint size when instanciating atom";
						break;
					}

					// goto the end of the blueprint
					// -2: the final 'end' opcode must be interpreted
					*cursor = &currentSequence.at(startOffset + count - 1 - 1);
				}
				break;
			}

			case IR::ISA::Pragma::visibility:
			{
				assert(frame != nullptr);
				break;
			}

			case IR::ISA::Pragma::shortcircuitOpNopOffset:
			{
				shortcircuit.label = operands.value.shortcircuitMetadata.label;
				break;
			}

			case IR::ISA::Pragma::shortcircuitMutateToBool:
			{
				uint32_t lvid = operands.value.shortcircuitMutate.lvid;
				uint32_t source = operands.value.shortcircuitMutate.source;

				frame->lvids[lvid].synthetic = false;

				if (true)
				{
					auto& instr = *(*cursor - 1);
					assert(instr.opcodes[0] == static_cast<uint32_t>(IR::ISA::Op::stackalloc));
					uint32_t sizeoflvid = instr.to<IR::ISA::Op::stackalloc>().lvid;

					// sizeof
					auto& atombool = *(cdeftable.atoms().core.object[nyt_bool]);
					out->emitSizeof(sizeoflvid, atombool.atomid);

					auto& opc = cdeftable.substitute(lvid);
					opc.mutateToAtom(&atombool);
					opc.qualifiers.ref = true;

					// ALLOC: memory allocation of the new temporary object
					out->emitMemalloc(lvid, sizeoflvid);
					out->emitRef(lvid);
					frame->lvids[lvid].autorelease = true;
					// reset the internal value of the object
					out->emitFieldset(source, /*self*/lvid, 0); // builtin
				}
				else
					out->emitStore(lvid, source);
				break;
			}

			case IR::ISA::Pragma::synthetic:
			{
				uint32_t lvid = operands.value.synthetic.lvid;
				bool onoff = (operands.value.synthetic.onoff != 0);
				frame->lvids[lvid].synthetic = onoff;
				break;
			}

			case IR::ISA::Pragma::suggest:
			case IR::ISA::Pragma::builtinalias:
			case IR::ISA::Pragma::shortcircuit:
			case IR::ISA::Pragma::unknown:
				break;
		}
	}

} // namespace Instanciate
} // namespace Pass
} // namespace Nany
<commit_msg>instanciate: added assert for the output IR sequence<commit_after>#include "instanciate.h"

using namespace Yuni;

namespace Nany
{
namespace Pass
{
namespace Instanciate
{

	void SequenceBuilder::pragmaBodyStart()
	{
		assert(frame != nullptr);
		assert(not signatureOnly);
		assert(codeGenerationLock == 0 and "any good reason to not generate code ?");
		assert(out != nullptr and "no output IR sequence");

		auto& atom = frame->atom;
		if (not atom.isFunction())
			return;

		bool generateCode = canGenerateCode();
		uint32_t count = atom.parameters.size();
		atom.parameters.each([&](uint32_t i, const AnyString& name, const Vardef& vardef)
		{
			// lvid for the given parameter
			uint32_t lvid  = i + 1 + 1; // 1: return type, 2: first parameter
			assert(lvid < frame->lvids.size());
			// Obviously, the parameters are not synthetic objects
			// but real variables
			frame->lvids[lvid].synthetic = false;

			//
			// Parameters Deep copy (if required)
			//
			if (name[0] != '^')
			{
				// normal input parameter (not captured - does not start with '^')
				// clone it if necessary (only non-ref parameters)

				if (not cdeftable.classdef(vardef.clid).qualifiers.ref)
				{
					if (debugmode and generateCode)
						out->emitComment(String{"----- deep copy parameter "} << i << " aka " << name);

					// a register has already been reserved for cloning parameters
					uint32_t clone = 2 + count + i; // 1: return type, 2: first parameter
					assert(clone < frame->lvids.size());
					// the new value is not synthetic
					frame->lvids[clone].synthetic = false;

					bool r = instanciateAssignment(*frame, clone, lvid, false, false, true);
					if (unlikely(not r))
						frame->invalidate(clone);

					if (canBeAcquired(lvid))
					{
						frame->lvids[lvid].autorelease = true;
						frame->lvids[clone].autorelease = false;
					}

					if (generateCode)
					{
						out->emitStore(lvid, clone); // register swap
						if (debugmode)
							out->emitComment("--\n");
					}
				}
			}
		});

		// generating some code on the fly
		if (atom.isSpecial() /*ctor, operators...*/ and generateCode)
		{
			// variables initialization (for a ctor)
			if (generateClassVarsAutoInit)
			{
				generateClassVarsAutoInit = false;
				generateMemberVarDefaultInitialization();
			}

			// variables destruction (for dtor)
			if (generateClassVarsAutoRelease)
			{
				generateClassVarsAutoRelease = false;
				generateMemberVarDefaultDispose();
			}

			// variables cloning (copy a ctor)
			if (generateClassVarsAutoClone)
			{
				generateClassVarsAutoClone = false;
				generateMemberVarDefaultClone();
			}
		}
	}

	void SequenceBuilder::visit(const IR::ISA::Operand<IR::ISA::Op::pragma>& operands)
	{
		assert(static_cast<uint32_t>(operands.pragma) < IR::ISA::PragmaCount);

		auto pragma = static_cast<IR::ISA::Pragma>(operands.pragma);
		switch (pragma)
		{
			case IR::ISA::Pragma::codegen:
			{
				if (operands.value.codegen != 0)
				{
					if (codeGenerationLock > 0) // re-enable code generation
						--codeGenerationLock;
				}
				else
					++codeGenerationLock;
				break;
			}

			case IR::ISA::Pragma::bodystart:
			{
				// In 'signature only' mode, we only care about the
				// parameter user types. Everything from this point in unrelevant
				if (signatureOnly)
					return currentSequence.invalidateCursor(*cursor);

				// parameters Deep copy, implicit var auto-init...
				pragmaBodyStart();
				break;
			}

			case IR::ISA::Pragma::blueprintsize:
			{
				if (0 == layerDepthLimit)
				{
					// ignore the current blueprint
					//*cursor += operands.value.blueprintsize;
					assert(frame != nullptr);
					assert(frame->offsetOpcodeBlueprint != (uint32_t) -1);
					auto startOffset = frame->offsetOpcodeBlueprint;
					uint32_t count = operands.value.blueprintsize;

					if (unlikely(count < 3))
					{
						ice() << "invalid blueprint size when instanciating atom";
						break;
					}

					// goto the end of the blueprint
					// -2: the final 'end' opcode must be interpreted
					*cursor = &currentSequence.at(startOffset + count - 1 - 1);
				}
				break;
			}

			case IR::ISA::Pragma::visibility:
			{
				assert(frame != nullptr);
				break;
			}

			case IR::ISA::Pragma::shortcircuitOpNopOffset:
			{
				shortcircuit.label = operands.value.shortcircuitMetadata.label;
				break;
			}

			case IR::ISA::Pragma::shortcircuitMutateToBool:
			{
				uint32_t lvid = operands.value.shortcircuitMutate.lvid;
				uint32_t source = operands.value.shortcircuitMutate.source;

				frame->lvids[lvid].synthetic = false;

				if (true)
				{
					auto& instr = *(*cursor - 1);
					assert(instr.opcodes[0] == static_cast<uint32_t>(IR::ISA::Op::stackalloc));
					uint32_t sizeoflvid = instr.to<IR::ISA::Op::stackalloc>().lvid;

					// sizeof
					auto& atombool = *(cdeftable.atoms().core.object[nyt_bool]);
					out->emitSizeof(sizeoflvid, atombool.atomid);

					auto& opc = cdeftable.substitute(lvid);
					opc.mutateToAtom(&atombool);
					opc.qualifiers.ref = true;

					// ALLOC: memory allocation of the new temporary object
					out->emitMemalloc(lvid, sizeoflvid);
					out->emitRef(lvid);
					frame->lvids[lvid].autorelease = true;
					// reset the internal value of the object
					out->emitFieldset(source, /*self*/lvid, 0); // builtin
				}
				else
					out->emitStore(lvid, source);
				break;
			}

			case IR::ISA::Pragma::synthetic:
			{
				uint32_t lvid = operands.value.synthetic.lvid;
				bool onoff = (operands.value.synthetic.onoff != 0);
				frame->lvids[lvid].synthetic = onoff;
				break;
			}

			case IR::ISA::Pragma::suggest:
			case IR::ISA::Pragma::builtinalias:
			case IR::ISA::Pragma::shortcircuit:
			case IR::ISA::Pragma::unknown:
				break;
		}
	}

} // namespace Instanciate
} // namespace Pass
} // namespace Nany
<|endoftext|>


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

#include "LedControllerRequestProxy.h"
#include "GeneratedTypes.h"

int main(int argc, const char **argv)
{
  LedControllerRequestProxy *device = new LedControllerRequestProxy(IfcNames_LedControllerRequestPortal);

  printf("Starting LED test");

  portalExec_start();

#ifdef BSIM
  // BSIM does not run very many cycles per second
  int blinkinterval = 10;
#else
  int blinkinterval = 100000000;
#endif
  int blinkon = 10;
  int blinkoff = 5;
  for (int i = 0; i < 20; i++) {
    printf("blink %d", blinkon);
    device->setLeds(blinkon, blinkinterval);
    sleep(2);
    printf("blink off %d", blinkoff);
    device->setLeds(blinkoff, blinkinterval);
    sleep(2);
  }
  printf("Done.\n");
}
<commit_msg>2 -> 4<commit_after>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

#include "LedControllerRequestProxy.h"
#include "GeneratedTypes.h"

int main(int argc, const char **argv)
{
  LedControllerRequestProxy *device = new LedControllerRequestProxy(IfcNames_LedControllerRequestPortal);

  printf("Starting LED test");

  portalExec_start();

#ifdef BSIM
  // BSIM does not run very many cycles per second
  int blinkinterval = 10;
#else
  int blinkinterval = 100000000;
#endif
  int blinkon = 10;
  int blinkoff = 5;
  for (int i = 0; i < 20; i++) {
    printf("blink %d", blinkon);
    device->setLeds(blinkon, blinkinterval);
    sleep(4);
    printf("blink off %d", blinkoff);
    device->setLeds(blinkoff, blinkinterval);
    sleep(4);
  }
  printf("Done.\n");
}
<|endoftext|>


<commit_before>// g++ -std=c++11 Hangman.cpp Game.cpp -o hangman
#include "Game.h"
#include <iostream>
#include <list>
#include <fstream>
#include <set>
#include <unordered_map>
#include <algorithm>
using namespace std;

unordered_map<int, list<string>> lenDic;

// iterates through all possibilities and guessed characters to find most common character in
// possible words that is not already guessed.
char findNextGuess(set<char> guessed, list<string> poss)
{
	unsigned int totalCounts[256] = {0};

	for (auto const& word: poss)
	{
		// letters should only count once per word
		// eg: in "shah", the h should only count once.
		set<char> string_set;
		for (auto c : word)
			string_set.insert(c);

		for (auto c : string_set)
			if (guessed.find(c) == guessed.end())
				totalCounts[(unsigned char)c]++;
	}

	unsigned int max = 0;
	char nextGuess;
	for (int i = 0; i < 256; i++)
		if (totalCounts[i] > max)
		{
			max = totalCounts[i];
			nextGuess = (char)i;
		}

	return nextGuess;
}

// we guessed the wrong character; iterate through possibilities, remove impossible elements
void trimPoss(list<string>* poss, char wrong_char)
{
	for(list<string>::iterator it = poss->begin(); it != poss->end(); it++)
		if ((*it).find('k') != string::npos)
		    it = poss->erase(it);
}

void trimPoss(string curr, list<string>* poss)
{

}

void readDict()
{
	string line;
	ifstream myfile ("words_50000.txt");
	if (myfile.is_open())
	{
		while (getline (myfile,line))
			if (lenDic.emplace(make_pair<int, list<string>>(int(line.length()), list<string>{string(line)})).second == false)
				lenDic[line.length()].push_back(line);
		myfile.close();
	}
	else
		cout << "Unable to open file";
}

int main()
{
	// readDict();

	// Game* g = new Game("back");
	// cout << *g;
	// g->guess_letter('a');
	// cout << *g;
	// delete g;

	// findNextGuess(guessed, possible);

	list<string> l;
	l.push_back("back");
	l.push_back("asdf");
	l.push_back("qwer");
	l.push_back("sack");
	l.push_back("lack");
	l.push_back("mat");
	l.push_back("daft");
	l.push_back("mace");
	l.push_back("kept");
	trimPoss(&l, 'k');

	for (auto const& item : l)
	{
		cout << item << " ";
	}

	return 0;
}
<commit_msg>trim possibilities: both completed<commit_after>// g++ -std=c++11 Hangman.cpp Game.cpp -o hangman -lboost_regex
#include "Game.h"
#include <boost/regex.hpp>
#include <iostream>
#include <list>
#include <fstream>
#include <set>
#include <unordered_map>
#include <algorithm>
using namespace std;

unordered_map<int, list<string>> lenDic;

// iterates through all possibilities and guessed characters to find most common character in
// possible words that is not already guessed.
char findNextGuess(set<char> guessed, list<string> poss)
{
	unsigned int totalCounts[256] = {0};

	for (auto const& word: poss)
	{
		// letters should only count once per word
		// eg: in "shah", the h should only count once.
		set<char> string_set;
		for (auto c : word)
			string_set.insert(c);

		for (auto c : string_set)
			if (guessed.find(c) == guessed.end())
				totalCounts[(unsigned char)c]++;
	}

	unsigned int max = 0;
	char nextGuess;
	for (int i = 0; i < 256; i++)
		if (totalCounts[i] > max)
		{
			max = totalCounts[i];
			nextGuess = (char)i;
		}

	return nextGuess;
}

// we guessed the wrong character; iterate through possibilities, remove impossible elements
void trimPoss(list<string>* poss, char wrong_char)
{
	for(list<string>::iterator it = poss->begin(); it != poss->end(); it++)
		if ((*it).find('k') != string::npos)
		    it = poss->erase(it);
}

void trimPoss(list<string>* poss, string curr)
{
	curr.insert(0,"^");
	curr.insert(curr.length(),"$");

	// boost::regex expr{curr};
	// boost::smatch what;
	// for (auto const& word : poss)
	// 	if (boost::regex_search(word, what, expr))
	boost::regex expr{curr};
	for(list<string>::iterator it = poss->begin(); it != poss->end(); ++it)
		if (!boost::regex_match(*it, expr))
		{
		    it = poss->erase(it);
		    --it;
		}

}

void readDict()
{
	string line;
	ifstream myfile ("words_50000.txt");
	if (myfile.is_open())
	{
		while (getline (myfile,line))
			if (lenDic.emplace(make_pair<int, list<string>>(int(line.length()), list<string>{string(line)})).second == false)
				lenDic[line.length()].push_back(line);
		myfile.close();
	}
	else
		cout << "Unable to open file";
}

int main(int argc, char *argv[])
{
	// readDict();

	// Game* g = new Game("back");
	// cout << *g;
	// g->guess_letter('a');
	// cout << *g;
	// delete g;

	// findNextGuess(guessed, possible);

	list<string> l;
	l.push_back("back");
	l.push_back("asdf");
	l.push_back("qwer");
	l.push_back("sack");
	l.push_back("stack");
	l.push_back("mat");
	l.push_back("daft");
	l.push_back("mace");
	l.push_back("kept");
	trimPoss(&l, ".ack");

	for (auto const& item : l)
		cout << item << " ";

	return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RL78/G13 DMA コントローラー定義 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/io_utils.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  DMA コントローラー・テンプレート
		@param[in]	BASE	ベース
		@param[in]	OFS		オフセット
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t BASE, uint32_t OFS>
	struct dma_t {

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  SFR アドレス・レジスタ（DSA）
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw8_t<BASE + OFS> DSA;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  RAM アドレス・レジスタ（DRAn）
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<BASE + 0x2 + (OFS * 2)> DRA;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	バイト・カウント・レジスタ（DBC）
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<BASE + 0x6 + (OFS * 2)> DBC;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  DMAモード・コントロール・レジスタ（DMC）
			@param[in]	T	アクセス・クラス
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		template <class T>
		struct dmc_t : public T {
			using T::operator =;
			using T::operator ();
			using T::operator |=;
			using T::operator &=;

			bit_rw_t<T, 7>	    STG;    ///< DMA転送開始ソフトウエア・トリガ
			bit_rw_t<T, 6>	    DRS;    ///< DMA転送方向の選択
			bit_rw_t<T, 5>	    DS;     ///< DMA転送での転送データ・サイズの指定
			bit_rw_t<T, 4>	    DWAIT;  ///< DMA転送の保留
			bits_rw_t<T, 0, 4>	IFC;    ///< DMA起動要因の選択
		};
		static dmc_t< rw8_t<BASE + 0xa + OFS> > DMC;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  DMA動作コントロール・レジスタ（DRC）
			@param[in]	T	アクセス・クラス
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		template <class T>
		struct drc_t : public T {
			using T::operator =;
			using T::operator ();
			using T::operator |=;
			using T::operator &=;

			bit_rw_t<T, 7>	DEN;  ///< DMA動作許可フラグ
			bit_rw_t<T, 0>	DST;  ///< DMA転送モード・フラグ
		};
		static drc_t< rw8_t<BASE + 0xc + OFS> > DRC;
	};

	typedef dma_t<0xFFFB0, 0> DMA0;
	typedef dma_t<0xFFFB0, 1> DMA1;
	typedef dma_t<0xF0200, 0> DMA2;
	typedef dma_t<0xF0200, 1> DMA3;
}
<commit_msg>fix bitpos<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RL78/G13 DMA コントローラー定義 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/io_utils.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  DMA コントローラー・テンプレート
		@param[in]	BASE	ベース
		@param[in]	OFS		オフセット
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t BASE, uint32_t OFS>
	struct dma_t {

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  SFR アドレス・レジスタ（DSA）
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw8_t<BASE + OFS> DSA;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  RAM アドレス・レジスタ（DRAn）
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<BASE + 0x2 + (OFS * 2)> DRA;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	バイト・カウント・レジスタ（DBC）
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<BASE + 0x6 + (OFS * 2)> DBC;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  DMAモード・コントロール・レジスタ（DMC）
			@param[in]	T	アクセス・クラス
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		template <class T>
		struct dmc_t : public T {
			using T::operator =;
			using T::operator ();
			using T::operator |=;
			using T::operator &=;

			bit_rw_t<T, bitpos::B7>	    STG;    ///< DMA転送開始ソフトウエア・トリガ
			bit_rw_t<T, bitpos::B6>	    DRS;    ///< DMA転送方向の選択
			bit_rw_t<T, bitpos::B5>	    DS;     ///< DMA転送での転送データ・サイズの指定
			bit_rw_t<T, bitpos::B4>	    DWAIT;  ///< DMA転送の保留
			bits_rw_t<T, bitpos::B0, 4>	IFC;    ///< DMA起動要因の選択
		};
		static dmc_t< rw8_t<BASE + 0xa + OFS> > DMC;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  DMA動作コントロール・レジスタ（DRC）
			@param[in]	T	アクセス・クラス
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		template <class T>
		struct drc_t : public T {
			using T::operator =;
			using T::operator ();
			using T::operator |=;
			using T::operator &=;

			bit_rw_t<T, bitpos::B7>	DEN;  ///< DMA動作許可フラグ
			bit_rw_t<T, bitpos::B0>	DST;  ///< DMA転送モード・フラグ
		};
		static drc_t< rw8_t<BASE + 0xc + OFS> > DRC;
	};

	typedef dma_t<0xFFFB0, 0> DMA0;
	typedef dma_t<0xFFFB0, 1> DMA1;
	typedef dma_t<0xF0200, 0> DMA2;
	typedef dma_t<0xF0200, 1> DMA3;
}
<|endoftext|>


<commit_before><commit_msg>Clean up previous rtl::OUStringBuffer changes<commit_after><|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_EVALUATION_ELLIPTIC_HH

#include <tuple>

#include <dune/common/dynmatrix.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/static_assert.hh>

#include <dune/stuff/functions/interfaces.hh>

#include <dune/gdt/basefunctionset/interface.hh>

#include "interface.hh"

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

// forward, to be used in the traits
template< class LocalizableFunctionImp >
class Elliptic;

/**
 *  \brief  Traits for the Elliptic evaluation.
 */
template< class LocalizableFunctionImp >
class EllipticTraits
{
public:
  typedef Elliptic< LocalizableFunctionImp >  derived_type;
  typedef LocalizableFunctionImp              LocalizableFunctionType;
  dune_static_assert((Dune::IsBaseOf< Dune::Stuff::LocalizableFunction, LocalizableFunctionImp >::value),
                     "ERROR: LocalizableFunctionImp is not a Dune::Stuff::LocalizableFunction.");
};

/**
 *  \brief  Computes an elliptic evaluation.
 */
template< class LocalizableFunctionImp >
class Elliptic
  : public LocalEvaluation::Codim0Interface< EllipticTraits< LocalizableFunctionImp >, 2 >
{
public:
  typedef EllipticTraits< LocalizableFunctionImp > Traits;
  typedef typename Traits::LocalizableFunctionType LocalizableFunctionType;

  Elliptic(const LocalizableFunctionType& inducingFunction)
    : inducingFunction_(inducingFunction)
  {}

  template< class EntityType >
  std::tuple< typename LocalizableFunctionType::template LocalFunction< EntityType >::Type > localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(inducingFunction_.localFunction(entity));
  }

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template< class L, class T, class A, class D, int d, class R, int rT, int rCT, int rA, int rCA >
  int order(const std::tuple< L >& localFuncs,
            const BaseFunctionSetInterface< T, D, d, R, rT, rCT >& testBase,
            const BaseFunctionSetInterface< A, D, d, R, rA, rCA >& ansatzBase) const
  {
    const auto& localFunction = std::get< 0 >(localFuncs);
    return order(localFunction, testBase, ansatzBase);
  }

  /**
   *  \todo add copydoc
   *  \return localFunction.order() + (testBase.order() - 1) + (ansatzBase.order() - 1)
   */
  template< class L, class T, class A, class D, int d, class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  int order(const Dune::Stuff::LocalFunctionInterface< L, D, d, R, rL, rCL >& localFunction,
            const BaseFunctionSetInterface< T, D, d, R, rT, rCT >& testBase,
            const BaseFunctionSetInterface< A, D, d, R, rA, rCA >& ansatzBase) const
  {
    if (localFunction.order() < 0)
      return -1;
    else
      return std::max(int(localFunction.order() + testBase.order() + ansatzBase.order() - 2), 0);
  } // int order(...)

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template< class L, class T, class A, class D, int d, class R, int rT, int rCT, int rA, int rCA >
  static void evaluate(const std::tuple< L >& localFunctions,
                       const BaseFunctionSetInterface< T, D, d, R, rT, rCT >& testBase,
                       const BaseFunctionSetInterface< A, D, d, R, rA, rCA >& ansatzBase,
                       const Dune::FieldVector< D, d >& localPoint,
                       Dune::DynamicMatrix< R >& ret)
  {
    const auto& localFunction = std::get< 0 >(localFunctions);
    evaluate(localFunction, testBase, ansatzBase, localPoint, ret);
  }

  template< class L, class T, class A, class D, int d, class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  static void evaluate(const Dune::Stuff::LocalFunctionInterface< L, D, d, R, rL, rCL >& /*localFunction*/,
                       const BaseFunctionSetInterface< T, D, d, R, rT, rCT >& /*testBase*/,
                       const BaseFunctionSetInterface< A, D, d, R, rA, rCA >& /*ansatzBase*/,
                       const Dune::FieldVector< D, d >& /*localPoint*/,
                       Dune::DynamicMatrix< R >& /*ret*/)
  {
    dune_static_assert((Dune::AlwaysFalse< R >::value),
                       "ERROR: not implemented for this combination of dimensions!");
  }

  /**
   *  \brief  Computes an elliptic evaluation for a scalar local function and scalar basefunctionsets.
   *  \tparam L Traits of the Dune::Stuff::LocalFunctionInterface implementation
   *  \tparam T Traits of the test BaseFunctionSetInterface implementation
   *  \tparam A Traits of the ansatz BaseFunctionSetInterface implementation
   *  \tparam D DomainFieldType
   *  \tparam d dimDomain
   *  \tparam R RangeFieldType
   */
  template< class L, class T, class A, class D, int d, class R >
  static void evaluate(const Dune::Stuff::LocalFunctionInterface< L, D, d, R, 1, 1 >& localFunction,
                       const BaseFunctionSetInterface< T, D, d, R, 1, 1 >& testBase,
                       const BaseFunctionSetInterface< A, D, d, R, 1, 1 >& ansatzBase,
                       const Dune::FieldVector< D, d >& localPoint,
                       Dune::DynamicMatrix< R >& ret)
  {
    typedef typename BaseFunctionSetInterface< A, D, d, R, 1, 1 >::RangeType         RangeType;
    typedef typename BaseFunctionSetInterface< A, D, d, R, 1, 1 >::JacobianRangeType JacobianRangeType;
    // evaluate local function
    const RangeType functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        const R gradientProduct = ansatzGradients[jj][0] * testGradients[ii][0];
        retRow[jj] = functionValue * gradientProduct;
      }
    }
  } // ... evaluate< ..., 1, 1 >(...)

  /**
   *  \brief  Computes an elliptic evaluation for a matrix-valued local function and matrix-valued basefunctionsets.
   *  \tparam L Traits of the Dune::Stuff::LocalFunctionInterface implementation
   *  \tparam T Traits of the test BaseFunctionSetInterface implementation
   *  \tparam A Traits of the ansatz BaseFunctionSetInterface implementation
   *  \tparam D DomainFieldType
   *  \tparam d dimDomain
   *  \tparam R RangeFieldType
   */
  template< class L, class T, class A, class D, int d, class R>
  static void evaluate(const Dune::Stuff::LocalFunctionInterface< L, D, d, R, d, d >& localFunction,
                       const BaseFunctionSetInterface< T, D, d, R, 1, 1 >& testBase,
                       const BaseFunctionSetInterface< A, D, d, R, 1, 1 >& ansatzBase,
                       const Dune::FieldVector< D, d >& localPoint,
                       Dune::DynamicMatrix< R >& ret)
  {
    typedef typename Dune::Stuff::LocalFunctionInterface< L, D, d, R, d, d >::RangeType DiffusionRangeType;
    typedef typename BaseFunctionSetInterface< A, D, d, R, 1, 1 >::JacobianRangeType    JacobianRangeType;
    typedef typename BaseFunctionSetInterface< A, D, d, R, 1, 1 >::RangeType            RangeType;

    // evaluate local function
    const DiffusionRangeType functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector< D, d > product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        functionValue.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate< ..., d, d >(...)

private:
  const LocalizableFunctionType& inducingFunction_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EVALUATION_ELLIPTIC_HH
<commit_msg>[localevaluation.elliptic] updated to new functions<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_EVALUATION_ELLIPTIC_HH

#include <tuple>
#include <type_traits>

#include <dune/common/dynmatrix.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/static_assert.hh>

#include <dune/stuff/functions/interfaces.hh>

#include "interface.hh"

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

// forward, to be used in the traits
template< class LocalizableFunctionImp >
class Elliptic;

/**
 *  \brief  Traits for the Elliptic evaluation.
 */
template< class LocalizableFunctionImp >
class EllipticTraits
{
public:
  typedef Elliptic< LocalizableFunctionImp >  derived_type;
  typedef LocalizableFunctionImp              LocalizableFunctionType;
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, LocalizableFunctionImp >::value,
                "LocalizableFunctionImp has to be derived from Stuff::IsLocalizableFunction.");
};

/**
 *  \brief  Computes an elliptic evaluation.
 */
template< class LocalizableFunctionImp >
class Elliptic
  : public LocalEvaluation::Codim0Interface< EllipticTraits< LocalizableFunctionImp >, 2 >
{
public:
  typedef EllipticTraits< LocalizableFunctionImp > Traits;
  typedef typename Traits::LocalizableFunctionType LocalizableFunctionType;

  Elliptic(const LocalizableFunctionType& inducingFunction)
    : inducingFunction_(inducingFunction)
  {}

  template< class EntityType >
  class LocalfunctionTuple
  {
    typedef typename LocalizableFunctionType::LocalfunctionType LocalfunctionType;
  public:
    typedef std::tuple< std::shared_ptr< LocalfunctionType > > Type;
  };

  template< class EntityType >
  typename LocalfunctionTuple< EntityType >::Type localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(inducingFunction_.local_function(entity));
  }

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template< class E, class D, int d, class R, int rT, int rCT, int rA, int rCA >
  size_t order(const typename LocalfunctionTuple< E >::Type& localFuncs,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& ansatzBase) const
  {
    const auto localFunction = std::get< 0 >(localFuncs);
    return order(*localFunction, testBase, ansatzBase);
  }

  /**
   *  \todo add copydoc
   *  \return localFunction.order() + (testBase.order() - 1) + (ansatzBase.order() - 1)
   */
  template< class E, class D, int d, class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  size_t order(const Stuff::LocalfunctionInterface< E, D, d, R, rL, rCL >& localFunction,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& ansatzBase) const
  {
    return std::max(int(localFunction.order() + testBase.order() + ansatzBase.order() - 2), 0);
  }

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template< class E, class D, int d, class R, int rT, int rCT, int rA, int rCA >
  static void evaluate(const typename LocalfunctionTuple< E >::Type& localFuncs,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& testBase,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& ansatzBase,
                       const Dune::FieldVector< D, d >& localPoint,
                       Dune::DynamicMatrix< R >& ret)
  {
    const auto localFunction = std::get< 0 >(localFuncs);
    evaluate(*localFunction, testBase, ansatzBase, localPoint, ret);
  }

  template< class E, class D, int d, class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  static void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, rL, rCL >& /*localFunction*/,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, rT, rCT >& /*testBase*/,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, rA, rCA >& /*ansatzBase*/,
                       const Dune::FieldVector< D, d >& /*localPoint*/,
                       Dune::DynamicMatrix< R >& /*ret*/)
  {
    static_assert(Dune::AlwaysFalse< R >::value, "Not implemented for these dimensions!");
  }

  /**
   *  \brief  Computes an elliptic evaluation for a scalar local function and scalar basefunctionsets.
   *  \tparam E EntityType
   *  \tparam D DomainFieldType
   *  \tparam d dimDomain
   *  \tparam R RangeFieldType
   */
  template< class E, class D, int d, class R >
  static void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, 1, 1 >& localFunction,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& testBase,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& ansatzBase,
                       const Dune::FieldVector< D, d >& localPoint,
                       Dune::DynamicMatrix< R >& ret)
  {
    typedef typename Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >::RangeType          RangeType;
    typedef typename Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >::JacobianRangeType  JacobianRangeType;
    // evaluate local function
    const RangeType functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        const R gradientProduct = ansatzGradients[jj][0] * testGradients[ii][0];
        retRow[jj] = functionValue * gradientProduct;
      }
    }
  } // ... evaluate< ..., 1, 1 >(...)

  /**
   *  \brief  Computes an elliptic evaluation for a matrix-valued local function and matrix-valued basefunctionsets.
   *  \tparam E EntityType
   *  \tparam D DomainFieldType
   *  \tparam d dimDomain
   *  \tparam R RangeFieldType
   */
  template< class E, class D, int d, class R>
  static void evaluate(const Stuff::LocalfunctionInterface< E, D, d, R, d, d >& localFunction,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& testBase,
                       const Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >& ansatzBase,
                       const Dune::FieldVector< D, d >& localPoint,
                       Dune::DynamicMatrix< R >& ret)
  {
    typedef typename Stuff::LocalfunctionInterface< E, D, d, R, d, d >::RangeType             DiffusionRangeType;
    typedef typename Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >::JacobianRangeType  JacobianRangeType;
    typedef typename Stuff::LocalfunctionSetInterface< E, D, d, R, 1, 1 >::RangeType          RangeType;

    // evaluate local function
    const DiffusionRangeType functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector< D, d > product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        functionValue.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate< ..., d, d >(...)

private:
  const LocalizableFunctionType& inducingFunction_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EVALUATION_ELLIPTIC_HH
<|endoftext|>


<commit_before>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    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.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "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 JOE HERMASZEWSKI OR CONTRIBUTORS 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.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "operator.hpp"

#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include <utility>

#include <engine/types.hpp>
#include <compiler/casting.hpp>
#include <compiler/code_generator.hpp>
#include <compiler/generic_value.hpp>
#include <compiler/parser.hpp>
#include <compiler/sema_analyzer.hpp>
#include <compiler/terminal_types.hpp>
#include <compiler/tokens/expression.hpp>
#include <compiler/tokens/token.hpp>

namespace JoeLang
{
namespace Compiler
{

//------------------------------------------------------------------------------
// AssignmentOperator
//------------------------------------------------------------------------------

AssignmentOperator::AssignmentOperator( Op op )
    :Token( TokenTy::AssignmentOperator )
    ,m_Operator(op)
{
}

AssignmentOperator::~AssignmentOperator()
{
}

void AssignmentOperator::Print(int depth) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << "assignment_op" << std::endl;
}

AssignmentOperator::Op AssignmentOperator::GetOp() const
{
    return m_Operator;
}

bool AssignmentOperator::Parse( Parser& parser,
                                std::unique_ptr<AssignmentOperator>& token )
{
    // A vector of terminals for assignment operators and their Op enumerants
    static const std::vector< std::pair<TerminalType, Op> >
           s_assignment_operator_terminals =
    {
        { TerminalType::EQUALS,             Op::EQUALS },
        { TerminalType::PLUS_EQUALS,        Op::PLUS_EQUALS },
        { TerminalType::MINUS_EQUALS,       Op::MINUS_EQUALS },
        { TerminalType::MULTIPLY_EQUALS,    Op::MULTIPLY_EQUALS },
        { TerminalType::DIVIDE_EQUALS,      Op::DIVIDE_EQUALS },
        { TerminalType::MODULO_EQUALS,      Op::MODULO_EQUALS },
        { TerminalType::LEFT_SHIFT_EQUALS,  Op::SHL_EQUALS },
        { TerminalType::RIGHT_SHIFT_EQUALS, Op::SHR_EQUALS },
        { TerminalType::AND_EQUALS,         Op::AND_EQUALS },
        { TerminalType::INCLUSIVE_OR_EQUALS, Op::OR_EQUALS },
        { TerminalType::EXCLUSIVE_OR_EQUALS, Op::XOR_EQUALS }
    };

    // Try and match any of these operators
    for( const auto& p : s_assignment_operator_terminals )
        if( parser.ExpectTerminal( p.first ) )
        {
            token.reset( new AssignmentOperator( p.second ) );
            return true;
        }
    return false;
}

//------------------------------------------------------------------------------
// PostfixOperator
//------------------------------------------------------------------------------

PostfixOperator::PostfixOperator( TokenTy sub_class_id )
    :Token( sub_class_id )
{
}

PostfixOperator::~PostfixOperator()
{
}

bool PostfixOperator::Parse( Parser& parser,
                             std::unique_ptr<PostfixOperator>& token )
{
    // Try and parse any of the operators
    std::unique_ptr<Token> t;
    if( !parser.ExpectAnyOf<SubscriptOperator,
                            ArgumentListOperator,
                            MemberAccessOperator,
                            IncrementOrDecrementOperator>( t ) )
        return false;

    // Cast the result to a PostfixOperator
    assert( isa<PostfixOperator>(t) );
    token.reset( static_cast<PostfixOperator*>( t.release() ) );
    return true;
}

llvm::Value* PostfixOperator::CodeGenPointerTo(
                                            CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

bool PostfixOperator::IsLValue( const Expression& expression ) const
{
    return false;
}

bool PostfixOperator::classof( const Token* e )
{
    return e->GetSubClassID() >= TokenTy::PostfixOperator_Start &&
           e->GetSubClassID() <= TokenTy::PostfixOperator_End;
}

bool PostfixOperator::classof( const PostfixOperator* e )
{
    return true;
}

//------------------------------------------------------------------------------
// SubscriptOperator
//------------------------------------------------------------------------------

SubscriptOperator::SubscriptOperator( Expression_up index_expression )
    :PostfixOperator( TokenTy::SubscriptOperator )
    ,m_IndexExpression( std::move(index_expression) )
{
    assert( m_IndexExpression &&
            "SubscriptOperator given a null index expression" );
}

SubscriptOperator::~SubscriptOperator()
{
}

bool SubscriptOperator::PerformSema( SemaAnalyzer& sema,
                                     const Expression_up& expression )
{
    bool good = m_IndexExpression->ResolveIdentifiers( sema );
    if( good )
    {
        m_IndexExpression = CastExpression::Create( Type::I64,
                                                    std::move(m_IndexExpression) );
        good &= m_IndexExpression->PerformSema( sema );
    }
    if( expression->GetReturnType() != Type::ARRAY )
    {
        sema.Error( "Trying to index into a non-array" );
        return false;
    }
    const std::vector<unsigned> extents = expression->GetArrayExtents();
    assert( extents.size() != 0 && "Indexing into a non array" );
    if( m_IndexExpression->IsConst() )
    {
        unsigned index = sema.EvaluateExpression( *m_IndexExpression ).GetI64();
        if( index >= extents[0] )
            sema.Error( "Indexing beyond array bounds" );
    }
    m_ArrayExtents.assign( ++extents.begin(), extents.end() );
    return good;
}

llvm::Value* SubscriptOperator::CodeGen( CodeGenerator& code_gen,
                                         const Expression_up& expression )
{
    assert( expression && "SubscriptOperator given an null expression" );
    return code_gen.CreateArrayIndex( *expression, *m_IndexExpression );
}

llvm::Value* SubscriptOperator::CodeGenPointerTo(
                                            CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( expression && "SubscriptOperator given an null expression" );
    return code_gen.CreateArrayIndexPointerTo( *expression,
                                               *m_IndexExpression );
}

Type SubscriptOperator::GetReturnType( const Expression_up& expression ) const
{
    assert( expression && "SubscriptOperator given an null expression" );
    const std::vector<unsigned>& array_extents = expression->GetArrayExtents();
    if( array_extents.size() > 1 )
        return Type::ARRAY;
    return expression->GetUnderlyingType();
}

Type SubscriptOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( expression && "SubscriptOperator given an null expression" );
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& SubscriptOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    return m_ArrayExtents;
}

bool SubscriptOperator::IsConst( const Expression& expression ) const
{
    return expression.IsConst() &&
           m_IndexExpression->IsConst();
}

bool SubscriptOperator::IsLValue( const Expression& expression ) const
{
    return true;
}

void SubscriptOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << "SubscriptOperator\n";
    m_IndexExpression->Print( depth + 1 );
}

bool SubscriptOperator::Parse( Parser& parser,
                               std::unique_ptr<SubscriptOperator>& token )
{
    // open bracket
    if( !parser.ExpectTerminal( TerminalType::OPEN_SQUARE ) )
        return false;

    // parse the index expression
    Expression_up index_expression;
    if( !parser.Expect<Expression>( index_expression ) )
        return false;

    // close bracket
    if( !parser.ExpectTerminal( TerminalType::CLOSE_SQUARE ) )
        return false;

    token.reset( new SubscriptOperator( std::move(index_expression) ) );
    return true;
}

//------------------------------------------------------------------------------
// ArgumentListOperator
//------------------------------------------------------------------------------

ArgumentListOperator::ArgumentListOperator(
        ArgumentExpressionVector argument_expressions )
    :PostfixOperator( TokenTy::ArgumentListOperator )
    ,m_ArgumentExpressions( std::move(argument_expressions) )
{
#ifndef NDEBUG
    for( const auto& e : m_ArgumentExpressions )
        assert( e && "ArgumentListOperator given a null argument expression" );
#endif
}

ArgumentListOperator::~ArgumentListOperator()
{
}

bool ArgumentListOperator::PerformSema(
                                SemaAnalyzer& sema,
                                const Expression_up& expression )
{
    assert( false && "Complete me" );
    return false;
}

llvm::Value* ArgumentListOperator::CodeGen( CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

Type ArgumentListOperator::GetReturnType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

Type ArgumentListOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& ArgumentListOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    const static std::vector<unsigned> empty;
    return empty;
}

bool ArgumentListOperator::IsConst( const Expression& expression ) const
{
    return false;
}

void ArgumentListOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << "ArgumentListOperator\n";
    for( const auto& i : m_ArgumentExpressions )
        i->Print( depth + 1 );
}

bool ArgumentListOperator::Parse( Parser& parser,
                                  std::unique_ptr<ArgumentListOperator>& token )
{
    // parse (
    if( !parser.ExpectTerminal( TerminalType::OPEN_ROUND ) )
        return false;

    // The vector to hold the expressions
    ArgumentExpressionVector argument_expressions;

    // The pointer to hold each argument as we parse
    Expression_up argument;

    // Try and parse the first argument
    if( parser.Expect<AssignmentExpression>( argument ) )
    {
        // We parsed the first argument push it onto the vector
        argument_expressions.push_back( std::move( argument ) );

        // Each subsequent argument expects a comma
        while( parser.ExpectTerminal( TerminalType::COMMA ) )
        {
            // If we've seen a comma we must have an expression to push
            if( !parser.Expect<AssignmentExpression>( argument ) )
                return false;
            argument_expressions.push_back( std::move( argument ) );
        }
    }

    // The lexer may be out of step
    CHECK_PARSER;

    // parse closing )
    if( !parser.ExpectTerminal( TerminalType::CLOSE_ROUND ) )
        return false;

    token.reset( new ArgumentListOperator( std::move(argument_expressions) ) );
    return true;
}

//------------------------------------------------------------------------------
// MemberAccessOperator
//------------------------------------------------------------------------------

MemberAccessOperator::MemberAccessOperator( std::string identifier )
    :PostfixOperator( TokenTy::MemberAccessOperator )
    ,m_Identifier( std::move( identifier ) )
{
}

MemberAccessOperator::~MemberAccessOperator()
{
}

bool MemberAccessOperator::PerformSema(
                                SemaAnalyzer& sema,
                                const Expression_up& expression )
{
    assert( false && "Complete me" );
    return false;
}

llvm::Value* MemberAccessOperator::CodeGen( CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

Type MemberAccessOperator::GetReturnType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

Type MemberAccessOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& MemberAccessOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    const static std::vector<unsigned> empty;
    return empty;
}

bool MemberAccessOperator::IsConst( const Expression& expression ) const
{
    return expression.IsConst();
}

void MemberAccessOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << ".\n";
    for( int i = 0; i < depth * 4 + 4; ++i )
        std::cout << " ";
    std::cout << m_Identifier << std::endl;
}

bool MemberAccessOperator::Parse( Parser& parser,
                                  std::unique_ptr<MemberAccessOperator>& token )
{
    // Parse the member access operator
    if( !parser.ExpectTerminal( TerminalType::PERIOD ) )
        return false;

    // Store the member identifier in identifier
    std::string identifier;
    if( !parser.ExpectTerminal( TerminalType::IDENTIFIER, identifier ) )
        return false;

    token.reset( new MemberAccessOperator( std::move(identifier) ) );
    return true;
}

//------------------------------------------------------------------------------
// IncrementOrDecrementOperator
//------------------------------------------------------------------------------

IncrementOrDecrementOperator::IncrementOrDecrementOperator( Op op )
    :PostfixOperator( TokenTy::IncrementOrDecrementOperator )
    ,m_Operator( op )
{
}

IncrementOrDecrementOperator::~IncrementOrDecrementOperator()
{
}

bool IncrementOrDecrementOperator::PerformSema(
                                SemaAnalyzer& sema,
                                const Expression_up& expression )
{
    assert( false && "Complete me" );
    return false;
}

llvm::Value* IncrementOrDecrementOperator::CodeGen(
                                               CodeGenerator& code_gen,
                                               const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

Type IncrementOrDecrementOperator::GetReturnType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

Type IncrementOrDecrementOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& IncrementOrDecrementOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    const static std::vector<unsigned> empty;
    return empty;
}

bool IncrementOrDecrementOperator::IsConst( const Expression& expression ) const
{
    return false;
}

void IncrementOrDecrementOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << (m_Operator == Op::INCREMENT ? "++" : "--") << std::endl;
}

bool IncrementOrDecrementOperator::Parse(
                          Parser& parser,
                          std::unique_ptr<IncrementOrDecrementOperator>& token )
{
    // Try to parse ++
    if( parser.ExpectTerminal( TerminalType::INCREMENT ) )
    {
        token.reset( new IncrementOrDecrementOperator( Op::INCREMENT ) );
        return true;
    }

    // Try to parse --
    if( parser.ExpectTerminal( TerminalType::DECREMENT ) )
    {
        token.reset( new IncrementOrDecrementOperator( Op::DECREMENT ) );
        return true;
    }

    return false;
}

} // namespace Compiler
} // namespace JoeLang
<commit_msg>[+] Completed GetUnderlyingType<commit_after>/*
    Copyright 2011 Joe Hermaszewski. All rights reserved.

    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.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "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 JOE HERMASZEWSKI OR CONTRIBUTORS 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.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "operator.hpp"

#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include <utility>

#include <engine/types.hpp>
#include <compiler/casting.hpp>
#include <compiler/code_generator.hpp>
#include <compiler/generic_value.hpp>
#include <compiler/parser.hpp>
#include <compiler/sema_analyzer.hpp>
#include <compiler/terminal_types.hpp>
#include <compiler/tokens/expression.hpp>
#include <compiler/tokens/token.hpp>

namespace JoeLang
{
namespace Compiler
{

//------------------------------------------------------------------------------
// AssignmentOperator
//------------------------------------------------------------------------------

AssignmentOperator::AssignmentOperator( Op op )
    :Token( TokenTy::AssignmentOperator )
    ,m_Operator(op)
{
}

AssignmentOperator::~AssignmentOperator()
{
}

void AssignmentOperator::Print(int depth) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << "assignment_op" << std::endl;
}

AssignmentOperator::Op AssignmentOperator::GetOp() const
{
    return m_Operator;
}

bool AssignmentOperator::Parse( Parser& parser,
                                std::unique_ptr<AssignmentOperator>& token )
{
    // A vector of terminals for assignment operators and their Op enumerants
    static const std::vector< std::pair<TerminalType, Op> >
           s_assignment_operator_terminals =
    {
        { TerminalType::EQUALS,             Op::EQUALS },
        { TerminalType::PLUS_EQUALS,        Op::PLUS_EQUALS },
        { TerminalType::MINUS_EQUALS,       Op::MINUS_EQUALS },
        { TerminalType::MULTIPLY_EQUALS,    Op::MULTIPLY_EQUALS },
        { TerminalType::DIVIDE_EQUALS,      Op::DIVIDE_EQUALS },
        { TerminalType::MODULO_EQUALS,      Op::MODULO_EQUALS },
        { TerminalType::LEFT_SHIFT_EQUALS,  Op::SHL_EQUALS },
        { TerminalType::RIGHT_SHIFT_EQUALS, Op::SHR_EQUALS },
        { TerminalType::AND_EQUALS,         Op::AND_EQUALS },
        { TerminalType::INCLUSIVE_OR_EQUALS, Op::OR_EQUALS },
        { TerminalType::EXCLUSIVE_OR_EQUALS, Op::XOR_EQUALS }
    };

    // Try and match any of these operators
    for( const auto& p : s_assignment_operator_terminals )
        if( parser.ExpectTerminal( p.first ) )
        {
            token.reset( new AssignmentOperator( p.second ) );
            return true;
        }
    return false;
}

//------------------------------------------------------------------------------
// PostfixOperator
//------------------------------------------------------------------------------

PostfixOperator::PostfixOperator( TokenTy sub_class_id )
    :Token( sub_class_id )
{
}

PostfixOperator::~PostfixOperator()
{
}

bool PostfixOperator::Parse( Parser& parser,
                             std::unique_ptr<PostfixOperator>& token )
{
    // Try and parse any of the operators
    std::unique_ptr<Token> t;
    if( !parser.ExpectAnyOf<SubscriptOperator,
                            ArgumentListOperator,
                            MemberAccessOperator,
                            IncrementOrDecrementOperator>( t ) )
        return false;

    // Cast the result to a PostfixOperator
    assert( isa<PostfixOperator>(t) );
    token.reset( static_cast<PostfixOperator*>( t.release() ) );
    return true;
}

llvm::Value* PostfixOperator::CodeGenPointerTo(
                                            CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

bool PostfixOperator::IsLValue( const Expression& expression ) const
{
    return false;
}

bool PostfixOperator::classof( const Token* e )
{
    return e->GetSubClassID() >= TokenTy::PostfixOperator_Start &&
           e->GetSubClassID() <= TokenTy::PostfixOperator_End;
}

bool PostfixOperator::classof( const PostfixOperator* e )
{
    return true;
}

//------------------------------------------------------------------------------
// SubscriptOperator
//------------------------------------------------------------------------------

SubscriptOperator::SubscriptOperator( Expression_up index_expression )
    :PostfixOperator( TokenTy::SubscriptOperator )
    ,m_IndexExpression( std::move(index_expression) )
{
    assert( m_IndexExpression &&
            "SubscriptOperator given a null index expression" );
}

SubscriptOperator::~SubscriptOperator()
{
}

bool SubscriptOperator::PerformSema( SemaAnalyzer& sema,
                                     const Expression_up& expression )
{
    bool good = m_IndexExpression->ResolveIdentifiers( sema );
    if( good )
    {
        m_IndexExpression = CastExpression::Create( Type::I64,
                                                    std::move(m_IndexExpression) );
        good &= m_IndexExpression->PerformSema( sema );
    }
    if( expression->GetReturnType() != Type::ARRAY )
    {
        sema.Error( "Trying to index into a non-array" );
        return false;
    }
    const std::vector<unsigned> extents = expression->GetArrayExtents();
    assert( extents.size() != 0 && "Indexing into a non array" );
    if( m_IndexExpression->IsConst() )
    {
        unsigned index = sema.EvaluateExpression( *m_IndexExpression ).GetI64();
        if( index >= extents[0] )
            sema.Error( "Indexing beyond array bounds" );
    }
    m_ArrayExtents.assign( ++extents.begin(), extents.end() );
    return good;
}

llvm::Value* SubscriptOperator::CodeGen( CodeGenerator& code_gen,
                                         const Expression_up& expression )
{
    assert( expression && "SubscriptOperator given an null expression" );
    return code_gen.CreateArrayIndex( *expression, *m_IndexExpression );
}

llvm::Value* SubscriptOperator::CodeGenPointerTo(
                                            CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( expression && "SubscriptOperator given an null expression" );
    return code_gen.CreateArrayIndexPointerTo( *expression,
                                               *m_IndexExpression );
}

Type SubscriptOperator::GetReturnType( const Expression_up& expression ) const
{
    assert( expression && "SubscriptOperator given an null expression" );
    const std::vector<unsigned>& array_extents = expression->GetArrayExtents();
    if( array_extents.size() > 1 )
        return Type::ARRAY;
    return expression->GetUnderlyingType();
}

Type SubscriptOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( expression && "SubscriptOperator given an null expression" );
    return expression->GetUnderlyingType();
}

const std::vector<unsigned>& SubscriptOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    return m_ArrayExtents;
}

bool SubscriptOperator::IsConst( const Expression& expression ) const
{
    return expression.IsConst() &&
           m_IndexExpression->IsConst();
}

bool SubscriptOperator::IsLValue( const Expression& expression ) const
{
    return true;
}

void SubscriptOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << "SubscriptOperator\n";
    m_IndexExpression->Print( depth + 1 );
}

bool SubscriptOperator::Parse( Parser& parser,
                               std::unique_ptr<SubscriptOperator>& token )
{
    // open bracket
    if( !parser.ExpectTerminal( TerminalType::OPEN_SQUARE ) )
        return false;

    // parse the index expression
    Expression_up index_expression;
    if( !parser.Expect<Expression>( index_expression ) )
        return false;

    // close bracket
    if( !parser.ExpectTerminal( TerminalType::CLOSE_SQUARE ) )
        return false;

    token.reset( new SubscriptOperator( std::move(index_expression) ) );
    return true;
}

//------------------------------------------------------------------------------
// ArgumentListOperator
//------------------------------------------------------------------------------

ArgumentListOperator::ArgumentListOperator(
        ArgumentExpressionVector argument_expressions )
    :PostfixOperator( TokenTy::ArgumentListOperator )
    ,m_ArgumentExpressions( std::move(argument_expressions) )
{
#ifndef NDEBUG
    for( const auto& e : m_ArgumentExpressions )
        assert( e && "ArgumentListOperator given a null argument expression" );
#endif
}

ArgumentListOperator::~ArgumentListOperator()
{
}

bool ArgumentListOperator::PerformSema(
                                SemaAnalyzer& sema,
                                const Expression_up& expression )
{
    assert( false && "Complete me" );
    return false;
}

llvm::Value* ArgumentListOperator::CodeGen( CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

Type ArgumentListOperator::GetReturnType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

Type ArgumentListOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& ArgumentListOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    const static std::vector<unsigned> empty;
    return empty;
}

bool ArgumentListOperator::IsConst( const Expression& expression ) const
{
    return false;
}

void ArgumentListOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << "ArgumentListOperator\n";
    for( const auto& i : m_ArgumentExpressions )
        i->Print( depth + 1 );
}

bool ArgumentListOperator::Parse( Parser& parser,
                                  std::unique_ptr<ArgumentListOperator>& token )
{
    // parse (
    if( !parser.ExpectTerminal( TerminalType::OPEN_ROUND ) )
        return false;

    // The vector to hold the expressions
    ArgumentExpressionVector argument_expressions;

    // The pointer to hold each argument as we parse
    Expression_up argument;

    // Try and parse the first argument
    if( parser.Expect<AssignmentExpression>( argument ) )
    {
        // We parsed the first argument push it onto the vector
        argument_expressions.push_back( std::move( argument ) );

        // Each subsequent argument expects a comma
        while( parser.ExpectTerminal( TerminalType::COMMA ) )
        {
            // If we've seen a comma we must have an expression to push
            if( !parser.Expect<AssignmentExpression>( argument ) )
                return false;
            argument_expressions.push_back( std::move( argument ) );
        }
    }

    // The lexer may be out of step
    CHECK_PARSER;

    // parse closing )
    if( !parser.ExpectTerminal( TerminalType::CLOSE_ROUND ) )
        return false;

    token.reset( new ArgumentListOperator( std::move(argument_expressions) ) );
    return true;
}

//------------------------------------------------------------------------------
// MemberAccessOperator
//------------------------------------------------------------------------------

MemberAccessOperator::MemberAccessOperator( std::string identifier )
    :PostfixOperator( TokenTy::MemberAccessOperator )
    ,m_Identifier( std::move( identifier ) )
{
}

MemberAccessOperator::~MemberAccessOperator()
{
}

bool MemberAccessOperator::PerformSema(
                                SemaAnalyzer& sema,
                                const Expression_up& expression )
{
    assert( false && "Complete me" );
    return false;
}

llvm::Value* MemberAccessOperator::CodeGen( CodeGenerator& code_gen,
                                            const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

Type MemberAccessOperator::GetReturnType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

Type MemberAccessOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& MemberAccessOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    const static std::vector<unsigned> empty;
    return empty;
}

bool MemberAccessOperator::IsConst( const Expression& expression ) const
{
    return expression.IsConst();
}

void MemberAccessOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << ".\n";
    for( int i = 0; i < depth * 4 + 4; ++i )
        std::cout << " ";
    std::cout << m_Identifier << std::endl;
}

bool MemberAccessOperator::Parse( Parser& parser,
                                  std::unique_ptr<MemberAccessOperator>& token )
{
    // Parse the member access operator
    if( !parser.ExpectTerminal( TerminalType::PERIOD ) )
        return false;

    // Store the member identifier in identifier
    std::string identifier;
    if( !parser.ExpectTerminal( TerminalType::IDENTIFIER, identifier ) )
        return false;

    token.reset( new MemberAccessOperator( std::move(identifier) ) );
    return true;
}

//------------------------------------------------------------------------------
// IncrementOrDecrementOperator
//------------------------------------------------------------------------------

IncrementOrDecrementOperator::IncrementOrDecrementOperator( Op op )
    :PostfixOperator( TokenTy::IncrementOrDecrementOperator )
    ,m_Operator( op )
{
}

IncrementOrDecrementOperator::~IncrementOrDecrementOperator()
{
}

bool IncrementOrDecrementOperator::PerformSema(
                                SemaAnalyzer& sema,
                                const Expression_up& expression )
{
    assert( false && "Complete me" );
    return false;
}

llvm::Value* IncrementOrDecrementOperator::CodeGen(
                                               CodeGenerator& code_gen,
                                               const Expression_up& expression )
{
    assert( false && "complete me" );
    return nullptr;
}

Type IncrementOrDecrementOperator::GetReturnType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

Type IncrementOrDecrementOperator::GetUnderlyingType(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    return Type::UNKNOWN_TYPE;
}

const std::vector<unsigned>& IncrementOrDecrementOperator::GetArrayExtents(
                                        const Expression_up& expression ) const
{
    assert( false && "Complete me" );
    const static std::vector<unsigned> empty;
    return empty;
}

bool IncrementOrDecrementOperator::IsConst( const Expression& expression ) const
{
    return false;
}

void IncrementOrDecrementOperator::Print( int depth ) const
{
    for( int i = 0; i < depth * 4; ++i )
        std::cout << " ";
    std::cout << (m_Operator == Op::INCREMENT ? "++" : "--") << std::endl;
}

bool IncrementOrDecrementOperator::Parse(
                          Parser& parser,
                          std::unique_ptr<IncrementOrDecrementOperator>& token )
{
    // Try to parse ++
    if( parser.ExpectTerminal( TerminalType::INCREMENT ) )
    {
        token.reset( new IncrementOrDecrementOperator( Op::INCREMENT ) );
        return true;
    }

    // Try to parse --
    if( parser.ExpectTerminal( TerminalType::DECREMENT ) )
    {
        token.reset( new IncrementOrDecrementOperator( Op::DECREMENT ) );
        return true;
    }

    return false;
}

} // namespace Compiler
} // namespace JoeLang
<|endoftext|>


<commit_before>class Solution {
public:
    int getMoneyAmount(int n) {
        vector<vector<int>> cache(n + 1, vector<int>(n + 1, 0));
        return myDP(1, n, cache);
    }

private:
    int myDP(int i, int j, vector<vector<int>>& cache) {
        if (i >= j) return 0;
        if (cache[i][j] != 0) return cache[i][j];

        int minMax = numeric_limits<int>::max(), maxS;
        for (int x = i; x <= j; ++x) {
            maxS = x + max(myDP(i, x - 1, cache), myDP(x + 1, j, cache));
            minMax = min(minMax, maxS);
        }

        cache[i][j] = minMax;
        return minMax;
    }
};
<commit_msg>update solution<commit_after>class Solution {
public:
    int getMoneyAmount(int n) {
        vector<vector<int>> cache(n + 1, vector<int>(n + 1, 0));
        return myDP(1, n, cache);
    }

private:
    int myDP(int i, int j, vector<vector<int>>& cache) {
        if (i >= j) return 0;
        if (cache[i][j] != 0) return cache[i][j];

        int minMax = numeric_limits<int>::max(), maxS;
        for (int x = i; x <= j; ++x) {
            maxS = x + max(myDP(i, x - 1, cache), myDP(x + 1, j, cache));
            minMax = min(minMax, maxS);
        }

        cache[i][j] = minMax;
        return minMax;
    }
};

// miniMax
// state: int (begin, end);
class Solution {
public:
    int getMoneyAmount(int n) {
        vector<vector<int>> cache(n + 1, vector<int>(n + 1, 0));
        return myMiniMax(1, n, cache);
    }

private:
    int myMiniMax(int begin, int end, vector<vector<int>>& cache) {
        if (begin >= end) return 0;
        if (begin + 1 == end) return begin;

        if (cache[begin][end] != 0) return cache[begin][end];

        int maxMoney, minMaxMoney = INT_MAX;
        for (int i = begin + 1; i < end; ++i) {
            maxMoney = i + max(myMiniMax(begin, i - 1, cache), myMiniMax(i + 1, end, cache));
            if (minMaxMoney > maxMoney) minMaxMoney = maxMoney;
        }

        cache[begin][end] = minMaxMoney;
        return minMaxMoney;
    }
};
<|endoftext|>


<commit_before>//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "JITRegistrar.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"

using namespace llvm;

// This must be kept in sync with gdb/gdb/jit.h .
extern "C" {

  typedef enum {
    JIT_NOACTION = 0,
    JIT_REGISTER_FN,
    JIT_UNREGISTER_FN
  } jit_actions_t;

  struct jit_code_entry {
    struct jit_code_entry *next_entry;
    struct jit_code_entry *prev_entry;
    const char *symfile_addr;
    uint64_t symfile_size;
  };

  struct jit_descriptor {
    uint32_t version;
    // This should be jit_actions_t, but we want to be specific about the
    // bit-width.
    uint32_t action_flag;
    struct jit_code_entry *relevant_entry;
    struct jit_code_entry *first_entry;
  };

  // We put information about the JITed function in this global, which the
  // debugger reads.  Make sure to specify the version statically, because the
  // debugger checks the version before we can set it during runtime.
  struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };

  // Debuggers puts a breakpoint in this function.
  LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
    // The noinline and the asm prevent calls to this function from being
    // optimized out.
#if !defined(_MSC_VER)
    asm volatile("":::"memory");
#endif
  }

}

namespace {

// Buffer for an in-memory object file in executable memory
typedef llvm::DenseMap< const char*,
                        std::pair<std::size_t, jit_code_entry*> >
  RegisteredObjectBufferMap;

/// Global access point for the JIT debugging interface designed for use with a
/// singleton toolbox. Handles thread-safe registration and deregistration of
/// object files that are in executable memory managed by the client of this
/// class.
class GDBJITRegistrar : public JITRegistrar {
  /// A map of in-memory object files that have been registered with the
  /// JIT interface.
  RegisteredObjectBufferMap ObjectBufferMap;

public:
  /// Instantiates the JIT service.
  GDBJITRegistrar() : ObjectBufferMap() {}

  /// Unregisters each object that was previously registered and releases all
  /// internal resources.
  virtual ~GDBJITRegistrar();

  /// Creates an entry in the JIT registry for the buffer @p Object,
  /// which must contain an object file in executable memory with any
  /// debug information for the debugger.
  void registerObject(const ObjectBuffer &Object) override;

  /// Removes the internal registration of @p Object, and
  /// frees associated resources.
  /// Returns true if @p Object was found in ObjectBufferMap.
  bool deregisterObject(const ObjectBuffer &Object) override;

private:
  /// Deregister the debug info for the given object file from the debugger
  /// and delete any temporary copies.  This private method does not remove
  /// the function from Map so that it can be called while iterating over Map.
  void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
};

/// Lock used to serialize all jit registration events, since they
/// modify global variables.
llvm::sys::Mutex JITDebugLock;

/// Acquire the lock and do the registration.
void NotifyDebugger(jit_code_entry* JITCodeEntry) {
  llvm::MutexGuard locked(JITDebugLock);
  __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;

  // Insert this entry at the head of the list.
  JITCodeEntry->prev_entry = NULL;
  jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry;
  JITCodeEntry->next_entry = NextEntry;
  if (NextEntry != NULL) {
    NextEntry->prev_entry = JITCodeEntry;
  }
  __jit_debug_descriptor.first_entry = JITCodeEntry;
  __jit_debug_descriptor.relevant_entry = JITCodeEntry;
  __jit_debug_register_code();
}

GDBJITRegistrar::~GDBJITRegistrar() {
  // Free all registered object files.
 for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end();
       I != E; ++I) {
    // Call the private method that doesn't update the map so our iterator
    // doesn't break.
    deregisterObjectInternal(I);
  }
  ObjectBufferMap.clear();
}

void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {

  const char *Buffer = Object.getBufferStart();
  size_t      Size = Object.getBufferSize();

  assert(Buffer && "Attempt to register a null object with a debugger.");
  assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() &&
         "Second attempt to perform debug registration.");
  jit_code_entry* JITCodeEntry = new jit_code_entry();

  if (JITCodeEntry == 0) {
    llvm::report_fatal_error(
      "Allocation failed when registering a JIT entry!\n");
  }
  else {
    JITCodeEntry->symfile_addr = Buffer;
    JITCodeEntry->symfile_size = Size;

    ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry);
    NotifyDebugger(JITCodeEntry);
  }
}

bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) {
  const char *Buffer = Object.getBufferStart();
  RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);

  if (I != ObjectBufferMap.end()) {
    deregisterObjectInternal(I);
    ObjectBufferMap.erase(I);
    return true;
  }
  return false;
}

void GDBJITRegistrar::deregisterObjectInternal(
    RegisteredObjectBufferMap::iterator I) {

  jit_code_entry*& JITCodeEntry = I->second.second;

  // Acquire the lock and do the unregistration.
  {
    llvm::MutexGuard locked(JITDebugLock);
    __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;

    // Remove the jit_code_entry from the linked list.
    jit_code_entry* PrevEntry = JITCodeEntry->prev_entry;
    jit_code_entry* NextEntry = JITCodeEntry->next_entry;

    if (NextEntry) {
      NextEntry->prev_entry = PrevEntry;
    }
    if (PrevEntry) {
      PrevEntry->next_entry = NextEntry;
    }
    else {
      assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
      __jit_debug_descriptor.first_entry = NextEntry;
    }

    // Tell the debugger which entry we removed, and unregister the code.
    __jit_debug_descriptor.relevant_entry = JITCodeEntry;
    __jit_debug_register_code();
  }

  delete JITCodeEntry;
  JITCodeEntry = NULL;
}

} // end namespace

namespace llvm {

JITRegistrar& JITRegistrar::getGDBRegistrar() {
  static GDBJITRegistrar* sRegistrar = NULL;
  if (sRegistrar == NULL) {
    // The mutex is here so that it won't slow down access once the registrar
    // is instantiated
    llvm::MutexGuard locked(JITDebugLock);
    // Check again to be sure another thread didn't create this while we waited
    if (sRegistrar == NULL) {
      sRegistrar = new GDBJITRegistrar;
    }
  }
  return *sRegistrar;
}

} // namespace llvm
<commit_msg>Make GDBJITRegistrar thread safe. Patch by Jim Kearyn, with cleanup by Ivan Puzyrevskiy.<commit_after>//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "JITRegistrar.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/ManagedStatic.h"

using namespace llvm;

// This must be kept in sync with gdb/gdb/jit.h .
extern "C" {

  typedef enum {
    JIT_NOACTION = 0,
    JIT_REGISTER_FN,
    JIT_UNREGISTER_FN
  } jit_actions_t;

  struct jit_code_entry {
    struct jit_code_entry *next_entry;
    struct jit_code_entry *prev_entry;
    const char *symfile_addr;
    uint64_t symfile_size;
  };

  struct jit_descriptor {
    uint32_t version;
    // This should be jit_actions_t, but we want to be specific about the
    // bit-width.
    uint32_t action_flag;
    struct jit_code_entry *relevant_entry;
    struct jit_code_entry *first_entry;
  };

  // We put information about the JITed function in this global, which the
  // debugger reads.  Make sure to specify the version statically, because the
  // debugger checks the version before we can set it during runtime.
  struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };

  // Debuggers puts a breakpoint in this function.
  LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
    // The noinline and the asm prevent calls to this function from being
    // optimized out.
#if !defined(_MSC_VER)
    asm volatile("":::"memory");
#endif
  }

}

namespace {

// Buffer for an in-memory object file in executable memory
typedef llvm::DenseMap< const char*,
                        std::pair<std::size_t, jit_code_entry*> >
  RegisteredObjectBufferMap;

/// Global access point for the JIT debugging interface designed for use with a
/// singleton toolbox. Handles thread-safe registration and deregistration of
/// object files that are in executable memory managed by the client of this
/// class.
class GDBJITRegistrar : public JITRegistrar {
  /// A map of in-memory object files that have been registered with the
  /// JIT interface.
  RegisteredObjectBufferMap ObjectBufferMap;

public:
  /// Instantiates the JIT service.
  GDBJITRegistrar() : ObjectBufferMap() {}

  /// Unregisters each object that was previously registered and releases all
  /// internal resources.
  virtual ~GDBJITRegistrar();

  /// Creates an entry in the JIT registry for the buffer @p Object,
  /// which must contain an object file in executable memory with any
  /// debug information for the debugger.
  void registerObject(const ObjectBuffer &Object) override;

  /// Removes the internal registration of @p Object, and
  /// frees associated resources.
  /// Returns true if @p Object was found in ObjectBufferMap.
  bool deregisterObject(const ObjectBuffer &Object) override;

private:
  /// Deregister the debug info for the given object file from the debugger
  /// and delete any temporary copies.  This private method does not remove
  /// the function from Map so that it can be called while iterating over Map.
  void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
};

/// Lock used to serialize all jit registration events, since they
/// modify global variables.
llvm::sys::Mutex JITDebugLock;

/// Do the registration.
void NotifyDebugger(jit_code_entry* JITCodeEntry) {
  __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;

  // Insert this entry at the head of the list.
  JITCodeEntry->prev_entry = NULL;
  jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry;
  JITCodeEntry->next_entry = NextEntry;
  if (NextEntry != NULL) {
    NextEntry->prev_entry = JITCodeEntry;
  }
  __jit_debug_descriptor.first_entry = JITCodeEntry;
  __jit_debug_descriptor.relevant_entry = JITCodeEntry;
  __jit_debug_register_code();
}

GDBJITRegistrar::~GDBJITRegistrar() {
  // Free all registered object files.
  llvm::MutexGuard locked(JITDebugLock);
  for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end();
       I != E; ++I) {
    // Call the private method that doesn't update the map so our iterator
    // doesn't break.
    deregisterObjectInternal(I);
  }
  ObjectBufferMap.clear();
}

void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) {

  const char *Buffer = Object.getBufferStart();
  size_t      Size = Object.getBufferSize();

  assert(Buffer && "Attempt to register a null object with a debugger.");
  llvm::MutexGuard locked(JITDebugLock);
  assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() &&
         "Second attempt to perform debug registration.");
  jit_code_entry* JITCodeEntry = new jit_code_entry();

  if (JITCodeEntry == 0) {
    llvm::report_fatal_error(
      "Allocation failed when registering a JIT entry!\n");
  }
  else {
    JITCodeEntry->symfile_addr = Buffer;
    JITCodeEntry->symfile_size = Size;

    ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry);
    NotifyDebugger(JITCodeEntry);
  }
}

bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) {
  const char *Buffer = Object.getBufferStart();
  llvm::MutexGuard locked(JITDebugLock);
  RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer);

  if (I != ObjectBufferMap.end()) {
    deregisterObjectInternal(I);
    ObjectBufferMap.erase(I);
    return true;
  }
  return false;
}

void GDBJITRegistrar::deregisterObjectInternal(
    RegisteredObjectBufferMap::iterator I) {

  jit_code_entry*& JITCodeEntry = I->second.second;

  // Do the unregistration.
  {
    __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;

    // Remove the jit_code_entry from the linked list.
    jit_code_entry* PrevEntry = JITCodeEntry->prev_entry;
    jit_code_entry* NextEntry = JITCodeEntry->next_entry;

    if (NextEntry) {
      NextEntry->prev_entry = PrevEntry;
    }
    if (PrevEntry) {
      PrevEntry->next_entry = NextEntry;
    }
    else {
      assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
      __jit_debug_descriptor.first_entry = NextEntry;
    }

    // Tell the debugger which entry we removed, and unregister the code.
    __jit_debug_descriptor.relevant_entry = JITCodeEntry;
    __jit_debug_register_code();
  }

  delete JITCodeEntry;
  JITCodeEntry = NULL;
}

llvm::ManagedStatic<GDBJITRegistrar> TheRegistrar;

} // end namespace

namespace llvm {

JITRegistrar& JITRegistrar::getGDBRegistrar() {
  return *TheRegistrar;
}

} // namespace llvm
<|endoftext|>