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

#ifndef CLEVER_AST_H
#define CLEVER_AST_H

#include <vector>
#include "core/value.h"
#include "core/location.hh"
#include "core/astvisitor.h"
#include "core/clever.h"

namespace clever { namespace ast {

class Node;

typedef std::vector<Node*> NodeList;

class Node: public RefCounted {
public:
	Node(const location& location)
		: RefCounted(0), m_location(location) {}

	virtual ~Node() {}

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	const location& m_location;
};

class NodeArray: public Node {
public:
	NodeArray(const location& location)
		: Node(location) {}

	virtual ~NodeArray() { clearNodes(); }

	NodeList& getNodes() { return m_nodes; }

	Node* getFirst() {
		if (m_nodes.empty()) {
			return NULL;
		}

		return *(m_nodes.begin());
	}

	Node* append(Node* node) {
		m_nodes.push_back(node);
		CLEVER_ADDREF(node);
		return node;
	}

	size_t getSize() const { return m_nodes.size(); }

	virtual void accept(Visitor& visitor) {
		NodeList::iterator node(m_nodes.begin()), end(m_nodes.end());
		while (node != end) {
			(*node)->accept(visitor);
			++node;
		}
	}

	void clearNodes() {
		NodeList::iterator it = m_nodes.begin(), end = m_nodes.end();

		while (it != end) {
			CLEVER_DELREF((*it));
			++it;
		}
	}
protected:
	NodeList m_nodes;
};

class Block: public NodeArray {
public:
	Block(const location& location)
		: NodeArray(location) {}

	virtual void accept(Visitor& visitor) {	visitor.visit(this); }
};

class Assignment: public Node {
public:
	Assignment(Node* lhs, Node* rhs, const location& location)
		: Node(location), m_lhs(lhs), m_rhs(rhs) {
		CLEVER_ADDREF(m_lhs);
		CLEVER_ADDREF(m_rhs);
	}

	~Assignment() {
		CLEVER_DELREF(m_lhs);
		CLEVER_DELREF(m_rhs);
	}

	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }
private:
	Node* m_lhs;
	Node* m_rhs;
};

class Ident: public Node {
public:
	Ident(const CString* name, const location& location)
		: Node(location), m_name(name) {}

	const CString* getName() const { return m_name; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	const CString* m_name;
};

class Import: public Node {
public:
	Import(Ident* package, Ident* module, const location& location)
		: Node(location), m_package(package), m_module(module) {
		CLEVER_ADDREF(m_package);
		CLEVER_ADDREF(m_module);
	}

	~Import() {
		CLEVER_DELREF(m_package);
		CLEVER_DELREF(m_module);
	}

	Ident* getPackage() const { return m_package; }
	Ident* getModule() const { return m_module; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }
private:
	Ident* m_package;
	Ident* m_module;
};

class VariableDecl: public Node {
public:
	VariableDecl(Ident* ident, Assignment* assignment, const location& location)
		: Node(location), m_ident(ident), m_assignment(assignment) {
		CLEVER_ADDREF(m_ident);
		if (m_assignment) {
			CLEVER_ADDREF(m_assignment);
		}
	}

	~VariableDecl() {
		CLEVER_DELREF(m_ident);
		if (m_assignment) {
			CLEVER_DELREF(m_assignment);
		}
	}

	Ident* getIdent() const { return m_ident; }
	Assignment* getAssignment() { return m_assignment; }
	bool hasAssignment() const { return m_assignment != NULL; }

	virtual void accept(Visitor& visitor) {	visitor.visit(this); }

private:
	Ident* m_ident;
	Assignment* m_assignment;
};

class Arithmetic: public Node {
public:
	enum ArithOperator {
		MOP_ADD = '+',
		MOP_SUB = '-',
		MOP_MUL = '*',
		MOP_DIV = '/',
		MOP_MOD = '%'
	};

	Arithmetic(ArithOperator op, Node* lhs, Node* rhs, const location& location)
		: Node(location), m_op(op), m_lhs(lhs), m_rhs(rhs) {}

