<commit_before>/*
 * Copyright (c) 2011  <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */

#ifndef CONCRETE_OBJECTS_TUPLE_HPP
#define CONCRETE_OBJECTS_TUPLE_HPP

#include <stdexcept>

#include <concrete/block.hpp>
#include <concrete/objects/object.hpp>
#include <concrete/util/packed.hpp>

namespace concrete {

struct TupleBlock: ObjectBlock {
	PortableObject items[0];

	TupleBlock(const TypeObject &type): ObjectBlock(type)
	{
		for (unsigned int i = 0; i < size(); i++)
			new (&items[i]) PortableObject();
	}

	~TupleBlock()
	{
		for (unsigned int i = size(); i-- > 0; )
			items[i].~PortableObject();
	}

	unsigned int size() const
	{
		return (block_size() - sizeof (TupleBlock)) / sizeof (PortableObject);
	}
} CONCRETE_PACKED;

template <typename Ops>
class tuple_object: public object<Ops> {
	friend class object<ObjectOps>;
	friend class object<PortableObjectOps>;

public:
	static TypeObject Type()
	{
		return Context::Builtins().tuple_type;
	}

	static tuple_object New(unsigned int size) throw (AllocError)
	{
		auto id = Context::Alloc(sizeof (TupleBlock) + sizeof (PortableObject) * size);
		new (Context::Pointer(id)) TupleBlock(Type());
		return id;
	}

	using object<Ops>::operator==;
	using object<Ops>::operator!=;

	template <typename OtherOps>
	tuple_object(const tuple_object<OtherOps> &other): object<Ops>(other)
	{
	}

	template <typename OtherOps>
	tuple_object &operator=(const tuple_object<OtherOps> &other)
	{
		object<Ops>::operator=(other);
		return *this;
	}

	void init_item(unsigned int index, const Object &item)
	{
		auto block = tuple_block();
		assert(index < block->size());
		block->items[index] = item;
	}

	unsigned int size() const
	{
		return tuple_block()->size();
	}

	Object get_item(unsigned int index) const
	{
		auto block = tuple_block();
		if (index >= block->size())
			throw std::range_error("tuple index out of bounds");
		return block->items[index];
	}

protected:
	tuple_object(BlockId id): object<Ops>(id)
	{
	}

	TupleBlock *tuple_block() const<commit_msg>TupleObject throws RuntimeError<commit_after>/*
 * Copyright (c) 2011  <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */

#ifndef CONCRETE_OBJECTS_TUPLE_HPP
#define CONCRETE_OBJECTS_TUPLE_HPP

#include <concrete/block.hpp>
#include <concrete/exception.hpp>
#include <concrete/objects/object.hpp>
#include <concrete/util/packed.hpp>

namespace concrete {

struct TupleBlock: ObjectBlock {
	PortableObject items[0];

	TupleBlock(const TypeObject &type): ObjectBlock(type)
	{
		for (unsigned int i = 0; i < size(); i++)
			new (&items[i]) PortableObject();
	}

	~TupleBlock()
	{
		for (unsigned int i = size(); i-- > 0; )
			items[i].~PortableObject();
	}

	unsigned int size() const
	{
		return (block_size() - sizeof (TupleBlock)) / sizeof (PortableObject);
	}
} CONCRETE_PACKED;

template <typename Ops>
class tuple_object: public object<Ops> {
	friend class object<ObjectOps>;
	friend class object<PortableObjectOps>;

public:
	static TypeObject Type()
	{
		return Context::Builtins().tuple_type;
	}

	static tuple_object New(unsigned int size) throw (AllocError)
	{
		auto id = Context::Alloc(sizeof (TupleBlock) + sizeof (PortableObject) * size);
		new (Context::Pointer(id)) TupleBlock(Type());
		return id;
	}

	using object<Ops>::operator==;
	using object<Ops>::operator!=;

	template <typename OtherOps>
	tuple_object(const tuple_object<OtherOps> &other): object<Ops>(other)
	{
	}

	template <typename OtherOps>
	tuple_object &operator=(const tuple_object<OtherOps> &other)
	{
		object<Ops>::operator=(other);
		return *this;
	}

	void init_item(unsigned int index, const Object &item)
	{
		auto block = tuple_block();
		assert(index < block->size());
		block->items[index] = item;
	}

	unsigned int size() const
	{
		return tuple_block()->size();
	}

	Object get_item(unsigned int index) const
	{
		auto block = tuple_block();
		if (index >= block->size())
			throw RuntimeError("tuple index out of bounds");
		return block->items[index];
	}

protected:
	tuple_object(BlockId id): object<Ops>(id)
	{
	}

	TupleBlock *tuple_block() const
{'fraction_non_alphanumeric': 0.13120567375886524, 'fraction_numerical': 0.003989361702127659, 'mean_word_length': 4.815721649484536, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 53, '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': '486147', 'n_tokens_mistral': 1552, 'n_tokens_neox': 1473, 'n_words': 413}