<commit_before>/*
 *	Copyright 2021 <NAME>, <NAME>
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *	Unless required by applicable law or agreed to in writing, software
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License.
 */

#include "builder.h"
#include <string.h>


static inline node node_create(syntax *const sx, operation_t type)
{
	return node_add_child(&sx->nd, type);
}

static inline void node_set_child(const node *const parent, const node *const child)
{
	node temp = node_add_child(parent, OP_NOP);
	node_swap(child, &temp);
	node_remove(&temp);
}

/**
 *	Emit a semantic error
 *
 *	@param	sx			Syntax structure
 *	@param	loc			Error location
 *	@param	num			Error code
 */
static void semantic_error(syntax *const sx, const location loc, error_t num, ...)
{
	va_list args;
	va_start(args, num);

	const size_t prev_loc = in_get_position(sx->io);
	in_set_position(sx->io, loc.begin);

	verror(sx->io, num, args);
	sx->was_error = true;

	in_set_position(sx->io, prev_loc);

	va_end(args);
}


/*
 *	 __     __   __     ______   ______     ______     ______   ______     ______     ______
 *	/\ \   /\ "-.\ \   /\__  _\ /\  ___\   /\  == \   /\  ___\ /\  __ \   /\  ___\   /\  ___\
 *	\ \ \  \ \ \-.  \  \/_/\ \/ \ \  __\   \ \  __<   \ \  __\ \ \  __ \  \ \ \____  \ \  __\
 *	 \ \_\  \ \_\\"\_\    \ \_\  \ \_____\  \ \_\ \_\  \ \_\    \ \_\ \_\  \ \_____\  \ \_____\
 *	  \/_/   \/_/ \/_/     \/_/   \/_____/   \/_/ /_/   \/_/     \/_/\/_/   \/_____/   \/_____/
 */


node build_identifier_expression(syntax *const sx, const size_t name, const location loc)
{
	const item_t identifier = repr_get_reference(sx, name);

	if (identifier == ITEM_MAX)
	{
		semantic_error(sx, loc, undeclared_var_use, repr_get_name(sx, name));
		return build_broken_expression();
	}

	const item_t type = ident_get_type(sx, (size_t)identifier);
	const category_t category = type_is_function(sx, type) ? RVALUE : LVALUE;

	node nd = node_create(sx, OP_IDENTIFIER);
	node_add_arg(&nd, type);						// Тип значения идентификатора
	node_add_arg(&nd, category);					// Категория значения идентификатора
	node_add_arg(&nd, identifier);					// Индекс в таблице идентификаторов
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция идентификатора
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция идентификатора

	return nd;
}

node build_integer_literal_expression(syntax *const sx, const int value, const location loc)
{
	node nd = node_create(sx, OP_CONSTANT);
	node_add_arg(&nd, TYPE_INTEGER);				// Тип значения константы
	node_add_arg(&nd, RVALUE);						// Категория значения константы
	node_add_arg(&nd, value);						// Значение константы
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция константы
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция константы

	return nd;
}

node build_floating_literal_expression(syntax *const sx, const double value, const location loc)
{
	uint64_t num64;
	memcpy(&num64, &value, sizeof(int64_t));

	const item_t fst = num64 & 0x00000000ffffffff;
	const item_t snd = (num64 & 0xffffffff00000000) >> 32;

	node nd = node_create(sx, OP_CONSTANT);
	node_add_arg(&nd, TYPE_FLOATING);				// Тип значения константы
	node_add_arg(&nd, RVALUE);						// Категория значения константы
	node_add_arg(&nd, fst);							// Первая часть значения константы
	node_add_arg(&nd, snd);							// Вторая часть значения константы
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция константы
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция константы

	return nd;
}

node build_string_literal_expression(syntax *const sx, const size_t index, const location loc)
{
	const item_t type = type_array(sx, TYPE_INTEGER);

	node nd = node_create(sx, OP_STRING);
	node_add_arg(&nd, type);						// Тип строки
	node_add_arg(&nd, LVALUE);						// Категория значения строки
	node_add_arg(&nd, (item_t)index);				// Индекс в списке строк
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция строки
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция строки

	return nd;
}