	ArithOperator getOperator() const { return m_op; }
	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	ArithOperator m_op;
	Node* m_lhs;
	Node* m_rhs;
};

class Logic: public Node {
public:
	enum LogicOperator {
		LOP_EQUALS,
		LOP_OR,
		LOP_AND
	};

	Logic(LogicOperator op, Node* lhs, Node* rhs, const location& location)
		: Node(location), m_op(op), m_lhs(lhs), m_rhs(rhs) {}

	LogicOperator getOperator() const { return m_op; }
	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	LogicOperator m_op;
	Node* m_lhs;
	Node* m_rhs;
};

class Bitwise: public Node {
public:
	enum BitwiseOperator {
		BOP_AND,
		BOP_OR,
		BOP_XOR,
		BOP_LSHIFT,
		BOP_RSHIFT
	};

	Bitwise(BitwiseOperator op, Node* lhs, Node* rhs, const location& location)
		: Node(location), m_op(op), m_lhs(lhs), m_rhs(rhs) {}

	BitwiseOperator getOperator() const { return m_op; }
	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	BitwiseOperator m_op;
	Node* m_lhs;
	Node* m_rhs;
};

class FunctionDecl: public Node {
public:
	FunctionDecl(Ident* ident, NodeArray* args, Block* block, const location& location)<commit_msg>- More AST refcounting work<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#ifndef CLEVER_AST_H
#define CLEVER_AST_H

#include <vector>
#include "core/value.h"
#include "core/location.hh"
#include "core/astvisitor.h"
#include "core/clever.h"

namespace clever { namespace ast {

class Node;

typedef std::vector<Node*> NodeList;

class Node: public RefCounted {
public:
	Node(const location& location)
		: RefCounted(0), m_location(location) {}

	virtual ~Node() {}

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	const location& m_location;
};

class NodeArray: public Node {
public:
	NodeArray(const location& location)
		: Node(location) {}

	virtual ~NodeArray() { clearNodes(); }

	NodeList& getNodes() { return m_nodes; }

	Node* getFirst() {
		if (m_nodes.empty()) {
			return NULL;
		}

		return *(m_nodes.begin());
	}

	Node* append(Node* node) {
		m_nodes.push_back(node);
		CLEVER_ADDREF(node);
		return node;
	}

	size_t getSize() const { return m_nodes.size(); }

	virtual void accept(Visitor& visitor) {
		NodeList::iterator node(m_nodes.begin()), end(m_nodes.end());
		while (node != end) {
			(*node)->accept(visitor);
			++node;
		}
	}

	void clearNodes() {
		NodeList::iterator it = m_nodes.begin(), end = m_nodes.end();

		while (it != end) {
			CLEVER_DELREF((*it));
			++it;
		}
	}
protected:
	NodeList m_nodes;
};

class Block: public NodeArray {
public:
	Block(const location& location)
		: NodeArray(location) {}

	virtual void accept(Visitor& visitor) {	visitor.visit(this); }
};

class Assignment: public Node {
public:
	Assignment(Node* lhs, Node* rhs, const location& location)
		: Node(location), m_lhs(lhs), m_rhs(rhs) {
		CLEVER_ADDREF(m_lhs);
		CLEVER_ADDREF(m_rhs);
	}

	~Assignment() {
		CLEVER_DELREF(m_lhs);
		CLEVER_DELREF(m_rhs);
	}

	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }
private:
	Node* m_lhs;
	Node* m_rhs;
};

class Ident: public Node {
public:
	Ident(const CString* name, const location& location)
		: Node(location), m_name(name) {}

	const CString* getName() const { return m_name; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	const CString* m_name;
};

class Import: public Node {
public:
	Import(Ident* package, Ident* module, const location& location)
		: Node(location), m_package(package), m_module(module) {
		CLEVER_ADDREF(m_package);
		CLEVER_ADDREF(m_module);
	}

	~Import() {
		CLEVER_DELREF(m_package);
		CLEVER_DELREF(m_module);
	}

	Ident* getPackage() const { return m_package; }
	Ident* getModule() const { return m_module; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }
private:
	Ident* m_package;
	Ident* m_module;
};

class VariableDecl: public Node {
public:
	VariableDecl(Ident* ident, Assignment* assignment, const location& location)
		: Node(location), m_ident(ident), m_assignment(assignment) {
		CLEVER_ADDREF(m_ident);
		if (m_assignment) {
			CLEVER_ADDREF(m_assignment);
		}
	}

	~VariableDecl() {
		CLEVER_DELREF(m_ident);
		if (m_assignment) {
			CLEVER_DELREF(m_assignment);
		}
	}

	Ident* getIdent() const { return m_ident; }
	Assignment* getAssignment() { return m_assignment; }
	bool hasAssignment() const { return m_assignment != NULL; }

	virtual void accept(Visitor& visitor) {	visitor.visit(this); }

private:
	Ident* m_ident;
	Assignment* m_assignment;
};

class Arithmetic: public Node {
public:
	enum ArithOperator {
		MOP_ADD = '+',
		MOP_SUB = '-',
		MOP_MUL = '*',
		MOP_DIV = '/',
		MOP_MOD = '%'
	};

	Arithmetic(ArithOperator op, Node* lhs, Node* rhs, const location& location)
		: Node(location), m_op(op), m_lhs(lhs), m_rhs(rhs) {
		CLEVER_ADDREF(m_lhs);
		CLEVER_ADDREF(m_rhs);
	}

	~Arithmetic() {
		CLEVER_DELREF(m_lhs);
		CLEVER_DELREF(m_rhs);
	}

	ArithOperator getOperator() const { return m_op; }
	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	ArithOperator m_op;
	Node* m_lhs;
	Node* m_rhs;
};

class Logic: public Node {
public:
	enum LogicOperator {
		LOP_EQUALS,
		LOP_OR,
		LOP_AND
	};

	Logic(LogicOperator op, Node* lhs, Node* rhs, const location& location)
		: Node(location), m_op(op), m_lhs(lhs), m_rhs(rhs) {
		CLEVER_ADDREF(m_lhs);
		CLEVER_ADDREF(m_rhs);
	}

	~Logic() {
		CLEVER_DELREF(m_lhs);
		CLEVER_DELREF(m_rhs);
	}

	LogicOperator getOperator() const { return m_op; }
	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	LogicOperator m_op;
	Node* m_lhs;
	Node* m_rhs;
};

class Bitwise: public Node {
public:
	enum BitwiseOperator {
		BOP_AND,
		BOP_OR,
		BOP_XOR,
		BOP_LSHIFT,
		BOP_RSHIFT
	};

	Bitwise(BitwiseOperator op, Node* lhs, Node* rhs, const location& location)
		: Node(location), m_op(op), m_lhs(lhs), m_rhs(rhs) {
		CLEVER_ADDREF(m_lhs);
		CLEVER_ADDREF(m_rhs);
	}

	~Bitwise() {
		CLEVER_DELREF(m_lhs);
		CLEVER_DELREF(m_rhs);
	}

	BitwiseOperator getOperator() const { return m_op; }
	Node* getLhs() { return m_lhs; }
	Node* getRhs() { return m_rhs; }

	virtual void accept(Visitor& visitor) { visitor.visit(this); }

private:
	BitwiseOperator m_op;
	Node* m_lhs;
	Node* m_rhs;
};

class FunctionDecl: public Node {
public:
	FunctionDecl(Ident* ident, NodeArray* args, Block* block, const location& location)
{'fraction_non_alphanumeric': 0.13960887059043697, 'fraction_numerical': 0.00018714325816412465, 'mean_word_length': 4.703308431163287, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, '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': '7602761', 'n_tokens_mistral': 4235, 'n_tokens_neox': 4039, 'n_words': 934}