<commit_before>#include "mapping.h"
#include <iostream>

using namespace Yuni;



namespace Nany
{
namespace Pass
{
namespace Mapping
{


	SequenceMapping::SequenceMapping(ClassdefTable& cdeftable, Mutex& mutex, Logs::Report& report, IR::Sequence& sequence)
		: cdeftable(cdeftable)
		, mutex(mutex)
		, currentSequence(sequence)
		, report(report)
	{
		// reduce memory allocations
		lastPushedNamedParameters.reserve(8); // arbitrary
		lastPushedIndexedParameters.reserve(8);
	}


	inline void SequenceMapping::pushNewFrame(Atom& atom)
	{
		std::unique_ptr<AtomStackFrame> next{atomStack.release()};
		atomStack = std::make_unique<AtomStackFrame>(atom, next);
	}


	Logs::Report SequenceMapping::error()
	{
		success = false;
		auto err = report.error();
		err.message.origins.location.filename   = currentFilename;
		err.message.origins.location.pos.line   = currentLine;
		err.message.origins.location.pos.offset = currentOffset;
		return err;
	}


	void SequenceMapping::printError(const IR::Instruction& operands, AnyString msg)
	{
		// example: ICE: unknown opcode 'resolveAttribute': from 'ref %4 = resolve %3."()"'
		auto trace = report.ICE();
		if (not msg.empty())
			trace << msg << ':';
		else
			trace << "invalid opcode ";

		trace << " '" << IR::ISA::print(currentSequence, operands) << '\'';
		success = false;
	}

	template<IR::ISA::Op O>
	inline void SequenceMapping::printError(const IR::ISA::Operand<O>& operands, AnyString msg)
	{
		printError(IR::Instruction::fromOpcode(operands), msg);
	}


	template<IR::ISA::Op O>
	inline bool SequenceMapping::checkForLVID(const IR::ISA::Operand<O>& operands, LVID lvid)
	{
		if (debugmode)
		{
			if (unlikely(lvid == 0 or not (lvid < atomStack->classdefs.size())))
			{
				printError(operands, String{"mapping: invalid lvid %"} << lvid << " (upper bound: %"
					<< atomStack->classdefs.size() << ')');
				return false;
			}
		}
		return true;
	}


	inline void SequenceMapping::resetClassdefOriginFromCurrentPosition(Classdef& cdef)
	{
		cdef.origins.filename = currentFilename;
		cdef.origins.line     = currentLine;
		cdef.origins.offset   = currentOffset;
	}


	void SequenceMapping::attachFuncCall(const IR::ISA::Operand<IR::ISA::Op::call>& operands)
	{
		if (unlikely(not checkForLVID(operands, operands.ptr2func)))
			return;
		if (unlikely(not checkForLVID(operands, operands.lvid)))
			return;

		auto& stackframe     = *atomStack;
		auto atomid          = stackframe.atom.atomid;
		auto& clidFuncToCall = stackframe.classdefs[operands.ptr2func];
		auto& clidRetValue   = stackframe.classdefs[operands.lvid];


		// update all underlying types
		{
			CLID clid{atomid, 0};

			MutexLocker locker{mutex};

			resetClassdefOriginFromCurrentPosition(cdeftable.classdef(clidRetValue));

			auto& funcdef = cdeftable.addClassdefInterfaceSelf(clidFuncToCall);
			funcdef.resetReturnType(clidRetValue);
			funcdef.clid = clidFuncToCall;

			for (uint i = 0; i != lastPushedIndexedParameters.size(); ++i)
			{
				auto lvid = lastPushedIndexedParameters[i];
				clid.reclass(lvid);
				funcdef.appendParameter(clid);

				auto& followup = cdeftable.classdef(clid).followup;
				followup.pushedIndexedParams.push_back(std::make_pair(clidFuncToCall, i));
			}

			for (auto& pair: lastPushedNamedParameters)
			{
				clid.reclass(pair.second);
				funcdef.appendParameter(pair.first, clid);

				auto& followup = cdeftable.classdef(clid).followup;
				followup.pushedNamedParams.push_back(std::make_pair(clidFuncToCall, pair.first));
			}
		}
	}


