<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include "core/compiler.h"
#include "core/resolver.h"
#include "types/native_types.h"

namespace clever { namespace ast {

Resolver::Resolver(Compiler* compiler)
	: Visitor(), m_compiler(compiler)
{
	// global environment and scope
	m_symtable = m_scope = new Scope();
	m_scope->setEnvironment(new Environment(NULL));
	m_stack.push(m_scope->getEnvironment());
	m_scope->getEnvironment()->delRef();

	// Native type allocation
	Value* intval = new Value(CLEVER_INT_TYPE    = new IntType);
	Value* strval = new Value(CLEVER_STR_TYPE    = new StrType);
	Value* dblval = new Value(CLEVER_DOUBLE_TYPE = new DoubleType);
	Value* fncval = new Value(CLEVER_FUNC_TYPE   = new FuncType);
	Value* bolval = new Value(CLEVER_BOOL_TYPE   = new BoolType);
	Value* arrval = new Value(CLEVER_ARRAY_TYPE  = new ArrayType);
	Value* trdval = new Value(CLEVER_THREAD_TYPE = new ThreadType);

	m_scope->pushValue(CSTRING("Int"),      intval)->voffset = m_stack.top()->pushValue(intval);
	m_scope->pushValue(CSTRING("String"),   strval)->voffset = m_stack.top()->pushValue(strval);
	m_scope->pushValue(CSTRING("Double"),   dblval)->voffset = m_stack.top()->pushValue(dblval);
	m_scope->pushValue(CSTRING("Function"), fncval)->voffset = m_stack.top()->pushValue(fncval);
	m_scope->pushValue(CSTRING("Thread"),   trdval)->voffset = m_stack.top()->pushValue(trdval);
	m_scope->pushValue(CSTRING("Bool"),     bolval)->voffset = m_stack.top()->pushValue(bolval);
	m_scope->pushValue(CSTRING("Array"),    arrval)->voffset = m_stack.top()->pushValue(arrval);

	CLEVER_INT_TYPE->init();
	CLEVER_STR_TYPE->init();
	CLEVER_ARRAY_TYPE->init();
}

void Resolver::visit(Block* node)
{
	m_scope = m_scope->enter();
	m_scope->setEnvironment(m_stack.top());

	node->setScope(m_scope);

	Visitor::visit(static_cast<NodeArray*>(node));

	m_scope = m_scope->leave();
}

void Resolver::visit(VariableDecl* node)
{
	const CString* name = node->getIdent()->getName();

	if (m_scope->getLocal(name)) {
		Compiler::errorf(node->getLocation(),
			"Cannot redeclare variable `%S'.", name);
	}

	Value* val = new Value();
	m_scope->pushValue(name, val)->voffset = m_stack.top()->pushValue(val);

	node->getIdent()->accept(*this);

	if (node->hasAssignment()) {
		node->getAssignment()->accept(*this);
	}

	val->setConst(node->isConst());
}

void Resolver::visit(ThreadBlock* node)
{
	const CString* name;

	if (node->getSize() != NULL) {
		node->getSize()->accept(*this);
	}

	name = node->getName()->getName();
	clever_assert_not_null(name);

	if (m_scope->getLocal(name)) {
		Compiler::errorf(node->getLocation(),
			"Cannot redeclare thread `%S'.", name);
	}

	Thread* thread = static_cast<Thread*>(CLEVER_THREAD_TYPE->allocData(NULL));

	thread->setUserDefined();

	Value* tval = new Value();
	tval->setType(CLEVER_THREAD_TYPE);
	tval->setObj(thread);

	thread->setName(*name);
	m_scope->pushValue(name, tval)->voffset = m_stack.top()->pushValue(tval);

	node->getName()->accept(*this);

	m_scope = m_scope->enter();

	m_scope->setEnvironment(new Environment(m_stack.top()));
	m_stack.push(m_scope->getEnvironment());
	thread->setEnvironment(m_scope->getEnvironment());
	m_scope->getEnvironment()->delRef();

	node->setScope(m_scope);

	node->getBlock()->accept(*this);

	m_scope = m_scope->leave();

	m_stack.pop();
}

void Resolver::visit(FunctionDecl* node)
{
	static size_t anon_fdecls = 0;

	const CString* name;

	// Create an user-unusable symbol name for anonymous functions
	if (!node->hasIdent()) {
		std::stringstream buf;
		buf << "<anonymous " << anon_fdecls++ << ">";
		node->setIdent(new Ident(CSTRING(buf.str()),
								 node->getLocation()));
	}

	name = node->getIdent()->getName();
	clever_assert_not_null(name);

	if (m_scope->getLocal(name)) {
		Compiler::errorf(node->getLocation(),
			"Cannot redeclare function `%S'.", name);
	}

	Function* func = static_cast<Function*>(CLEVER_FUNC_TYPE->allocData(NULL));

	func->setUserDefined();

	Value* fval = new Value();
	fval->setType(CLEVER_FUNC_TYPE);
	fval->setObj(func);

	func->setName(*name);

	m_scope->pushValue(name, fval)->voffset = m_stack.top()->pushValue(fval);

	node->getIdent()->accept(*this);

	m_scope = m_scope->enter();

	m_scope->setEnvironment(new Environment(m_stack.top()));
	m_stack.push(m_scope->getEnvironment());
	func->setEnvironment(m_scope->getEnvironment());
	m_scope->getEnvironment()->delRef();

	node->setScope(m_scope);

	if (node->hasArgs()) {
		for (size_t i = 0; i < node->numArgs(); ++i) {
			static_cast<VariableDecl*>(node->getArg(i))->getAssignment()->setConditional(true);
		}

		node->getArgs()->accept(*this);

		func->setNumArgs(node->numArgs());
	}

	node->getBlock()->accept(*this);

	m_scope = m_scope->leave();
<commit_msg>- Lets use the constructor instead of calling setType here<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include "core/compiler.h"
#include "core/resolver.h"
#include "types/native_types.h"

namespace clever { namespace ast {

Resolver::Resolver(Compiler* compiler)
	: Visitor(), m_compiler(compiler)
{
	// global environment and scope
	m_symtable = m_scope = new Scope();
	m_scope->setEnvironment(new Environment(NULL));
	m_stack.push(m_scope->getEnvironment());
	m_scope->getEnvironment()->delRef();

	// Native type allocation
	Value* intval = new Value(CLEVER_INT_TYPE    = new IntType);
	Value* strval = new Value(CLEVER_STR_TYPE    = new StrType);
	Value* dblval = new Value(CLEVER_DOUBLE_TYPE = new DoubleType);
	Value* fncval = new Value(CLEVER_FUNC_TYPE   = new FuncType);
	Value* bolval = new Value(CLEVER_BOOL_TYPE   = new BoolType);
	Value* arrval = new Value(CLEVER_ARRAY_TYPE  = new ArrayType);
	Value* trdval = new Value(CLEVER_THREAD_TYPE = new ThreadType);

	m_scope->pushValue(CSTRING("Int"),      intval)->voffset = m_stack.top()->pushValue(intval);
	m_scope->pushValue(CSTRING("String"),   strval)->voffset = m_stack.top()->pushValue(strval);
	m_scope->pushValue(CSTRING("Double"),   dblval)->voffset = m_stack.top()->pushValue(dblval);
	m_scope->pushValue(CSTRING("Function"), fncval)->voffset = m_stack.top()->pushValue(fncval);
	m_scope->pushValue(CSTRING("Thread"),   trdval)->voffset = m_stack.top()->pushValue(trdval);
	m_scope->pushValue(CSTRING("Bool"),     bolval)->voffset = m_stack.top()->pushValue(bolval);
	m_scope->pushValue(CSTRING("Array"),    arrval)->voffset = m_stack.top()->pushValue(arrval);

	CLEVER_INT_TYPE->init();
	CLEVER_STR_TYPE->init();
	CLEVER_ARRAY_TYPE->init();
}

void Resolver::visit(Block* node)
{
	m_scope = m_scope->enter();
	m_scope->setEnvironment(m_stack.top());

	node->setScope(m_scope);

	Visitor::visit(static_cast<NodeArray*>(node));

	m_scope = m_scope->leave();
}

void Resolver::visit(VariableDecl* node)
{
	const CString* name = node->getIdent()->getName();

	if (m_scope->getLocal(name)) {
		Compiler::errorf(node->getLocation(),
			"Cannot redeclare variable `%S'.", name);
	}

	Value* val = new Value();
	m_scope->pushValue(name, val)->voffset = m_stack.top()->pushValue(val);

	node->getIdent()->accept(*this);

	if (node->hasAssignment()) {
		node->getAssignment()->accept(*this);
	}

	val->setConst(node->isConst());
}

void Resolver::visit(ThreadBlock* node)
{
	const CString* name;

	if (node->getSize() != NULL) {
		node->getSize()->accept(*this);
	}

	name = node->getName()->getName();
	clever_assert_not_null(name);

	if (m_scope->getLocal(name)) {
		Compiler::errorf(node->getLocation(),
			"Cannot redeclare thread `%S'.", name);
	}

	Thread* thread = static_cast<Thread*>(CLEVER_THREAD_TYPE->allocData(NULL));

	thread->setUserDefined();

	Value* tval = new Value(CLEVER_THREAD_TYPE);
	tval->setObj(thread);

	thread->setName(*name);
	m_scope->pushValue(name, tval)->voffset = m_stack.top()->pushValue(tval);

	node->getName()->accept(*this);

	m_scope = m_scope->enter();

	m_scope->setEnvironment(new Environment(m_stack.top()));
	m_stack.push(m_scope->getEnvironment());
	thread->setEnvironment(m_scope->getEnvironment());
	m_scope->getEnvironment()->delRef();

	node->setScope(m_scope);

	node->getBlock()->accept(*this);

	m_scope = m_scope->leave();

	m_stack.pop();
}

void Resolver::visit(FunctionDecl* node)
{
	static size_t anon_fdecls = 0;

	const CString* name;

	// Create an user-unusable symbol name for anonymous functions
	if (!node->hasIdent()) {
		std::stringstream buf;
		buf << "<anonymous " << anon_fdecls++ << ">";
		node->setIdent(new Ident(CSTRING(buf.str()),
								 node->getLocation()));
	}

	name = node->getIdent()->getName();
	clever_assert_not_null(name);

	if (m_scope->getLocal(name)) {
		Compiler::errorf(node->getLocation(),
			"Cannot redeclare function `%S'.", name);
	}

	Function* func = static_cast<Function*>(CLEVER_FUNC_TYPE->allocData(NULL));

	func->setUserDefined();

	Value* fval = new Value(CLEVER_FUNC_TYPE);
	fval->setObj(func);

	func->setName(*name);

	m_scope->pushValue(name, fval)->voffset = m_stack.top()->pushValue(fval);

	node->getIdent()->accept(*this);

	m_scope = m_scope->enter();

	m_scope->setEnvironment(new Environment(m_stack.top()));
	m_stack.push(m_scope->getEnvironment());
	func->setEnvironment(m_scope->getEnvironment());
	m_scope->getEnvironment()->delRef();

	node->setScope(m_scope);

	if (node->hasArgs()) {
		for (size_t i = 0; i < node->numArgs(); ++i) {
			static_cast<VariableDecl*>(node->getArg(i))->getAssignment()->setConditional(true);
		}

		node->getArgs()->accept(*this);

		func->setNumArgs(node->numArgs());
	}

	node->getBlock()->accept(*this);

	m_scope = m_scope->leave();

{'fraction_non_alphanumeric': 0.18375321336760925, 'fraction_numerical': 0.00041131105398457585, 'mean_word_length': 5.6479835953520166, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 233, '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': '4070568', 'n_tokens_mistral': 3522, 'n_tokens_neox': 3372, 'n_words': 567}