forked from KPGPMC/furlang
Add default constructor to handle
Signed-off-by: CHatingPython <chatingpython@gmail.com>
This commit is contained in:
@@ -5,7 +5,6 @@
|
|||||||
#include "furc/ast/statement.hpp"
|
#include "furc/ast/statement.hpp"
|
||||||
#include "furc/front/token.hpp"
|
#include "furc/front/token.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace furc {
|
namespace furc {
|
||||||
@@ -42,9 +41,7 @@ public:
|
|||||||
|
|
||||||
front::token name() const { return m_name; }
|
front::token name() const { return m_name; }
|
||||||
public:
|
public:
|
||||||
std::ostream& print(std::ostream& os) const override {
|
std::ostream& print(std::ostream& os) const override;
|
||||||
return os << "function " << m_name->string << " declaration";
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
front::token m_name;
|
front::token m_name;
|
||||||
};
|
};
|
||||||
@@ -74,16 +71,7 @@ public:
|
|||||||
|
|
||||||
const function_body_handle& body() const { return m_body; }
|
const function_body_handle& body() const { return m_body; }
|
||||||
public:
|
public:
|
||||||
std::ostream& print(std::ostream& os) const override {
|
std::ostream& print(std::ostream& os) const override;
|
||||||
function_declarartion_node::print(os);
|
|
||||||
os << ':';
|
|
||||||
if (m_body.present()) {
|
|
||||||
for (const auto& entry : m_body->statements)
|
|
||||||
os << '\n' << entry;
|
|
||||||
return os << '\n' << m_body->end << ": " << m_name->string << " end";
|
|
||||||
}
|
|
||||||
return os << m_body.error(); // error
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
function_body_handle m_body;
|
function_body_handle m_body;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#include "furc/ast/node.hpp"
|
#include "furc/ast/node.hpp"
|
||||||
#include "furc/front/token.hpp"
|
#include "furc/front/token.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace furc {
|
namespace furc {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
@@ -50,10 +48,7 @@ public:
|
|||||||
|
|
||||||
const handle<front::integer_token>& value() const { return m_value; }
|
const handle<front::integer_token>& value() const { return m_value; }
|
||||||
public:
|
public:
|
||||||
std::ostream& print(std::ostream& os) const override {
|
std::ostream& print(std::ostream& os) const override;
|
||||||
if (m_value.has_error()) return os << m_value.error();
|
|
||||||
return os << "integer literal (" << *m_value << ")";
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
handle<front::integer_token> m_value;
|
handle<front::integer_token> m_value;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "furc/ast/declaration.hpp"
|
#include "furc/ast/declaration.hpp"
|
||||||
#include "furc/ast/node.hpp"
|
#include "furc/ast/node.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace furc {
|
namespace furc {
|
||||||
@@ -20,13 +19,7 @@ public:
|
|||||||
|
|
||||||
const std::vector<node_handle<declaration_node>>& declarations() const { return m_declarations; }
|
const std::vector<node_handle<declaration_node>>& declarations() const { return m_declarations; }
|
||||||
public:
|
public:
|
||||||
std::ostream& print(std::ostream& os) const override {
|
std::ostream& print(std::ostream& os) const override;
|
||||||
os << "program:";
|
|
||||||
for (const auto& handle : m_declarations) {
|
|
||||||
os << '\n' << handle;
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
std::vector<node_handle<declaration_node>> m_declarations;
|
std::vector<node_handle<declaration_node>> m_declarations;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#include "furc/ast/node.hpp"
|
#include "furc/ast/node.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace furc {
|
namespace furc {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
@@ -21,13 +19,19 @@ public:
|
|||||||
virtual statement_node_t statement_type() const = 0;
|
virtual statement_node_t statement_type() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class expression_node;
|
||||||
class return_statement_node : public statement_node {
|
class return_statement_node : public statement_node {
|
||||||
public:
|
public:
|
||||||
return_statement_node() = default;
|
return_statement_node() = default;
|
||||||
|
|
||||||
|
return_statement_node(node_handle<expression_node>&& value)
|
||||||
|
: m_value(std::move(value)) {}
|
||||||
public:
|
public:
|
||||||
statement_node_t statement_type() const override { return statement_node_t::Return; }
|
statement_node_t statement_type() const override { return statement_node_t::Return; }
|
||||||
|
|
||||||
std::ostream& print(std::ostream& os) const override { return os << "return statement"; }
|
std::ostream& print(std::ostream& os) const override;
|
||||||
|
private:
|
||||||
|
node_handle<expression_node> m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
|||||||
+106
-45
@@ -105,6 +105,8 @@ class handle<T*, Error> {
|
|||||||
template <typename, typename, typename>
|
template <typename, typename, typename>
|
||||||
friend class handle;
|
friend class handle;
|
||||||
|
|
||||||
|
friend struct data;
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& os, const handle& result);
|
friend std::ostream& operator<<(std::ostream& os, const handle& result);
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
@@ -113,92 +115,151 @@ public:
|
|||||||
using reference = T&;
|
using reference = T&;
|
||||||
using const_reference = const T&;
|
using const_reference = const T&;
|
||||||
public:
|
public:
|
||||||
template <typename U = value_type, typename = std::enable_if_t<std::is_base_of_v<value_type, U>>>
|
handle() = default;
|
||||||
handle(location location, std::shared_ptr<U> value)
|
|
||||||
: m_location(location), m_value(value) {}
|
|
||||||
|
|
||||||
template <typename U, typename = std::enable_if_t<std::is_base_of_v<U, value_type>>>
|
template <typename U, typename = std::enable_if_t<std::is_base_of_v<value_type, U>>>
|
||||||
|
handle(location location, std::shared_ptr<U> value)
|
||||||
|
: m_data(data(location, value)) {}
|
||||||
|
|
||||||
|
template <typename U,
|
||||||
|
typename = std::enable_if_t<std::is_base_of_v<value_type, U> || std::is_base_of_v<U, value_type>>>
|
||||||
handle(const handle<U*, Error>& other)
|
handle(const handle<U*, Error>& other)
|
||||||
: m_location(other.m_location), m_value(std::dynamic_pointer_cast<value_type>(other.m_value)) {}
|
: m_data(data{ other }) {}
|
||||||
|
|
||||||
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
||||||
handle(location location, Args&&... args)
|
handle(location location, Args&&... args)
|
||||||
: m_location(location), m_value(std::make_shared<value_type>(std::forward<Args>(args)...)) {}
|
: m_data(data(location, std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
||||||
handle(location location, furlang::arena& arena, Args&&... args)
|
handle(location location, furlang::arena& arena, Args&&... args)
|
||||||
: m_location(location), m_value(arena.allocate_shared<value_type>(std::forward<Args>(args)...)) {}
|
: m_data(data(location, arena, std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
handle(location location, Error&& error)
|
handle(location location, Error&& error)
|
||||||
: m_location(location), m_error(std::move(error)) {}
|
: m_data(data(location, std::move(error))) {}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
handle(const handle<U, Error>& error)
|
handle(const handle<U, Error>& error)
|
||||||
: m_location(error.location()), m_error(error.error()) {}
|
: m_data(data(error)) {}
|
||||||
|
|
||||||
~handle() = default;
|
~handle() = default;
|
||||||
|
|
||||||
handle(handle&& other) noexcept
|
handle(handle&& other) noexcept
|
||||||
: m_location(other.m_location), m_value(std::move(other.m_value)), m_error(std::move(other.m_error)) {
|
: m_data(std::move(other.m_data)) {}
|
||||||
other.m_value = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U = value_type,
|
template <typename U, typename = std::enable_if_t<std::is_base_of_v<value_type, U>>>
|
||||||
typename = std::enable_if_t<std::is_base_of_v<value_type, U> || std::is_base_of_v<U, value_type>>>
|
handle(handle<U*, Error>&& other) noexcept
|
||||||
handle(handle<U*, Error>&& other) noexcept // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
|
: m_data(data{ std::move(other) }) {}
|
||||||
: m_location(other.m_location), m_value(std::move(other.m_value)), m_error(std::move(other.m_error)) {
|
|
||||||
other.m_value = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle(const handle& other)
|
handle(const handle& other)
|
||||||
: m_location(other.m_location), m_value(other.m_value), m_error(other.m_error) {}
|
: m_data(other.m_data) {}
|
||||||
|
|
||||||
handle& operator=(handle&& other) noexcept {
|
handle& operator=(handle&& other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
m_location = other.m_location;
|
m_data = std::move(other.m_data);
|
||||||
m_value = std::move(other.m_value);
|
|
||||||
m_error = std::move(other.m_error);
|
|
||||||
other.m_value = nullptr;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle& operator=(const handle& other) {
|
handle& operator=(const handle& other) {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
m_location = other.m_location;
|
m_data = other.m_data;
|
||||||
m_value = other.m_value;
|
|
||||||
m_error = other.m_error;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
location location() const { return m_location; }
|
location location() const { return m_data->location; }
|
||||||
|
|
||||||
bool present() const { return m_value != nullptr; }
|
bool present() const { return m_data.has_value() && m_data->value != nullptr; }
|
||||||
bool has_error() const { return m_value == nullptr; }
|
bool has_error() const { return m_data.has_value() && m_data->value == nullptr; }
|
||||||
|
|
||||||
std::shared_ptr<value_type> shared() { return m_value; }
|
std::shared_ptr<value_type> shared() const { return m_data->value; }
|
||||||
Error error() const { return m_error; }
|
Error error() const { return m_data->error; }
|
||||||
|
|
||||||
operator reference() { return *m_value; }
|
reference operator*() { return *m_data->value; }
|
||||||
operator const_reference() const { return *m_value; }
|
const_reference operator*() const { return *m_data->value; }
|
||||||
|
pointer operator->() { return m_data->value.get(); }
|
||||||
reference operator*() { return *m_value; }
|
const_pointer operator->() const { return m_data->value.get(); }
|
||||||
const_reference operator*() const { return *m_value; }
|
|
||||||
pointer operator->() { return m_value.get(); }
|
|
||||||
const_pointer operator->() const { return m_value.get(); }
|
|
||||||
public:
|
public:
|
||||||
friend std::ostream& operator<<(std::ostream& os, const handle& result) {
|
friend std::ostream& operator<<(std::ostream& os, const handle& result) {
|
||||||
os << result.m_location << ": ";
|
if (!result.m_data.has_value()) return os << "handle empty";
|
||||||
if (result.m_value != nullptr) {
|
os << result.m_data->location << ": ";
|
||||||
os << *result.m_value;
|
if (result.m_data->value != nullptr) {
|
||||||
|
os << *result.m_data->value;
|
||||||
} else {
|
} else {
|
||||||
os << "ERROR: " << result.m_error;
|
os << "ERROR: " << result.m_data->error;
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
struct location m_location;
|
struct data {
|
||||||
std::shared_ptr<value_type> m_value = nullptr;
|
struct location location;
|
||||||
Error m_error;
|
std::shared_ptr<value_type> value = nullptr;
|
||||||
|
Error error = {};
|
||||||
|
|
||||||
|
template <typename U, typename = std::enable_if_t<std::is_base_of_v<value_type, U>>>
|
||||||
|
data(struct location location, std::shared_ptr<U> value)
|
||||||
|
: location(location), value(value) {}
|
||||||
|
|
||||||
|
template <typename U,
|
||||||
|
typename = std::enable_if_t<std::is_base_of_v<value_type, U> || std::is_base_of_v<U, value_type>>>
|
||||||
|
data(handle<U*, Error>&& other) // NOLINT
|
||||||
|
: location(other.m_data->location) {
|
||||||
|
if constexpr (std::is_base_of_v<value_type, U>) {
|
||||||
|
value = std::static_pointer_cast<value_type>(std::move(other.m_data->value));
|
||||||
|
} else {
|
||||||
|
value = std::dynamic_pointer_cast<value_type>(std::move(other.m_data->value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U,
|
||||||
|
typename = std::enable_if_t<std::is_base_of_v<value_type, U> || std::is_base_of_v<U, value_type>>>
|
||||||
|
data(const handle<U*, Error>& other)
|
||||||
|
: location(other.m_data->location) {
|
||||||
|
if constexpr (std::is_base_of_v<value_type, U>) {
|
||||||
|
value = std::static_pointer_cast<value_type>(std::move(other.m_data->value));
|
||||||
|
} else {
|
||||||
|
value = std::dynamic_pointer_cast<value_type>(std::move(other.m_data->value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
||||||
|
data(struct location location, Args&&... args)
|
||||||
|
: location(location), value(std::make_shared<value_type>(std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
|
||||||
|
data(struct location location, furlang::arena& arena, Args&&... args)
|
||||||
|
: location(location), value(arena.allocate_shared<value_type>(std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
|
data(struct location location, Error&& error)
|
||||||
|
: location(location), error(std::move(error)) {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
data(const handle<U, Error>& error)
|
||||||
|
: location(error.location()), error(error.error()) {}
|
||||||
|
|
||||||
|
~data() = default;
|
||||||
|
|
||||||
|
data(data&& other) noexcept
|
||||||
|
: location(other.location), value(std::move(other.value)), error(std::move(other.error)) {}
|
||||||
|
|
||||||
|
data(const data& other)
|
||||||
|
: location(other.location), value(other.value), error(other.error) {}
|
||||||
|
|
||||||
|
data& operator=(data&& other) noexcept {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
location = other.location;
|
||||||
|
value = std::move(other.value);
|
||||||
|
error = std::move(other.error);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
data& operator=(const data& other) noexcept {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
location = other.location;
|
||||||
|
value = other.value;
|
||||||
|
error = other.error;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::optional<data> m_data = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace furc
|
} // namespace furc
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "furc/ast/declaration.hpp"
|
||||||
|
#include "furc/ast/literal.hpp"
|
||||||
|
#include "furc/ast/node.hpp"
|
||||||
|
#include "furc/ast/program.hpp"
|
||||||
|
#include "furc/ast/statement.hpp"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace furc::ast {
|
||||||
|
|
||||||
|
std::ostream& integer_literal_node::print(std::ostream& os) const {
|
||||||
|
if (m_value.has_error()) return os << m_value.error();
|
||||||
|
return os << "integer literal (" << *m_value << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& function_declarartion_node::print(std::ostream& os) const {
|
||||||
|
return os << "function " << m_name->string << " declaration";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& function_definition_node::print(std::ostream& os) const {
|
||||||
|
function_declarartion_node::print(os);
|
||||||
|
os << ':';
|
||||||
|
if (m_body.present()) {
|
||||||
|
for (const auto& entry : m_body->statements)
|
||||||
|
os << '\n' << entry;
|
||||||
|
return os << '\n' << m_body->end << ": " << m_name->string << " end";
|
||||||
|
}
|
||||||
|
return os << m_body.error(); // error
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& return_statement_node::print(std::ostream& os) const {
|
||||||
|
os << "return statement";
|
||||||
|
if (m_value.present()) return os << " (" << *m_value << ')';
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& program_node::print(std::ostream& os) const {
|
||||||
|
os << "program:";
|
||||||
|
for (const auto& handle : m_declarations) {
|
||||||
|
os << '\n' << handle;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace furc::ast
|
||||||
@@ -93,11 +93,16 @@ ast::node_handle<ast::statement_node> parser::parse_statement() {
|
|||||||
if (tok.has_error()) return tok;
|
if (tok.has_error()) return tok;
|
||||||
switch (tok->type) {
|
switch (tok->type) {
|
||||||
case token_t::Keyword: {
|
case token_t::Keyword: {
|
||||||
|
auto tok = next_token();
|
||||||
|
if (peek_token()->type == token_t::Semicolon) {
|
||||||
next_token();
|
next_token();
|
||||||
|
return ast::node_handle<ast::return_statement_node>{ tok.location(), m_arena };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value = parse_expression();
|
||||||
auto err = eat_token(token_t::Semicolon);
|
auto err = eat_token(token_t::Semicolon);
|
||||||
if (err.has_error()) return err;
|
if (err.has_error()) return err;
|
||||||
|
return ast::node_handle<ast::return_statement_node>{ tok.location(), m_arena, std::move(value) };
|
||||||
return ast::node_handle<ast::return_statement_node>{ tok.location(), m_arena };
|
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
furc::front::parser parser("<TEMP>", "func main() {\n return;\n}");
|
furc::front::parser parser("<TEMP>", "func main() {\n return 67;return \"uwu\";\n}");
|
||||||
std::cout << parser.parse() << '\n';
|
std::cout << parser.parse() << '\n';
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user