mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +00:00
function definition class structure changed, corresponding builders and printers fixes, fixes
This commit is contained in:
parent
18d7bdf5c1
commit
b4ce56b5f7
13 changed files with 323 additions and 284 deletions
|
|
@ -118,6 +118,8 @@ private:
|
|||
size_t indentation_level_ = 0;
|
||||
};
|
||||
|
||||
void print_modifier(const nodes::Modifier &modifier, Printer &printer);
|
||||
|
||||
void print_literal(const nodes::Literal &literal, Printer &printer);
|
||||
|
||||
void print_identifier(const nodes::Identifier &identifier, Printer &printer);
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ public:
|
|||
|
||||
private:
|
||||
ExpressionProxy(ExpressionStorage &expression_storage, size_t id)
|
||||
: expression_storage_(expression_storage), id_(id) {}
|
||||
: expression_storage_(&expression_storage), id_(id) {}
|
||||
|
||||
private:
|
||||
ExpressionStorage &expression_storage_;
|
||||
ExpressionStorage *expression_storage_;
|
||||
size_t id_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -66,24 +66,138 @@ public:
|
|||
VAR,
|
||||
};
|
||||
|
||||
class Argument {
|
||||
public:
|
||||
Argument(const std::optional<std::string> &annotation, Identifier &&name,
|
||||
Modifier before_modifier = Modifier::NONE,
|
||||
Modifier after_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), name_(std::move(name)),
|
||||
before_modifier_(before_modifier), after_modifier_(after_modifier) {}
|
||||
|
||||
Argument(const std::optional<std::string> &annotation,
|
||||
const Identifier &name, Modifier before_modifier = Modifier::NONE,
|
||||
Modifier after_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), name_(name),
|
||||
before_modifier_(before_modifier), after_modifier_(after_modifier) {}
|
||||
|
||||
Argument(const std::optional<std::string> &annotation, TypeProxy type,
|
||||
Modifier before_modifier = Modifier::NONE)
|
||||
: annotation_(annotation), type_(type),
|
||||
before_modifier_(before_modifier),
|
||||
after_modifier_(type.get()->get_modifier()) {}
|
||||
|
||||
//
|
||||
|
||||
bool add_type(const std::optional<std::string> &annotation, TypeProxy type,
|
||||
nodes::Modifier before_modifier = Modifier::NONE) {
|
||||
if (annotation_.has_value() &&
|
||||
(!annotation.has_value() ||
|
||||
annotation_.value() != annotation.value())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (before_modifier_ != Modifier::NONE &&
|
||||
before_modifier_ != before_modifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (after_modifier_ != Modifier::NONE &&
|
||||
after_modifier_ != type.get()->get_modifier()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = annotation;
|
||||
type_ = type;
|
||||
before_modifier_ = before_modifier;
|
||||
after_modifier_ = type.get()->get_modifier();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_annotation(const std::string &annotation) {
|
||||
if (annotation_.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
annotation_ = annotation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<std::string *> get_annotation() {
|
||||
if (annotation_.has_value()) {
|
||||
return &annotation_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_annotation() const {
|
||||
if (annotation_.has_value()) {
|
||||
return &annotation_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<Identifier *> get_name() {
|
||||
if (name_.has_value()) {
|
||||
return &name_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Identifier *> get_name() const {
|
||||
if (name_.has_value()) {
|
||||
return &name_.value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::optional<Type *> get_type() {
|
||||
if (type_.has_value()) {
|
||||
return type_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const Type *> get_type() const {
|
||||
if (type_.has_value()) {
|
||||
return type_.value().get();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Modifier get_before_modifier() const { return before_modifier_; }
|
||||
|
||||
Modifier get_after_modifier() const { return after_modifier_; }
|
||||
|
||||
private:
|
||||
std::optional<std::string> annotation_;
|
||||
std::optional<Identifier> name_; // no name for output arguments
|
||||
std::optional<TypeProxy> type_; // no type if it is deduced
|
||||
Modifier before_modifier_ =
|
||||
Modifier::NONE; // in, out, ref, none // sync with type
|
||||
Modifier after_modifier_ =
|
||||
Modifier::NONE; // optional, result, none // sync with type
|
||||
};
|
||||
|
||||
FunctionDefinition(Node node, SymbolDocs &&docs,
|
||||
std::vector<Constraint> &&constraints,
|
||||
ModifierType modifier, const Identifier &name,
|
||||
std::vector<std::optional<std::string>> &&annotations,
|
||||
std::vector<Identifier> &&arguments,
|
||||
std::vector<Modifier> &&reference_types,
|
||||
std::vector<TypeProxy> &&types,
|
||||
std::vector<bool> &&optional_arguments,
|
||||
std::vector<bool> &&result_arguments,
|
||||
bool is_annotations_same_to_names,
|
||||
std::vector<Argument> &&arguments,
|
||||
bool are_annotations_same_to_names,
|
||||
std::optional<ExpressionProxy> expression)
|
||||
: Node(node), docs_(std::move(docs)),
|
||||
constraints_(std::move(constraints)), modifier_(modifier), name_(name),
|
||||
annotations_(std::move(annotations)), arguments_(std::move(arguments)),
|
||||
reference_types_(std::move(reference_types)), types_(std::move(types)),
|
||||
optional_arguments_(optional_arguments),
|
||||
result_arguments_(result_arguments),
|
||||
is_annotations_same_to_names_(is_annotations_same_to_names),
|
||||
arguments_(std::move(arguments)),
|
||||
are_annotations_same_to_names_(are_annotations_same_to_names),
|
||||
expression_(expression) {}
|
||||
|
||||
//
|
||||
|
|
@ -114,57 +228,11 @@ public:
|
|||
|
||||
//
|
||||
|
||||
std::optional<std::string *> get_argument_annotation(size_t id) {
|
||||
if (annotations_.at(id).has_value()) {
|
||||
return &annotations_[id].value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<const std::string *> get_argument_annotation(size_t id) const {
|
||||
if (annotations_.at(id).has_value()) {
|
||||
return &annotations_[id].value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
size_t get_arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Identifier *get_argument(size_t id) { return &arguments_.at(id); }
|
||||
Argument *get_argument(size_t id) { return &arguments_.at(id); }
|
||||
|
||||
const Identifier *get_argument(size_t id) const { return &arguments_.at(id); }
|
||||
|
||||
//
|
||||
|
||||
Modifier get_argument_reference_type(size_t id) const {
|
||||
return reference_types_.at(id);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
size_t get_argument_types_size() const { return types_.size(); }
|
||||
|
||||
Type *get_argument_type(size_t id) { return types_.at(id).get(); }
|
||||
|
||||
const Type *get_argument_type(size_t id) const { return types_.at(id).get(); }
|
||||
|
||||
//
|
||||
|
||||
bool is_argument_optional(size_t id) const {
|
||||
return optional_arguments_.at(id);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool is_argument_result(size_t id) const { return result_arguments_.at(id); }
|
||||
|
||||
//
|
||||
|
||||
bool is_annotations_same_to_names() const {
|
||||
return is_annotations_same_to_names_;
|
||||
}
|
||||
const Argument *get_argument(size_t id) const { return &arguments_.at(id); }
|
||||
|
||||
//
|
||||
|
||||
|
|
@ -182,18 +250,19 @@ public:
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool are_annotations_same_to_names() const {
|
||||
return are_annotations_same_to_names_;
|
||||
}
|
||||
|
||||
private:
|
||||
SymbolDocs docs_;
|
||||
std::vector<Constraint> constraints_;
|
||||
ModifierType modifier_;
|
||||
Identifier name_;
|
||||
std::vector<std::optional<std::string>> annotations_;
|
||||
std::vector<Identifier> arguments_;
|
||||
std::vector<Modifier> reference_types_;
|
||||
std::vector<TypeProxy> types_;
|
||||
std::vector<bool> optional_arguments_;
|
||||
std::vector<bool> result_arguments_;
|
||||
bool is_annotations_same_to_names_;
|
||||
std::vector<Argument> arguments_;
|
||||
bool are_annotations_same_to_names_; // needed for easier prinitng process
|
||||
std::optional<ExpressionProxy> expression_;
|
||||
}; // refactor ??
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ public:
|
|||
|
||||
private:
|
||||
TypeProxy(TypeStorage &type_storage, size_t id)
|
||||
: type_storage_(type_storage), id_(id) {}
|
||||
: type_storage_(&type_storage), id_(id) {}
|
||||
|
||||
private:
|
||||
TypeStorage &type_storage_;
|
||||
TypeStorage *type_storage_;
|
||||
size_t id_;
|
||||
};
|
||||
|
||||
|
|
@ -35,28 +35,26 @@ private:
|
|||
class Type : public Node {
|
||||
public:
|
||||
Type(Node node, Identifier &&identifier, bool is_on_heap = false,
|
||||
bool is_optional = false, bool is_result = false)
|
||||
Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(std::move(identifier)), is_on_heap_(is_on_heap),
|
||||
is_optional_(is_optional), is_result_(is_result) {}
|
||||
modifier_(modifier) {}
|
||||
|
||||
Type(Node node, const Identifier &identifier, bool is_on_heap = false,
|
||||
bool is_optional = false, bool is_result = false)
|
||||
Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(identifier), is_on_heap_(is_on_heap),
|
||||
is_optional_(is_optional), is_result_(is_result) {}
|
||||
modifier_(modifier) {}
|
||||
|
||||
Type(Node node, Identifier &&identifier, std::vector<TypeProxy> &¶meters,
|
||||
bool is_on_heap = false, bool is_optional = false,
|
||||
bool is_result = false)
|
||||
bool is_on_heap = false, Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(std::move(identifier)),
|
||||
parameters_(std::move(parameters)), is_on_heap_(is_on_heap),
|
||||
is_optional_(is_optional), is_result_(is_result) {}
|
||||
modifier_(modifier) {}
|
||||
|
||||
Type(Node node, const Identifier &identifier,
|
||||
std::vector<TypeProxy> &¶meters, bool is_on_heap = false,
|
||||
bool is_optional = false, bool is_result = false)
|
||||
Modifier modifier = Modifier::NONE)
|
||||
: Node(node), name_(identifier), parameters_(std::move(parameters)),
|
||||
is_on_heap_(is_on_heap), is_optional_(is_optional),
|
||||
is_result_(is_result) {}
|
||||
is_on_heap_(is_on_heap), modifier_(modifier) {}
|
||||
|
||||
Identifier *get_name() { return &name_; }
|
||||
|
||||
|
|
@ -72,17 +70,14 @@ public:
|
|||
|
||||
bool is_on_heap() const { return is_on_heap_; }
|
||||
|
||||
bool is_optional() const { return is_optional_; }
|
||||
|
||||
bool is_result() const { return is_result_; }
|
||||
Modifier get_modifier() const { return modifier_; }
|
||||
|
||||
private:
|
||||
Identifier name_;
|
||||
std::vector<TypeProxy> parameters_;
|
||||
// or use allocator ??
|
||||
bool is_on_heap_ = false;
|
||||
bool is_optional_ = false;
|
||||
bool is_result_ = false;
|
||||
Modifier modifier_ = Modifier::NONE; // optional, result or none
|
||||
};
|
||||
|
||||
class TypeStorage {
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ nodes::Literal build_string_literal(parser::ParseTree::Node parser_node) {
|
|||
std::string literal = parser_node.get_value();
|
||||
|
||||
// remove " from both sides ("string")
|
||||
literal.pop_back();
|
||||
literal = literal.substr(1, literal.size() - 1);
|
||||
literal = literal.substr(1, literal.size() - 2);
|
||||
|
||||
// replace escape sequences with escape characters
|
||||
bool is_escape_symbol = false;
|
||||
|
|
@ -111,9 +110,7 @@ nodes::Literal build_char_literal(parser::ParseTree::Node parser_node) {
|
|||
std::string literal = parser_node.get_value();
|
||||
|
||||
// remove '' from both sides (''x'')
|
||||
literal.pop_back();
|
||||
literal.pop_back();
|
||||
literal = literal.substr(1, literal.size() - 2);
|
||||
literal = literal.substr(2, literal.size() - 4);
|
||||
|
||||
char ch = '\0';
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,30 @@
|
|||
|
||||
namespace printers {
|
||||
|
||||
void print_modifier(const nodes::Modifier &modifier, Printer &printer) {
|
||||
switch (modifier) {
|
||||
case nodes::Modifier::OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "out " : "-> ");
|
||||
break;
|
||||
case nodes::Modifier::IN:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- ");
|
||||
break;
|
||||
case nodes::Modifier::REF:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref " : "<> ");
|
||||
break;
|
||||
case nodes::Modifier::OR_FALSE:
|
||||
printer.print("?");
|
||||
break;
|
||||
case nodes::Modifier::OR_RETURN:
|
||||
printer.print("!");
|
||||
break;
|
||||
case nodes::Modifier::NONE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_literal(const nodes::Literal &literal, Printer &printer) {
|
||||
switch (literal.get_any()->index()) {
|
||||
case 0: // double
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
namespace nodes {
|
||||
|
||||
Expression *ExpressionProxy::get() {
|
||||
return expression_storage_.get_expression(id_);
|
||||
return expression_storage_->get_expression(id_);
|
||||
}
|
||||
|
||||
const Expression *ExpressionProxy::get() const {
|
||||
return expression_storage_.get_expression(id_);
|
||||
return expression_storage_->get_expression(id_);
|
||||
}
|
||||
|
||||
}; // namespace nodes
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include "basic_nodes.hpp"
|
||||
#include "basic_printers.hpp"
|
||||
#include "expression_nodes.hpp"
|
||||
#include "tokens.hpp"
|
||||
#include "type_printers.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
|
|
@ -331,48 +330,17 @@ void print_loop_control(const nodes::LoopControl &expression,
|
|||
|
||||
void print_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
printers::Printer &printer) {
|
||||
|
||||
if (printer.print_words_instead_of_symbols()) {
|
||||
switch (expression.get_modifier()) {
|
||||
case nodes::Modifier::OUT:
|
||||
printer.print("out ");
|
||||
break;
|
||||
case nodes::Modifier::IN:
|
||||
printer.print("in ");
|
||||
break;
|
||||
case nodes::Modifier::REF:
|
||||
printer.print("ref ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (expression.get_modifier()) {
|
||||
case nodes::Modifier::OUT:
|
||||
printer.print("-> ");
|
||||
break;
|
||||
case nodes::Modifier::IN:
|
||||
printer.print("<- ");
|
||||
break;
|
||||
case nodes::Modifier::REF:
|
||||
printer.print("<> ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (expression.get_modifier() == nodes::Modifier::OUT ||
|
||||
expression.get_modifier() == nodes::Modifier::IN ||
|
||||
expression.get_modifier() == nodes::Modifier::REF) {
|
||||
print_modifier(expression.get_modifier(), printer);
|
||||
}
|
||||
|
||||
print_expression(*expression.get_expression(), printer);
|
||||
|
||||
switch (expression.get_modifier()) {
|
||||
case nodes::Modifier::OR_FALSE:
|
||||
printer.print("?");
|
||||
break;
|
||||
case nodes::Modifier::OR_RETURN:
|
||||
printer.print("!");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (expression.get_modifier() == nodes::Modifier::OR_FALSE ||
|
||||
expression.get_modifier() == nodes::Modifier::OR_RETURN) {
|
||||
print_modifier(expression.get_modifier(), printer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,29 +254,32 @@ build_function_definition(parser::ParseTree::Node parser_node,
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::optional<std::string>> argument_annotations;
|
||||
std::vector<nodes::Modifier> argument_reference_types;
|
||||
std::vector<nodes::Identifier> arguments;
|
||||
std::vector<bool> optional_arguments;
|
||||
std::vector<bool> result_arguments;
|
||||
|
||||
std::vector<std::optional<std::string>> type_annotations;
|
||||
std::vector<nodes::Modifier> type_reference_types;
|
||||
std::vector<nodes::TypeProxy> types;
|
||||
std::vector<nodes::FunctionDefinition::Argument> arguments;
|
||||
std::vector<nodes::FunctionDefinition::Argument> argument_types;
|
||||
|
||||
std::optional<parser::ParseTree::Node> expression_node;
|
||||
|
||||
current_node = name_node.next_named_sibling();
|
||||
|
||||
bool at_least_one_argument_annotation_found = false;
|
||||
bool at_least_one_argument_modifier_found = false;
|
||||
|
||||
size_t current_type_id = 0;
|
||||
|
||||
std::optional<std::string> last_annotation;
|
||||
nodes::Modifier last_reference_type = nodes::Modifier::NONE;
|
||||
nodes::Modifier last_before_modifier = nodes::Modifier::NONE;
|
||||
nodes::Modifier last_after_modifier = nodes::Modifier::NONE;
|
||||
while (!current_node.is_null()) {
|
||||
// update last before modifier
|
||||
auto maybe_reference_node = current_node.previous_sibling();
|
||||
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
||||
last_reference_type = build_modifier(maybe_reference_node);
|
||||
last_before_modifier = build_modifier(maybe_reference_node);
|
||||
|
||||
// only out, in, ref allowed
|
||||
if (last_before_modifier != nodes::Modifier::OUT &&
|
||||
last_before_modifier != nodes::Modifier::IN &&
|
||||
last_before_modifier != nodes::Modifier::REF) {
|
||||
last_before_modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (tokens::string_to_type(current_node.get_type())) {
|
||||
|
|
@ -284,38 +287,50 @@ build_function_definition(parser::ParseTree::Node parser_node,
|
|||
last_annotation = build_annotation(current_node);
|
||||
break;
|
||||
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
|
||||
// update last after modifier
|
||||
maybe_reference_node = current_node.next_sibling();
|
||||
if (!maybe_reference_node.is_null() && !maybe_reference_node.is_named()) {
|
||||
last_after_modifier = build_modifier(maybe_reference_node);
|
||||
|
||||
// only optional, result allowed
|
||||
if (last_after_modifier != nodes::Modifier::OR_FALSE &&
|
||||
last_after_modifier != nodes::Modifier::OR_RETURN) {
|
||||
last_after_modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// update conditions
|
||||
if (last_annotation.has_value()) {
|
||||
at_least_one_argument_annotation_found = true;
|
||||
at_least_one_argument_modifier_found = true;
|
||||
}
|
||||
if (last_reference_type != nodes::Modifier::NONE) {
|
||||
at_least_one_argument_modifier_found = true;
|
||||
}
|
||||
|
||||
argument_annotations.push_back(last_annotation);
|
||||
argument_reference_types.push_back(last_reference_type);
|
||||
arguments.push_back(build_identifier(current_node));
|
||||
optional_arguments.push_back(!current_node.next_sibling().is_null() &&
|
||||
!current_node.next_sibling().is_named() &&
|
||||
current_node.next_sibling().get_value() ==
|
||||
"?");
|
||||
result_arguments.push_back(!current_node.next_sibling().is_null() &&
|
||||
!current_node.next_sibling().is_named() &&
|
||||
current_node.next_sibling().get_value() ==
|
||||
"!");
|
||||
if (optional_arguments.back() || result_arguments.back()) {
|
||||
at_least_one_argument_modifier_found = true;
|
||||
}
|
||||
arguments.push_back(nodes::FunctionDefinition::Argument(
|
||||
last_annotation, build_identifier(current_node), last_before_modifier,
|
||||
last_after_modifier));
|
||||
|
||||
last_reference_type = nodes::Modifier::NONE;
|
||||
last_annotation = std::nullopt;
|
||||
break;
|
||||
case tokens::Type::TYPE:
|
||||
type_annotations.push_back(last_annotation);
|
||||
type_reference_types.push_back(last_reference_type);
|
||||
types.push_back(build_type(current_node, type_storage));
|
||||
last_reference_type = nodes::Modifier::NONE;
|
||||
if (current_type_id >= arguments.size()) {
|
||||
arguments.push_back(nodes::FunctionDefinition::Argument(
|
||||
last_annotation, build_type(current_node, type_storage),
|
||||
last_before_modifier));
|
||||
} else {
|
||||
if (!arguments[current_type_id].add_type(
|
||||
last_annotation, build_type(current_node, type_storage),
|
||||
last_before_modifier)) {
|
||||
error_handling::handle_parsing_error(
|
||||
"It is impossible to use argument modifiers (annotations, "
|
||||
"references, "
|
||||
"optional markers, result markers) when types explicitely "
|
||||
"defined. Use type annotations instead.",
|
||||
current_node);
|
||||
}
|
||||
}
|
||||
|
||||
last_annotation = std::nullopt;
|
||||
|
||||
++current_type_id;
|
||||
break;
|
||||
default:
|
||||
if (expression_node.has_value()) {
|
||||
|
|
@ -329,38 +344,32 @@ build_function_definition(parser::ParseTree::Node parser_node,
|
|||
current_node = current_node.next_named_sibling();
|
||||
}
|
||||
|
||||
std::vector<std::optional<std::string>> *annotations = nullptr;
|
||||
std::vector<nodes::Modifier> *reference_types = nullptr;
|
||||
|
||||
bool is_annotations_same_to_names =
|
||||
(!at_least_one_argument_annotation_found && types.empty());
|
||||
|
||||
if (is_annotations_same_to_names) {
|
||||
for (size_t i = 0; i < argument_annotations.size(); ++i) {
|
||||
std::string argument_annotation = *arguments[i].get();
|
||||
argument_annotations[i] =
|
||||
argument_annotation.substr(1, argument_annotation.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (types.empty()) {
|
||||
annotations = &argument_annotations;
|
||||
reference_types = &argument_reference_types;
|
||||
} else if (at_least_one_argument_modifier_found) {
|
||||
if (current_type_id > 0 && current_type_id < arguments.size()) {
|
||||
error_handling::handle_parsing_error(
|
||||
"It is impossible to use argument modifiers (annotations, references, "
|
||||
"optional markers, result markers) when types explicitely "
|
||||
"defined. Use type annotations instead.",
|
||||
parser_node);
|
||||
} else {
|
||||
annotations = &type_annotations;
|
||||
reference_types = &type_reference_types;
|
||||
"Less types then arguments in function definition", parser_node);
|
||||
}
|
||||
|
||||
// automatic annotations
|
||||
bool are_annotations_same_to_names =
|
||||
(!at_least_one_argument_annotation_found && current_type_id == 0);
|
||||
|
||||
if (are_annotations_same_to_names) {
|
||||
for (size_t i = 0; i < arguments.size(); ++i) {
|
||||
std::string new_annotation = *arguments[i].get_name().value()->get();
|
||||
if (!arguments[i].add_annotation(
|
||||
new_annotation.substr(1, new_annotation.size() - 1))) {
|
||||
error_handling::handle_parsing_error(
|
||||
"no annotations provided ( => all annotations same to names), but "
|
||||
"can't add name annotation",
|
||||
current_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> annotations_set;
|
||||
for (auto &annotation : *annotations) {
|
||||
if (annotation.has_value()) {
|
||||
if (!annotations_set.insert(annotation.value()).second) {
|
||||
for (auto &argument : arguments) {
|
||||
if (argument.get_annotation().has_value()) {
|
||||
if (!annotations_set.insert(*argument.get_annotation().value()).second) {
|
||||
error_handling::handle_parsing_error(
|
||||
"Two or more same annotations found in function definition",
|
||||
parser_node);
|
||||
|
|
@ -372,15 +381,12 @@ build_function_definition(parser::ParseTree::Node parser_node,
|
|||
build_node(parser_node),
|
||||
build_symbol_docs(description_node, annotation_nodes, annotations_set),
|
||||
std::move(constraints), modifier, build_identifier(name_node),
|
||||
std::move(*annotations), std::move(arguments),
|
||||
std::move(*reference_types), std::move(types),
|
||||
std::move(optional_arguments), std::move(result_arguments),
|
||||
is_annotations_same_to_names,
|
||||
std::move(arguments), are_annotations_same_to_names,
|
||||
expression_node.has_value()
|
||||
? build_expression(expression_node.value(), expression_storage,
|
||||
type_storage)
|
||||
: std::optional<nodes::ExpressionProxy>());
|
||||
} // TODO: refactor ??
|
||||
}
|
||||
|
||||
// definition_info? annotation_info* typeclass_identifier (':'
|
||||
// typeclass_identifier+)? ('{' function_definition* '}' | ';')
|
||||
|
|
|
|||
|
|
@ -23,8 +23,19 @@ void print_import(const nodes::Import &statement, Printer &printer) {
|
|||
printer.print(" :");
|
||||
for (size_t i = 0; i < statement.symbols_size(); ++i) {
|
||||
printer.space();
|
||||
// TODO: properly print operator identifier
|
||||
|
||||
bool identifier_is_operator =
|
||||
(statement.get_symbol(i)->get_type() == nodes::Identifier::OPERATOR);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print("( ");
|
||||
}
|
||||
|
||||
print_identifier(*statement.get_symbol(i), printer);
|
||||
|
||||
if (identifier_is_operator) {
|
||||
printer.print(" )");
|
||||
}
|
||||
}
|
||||
}
|
||||
printer.print(";");
|
||||
|
|
@ -60,7 +71,7 @@ void print_statement_methods(const T &statement, Printer &printer) {
|
|||
|
||||
void print_type_definition(const nodes::TypeDefinition &statement,
|
||||
Printer &printer) {
|
||||
print_docs(*statement.get_docs(), printer); // TODO
|
||||
print_docs(*statement.get_docs(), printer);
|
||||
|
||||
if (statement.is_on_heap()) {
|
||||
printer.print("^");
|
||||
|
|
@ -90,7 +101,7 @@ void print_type_definition(const nodes::TypeDefinition &statement,
|
|||
|
||||
void print_function_definition(const nodes::FunctionDefinition &statement,
|
||||
Printer &printer) {
|
||||
print_docs(*statement.get_docs(), printer); // TODO
|
||||
print_docs(*statement.get_docs(), printer);
|
||||
|
||||
for (size_t i = 0; i < statement.get_constraints_size(); ++i) {
|
||||
print_constraint(*statement.get_constraint(i), printer);
|
||||
|
|
@ -110,95 +121,65 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
|
|||
break;
|
||||
}
|
||||
|
||||
bool operator_called_as_function =
|
||||
bool identifier_is_operator =
|
||||
(statement.get_name()->get_type() == nodes::Identifier::OPERATOR);
|
||||
|
||||
if (operator_called_as_function) {
|
||||
if (identifier_is_operator) {
|
||||
printer.print("( ");
|
||||
}
|
||||
|
||||
print_identifier(*statement.get_name(), printer);
|
||||
|
||||
if (operator_called_as_function) {
|
||||
if (identifier_is_operator) {
|
||||
printer.print(" )");
|
||||
}
|
||||
|
||||
// TODO: same fragments with function type, maybe better make separated
|
||||
// function
|
||||
for (size_t i = 0; i < statement.get_arguments_size(); ++i) {
|
||||
if (!statement.get_argument(i)->get_name().has_value()) {
|
||||
break;
|
||||
}
|
||||
|
||||
printer.space();
|
||||
|
||||
// all arguments are typed or are untyped in the same time
|
||||
if (!statement.get_argument(i)->get_type().has_value()) {
|
||||
|
||||
// print annotation
|
||||
if (!statement.are_annotations_same_to_names() &&
|
||||
statement.get_argument(i)->get_annotation().has_value()) {
|
||||
print_annotation(*statement.get_argument(i)->get_annotation().value(),
|
||||
printer);
|
||||
printer.space();
|
||||
}
|
||||
|
||||
print_modifier(statement.get_argument(i)->get_before_modifier(), printer);
|
||||
}
|
||||
|
||||
print_identifier(*statement.get_argument(i)->get_name().value(), printer);
|
||||
|
||||
// all arguments are typed or are untyped in the same time
|
||||
if (!statement.get_argument(i)->get_type().has_value()) {
|
||||
print_modifier(statement.get_argument(i)->get_after_modifier(), printer);
|
||||
}
|
||||
}
|
||||
|
||||
// all arguments are typed or are untyped in the same time
|
||||
if (statement.get_arguments_size() > 0 &&
|
||||
statement.get_argument(0)->get_type().has_value()) {
|
||||
|
||||
printer.print(" :");
|
||||
|
||||
for (size_t i = 0; i < statement.get_arguments_size(); ++i) {
|
||||
printer.space();
|
||||
|
||||
if (statement.get_argument_types_size() == 0) {
|
||||
if (!statement.is_annotations_same_to_names() &&
|
||||
statement.get_argument_annotation(i).has_value()) {
|
||||
print_annotation(*statement.get_argument_annotation(i).value(),
|
||||
if (statement.get_argument(i)->get_annotation().has_value()) {
|
||||
print_annotation(*statement.get_argument(i)->get_annotation().value(),
|
||||
printer);
|
||||
printer.space();
|
||||
}
|
||||
|
||||
switch (statement.get_argument_reference_type(i)) {
|
||||
case nodes::Modifier::OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "out "
|
||||
: "-> ");
|
||||
break;
|
||||
case nodes::Modifier::IN:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- ");
|
||||
break;
|
||||
case nodes::Modifier::REF:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref "
|
||||
: "<> ");
|
||||
break;
|
||||
case nodes::Modifier::NONE:
|
||||
break;
|
||||
default: // TODO: handle errors ??
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_modifier(statement.get_argument(i)->get_before_modifier(), printer);
|
||||
|
||||
print_identifier(*statement.get_argument(i), printer);
|
||||
|
||||
if (statement.get_argument_types_size() == 0) {
|
||||
// TODO: can't be optional and result in same time
|
||||
|
||||
if (statement.is_argument_optional(i)) {
|
||||
printer.print("?");
|
||||
}
|
||||
|
||||
if (statement.is_argument_result(i)) {
|
||||
printer.print("!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (statement.get_argument_types_size() > 0) {
|
||||
printer.print(" :");
|
||||
for (size_t i = 0; i < statement.get_argument_types_size(); ++i) {
|
||||
printer.space();
|
||||
if (statement.get_argument_annotation(i).has_value()) {
|
||||
print_annotation(*statement.get_argument_annotation(i).value(),
|
||||
printer);
|
||||
printer.space();
|
||||
}
|
||||
|
||||
switch (statement.get_argument_reference_type(i)) {
|
||||
case nodes::Modifier::OUT:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "out "
|
||||
: "-> ");
|
||||
break;
|
||||
case nodes::Modifier::IN:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "in " : "<- ");
|
||||
break;
|
||||
case nodes::Modifier::REF:
|
||||
printer.print(printer.print_words_instead_of_symbols() ? "ref "
|
||||
: "<> ");
|
||||
break;
|
||||
case nodes::Modifier::NONE:
|
||||
break;
|
||||
default: // TODO: handle errors ??
|
||||
break;
|
||||
}
|
||||
|
||||
print_type(*statement.get_argument_type(i), printer);
|
||||
print_type(*statement.get_argument(i)->get_type().value(), printer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +199,7 @@ void print_function_definition(const nodes::FunctionDefinition &statement,
|
|||
|
||||
void print_typeclass_definition(const nodes::TypeclassDefinition &statement,
|
||||
Printer &printer) {
|
||||
print_docs(*statement.get_docs(), printer); // TODO
|
||||
print_docs(*statement.get_docs(), printer);
|
||||
|
||||
print_identifier(*statement.get_name(), printer);
|
||||
|
||||
|
|
@ -234,5 +215,3 @@ void print_typeclass_definition(const nodes::TypeclassDefinition &statement,
|
|||
} // IN PROGRESS
|
||||
|
||||
} // namespace printers
|
||||
|
||||
// TODO: print operator in ()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "type_builders.hpp"
|
||||
#include "basic_builders.hpp"
|
||||
#include "basic_nodes.hpp"
|
||||
#include "tokens.hpp"
|
||||
|
||||
namespace builders {
|
||||
|
|
@ -15,12 +16,19 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parse_node,
|
|||
bool is_on_heap = (!current_node.is_null() && !current_node.is_named() &&
|
||||
current_node.get_value() == "^");
|
||||
|
||||
current_node = name_node.next_sibling();
|
||||
bool is_optional = (!current_node.is_null() && !current_node.is_named() &&
|
||||
current_node.get_value() == "?");
|
||||
nodes::Modifier modifier = nodes::Modifier::NONE;
|
||||
|
||||
bool is_result = (!current_node.is_null() && !current_node.is_named() &&
|
||||
current_node.get_value() == "!");
|
||||
current_node = name_node.next_sibling();
|
||||
// update last after modifier
|
||||
if (!current_node.is_null() && !current_node.is_named()) {
|
||||
modifier = build_modifier(current_node);
|
||||
|
||||
// only optional, result allowed
|
||||
if (modifier != nodes::Modifier::OR_FALSE &&
|
||||
modifier != nodes::Modifier::OR_RETURN) {
|
||||
modifier = nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
current_node = name_node.next_named_sibling();
|
||||
while (!current_node.is_null()) {
|
||||
|
|
@ -30,7 +38,7 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parse_node,
|
|||
|
||||
return type_storage.add_type(
|
||||
nodes::Type(build_node(parse_node), build_identifier(name_node),
|
||||
std::move(parameters), is_on_heap, is_optional, is_result));
|
||||
std::move(parameters), is_on_heap, modifier));
|
||||
}
|
||||
|
||||
// '&'? annotation? type ('&' annotation? type)*
|
||||
|
|
|
|||
|
|
@ -2,12 +2,8 @@
|
|||
|
||||
namespace nodes {
|
||||
|
||||
Type* TypeProxy::get() {
|
||||
return type_storage_.get_type(id_);
|
||||
}
|
||||
Type *TypeProxy::get() { return type_storage_->get_type(id_); }
|
||||
|
||||
const Type* TypeProxy::get() const {
|
||||
return type_storage_.get_type(id_);
|
||||
}
|
||||
const Type *TypeProxy::get() const { return type_storage_->get_type(id_); }
|
||||
|
||||
}; // namespace nodes
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "type_printers.hpp"
|
||||
#include "basic_nodes.hpp"
|
||||
#include "basic_printers.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
|
|
@ -11,13 +12,7 @@ void print_type(const nodes::Type &type, printers::Printer &printer) {
|
|||
|
||||
print_identifier(*type.get_name(), printer);
|
||||
|
||||
if (type.is_optional()) {
|
||||
printer.print("?");
|
||||
}
|
||||
|
||||
if (type.is_result()) {
|
||||
printer.print("!");
|
||||
}
|
||||
print_modifier(type.get_modifier(), printer);
|
||||
|
||||
if (type.get_parametrs_size() > 0) {
|
||||
printer.print("[");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue