text:
#include "Compiler.h"
#include "CompilerContext.h"
#include "Types/Function.h"

#include "Lexer.h"
#include "Expressions.h"
#include "DeclarationExpressions.h"

#ifdef _DEBUG
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif  // _DEBUG

using namespace Jet;

CompilerContext* CompilerContext::AddFunction(const std::string& fname, Type* ret, const std::vector<std::pair<Type*, std::string>>& args, Type* member, bool lambda)
{
	Function* func = 0;
	if (member)
	{
		//ok, if member just pass the type so we dont have to do this crap
		int i = member->name.length() + 2;
		std::string fname2 = fname.substr(++i, fname.length() - i);

		auto range = member->data->functions.equal_range(fname2);
		for (auto ii = range.first; ii != range.second; ii++)
		{
			//printf("found option for %s with %i args\n", fname.c_str(), ii->second->argst.size());
			if (ii->second->arguments.size() == args.size())
			{
				func = ii->second;
			}
		}
	}
	else
	{
		func = root->ns->GetFunction(fname);
		if (!func)
		{
			//no function exists, create it
			func = new Function(fname, lambda);
			func->return_type = ret;
			func->arguments = args;

			if (member == false)
				this->root->ns->members.insert({ fname, func });
		}
	}

	func->Load(this->root);

	auto n = new CompilerContext(this->root, this);
	n->function = func;
	func->context = n;
	llvm::BasicBlock *bb = llvm::BasicBlock::Create(root->context, "entry", n->function->f);
	root->builder.SetInsertPoint(bb);

	// Do not export lambdas
	if (lambda)
		func->do_export = false;

	return n;
}

CValue CompilerContext::UnaryOperation(TokenType operation, CValue value)
{
	llvm::Value* res = 0;

	if (operation == TokenType::BAnd)
	{
		//this should already have been done elsewhere, so error
		assert(false);
	}

	if (value.type->type == Types::Float || value.type->type == Types::Double)
	{
		switch (operation)
		{
		case TokenType::Minus:
			res = root->builder.CreateFNeg(value.val);
			break;
		default:
			this->root->Error("Invalid Unary Operation '" + TokenToString[operation] + "' On Type '" + value.type->ToString() + "'", *current_token);
			break;
		}

		return CValue(value.type, res);
	}
	else if (value.type->IsInteger())//value.type->type == Types::Int || value.type->type == Types::Short || value.type->type == Types::Char)
	{
		//integer probably
		switch (operation)
		{
		case TokenType::Increment:
			res = root->builder.CreateAdd(value.val, root->builder.getInt32(1));
			break;
		case TokenType::Decrement:
			res = root->builder.CreateSub(value.val, root->builder.getInt32(1));
			break;
		case TokenType::Minus:
			res = root->builder.CreateNeg(value.val);
			break;
		case TokenType::BNot:
			res = root->builder.CreateNot(value.val);
			break;
		default:
			this->root->Error("Invalid Unary Operation '" + TokenToString[operation] + "' On Type '" + value.type->ToString() + "'", *current_token);
			break;
		}

		return CValue(value.type, res);
	}
	else if (value.type->type == Types::Pointer)
	{
		switch (operation)
		{
		case TokenType::Asterisk:
			return CValue(value.type->base, this->root->builder.CreateLoad(value.val), value.val);
		case TokenType::Increment:
			return CValue(value.type, this->root->builder.CreateGEP(value.val, root->builder.getInt32(1)));
		case TokenType::Decrement:
			return CValue(value.type, this->root->builder.CreateGEP(value.val, root->builder.getInt32(-1)));
		default:
			this->root->Error("Invalid Unary Operation '" + TokenToString[operation] + "' On Type '" + value.type->base->ToString() + "'", *current_token);
		}

	}
	else if (value.type->type == Types::Bool)
	{
		switch (operation)
		{
		case TokenType::Not:
			return CValue(value.type, this->root->builder.CreateNot(value.val));
		default:
			break;
		}
	}
	this->root->Error("Invalid Unary Operation '" + TokenToString[operation] + "' On Type '" + value.type->ToString() + "'", *current_token);
}

void CompilerContext::Store(CValue loc, CValue val, bool RVO)
{
	if (loc.type->base->type == Types::Struct && RVO == false)
	{
		if (loc.type->base->data->is_class == true)
			this->root->Error("Cannot copy class '" + loc.type->base->data->name + "' unless it has a copy operator.", *this->current_token);

		// Handle equality operator if we can find it
		auto funiter = val.type->data->functions.find("=");
		//todo: search through multimap to find one with the right number of args
		if (funiter != val.type->data->functions.end() && funiter->second->arguments.size() == 2)
		{
			llvm::Value* pointer = val.pointer;
			if (val.pointer == 0)//its a value type (return value)
			{
				//ok, lets be dumb
				//copy it to an alloca
				auto TheFunction = this->function->f;
				llvm::IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
					TheFunction->getEntryBlock().begin());
				pointer = TmpB.CreateAlloca(val.type->GetLLVMType(), 0, "return_pass_tmp");
				this->root->builder.CreateStore(val.val, pointer);
			}

			Function* fun = funiter->second;
			fun->Load(this->root);
			std::vector<CValue> argsv = { loc, CValue(loc.type, pointer) };

			fun->Call(this, argsv, true);

			if (pointer != val.pointer)
			{
				//destruct temp one
				this->Destruct(CValue(val.type->GetPointerType(), pointer), 0);
			}
			return;
		}
	}

	auto vall = this->DoCast(loc.type->base, val);

	// Handle copying
	if (loc.type->base->type == Types::Struct)
	{
		if (vall.val)
		{
			llvm::Instruction* I = llvm::dyn_cast<llvm::Instruction>(vall.val);
			I->eraseFromParent();// remove the load so we dont freak out llvm doing a struct copy
		}
		auto dptr = root->builder.CreatePointerCast(loc.val, root->CharPointerType->GetLLVMType());
		auto sptr = root->builder.CreatePointerCast(vall.pointer, root->CharPointerType->GetLLVMType());
		root->builder.CreateMemCpy(dptr, sptr, loc.type->base->GetSize(), 1);
		return;
	}
	else if (loc.type->base->type == Types::InternalArray)
	{
		llvm::Instruction* I = llvm::dyn_cast<llvm::Instruction>(vall.val);
		I->eraseFromParent();// remove the load so we dont freak out llvm doing a struct copy
		auto dptr = root->builder.CreatePointerCast(loc.val, root->CharPointerType->GetLLVMType());
		auto sptr = root->builder.CreatePointerCast(vall.pointer, root->CharPointerType->GetLLVMType());
		root->builder.CreateMemCpy(dptr, sptr, loc.type->base->GetSize(), 1);
		return;
	}

	root->builder.CreateStore(vall.val, loc.val);
}