node build_subscript_expression(syntax *const sx, const node *const nd_fst, const node *const nd_snd
	, const location l_loc, const location r_loc)
{
	if (!node_is_correct(nd_fst) || !node_is_correct(nd_snd))
	{<commit_msg>Add double arg for node by interface<commit_after>/*
 *	Copyright 2021 <NAME>, <NAME>
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *	Unless required by applicable law or agreed to in writing, software
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License.
 */

#include "builder.h"
#include <string.h>


static inline node node_create(syntax *const sx, operation_t type)
{
	return node_add_child(&sx->nd, type);
}

static inline void node_set_child(const node *const parent, const node *const child)
{
	node temp = node_add_child(parent, OP_NOP);
	node_swap(child, &temp);
	node_remove(&temp);
}

/**
 *	Emit a semantic error
 *
 *	@param	sx			Syntax structure
 *	@param	loc			Error location
 *	@param	num			Error code
 */
static void semantic_error(syntax *const sx, const location loc, error_t num, ...)
{
	va_list args;
	va_start(args, num);

	const size_t prev_loc = in_get_position(sx->io);
	in_set_position(sx->io, loc.begin);

	verror(sx->io, num, args);
	sx->was_error = true;

	in_set_position(sx->io, prev_loc);

	va_end(args);
}


/*
 *	 __     __   __     ______   ______     ______     ______   ______     ______     ______
 *	/\ \   /\ "-.\ \   /\__  _\ /\  ___\   /\  == \   /\  ___\ /\  __ \   /\  ___\   /\  ___\
 *	\ \ \  \ \ \-.  \  \/_/\ \/ \ \  __\   \ \  __<   \ \  __\ \ \  __ \  \ \ \____  \ \  __\
 *	 \ \_\  \ \_\\"\_\    \ \_\  \ \_____\  \ \_\ \_\  \ \_\    \ \_\ \_\  \ \_____\  \ \_____\
 *	  \/_/   \/_/ \/_/     \/_/   \/_____/   \/_/ /_/   \/_/     \/_/\/_/   \/_____/   \/_____/
 */


node build_identifier_expression(syntax *const sx, const size_t name, const location loc)
{
	const item_t identifier = repr_get_reference(sx, name);

	if (identifier == ITEM_MAX)
	{
		semantic_error(sx, loc, undeclared_var_use, repr_get_name(sx, name));
		return build_broken_expression();
	}

	const item_t type = ident_get_type(sx, (size_t)identifier);
	const category_t category = type_is_function(sx, type) ? RVALUE : LVALUE;

	node nd = node_create(sx, OP_IDENTIFIER);
	node_add_arg(&nd, type);						// Тип значения идентификатора
	node_add_arg(&nd, category);					// Категория значения идентификатора
	node_add_arg(&nd, identifier);					// Индекс в таблице идентификаторов
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция идентификатора
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция идентификатора

	return nd;
}

node build_integer_literal_expression(syntax *const sx, const int value, const location loc)
{
	node nd = node_create(sx, OP_CONSTANT);
	node_add_arg(&nd, TYPE_INTEGER);				// Тип значения константы
	node_add_arg(&nd, RVALUE);						// Категория значения константы
	node_add_arg(&nd, value);						// Значение константы
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция константы
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция константы

	return nd;
}

node build_floating_literal_expression(syntax *const sx, const double value, const location loc)
{
	node nd = node_create(sx, OP_CONSTANT);
	node_add_arg(&nd, TYPE_FLOATING);				// Тип значения константы
	node_add_arg(&nd, RVALUE);						// Категория значения константы
	node_add_arg_double(&nd, value);				// Значение константы
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция константы
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция константы

	return nd;
}

node build_string_literal_expression(syntax *const sx, const size_t index, const location loc)
{
	const item_t type = type_array(sx, TYPE_INTEGER);

	node nd = node_create(sx, OP_STRING);
	node_add_arg(&nd, type);						// Тип строки
	node_add_arg(&nd, LVALUE);						// Категория значения строки
	node_add_arg(&nd, (item_t)index);				// Индекс в списке строк
	node_add_arg(&nd, (item_t)loc.begin);			// Начальная позиция строки
	node_add_arg(&nd, (item_t)loc.end);				// Конечная позиция строки

	return nd;
}

node build_subscript_expression(syntax *const sx, const node *const nd_fst, const node *const nd_snd
	, const location l_loc, const location r_loc)
{
	if (!node_is_correct(nd_fst) || !node_is_correct(nd_snd))
	{
{'fraction_non_alphanumeric': 0.1304635032478256, 'fraction_numerical': 0.005284597599911923, 'mean_word_length': 3.262787423744721, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, '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': '5865205', 'n_tokens_mistral': 3719, 'n_tokens_neox': 3585, 'n_words': 782}