	inline void SequenceMapping::visit(IR::ISA::Operand<IR::ISA::Op::blueprint>& operands)
	{
		if (unlikely(nullptr == atomStack))
			return printError(operands, "invalid stack for blueprint");

		auto kind = static_cast<IR::ISA::Blueprint>(operands.kind);
		switch (kind)
		{
			case IR::ISA::Blueprint::vardef:
			{
				// registering the blueprint into the outline...
				Atom& atom = atomStack->currentAtomNotUnit();
				AnyString varname = currentSequence.stringrefs[operands.name];
				if (unlikely(varname.empty()))
					return printError(operands, "invalid func name");
				if (unlikely(atom.type != Atom::Type::classdef))
					return printError(operands, "vardef: invalid parent atom");

				MutexLocker locker{mutex};
				// create a new atom in the global type table
				auto* newVarAtom = cdeftable.atoms.createVardef(atom, varname);
				assert(newVarAtom != nullptr);

				cdeftable.registerAtom(newVarAtom);
				newVarAtom->returnType.clid.reclass(atom.atomid, operands.lvid);
				if (!firstAtomCreated)
					firstAtomCreated = newVarAtom;
				break;
			}

			case IR::ISA::Blueprint::param:
			case IR::ISA::Blueprint::paramself:
			case IR::ISA::Blueprint::gentypeparam:
			{
				auto& frame = *atomStack;

				// calculating the lvid for the current parameter
				// (+1 since %1 is the return value/type)
				uint paramLVID = (++frame.parameterIndex) + 1;

				if (unlikely(not checkForLVID(operands, paramLVID)))
					return;

				bool isTemplate = (kind == IR::ISA::Blueprint::gentypeparam);
				if (unlikely(not isTemplate and not frame.atom.isFunction()))
					return printError(operands, "parameter for non-function");

				CLID clid {frame.atom.atomid, paramLVID};
				AnyString name = currentSequence.stringrefs[operands.name];

				auto& parameters = (not isTemplate)
					? frame.atom.parameters : frame.atom.tmplparams;
				parameters.append(clid, name);

				// keep somewhere that this definition is a variable instance
				MutexLocker locker{mutex};
				auto& cdef = cdeftable.classdef(clid);
				cdef.instance = not isTemplate;
				cdef.qualifiers.ref = false; // should not be 'ref' by default, contrary to all other classdefs
				break;
			}

			case IR::ISA::Blueprint::funcdef:
			{
				// registering the blueprint into the outline...
				Atom& atom = atomStack->currentAtomNotUnit();
				AnyString funcname = currentSequence.stringrefs[operands.name];
				if (unlikely(funcname.empty()))
					return printError(operands, "invalid func name");

				// reset last lvid and parameters
				lastLVID = 0;
				lastPushedNamedParameters.clear();
				lastPushedIndexedParameters.clear();

				MutexLocker locker{mutex};
				// create a new atom in the global type table
				auto* newFuncAtom = cdeftable.atoms.createFuncdef(atom, funcname);
				assert(newFuncAtom != nullptr);
				newFuncAtom->opcodes.sequence  = &currentSequence;
				newFuncAtom->opcodes.offset   = currentSequence.offsetOf(operands);
				// create a pseudo classdef to easily retrieve the real atom from a clid
				cdeftable.registerAtom(newFuncAtom);

				operands.atomid = newFuncAtom->atomid;

				// return type
				newFuncAtom->returnType.clid.reclass(newFuncAtom->atomid, 1);<commit_msg>fixed definition of generic type parameters<commit_after>#include "mapping.h"
#include <iostream>

using namespace Yuni;



namespace Nany
{
namespace Pass
{
namespace Mapping
{


	SequenceMapping::SequenceMapping(ClassdefTable& cdeftable, Mutex& mutex, Logs::Report& report, IR::Sequence& sequence)
		: cdeftable(cdeftable)
		, mutex(mutex)
		, currentSequence(sequence)
		, report(report)
	{
		// reduce memory allocations
		lastPushedNamedParameters.reserve(8); // arbitrary
		lastPushedIndexedParameters.reserve(8);
	}


	inline void SequenceMapping::pushNewFrame(Atom& atom)
	{
		std::unique_ptr<AtomStackFrame> next{atomStack.release()};
		atomStack = std::make_unique<AtomStackFrame>(atom, next);
	}


	Logs::Report SequenceMapping::error()
	{
		success = false;
		auto err = report.error();
		err.message.origins.location.filename   = currentFilename;
		err.message.origins.location.pos.line   = currentLine;
		err.message.origins.location.pos.offset = currentOffset;
		return err;
	}


	void SequenceMapping::printError(const IR::Instruction& operands, AnyString msg)
	{
		// example: ICE: unknown opcode 'resolveAttribute': from 'ref %4 = resolve %3."()"'
		auto trace = report.ICE();
		if (not msg.empty())
			trace << msg << ':';
		else
			trace << "invalid opcode ";

		trace << " '" << IR::ISA::print(currentSequence, operands) << '\'';
		success = false;
	}

	template<IR::ISA::Op O>
	inline void SequenceMapping::printError(const IR::ISA::Operand<O>& operands, AnyString msg)
	{
		printError(IR::Instruction::fromOpcode(operands), msg);
	}


	template<IR::ISA::Op O>
	inline bool SequenceMapping::checkForLVID(const IR::ISA::Operand<O>& operands, LVID lvid)
	{
		if (debugmode)
		{
			if (unlikely(lvid == 0 or not (lvid < atomStack->classdefs.size())))
			{
				printError(operands, String{"mapping: invalid lvid %"} << lvid << " (upper bound: %"
					<< atomStack->classdefs.size() << ')');
				return false;
			}
		}
		return true;
	}


	inline void SequenceMapping::resetClassdefOriginFromCurrentPosition(Classdef& cdef)
	{
		cdef.origins.filename = currentFilename;
		cdef.origins.line     = currentLine;
		cdef.origins.offset   = currentOffset;
	}


	void SequenceMapping::attachFuncCall(const IR::ISA::Operand<IR::ISA::Op::call>& operands)
	{
		if (unlikely(not checkForLVID(operands, operands.ptr2func)))
			return;
		if (unlikely(not checkForLVID(operands, operands.lvid)))
			return;

		auto& stackframe     = *atomStack;
		auto atomid          = stackframe.atom.atomid;
		auto& clidFuncToCall = stackframe.classdefs[operands.ptr2func];
		auto& clidRetValue   = stackframe.classdefs[operands.lvid];


		// update all underlying types
		{
			CLID clid{atomid, 0};

			MutexLocker locker{mutex};

			resetClassdefOriginFromCurrentPosition(cdeftable.classdef(clidRetValue));

			auto& funcdef = cdeftable.addClassdefInterfaceSelf(clidFuncToCall);
			funcdef.resetReturnType(clidRetValue);
			funcdef.clid = clidFuncToCall;

			for (uint i = 0; i != lastPushedIndexedParameters.size(); ++i)
			{
				auto lvid = lastPushedIndexedParameters[i];
				clid.reclass(lvid);
				funcdef.appendParameter(clid);

				auto& followup = cdeftable.classdef(clid).followup;
				followup.pushedIndexedParams.push_back(std::make_pair(clidFuncToCall, i));
			}

			for (auto& pair: lastPushedNamedParameters)
			{
				clid.reclass(pair.second);
				funcdef.appendParameter(pair.first, clid);

				auto& followup = cdeftable.classdef(clid).followup;
				followup.pushedNamedParams.push_back(std::make_pair(clidFuncToCall, pair.first));
			}
		}
	}


	inline void SequenceMapping::visit(IR::ISA::Operand<IR::ISA::Op::blueprint>& operands)
	{
		if (unlikely(nullptr == atomStack))
			return printError(operands, "invalid stack for blueprint");

		auto kind = static_cast<IR::ISA::Blueprint>(operands.kind);
		switch (kind)
		{
			case IR::ISA::Blueprint::vardef:
			{
				// registering the blueprint into the outline...
				Atom& atom = atomStack->currentAtomNotUnit();
				AnyString varname = currentSequence.stringrefs[operands.name];
				if (unlikely(varname.empty()))
					return printError(operands, "invalid func name");
				if (unlikely(atom.type != Atom::Type::classdef))
					return printError(operands, "vardef: invalid parent atom");

				MutexLocker locker{mutex};
				// create a new atom in the global type table
				auto* newVarAtom = cdeftable.atoms.createVardef(atom, varname);
				assert(newVarAtom != nullptr);

				cdeftable.registerAtom(newVarAtom);
				newVarAtom->returnType.clid.reclass(atom.atomid, operands.lvid);
				if (!firstAtomCreated)
					firstAtomCreated = newVarAtom;
				break;
			}

			case IR::ISA::Blueprint::param:
			case IR::ISA::Blueprint::paramself:
			case IR::ISA::Blueprint::gentypeparam:
			{
				auto& frame = *atomStack;

				// calculating the lvid for the current parameter
				// (+1 since %1 is the return value/type)
				uint paramLVID = (++frame.parameterIndex) + 1;

				if (unlikely(not checkForLVID(operands, paramLVID)))
					return;

				bool isTemplate = (kind == IR::ISA::Blueprint::gentypeparam);
				if (unlikely(not isTemplate and not frame.atom.isFunction()))
					return printError(operands, "parameter for non-function");

				CLID clid {frame.atom.atomid, paramLVID};
				AnyString name = currentSequence.stringrefs[operands.name];

				auto& parameters = (not isTemplate)
					? frame.atom.parameters : frame.atom.tmplparams;
				parameters.append(clid, name);


				MutexLocker locker{mutex};
				// information about the parameter itself
				auto& cdef = cdeftable.classdef(clid);
				cdef.instance = not isTemplate;
				cdef.qualifiers.ref = false; // should not be 'ref' by default, contrary to all other classdefs

				if (isTemplate)
				{
					// if a generic type parameter, generating an implicit typedef
					Atom& atom = atomStack->currentAtomNotUnit();
					auto* newAliasAtom = cdeftable.atoms.createTypealias(atom, name);
					cdeftable.registerAtom(newAliasAtom);
					newAliasAtom->returnType.clid = cdef.clid; // type of the typedef
				}
				break;
			}

			case IR::ISA::Blueprint::funcdef:
			{
				// registering the blueprint into the outline...
				Atom& atom = atomStack->currentAtomNotUnit();
				AnyString funcname = currentSequence.stringrefs[operands.name];
				if (unlikely(funcname.empty()))
					return printError(operands, "invalid func name");

				// reset last lvid and parameters
				lastLVID = 0;
				lastPushedNamedParameters.clear();
				lastPushedIndexedParameters.clear();

				MutexLocker locker{mutex};
				// create a new atom in the global type table
				auto* newFuncAtom = cdeftable.atoms.createFuncdef(atom, funcname);
				assert(newFuncAtom != nullptr);
				newFuncAtom->opcodes.sequence  = &currentSequence;
				newFuncAtom->opcodes.offset   = currentSequence.offsetOf(operands);
				// create a pseudo classdef to easily retrieve the real atom from a clid
				cdeftable.registerAtom(newFuncAtom);

				operands.atomid = newFuncAtom->atomid;

				// return type
				newFuncAtom->returnType.clid.reclass(newFuncAtom->atomid, 1);
{'fraction_non_alphanumeric': 0.12694488875963356, 'fraction_numerical': 0.0020357714119528863, 'mean_word_length': 4.206283118849356, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5044725', 'n_tokens_mistral': 5262, 'n_tokens_neox': 4473, 'n_words': 919}