CValue CompilerContext::BinaryOperation(Jet::TokenType op, CValue left, CValue lhsptr, CValue right)
{
	llvm::Value* res = 0;

	if (left.type->type == Types::Pointer && right.type->IsInteger())
	{
		//ok, lets just do a GeP
		if (op == TokenType::Plus)
			return CValue(left.type, this->root->builder.CreateGEP(left.val, right.val));
		else if (op == TokenType::Minus)
			return CValue(left.type, this->root->builder.CreateGEP(left.val, this->root->builder.CreateNeg(right.val)));
	}
	else if (left.type->type == Types::Struct)
	{
		//operator overloads
		const static std::map<Jet::TokenType, std::string> token_to_string = {
			{ TokenType::Plus, "+" },
			{ TokenType::Minus, "-" },
			{ TokenType::Slash, "/" },
			{ TokenType::Asterisk, "*" },
			{ TokenType::LeftShift, "<<" },
			{ TokenType::RightShift, ">>" },
			{ TokenType::BAnd, "&" },
			{ TokenType::BOr, "|" },
			{ TokenType::Xor, "^" },
			{ TokenType::Modulo, "%" },
			{ TokenType::LessThan, "<" },
			{ TokenType::GreaterThan, ">" },
			{ TokenType::LessThanEqual, "<=" },
			{ TokenType::GreaterThanEqual, ">=" }
		};
		auto res = token_to_string.find(op);
		if (res != token_to_string.end())
		{
			auto funiter = left.type->data->functions.find(res->second);
			//todo: search through multimap to find one with the right number of args
			//check args
			if (funiter != left.type->data->functions.end() && funiter->second->arguments.size() == 2)
			{
				Function* fun = funiter->second;
				fun->Load(this->root);
				std::vector<CValue> argsv = { lhsptr, right };
				return fun->Call(this, argsv, true);//for now lets keep these operators non-virtual
			}
		}
	}

	//try to do a cast
	right = this->DoCast(left.type, right);

	if (left.type->type != right.type->type)
	{
		root->Error("Cannot perform a binary operation between two incompatible types", *this->current_token);
	}

	if (left.type->type == Types::Float || left.type->type == Types::Double)
	{
		switch (op)
		{
		case TokenType::AddAssign:
		case TokenType::Plus:
			res = root->builder.CreateFAdd(left.val, right.val);
			break;
		case TokenType::SubtractAssign:
		case TokenType::Minus:
			res = root->builder.CreateFSub(left.val, right.val);
			break;
		case TokenType::MultiplyAssign:
		case TokenType::Asterisk:
			res = root->builder.CreateFMul(left.val, right.val);
			break;
		case TokenType::DivideAssign:
		case TokenType::Slash:
			res = root->builder.CreateFDiv(left.val, right.val);
			break;
		case TokenType::LessThan:
			//use U or O?
			res = root->builder.CreateFCmpULT(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::LessThanEqual:
			res = root->builder.CreateFCmpULE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::GreaterThan:
			res = root->builder.CreateFCmpUGT(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::GreaterThanEqual:
			res = root->builder.CreateFCmpUGE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::Equals:
			res = root->builder.CreateFCmpUEQ(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::NotEqual:
			res = root->builder.CreateFCmpUNE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		default:
			this->root->Error("Invalid Binary Operation '" + TokenToString[op] + "' On Type '" + left.type->ToString() + "'", *current_token);

			break;
		}

		return CValue(left.type, res);
	}
	else if (left.type->IsInteger())
	{
		//integer probably
		switch (op)
		{
		case TokenType::AddAssign:
		case TokenType::Plus:
			res = root->builder.CreateAdd(left.val, right.val);
			break;
		case TokenType::SubtractAssign:
		case TokenType::Minus:
			res = root->builder.CreateSub(left.val, right.val);
			break;
		case TokenType::MultiplyAssign:
		case TokenType::Asterisk:
			res = root->builder.CreateMul(left.val, right.val);
			break;
		case TokenType::DivideAssign:
		case TokenType::Slash:
			if (left.type->IsSignedInteger())//signed
				res = root->builder.CreateSDiv(left.val, right.val);
			else//unsigned
				res = root->builder.CreateUDiv(left.val, right.val);
			break;
		case TokenType::Modulo:
			if (left.type->IsSignedInteger())//signed
				res = root->builder.CreateSRem(left.val, right.val);
			else//unsigned
				res = root->builder.CreateURem(left.val, right.val);
			break;
		case TokenType::LessThan:
			//use U or S?
			if (left.type->IsSignedInteger())
				res = root->builder.CreateICmpSLT(left.val, right.val);
			else
				res = root->builder.CreateICmpULT(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::LessThanEqual:
			if (left.type->IsSignedInteger())
				res = root->builder.CreateICmpSLE(left.val, right.val);
			else
				res = root->builder.CreateICmpULE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::GreaterThan:
			if (left.type->IsSignedInteger())
				res = root->builder.CreateICmpSGT(left.val, right.val);
			else
				res = root->builder.CreateICmpUGT(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::GreaterThanEqual:
			if (left.type->IsSignedInteger())
				res = root->builder.CreateICmpSGE(left.val, right.val);
			else
				res = root->builder.CreateICmpUGE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::Equals:
			res = root->builder.CreateICmpEQ(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::NotEqual:
			res = root->builder.CreateICmpNE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::BAnd:
		case TokenType::AndAssign:
			res = root->builder.CreateAnd(left.val, right.val);
			break;
		case TokenType::BOr:
		case TokenType::OrAssign:
			res = root->builder.CreateOr(left.val, right.val);
			break;
		case TokenType::Xor:
		case TokenType::XorAssign:
			res = root->builder.CreateXor(left.val, right.val);
			break;
		case TokenType::LeftShift:
			res = root->builder.CreateShl(left.val, right.val);
			break;
		case TokenType::RightShift:
			res = root->builder.CreateLShr(left.val, right.val);
			break;
		default:
			this->root->Error("Invalid Binary Operation '" + TokenToString[op] + "' On Type '" + left.type->ToString() + "'", *current_token);

			break;
		}

		return CValue(left.type, res);
	}
	else if (left.type->type == Types::Pointer)
	{
		//com
		switch (op)
		{
		case TokenType::Equals:
			res = root->builder.CreateICmpEQ(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		case TokenType::NotEqual:
			res = root->builder.CreateICmpNE(left.val, right.val);
			return CValue(root->BoolType, res);
			break;
		}
	}

	this->root->Error("Invalid Binary Operation '" + TokenToString[op] + "' On Type '" + left.type->ToString() + "'", *current_token);
}

Function* CompilerContext::GetMethod(const std::string& name, const std::vector<Type*>& args, Type* Struct)
{
	Function* fun = 0;

	if (Struct == 0)
	{
		//global function?
		auto iter = this->root->GetFunction(name);
		if (iter == 0)
		{
			//check if its a type, if so try and find a constructor
			auto type = this->root->TryLookupType(name);
			if (type != 0 && type->type == Types::Struct)
			{
				type->Load(this->root);
				//look for a constructor
				//if we are template, remove the templated part
				auto tmp_name = name;
				if (name.back() == '>')
					tmp_name = name.substr(0, name.find_first_of('<'));
				auto range = type->data->functions.equal_range(tmp_name);
				for (auto ii = range.first; ii != range.second; ii++)
				{
					if (ii->second->arguments.size() == args.size() + 1)
						fun = ii->second;
				}
				if (fun)
				{
					return fun;
				}
			}
		}

		if (name[name.length() - 1] == '>')//its a template
		{
			int i = name.find_first_of('<');
			auto base_name = name.substr(0, i);

			//auto range = this->root->functions.equal_range(name);
			auto type = this->root->LookupType(name);

			if (type)
			{
				auto fun = type->data->functions.find(type->data->template_base->name);
				if (fun != type->data->functions.end())
					return fun->second;
				else
					return 0;
			}
			//instantiate here
			this->root->Error("Not implemented", *this->current_token);

			//return range.first->second;
		}

		//look for the best one
		fun = this->root->GetFunction(name, args);

		if (fun && fun->templates.size() > 0)
		{
			auto templates = new Type*[fun->templates.size()];
			for (unsigned int i = 0; i < fun->templates.size(); i++)
				templates[i] = 0;

			//need to infer
			if (fun->arguments.size() > 0)
			{
				int i = 0;
				for (auto ii : fun->templates)
				{
					//look for stuff in args
					int i2 = 0;
					for (auto iii : fun->arguments)
					{
						//get the name of the variable
						unsigned int subl = 0;
						for (; subl < iii.first->name.length(); subl++)
						{
							if (!IsLetter(iii.first->name[subl]))//todo this might break with numbers in variable names
								break;
						}
						//check if it refers to same type
						std::string sub = iii.first->name.substr(0, subl);
						//check if it refers to this type
						if (sub/*iii.first->name*/ == ii.second)
						{
							//found it
							if (templates[i] != 0 && templates[i] != args[i2])
								this->root->Error("Could not infer template type", *this->current_token);

							//need to convert back to root type
							Type* top_type = args[i2];
							Type* cur_type = args[i2];
							//work backwards to get to the type
							int pos = iii.first->name.size() - 1;
							while (pos >= 0)
							{
								char c = iii.first->name[pos];
								if (c == '*' && cur_type->type == Types::Pointer)
									cur_type = cur_type->base;
								else if (!IsLetter(c))
									this->root->Error("Could not infer template type", *this->current_token);
								pos--;
							}
							templates[i] = cur_type;
						}
						i2++;
					}
					i++;
				}
			}

			for (unsigned int i = 0; i < fun->templates.size(); i++)
			{
				if (templates[i] == 0)
					this->root->Error("Could not infer template type", *this->current_token);
			}

			auto oldname = fun->expression->name.text;
			fun->expression->name.text += '<';
			for (unsigned int i = 0; i < fun->templates.size(); i++)
			{
				fun->expression->name.text += templates[i]->ToString();
				if (i + 1 < fun->templates.size())
					fun->expression->name.text += ',';
			}
			fun->expression->name.text += '>';
			auto rname = fun->expression->name.text;

			//register the types
			int i = 0;
			for (auto ii : fun->templates)
			{
				//check if traits match
				if (templates[i]->MatchesTrait(this->root, ii.first->trait) == false)
					root->Error("Type '" + templates[i]->name + "' doesn't match Trait '" + ii.first->name + "'", *root->current_function->current_token);

				root->ns->members.insert({ ii.second, templates[i++] });
			}

			//store then restore insertion point
			auto rp = root->builder.GetInsertBlock();
			auto dp = root->builder.getCurrentDebugLocation();

			fun->expression->CompileDeclarations(this);
			fun->expression->DoCompile(this);

			root->builder.SetCurrentDebugLocation(dp);
			if (rp)
				root->builder.SetInsertPoint(rp);

			fun->expression->name.text = oldname;

			//time to recompile and stuff
			return root->ns->members.find(rname)->second.fn;
		}
		return fun;
	}
	else
	{
		return Struct->GetMethod(name, args, this);
	}
}

CValue CompilerContext::Call(const std::string& name, const std::vector<CValue>& args, Type* Struct, bool devirtualize)
{
	std::vector<Type*> arsgs;
	for (auto ii : args)
		arsgs.push_back(ii.type);

	auto old_tok = this->current_token;
	Function* fun = this->GetMethod(name, arsgs, Struct);
	this->current_token = old_tok;

	if (fun == 0 && Struct == 0)
	{
		//try and find something like a variable or constructor in the global namespace
		auto type = this->root->TryLookupType(name);
		if (type != 0 && type->type == Types::Struct)// If we found a type, call its constructor like a function
		{
			// Look for its constructor
			auto range = type->data->functions.equal_range(name);
			for (auto ii = range.first; ii != range.second; ii++)
			{
				if (ii->second->arguments.size() == args.size())
					fun = ii->second;
			}
			if (fun)
			{
				//ok, we allocate, call then
				//allocate thing
				type->Load(this->root);

				auto TheFunction = this->function->f;
				llvm::IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
					TheFunction->getEntryBlock().begin());
				auto Alloca = TmpB.CreateAlloca(type->GetLLVMType(), 0, "constructortemp");

				std::vector<llvm::Value*> argsv;
				int i = 1;
				argsv.push_back(Alloca);// add 'this' ptr
				for (auto ii : args)// add other arguments
					argsv.push_back(this->DoCast(fun->arguments[i++].first, ii).val);//try and cast to the correct type if we can

				fun->Load(this->root);

				this->root->builder.CreateCall(fun->f, argsv);

				return CValue(type, this->root->builder.CreateLoad(Alloca), Alloca);
			}
			else // Fake a constructor if we couldnt find one
			{
				type->Load(this->root);

				if (type->type == Types::Struct)
				{
					auto TheFunction = this->function->f;
					llvm::IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
						TheFunction->getEntryBlock().begin());
					auto Alloca = TmpB.CreateAlloca(type->GetLLVMType(), 0, "constructortemp");

					//store defaults here...
					return CValue(type, this->root->builder.CreateLoad(Alloca), Alloca);
				}

				return CValue(type, type->GetDefaultValue(this->root));
			}
		}
		else
		{
			//try to find it in variables
			auto var = this->GetVariable(name);

			if (var.type->type != Types::Function && (var.type->type != Types::Pointer || var.type->base->type != Types::Function))
			{
				if (var.type->type == Types::Pointer && var.type->base->type == Types::Struct && var.type->base->data->template_base && var.type->base->data->template_base->name == "function")
				{
					auto function_ptr = this->root->builder.CreateGEP(var.val, { this->root->builder.getInt32(0), this->root->builder.getInt32(0) }, "fptr");

					//get the template param to examine the type
					auto type = var.type->base->data->members.begin()->second.ty;// .find("T")->second.ty;

					if (args.size() != type->function->args.size())
						this->root->Error("Too many args in function call got " + std::to_string(args.size()) + " expected " + std::to_string(type->function->args.size()), *this->current_token);

					std::vector<llvm::Value*> argsv;
					for (unsigned int i = 0; i < args.size(); i++)
						argsv.push_back(this->DoCast(type->function->args[i], args[i]).val);//try and cast to the correct type if we can

					//add the data
					auto data_ptr = this->root->builder.CreateGEP(var.val, { this->root->builder.getInt32(0), this->root->builder.getInt32(1) });
					data_ptr = this->root->builder.CreateGEP(data_ptr, { this->root->builder.getInt32(0), this->root->builder.getInt32(0) });
					argsv.push_back(data_ptr);

					llvm::Value* fun = this->root->builder.CreateLoad(function_ptr);

					auto rtype = fun->getType()->getContainedType(0)->getContainedType(0);
					std::vector<llvm::Type*> fargs;
					for (unsigned int i = 1; i < fun->getType()->getContainedType(0)->getNumContainedTypes(); i++)
						fargs.push_back(fun->getType()->getContainedType(0)->getContainedType(i));
					fargs.push_back(this->root->builder.getInt8PtrTy());

					auto fp = llvm::FunctionType::get(rtype, fargs, false)->getPointerTo();
					fun = this->root->builder.CreatePointerCast(fun, fp);
					return CValue(type->function->return_type, this->root->builder.CreateCall(fun, argsv));
				}
				else
					this->root->Error("Cannot call non-function type", *this->current_token);
			}
			if (var.type->type == Types::Pointer && var.type->base->type == Types::Function)
			{
				var.val = this->root->builder.CreateLoad(var.val);
				var.type = var.type->base;
			}

			std::vector<llvm::Value*> argsv;
			for (unsigned int i = 0; i < args.size(); i++)
				argsv.push_back(this->DoCast(var.type->function->args[i], args[i]).val);//try and cast to the correct type if we can

			return CValue(var.type->function->return_type, this->root->builder.CreateCall(var.val, argsv));
		}
		this->root->Error("Function '" + name + "' with " + std::to_string(args.size()) + " arguments is not defined", *this->current_token);
	}
	else if (fun == 0)
	{
		this->root->Error("Function '" + name + "' is not defined on object '" + Struct->ToString() + "'", *this->current_token);
	}

	fun->Load(this->root);

	//todo: fixme this isnt a very reliable fix
	if (args.size() + (fun->return_type->type == Types::Struct ? 1 : 0) != fun->f->arg_size() && fun->arguments.size() > 0 && fun->arguments[0].second == "this")
	{
		//ok, we allocate, call then
		//allocate thing
		auto type = fun->arguments[0].first->base;
		type->Load(this->root);

		auto TheFunction = this->function->f;
		llvm::IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
			TheFunction->getEntryBlock().begin());

		auto Alloca = TmpB.CreateAlloca(type->GetLLVMType(), 0, "constructortemp");

		std::vector<llvm::Value*> argsv;
		int i = 1;

		//add struct
		argsv.push_back(Alloca);
		for (auto ii : args)
			argsv.push_back(this->DoCast(fun->arguments[i++].first, ii).val);//try and cast to the correct type if we can

		fun->Load(this->root);

		this->root->builder.CreateCall(fun->f, argsv);

		return CValue(type, this->root->builder.CreateLoad(Alloca));
	}
	else if (args.size() != fun->f->arg_size() && fun->return_type->type != Types::Struct)
	{
		this->root->Error("Function expected " + std::to_string(fun->f->arg_size()) + " arguments, got " + std::to_string(args.size()), *this->current_token);
	}

	std::vector<CValue> argsv;
	for (unsigned int i = 0; i < args.size(); i++)
		argsv.push_back(this->DoCast(fun->arguments[i].first, args[i]));//try and cast to the correct type if we can

	return fun->Call(this, argsv, devirtualize);
}

void CompilerContext::SetDebugLocation(const Token& t)
{
	assert(this->function->loaded);
	this->root->builder.SetCurrentDebugLocation(llvm::DebugLoc::get(t.line, t.column, this->function->scope));
}

CValue CompilerContext::GetVariable(const std::string& name)
{
	auto cur = this->scope;
	CValue value;
	do
	{
		auto iter = cur->named_values.find(name);
		if (iter != cur->named_values.end())
		{
			value = iter->second;
			break;
		}
		cur = cur->prev;
	} while (cur);

	if (value.type->type == Types::Void)
	{
		auto sym = this->root->GetVariableOrFunction(name);
		if (sym.type != SymbolType::Invalid)
		{
			if (sym.type == SymbolType::Function)
			{
				auto function = sym.fn;
				function->Load(this->root);
				return CValue(function->GetType(this->root), function->f);
			}
			else if (sym.type == SymbolType::Variable)
			{
				//variable
				return *sym.val;
			}
		}

		if (this->function->is_lambda)
		{
			auto var = this->parent->GetVariable(name);

			//look in locals above me
			CValue location = this->Load("_capture_data");
			auto storage_t = this->function->lambda.storage_type;

			//todo make sure this is the right location to do all of this
			//append the new type
			std::vector<llvm::Type*> types;
			for (unsigned int i = 0; i < this->captures.size(); i++)
				types.push_back(storage_t->getContainedType(i));

			types.push_back(var.type->base->GetLLVMType());
			storage_t = this->function->lambda.storage_type = storage_t->create(types);

			auto data = root->builder.CreatePointerCast(location.val, storage_t->getPointerTo());

			//load it, then store it as a local
			auto val = root->builder.CreateGEP(data, { root->builder.getInt32(0), root->builder.getInt32(this->captures.size()) });

			CValue value;
			value.val = root->builder.CreateAlloca(var.type->base->GetLLVMType());
			value.type = var.type;

			this->RegisterLocal(name, value);//need to register it as immutable

			root->builder.CreateStore(root->builder.CreateLoad(val), value.val);
			this->captures.push_back(name);

			return value;
		}

		this->root->Error("Undeclared identifier '" + name + "'", *current_token);
	}
	return value;
}

llvm::ReturnInst* CompilerContext::Return(CValue ret)
{
	if (this->function == 0)
	{
		this->root->Error("Cannot return from outside function!", *current_token);
	}

	// Call destructors
	auto cur = this->scope;
	do
	{
		if (cur->destructed == false)
		{
			cur->Destruct(this, ret.pointer);
		}

		cur->destructed = true;
		cur = cur->prev;
	} while (cur);

	if (ret.type->type == Types::Void)
	{
		return root->builder.CreateRetVoid();
	}
	else if (ret.type->type == Types::Struct)
	{
		llvm::Instruction* I = llvm::dyn_cast<llvm::Instruction>(ret.val);
		I->eraseFromParent();// remove the load so we dont freak out llvm doing a struct copy

		//do a memcpy
		auto dptr = root->builder.CreatePointerCast(this->function->f->arg_begin(), this->root->CharPointerType->GetLLVMType());
		auto sptr = root->builder.CreatePointerCast(ret.pointer, this->root->CharPointerType->GetLLVMType());
		root->builder.CreateMemCpy(dptr, sptr, ret.type->GetSize(), 1);
		return root->builder.CreateRetVoid();
	}

	// Try and cast to the return type if we can
	if (ret.val)
	{
		ret = this->DoCast(this->function->return_type, ret);
	}
	return root->builder.CreateRet(ret.val);
}

CValue CompilerContext::DoCast(Type* t, CValue value, bool Explicit)
{
	if (value.type->type == t->type && value.type->data == t->data)
		return value;

	llvm::Type* tt = t->GetLLVMType();
	if (value.type->type == Types::Float && t->type == Types::Double)
	{
		return CValue(t, root->builder.CreateFPExt(value.val, tt));
	}
	if (value.type->type == Types::Double && t->type == Types::Float)
	{
		// Todo warn for downcasting if implicit
		return CValue(t, root->builder.CreateFPTrunc(value.val, tt));
	}
	if (value.type->type == Types::Double || value.type->type == Types::Float)
	{
		//float to int
		if (t->IsSignedInteger())
			return CValue(t, root->builder.CreateFPToSI(value.val, tt));
		else if (t->IsInteger())
			return CValue(t, root->builder.CreateFPToUI(value.val, tt));

		//todo: maybe do a warning if implicit from float->int or larger as it cant directly fit 1 to 1
	}
	if (value.type->IsInteger())
	{
		//int to float
		if (t->type == Types::Double || t->type == Types::Float)
		{
			if (value.type->IsSignedInteger())
				return CValue(t, root->builder.CreateSIToFP(value.val, tt));
			else
				return CValue(t, root->builder.CreateUIToFP(value.val, tt));
		}
		if (t->type == Types::Bool)
			return CValue(t, root->builder.CreateIsNotNull(value.val));
		if (t->type == Types::Pointer)
		{
			llvm::ConstantInt* ty = llvm::dyn_cast<llvm::ConstantInt>(value.val);
			if (Explicit == false && (ty == 0 || ty->getSExtValue() != 0))
				root->Error("Cannot cast a non-zero integer value to pointer implicitly.", *this->current_token);

			return CValue(t, root->builder.CreateIntToPtr(value.val, t->GetLLVMType()));
		}

		if (t->IsSignedInteger())
			return CValue(t, root->builder.CreateSExtOrTrunc(value.val, tt));
		else if (t->IsInteger())
			return CValue(t, root->builder.CreateZExtOrTrunc(value.val, tt));
	}
	if (value.type->type == Types::Pointer)
	{
		if (t->type == Types::Bool)
			return CValue(t, root->builder.CreateIsNotNull(value.val));

		if (t->type == Types::Pointer && value.type->base->type == Types::Array && value.type->base->base == t->base)
			return CValue(t, root->builder.CreatePointerCast(value.val, t->GetLLVMType(), "arraycast"));

		if (value.type->base->type == Types::Struct && t->type == Types::Pointer && t->base->type == Types::Struct)
		{
			if (value.type->base->data->IsParent(t->base))
			{
				return CValue(t, root->builder.CreatePointerCast(value.val, t->GetLLVMType(), "ptr2ptr"));
			}
		}
		if (Explicit)
		{
			if (t->type == Types::Pointer)
			{
				return CValue(t, root->builder.CreatePointerCast(value.val, t->GetLLVMType(), "ptr2ptr"));
			}
			else if (t->IsInteger())
			{
				return CValue(t, root->builder.CreatePtrToInt(value.val, t->GetLLVMType(), "ptr2int"));
			}
		}
	}
	if (value.type->type == Types::InternalArray)
	{
		if (t->type == Types::Array && t->base == value.type->base)
		{
			// construct an array and use that
			auto str_type = root->GetArrayType(value.type->base);

			//alloc the struct for it
			auto Alloca = root->builder.CreateAlloca(str_type->GetLLVMType(), root->builder.getInt32(1), "into_array");

			auto size = root->builder.getInt32(value.type->size);

			//store size
			auto size_p = root->builder.CreateGEP(Alloca, { root->builder.getInt32(0), root->builder.getInt32(0) });
			root->builder.CreateStore(size, size_p);

			//store data pointer
			auto data_p = root->builder.CreateGEP(Alloca, { root->builder.getInt32(0), root->builder.getInt32(1) });

			auto data_v = root->builder.CreateGEP(value.pointer, { root->builder.getInt32(0), root->builder.getInt32(0) });
			//value.val->dump();
			//value.val->getType()->dump();
			//value.pointer->dump();
			//value.pointer->getType()->dump();
			root->builder.CreateStore(data_v, data_p);

			// todo do we need this load?
			return CValue(t, this->root->builder.CreateLoad(Alloca));
		}
	}
	if (value.type->type == Types::Array)
	{
		if (t->type == Types::Pointer)// array to pointer
		{
			if (t->base == value.type->base)
			{
				//ok for now lets not allow this, users can just access the ptr field
				/*std::vector<llvm::Value*> arr = { root->builder.getInt32(0), root->builder.getInt32(0) };

				this->f->dump();
				value.val->dump();
				value.val = root->builder.CreateGEP(value.val, arr, "array2ptr");
				value.val->dump();
				return CValue(t, value.val);*/
			}
		}
	}
	if (value.type->type == Types::Function)
	{
		if (t->type == Types::Function && t->function == value.type->function)
			return value;
		else if (Explicit && t->type == Types::Function)
			return CValue(t, this->root->builder.CreateBitOrPointerCast(value.val, tt));
	}
	if (t->type == Types::Union && value.type->type == Types::Struct)
	{
		for (unsigned int i = 0; i < t->_union->members.size(); i++)
		{
			if (t->_union->members[i] == value.type)
			{
				//Alloca the type, then store values in it and load. This is dumb but will work.
				auto alloc = this->root->builder.CreateAlloca(t->_union->type);

				//store type
				auto type = this->root->builder.CreateGEP(alloc, { this->root->builder.getInt32(0), this->root->builder.getInt32(0) });
				this->root->builder.CreateStore(this->root->builder.getInt32(i), type);

				//store data
				auto data = this->root->builder.CreateGEP(alloc, { this->root->builder.getInt32(0), this->root->builder.getInt32(1) });
				data = this->root->builder.CreatePointerCast(data, value.type->GetPointerType()->GetLLVMType());
				this->root->builder.CreateStore(value.val, data);

				//return the new value
				return CValue(t, this->root->builder.CreateLoad(alloc));
			}
		}
	}

	this->root->Error("Cannot cast '" + value.type->ToString() + "' to '" + t->ToString() + "'!", *current_token);
}

//reduce redundancy by making one general version that just omits the llvm::Value from the CValue when doign a check
bool CompilerContext::CheckCast(Type* src, Type* t, bool Explicit, bool Throw)
{
	CValue value;
	value.type = src;

	if (value.type->type == t->type && value.type->data == t->data)
		return true;

	if (value.type->type == Types::Float && t->type == Types::Double)
	{
		//lets do this
		return true;// CValue(t, root->builder.CreateFPExt(value.val, tt));
	}
	else if (value.type->type == Types::Double && t->type == Types::Float)
	{
		//lets do this
		return true;// CValue(t, root->builder.CreateFPTrunc(value.val, tt));
	}
	else if (value.type->type == Types::Double || value.type->type == Types::Float)
	{
		//float to int
		if (t->IsInteger())//t->type == Types::Int || t->type == Types::Short || t->type == Types::Char)
			return true;// CValue(t, root->builder.CreateFPToSI(value.val, tt));

		//remove me later float to bool
		//if (t->type == Types::Bool)
		//return CValue(t, root->builder.CreateFCmpONE(value.val, llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(0.0))));
	}
	if (value.type->IsInteger())//value.type->type == Types::Int || value.type->type == Types::Short || value.type->type == Types::Char)
	{
		//int to float
		if (t->type == Types::Double || t->type == Types::Float)
			return true;// CValue(t, root->builder.CreateSIToFP(value.val, tt));
		if (t->type == Types::Bool)
			return true;// CValue(t, root->builder.CreateIsNotNull(value.val));
		if (t->type == Types::Pointer)
		{
			//auto ty1 = value.val->getType()->getContainedType(0);
			//llvm::ConstantInt* ty = llvm::dyn_cast<llvm::ConstantInt>(value.val);
			//if (ty && Explicit == false && ty->getSExtValue() != 0)
			//	return false;// root->Error("Cannot cast a non-zero integer value to pointer implicitly.", *this->current_token);

			return true;
		}

		/*if (value.type->type == Types::Int && (t->type == Types::Char || t->type == Types::Short))
		{
		return CValue(t, root->builder.CreateTrunc(value.val, tt));
		}
		if (value.type->type == Types::Short && t->type == Types::Int)
		{
		return CValue(t, root->builder.CreateSExt(value.val, tt));
		}*/
		if (t->IsInteger())//t->type == Types::Int || t->type == Types::Short || t->type == Types::Char)
			return true;
	}
	if (value.type->type == Types::Pointer)
	{
		//pointer to bool
		if (t->type == Types::Bool)
			return true;

		if (t->type == Types::Pointer && value.type->base->type == Types::Array && value.type->base->base == t->base)
			return true;

		if (value.type->base->type == Types::Struct && t->type == Types::Pointer && t->base->type == Types::Struct)
		{
			if (value.type->base->data->IsParent(t->base))
			{
				return true;
			}
		}
		if (Explicit)
		{
			if (t->type == Types::Pointer)
			{
				//pointer to pointer cast;
				return true;
			}
			else if (t->IsInteger())
				return true;
		}
	}
	if (value.type->type == Types::Function)
	{
		if (t->type == Types::Function && t->function == value.type->function)
			return true;
		else if (Explicit && t->type == Types::Function)
			return true;
	}
	if (t->type == Types::Union && value.type->type == Types::Struct)
	{
		for (unsigned int i = 0; i < t->_union->members.size(); i++)
		{
			if (t->_union->members[i] == value.type)
				return true;
		}
	}

	//special check for traits
	if (value.type->type == Types::Trait && this->root->typecheck)
	{
		//this is a bad hack that doesnt catch all cases, but better than nothing
		auto traits = t->GetTraits(this->root);
		for (unsigned int i = 0; i < traits.size(); i++)
			if (traits[i].second->name == value.type->trait->name)// t->MatchesTrait(this->root, value.type->trait))
				return true;
	}

	//its a template arg
	if (this->root->typecheck && value.type->type == Types::Invalid)
	{
		return true;//once again, another hack that misses errors
	}

	if (Throw)
		this->root->Error("Cannot cast '" + value.type->ToString() + "' to '" + t->ToString() + "'!", *current_token);

	return false;
}

Scope* CompilerContext::PushScope()
{
	auto temp = this->scope;
	this->scope = new Scope;
	this->scope->prev = temp;

	temp->next.push_back(this->scope);
	return this->scope;
}

void Scope::Destruct(CompilerContext* context, llvm::Value* ignore)
{
	for (auto ii : this->named_values)
	{
		if (ii.second.val == ignore)
			continue;//dont destruct what we are returning
		if (ii.second.type->type == Types::Pointer && ii.second.type->base->type == Types::Struct)
			context->Destruct(ii.second, 0);
		//else if (ii.second.type->type == Types::Pointer && ii.second.type->base->type == Types::Array && ii.second.type->base->base->type == Types::Struct)
		//	context->Destruct(CValue(ii.second.type->base, ii.second.val), context->root->builder.getInt32(ii.second.type->base->size));
	}

	for (auto ii : this->to_destruct)
	{
		if (ii.type->type == Types::Pointer && ii.type->base->type == Types::Array && ii.type->base->base->type == Types::Struct)
		{
			auto loc = context->root->builder.CreateGEP(ii.val, { context->root->builder.getInt32(0), context->root->builder.getInt32(0) });
			auto size = context->root->builder.CreateLoad(loc);

			auto ptr = context->root->builder.CreateGEP(ii.val, { context->root->builder.getInt32(0), context->root->builder.getInt32(1) });
			ptr = context->root->builder.CreateLoad(ptr);
			context->Destruct(CValue(ii.type->base->GetPointerType() , ptr), size);
		}
	}
	this->destructed = true;
}

void CompilerContext::PopScope()
{
	//call destructors
	if (this->scope->prev != 0)
	{
		if (this->scope->destructed == false)
			this->scope->Destruct(this);

		this->scope->destructed = true;
	}

	auto temp = this->scope;
	this->scope = this->scope->prev;
}

void CompilerContext::WriteCaptures(llvm::Value* lambda)
{
	if (this->captures.size())
	{
		//allocate the function object
		std::vector<llvm::Type*> elements;
		for (auto ii : this->captures)
		{
			//this->CurrentToken(&ii);
			auto var = parent->GetVariable(ii);
			elements.push_back(var.type->base->GetLLVMType());
		}

		auto storage_t = llvm::StructType::get(this->root->context, elements);

		int size = 0;
		for (unsigned int i = 0; i < this->captures.size(); i++)
		{
			auto var = this->captures[i];

			//get pointer to data location
			auto ptr = root->builder.CreateGEP(lambda, { root->builder.getInt32(0), root->builder.getInt32(1) }, "lambda_data");
			ptr = root->builder.CreatePointerCast(ptr, storage_t->getPointerTo());
			ptr = root->builder.CreateGEP(ptr, { root->builder.getInt32(0), root->builder.getInt32(i) });

			//then store it
			auto val = parent->Load(var);
			size += val.type->GetSize();
			root->builder.CreateStore(val.val, ptr);
		}
		if (size > 64)
		{
			this->root->Error("Capture size too big! Captured " + std::to_string(size) + " bytes but max was 64!", *this->current_token);
		}
	}
	this->captures.clear();
}

CValue CompilerContext::Load(const std::string& name)
{
	CValue value = GetVariable(name);
	if (value.type->type == Types::Function || value.type->type == Types::Int)// last case is for constants
		return value;

	return CValue(value.type->base, root->builder.CreateLoad(value.val, name.c_str()), value.val);
}

void CompilerContext::Construct(CValue pointer, llvm::Value* arr_size)
{
	if (pointer.type->base->type == Types::Struct)
	{
		Type* ty = pointer.type->base;
		Function* fun = 0;
		if (ty->data->template_base)
			fun = ty->GetMethod(ty->data->template_base->name, { pointer.type }, this);
		else
			fun = ty->GetMethod(ty->data->name, { pointer.type }, this);
		if (fun == 0)
			return;//todo: is this right behavior?
		fun->Load(this->root);
		if (arr_size == 0)
		{//just one element, construct it
			this->root->builder.CreateCall(fun->f, { pointer.val });
		}
		else
		{//construct each child element
			llvm::Value* counter = this->root->builder.CreateAlloca(this->root->IntType->GetLLVMType(), 0, "newcounter");
			this->root->builder.CreateStore(this->Integer(0).val, counter);

			auto start = llvm::BasicBlock::Create(this->root->context, "start", this->root->current_function->function->f);
			auto body = llvm::BasicBlock::Create(this->root->context, "body", this->root->current_function->function->f);
			auto end = llvm::BasicBlock::Create(this->root->context, "end", this->root->current_function->function->f);

			this->root->builder.CreateBr(start);
			this->root->builder.SetInsertPoint(start);
			auto cval = this->root->builder.CreateLoad(counter, "curcount");
			auto res = this->root->builder.CreateICmpUGE(cval, arr_size);
			this->root->builder.CreateCondBr(res, end, body);

			this->root->builder.SetInsertPoint(body);
			if (pointer.type->type == Types::Array)
			{
				auto elementptr = this->root->builder.CreateGEP(pointer.val, { this->root->builder.getInt32(0), cval });
				this->root->builder.CreateCall(fun->f, { elementptr });
			}
			else
			{
				auto elementptr = this->root->builder.CreateGEP(pointer.val, { cval });
				this->root->builder.CreateCall(fun->f, { elementptr });
			}

			auto inc = this->root->builder.CreateAdd(cval, this->Integer(1).val);
			this->root->builder.CreateStore(inc, counter);

			this->root->builder.CreateBr(start);

			this->root->builder.SetInsertPoint(end);
		}
	}
}

void CompilerContext::Destruct(CValue pointer, llvm::Value* arr_size)
{
	if (pointer.type->base->type == Types::Struct)
	{
		Type* ty = pointer.type->base;
		Function* fun = 0;
		if (ty->data->template_base)
			fun = ty->GetMethod("~" + ty->data->template_base->name, { pointer.type }, this);
		else
			fun = ty->GetMethod("~" + ty->data->name, { pointer.type }, this);
		if (fun == 0)
			return;
		fun->Load(this->root);
		if (arr_size == 0)
		{//just one element, construct it
			this->root->builder.CreateCall(fun->f, { pointer.val });
		}
		else
		{//construct each child element
			llvm::Value* counter = this->root->builder.CreateAlloca(this->root->IntType->GetLLVMType(), 0, "newcounter");
			this->root->builder.CreateStore(this->Integer(0).val, counter);

			auto start = llvm::BasicBlock::Create(this->root->context, "start", this->root->current_function->function->f);
			auto body = llvm::BasicBlock::Create(this->root->context, "body", this->root->current_function->function->f);
			auto end = llvm::BasicBlock::Create(this->root->context, "end", this->root->current_function->function->f);

			this->root->builder.CreateBr(start);
			this->root->builder.SetInsertPoint(start);
			auto cval = this->root->builder.CreateLoad(counter, "curcount");
			auto res = this->root->builder.CreateICmpUGE(cval, arr_size);
			this->root->builder.CreateCondBr(res, end, body);

			this->root->builder.SetInsertPoint(body);
			if (pointer.type->type == Types::Array)
			{
				auto elementptr = this->root->builder.CreateGEP(pointer.val, { this->root->builder.getInt32(0), cval });
				this->root->builder.CreateCall(fun->f, { elementptr });
			}
			else
			{
				auto elementptr = this->root->builder.CreateGEP(pointer.val, { cval });
				this->root->builder.CreateCall(fun->f, { elementptr });
			}

			auto inc = this->root->builder.CreateAdd(cval, this->Integer(1).val);
			this->root->builder.CreateStore(inc, counter);

			this->root->builder.CreateBr(start);

			this->root->builder.SetInsertPoint(end);
		}
	}
}


text:
package uk.ac.ebi.phenotype.solr.indexer.beans;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Encapsulates an ontology termId, name, termId & name concatenated, and a list
 of synonyms.
 *
 * @author mrelac
 */
public class OntologyTermBean {
    private String id;
    private String name;
    private String definition;
    private List<String> synonyms=new ArrayList<>();

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public OntologyTermBean() {

    }

    public String getId() {
        return id;
    }

    public void setId(String termId) {
        this.id = termId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDefinition() {
        return definition;
    }

    public void setDefinition(String definition) {
        this.definition = definition;
    }

    public List<String> getSynonyms() {
        return synonyms;
    }

    public void setSynonyms(List<String> synonyms) {
        this.synonyms = synonyms;
    }

    // AUXILIARY METHODS

    /**
     * Returns a concatenation of term id and term name.
     * @return a concatenation of term id and term name, separated by a pair of
     * underscores. If either id or name is null, that null component is replaced
     * by an empty string.
     */
    public String getTermIdTermName() {
        String value = "";
        if (id != null)
            value += id;
        value += "__";
        if (name != null)
            value += name;

        return value;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 67 * hash + Objects.hashCode(this.id);
        hash = 67 * hash + Objects.hashCode(this.name);
        hash = 67 * hash + Objects.hashCode(this.definition);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final OntologyTermBean other = (OntologyTermBean) obj;
        if ( ! Objects.equals(this.id, other.id)) {
            return false;
        }
        if ( ! Objects.equals(this.name, other.name)) {
            return false;
        }
        if ( ! Objects.equals(this.definition, other.definition)) {
            return false;
        }
        return true;
    }
}

redpajama_set_name: RedPajamaGithub


text:
package storage

import (
	"context"
	"errors"
	"io"

	"github.com/distribution/distribution/v3/registry/storage/driver"
)

const (
	maxBlobGetSize = 4 << 20
)

func getContent(ctx context.Context, driver driver.StorageDriver, p string) ([]byte, error) {
	r, err := driver.Reader(ctx, p, 0)
	if err != nil {
		return nil, err
	}
	defer r.Close()

	return readAllLimited(r, maxBlobGetSize)
}

func readAllLimited(r io.Reader, limit int64) ([]byte, error) {
	r = limitReader(r, limit)
	return io.ReadAll(r)
}

// limitReader returns a new reader limited to n bytes. Unlike io.LimitReader,
// this returns an error when the limit reached.
func limitReader(r io.Reader, n int64) io.Reader {
	return &limitedReader{r: r, n: n}
}

// limitedReader implements a reader that errors when the limit is reached.
//
// Partially cribbed from net/http.MaxBytesReader.
type limitedReader struct {
	r   io.Reader // underlying reader
	n   int64     // max bytes remaining
	err error     // sticky error
}

func (l *limitedReader) Read(p []byte) (n int, err error) {
	if l.err != nil {
		return 0, l.err
	}
	if len(p) == 0 {
		return 0, nil
	}
	// If they asked for a 32KB byte read but only 5 bytes are
	// remaining, no need to read 32KB. 6 bytes will answer the
	// question of the whether we hit the limit or go past it.
	if int64(len(p)) > l.n+1 {
		p = p[:l.n+1]
	}
	n, err = l.r.Read(p)

	if int64(n) <= l.n {
		l.n -= int64(n)
		l.err = err
		return n, err
	}

	n = int(l.n)
	l.n = 0

	l.err = errors.New("storage: read exceeds limit")
	return n, l.err
}


text:
namespace sh
{

void RewriteElseBlocks(TIntermNode *node);

}

#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_


text:
package com.minsheng.flume.source;

import java.util.Map;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;

public class FileMapReaderWriter {
  private static final Logger LOG = LoggerFactory
      .getLogger(FileMapReaderWriter.class);
  private static String format_string_ = "# ${inode}\t${length}\t{$offset}\t${file_name}";
  private String file_name_;

  public FileMapReaderWriter() {
    file_name_ = null;
  }

  public void Configure(String name) {
    Preconditions.checkState(null != name && !name.isEmpty(),
        "Map meta record file must be specified");
    file_name_ = name;
    LOG.info("map_record_meta_file=" + file_name_);
  }

  public boolean ParseLine(String line, FileInfo file_info) {
    Preconditions.checkState(file_name_ != null,
        "Plz call Configure to initialize before call other functions");
    String eles[] = line.split(FileInfo.FIELD_SEPERATOR);
    if (eles.length != FileInfo.NUM_FIELDS) {
      LOG.warn("Invalid record line:" + line);
      return false;
    }
    try {
    file_info.set_file_name(eles[FileInfo.FILE_NAME_INDEX]);
    file_info.set_file_length((Long.valueOf(eles[FileInfo.FILE_LENGTH_INDEX])));
    file_info.set_offset((Long.valueOf(eles[FileInfo.OFFSET_INDEX])));
    file_info.set_id((Integer.valueOf(eles[FileInfo.ID_INDEX])));
    } catch (NumberFormatException e) {
      LOG.warn("Invalid line:" + line);
      return false;
    }
    return true;
  }

  public static void PrintMap(Map<Integer, FileInfo> file_info_map) {
    int cnter = 0;
    LOG.debug("Total num file in file_map:" + file_info_map.size());
    for (FileInfo file_info : file_info_map.values()) {
      LOG.debug("idx = " + cnter + " info = " + file_info.toString());
    }
  }

  public synchronized void LoadMap(Map<Integer, FileInfo> file_info_map) {
    LOG.info("LoadFileMap from file: " + file_name_);
    BufferedReader file_reader = null;
    try {
      file_reader = new BufferedReader(new InputStreamReader(
          new FileInputStream(file_name_)));
      String line = null;
      while ((line = file_reader.readLine()) != null) {
        if (line.startsWith("#")) {
          continue;
        }
        FileInfo file_info = new FileInfo();
        if (ParseLine(line, file_info)) {
          file_info_map.put(file_info.get_id(), file_info);
        } else {
          LOG.warn("LoadMap invalid line, parse error: " + line);
        }
      }
      PrintMap(file_info_map);
    } catch(FileNotFoundException e) {
      LOG.info("Map record file not exist, skip loading " + file_name_);
    } catch (Exception e) {
      LOG.warn("Map record file read error due to " + e.toString());
    } finally {
      if (null != file_reader) {
        try {
          file_reader.close();
        } catch (IOException e) {
          LOG.warn("close file exception, " + e.toString());
        }
      }
    }
  }

  public synchronized void WriteMap(Map<Integer, FileInfo> file_info_map) {
    PrintWriter file_writter = null;
    int cnter = 0;
    try {
      File file = new File(file_name_);
      // create parent directory if not exist
      file.getParentFile().mkdirs();
      file_writter = new PrintWriter(file_name_);
	  file_writter.println(format_string_);
      synchronized (file_info_map) {
        for (FileInfo file_info : file_info_map.values()) {
          file_writter.println(file_info.GetWriteString());
          cnter++;
        }
      }
    } catch (FileNotFoundException e) {
      LOG.warn("File not found, you should never see this");
    } catch (Exception e) {
      LOG.warn("Write map meta failed due to " + e.toString());
    } finally {
      if (null != file_writter) {
        file_writter.close();
      }
      LOG.info("Write \'" + cnter + "\' records to map meta file" + file_name_ );
    }
  }

}


text:
package org.apache.sis.internal.jaxb.gmx;

import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * The {@code <gmx:MimeFileType>} element, which may be used as a substitute of {@code <gco:CharacterString>}.
 * This is used in {@link org.apache.sis.metadata.iso.identification.DefaultBrowseGraphic}.
 * Example:
 *
 * {@preformat xml
 *   <fileType>
 *     <gmx:MimeFileType type="image/tiff">Graphic TIFF</gmx:MimeFileType>
 *   </fileType>
 * }
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @since   0.4
 * @version 0.4
 * @module
 *
 * @see SIS-119
 */
@XmlType(name = "MimeFileType_PropertyType")
@XmlRootElement(name = "MimeFileType")
public final class MimeFileType {
    /**
     * The value of the {@code type} attribute, which is the mime type.
     */
    @XmlAttribute
    private String type;

    /**
     * A human-readable description of the mime type. If {@link #type} is null,
     * then this will be taken as the mime type.
     */
    @XmlValue
    private String value;

    /**
     * Empty constructor for JAXB only.
     */
    public MimeFileType() {
    }

    /**
     * Creates a new {@code <gml:MimeFileType>} for the given type.
     *
     * @param type The MIME type.
     */
    public MimeFileType(final String type) {
        this.type  = type;
        this.value = type; // May provide a more human-redeable value in a future SIS version.
    }

    /**
     * Returns the MIME type, or {@code null} if none.
     *
     *
Note:
     * Returning {@code null} is usually not recommended for a {@code toString()} method,
     * but this class is for internal usage only.

     *
     * @return The MIME type, or {@code null} if none.
     */
    @Override
    public String toString() {
        return (type != null) ? type : value;
    }
}


text:
    quartett.Util = {
        isArray: function(value){
            return toString.call(value) === '[object Array]';
        },
        isFunction: function(value){
            return typeof value === 'function';
        },
        isString: function(value){
            return typeof  value === 'string';
        },
        deepExtend: function () {
            var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

            if (target.constructor == Boolean) {
                deep = target;
                target = arguments[1] || {};
                i = 2;
            }

            if (typeof target != "object" && typeof target != "function")
                target = {};

            if (length == 1) {
                target = this;
                i = 0;
            }

            for (; i < length; i++)
                if ((options = arguments[i]) != null)
                    for (var name in options) {
                        if (target === options[name])
                            continue;

                        if (deep && options[name] && typeof options[name] == "object" && target[name] && !options[name].nodeType)
                            target[name] = this.deepExtend(true, target[name], options[name]);

                        else if (options[name] != undefined)
                            target[name] = options[name];
                    }

            return target;
        },
        shuffleArray: function (arr) {
            for (var i = arr.length - 1; i > 0; i--) {
                var j = Math.floor(Math.random() * (i + 1));
                var tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
            }

            return arr;
        }
    };


text:
package de.rosstauscher.comparandum.render;

import java.awt.Dimension;
import java.awt.Graphics2D;

public abstract class AbstractRenderableFacade implements IRenderable {

	protected IRenderable delegate;

	/*************************************************************************
	 * Constructor
	 * @param delegate to use.
	 ************************************************************************/

	public AbstractRenderableFacade(IRenderable delegate) {
		super();
		this.delegate = delegate;
	}

	/*************************************************************************
	 * paint
	 * @see de.rosstauscher.comparandum.render.IRenderable#paint(java.awt.Graphics2D)
	 ************************************************************************/
	@Override
	public void paint(Graphics2D g) {
		this.delegate.paint(g);
	}

	/*************************************************************************
	 * getDimension
	 * @see de.rosstauscher.comparandum.render.IRenderable#getDimension()
	 ************************************************************************/
	@Override
	public Dimension getDimension() {
		return this.delegate.getDimension();
	}

}


text:
<?php

namespace Oro\Bundle\LocaleBundle\Twig;

use Oro\Bundle\LocaleBundle\Formatter\DateTimeFormatter;

class DateTimeExtension extends \Twig_Extension
{
    /**
     * @var DateTimeFormatter
     */
    protected $formatter;

    /**
     * @param DateTimeFormatter $formatter
     */
    public function __construct(DateTimeFormatter $formatter)
    {
        $this->formatter = $formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter(
                'oro_format_datetime',
                array($this, 'formatDateTime'),
                array('is_safe' => array('html'))
            ),
            new \Twig_SimpleFilter(
                'oro_format_date',
                array($this, 'formatDate'),
                array('is_safe' => array('html'))
            ),
            new \Twig_SimpleFilter(
                'oro_format_time',
                array($this, 'formatTime'),
                array('is_safe' => array('html'))
            ),
        );
    }

    /**
     * Formats date time according to locale settings.
     *
     * Options format:
     * array(
     *     'dateType' => <dateType>,
     *     'timeType' => <timeType>,
     *     'locale' => <locale>,
     *     'timezone' => <timezone>,
     * )
     *
     * @param \DateTime|string|int $date
     * @param array $options
     * @return string
     */
    public function formatDateTime($date, array $options = array())
    {
        $dateType = $this->getOption($options, 'dateType');
        $timeType = $this->getOption($options, 'timeType');
        $locale = $this->getOption($options, 'locale');
        $timeZone = $this->getOption($options, 'timeZone');

        return $this->formatter->format($date, $dateType, $timeType, $locale, $timeZone);
    }

    /**
     * Formats date time according to locale settings.
     *
     * Options format:
     * array(
     *     'dateType' => <dateType>,
     *     'locale' => <locale>,
     *     'timeZone' => <timeZone>,
     * )
     *
     * @param \DateTime|string|int $date
     * @param array $options
     * @return string
     */
    public function formatDate($date, array $options = array())
    {
        $dateType = $this->getOption($options, 'dateType');
        $locale = $this->getOption($options, 'locale');
        $timeZone = $this->getOption($options, 'timeZone');

        return $this->formatter->formatDate($date, $dateType, $locale, $timeZone);
    }

    /**
     * Formats date time according to locale settings.
     *
     * Options format:
     * array(
     *     'timeType' => <timeType>,
     *     'locale' => <locale>,
     *     'timeZone' => <timeZone>,
     * )
     *
     * @param \DateTime|string|int $date
     * @param array $options
     * @return string
     */
    public function formatTime($date, array $options = array())
    {
        $timeType = $this->getOption($options, 'timeType');
        $locale = $this->getOption($options, 'locale');
        $timeZone = $this->getOption($options, 'timeZone');

        return $this->formatter->formatTime($date, $timeType, $locale, $timeZone);
    }

    /**
     * Gets option or default value if option not exist
     *
     * @param array $options
     * @param string $name
     * @param mixed $default
     * @return mixed
     */
    protected function getOption(array $options, $name, $default = null)
    {
        return isset($options[$name]) ? $options[$name] : $default;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'oro_locale_datetime';
    }
}


text:
package com.oracle.xmlns.apps.crmcommon.notes.noteservice;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

/**
 * This object contains factory methods for each
 * Java content interface and Java element interface
 * generated in the com.oracle.xmlns.apps.crmcommon.notes.noteservice package.
 * <p>An ObjectFactory allows you to programatically
 * construct new instances of the Java representation
 * for XML content. The Java representation of XML
 * content can consist of schema derived interfaces
 * and classes representing the binding of schema
 * type definitions, element declarations and model
 * groups.  Factory methods for each of these are
 * provided in this class.
 *
 */
@XmlRegistry
public class ObjectFactory {

    private final static QName _Note_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "note");
    private final static QName _NoteNoteAttributeUid2_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "NoteAttributeUid2");
    private final static QName _NoteNoteAttributeUid3_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "NoteAttributeUid3");
    private final static QName _NoteNoteAttributeUid4_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "NoteAttributeUid4");
    private final static QName _NoteNoteAttributeUid5_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "NoteAttributeUid5");
    private final static QName _NoteNoteAttributeCategory_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "NoteAttributeCategory");
    private final static QName _NoteContactRelationshipId_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "ContactRelationshipId");
    private final static QName _NoteNoteAttributeUid1_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "NoteAttributeUid1");
    private final static QName _NoteCreatorPartyId_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "CreatorPartyId");
    private final static QName _NoteCurcyConvRateType_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "CurcyConvRateType");
    private final static QName _NoteCurrencyCode_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "CurrencyCode");
    private final static QName _NoteCorpCurrencyCode_QNAME = new QName("http://xmlns.oracle.com/apps/crmCommon/notes/noteService", "CorpCurrencyCode");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.oracle.xmlns.apps.crmcommon.notes.noteservice
     *
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link Note }
     *
     */
    public Note createNote() {
        return new Note();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Note }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "note")
    public JAXBElement<Note> createNote(Note value) {
        return new JAXBElement<Note>(_Note_QNAME, Note.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "NoteAttributeUid2", scope = Note.class)
    public JAXBElement<String> createNoteNoteAttributeUid2(String value) {
        return new JAXBElement<String>(_NoteNoteAttributeUid2_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "NoteAttributeUid3", scope = Note.class)
    public JAXBElement<String> createNoteNoteAttributeUid3(String value) {
        return new JAXBElement<String>(_NoteNoteAttributeUid3_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "NoteAttributeUid4", scope = Note.class)
    public JAXBElement<String> createNoteNoteAttributeUid4(String value) {
        return new JAXBElement<String>(_NoteNoteAttributeUid4_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "NoteAttributeUid5", scope = Note.class)
    public JAXBElement<String> createNoteNoteAttributeUid5(String value) {
        return new JAXBElement<String>(_NoteNoteAttributeUid5_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "NoteAttributeCategory", scope = Note.class)
    public JAXBElement<String> createNoteNoteAttributeCategory(String value) {
        return new JAXBElement<String>(_NoteNoteAttributeCategory_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Long }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "ContactRelationshipId", scope = Note.class)
    public JAXBElement<Long> createNoteContactRelationshipId(Long value) {
        return new JAXBElement<Long>(_NoteContactRelationshipId_QNAME, Long.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "NoteAttributeUid1", scope = Note.class)
    public JAXBElement<String> createNoteNoteAttributeUid1(String value) {
        return new JAXBElement<String>(_NoteNoteAttributeUid1_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Long }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "CreatorPartyId", scope = Note.class)
    public JAXBElement<Long> createNoteCreatorPartyId(Long value) {
        return new JAXBElement<Long>(_NoteCreatorPartyId_QNAME, Long.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "CurcyConvRateType", scope = Note.class)
    public JAXBElement<String> createNoteCurcyConvRateType(String value) {
        return new JAXBElement<String>(_NoteCurcyConvRateType_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "CurrencyCode", scope = Note.class)
    public JAXBElement<String> createNoteCurrencyCode(String value) {
        return new JAXBElement<String>(_NoteCurrencyCode_QNAME, String.class, Note.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://xmlns.oracle.com/apps/crmCommon/notes/noteService", name = "CorpCurrencyCode", scope = Note.class)
    public JAXBElement<String> createNoteCorpCurrencyCode(String value) {
        return new JAXBElement<String>(_NoteCorpCurrencyCode_QNAME, String.class, Note.class, value);
    }

}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/.idea/fengming.iml" filepath="$PROJECT_DIR$/.idea/fengming.iml" />
    </modules>
  </component>
</project>