From 0c4afe87d9f96b1be16cf651343ddb3727e513dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borna=20Rajkovi=C4=87?= Date: Fri, 27 May 2022 08:18:17 +0200 Subject: [PATCH] Basic refactor --- CMakeLists.txt | 27 +- comdel/display/attribute_dialog.cpp | 275 +- comdel/display/attribute_dialog.h | 263 +- comdel/display/component_display.cpp | 218 +- comdel/display/component_display.h | 243 +- comdel/display/library_display.cpp | 68 +- comdel/display/library_display.h | 19 +- comdel/display/library_list.cpp | 11 +- comdel/display/library_list.h | 8 +- comdel/display/name_dialog.cpp | 37 + comdel/display/name_dialog.h | 50 +- comdel/display/schema_display.cpp | 187 +- comdel/display/schema_display.h | 107 +- comdel/domain/address_space.cpp | 29 + comdel/domain/address_space.h | 29 + comdel/domain/addressspace.cpp | 28 - comdel/domain/addressspace.h | 27 - comdel/domain/attribute.cpp | 90 +- comdel/domain/attribute.h | 95 +- comdel/domain/bus.cpp | 93 +- comdel/domain/bus.h | 109 +- comdel/domain/comdel_generator.cpp | 590 +-- comdel/domain/comdel_generator.h | 4 +- comdel/domain/comdel_validator.cpp | 206 + comdel/domain/comdel_validator.h | 52 + comdel/domain/comdelvalidator.cpp | 187 - comdel/domain/comdelvalidator.h | 54 - comdel/domain/component.cpp | 155 +- comdel/domain/component.h | 103 +- comdel/domain/connection.cpp | 111 +- comdel/domain/connection.h | 99 +- comdel/domain/connection_instance.cpp | 29 + comdel/domain/connection_instance.h | 49 + comdel/domain/connectioninstance.cpp | 28 - comdel/domain/connectioninstance.h | 50 - comdel/domain/display.cpp | 168 +- comdel/domain/display.h | 314 +- comdel/domain/function_signature.cpp | 166 + comdel/domain/function_signature.h | 36 + comdel/domain/functionsignature.cpp | 138 - comdel/domain/functionsignature.h | 53 - comdel/domain/instance.cpp | 19 +- comdel/domain/instance.h | 43 +- comdel/domain/instance_attribute.cpp | 8 + comdel/domain/instance_attribute.h | 25 + comdel/domain/instanceattribute.cpp | 9 - comdel/domain/instanceattribute.h | 27 - comdel/domain/library.cpp | 213 +- comdel/domain/library.h | 96 +- comdel/domain/pin.cpp | 65 +- comdel/domain/pin.h | 88 +- comdel/domain/rule.cpp | 89 +- comdel/domain/rule.h | 92 +- comdel/domain/schema.cpp | 50 +- comdel/domain/schema.h | 42 +- comdel/domain/schema_creator.cpp | 1079 +++++ comdel/domain/schema_creator.h | 93 + comdel/domain/schemacreator.cpp | 1003 ----- comdel/domain/schemacreator.h | 153 - comdel/domain/value.cpp | 311 +- comdel/domain/value.h | 169 +- comdel/domain/wireinstance.cpp | 10 - comdel/domain/wireinstance.h | 24 - comdel/parser/{astnode.cpp => ast_nodes.cpp} | 26 +- comdel/parser/{astnode.h => ast_nodes.h} | 159 +- .../{comdelparser.cpp => comdel_parser.cpp} | 437 +- .../{comdelparser.h => comdel_parser.h} | 71 +- comdel/parser/comdellexer.cpp | 205 +- comdel/parser/comdellexer.h | 19 +- comdel/parser/expected.h | 3774 +++++++++-------- .../{parsecontext.cpp => parse_context.cpp} | 48 +- .../{parsecontext.h => parse_context.h} | 21 +- .../{parserutil.cpp => parser_util.cpp} | 50 +- comdel/parser/parser_util.h | 15 + comdel/parser/parserutil.h | 15 - comdel/parser/poly.h | 258 +- comdel/parser/presult.h | 11 +- comdel/parser/source_error.cpp | 5 + .../parser/{sourceerror.h => source_error.h} | 0 comdel/parser/sourceerror.cpp | 6 - comdel/parser/token.cpp | 25 +- comdel/parser/token.h | 5 +- comdel/parser/tokens_type.cpp | 173 + comdel/parser/{tokenstype.h => tokens_type.h} | 2 +- comdel/parser/tokenstype.cpp | 176 - examples/simplified FRISC model/comdel.system | 26 +- examples/simplified FRISC model/schema3.csl | 22 +- mainwindow.cpp | 18 +- mainwindow.h | 2 +- 89 files changed, 7110 insertions(+), 6772 deletions(-) create mode 100644 comdel/domain/address_space.cpp create mode 100644 comdel/domain/address_space.h delete mode 100644 comdel/domain/addressspace.cpp delete mode 100644 comdel/domain/addressspace.h create mode 100644 comdel/domain/comdel_validator.cpp create mode 100644 comdel/domain/comdel_validator.h delete mode 100644 comdel/domain/comdelvalidator.cpp delete mode 100644 comdel/domain/comdelvalidator.h create mode 100644 comdel/domain/connection_instance.cpp create mode 100644 comdel/domain/connection_instance.h delete mode 100644 comdel/domain/connectioninstance.cpp delete mode 100644 comdel/domain/connectioninstance.h create mode 100644 comdel/domain/function_signature.cpp create mode 100644 comdel/domain/function_signature.h delete mode 100644 comdel/domain/functionsignature.cpp delete mode 100644 comdel/domain/functionsignature.h create mode 100644 comdel/domain/instance_attribute.cpp create mode 100644 comdel/domain/instance_attribute.h delete mode 100644 comdel/domain/instanceattribute.cpp delete mode 100644 comdel/domain/instanceattribute.h create mode 100644 comdel/domain/schema_creator.cpp create mode 100644 comdel/domain/schema_creator.h delete mode 100644 comdel/domain/schemacreator.cpp delete mode 100644 comdel/domain/schemacreator.h delete mode 100644 comdel/domain/wireinstance.cpp delete mode 100644 comdel/domain/wireinstance.h rename comdel/parser/{astnode.cpp => ast_nodes.cpp} (79%) rename comdel/parser/{astnode.h => ast_nodes.h} (70%) rename comdel/parser/{comdelparser.cpp => comdel_parser.cpp} (77%) rename comdel/parser/{comdelparser.h => comdel_parser.h} (74%) rename comdel/parser/{parsecontext.cpp => parse_context.cpp} (70%) rename comdel/parser/{parsecontext.h => parse_context.h} (53%) rename comdel/parser/{parserutil.cpp => parser_util.cpp} (64%) create mode 100644 comdel/parser/parser_util.h delete mode 100644 comdel/parser/parserutil.h create mode 100644 comdel/parser/source_error.cpp rename comdel/parser/{sourceerror.h => source_error.h} (100%) delete mode 100644 comdel/parser/sourceerror.cpp create mode 100644 comdel/parser/tokens_type.cpp rename comdel/parser/{tokenstype.h => tokens_type.h} (79%) delete mode 100644 comdel/parser/tokenstype.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1237ce9..306e068 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,29 +14,28 @@ add_executable(SchemeEditor comdel/domain/value.cpp comdel/domain/schema.cpp comdel/domain/component.cpp - comdel/domain/connectioninstance.cpp + comdel/domain/connection_instance.cpp comdel/domain/rule.cpp - comdel/domain/wireinstance.cpp - comdel/domain/attribute.cpp + comdel/domain/attribute.cpp comdel/domain/bus.cpp comdel/domain/pin.cpp comdel/domain/display.cpp comdel/domain/library.cpp - comdel/domain/functionsignature.cpp - comdel/domain/addressspace.cpp - comdel/domain/instanceattribute.cpp + comdel/domain/function_signature.cpp + comdel/domain/address_space.cpp + comdel/domain/instance_attribute.cpp comdel/domain/connection.cpp comdel/domain/instance.cpp - comdel/domain/schemacreator.cpp - comdel/parser/comdelparser.cpp + comdel/domain/schema_creator.cpp + comdel/parser/comdel_parser.cpp comdel/parser/token.cpp - comdel/parser/sourceerror.cpp - comdel/parser/parsecontext.cpp - comdel/parser/tokenstype.cpp - comdel/parser/astnode.cpp - comdel/parser/parserutil.cpp + comdel/parser/source_error.cpp + comdel/parser/parse_context.cpp + comdel/parser/tokens_type.cpp + comdel/parser/ast_nodes.cpp + comdel/parser/parser_util.cpp comdel/parser/comdellexer.cpp main.cpp mainwindow.ui - comdel/domain/comdelvalidator.cpp comdel/domain/comdelvalidator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h) + comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h) target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/comdel/display/attribute_dialog.cpp b/comdel/display/attribute_dialog.cpp index 684a8ae..4d12b75 100644 --- a/comdel/display/attribute_dialog.cpp +++ b/comdel/display/attribute_dialog.cpp @@ -7,55 +7,159 @@ namespace display { -void AttributeDialog::onUpdate() { - auto oldValue = attributeValue->value; + void AttributeDialog::onUpdate() { + auto oldValue = attributeValue->value; - attributeValue->value = value; - domain::ComdelValidator validator(domain::getSupportedValidators()); + attributeValue->value = value; + domain::ComdelValidator validator(domain::getSupportedValidators()); - domain::ValidationContext context; + domain::ValidationContext context; - for (auto &addressSpace: MainWindow::getLibrary()->getAddressSpaces()) { - context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace)); - } - - auto validationErrors = validator.validateAttribute(attributeValue, context); - if(validationErrors.empty()) { - accept(); - } else { - bool canAccept = true; - - std::vector errors; - std::vector warnings; - for(auto& err: validationErrors) { - if(err.type == domain::Action::ERROR) { - errors.push_back(err); - } else { - warnings.push_back(err); - } - } - if(!errors.empty()) { - canAccept = false; - auto errorDialog = new ErrorDialog(errors); - errorDialog->exec(); + for (auto &addressSpace: MainWindow::getLibrary()->getAddressSpaces()) { + context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace)); } - for(auto& warning: warnings) { - auto warningDialog = new WarningDialog(warning); - int response = warningDialog->exec(); - if(response == QDialog::Rejected) { - canAccept = false; - } - } - - if(canAccept) { + auto validationErrors = validator.validateAttribute(attributeValue, context); + if (validationErrors.empty()) { accept(); } else { - attributeValue->value = oldValue; + bool canAccept = true; + + std::vector errors; + std::vector warnings; + for (auto &err: validationErrors) { + if (err.type == domain::Action::ERROR) { + errors.push_back(err); + } else { + warnings.push_back(err); + } + } + if (!errors.empty()) { + canAccept = false; + auto errorDialog = new ErrorDialog(errors); + errorDialog->exec(); + } + + for (auto &warning: warnings) { + auto warningDialog = new WarningDialog(warning); + int response = warningDialog->exec(); + if (response == QDialog::Rejected) { + canAccept = false; + } + } + + if (canAccept) { + accept(); + } else { + attributeValue->value = oldValue; + } + } + + } + + AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute) { + + + setAttribute(Qt::WA_DeleteOnClose); + + attributeValue = attribute; + + this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName())); + + auto layout = new QVBoxLayout(this); + this->setLayout(layout); + auto popup = *attribute->attribute.getPopup(); + + layout->addWidget(new QLabel(popup.getTitle().c_str())); + layout->addWidget(new QLabel(popup.getText().c_str())); + + auto type = attribute->attribute.getDefault().getType(); + value = attribute->value; + + if (attribute->attribute.getPopup()->isEnumerated()) { + auto *combo = new QComboBox(this); + auto enumeration = attribute->attribute.getPopup()->getEnumeration(); + for (auto entry: enumeration) { + combo->addItem(QString::fromStdString(entry.getName())); + } + + connect(combo, QOverload::of(&QComboBox::currentIndexChanged), this, + &AttributeDialog::onEnumerationChanged); + layout->addWidget(combo); + + for (int i = 0; i < enumeration.size(); i++) { + if (attributeValue->value.equals(enumeration[i].getValue())) { + combo->setCurrentIndex(i); + break; + } + } + + } else if (!(type == domain::Value::ValueType::WIRE_REFERENCE || type == domain::Value::ValueType::BOOL)) { + + auto edit = new QLineEdit(this); + connect(edit, &QLineEdit::textChanged, this, &AttributeDialog::onTextChanged); + layout->addWidget(edit); + + switch (attribute->attribute.getDefault().getType()) { + case domain::Value::ValueType::INT: + edit->setValidator(new QIntValidator(-10000000, 10000000, edit)); + edit->insert(std::to_string(attribute->value.asInt()).c_str()); + break; + case domain::Value::ValueType::STRING: + edit->insert(attribute->value.asString().c_str()); + break; + default: + throw std::exception(); + } + + } else if (type == domain::Value::ValueType::BOOL) { + auto *group = new QGroupBox(this); + + auto *radioLayout = new QHBoxLayout(group); + group->setLayout(radioLayout); + + auto isTrue = new QRadioButton("true", group); + connect(isTrue, &QRadioButton::clicked, [this]() { + this->value = domain::Value::fromBool(true); + }); + auto isFalse = new QRadioButton("false", group); + connect(isFalse, &QRadioButton::clicked, [this]() { + this->value = domain::Value::fromBool(false); + }); + + if (attribute->value.asBool()) { + isTrue->setChecked(true); + } else { + isFalse->setChecked(true); + } + + radioLayout->addWidget(isTrue); + radioLayout->addWidget(isFalse); + layout->addWidget(group); + } + + auto button = new QPushButton("Ažuriraj"); + connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate); + + layout->addWidget(button); + } + + void AttributeDialog::onTextChanged(const QString &string) { + switch (value.getType()) { + case domain::Value::STRING: + value.setString(string.toStdString()); + break; + case domain::Value::INT: + value = domain::Value::fromInt(parseInt(string.toStdString())); + break; + default: + throw std::exception(); } } -} + void AttributeDialog::onEnumerationChanged(int index) { + value = attributeValue->attribute.getPopup()->getEnumeration()[index].getValue(); + } void MemoryDialog::onUpdate() { @@ -63,4 +167,97 @@ void AttributeDialog::onUpdate() { accept(); } + MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute, + std::vector> instances) { + memoryInstances = std::vector(); + + setAttribute(Qt::WA_DeleteOnClose); + + attributeValue = attribute; + + this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName())); + + for (auto &instance: instances) { + if (instance->component.getType() == domain::Component::MEMORY) { + memoryInstances.push_back(instance->name); + } + } + + auto layout = new QVBoxLayout(this); + this->setLayout(layout); + auto popup = *attribute->attribute.getPopup(); + + layout->addWidget(new QLabel(popup.getTitle().c_str())); + layout->addWidget(new QLabel(popup.getText().c_str())); + + value = attribute->value; + + auto *combo = new QComboBox(this); + for (auto &entry: memoryInstances) { + combo->addItem(QString::fromStdString(entry)); + } + combo->addItem("null"); + + connect(combo, QOverload::of(&QComboBox::currentIndexChanged), this, &MemoryDialog::onMemoryChanged); + layout->addWidget(combo); + + combo->setCurrentIndex(memoryInstances.size()); + for (int i = 0; i < memoryInstances.size(); i++) { + if (attributeValue->value.asMemoryReference().has_value() && + attributeValue->value.asMemoryReference() == memoryInstances[i]) { + combo->setCurrentIndex(i); + break; + } + } + + auto button = new QPushButton("Ažuriraj"); + connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate); + + layout->addWidget(button); + } + + void MemoryDialog::onMemoryChanged(int index) { + if (index == memoryInstances.size()) { + value = domain::Value::fromMemoryReference(std::nullopt); + } else { + value = domain::Value::fromMemoryReference(memoryInstances[index]); + } + } + + ErrorDialog::ErrorDialog(std::vector errors) { + setAttribute(Qt::WA_DeleteOnClose); + + this->setWindowTitle("Greške"); + + auto layout = new QVBoxLayout(this); + this->setLayout(layout); + + for (auto &err: errors) { + layout->addWidget(new QLabel(QString::fromStdString(err.message), this)); + } + } + + WarningDialog::WarningDialog(domain::ValidationError error) { + setAttribute(Qt::WA_DeleteOnClose); + + this->setWindowTitle("Upozorenje"); + + auto layout = new QVBoxLayout(this); + this->setLayout(layout); + + layout->addWidget(new QLabel(QString::fromStdString(error.message), this)); + + auto buttonLayout = new QHBoxLayout(this); + + auto okButton = new QPushButton("U redu", this); + auto cancelButton = new QPushButton("Odustani", this); + + connect(okButton, &QPushButton::clicked, [this]() { accept(); }); + connect(cancelButton, &QPushButton::clicked, [this]() { reject(); }); + + buttonLayout->addWidget(okButton); + buttonLayout->addWidget(cancelButton); + + layout->addItem(buttonLayout); + } } \ No newline at end of file diff --git a/comdel/display/attribute_dialog.h b/comdel/display/attribute_dialog.h index c086511..95c037e 100644 --- a/comdel/display/attribute_dialog.h +++ b/comdel/display/attribute_dialog.h @@ -11,257 +11,78 @@ #include #include #include -#include +#include #include -#include "comdel/domain/comdelvalidator.h" +#include "comdel/domain/comdel_validator.h" namespace display { -class AttributeDialog: public QDialog { - domain::Value value; - - long long int parseInt(std::string expression) { - try { - if (expression.size() > 2) { - if (expression.substr(0, 2) == "0x") { - return std::stoll(expression, 0, 16); - } else if (expression.substr(0, 2) == "0b") { - return std::stoll(expression, 0, 2); - } else { - return std::stoll(expression, 0, 10); - } - } else { - return std::stoll(expression, 0, 10); - } - } catch (std::exception &e) { - return 0; - } - } - - domain::InstanceAttribute* attributeValue; - -public: - AttributeDialog(domain::InstanceAttribute *attribute) { - - setAttribute(Qt::WA_DeleteOnClose); - - attributeValue = attribute; - - this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName())); - - auto layout = new QVBoxLayout(this); - this->setLayout(layout); - auto popup = *attribute->attribute.getPopup(); - - layout->addWidget(new QLabel(popup.getTitle().c_str())); - layout->addWidget(new QLabel(popup.getText().c_str())); - - auto type = attribute->attribute.getDefault().getType(); - value = attribute->value; - - if(attribute->attribute.getPopup()->isEnumerated()) { - auto* combo = new QComboBox(this); - auto enumeration = attribute->attribute.getPopup()->getEnumeration(); - for(auto entry: enumeration) { - combo->addItem(QString::fromStdString(entry.getName())); - } - - connect(combo, QOverload::of(&QComboBox::currentIndexChanged), this, &AttributeDialog::onEnumerationChanged); - layout->addWidget(combo); - - for(int i=0; ivalue.equals(enumeration[i].getValue())) { - combo->setCurrentIndex(i); - break; - } - } - - } else if(!(type == domain::Value::ValueType::WIRE_REFERENCE || type == domain::Value::ValueType::BOOL)) { - - auto edit = new QLineEdit(this); - connect(edit, &QLineEdit::textChanged, this, &AttributeDialog::onTextChanged); - layout->addWidget(edit); - - switch (attribute->attribute.getDefault().getType()) { - case domain::Value::ValueType::INT: - edit->setValidator(new QIntValidator(-10000000, 10000000, edit)); - edit->insert(std::to_string(attribute->value.asInt()).c_str()); - break; - case domain::Value::ValueType::STRING: - edit->insert(attribute->value.asString().c_str()); - break; - } - - } else if(type == domain::Value::ValueType::BOOL) { - auto *group = new QGroupBox(this); - - auto *radioLayout = new QHBoxLayout(group); - group->setLayout(radioLayout); - - auto isTrue = new QRadioButton("true", group); - connect(isTrue, &QRadioButton::clicked, [this]() { - this->value = domain::Value::fromBool(true); - }); - auto isFalse = new QRadioButton("false", group); - connect(isFalse, &QRadioButton::clicked, [this]() { - this->value = domain::Value::fromBool(false); - }); - - if(attribute->value.asBool()) { - isTrue->setChecked(true); - } else { - isFalse->setChecked(true); - } - - radioLayout->addWidget(isTrue); - radioLayout->addWidget(isFalse); - layout->addWidget(group); - } - - auto button = new QPushButton("Ažuriraj"); - connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate); - - layout->addWidget(button); - } - -public slots: - void onTextChanged(const QString& string) { - switch (value.getType()) { - case domain::Value::STRING: - value.setString(string.toStdString()); - break; - case domain::Value::INT: - value = domain::Value::fromInt(parseInt(string.toStdString())); - } - }; - - void onEnumerationChanged(int index) { - value = attributeValue->attribute.getPopup()->getEnumeration()[index].getValue(); - } - - void onUpdate(); - -}; - - - class MemoryDialog: public QDialog { + class AttributeDialog : public QDialog { domain::Value value; - domain::InstanceAttribute* attributeValue; - std::vector memoryInstances; + long long int parseInt(std::string expression) { + try { + if (expression.size() > 2) { + if (expression.substr(0, 2) == "0x") { + return std::stoll(expression, nullptr, 16); + } else if (expression.substr(0, 2) == "0b") { + return std::stoll(expression, nullptr, 2); + } else { + return std::stoll(expression, nullptr, 10); + } + } else { + return std::stoll(expression, nullptr, 10); + } + } catch (std::exception &e) { + return 0; + } + } + + domain::InstanceAttribute *attributeValue; public: - MemoryDialog(domain::InstanceAttribute *attribute, std::vector> instances) { - memoryInstances = std::vector(); - - setAttribute(Qt::WA_DeleteOnClose); - - attributeValue = attribute; - - this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName())); - - for(auto& instance: instances) { - if(instance->component.getType() == domain::Component::MEMORY) { - memoryInstances.push_back(instance->name); - } - } - - auto layout = new QVBoxLayout(this); - this->setLayout(layout); - auto popup = *attribute->attribute.getPopup(); - - layout->addWidget(new QLabel(popup.getTitle().c_str())); - layout->addWidget(new QLabel(popup.getText().c_str())); - - value = attribute->value; - - auto* combo = new QComboBox(this); - for(auto& entry: memoryInstances) { - combo->addItem(QString::fromStdString(entry)); - } - combo->addItem("null"); - - connect(combo, QOverload::of(&QComboBox::currentIndexChanged), this, &MemoryDialog::onMemoryChanged); - layout->addWidget(combo); - - combo->setCurrentIndex(memoryInstances.size()); - for(int i=0; ivalue.asMemoryReference().has_value() && attributeValue->value.asMemoryReference() == memoryInstances[i]) { - combo->setCurrentIndex(i); - break; - } - } - - auto button = new QPushButton("Ažuriraj"); - connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate); - - layout->addWidget(button); - } + AttributeDialog(domain::InstanceAttribute *attribute); public slots: - void onMemoryChanged(int index) { - if(index == memoryInstances.size()) { - value = domain::Value::fromMemoryReference(std::nullopt); - } else { - value = domain::Value::fromMemoryReference(memoryInstances[index]); - } - } + void onTextChanged(const QString &string); + + void onEnumerationChanged(int index); void onUpdate(); }; - class ErrorDialog: public QDialog { + class MemoryDialog : public QDialog { + domain::Value value; + + domain::InstanceAttribute *attributeValue; + std::vector memoryInstances; public: - ErrorDialog(std::vector errors) { + MemoryDialog(domain::InstanceAttribute *attribute, + std::vector> instances); - setAttribute(Qt::WA_DeleteOnClose); + public slots: - this->setWindowTitle("Greške"); + void onMemoryChanged(int index); - auto layout = new QVBoxLayout(this); - this->setLayout(layout); + void onUpdate(); - for(auto& err: errors) { - layout->addWidget(new QLabel(QString::fromStdString(err.message), this)); - } - - } }; - class WarningDialog: public QDialog { + class ErrorDialog : public QDialog { public: - WarningDialog(domain::ValidationError error) { - - setAttribute(Qt::WA_DeleteOnClose); - - this->setWindowTitle("Upozorenje"); - - auto layout = new QVBoxLayout(this); - this->setLayout(layout); - - layout->addWidget(new QLabel(QString::fromStdString(error.message), this)); - - auto buttonLayout = new QHBoxLayout(this); - - auto okButton = new QPushButton("U redu", this); - auto cancelButton = new QPushButton("Odustani", this); - - connect(okButton, &QPushButton::clicked, [this]() { accept(); }); - connect(cancelButton, &QPushButton::clicked, [this]() { reject(); }); - - buttonLayout->addWidget(okButton); - buttonLayout->addWidget(cancelButton); - - layout->addItem(buttonLayout); - } + ErrorDialog(std::vector errors); }; + class WarningDialog : public QDialog { + public: + WarningDialog(domain::ValidationError error); + }; } diff --git a/comdel/display/component_display.cpp b/comdel/display/component_display.cpp index f865f89..4995a4d 100644 --- a/comdel/display/component_display.cpp +++ b/comdel/display/component_display.cpp @@ -9,31 +9,37 @@ namespace display { -void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { - QMenu menu; - menu.addAction("Izmjeni ime", [this](){ - auto dialog = new NameDialog(this->instance.get()); - dialog->exec(); - }); - menu.addSeparator(); - for(int i=0; iinstance->attributes.size(); i++) { - auto* attr = &this->instance->attributes[i]; - bool enabled = attr->attribute.getPopup().has_value(); - - auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name), - [attr]() { - if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) { - auto dialog = new MemoryDialog(attr, MainWindow::getSchema()->componentInstances); - dialog->exec(); - } else { - auto dialog = new AttributeDialog(attr); - dialog->exec(); - } + void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + QMenu menu; + menu.addAction("Izmjeni ime", [this]() { + auto dialog = new NameDialog(this->instance.get()); + dialog->exec(); }); - action->setEnabled(enabled); + menu.addSeparator(); + for (int i = 0; i < this->instance->attributes.size(); i++) { + auto *attr = &this->instance->attributes[i]; + bool enabled = attr->attribute.getPopup().has_value(); + + auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name), + [attr]() { + if (attr->value.getType() == domain::Value::MEMORY_REFERENCE) { + auto dialog = new MemoryDialog(attr, + MainWindow::getSchema()->componentInstances); + dialog->exec(); + } else { + auto dialog = new AttributeDialog(attr); + dialog->exec(); + } + }); + action->setEnabled(enabled); + } + menu.exec(event->screenPos()); + } + + Component::Component(const std::shared_ptr &instance): instance(instance) { + setFlag(ItemSendsGeometryChanges, true); + instance->component.getDisplay().render(this); } - menu.exec(event->screenPos()); -} void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QMenu menu; @@ -42,11 +48,13 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { } void Pin::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if(event->button() == Qt::MouseButton::LeftButton) { - auto view = dynamic_cast(this->scene()->views()[0]); + if (event->button() == Qt::MouseButton::LeftButton) { + auto view = dynamic_cast(this->scene()->views()[0]); view->state = Schema::CREATING_CONNECTION; view->context.pin = this; - view->context.startingPoint = dynamic_cast(this->parentItem())->pos() + QPointF(pin.getDisplayPin().getConnectionX(), pin.getDisplayPin().getConnectionY()); + view->context.startingPoint = dynamic_cast(this->parentItem())->pos() + + QPointF(pin.getDisplayPin().getConnectionX(), + pin.getDisplayPin().getConnectionY()); view->context.line = new QGraphicsLineItem(QLineF(view->context.startingPoint, event->scenePos())); this->scene()->addItem(view->context.line); @@ -55,8 +63,8 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { } void Pin::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - auto view = dynamic_cast(this->scene()->views()[0]); - if(view->state == Schema::CREATING_CONNECTION) { + auto view = dynamic_cast(this->scene()->views()[0]); + if (view->state == Schema::CREATING_CONNECTION) { auto line = view->context.line->line(); line.setP2(event->scenePos()); view->context.line->setLine(line); @@ -64,8 +72,8 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { } void Pin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if(event->button() == Qt::MouseButton::LeftButton) { - auto view = dynamic_cast(this->scene()->views()[0]); + if (event->button() == Qt::MouseButton::LeftButton) { + auto view = dynamic_cast(this->scene()->views()[0]); view->state = Schema::DEFAULT; this->scene()->removeItem(view->context.line); delete view->context.line; @@ -73,14 +81,30 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { } } + domain::Pin &Pin::getPin() { + return pin; + } + + domain::ComponentInstance *Pin::getComponentInstance() { + return componentInstance.get(); + } + void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { - QMenu menu; - menu.addAction("Izmjeni ime", [this](){ - auto dialog = new NameDialog(this->busInstance.get()); - dialog->exec(); - }); - menu.exec(event->screenPos()); -} + QMenu menu; + menu.addAction("Izmjeni ime", [this]() { + auto dialog = new NameDialog(this->busInstance.get()); + dialog->exec(); + }); + menu.exec(event->screenPos()); + } + + Bus::Bus(const std::shared_ptr &instance): busInstance(instance) { + instance->bus.getDisplayBus()->render(this, instance->size); + } + + domain::BusInstance *Bus::getBusInstance() { + { return busInstance.get(); } + } QVariant BusGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { if (change == ItemPositionChange && scene()) { @@ -89,13 +113,13 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { busInstance->position.first = newPos.x(); busInstance->position.second = newPos.y(); - auto view = dynamic_cast(scene()->views()[0]); + auto view = dynamic_cast(scene()->views()[0]); view->updateConnections(); } return QGraphicsItem::itemChange(change, value); } - BusGroup::BusGroup(const std::shared_ptr &instance): busInstance(instance) { + BusGroup::BusGroup(const std::shared_ptr &instance) : busInstance(instance) { setFlag(ItemIsMovable, true); setFlag(ItemSendsGeometryChanges, true); @@ -105,7 +129,7 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { addToGroup(bus); setPos(instance->position.first, instance->position.second); - } + } QVariant ComponentGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { @@ -115,36 +139,43 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { componentInstance->position.first = newPos.x(); componentInstance->position.second = newPos.y(); - auto view = dynamic_cast(scene()->views()[0]); + auto view = dynamic_cast(scene()->views()[0]); view->updateConnections(); } return QGraphicsItem::itemChange(change, value); } - void BusConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { - QMenu menu; - menu.addAction("Ukloni poveznicu", [this](){}); - menu.addSeparator(); - for(int i=0; iconnection->attributes.size(); i++) { - auto* attr = &this->connection->attributes[i]; - bool enabled = attr->attribute.getPopup().has_value(); - - auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name), - [attr]() { - auto dialog = new AttributeDialog(attr); - dialog->exec(); - }); - action->setEnabled(enabled); - } - menu.exec(event->screenPos()); + std::shared_ptr ComponentGroup::getComponentInstance() { + return componentInstance; } - void DirectConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + std::vector &ComponentGroup::getPins() { + return pins; + } + + ComponentGroup::ComponentGroup(const std::shared_ptr &instance): componentInstance( + instance) { + setFlag(ItemIsMovable, true); + setFlag(ItemSendsGeometryChanges, true); + + setHandlesChildEvents(false); + + addToGroup(new display::Component(instance)); + + for (auto &pin: instance->component.getPins()) { + pins.push_back(new display::Pin(pin, componentInstance)); + addToGroup(pins.back()); + } + + setPos(instance->position.first, instance->position.second); + } + + void BusConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QMenu menu; - menu.addAction("Ukloni poveznicu", [this](){}); + menu.addAction("Ukloni poveznicu", [this]() {}); menu.addSeparator(); - for(int i=0; iconnection->attributes.size(); i++) { - auto* attr = &this->connection->attributes[i]; + for (int i = 0; i < this->connection->attributes.size(); i++) { + auto *attr = &this->connection->attributes[i]; bool enabled = attr->attribute.getPopup().has_value(); auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name), @@ -157,4 +188,69 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { menu.exec(event->screenPos()); } + BusConnection::BusConnection(domain::BusConnectionInstance *connection, ComponentGroup *component, BusGroup *bus): connection( + connection), component(component), bus(bus) { + updateConnection(); + + setHandlesChildEvents(false); + } + + void BusConnection::updateConnection() { + auto busPosition = bus->boundingRect(); + auto pin = connection->instance->component.getPin( + connection->connection.getComponent().pin).getDisplayPin(); + + setLine(connection->instance->position.first + pin.getConnectionX(), + connection->instance->position.second + pin.getConnectionY(), + connection->bus->position.first + busPosition.width() / 2, + connection->bus->position.second + busPosition.height() / 2); + + connection->start.first = connection->instance->position.first + pin.getConnectionX(); + connection->start.second = connection->instance->position.second + pin.getConnectionY(); + connection->end.first = connection->bus->position.first + busPosition.width() / 2; + connection->end.second = connection->bus->position.second + busPosition.height() / 2; + } + + + void DirectConnection::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + QMenu menu; + menu.addAction("Ukloni poveznicu", [this]() {}); + menu.addSeparator(); + for (int i = 0; i < this->connection->attributes.size(); i++) { + auto *attr = &this->connection->attributes[i]; + bool enabled = attr->attribute.getPopup().has_value(); + + auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name), + [attr]() { + auto dialog = new AttributeDialog(attr); + dialog->exec(); + }); + action->setEnabled(enabled); + } + menu.exec(event->screenPos()); + } + + DirectConnection::DirectConnection(domain::DirectConnectionInstance *connection, ComponentGroup *first, + ComponentGroup *second): connection(connection), first(first), second(second) { + updateConnection(); + setHandlesChildEvents(false); + } + + void DirectConnection::updateConnection() { + auto pin1 = connection->instance->component.getPin( + connection->connection.getComponent().pin).getDisplayPin(); + auto pin2 = connection->secondInstance->component.getPin( + connection->connection.getSecondComponent()->pin).getDisplayPin(); + + setLine(connection->instance->position.first + pin1.getConnectionX(), + connection->instance->position.second + pin1.getConnectionY(), + connection->secondInstance->position.first + pin2.getConnectionX(), + connection->secondInstance->position.second + pin2.getConnectionY()); + + connection->start.first = connection->instance->position.first + pin1.getConnectionX(); + connection->start.second = connection->instance->position.second + pin1.getConnectionY(); + connection->end.first = connection->secondInstance->position.first + pin2.getConnectionX(); + connection->end.second = connection->secondInstance->position.second + pin2.getConnectionY(); + } + } // namespace display diff --git a/comdel/display/component_display.h b/comdel/display/component_display.h index c7ac893..17a095c 100644 --- a/comdel/display/component_display.h +++ b/comdel/display/component_display.h @@ -2,169 +2,116 @@ #define DISPLAY_COMPONENT_H #include -#include #include #include #include -#include "comdel/domain/connectioninstance.h" +#include +#include "comdel/domain/connection_instance.h" namespace display { -class Pin: public QGraphicsItemGroup -{ -private: - domain::Pin pin; - std::shared_ptr componentInstance; - -public: - Pin(domain::Pin pin, std::shared_ptr componentInstance): pin(pin), componentInstance(componentInstance) { - pin.getDisplayPin().render(this); - } - - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; - void mousePressEvent(QGraphicsSceneMouseEvent *event) override; - void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; - - domain::Pin& getPin() { - return pin; - } - - domain::ComponentInstance* getComponentInstance() { - return componentInstance.get(); - } -}; - -class Component: public QGraphicsItemGroup -{ -private: - std::shared_ptr instance; -public: - Component(const std::shared_ptr& instance): instance(instance) { - setFlag(ItemSendsGeometryChanges, true); - - instance->component.getDisplay().render(this); - } - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; - -}; - -class Bus: public QGraphicsItemGroup -{ - std::shared_ptr busInstance; -public: - Bus(const std::shared_ptr& instance): busInstance(instance) { - instance->bus.getDisplayBus()->render(this, instance->size); - } - domain::BusInstance *getBusInstance() { return busInstance.get(); } - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; -}; - -class ComponentGroup: public QGraphicsItemGroup -{ -private: - std::shared_ptr componentInstance; - std::vector pins; - -public: - - std::shared_ptr getComponentInstance() { return componentInstance; } - std::vector& getPins() { return pins; } - - explicit ComponentGroup(const std::shared_ptr& instance): componentInstance(instance) { - setFlag(ItemIsMovable, true); - setFlag(ItemSendsGeometryChanges, true); - - setHandlesChildEvents(false); - - addToGroup(new display::Component(instance)); - - for(auto &pin: instance->component.getPins()) { - pins.push_back(new display::Pin(pin, componentInstance)); - addToGroup(pins.back()); - } - - setPos(instance->position.first, instance->position.second); - } - -protected: - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); - -}; - -class BusGroup: public QGraphicsItemGroup -{ -private: - std::shared_ptr busInstance; - display::Bus* bus; - -public: - explicit BusGroup(const std::shared_ptr& instance); - - display::Bus* getBus() { return bus; } - -protected: - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); -}; - -class BusConnection: public QGraphicsLineItem -{ -private: - domain::BusConnectionInstance* connection; - ComponentGroup* component; - BusGroup* bus; - -public: - BusConnection(domain::BusConnectionInstance* connection, ComponentGroup *component, BusGroup *bus): connection(connection), component(component), bus(bus) { - updateConnection(); - - setHandlesChildEvents(false); - } - - void updateConnection() { - auto busPosition = bus->boundingRect(); - auto pin = connection->instance->component.getPin(connection->connection.getComponent().pin).getDisplayPin(); - - setLine(connection->instance->position.first + pin.getConnectionX(), connection->instance->position.second + pin.getConnectionY(), connection->bus->position.first + busPosition.width()/2, connection->bus->position.second + busPosition.height()/2); - - connection->start.first = connection->instance->position.first + pin.getConnectionX(); - connection->start.second = connection->instance->position.second + pin.getConnectionY(); - connection->end.first = connection->bus->position.first + busPosition.width()/2; - connection->end.second = connection->bus->position.second + busPosition.height()/2; - - } - - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; -}; - - - class DirectConnection: public QGraphicsLineItem - { + class Pin : public QGraphicsItemGroup { private: - domain::DirectConnectionInstance* connection; - ComponentGroup* first; - ComponentGroup* second; + domain::Pin pin; + std::shared_ptr componentInstance; public: - DirectConnection(domain::DirectConnectionInstance* connection, ComponentGroup *first, ComponentGroup *second): connection(connection), first(first), second(second) { - updateConnection(); - setHandlesChildEvents(false); + Pin(domain::Pin pin, std::shared_ptr componentInstance) : pin(pin), + componentInstance(std::move( + componentInstance)) { + pin.getDisplayPin().render(this); + this->setToolTip(QString::fromStdString(pin.getTooltip())); } - void updateConnection() { - auto pin1 = connection->instance->component.getPin(connection->connection.getComponent().pin).getDisplayPin(); - auto pin2 = connection->secondInstance->component.getPin(connection->connection.getSecondComponent()->pin).getDisplayPin(); + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; - setLine(connection->instance->position.first + pin1.getConnectionX(), connection->instance->position.second + pin1.getConnectionY(), - connection->secondInstance->position.first + pin2.getConnectionX(), connection->secondInstance->position.second + pin2.getConnectionY()); + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; - connection->start.first = connection->instance->position.first + pin1.getConnectionX(); - connection->start.second = connection->instance->position.second + pin1.getConnectionY(); - connection->end.first = connection->secondInstance->position.first + pin2.getConnectionX(); - connection->end.second = connection->secondInstance->position.second + pin2.getConnectionY(); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; - } + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + + domain::Pin &getPin(); + + domain::ComponentInstance *getComponentInstance(); + }; + + class Component : public QGraphicsItemGroup { + private: + std::shared_ptr instance; + public: + explicit Component(const std::shared_ptr &instance); + + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; + + }; + + class Bus : public QGraphicsItemGroup { + std::shared_ptr busInstance; + public: + explicit Bus(const std::shared_ptr &instance); + + domain::BusInstance *getBusInstance(); + + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; + }; + + class ComponentGroup : public QGraphicsItemGroup { + private: + std::shared_ptr componentInstance; + std::vector pins; + + public: + + std::shared_ptr getComponentInstance(); + + std::vector &getPins(); + + explicit ComponentGroup(const std::shared_ptr &instance); + + protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + + }; + + class BusGroup : public QGraphicsItemGroup { + private: + std::shared_ptr busInstance; + display::Bus *bus; + + public: + explicit BusGroup(const std::shared_ptr &instance); + + protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + }; + + class BusConnection : public QGraphicsLineItem { + private: + domain::BusConnectionInstance *connection; + ComponentGroup *component; + BusGroup *bus; + + public: + BusConnection(domain::BusConnectionInstance *connection, ComponentGroup *component, BusGroup *bus); + + void updateConnection(); + + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; + }; + + + class DirectConnection : public QGraphicsLineItem { + private: + domain::DirectConnectionInstance *connection; + ComponentGroup *first; + ComponentGroup *second; + + public: + DirectConnection(domain::DirectConnectionInstance *connection, ComponentGroup *first, ComponentGroup *second); + + void updateConnection(); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; }; diff --git a/comdel/display/library_display.cpp b/comdel/display/library_display.cpp index 749c4ad..07060e0 100644 --- a/comdel/display/library_display.cpp +++ b/comdel/display/library_display.cpp @@ -6,47 +6,47 @@ namespace display { -Library::Library() -{ - auto layout = new QVBoxLayout(); - this->setLayout(layout); + Library::Library() { + auto layout = new QVBoxLayout(); + this->setLayout(layout); - componentList = new LibraryList(this); - busList = new LibraryList(this); + componentList = new LibraryList(this); + busList = new LibraryList(this); - layout->setMargin(4); - layout->addWidget(new QLabel("Components:")); - layout->addWidget(componentList, 1); - layout->addSpacing(8); - layout->addWidget(new QLabel("Buses:")); - layout->addWidget(busList, 1); + layout->setMargin(4); + layout->addWidget(new QLabel("Components:")); + layout->addWidget(componentList, 1); + layout->addSpacing(8); + layout->addWidget(new QLabel("Buses:")); + layout->addWidget(busList, 1); - setLibrary(library); -} - -void Library::setLibrary(std::optional library) { - - componentList->clear(); - busList->clear(); - - if(!library) { - return; + setLibrary(library); } - for(auto& component: library->getComponents()) { - auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(), componentList}; - item->setToolTip(QString::fromStdString(component.getTooltip())); - componentList->addItem(item); - } + void Library::setLibrary(std::optional library) { - for(auto& bus: library->getBuses()) { - if(bus.getType() == domain::Bus::REGULAR) { - auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList}; - item->setToolTip(QString::fromStdString(bus.getTooltip())); - busList->addItem(item); + componentList->clear(); + busList->clear(); + + if (!library) { + return; } - } -} + for (auto &component: library->getComponents()) { + auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(), + componentList}; + item->setToolTip(QString::fromStdString(component.getTooltip())); + componentList->addItem(item); + } + + for (auto &bus: library->getBuses()) { + if (bus.getType() == domain::Bus::REGULAR) { + auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList}; + item->setToolTip(QString::fromStdString(bus.getTooltip())); + busList->addItem(item); + } + } + + } } // namespace display diff --git a/comdel/display/library_display.h b/comdel/display/library_display.h index c35aa36..41b6bc3 100644 --- a/comdel/display/library_display.h +++ b/comdel/display/library_display.h @@ -9,20 +9,19 @@ namespace display { -class Library: public QWidget -{ -public: - Library(); + class Library : public QWidget { + public: + Library(); - void setLibrary(std::optional library); + void setLibrary(std::optional library); -private: - std::optional library; + private: + std::optional library; - LibraryList *componentList; - LibraryList *busList; + LibraryList *componentList; + LibraryList *busList; -}; + }; } // namespace display diff --git a/comdel/display/library_list.cpp b/comdel/display/library_list.cpp index 0b769a2..ec766ff 100644 --- a/comdel/display/library_list.cpp +++ b/comdel/display/library_list.cpp @@ -10,22 +10,23 @@ namespace display { - LibraryList::LibraryList(QWidget *parent): QListWidget(parent) { + LibraryList::LibraryList(QWidget *parent) : QListWidget(parent) { setDragDropMode(DragOnly); } QMimeData *LibraryList::mimeData(const QList items) const { - for(auto qItem: items) { + for (auto qItem: items) { // we only allow one item to be dragged at a time - auto item = dynamic_cast(qItem); - auto* md = new QMimeData(); + auto item = dynamic_cast(qItem); + auto *md = new QMimeData(); md->setData(QString::fromStdString(item->mimeType), QByteArray::fromStdString(item->value)); return md; } return nullptr; } - LibraryListItem::LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent): QListWidgetItem(parent), mimeType(mimeType), value(value) { + LibraryListItem::LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent) + : QListWidgetItem(parent), mimeType(mimeType), value(value) { setText(QString::fromStdString(title)); } } // display \ No newline at end of file diff --git a/comdel/display/library_list.h b/comdel/display/library_list.h index 4b8ab76..c2154f9 100644 --- a/comdel/display/library_list.h +++ b/comdel/display/library_list.h @@ -11,16 +11,16 @@ namespace display { - class LibraryList: public QListWidget { - Q_OBJECT + class LibraryList : public QListWidget { + Q_OBJECT public: LibraryList(QWidget *parent); protected: - QMimeData *mimeData(const QList items) const override; + QMimeData *mimeData(const QList items) const override; }; - class LibraryListItem: public QListWidgetItem { + class LibraryListItem : public QListWidgetItem { public: std::string mimeType; diff --git a/comdel/display/name_dialog.cpp b/comdel/display/name_dialog.cpp index 77b646d..29505ba 100644 --- a/comdel/display/name_dialog.cpp +++ b/comdel/display/name_dialog.cpp @@ -3,3 +3,40 @@ // #include "name_dialog.h" + +display::NameDialog::NameDialog(domain::ComponentInstance *instance) : componentInstance(instance) { + auto *layout = new QVBoxLayout(this); + layout->addWidget(new QLabel("Izmjeni ime", this)); + + edit = new QLineEdit(this); + edit->insert(instance->name.c_str()); + layout->addWidget(edit); + this->setWindowTitle("Izmjeni ime"); + auto *button = new QPushButton("Ažuriraj", this); + connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange); + layout->addWidget(button); + this->setLayout(layout); +} + +display::NameDialog::NameDialog(domain::BusInstance *instance): busInstance(instance) { + auto *layout = new QVBoxLayout(this); + layout->addWidget(new QLabel("Izmjeni ime", this)); + + edit = new QLineEdit(this); + edit->insert(instance->name.c_str()); + layout->addWidget(edit); + this->setWindowTitle("Izmjeni ime"); + auto *button = new QPushButton("Ažuriraj", this); + connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange); + layout->addWidget(button); + this->setLayout(layout); +} + +void display::NameDialog::onNameChange() { + if (componentInstance != nullptr) { + componentInstance->name = this->edit->text().toStdString(); + } else if (busInstance != nullptr) { + busInstance->name = this->edit->text().toStdString(); + } + this->close(); +} diff --git a/comdel/display/name_dialog.h b/comdel/display/name_dialog.h index 006adea..7e6960d 100644 --- a/comdel/display/name_dialog.h +++ b/comdel/display/name_dialog.h @@ -11,52 +11,22 @@ namespace display { -class NameDialog: public QDialog { + class NameDialog : public QDialog { - QLineEdit *edit = nullptr; - domain::ComponentInstance *componentInstance = nullptr; - domain::BusInstance *busInstance = nullptr; + QLineEdit *edit = nullptr; + domain::ComponentInstance *componentInstance = nullptr; + domain::BusInstance *busInstance = nullptr; -public: + public: - NameDialog(domain::ComponentInstance *instance): componentInstance(instance) { - auto *layout = new QVBoxLayout(this); - layout->addWidget(new QLabel("Izmjeni ime", this)); + NameDialog(domain::ComponentInstance *instance); - edit = new QLineEdit(this); - edit->insert(instance->name.c_str()); - layout->addWidget(edit); - this->setWindowTitle("Izmjeni ime"); - auto *button = new QPushButton("Ažuriraj", this); - connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange); - layout->addWidget(button); - this->setLayout(layout); - } + NameDialog(domain::BusInstance *instance); - NameDialog(domain::BusInstance *instance): busInstance(instance) { - auto *layout = new QVBoxLayout(this); - layout->addWidget(new QLabel("Izmjeni ime", this)); + public slots: - edit = new QLineEdit(this); - edit->insert(instance->name.c_str()); - layout->addWidget(edit); - this->setWindowTitle("Izmjeni ime"); - auto *button = new QPushButton("Ažuriraj", this); - connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange); - layout->addWidget(button); - this->setLayout(layout); - } - -public slots: - void onNameChange() { - if(componentInstance != nullptr) { - componentInstance->name = this->edit->text().toStdString(); - } else if(busInstance != nullptr) { - busInstance->name = this->edit->text().toStdString(); - } - this->close(); - } -}; + void onNameChange(); + }; } diff --git a/comdel/display/schema_display.cpp b/comdel/display/schema_display.cpp index 00b0ef1..ce2214a 100644 --- a/comdel/display/schema_display.cpp +++ b/comdel/display/schema_display.cpp @@ -7,96 +7,98 @@ namespace display { -Schema::Schema() -{ - this->selectedBrush.setColor(QColor::fromRgb(20,20,125)); - this->selectedPen.setColor(QColor::fromRgb(20, 20, 125)); + Schema::Schema() { + this->selectedBrush.setColor(QColor::fromRgb(20, 20, 125)); + this->selectedPen.setColor(QColor::fromRgb(20, 20, 125)); - this->setScene(&scene); - this->setAcceptDrops(true); -} + this->setScene(&scene); + this->setAcceptDrops(true); + } -void Schema::setSchema(domain::Schema* _schema, domain::Library* _library) -{ - components.clear(); - buses.clear(); + void Schema::setSchema(domain::Schema *_schema, domain::Library *_library) { + components.clear(); + buses.clear(); - scene.clear(); - busConnections.clear(); - this->schema = _schema; - this->library = _library; - if(schema != nullptr) { - for(auto &instance: schema->componentInstances) { - auto group = new display::ComponentGroup(instance); - for(auto pin: group->getPins()) { - display::Pin* p = pin; - domain::ConnectionComponent connection{instance->name, p->getPin().getName()}; - pins.insert(std::make_pair(connection, p)); - } - components.insert(std::make_pair(instance->name, group)); - scene.addItem(group); - } - for(auto &instance: schema->busInstances) { - if(instance->bus.getDisplayBus().has_value()) { - auto group = new display::BusGroup(instance); - buses.insert(std::make_pair(instance->name, group)); + scene.clear(); + busConnections.clear(); + this->schema = _schema; + this->library = _library; + if (schema != nullptr) { + for (auto &instance: schema->componentInstances) { + auto group = new display::ComponentGroup(instance); + for (auto pin: group->getPins()) { + display::Pin *p = pin; + domain::ConnectionComponent connection{instance->name, p->getPin().getName()}; + pins.insert(std::make_pair(connection, p)); + } + components.insert(std::make_pair(instance->name, group)); scene.addItem(group); } - } - for(auto &connection: schema->connections) { - auto busInstance = dynamic_cast(connection.get()); - if(busInstance != nullptr) { - auto con = new display::BusConnection(busInstance, components[busInstance->instance->name], buses[busInstance->bus->name]); - busConnections.push_back(con); - scene.addItem(con); + for (auto &instance: schema->busInstances) { + if (instance->bus.getDisplayBus().has_value()) { + auto group = new display::BusGroup(instance); + buses.insert(std::make_pair(instance->name, group)); + scene.addItem(group); + } } - auto directInstance = dynamic_cast(connection.get()); - if(directInstance != nullptr) { - auto con = new display::DirectConnection(directInstance, components[directInstance->instance->name], components[directInstance->secondInstance->name]); - directConnections.push_back(con); - scene.addItem(con); + for (auto &connection: schema->connections) { + auto busInstance = dynamic_cast(connection.get()); + if (busInstance != nullptr) { + auto con = new display::BusConnection(busInstance, components[busInstance->instance->name], + buses[busInstance->bus->name]); + busConnections.push_back(con); + scene.addItem(con); + } + auto directInstance = dynamic_cast(connection.get()); + if (directInstance != nullptr) { + auto con = new display::DirectConnection(directInstance, components[directInstance->instance->name], + components[directInstance->secondInstance->name]); + directConnections.push_back(con); + scene.addItem(con); + } } } } -} -void Schema::updateConnections() { - if(schema != nullptr) { - for(auto conn: busConnections) { - conn->updateConnection(); - } - for(auto conn: directConnections) { - conn->updateConnection(); + void Schema::updateConnections() { + if (schema != nullptr) { + for (auto conn: busConnections) { + conn->updateConnection(); + } + for (auto conn: directConnections) { + conn->updateConnection(); + } } } -} void Schema::dragEnterEvent(QDragEnterEvent *event) { - if(event->mimeData()->hasFormat("comdel/component") || - event->mimeData()->hasFormat("comdel/bus")) { + if (event->mimeData()->hasFormat("comdel/component") || + event->mimeData()->hasFormat("comdel/bus")) { event->acceptProposedAction(); } } void Schema::dropEvent(QDropEvent *event) { - if(event->mimeData()->hasFormat("comdel/component")) { + if (event->mimeData()->hasFormat("comdel/component")) { auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString()); auto attributes = std::vector(); - for(auto attr: component.getAttributes()) { + for (auto attr: component.getAttributes()) { attributes.emplace_back(attr.getName(), attr.getDefault(), attr); } auto currentPos = this->mapToScene(event->pos()); - auto instance = std::make_shared(component.getInstanceName(), attributes, std::make_pair(currentPos.x(), currentPos.y()), component); + auto instance = std::make_shared(component.getInstanceName(), attributes, + std::make_pair(currentPos.x(), currentPos.y()), + component); schema->componentInstances.push_back(instance); auto group = new display::ComponentGroup(instance); scene.addItem(group); - for(auto pin: group->getPins()) { - display::Pin* p = pin; + for (auto pin: group->getPins()) { + display::Pin *p = pin; domain::ConnectionComponent connection{instance->name, p->getPin().getName()}; pins.insert(std::make_pair(connection, p)); } @@ -105,12 +107,13 @@ void Schema::updateConnections() { event->acceptProposedAction(); } - if(event->mimeData()->hasFormat("comdel/bus")) { + if (event->mimeData()->hasFormat("comdel/bus")) { auto bus = library->getBus(event->mimeData()->data("comdel/bus").toStdString()); auto currentPos = this->mapToScene(event->pos()); - auto instance = std::make_shared(bus.getName(), std::make_pair(currentPos.x(), currentPos.y()), bus); + auto instance = std::make_shared(bus.getName(), + std::make_pair(currentPos.x(), currentPos.y()), bus); schema->busInstances.push_back(instance); auto group = new display::BusGroup(instance); @@ -127,19 +130,19 @@ void Schema::updateConnections() { void Schema::removeConnectable(QPointF endPoint) { auto instance = context.pin->getComponentInstance(); - auto& pin = context.pin->getPin(); + auto &pin = context.pin->getPin(); auto busInstances = getAvailableConnectionBusses(instance, pin); - for(auto &bus: busInstances) { + for (auto &bus: busInstances) { auto rect = buses[bus->name]->boundingRect(); rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height()); - if(rect.contains(endPoint)) { + if (rect.contains(endPoint)) { auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName()); - if(con.has_value()) { + if (con.has_value()) { std::vector attributes; - for(auto attr: con->getAttributes()) { + for (auto attr: con->getAttributes()) { attributes.emplace_back(attr.getName(), attr.getDefault(), attr); } @@ -148,7 +151,7 @@ void Schema::updateConnections() { if (conInstance != nullptr) { auto c = new display::BusConnection(conInstance.get(), components[conInstance->instance->name], - buses[conInstance->bus->name]); + buses[conInstance->bus->name]); busConnections.push_back(c); scene.addItem(c); } @@ -159,29 +162,35 @@ void Schema::updateConnections() { auto pinInstances = getAvailableConnectionPins(instance, pin); - for(auto &pinInstance: pinInstances) { + for (auto &pinInstance: pinInstances) { auto rect = pins[pinInstance]->boundingRect(); rect.setX(pins[pinInstance]->scenePos().x()); rect.setY(pins[pinInstance]->scenePos().y()); - if(rect.contains(endPoint)) { + if (rect.contains(endPoint)) { auto name = components[pinInstance.component]->getComponentInstance()->component.getName(); - auto con = library->getConnection({instance->component.getName(), pin.getName()}, {name, pinInstance.pin}); - if(con.has_value()) { + auto con = library->getConnection({instance->component.getName(), pin.getName()}, + {name, pinInstance.pin}); + if (con.has_value()) { auto bus = library->getBus(con->getBus()); auto busInstance = std::make_shared(bus.getName(), bus); schema->busInstances.push_back(busInstance); std::vector attributes; - for(auto attr: con->getAttributes()) { + for (auto attr: con->getAttributes()) { attributes.emplace_back(attr.getName(), attr.getDefault(), attr); } - auto conInstance = std::make_shared(instance, components[pinInstance.component]->getComponentInstance().get(), attributes, busInstance.get(), *con); + auto conInstance = std::make_shared(instance, + components[pinInstance.component]->getComponentInstance().get(), + attributes, busInstance.get(), + *con); schema->connections.push_back(conInstance); if (conInstance != nullptr) { - auto c = new display::DirectConnection(conInstance.get(), components[conInstance->instance->name], components[conInstance->secondInstance->name]); + auto c = new display::DirectConnection(conInstance.get(), + components[conInstance->instance->name], + components[conInstance->secondInstance->name]); directConnections.push_back(c); scene.addItem(c); } @@ -193,7 +202,7 @@ void Schema::updateConnections() { updateConnections(); - for(auto& item: this->context.selectable) { + for (auto &item: this->context.selectable) { this->scene.removeItem(item); delete item; } @@ -201,12 +210,12 @@ void Schema::updateConnections() { } void Schema::showConnectable(Pin *domainPin) { - auto& pin = domainPin->getPin(); + auto &pin = domainPin->getPin(); auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin()); - for(auto bus: busInstances) { - auto& group = buses[bus->name]; + for (auto bus: busInstances) { + auto &group = buses[bus->name]; auto rect = new QGraphicsRectItem(group->boundingRect()); rect->setPen(selectedPen); rect->setPos(group->scenePos()); @@ -220,10 +229,11 @@ void Schema::updateConnections() { scene.addItem(rect); } - std::vector pinInstances = getAvailableConnectionPins(domainPin->getComponentInstance(), domainPin->getPin()); + std::vector pinInstances = getAvailableConnectionPins( + domainPin->getComponentInstance(), domainPin->getPin()); - for(auto& pinInstance: pinInstances) { - auto& instance = pins[pinInstance]; + for (auto &pinInstance: pinInstances) { + auto &instance = pins[pinInstance]; auto rect = new QGraphicsRectItem(instance->boundingRect()); rect->setPen(selectedPen); rect->setPos(instance->scenePos()); @@ -239,22 +249,25 @@ void Schema::updateConnections() { } - std::vector Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) { - std::vector instances; - for(const auto& bus: schema->busInstances) { - if(library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()}, bus->bus.getName())) { + std::vector + Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) { + std::vector instances; + for (const auto &bus: schema->busInstances) { + if (library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()}, + bus->bus.getName())) { instances.push_back(bus.get()); } } return instances; } - std::vector Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) { + std::vector + Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) { std::vector instances; domain::ConnectionComponent source{instance->component.getName(), pin.getName()}; - for(const auto& entry: pins) { + for (const auto &entry: pins) { std::string name = components[entry.first.component]->getComponentInstance()->component.getName(); - if(library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) { + if (library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) { instances.push_back(entry.first); } } diff --git a/comdel/display/schema_display.h b/comdel/display/schema_display.h index 0d0173e..6593435 100644 --- a/comdel/display/schema_display.h +++ b/comdel/display/schema_display.h @@ -14,64 +14,67 @@ namespace display { class BusConnection; -class Schema: public QGraphicsView -{ + class Schema : public QGraphicsView { Q_OBJECT -public: + public: - QBrush selectedBrush; - QPen selectedPen; + QBrush selectedBrush; + QPen selectedPen; - enum State { - DEFAULT, - CREATING_CONNECTION + enum State { + DEFAULT, + CREATING_CONNECTION + }; + + struct Context { + display::Pin *pin = nullptr; + QPointF startingPoint; + QGraphicsLineItem *line = nullptr; + std::vector selectable; + }; + + std::map components; + std::map buses; + std::map pins; + + State state = DEFAULT; + Context context; + + Schema(); + + std::vector busConnections; + std::vector directConnections; + + void setSchema(domain::Schema *schema, domain::Library *library); + + void updateConnections(); + + void removeConnectable(QPointF f); + + void showConnectable(Pin *pin); + + protected: + + void dragEnterEvent(QDragEnterEvent *event) override; + + void dropEvent(QDropEvent *event) override; + + void dragMoveEvent(QDragMoveEvent *event) override; + + private: + QGraphicsScene scene; + + domain::Schema *schema; + domain::Library *library; + + std::vector + getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin); + + std::vector + getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin); }; - struct Context { - display::Pin *pin = nullptr; - QPointF startingPoint; - QGraphicsLineItem *line = nullptr; - std::vector selectable; - }; - - std::map components; - std::map buses; - std::map pins; - - State state = DEFAULT; - Context context; - - Schema(); - - std::vector busConnections; - std::vector directConnections; - - void setSchema(domain::Schema* schema, domain::Library* library); - - void updateConnections(); - - void removeConnectable(QPointF f); - - void showConnectable(Pin *pin); - -protected: - - void dragEnterEvent(QDragEnterEvent *event) override; - void dropEvent(QDropEvent *event) override; - void dragMoveEvent(QDragMoveEvent *event) override; - -private: - QGraphicsScene scene; - - domain::Schema* schema; - domain::Library* library; - - std::vector getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin); - - std::vector getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin); -}; - } // namespace display #endif // DISPLAY_SCHEMA_H diff --git a/comdel/domain/address_space.cpp b/comdel/domain/address_space.cpp new file mode 100644 index 0000000..c2366aa --- /dev/null +++ b/comdel/domain/address_space.cpp @@ -0,0 +1,29 @@ +#include +#include "address_space.h" + +namespace domain { + + AddressSpace::AddressSpace(std::string name, long long start, long long end) : + name(name), start(start), end(end) {} + + std::string AddressSpace::getName() { + return name; + } + + long long AddressSpace::getStart() const { + return start; + } + + long long AddressSpace::getEnd() const { + return end; + } + + bool AddressSpace::contains(long long int address) { + return address >= start && address < end; + } + + bool AddressSpace::contains(long long int pstart, long long int pend) { + return pstart >= start && pend < end; + } + +} // namespace domain diff --git a/comdel/domain/address_space.h b/comdel/domain/address_space.h new file mode 100644 index 0000000..2442253 --- /dev/null +++ b/comdel/domain/address_space.h @@ -0,0 +1,29 @@ +#ifndef DOMAIN_ADDRESS_SPACE_H +#define DOMAIN_ADDRESS_SPACE_H + +#include + +namespace domain { + + class AddressSpace { + std::string name; + long long start; + long long end; + + public: + AddressSpace(std::string name, long long start, long long end); + + std::string getName(); + + long long getStart() const; + + long long getEnd() const; + + bool contains(long long int address); + + bool contains(long long int start, long long int end); + }; + +} // namespace domain + +#endif // DOMAIN_ADDRESS_SPACE_H diff --git a/comdel/domain/addressspace.cpp b/comdel/domain/addressspace.cpp deleted file mode 100644 index 076d271..0000000 --- a/comdel/domain/addressspace.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include "addressspace.h" - -namespace domain { - -AddressSpace::AddressSpace(std::string name, long long start, long long end): - name(name), start(start), end(end) -{} - -std::string AddressSpace::getName() { - return name; -} -long long AddressSpace::getStart() const { - return start; -} -long long AddressSpace::getEnd() const { - return end; -} - -bool AddressSpace::contains(long long int address) { - return address >= start && address < end; -} - -bool AddressSpace::contains(long long int pstart, long long int pend) { - return pstart >= start && pend < end; -} - -} // namespace domain diff --git a/comdel/domain/addressspace.h b/comdel/domain/addressspace.h deleted file mode 100644 index f68474f..0000000 --- a/comdel/domain/addressspace.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef DOMAIN_ADDRESS_SPACE_H -#define DOMAIN_ADDRESS_SPACE_H - -#include - -namespace domain { - -class AddressSpace -{ - std::string name; - long long start; - long long end; - -public: - AddressSpace(std::string name, long long start, long long end); - - std::string getName(); - long long getStart() const; - long long getEnd() const; - - bool contains(long long int address); - bool contains(long long int start, long long int end); -}; - -} // namespace domain - -#endif // DOMAIN_ADDRESS_SPACE_H diff --git a/comdel/domain/attribute.cpp b/comdel/domain/attribute.cpp index 8e79006..90ff708 100644 --- a/comdel/domain/attribute.cpp +++ b/comdel/domain/attribute.cpp @@ -2,55 +2,61 @@ namespace domain { -Enumeration::Enumeration(std::string name, Value value) - : name(name), value(value) -{} + Enumeration::Enumeration(std::string name, Value value) + : name(name), value(value) {} -std::string& Enumeration::getName() { - return name; -} -Value Enumeration::getValue() { - return value; -} + std::string &Enumeration::getName() { + return name; + } + + Value Enumeration::getValue() { + return value; + } -Popup::Popup(std::string title, std::string text, PopupType type, std::vector rules, std::vector enumeration) - : title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0), enumeration(enumeration) -{} + Popup::Popup(std::string title, std::string text, PopupType type, std::vector rules, + std::vector enumeration) + : title(title), text(text), type(type), rules(rules), enumerated(enumeration.size() > 0), + enumeration(enumeration) {} -std::string Popup::getTitle() { - return title; -} -std::string Popup::getText() { - return text; -} -Popup::PopupType Popup::getType() { - return type; -} -std::vector Popup::getRules() { - return rules; -} + std::string Popup::getTitle() { + return title; + } -bool Popup::isEnumerated() { - return enumerated; -} -std::vector &Popup::getEnumeration() { - return enumeration; -} + std::string Popup::getText() { + return text; + } + + Popup::PopupType Popup::getType() { + return type; + } + + std::vector Popup::getRules() { + return rules; + } + + bool Popup::isEnumerated() { + return enumerated; + } + + std::vector &Popup::getEnumeration() { + return enumeration; + } -Attribute::Attribute(std::string name, Value defaultValue, std::optional popup) - : name(name), defaultValue(defaultValue), popup(popup) -{} + Attribute::Attribute(std::string name, Value defaultValue, std::optional popup) + : name(name), defaultValue(defaultValue), popup(popup) {} -std::string Attribute::getName() { - return name; -} -Value Attribute::getDefault() { - return defaultValue; -} -std::optional Attribute::getPopup() { - return popup; -} + std::string Attribute::getName() { + return name; + } + + Value Attribute::getDefault() { + return defaultValue; + } + + std::optional Attribute::getPopup() { + return popup; + } } // namespace domain diff --git a/comdel/domain/attribute.h b/comdel/domain/attribute.h index b4730b2..6c1daa5 100644 --- a/comdel/domain/attribute.h +++ b/comdel/domain/attribute.h @@ -9,62 +9,69 @@ namespace domain { -class Enumeration { - std::string name; - Value value; -public: - Enumeration(std::string name, Value value); + class Enumeration { + std::string name; + Value value; + public: + Enumeration(std::string name, Value value); - std::string& getName(); - Value getValue(); -}; + std::string &getName(); -class Popup { -public: - enum PopupType { - AUTOMATIC, - ON_DEMAND + Value getValue(); }; -private: - std::string title; - std::string text; - PopupType type; + class Popup { + public: + enum PopupType { + AUTOMATIC, + ON_DEMAND + }; - bool enumerated; - std::vector enumeration; - std::vector rules; + private: + std::string title; + std::string text; + PopupType type; -public: - Popup(std::string title, std::string text, PopupType type, std::vector rules, std::vector enumeration); + bool enumerated; + std::vector enumeration; + std::vector rules; - std::string getTitle(); - std::string getText(); - PopupType getType(); - std::vector getRules(); + public: + Popup(std::string title, std::string text, PopupType type, std::vector rules, + std::vector enumeration); - bool isEnumerated(); - std::vector &getEnumeration(); + std::string getTitle(); - void setEnumeration(std::vector enums) { - enumerated = true; - enumeration = std::move(enums); - } + std::string getText(); -}; + PopupType getType(); -class Attribute -{ - std::string name; - Value defaultValue; - std::optional popup; -public: - Attribute(std::string name, Value defaultValue, std::optional popup = std::nullopt); + std::vector getRules(); - std::string getName(); - Value getDefault(); - std::optional getPopup(); -}; + bool isEnumerated(); + + std::vector &getEnumeration(); + + void setEnumeration(std::vector enums) { + enumerated = true; + enumeration = std::move(enums); + } + + }; + + class Attribute { + std::string name; + Value defaultValue; + std::optional popup; + public: + Attribute(std::string name, Value defaultValue, std::optional popup = std::nullopt); + + std::string getName(); + + Value getDefault(); + + std::optional getPopup(); + }; } // namespace domain diff --git a/comdel/domain/bus.cpp b/comdel/domain/bus.cpp index 683ad05..5f7c8cc 100644 --- a/comdel/domain/bus.cpp +++ b/comdel/domain/bus.cpp @@ -2,51 +2,60 @@ namespace domain { -Wire::Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith) - : name(name), type(type), width(width), hidden(hidden), hasTerminate(hasTerminate), terminateWith(terminateWith) -{} + Wire::Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith) + : name(name), type(type), width(width), hidden(hidden), hasTerminate(hasTerminate), + terminateWith(terminateWith) {} -std::string Wire::getName() { - return name; -} -int Wire::getWidth() { - return width; -} -bool Wire::isHidden() { - return hidden; -} + std::string Wire::getName() { + return name; + } -bool Wire::hasTerminateWith() { - return hasTerminate; -} -Value Wire::getTerminateWith() { - return terminateWith; -} -Wire::WireType Wire::getType() { - return type; -} + int Wire::getWidth() { + return width; + } -Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair count, std::vector wires, std::optional displayBus) - : name(name), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) -{} + bool Wire::isHidden() { + return hidden; + } -std::string Bus::getName() { - return name; -} -std::string Bus::getTooltip() { - return tooltip; -} -Bus::BusType Bus::getType() { - return type; -} -std::pair Bus::getCount() { - return count; -} -std::vector Bus::getWires() { - return wires; -} -std::optional Bus::getDisplayBus() { - return displayBus; -} + bool Wire::hasTerminateWith() { + return hasTerminate; + } + + Value Wire::getTerminateWith() { + return terminateWith; + } + + Wire::WireType Wire::getType() { + return type; + } + + Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair count, std::vector wires, + std::optional displayBus) + : name(name), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) {} + + std::string Bus::getName() { + return name; + } + + std::string Bus::getTooltip() { + return tooltip; + } + + Bus::BusType Bus::getType() { + return type; + } + + std::pair Bus::getCount() { + return count; + } + + std::vector Bus::getWires() { + return wires; + } + + std::optional Bus::getDisplayBus() { + return displayBus; + } } // namespace domain diff --git a/comdel/domain/bus.h b/comdel/domain/bus.h index 13d4386..fcbd2e2 100644 --- a/comdel/domain/bus.h +++ b/comdel/domain/bus.h @@ -11,63 +11,72 @@ namespace domain { -class Wire -{ -public: - enum WireType { - WIRE_DEFAULT, - WIRED_AND, - WIRED_OR, - R_WIRE + class Wire { + public: + enum WireType { + WIRE_DEFAULT, + WIRED_AND, + WIRED_OR, + R_WIRE + }; + + + private: + std::string name; + WireType type; + int width; + bool hidden; + bool hasTerminate; + Value terminateWith; + + public: + Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith); + + std::string getName(); + + int getWidth(); + + bool isHidden(); + + bool hasTerminateWith(); + + Value getTerminateWith(); + + WireType getType(); }; + class Bus { + public: + enum BusType { + AUTOMATIC, + REGULAR, + SINGLE_AUTOMATIC + }; + private: + std::string name; + std::string tooltip; + BusType type; -private: - std::string name; - WireType type; - int width; - bool hidden; - bool hasTerminate; - Value terminateWith; + std::pair count; + std::optional displayBus; + std::vector wires; -public: - Wire(std::string name, WireType type, int width, bool hidden, bool hasTerminate, Value terminateWith); + public: + Bus(std::string name, std::string tooltip, BusType type, std::pair count, std::vector wires, + std::optional display = std::nullopt); - std::string getName(); - int getWidth(); - bool isHidden(); - bool hasTerminateWith(); - Value getTerminateWith(); - WireType getType(); -}; + std::string getName(); -class Bus -{ -public: - enum BusType { - AUTOMATIC, - REGULAR, - SINGLE_AUTOMATIC + std::string getTooltip(); + + BusType getType(); + + std::pair getCount(); + + std::vector getWires(); + + std::optional getDisplayBus(); }; -private: - std::string name; - std::string tooltip; - BusType type; - - std::pair count; - std::optional displayBus; - std::vector wires; - -public: - Bus(std::string name, std::string tooltip, BusType type, std::pair count, std::vector wires, std::optional display = std::nullopt); - - std::string getName(); - std::string getTooltip(); - BusType getType(); - std::pair getCount(); - std::vector getWires(); - std::optional getDisplayBus(); -}; } // namespace domain diff --git a/comdel/domain/comdel_generator.cpp b/comdel/domain/comdel_generator.cpp index b9393b7..9646b4a 100644 --- a/comdel/domain/comdel_generator.cpp +++ b/comdel/domain/comdel_generator.cpp @@ -7,345 +7,361 @@ namespace domain { -void generateSchemaFile(std::string& librarySource, Schema *schema, std::ostream &buffer) { - buffer << "@source " << librarySource << std::endl << std::endl; + void generate_schema(std::string &librarySource, Schema *schema, std::ostream &buffer) { + buffer << "@source \"" << librarySource << "\"" << std::endl << std::endl; - buffer << "@schema {" << std::endl; + buffer << "@schema {" << std::endl; - for(auto &componentInstance: schema->componentInstances) { - buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName() << " {" << std::endl; - buffer << "\t\t" << "@position (" << componentInstance->position.first << ", " << componentInstance->position.second << ")" << std::endl; + for (auto &componentInstance: schema->componentInstances) { + buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName() + << " {" << std::endl; + buffer << "\t\t" << "@position (" << componentInstance->position.first << ", " + << componentInstance->position.second << ")" << std::endl; - for(auto &attribute: componentInstance->attributes) { - buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; - } - - buffer << "\t}" << std::endl << std::endl; - } - - for(auto &busInstance: schema->busInstances) { - buffer << "\t" << "@instance " << busInstance->name << " " << busInstance->bus.getName() << " {" << std::endl; - buffer << "\t\t" << "@position (" << busInstance->position.first << ", " << busInstance->position.second << ")" << std::endl; - buffer << "\t\t" << "@size " << busInstance->size << std::endl; - buffer << "\t}" << std::endl << std::endl; - } - - for(auto &conn: schema->connections) { - auto busConn = dynamic_cast(conn.get()); - if(busConn) { - buffer << "\t" << "@connection (" << busConn->instance->name << "." << busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl; - - for(auto attribute: busConn->attributes) { + for (auto &attribute: componentInstance->attributes) { buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; } - buffer << "\t" << "}" << std::endl; + buffer << "\t}" << std::endl << std::endl; } - auto dirConn = dynamic_cast(conn.get()); - if(dirConn) { - buffer << "\t" << "@connection (" << dirConn->instance->name << "." << dirConn->connection.getComponent().pin << ", " - << dirConn->bus->name << ", " - << dirConn->secondInstance->name << "." << dirConn->connection.getSecondComponent()->pin - << ") {" << std::endl; - for(auto attribute: dirConn->attributes) { - buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; + for (auto &busInstance: schema->busInstances) { + buffer << "\t" << "@instance " << busInstance->name << " " << busInstance->bus.getName() << " {" + << std::endl; + buffer << "\t\t" << "@position (" << busInstance->position.first << ", " << busInstance->position.second + << ")" << std::endl; + buffer << "\t\t" << "@size " << busInstance->size << std::endl; + buffer << "\t}" << std::endl << std::endl; + } + + for (auto &conn: schema->connections) { + auto busConn = dynamic_cast(conn.get()); + if (busConn) { + buffer << "\t" << "@connection (" << busConn->instance->name << "." + << busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl; + + for (auto attribute: busConn->attributes) { + buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() + << std::endl; + } + + buffer << "\t" << "}" << std::endl; } + auto dirConn = dynamic_cast(conn.get()); + if (dirConn) { + buffer << "\t" << "@connection (" << dirConn->instance->name << "." + << dirConn->connection.getComponent().pin << ", " + << dirConn->bus->name << ", " + << dirConn->secondInstance->name << "." << dirConn->connection.getSecondComponent()->pin + << ") {" << std::endl; - buffer << "\t" << "}" << std::endl; + for (auto attribute: dirConn->attributes) { + buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() + << std::endl; + } + + buffer << "\t" << "}" << std::endl; + } + } + + buffer << "}" << std::endl; + } + + std::set createImports(Schema *schema); + + std::map generateWires(Schema *schema, ostream &ostream); + + void generateSubComponents(Schema *schema, map &wires, ostream &buffer); + + void generateDisplay(Schema *schema, ostream &buffer); + + void generate_comdel(Schema *schema, Library &library, std::ostream &buffer) { + buffer << library.getHeader() << std::endl; + + std::set imports = createImports(schema); + + for (auto &import: imports) { + buffer << "#include \"" << library.getComponentDirectory() << "\\" << import << "\"" << std::endl; + } + + buffer << "\n\n" << std::endl; + + buffer << "component System" << std::endl << "{" << std::endl; + + if (library.getComponentHeader().has_value()) { + buffer << library.getComponentHeader().value() << endl; + } + + auto wires = generateWires(schema, buffer); + + generateSubComponents(schema, wires, buffer); + + generateDisplay(schema, buffer); + + buffer << "}"; + } + + void generateBus(BusInstance *bus, ostream &buffer); + + void generateConnection(ConnectionInstance *connection, ostream &buffer); + + void generateDisplay(Schema *schema, ostream &buffer) { + buffer << "\n\tdisplay {\n"; + + for (auto &component: schema->componentInstances) { + buffer << "\t\tcomponent { x: " << component->position.first << "; y: " << component->position.second + << "; ref: \"" << component->name << "\"; }" << std::endl; + } + + for (auto &bus: schema->busInstances) { + generateBus(bus.get(), buffer); + } + + buffer << "\n"; + + for (auto &connection: schema->connections) { + generateConnection(connection.get(), buffer); + } + + buffer << "\t}\n"; + } + + void generateConnection(ConnectionInstance *connection, ostream &buffer) { + buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " << + "x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n"; + } + + void generateBus(BusInstance *bus, ostream &buffer) { + buffer << "\n"; + buffer << "\t\t// " << bus->name << " bus\n\n"; + + if (bus->bus.getDisplayBus().has_value()) { + bus->bus.getDisplayBus()->comdel(buffer, bus->position.first, bus->position.second, bus->size); } } - buffer << "}" << std::endl; -} + void generateWire(std::string &name, Wire &wire, ostream &buffer); -std::set createImports(Schema *schema); + std::map generateWires(Schema *schema, ostream &buffer) { + std::set usedNames; + std::map usedMappings; + for (auto &bus: schema->busInstances) { + buffer << "\t//" << bus->name << std::endl; + for (auto &wire: bus->bus.getWires()) { + std::string name = wire.getName(); + if (usedNames.count(wire.getName()) > 0) { + name = bus->name + "__" + wire.getName(); + } + if (wire.isHidden()) { + name = "--" + name; + } + usedNames.insert(name); + usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name)); -std::map generateWires(Schema *schema, ostream &ostream); - -void generateSubComponents(Schema *schema, map &wires, ostream &buffer); - -void generateDisplay(Schema *schema, ostream &buffer); - -void generateComdelFile(Schema *schema, Library &library, std::ostream &buffer) { - buffer << library.getHeader() << std::endl; - - std::set imports = createImports(schema); - - for(auto& import: imports) { - buffer << "#include \"" << library.getComponentDirectory() << "\\" << import << "\"" << std::endl; - } - - buffer << "\n\n" << std::endl; - - buffer << "component System" << std::endl << "{" << std::endl; - - if(library.getComponentHeader().has_value()) { - buffer << library.getComponentHeader().value() << endl; - } - - auto wires = generateWires(schema, buffer); - - generateSubComponents(schema, wires, buffer); - - generateDisplay(schema, buffer); - - buffer << "}"; -} - -void generateBus(BusInstance *bus, ostream &buffer); -void generateConnection(ConnectionInstance *connection, ostream &buffer); - -void generateDisplay(Schema *schema, ostream &buffer) { - buffer << "\n\tdisplay {\n"; - - for(auto &component: schema->componentInstances) { - buffer << "\t\tcomponent { x: " << component->position.first << "; y: " << component->position.second << "; ref: \"" << component->name << "\"; }" << std::endl; - } - - for(auto &bus: schema->busInstances) { - generateBus(bus.get(), buffer); - } - - buffer << "\n"; - - for(auto &connection: schema->connections) { - generateConnection(connection.get(), buffer); - } - - buffer << "\t}\n"; -} - -void generateConnection(ConnectionInstance *connection, ostream &buffer) { - buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " << - "x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n"; -} - -void generateBus(BusInstance *bus, ostream &buffer) { - buffer << "\n"; - buffer << "\t\t// " << bus->name << " bus\n\n"; - - if(bus->bus.getDisplayBus().has_value()) { - bus->bus.getDisplayBus()->comdel(buffer, bus->position.first, bus->position.second, bus->size); - } -} - -void generateWire(std::string &name, Wire& wire, ostream &buffer); - -std::map generateWires(Schema *schema, ostream &buffer) { - std::set usedNames; - std::map usedMappings; - for(auto &bus: schema->busInstances) { - buffer << "\t//" << bus->name << std::endl; - for(auto& wire: bus->bus.getWires()) { - std::string name = wire.getName(); - if(usedNames.count(wire.getName()) > 0) { - name = bus->name + "__" + wire.getName(); + generateWire(name, wire, buffer); } - if(wire.isHidden()) { - name = "--" + name; - } - usedNames.insert(name); - usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name)); - - generateWire(name, wire, buffer); + buffer << std::endl << std::endl; } - buffer << std::endl << std::endl; - } - return usedMappings; -} - -void generateWire(std::string &name, Wire& wire, ostream &buffer) { - buffer << "\t"; - switch (wire.getType()) { - case Wire::R_WIRE: - buffer << "r_wire"; - break; - case Wire::WIRED_AND: - buffer << "wired_and"; - break; - case Wire::WIRED_OR: - buffer << "wired_or"; - break; - default: - buffer << "wire"; + return usedMappings; } - if(wire.getWidth() != 1) { - buffer << "<" << wire.getWidth() << ">"; + void generateWire(std::string &name, Wire &wire, ostream &buffer) { + buffer << "\t"; + switch (wire.getType()) { + case Wire::R_WIRE: + buffer << "r_wire"; + break; + case Wire::WIRED_AND: + buffer << "wired_and"; + break; + case Wire::WIRED_OR: + buffer << "wired_or"; + break; + default: + buffer << "wire"; + } + + if (wire.getWidth() != 1) { + buffer << "<" << wire.getWidth() << ">"; + } + buffer << " " << name << ";" << std::endl; } - buffer << " " << name << ";" << std::endl; -} -std::set createImports(Schema *schema) { - std::set importSet; - for(auto &component: schema->componentInstances) { - importSet.insert(component->component.getSource()); + std::set createImports(Schema *schema) { + std::set importSet; + for (auto &component: schema->componentInstances) { + importSet.insert(component->component.getSource()); + } + return importSet; } - return importSet; -} -void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, stringstream &buffer); + void + generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, + stringstream &buffer); -void generateSingleAutomaticPin(DirectConnectionInstance *instance, string name, string pin, - map &wireNames, - stringstream &buffer); + void generateSingleAutomaticPin(DirectConnectionInstance *instance, string name, string pin, + map &wireNames, + stringstream &buffer); - void generateComponent(Schema *schema, map &wires, ostream &buffer, - shared_ptr &component); + void generateComponent(Schema *schema, map &wires, ostream &buffer, + shared_ptr &component); void generateSubComponents(Schema *schema, map &wires, ostream &buffer) { - buffer << "\t// components --------------------------------------------" << std::endl; + buffer << "\t// components --------------------------------------------" << std::endl; - for(auto& component: schema->componentInstances) { - if(component->component.getType() == Component::MEMORY) { - generateComponent(schema, wires, buffer, component); + for (auto &component: schema->componentInstances) { + if (component->component.getType() == Component::MEMORY) { + generateComponent(schema, wires, buffer, component); + } } - } - for(auto& component: schema->componentInstances) { - if(component->component.getType() != Component::MEMORY) { - generateComponent(schema, wires, buffer, component); - } - } -} - -void generateComponent(Schema *schema, map &wires, ostream &buffer, - shared_ptr &component) { - buffer << "\tsubcomponent " << component->component.getName() << " " << component->name; - - std::optional memory; - - std::vector attributes; - for(auto& attr: component->attributes) { - if(attr.name != "_memory") { - attributes.push_back(attr); - } else if(attr.name == "_memory" && attr.value.asMemoryReference().has_value()) { - memory = attr; + for (auto &component: schema->componentInstances) { + if (component->component.getType() != Component::MEMORY) { + generateComponent(schema, wires, buffer, component); + } } } - if(!attributes.empty()) { - buffer << "<"; - buffer << attributes[0].value.stringify(); - for(int i=1; i &wires, ostream &buffer, + shared_ptr &component) { + buffer << "\tsubcomponent " << component->component.getName() << " " << component->name; + + std::optional memory; + + std::vector attributes; + for (auto &attr: component->attributes) { + if (attr.name != "_memory") { + attributes.push_back(attr); + } else if (attr.name == "_memory" && attr.value.asMemoryReference().has_value()) { + memory = attr; + } } - buffer << ">"; - } - stringstream tempOutput; + if (!attributes.empty()) { + buffer << "<"; + buffer << attributes[0].value.stringify(); + for (int i = 1; i < attributes.size(); i++) { + buffer << ", " << attributes[i].value.stringify(); + } + buffer << ">"; + } - for(auto &pin: component->component.getPins()) { - if(schema->hasConnection(component->name, pin.getName())) { - auto conn = schema->getConnection(component->name, pin.getName()); - auto busConn = dynamic_cast(conn); - if(busConn != nullptr) { - for(auto wire: busConn->connection.getWires()) { - if(wire.isType(Value::ATTRIBUTE_REFERENCE)) { - auto attribute = busConn->getAttribute(wire.asReference()); - if(wire.isType(Value::WIRE_REFERENCE)) { - tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; - } else if(wire.isType(Value::NIL)) { - tempOutput << "*, "; + stringstream tempOutput; + + for (auto &pin: component->component.getPins()) { + if (schema->hasConnection(component->name, pin.getName())) { + auto conn = schema->getConnection(component->name, pin.getName()); + auto busConn = dynamic_cast(conn); + if (busConn != nullptr) { + for (auto wire: busConn->connection.getWires()) { + if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { + auto attribute = busConn->getAttribute(wire.asReference()); + if (wire.isType(Value::WIRE_REFERENCE)) { + tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; + } else if (wire.isType(Value::NIL)) { + tempOutput << "*, "; + } else { + tempOutput << attribute.value.stringify() << ", "; + } } else { - tempOutput << attribute.value.stringify() << ", "; - } - } else { - if(wire.isType(Value::WIRE_REFERENCE)) { - tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; - } else if(wire.isType(Value::NIL)) { - tempOutput << "*, "; - } else { - tempOutput << wire.stringify() << ", "; + if (wire.isType(Value::WIRE_REFERENCE)) { + tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; + } else if (wire.isType(Value::NIL)) { + tempOutput << "*, "; + } else { + tempOutput << wire.stringify() << ", "; + } } } } - } - auto dirConn = dynamic_cast(conn); - if(dirConn != nullptr) { - if(dirConn->bus->bus.getType() == Bus::AUTOMATIC) { - generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); - } else { - generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); + auto dirConn = dynamic_cast(conn); + if (dirConn != nullptr) { + if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) { + generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); + } else { + generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); + } + } + } else { + // if no connection exists than defaults must exist + for (auto &wire: *pin.getWires()) { + tempOutput << wire.stringify() << ", "; } } + } + + auto wireList = tempOutput.str(); + wireList.pop_back(); + wireList.pop_back(); // remove last COMMA(", ") + + buffer << "(" << wireList << ")"; + + if (memory.has_value()) { + buffer << " uses " << *memory->value.asMemoryReference(); + } + + buffer << ";" << std::endl; + + } + + void generateSingleAutomaticPin(DirectConnectionInstance *connection, string name, string pin, + map &wireNames, stringstream &buffer) { + std::vector wires; + std::string selected; + std::vector defaults; + if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { + wires = connection->connection.getWires(); + selected = connection->attributes[0].value.asReference(); + defaults = *connection->instance->component.getPin(pin).getWires(); } else { - // if no connection exists than defaults must exist - for(auto& wire: *pin.getWires()) { - tempOutput << wire.stringify() << ", "; + wires = *connection->connection.getSecondWires(); + selected = connection->attributes[1].value.asReference(); + defaults = *connection->secondInstance->component.getPin(pin).getWires(); + } + + for (int i = 0; i < wires.size(); i++) { + if (wires[i].isType(Value::STRING)) { + if (wires[i].asString() == selected) { + buffer << wireNames[connection->bus->name + "." + connection->bus->bus.getWires()[0].getName()] + << ", "; + } else { + buffer << defaults[i].stringify(); + } + } else { + buffer << wires[i].stringify() << ", "; } } } - auto wireList = tempOutput.str(); - wireList.pop_back(); - wireList.pop_back(); // remove last COMMA(", ") - - buffer << "(" << wireList << ")"; - - if(memory.has_value()) { - buffer << " uses " << *memory->value.asMemoryReference(); - } - - buffer << ";" << std::endl; - -} - -void generateSingleAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map &wireNames, stringstream &buffer) { - std::vector wires; - std::string selected; - std::vector defaults; - if(connection->instance->name == name && connection->connection.getComponent().pin == pin) { - wires = connection->connection.getWires(); - selected = connection->attributes[0].value.asReference(); - defaults = *connection->instance->component.getPin(pin).getWires(); - } else { - wires = *connection->connection.getSecondWires(); - selected = connection->attributes[1].value.asReference(); - defaults = *connection->secondInstance->component.getPin(pin).getWires(); - } - - for(int i=0; ibus->name + "." + connection->bus->bus.getWires()[0].getName()] << ", "; - } else { - buffer << defaults[i].stringify(); - } + void + generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, + stringstream &buffer) { + std::vector wires; + if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { + wires = connection->connection.getWires(); } else { - buffer << wires[i].stringify() << ", "; + wires = *connection->connection.getSecondWires(); } - } -} - -void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, stringstream &buffer) { - std::vector wires; - if(connection->instance->name == name && connection->connection.getComponent().pin == pin) { - wires = connection->connection.getWires(); - } else { - wires = *connection->connection.getSecondWires(); - } - for(auto& wire: wires) { - if(wire.isType(Value::ATTRIBUTE_REFERENCE)) { - auto attribute = connection->getAttribute(wire.asReference()); - if(wire.isType(Value::WIRE_REFERENCE)) { - buffer << wireNames[connection->bus->name + "." + attribute.value.asReference()] << ", "; - } else if(wire.isType(Value::NIL)) { - buffer << "*, "; + for (auto &wire: wires) { + if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { + auto attribute = connection->getAttribute(wire.asReference()); + if (wire.isType(Value::WIRE_REFERENCE)) { + buffer << wireNames[connection->bus->name + "." + attribute.value.asReference()] << ", "; + } else if (wire.isType(Value::NIL)) { + buffer << "*, "; + } else { + buffer << attribute.value.stringify() << ", "; + } } else { - buffer << attribute.value.stringify() << ", "; - } - } else { - if(wire.isType(Value::WIRE_REFERENCE)) { - buffer << wireNames[connection->bus->name + "." + wire.asReference()] << ", "; - } else if(wire.isType(Value::NIL)) { - buffer << "*, "; - } else { - buffer << wire.stringify() << ", "; + if (wire.isType(Value::WIRE_REFERENCE)) { + buffer << wireNames[connection->bus->name + "." + wire.asReference()] << ", "; + } else if (wire.isType(Value::NIL)) { + buffer << "*, "; + } else { + buffer << wire.stringify() << ", "; + } } } } -} } // domain \ No newline at end of file diff --git a/comdel/domain/comdel_generator.h b/comdel/domain/comdel_generator.h index 170b5c1..644ff1f 100644 --- a/comdel/domain/comdel_generator.h +++ b/comdel/domain/comdel_generator.h @@ -7,9 +7,9 @@ namespace domain { -void generateSchemaFile(std::string& librarySource, Schema *schema, std::ostream &buffer); + void generate_schema(std::string &librarySource, Schema *schema, std::ostream &buffer); -void generateComdelFile(Schema *schema, Library &library, std::ostream &buffer); + void generate_comdel(Schema *schema, Library &library, std::ostream &buffer); } // domain diff --git a/comdel/domain/comdel_validator.cpp b/comdel/domain/comdel_validator.cpp new file mode 100644 index 0000000..d4ba64e --- /dev/null +++ b/comdel/domain/comdel_validator.cpp @@ -0,0 +1,206 @@ +#include "comdel_validator.h" +#include "library.h" + +namespace domain { + + std::vector ComdelValidator::validateSchema(Schema &schema, ValidationContext context) { + std::vector errors; + + context.instance = nullptr; + context.attribute = nullptr; + + for (auto &instance: schema.componentInstances) { + auto result = validateComponent(instance.get(), context); + errors.insert(errors.end(), result.begin(), result.end()); + } + return errors; + } + + std::vector + ComdelValidator::validateInstanceCount(Schema &schema, Library &library, ValidationContext context) { + std::vector errors; + + // validate instance count + std::map instanceMap; + for (auto &inst: schema.componentInstances) { + instanceMap[inst->component.getName()]++; + } + + for (auto comp: library.getComponents()) { + int count = instanceMap[comp.getName()]; + + context.attributes["componentName"] = Value::fromString(comp.getName()); + context.attributes["min"] = Value::fromInt(comp.getCount().first); + context.attributes["max"] = Value::fromInt(comp.getCount().second); + context.attributes["count"] = Value::fromInt(count); + + if (count < comp.getCount().first) { + auto message = populateMessage( + "Not enough instances of component '{componentName}' required at least {min}, found {count}", + context); + errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); + } else if (count > comp.getCount().second) { + auto message = populateMessage( + "To many instances of component '{componentName}' allow at most {max}, found {count}", context); + errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); + } + } + + + // validate bus instance count + std::map busInstanceMap; + for (auto &inst: schema.busInstances) { + busInstanceMap[inst->bus.getName()]++; + } + + for (auto bus: library.getBuses()) { + int count = busInstanceMap[bus.getName()]; + + context.attributes["busName"] = Value::fromString(bus.getName()); + context.attributes["min"] = Value::fromInt(bus.getCount().first); + context.attributes["max"] = Value::fromInt(bus.getCount().second); + context.attributes["count"] = Value::fromInt(count); + + if (count < bus.getCount().first) { + auto message = populateMessage( + "Not enough instances of bus '{busName}' required at least {min}, found {count}", context); + errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); + } else if (count > bus.getCount().second) { + auto message = populateMessage( + "To many instances of bus '{busName}' allow at most {max}, found {count}", context); + errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); + } + } + + return errors; + } + + std::vector + ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) { + std::vector errors; + + for (auto &inst: schema.componentInstances) { + for (auto &pin: inst->component.getPins()) { + if (pin.getConnection().getType() == PinConnection::REQUIRED) { + if (!connectionExists(schema, inst, pin)) { + context.instance = inst.get(); + context.attributes["instanceName"] = Value::fromString(inst->name); + auto message = populateMessage(pin.getConnection().getMessage(), context); + errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); + } + } + } + } + + return errors; + } + + std::vector + ComdelValidator::validateComponent(ComponentInstance *instance, ValidationContext context) { + std::vector errors; + + context.instance = instance; + context.attributes.clear(); + + for (auto &attribute: instance->attributes) { + context.attributes[attribute.name] = attribute.value; + } + + for (auto &rule: instance->component.getRules()) { + auto result = validateRule(rule, context); + if (result) { + errors.push_back(*result); + } + } + + for (auto &attribute: instance->attributes) { + auto result = validateAttribute(&attribute, context); + errors.insert(errors.end(), result.begin(), result.end()); + } + + return errors; + } + + std::vector + ComdelValidator::validateAttribute(InstanceAttribute *attribute, ValidationContext context) { + std::vector errors; + if (attribute->attribute.getPopup()) { + Popup popup = *attribute->attribute.getPopup(); + context.attribute = attribute; + context.attributes = std::map{{attribute->name, attribute->value}}; + + for (auto &rule: popup.getRules()) { + auto result = validateRule(rule, context); + if (result) { + errors.push_back(*result); + } + } + } + return errors; + } + + std::optional ComdelValidator::validateRule(Rule rule, ValidationContext context) { + RuleContext ruleContext; + ruleContext.addressSpaces = context.addressSpaces; + ruleContext.attributes = context.attributes; + ruleContext.function = validators; + auto action = rule.evaluate(ruleContext); + if (action) { + std::string message = this->populateMessage(action->getMessage(), context); + return ValidationError{context.instance, context.attribute, action->getType(), message}; + } + return nullopt; + } + + std::string ComdelValidator::populateMessage(string source, ValidationContext context) { + for (auto &[key, value]: context.attributes) { + source = replacePlaceholder(source, key, value); + } + return source; + } + + string ComdelValidator::replacePlaceholder(string source, string key, Value value) { + key = "{" + key + "}"; + auto placeholderValue = value.string(); + + auto found = source.find(key); + while (found != string::npos) { + source.replace(found, key.length(), placeholderValue); + found = source.find(key); + } + return source; + } + + bool ComdelValidator::connectionExists(Schema &schema, shared_ptr &component, Pin &pin) { + for (auto conn: schema.connections) { + auto busConnection = dynamic_cast(conn.get()); + if (busConnection != nullptr) { + if (busConnection->instance->name == component->name && + busConnection->connection.getComponent().pin == pin.getName()) { + return true; + } + } + + auto directConnection = dynamic_cast(conn.get()); + if (directConnection != nullptr) { + if (directConnection->instance->name == component->name && + busConnection->connection.getComponent().pin == pin.getName()) { + return true; + } + if (directConnection->secondInstance->name == component->name && + busConnection->connection.getSecondComponent()->pin == pin.getName()) { + return true; + } + } + } + return false; + } + + ComdelValidator::ComdelValidator(std::vector validators) { + for (auto *validator: validators) { + validator->clear(); + this->validators.insert(std::make_pair(validator->getName(), validator)); + } + } + +} \ No newline at end of file diff --git a/comdel/domain/comdel_validator.h b/comdel/domain/comdel_validator.h new file mode 100644 index 0000000..f5d9fb5 --- /dev/null +++ b/comdel/domain/comdel_validator.h @@ -0,0 +1,52 @@ +#ifndef COMDEL_VALIDATOR_H +#define COMDEL_VALIDATOR_H + +#include "instance.h" +#include "schema.h" +#include "library.h" + +namespace domain { + + struct ValidationError { + ComponentInstance *instance; + InstanceAttribute *attribute; + Action::ActionType type; + std::string message; + }; + + struct ValidationContext { + ComponentInstance *instance; + InstanceAttribute *attribute; + std::map addressSpaces; + std::map attributes; + }; + + class ComdelValidator { + public: + std::vector validateSchema(Schema &schema, ValidationContext context); + + std::vector validateComponent(ComponentInstance *instance, ValidationContext context); + + std::vector validateAttribute(InstanceAttribute *attribute, ValidationContext context); + + std::optional validateRule(Rule rule, ValidationContext context); + + std::vector validateInstanceCount(Schema &schema, Library &library, ValidationContext context); + + std::vector + validatePinConnections(Schema &schema, Library &library, ValidationContext context); + + ComdelValidator(std::vector validators); + + private: + std::map validators; + + std::string populateMessage(string message, ValidationContext context); + + string replacePlaceholder(string message, const string name, Value value); + + bool connectionExists(Schema &schema, shared_ptr &component, Pin &pin); + }; + +} +#endif //COMDEL_VALIDATOR_H diff --git a/comdel/domain/comdelvalidator.cpp b/comdel/domain/comdelvalidator.cpp deleted file mode 100644 index 7e749e4..0000000 --- a/comdel/domain/comdelvalidator.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "comdelvalidator.h" -#include "library.h" - -namespace domain { - -std::vector ComdelValidator::validateSchema(Schema &schema, ValidationContext context) { - std::vector errors; - - context.instance = nullptr; - context.attribute = nullptr; - - for(auto &instance: schema.componentInstances) { - auto result = validateComponent(instance.get(), context); - errors.insert(errors.end(), result.begin(), result.end()); - } - return errors; -} - - std::vector ComdelValidator::validateInstanceCount(Schema& schema, Library& library, ValidationContext context) { - std::vector errors; - - // validate instance count - std::map instanceMap; - for(auto& inst: schema.componentInstances) { - instanceMap[inst->component.getName()]++; - } - - for(auto comp: library.getComponents()) { - int count = instanceMap[comp.getName()]; - - context.attributes["componentName"] = Value::fromString(comp.getName()); - context.attributes["min"] = Value::fromInt(comp.getCount().first); - context.attributes["max"] = Value::fromInt(comp.getCount().second); - context.attributes["count"] = Value::fromInt(count); - - if(count < comp.getCount().first) { - auto message = populateMessage("Not enough instances of component '{componentName}' required at least {min}, found {count}", context); - errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); - } else if(count > comp.getCount().second) { - auto message = populateMessage("To many instances of component '{componentName}' allow at most {max}, found {count}", context); - errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); - } - } - - - // validate bus instance count - std::map busInstanceMap; - for(auto& inst: schema.busInstances) { - busInstanceMap[inst->bus.getName()]++; - } - - for(auto bus: library.getBuses()) { - int count = busInstanceMap[bus.getName()]; - - context.attributes["busName"] = Value::fromString(bus.getName()); - context.attributes["min"] = Value::fromInt(bus.getCount().first); - context.attributes["max"] = Value::fromInt(bus.getCount().second); - context.attributes["count"] = Value::fromInt(count); - - if(count < bus.getCount().first) { - auto message = populateMessage("Not enough instances of bus '{busName}' required at least {min}, found {count}", context); - errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); - } else if(count > bus.getCount().second) { - auto message = populateMessage("To many instances of bus '{busName}' allow at most {max}, found {count}", context); - errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); - } - } - - return errors; - } - - std::vector ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) { - std::vector errors; - - for(auto& inst: schema.componentInstances) { - for(auto& pin: inst->component.getPins()) { - if(pin.getConnection().getType() == PinConnection::REQUIRED) { - if(!connectionExists(schema, inst, pin)) { - context.instance = inst.get(); - context.attributes["instanceName"] = Value::fromString(inst->name); - auto message = populateMessage(pin.getConnection().getMessage(), context); - errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message}); - } - } - } - } - - return errors; - } - -std::vector ComdelValidator::validateComponent(ComponentInstance* instance, ValidationContext context) { - std::vector errors; - - context.instance = instance; - context.attributes.clear(); - - for(auto &attribute: instance->attributes) { - context.attributes[attribute.name] = attribute.value; - } - - for(auto &rule: instance->component.getRules()) { - auto result = validateRule(rule, context); - if(result) { - errors.push_back(*result); - } - } - - for(auto &attribute: instance->attributes) { - auto result = validateAttribute(&attribute, context); - errors.insert(errors.end(), result.begin(), result.end()); - } - - return errors; -} - -std::vector ComdelValidator::validateAttribute(InstanceAttribute *attribute, ValidationContext context) { - std::vector errors; - if(attribute->attribute.getPopup()) { - Popup popup = *attribute->attribute.getPopup(); - context.attribute = attribute; - context.attributes = std::map{{attribute->name, attribute->value}}; - - for(auto &rule: popup.getRules()) { - auto result = validateRule(rule, context); - if(result) { - errors.push_back(*result); - } - } - } - return errors; -} - -std::optional ComdelValidator::validateRule(Rule rule, ValidationContext context) { - RuleContext ruleContext; - ruleContext.addressSpaces = context.addressSpaces; - ruleContext.attributes = context.attributes; - ruleContext.function = validators; - auto action = rule.evaluate(ruleContext); - if (action) { - std::string message = this->populateMessage(action->getMessage(), context); - return ValidationError{context.instance, context.attribute, action->getType(), message}; - } - return nullopt; -} - -std::string ComdelValidator::populateMessage(string source, ValidationContext context) { - for(auto &[key, value]: context.attributes) { - source = replacePlaceholder(source, key, value); - } - return source; -} - -string ComdelValidator::replacePlaceholder(string source, string key, Value value) { - key = "{" + key + "}"; - auto placeholderValue = value.string(); - - auto found = source.find(key); - while(found != string::npos) { - source.replace(found, key.length(), placeholderValue); - found = source.find(key); - } - return source; -} - - bool ComdelValidator::connectionExists(Schema &schema, shared_ptr &component, Pin &pin) { - for(auto conn: schema.connections) { - auto busConnection = dynamic_cast(conn.get()); - if(busConnection != nullptr) { - if(busConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) { - return true; - } - } - - auto directConnection = dynamic_cast(conn.get()); - if(directConnection != nullptr) { - if(directConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) { - return true; - } - if(directConnection->secondInstance->name == component->name && busConnection->connection.getSecondComponent()->pin == pin.getName()) { - return true; - } - } - } - return false; - } - -} \ No newline at end of file diff --git a/comdel/domain/comdelvalidator.h b/comdel/domain/comdelvalidator.h deleted file mode 100644 index f8c608b..0000000 --- a/comdel/domain/comdelvalidator.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef COMDEL_VALIDATOR_H -#define COMDEL_VALIDATOR_H - -#include "instance.h" -#include "schema.h" -#include "library.h" - -namespace domain { - -struct ValidationError -{ - ComponentInstance *instance; - InstanceAttribute *attribute; - Action::ActionType type; - std::string message; -}; - -struct ValidationContext { - ComponentInstance *instance; - InstanceAttribute *attribute; - std::map addressSpaces; - std::map attributes; -}; - -class ComdelValidator -{ -public: - std::vector validateSchema(Schema& schema, ValidationContext context); - std::vector validateComponent(ComponentInstance *instance, ValidationContext context); - std::vector validateAttribute(InstanceAttribute *attribute, ValidationContext context); - std::optional validateRule(Rule rule, ValidationContext context); - - std::vector validateInstanceCount(Schema &schema, Library& library, ValidationContext context); - std::vector validatePinConnections(Schema &schema, Library& library, ValidationContext context); - - ComdelValidator(std::vector validators) { - for(auto* validator: validators) { - validator->clear(); - this->validators.insert(std::make_pair(validator->getName(), validator)); - } - } - -private: - std::map validators; - - std::string populateMessage(string message, ValidationContext context); - - string replacePlaceholder(string message, const string name, Value value); - - bool connectionExists(Schema &schema, shared_ptr &component, Pin &pin); -}; - -} -#endif //COMDEL_VALIDATOR_H diff --git a/comdel/domain/component.cpp b/comdel/domain/component.cpp index f671b9d..e6555df 100644 --- a/comdel/domain/component.cpp +++ b/comdel/domain/component.cpp @@ -2,84 +2,97 @@ namespace domain { -Component::Component(string name, string tooltip, string source, ComponentType type, - vector rules, string instanceName, pair count, Display display, - vector pins, vector attributes) - : name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), count(count), display(display), pins(pins), attributes(attributes) -{} + Component::Component(string name, string tooltip, string source, ComponentType type, + vector rules, string instanceName, pair count, Display display, + vector pins, vector attributes) + : name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), + count(count), display(display), pins(pins), attributes(attributes) {} -std::string Component::getName() { - return name; -} -std::string Component::getTooltip() { - return tooltip; -} -std::string Component::getSource() { - return source; -} -Component::ComponentType Component::getType() { - return type; -} -std::vector Component::getRules() { - return rules; -} -std::string Component::getInstanceName() { - return instanceName; -} -std::pair Component::getCount() { - return count; -} -Display Component::getDisplay() { - return display; -} - -std::vector Component::getPins() { - return pins; -} -Pin Component::getPin(std::string pin) { - for(uint i=0; i Component::getAttributes() { - return attributes; -} -Attribute Component::getAttribute(std::string attribute) { - for(uint i=0; i Component::getRules() { + return rules; + } + + std::string Component::getInstanceName() { + return instanceName; + } + + std::pair Component::getCount() { + return count; + } + + Display Component::getDisplay() { + return display; + } + + std::vector Component::getPins() { + return pins; + } + + Pin Component::getPin(std::string pin) { + for (auto & p: pins) { + if (p.getName() == pin) { + return p; + } + } + throw std::exception(); + } + + bool Component::hasPin(std::string name) { + for (auto pin: pins) { + if (pin.getName() == name) { + return true; + } + } + return false; + } + + std::vector Component::getAttributes() { + return attributes; + } + + Attribute Component::getAttribute(std::string attribute) { + for (auto & attr : attributes) { + if (attr.getName() == attribute) { + return attr; + } + } + throw std::exception(); + } + + bool Component::hasAttribute(std::string name, Value::ValueType type) { + for (auto & attribute : attributes) { + if (attribute.getName() == name && attribute.getDefault().getType() == type) { + return true; + } + if (attribute.getName() == name && (type == Value::NIL && + (attribute.getDefault().getType() == Value::MEMORY_REFERENCE || + attribute.getDefault().getType() == Value::WIRE_REFERENCE))) { + return true; + } + if (attribute.getName() == name && (type == Value::UNDEFINED && + (attribute.getDefault().getType() == Value::MEMORY_REFERENCE || + attribute.getDefault().getType() == Value::WIRE_REFERENCE))) { + return true; + } + } + return false; + } } // namespace domain diff --git a/comdel/domain/component.h b/comdel/domain/component.h index c377522..5a8cbab 100644 --- a/comdel/domain/component.h +++ b/comdel/domain/component.h @@ -11,56 +11,65 @@ namespace domain { -using namespace std; + using namespace std; + + class Component { + public: + enum ComponentType { + OTHER, + PROCESSOR, + MEMORY + }; + + private: + std::string name; + std::string tooltip; + std::string source; + ComponentType type; + std::vector rules; + std::string instanceName; + std::pair count; + Display display; + + std::vector pins; + std::vector attributes; + + public: + + Component(string name, string tooltip, string source, ComponentType type, + vector rules, string instanceName, pair count, Display display, + vector pins, vector attributes); + + std::string getName(); + + std::string getTooltip(); + + std::string getSource(); + + ComponentType getType(); + + std::vector getRules(); + + std::string getInstanceName(); + + std::pair getCount(); + + Display getDisplay(); + + std::vector getPins(); + + Pin getPin(std::string pin); + + std::vector getAttributes(); + + Attribute getAttribute(std::string attribute); + + bool hasAttribute(std::string name, Value::ValueType type); + + bool hasPin(std::string name); -class Component -{ -public: - enum ComponentType { - OTHER, - PROCESSOR, - MEMORY }; -private: - std::string name; - std::string tooltip; - std::string source; - ComponentType type; - std::vector rules; - std::string instanceName; - std::pair count; - Display display; - - std::vector pins; - std::vector attributes; - -public: - - Component(string name, string tooltip, string source, ComponentType type, - vector rules, string instanceName, pair count, Display display, - vector pins, vector attributes); - - std::string getName(); - std::string getTooltip(); - std::string getSource(); - ComponentType getType(); - std::vector getRules(); - std::string getInstanceName(); - std::pair getCount(); - Display getDisplay(); - - std::vector getPins(); - Pin getPin(std::string pin); - - std::vector getAttributes(); - Attribute getAttribute(std::string attribute); - bool hasAttribute(std::string name, Value::ValueType type); - - bool hasPin(std::string name); - -}; - } // namespace domain #endif // DOMAIN_COMPONENT_H diff --git a/comdel/domain/connection.cpp b/comdel/domain/connection.cpp index 601f5ec..732eb90 100644 --- a/comdel/domain/connection.cpp +++ b/comdel/domain/connection.cpp @@ -2,74 +2,77 @@ namespace domain { -Connection::Connection(ConnectionComponent first, std::optional second, - std::string bus, std::vector attributes, - std::vector firstWires, std::optional> secondWires) - : first(first), second(second), bus(bus), attributes(attributes), firstWires(firstWires), secondWires(secondWires) -{} + Connection::Connection(ConnectionComponent first, std::optional second, + std::string bus, std::vector attributes, + std::vector firstWires, std::optional> secondWires) + : first(first), second(second), bus(bus), attributes(attributes), firstWires(firstWires), + secondWires(secondWires) {} -ConnectionComponent Connection::getComponent() { - return first; -} -std::optional Connection::getSecondComponent() { - return second; -} - -std::string Connection::getBus() { - return bus; -} - -std::vector Connection::getAttributes() { - return attributes; -} -std::vector Connection::getWires() { - return firstWires; -} -std::optional> Connection::getSecondWires() { - return secondWires; -} - -Attribute Connection::getAttribute(std::string name) { - for(unsigned int i=0; i Connection::getSecondComponent() { + return second; } - return false; -} -bool Connection::isConnecting(ConnectionComponent component) { - return first == component || (second.has_value() && *second == component); -} + std::string Connection::getBus() { + return bus; + } -bool Connection::isConnecting(ConnectionComponent component, std::string bus) { - return this->bus == bus && (first == component || (second.has_value() && *second == component)); -} + std::vector Connection::getAttributes() { + return attributes; + } -bool Connection::isConnecting(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { - if(!second.has_value()) { + std::vector Connection::getWires() { + return firstWires; + } + + std::optional> Connection::getSecondWires() { + return secondWires; + } + + Attribute Connection::getAttribute(std::string name) { + for (unsigned int i = 0; i < attributes.size(); i++) { + if (attributes[i].getName() == name) { + return attributes[i]; + } + } + throw std::exception(); + } + + bool Connection::hasAttribute(std::string name) { + for (unsigned int i = 0; i < attributes.size(); i++) { + if (attributes[i].getName() == name) { + return true; + } + } return false; } - return (this->first == component && this->bus == bus && this->second == secondComponent) || - (this->first == secondComponent && this->bus == bus && this->second == component); -} + + bool Connection::isConnecting(ConnectionComponent component) { + return first == component || (second.has_value() && *second == component); + } + + bool Connection::isConnecting(ConnectionComponent component, std::string bus) { + return this->bus == bus && (first == component || (second.has_value() && *second == component)); + } + + bool Connection::isConnecting(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { + if (!second.has_value()) { + return false; + } + return (this->first == component && this->bus == bus && this->second == secondComponent) || + (this->first == secondComponent && this->bus == bus && this->second == component); + } bool Connection::isConnecting(ConnectionComponent component, ConnectionComponent secondComponent) { - if(!second.has_value()) { + if (!second.has_value()) { return false; } - return (this->first == component && this->second == secondComponent) || - (this->first == secondComponent && this->second == component); + return (this->first == component && this->second == secondComponent) || + (this->first == secondComponent && this->second == component); } diff --git a/comdel/domain/connection.h b/comdel/domain/connection.h index 8319ee7..8e2f96c 100644 --- a/comdel/domain/connection.h +++ b/comdel/domain/connection.h @@ -8,65 +8,68 @@ namespace domain { -struct ConnectionComponent -{ - std::string component; - std::string pin; + struct ConnectionComponent { + std::string component; + std::string pin; - bool operator==(const ConnectionComponent& rhs) const - { - return (component == rhs.component) && (pin == rhs.pin); - } - bool operator!=(const ConnectionComponent& rhs) const - { - return !operator==(rhs); - } - bool operator<(const ConnectionComponent& rhs) const - { - if(component < rhs.component) { - return true; - } else if(component == rhs.component) { - if(pin < rhs.pin) { - return true; - } + bool operator==(const ConnectionComponent &rhs) const { + return (component == rhs.component) && (pin == rhs.pin); } - return false; - } -}; -class Connection -{ - ConnectionComponent first; - std::optional second; - std::string bus; - std::vector attributes; + bool operator!=(const ConnectionComponent &rhs) const { + return !operator==(rhs); + } - std::vector firstWires; - std::optional> secondWires; -public: - Connection(ConnectionComponent first, std::optional second, - std::string bus, std::vector attributes, - std::vector firstWires, std::optional> secondWires); + bool operator<(const ConnectionComponent &rhs) const { + if (component < rhs.component) { + return true; + } else if (component == rhs.component) { + if (pin < rhs.pin) { + return true; + } + } + return false; + } + }; - bool isConnecting(ConnectionComponent first); - bool isConnecting(ConnectionComponent first, std::string bus); - bool isConnecting(ConnectionComponent first, std::string bus, ConnectionComponent second); - bool isConnecting(ConnectionComponent first, ConnectionComponent second); + class Connection { + ConnectionComponent first; + std::optional second; + std::string bus; + std::vector attributes; + + std::vector firstWires; + std::optional> secondWires; + public: + Connection(ConnectionComponent first, std::optional second, + std::string bus, std::vector attributes, + std::vector firstWires, std::optional> secondWires); + + bool isConnecting(ConnectionComponent first); + + bool isConnecting(ConnectionComponent first, std::string bus); + + bool isConnecting(ConnectionComponent first, std::string bus, ConnectionComponent second); + + bool isConnecting(ConnectionComponent first, ConnectionComponent second); - ConnectionComponent getComponent(); - std::optional getSecondComponent(); + ConnectionComponent getComponent(); - std::string getBus(); + std::optional getSecondComponent(); - std::vector getAttributes(); + std::string getBus(); - std::vector getWires(); - std::optional> getSecondWires(); + std::vector getAttributes(); - Attribute getAttribute(std::string name); - bool hasAttribute(std::string name); -}; + std::vector getWires(); + + std::optional> getSecondWires(); + + Attribute getAttribute(std::string name); + + bool hasAttribute(std::string name); + }; } // namespace domain diff --git a/comdel/domain/connection_instance.cpp b/comdel/domain/connection_instance.cpp new file mode 100644 index 0000000..56dbced --- /dev/null +++ b/comdel/domain/connection_instance.cpp @@ -0,0 +1,29 @@ +#include "connection_instance.h" + +namespace domain { + + + ConnectionInstance::ConnectionInstance(ComponentInstance *instance, std::vector attributes, + Connection connection) + : instance(instance), attributes(attributes), connection(connection) {} + + InstanceAttribute ConnectionInstance::getAttribute(string attribute) { + for (auto &attr: attributes) { + if (attr.name == attribute) { + return attr; + } + } + throw std::exception(); + } + + + BusConnectionInstance::BusConnectionInstance(ComponentInstance *instance, std::vector attributes, + BusInstance *bus, Connection connection) + : ConnectionInstance(instance, attributes, connection), bus(bus) {} + + DirectConnectionInstance::DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondInstance, + std::vector attributes, BusInstance *bus, + Connection connection) + : ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus) {} + +} // namespace domain diff --git a/comdel/domain/connection_instance.h b/comdel/domain/connection_instance.h new file mode 100644 index 0000000..e2f5e8d --- /dev/null +++ b/comdel/domain/connection_instance.h @@ -0,0 +1,49 @@ +#ifndef DOMAIN_CONNECTION_INSTANCE_H +#define DOMAIN_CONNECTION_INSTANCE_H + +#include "connection.h" +#include "instance.h" + +namespace domain { + + class ConnectionInstance { + public: + ComponentInstance *instance; + Connection connection; + + virtual ~ConnectionInstance() = default; + + std::vector attributes; + + std::pair start; + std::pair end; + + ConnectionInstance(ComponentInstance *instance, std::vector attributes, + Connection connection); + + InstanceAttribute getAttribute(string attribute); + }; + + + class BusConnectionInstance : public ConnectionInstance { + public: + BusInstance *bus; + + BusConnectionInstance(ComponentInstance *instance, std::vector attributes, BusInstance *bus, + Connection connection); + }; + + + class DirectConnectionInstance : public ConnectionInstance { + public: + BusInstance *bus; + ComponentInstance *secondInstance; + + DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, + std::vector attributes, BusInstance *bus, Connection connection); + }; + + +} // namespace domain + +#endif // DOMAIN_CONNECTIONINSTANCE_H diff --git a/comdel/domain/connectioninstance.cpp b/comdel/domain/connectioninstance.cpp deleted file mode 100644 index 46538f1..0000000 --- a/comdel/domain/connectioninstance.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "connectioninstance.h" - -namespace domain { - - -ConnectionInstance::ConnectionInstance(ComponentInstance *instance, std::vector attributes, Connection connection) - : instance(instance), attributes(attributes), connection(connection) -{} - -InstanceAttribute ConnectionInstance::getAttribute(string attribute) { - for(auto& attr: attributes) { - if(attr.name == attribute) { - return attr; - } - } - throw std::exception(); -} - - -BusConnectionInstance::BusConnectionInstance(ComponentInstance *instance, std::vector attributes, BusInstance *bus, Connection connection) - : ConnectionInstance(instance, attributes, connection), bus(bus) -{} - -DirectConnectionInstance::DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondInstance, std::vector attributes, BusInstance *bus, Connection connection) - : ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus) -{} - -} // namespace domain diff --git a/comdel/domain/connectioninstance.h b/comdel/domain/connectioninstance.h deleted file mode 100644 index e84b171..0000000 --- a/comdel/domain/connectioninstance.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef DOMAIN_CONNECTION_INSTANCE_H -#define DOMAIN_CONNECTION_INSTANCE_H - -#include "connection.h" -#include "instance.h" -#include "wireinstance.h" - -namespace domain { - -class ConnectionInstance -{ -public: - ComponentInstance *instance; - Connection connection; - - virtual ~ConnectionInstance() = default; - - std::vector attributes; - - std::pair start; - std::pair end; - - ConnectionInstance(ComponentInstance *instance, std::vector attributes, Connection connection); - - InstanceAttribute getAttribute(string attribute); -}; - - -class BusConnectionInstance: public ConnectionInstance -{ -public: - BusInstance *bus; - - BusConnectionInstance(ComponentInstance *instance, std::vector attributes, BusInstance *bus, Connection connection); -}; - - -class DirectConnectionInstance: public ConnectionInstance -{ -public: - BusInstance *bus; - ComponentInstance *secondInstance; - - DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, std::vector attributes, BusInstance *bus, Connection connection); -}; - - -} // namespace domain - -#endif // DOMAIN_CONNECTIONINSTANCE_H diff --git a/comdel/domain/display.cpp b/comdel/domain/display.cpp index 177e8f7..a5ee669 100644 --- a/comdel/domain/display.cpp +++ b/comdel/domain/display.cpp @@ -2,6 +2,172 @@ namespace domain { -Display::Display(std::vector items): items(items) {} + Display::Display(std::vector items) : items(items) {} + void Display::render(QGraphicsItemGroup *group) { + for (auto &item: items) { + item.render(group); + } + } + + void Display::comdel(std::ostream &buffer, int x, int y, int size) { + for (auto &item: items) { + item.comdel(buffer, x, y, size); + } + } + + void ui::Rect::render(QGraphicsItemGroup *group) { + group->addToGroup(new QGraphicsRectItem(x, y, w, h)); + } + + void ui::Rect::comdel(std::ostream &buffer, int x, int y) { + buffer << "\t\trectangle {\n"; + buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; + buffer << "\t\t\tw: " << w << "; h: " << h << ";\n"; + buffer << "\t\t}\n\n"; + } + + void ui::Line::render(QGraphicsItemGroup *group) { + group->addToGroup(new QGraphicsLineItem(x1, y1, x2, y2)); + } + + void ui::Line::comdel(std::ostream &buffer, int x, int y) { + buffer << "\t\tline {\n"; + buffer << "\t\t\tx1: " << (x1 + x) << "; y1: " << (y1 + y) << ";\n"; + buffer << "\t\t\tx2: " << (x2 + x) << "; y2: " << (y2 + y) << ";\n"; + buffer << "\t\t}\n\n"; + } + + void ui::Bus::render(QGraphicsItemGroup *group, int size) { + if (orientation == HORIZONTAL) { + group->addToGroup(new QGraphicsRectItem(x, y, size, h)); + } else { + group->addToGroup(new QGraphicsRectItem(x, y, w, size)); + } + } + + int ui::Bus::getDefaultSize() { + if (orientation == HORIZONTAL) { + return w; + } else { + return h; + } + } + + void ui::Bus::comdel(std::ostream &buffer, int x, int y, int size) { + buffer << "\t\trectangle {\n"; + buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; + if (orientation == HORIZONTAL) { + buffer << "\t\t\tw: " << size << "; h: " << h << ";\n"; + } else { + buffer << "\t\t\tw: " << w << "; h: " << size << ";\n"; + } + buffer << "\t\t}\n\n"; + } + + void ui::Pin::renderIn(QGraphicsItemGroup *group) { + QPolygon polygon; + + switch (orientation) { + case PinOrientation::TOP: + polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w, y + h) << QPoint(x + w, y) + << QPoint(x + w / 2, y + h / 2); + break; + case PinOrientation::BOTTOM: + polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w / 2, y + h / 2) + << QPoint(x + w, y + h) << QPoint(x + w, y); + break; + case PinOrientation::LEFT: + polygon << QPoint(x, y) << QPoint(x + w / 2, y + h / 2) << QPoint(x, y + h) + << QPoint(x + w, y + h) << QPoint(x + w, y); + break; + case PinOrientation::RIGHT: + polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w, y + h) + << QPoint(x + w / 2, y + h / 2) << QPoint(x + w, y); + break; + } + group->addToGroup(new QGraphicsPolygonItem(polygon)); + } + + void ui::Pin::renderOut(QGraphicsItemGroup *group) { + QPolygon polygon; + + switch (orientation) { + case PinOrientation::TOP: + polygon << QPoint(x, y + h / 2) << QPoint(x, y + h) << QPoint(x + w, y + h) + << QPoint(x + w, y + h / 2) << QPoint(x + w / 2, y); + break; + case PinOrientation::BOTTOM: + polygon << QPoint(x, y) << QPoint(x, y + h / 2) << QPoint(x + w / 2, y + h) + << QPoint(x + w, y + h / 2) << QPoint(x + w, y); + break; + case PinOrientation::LEFT: + polygon << QPoint(x + w, y) << QPoint(x + w / 2, y) << QPoint(x, y + h / 2) + << QPoint(x + w / 2, y + h) << QPoint(x + w, y + w); + break; + case PinOrientation::RIGHT: + polygon << QPoint(x, y) << QPoint(x, y + h) << QPoint(x + w / 2, y + h) + << QPoint(x + w, y + h / 2) << QPoint(x + w / 2, y); + break; + } + group->addToGroup(new QGraphicsPolygonItem(polygon)); + } + + void ui::Pin::renderInOut(QGraphicsItemGroup *group) { + group->addToGroup(new QGraphicsRectItem(x, y, w, h)); + } + + void ui::Pin::render(QGraphicsItemGroup *group) { + switch (pinType) { + case PinType::IN: + renderIn(group); + break; + case PinType::OUT: + renderOut(group); + break; + case PinType::IN_OUT: + renderInOut(group); + break; + } + } + + int ui::Pin::getConnectionX() { + switch (orientation) { + case ui::PinOrientation::TOP: + case ui::PinOrientation::BOTTOM: + return x + w / 2; + case ui::PinOrientation::LEFT: + return x; + case ui::PinOrientation::RIGHT: + return x + w; + } + return 0; + } + + int ui::Pin::getConnectionY() { + switch (orientation) { + case ui::PinOrientation::LEFT: + case ui::PinOrientation::RIGHT: + return y + h / 2; + case ui::PinOrientation::TOP: + return y; + case ui::PinOrientation::BOTTOM: + return y + h; + } + return 0; + } + + void ui::Item::render(QGraphicsItemGroup *group, int size) { + if (rect) rect->render(group); + if (line) line->render(group); + if (pin) pin->render(group); + if (bus) bus->render(group, size); + } + + void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) { + if (rect) rect->comdel(buffer, x, y); + if (line) line->comdel(buffer, x, y); + // pins aren't exported + if (bus) bus->comdel(buffer, x, y, size); + } } // namespace domain diff --git a/comdel/domain/display.h b/comdel/domain/display.h index ed87bee..38334aa 100644 --- a/comdel/domain/display.h +++ b/comdel/domain/display.h @@ -8,237 +8,109 @@ namespace domain { -namespace ui { + namespace ui { -class Rect { -public: - int x, y, w, h; + class Rect { + public: + int x, y, w, h; - Rect(int x, int y, int w, int h): x(x), y(y), w(w), h(h) {} + Rect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {} + + void render(QGraphicsItemGroup *group); + + void comdel(std::ostream &buffer, int x, int y); + + }; + + class Line { + public: + int x1, y1, x2, y2; + + Line(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {} + + void render(QGraphicsItemGroup *group); + + void comdel(std::ostream &buffer, int x, int y); + }; + + enum PinType { + IN, OUT, IN_OUT + }; + enum PinOrientation { + LEFT, RIGHT, TOP, BOTTOM + }; + enum BusOrientation { + VERTICAL, HORIZONTAL + }; + + class Bus { + public: + int x, y, w, h; + BusOrientation orientation; + + Bus(int x, int y, int w, int h, BusOrientation orientation) : x(x), y(y), w(w), h(h), + orientation(orientation) {} + + void render(QGraphicsItemGroup *group, int size); + + int getDefaultSize(); + + void comdel(std::ostream &buffer, int x, int y, int size); + + }; + + class Pin { + public: + PinOrientation orientation; + PinType pinType; + int x, y, w, h; + + Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType) : x(x), y(y), w(w), h(h), + orientation(orientation), + pinType(pinType) {} + + public: + void render(QGraphicsItemGroup *group); + + int getConnectionX(); + int getConnectionY(); + + private: + void renderIn(QGraphicsItemGroup *group); + void renderOut(QGraphicsItemGroup *group); + void renderInOut(QGraphicsItemGroup *group); + }; + + + class Item { + public: + Item() : rect(std::nullopt), line(std::nullopt), pin(std::nullopt), bus(std::nullopt) {} + + std::optional rect = std::nullopt; + std::optional line = std::nullopt; + std::optional pin = std::nullopt; + std::optional bus = std::nullopt; + + void render(QGraphicsItemGroup *group, int size = 0); + void comdel(std::ostream &buffer, int x, int y, int size = 0); + }; - void render(QGraphicsItemGroup *group) { - group->addToGroup(new QGraphicsRectItem(x,y,w,h)); } - void comdel(std::ostream &buffer, int x, int y) { - buffer << "\t\trectangle {\n"; - buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; - buffer << "\t\t\tw: " << w << "; h: " << h << ";\n"; - buffer << "\t\t}\n\n"; - } + class Display { + public: -}; + Display(std::vector items); -class Line { -public: - int x1, y1, x2, y2; + void render(QGraphicsItemGroup *group); - Line(int x1, int y1, int x2, int y2): x1(x1), y1(y1), x2(x2), y2(y2) {} + void comdel(std::ostream &buffer, int x, int y, int size = 0); - void render(QGraphicsItemGroup *group) { - group->addToGroup(new QGraphicsLineItem(x1, y1, x2, y2)); - } + std::vector &getItems() { return items; } - void comdel(std::ostream &buffer, int x, int y) { - buffer << "\t\tline {\n"; - buffer << "\t\t\tx1: " << (x1 + x) << "; y1: " << (y1 + y) << ";\n"; - buffer << "\t\t\tx2: " << (x2 + x) << "; y2: " << (y2 + y) << ";\n"; - buffer << "\t\t}\n\n"; - } -}; - -enum PinOrientation { - LEFT, RIGHT, TOP, BOTTOM -}; -enum BusOrientation { - VERTICAL, HORIZONTAL -}; - -enum PinType { - IN, OUT, IN_OUT -}; - - -class Bus { -public: - int x, y, w, h; - BusOrientation orientation; - - Bus(int x, int y, int w, int h, BusOrientation orientation): x(x), y(y), w(w), h(h), orientation(orientation) {} - - void render(QGraphicsItemGroup *group, int size) { - if(orientation == HORIZONTAL) { - group->addToGroup(new QGraphicsRectItem(x,y,size, h)); - } else { - group->addToGroup(new QGraphicsRectItem(x,y,w,size)); - } - } - - int getDefaultSize() { - if(orientation == HORIZONTAL) { - return w; - } else { - return h; - } - } - - void comdel(std::ostream &buffer, int x, int y, int size) { - buffer << "\t\trectangle {\n"; - buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; - if(orientation == HORIZONTAL) { - buffer << "\t\t\tw: " << size << "; h: " << h << ";\n"; - } else { - buffer << "\t\t\tw: " << w << "; h: " << size << ";\n"; - } - buffer << "\t\t}\n\n"; - } - -}; - - -class Pin { -public: - PinOrientation orientation; - PinType pinType; - int x, y, w, h; - - Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType): x(x), y(y), w(w), h(h), orientation(orientation), pinType(pinType) {} - - void renderIn(QGraphicsItemGroup *group) { - QPolygon polygon; - - switch (orientation) { - case PinOrientation::TOP: - polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w, y) << QPoint(x+w/2, y+h/2); - break; - case PinOrientation::BOTTOM: - polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w/2, y+h/2) << QPoint(x+w, y+h) << QPoint(x+w, y); - break; - case PinOrientation::LEFT: - polygon << QPoint(x, y) << QPoint(x+w/2, y+h/2) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w, y); - break; - case PinOrientation::RIGHT: - polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w/2, y+h/2) << QPoint(x+w, y); - break; - } - group->addToGroup(new QGraphicsPolygonItem(polygon)); - } - - void renderOut(QGraphicsItemGroup *group) { - QPolygon polygon; - - switch (orientation) { - case PinOrientation::TOP: - polygon << QPoint(x, y+h/2) << QPoint(x, y+h) << QPoint(x+w, y+h) << QPoint(x+w, y+h/2) << QPoint(x+w/2, y); - break; - case PinOrientation::BOTTOM: - polygon << QPoint(x, y) << QPoint(x, y+h/2) << QPoint(x+w/2, y+h) << QPoint(x+w, y+h/2) << QPoint(x+w, y); - break; - case PinOrientation::LEFT: - polygon << QPoint(x+w, y) << QPoint(x+w/2, y) << QPoint(x, y+h/2) << QPoint(x+w/2, y+h) << QPoint(x+w, y+w); - break; - case PinOrientation::RIGHT: - polygon << QPoint(x, y) << QPoint(x, y+h) << QPoint(x+w/2, y+h) << QPoint(x+w, y+h/2) << QPoint(x+w/2, y); - break; - } - group->addToGroup(new QGraphicsPolygonItem(polygon)); - } - - void renderInOut(QGraphicsItemGroup *group) { - group->addToGroup(new QGraphicsRectItem(x, y ,w, h)); - } - - void render(QGraphicsItemGroup *group) { - switch (pinType) { - case PinType::IN: - renderIn(group); - break; - case PinType::OUT: - renderOut(group); - break; - case PinType::IN_OUT: - renderInOut(group); - break; - } - } - - int getConnectionX() { - switch (orientation) { - case ui::PinOrientation::TOP: - case ui::PinOrientation::BOTTOM: - return x+w/2; - case ui::PinOrientation::LEFT: - return x; - case ui::PinOrientation::RIGHT: - return x+w; - } - return 0; - } - - int getConnectionY() { - switch (orientation) { - case ui::PinOrientation::LEFT: - case ui::PinOrientation::RIGHT: - return y+h/2; - case ui::PinOrientation::TOP: - return y; - case ui::PinOrientation::BOTTOM: - return y+h; - } - return 0; - } -}; - - -class Item { -public: - Item(): rect(std::nullopt), line(std::nullopt), pin(std::nullopt), bus(std::nullopt) {} - - void render(QGraphicsItemGroup *group, int size = 0) { - if(rect) rect->render(group); - if(line) line->render(group); - if(pin) pin->render(group); - if(bus) bus->render(group, size); - } - - std::optional rect = std::nullopt; - std::optional line = std::nullopt; - std::optional pin = std::nullopt; - std::optional bus = std::nullopt; - - void comdel(std::ostream &buffer, int x, int y, int size = 0) { - if(rect) rect->comdel(buffer, x, y); - if(line) line->comdel(buffer, x, y); - // pins aren't exported - if(bus) bus->comdel(buffer, x, y, size); - } -}; - -} - -class Display -{ -public: - - Display(std::vector items); - - void render(QGraphicsItemGroup *group) { - for(auto &item: items) { - item.render(group); - } - } - - void comdel(std::ostream &buffer, int x, int y, int size = 0) { - for(auto &item: items) { - item.comdel(buffer, x, y, size); - } - } - - std::vector& getItems() {return items;} - -private: - std::vector items; -}; + private: + std::vector items; + }; } // namespace domain diff --git a/comdel/domain/function_signature.cpp b/comdel/domain/function_signature.cpp new file mode 100644 index 0000000..a5577be --- /dev/null +++ b/comdel/domain/function_signature.cpp @@ -0,0 +1,166 @@ +#include +#include +#include "function_signature.h" + +namespace domain { + + class DivisibleValidator : public FunctionValidator { + public: + DivisibleValidator() : FunctionValidator("divisible", {Value::INT, Value::INT}) {} + + bool validate(std::vector values) override { + if (validateSignature(values)) { + long long first = values[0].asInt(); + long long second = values[1].asInt(); + return (first % second) == 0; + } + return false; + } + + void clear() override {} + }; + + class LessThenValidator : public FunctionValidator { + public: + LessThenValidator() : FunctionValidator("less_then", {Value::INT, Value::INT}) {} + + bool validate(std::vector values) override { + if (validateSignature(values)) { + long long first = values[0].asInt(); + long long second = values[1].asInt(); + return first < second; + } + return false; + } + + void clear() override {} + }; + + class GreaterThenValidator : public FunctionValidator { + public: + GreaterThenValidator() : FunctionValidator("greater_then", {Value::INT, Value::INT}) {} + + bool validate(std::vector values) override { + if (validateSignature(values)) { + long long first = values[0].asInt(); + long long second = values[1].asInt(); + return first > second; + } + return false; + } + + void clear() override {} + }; + + + class ContainsAddressValidator : public FunctionValidator { + public: + ContainsAddressValidator() : FunctionValidator("contains_address", {Value::ADDRESS_SPACE, Value::INT}) {} + + bool validate(std::vector values) override { + if (validateSignature(values)) { + AddressSpace space = values[0].asAddressSpace(); + long long address = values[1].asInt(); + return space.contains(address); + } + return false; + } + + void clear() override {} + }; + + + class ContainsValidator : public FunctionValidator { + public: + ContainsValidator() : FunctionValidator("contains", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {} + + bool validate(std::vector values) override { + if (validateSignature(values)) { + AddressSpace space = values[0].asAddressSpace(); + long long start = values[1].asInt(); + long long size = values[1].asInt(); + return space.contains(start, start + size); + } + return false; + } + + void clear() override {} + }; + + + class UniqueValidator : public FunctionValidator { + + private: + std::map>> spaces; + + bool overlaps(long long int start1, long long int end1, long long int start2, long long int end2) { + return std::max((long long int) 0, std::min(end1, end2) - std::max(start1, start2)) > 0; + } + + public: + UniqueValidator() : FunctionValidator("unique", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {} + + bool validate(std::vector values) override { + if (validateSignature(values)) { + std::string space = values[0].asAddressSpace().getName(); + long long int start = values[1].asInt(); + long long int end = start + values[2].asInt(); + if (spaces.count(space) == 0) { + spaces.insert(std::make_pair(space, std::vector>{})); + } + for (auto &s: spaces[space]) { + if (overlaps(s.first, s.second, start, end)) { + return false; + } + } + spaces[space].push_back(std::make_pair(start, end)); + return true; + } + return false; + } + + void clear() override { + spaces.clear(); + } + }; + + + std::vector getSupportedValidators() { + std::vector validators; + + validators.push_back(new DivisibleValidator()); + validators.push_back(new LessThenValidator()); + validators.push_back(new GreaterThenValidator()); + validators.push_back(new ContainsAddressValidator()); + validators.push_back(new ContainsValidator()); + validators.push_back(new UniqueValidator()); + + return validators; + } + + + FunctionValidator::FunctionValidator(std::string name, std::vector signature) + : name(std::move(name)), signature(std::move(signature)) {} + + std::string FunctionValidator::getName() { + return name; + } + + std::vector FunctionValidator::getSignature() { + return signature; + } + + bool FunctionValidator::validateSignature(std::vector _signature) { + if (this->signature.size() != _signature.size()) { + return false; + } + + for (int i = 0; i < this->signature.size(); i++) { + if (this->signature[i] != _signature[i].getType()) { + return false; + } + } + return true; + } + +} // namespace domain diff --git a/comdel/domain/function_signature.h b/comdel/domain/function_signature.h new file mode 100644 index 0000000..43f56b5 --- /dev/null +++ b/comdel/domain/function_signature.h @@ -0,0 +1,36 @@ +#ifndef DOMAIN_FUNCTION_VALIDATOR_H +#define DOMAIN_FUNCTION_VALIDATOR_H + +#include +#include + +#include "value.h" + +namespace domain { + + class FunctionValidator { + private: + std::string name; + std::vector signature; + + protected: + FunctionValidator(std::string name, std::vector signature); + + public: + + std::string getName(); + + std::vector getSignature(); + + bool validateSignature(std::vector signature); + + virtual bool validate(std::vector values) = 0; + + virtual void clear() = 0; + }; + + std::vector getSupportedValidators(); + +} // namespace domain + +#endif // DOMAIN_FUNCTION_VALIDATOR_H diff --git a/comdel/domain/functionsignature.cpp b/comdel/domain/functionsignature.cpp deleted file mode 100644 index 575cfae..0000000 --- a/comdel/domain/functionsignature.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include "functionsignature.h" - -namespace domain { - -class DivisibleValidator: public FunctionValidator { -public: - DivisibleValidator(): FunctionValidator("divisible", {Value::INT, Value::INT}) {} - - bool validate(std::vector values) override { - if(validateSignature(values)) { - long long first = values[0].asInt(); - long long second = values[1].asInt(); - return (first % second) == 0; - } - return false; - } - void clear() override {} -}; - -class LessThenValidator: public FunctionValidator { -public: - LessThenValidator(): FunctionValidator("less_then", {Value::INT, Value::INT}) {} - - bool validate(std::vector values) override { - if(validateSignature(values)) { - long long first = values[0].asInt(); - long long second = values[1].asInt(); - return first < second; - } - return false; - } - void clear() override {} -}; - -class GreaterThenValidator: public FunctionValidator { -public: - GreaterThenValidator(): FunctionValidator("greater_then", {Value::INT, Value::INT}) {} - - bool validate(std::vector values) override { - if(validateSignature(values)) { - long long first = values[0].asInt(); - long long second = values[1].asInt(); - return first > second; - } - return false; - } - void clear() override {} -}; - - -class ContainsAddressValidator: public FunctionValidator { -public: - ContainsAddressValidator(): FunctionValidator("contains_address", {Value::ADDRESS_SPACE, Value::INT}) {} - - bool validate(std::vector values) override { - if(validateSignature(values)) { - AddressSpace space = values[0].asAddressSpace(); - long long address = values[1].asInt(); - return space.contains(address); - } - return false; - } - void clear() override {} -}; - - -class ContainsValidator: public FunctionValidator { -public: - ContainsValidator(): FunctionValidator("contains", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {} - - bool validate(std::vector values) override { - if(validateSignature(values)) { - AddressSpace space = values[0].asAddressSpace(); - long long start = values[1].asInt(); - long long size = values[1].asInt(); - return space.contains(start, start + size); - } - return false; - } - void clear() override {} -}; - - - - -class UniqueValidator: public FunctionValidator { - -private: - std::map>> spaces; - - bool overlaps(long long int start1, long long int end1, long long int start2, long long int end2) { - return std::max((long long int)0, std::min(end1, end2) - std::max(start1, start2)) > 0; - } - -public: - UniqueValidator(): FunctionValidator("unique", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {} - - bool validate(std::vector values) override { - if(validateSignature(values)) { - std::string space = values[0].asAddressSpace().getName(); - long long int start = values[1].asInt(); - long long int end = start + values[2].asInt(); - if(spaces.count(space) == 0) { - spaces.insert(std::make_pair(space, std::vector>{})); - } - for(auto& s: spaces[space]) { - if(overlaps(s.first, s.second, start, end)) { - return false; - } - } - spaces[space].push_back(std::make_pair(start, end)); - return true; - } - return false; - } - void clear() override { - spaces.clear(); - } -}; - - -std::vector getSupportedValidators() { - std::vector validators; - - validators.push_back(new DivisibleValidator()); - validators.push_back(new LessThenValidator()); - validators.push_back(new GreaterThenValidator()); - validators.push_back(new ContainsAddressValidator()); - validators.push_back(new ContainsValidator()); - validators.push_back(new UniqueValidator()); - - return validators; -} - - - -} // namespace domain diff --git a/comdel/domain/functionsignature.h b/comdel/domain/functionsignature.h deleted file mode 100644 index 961628d..0000000 --- a/comdel/domain/functionsignature.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef DOMAIN_FUNCTION_VALIDATOR_H -#define DOMAIN_FUNCTION_VALIDATOR_H - -#include -#include - -#include "value.h" - -namespace domain { - -class FunctionValidator { -private: - std::string name; - std::vector signature; - -protected: - FunctionValidator(std::string name, std::vector signature) { - this->name = name; - this->signature = signature; - } - -public: - - std::string getName() { - return name; - } - - std::vector getSignature() { - return signature; - } - - bool validateSignature(std::vector signature) { - if(this->signature.size() != signature.size()) { - return false; - } - - for(int i=0; isignature.size(); i++) { - if(this->signature[i] != signature[i].getType()) { - return false; - } - } - return true; - } - - virtual bool validate(std::vector values) = 0; - virtual void clear() = 0; -}; - -std::vector getSupportedValidators(); - -} // namespace domain - -#endif // DOMAIN_FUNCTION_VALIDATOR_H diff --git a/comdel/domain/instance.cpp b/comdel/domain/instance.cpp index 77143da..bd13747 100644 --- a/comdel/domain/instance.cpp +++ b/comdel/domain/instance.cpp @@ -2,19 +2,18 @@ namespace domain { -BusInstance::BusInstance(std::string name, std::pair position, Bus bus, int size) - : name(name), position(position), bus(bus), size(size) -{ - if(size < 0 && bus.getDisplayBus().has_value()) { - this->size = bus.getDisplayBus()->getDefaultSize(); + BusInstance::BusInstance(std::string name, std::pair position, Bus bus, int size) + : name(name), position(position), bus(bus), size(size) { + if (size < 0 && bus.getDisplayBus().has_value()) { + this->size = bus.getDisplayBus()->getDefaultSize(); + } } -} - BusInstance::BusInstance(std::string name, Bus bus): name(name), bus(bus), position(0,0), size(0) {} + BusInstance::BusInstance(std::string name, Bus bus) : name(name), bus(bus), position(0, 0), size(0) {} - ComponentInstance::ComponentInstance(std::string name, std::vector attributes, std::pair position, Component component) - : name(name), attributes(std::move(attributes)), position(position), component(component) -{} + ComponentInstance::ComponentInstance(std::string name, std::vector attributes, + std::pair position, Component component) + : name(name), attributes(std::move(attributes)), position(position), component(component) {} } // namespace domain diff --git a/comdel/domain/instance.h b/comdel/domain/instance.h index 99428a0..57e6235 100644 --- a/comdel/domain/instance.h +++ b/comdel/domain/instance.h @@ -3,44 +3,41 @@ #include "bus.h" #include "component.h" -#include "instanceattribute.h" +#include "instance_attribute.h" #include #include - namespace domain { -class BusInstance -{ -public: - std::string name; - std::pair position; + class BusInstance { + public: + std::string name; + std::pair position; - Bus bus; - int size; + Bus bus; + int size; - BusInstance(std::string name, Bus bus); + BusInstance(std::string name, Bus bus); - BusInstance(std::string name, std::pair position, Bus bus, int size = -1); + BusInstance(std::string name, std::pair position, Bus bus, int size = -1); - virtual ~BusInstance() = default; -}; + virtual ~BusInstance() = default; + }; -class ComponentInstance -{ -public: - std::string name; - std::vector attributes; - std::pair position; + class ComponentInstance { + public: + std::string name; + std::vector attributes; + std::pair position; - Component component; + Component component; - ComponentInstance(std::string name, std::vector attributes, std::pair position, Component component); + ComponentInstance(std::string name, std::vector attributes, std::pair position, Component component); - virtual ~ComponentInstance() = default; -}; + virtual ~ComponentInstance() = default; + }; } // namespace domain diff --git a/comdel/domain/instance_attribute.cpp b/comdel/domain/instance_attribute.cpp new file mode 100644 index 0000000..028670a --- /dev/null +++ b/comdel/domain/instance_attribute.cpp @@ -0,0 +1,8 @@ +#include "instance_attribute.h" + +namespace domain { + + InstanceAttribute::InstanceAttribute(std::string name, Value value, Attribute attribute) + : name(name), value(value), attribute(attribute) {} + +} // namespace domain diff --git a/comdel/domain/instance_attribute.h b/comdel/domain/instance_attribute.h new file mode 100644 index 0000000..f9c0a57 --- /dev/null +++ b/comdel/domain/instance_attribute.h @@ -0,0 +1,25 @@ +#ifndef DOMAIN_INSTANCE_ATTRIBUTE_H +#define DOMAIN_INSTANCE_ATTRIBUTE_H + +#include "attribute.h" +#include "value.h" + +#include + + +namespace domain { + + class InstanceAttribute { + public: + InstanceAttribute(std::string name, Value value, Attribute attribute); + + std::string name; + Value value; + Attribute attribute; + + ~InstanceAttribute() = default; + }; + +} // namespace domain + +#endif // DOMAIN_INSTANCE_ATTRIBUTE_H diff --git a/comdel/domain/instanceattribute.cpp b/comdel/domain/instanceattribute.cpp deleted file mode 100644 index 4eba83d..0000000 --- a/comdel/domain/instanceattribute.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "instanceattribute.h" - -namespace domain { - -InstanceAttribute::InstanceAttribute(std::string name, Value value, Attribute attribute) - : name(name), value(value), attribute(attribute) -{} - -} // namespace domain diff --git a/comdel/domain/instanceattribute.h b/comdel/domain/instanceattribute.h deleted file mode 100644 index d66bdc4..0000000 --- a/comdel/domain/instanceattribute.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef DOMAIN_INSTANCE_ATTRIBUTE_H -#define DOMAIN_INSTANCE_ATTRIBUTE_H - -#include "attribute.h" -#include "value.h" - -#include - - - -namespace domain { - -class InstanceAttribute -{ -public: - InstanceAttribute(std::string name, Value value, Attribute attribute); - - std::string name = ""; - Value value; - Attribute attribute; - - ~InstanceAttribute() = default; -}; - -} // namespace domain - -#endif // DOMAIN_INSTANCE_ATTRIBUTE_H diff --git a/comdel/domain/library.cpp b/comdel/domain/library.cpp index e36d33e..1b6f19e 100644 --- a/comdel/domain/library.cpp +++ b/comdel/domain/library.cpp @@ -2,116 +2,131 @@ namespace domain { -Library::Library(string name, string libraryInfo, string header, string componentDirectory, std::optional componentHeader, - vector addressSpaces, vector components, vector buses, vector connections, map messages) - : name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory), componentHeader(componentHeader), addressSpaces(addressSpaces), - components(components), buses(buses), connections(connections), messages(messages) -{} + Library::Library(string name, string libraryInfo, string header, string componentDirectory, + std::optional componentHeader, + vector addressSpaces, vector components, vector buses, + vector connections, map messages) + : name(name), libraryInfo(libraryInfo), header(header), componentDirectory(componentDirectory), + componentHeader(componentHeader), addressSpaces(addressSpaces), + components(components), buses(buses), connections(connections), messages(messages) {} -std::string Library::getName() { - return name; -} -std::string Library::getLibraryInfo() { - return libraryInfo; -} -std::string Library::getHeader() { - return header; -} -std::string Library::getComponentDirectory() { - return componentDirectory; -} -std::optional Library::getComponentHeader() { - return componentHeader; -} - -std::vector Library::getAddressSpaces() { - return addressSpaces; -} -std::vector Library::getComponents() { - return components; -} -std::vector Library::getBuses() { - return buses; -} -std::vector Library::getConnections() { - return connections; -} - -std::map Library::getMessages() { - return messages; -} - -bool Library::hasComponent(std::string name) { - for(uint i=0; i Library::getComponentHeader() { + return componentHeader; + } + + std::vector Library::getAddressSpaces() { + return addressSpaces; + } + + std::vector Library::getComponents() { + return components; + } + + std::vector Library::getBuses() { + return buses; + } + + std::vector Library::getConnections() { + return connections; + } + + std::map Library::getMessages() { + return messages; + } + + bool Library::hasComponent(std::string name) { + for (uint i = 0; i < components.size(); i++) { + if (components[i].getName() == name) { + return true; + } + } + return false; + } + + bool Library::hasBus(std::string name) { + for (uint i = 0; i < buses.size(); i++) { + if (buses[i].getName() == name) { + return true; + } + } + return false; } - return false; -} -AddressSpace &Library::getAddressSpace(std::string addressSpace) { - for(uint i=0; i Library::getConnection(ConnectionComponent component, std::string bus) { - for(uint i=0; i Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { - for(uint i=0; i Library::getConnection(ConnectionComponent component, std::string bus) { + for (uint i = 0; i < connections.size(); i++) { + if (connections[i].isConnecting(component, bus)) { + return connections[i]; + } + } + return nullopt; + } + + bool Library::hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { + return getConnection(component, bus, secondComponent).has_value(); + } + + std::optional + Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { + for (uint i = 0; i < connections.size(); i++) { + if (connections[i].isConnecting(component, bus, secondComponent)) { + return connections[i]; + } + } + return nullopt; + } + + std::string Library::getMessage(std::string key) { + return messages[key]; + } bool Library::hasConnection(ConnectionComponent component, ConnectionComponent secondComponent) { return getConnection(component, secondComponent).has_value(); @@ -119,8 +134,8 @@ std::string Library::getMessage(std::string key) { std::optional Library::getConnection(ConnectionComponent component, ConnectionComponent secondComponent) { - for(auto & connection : connections) { - if(connection.isConnecting(component, secondComponent)) { + for (auto &connection: connections) { + if (connection.isConnecting(component, secondComponent)) { return connection; } } diff --git a/comdel/domain/library.h b/comdel/domain/library.h index 921d278..9e3990e 100644 --- a/comdel/domain/library.h +++ b/comdel/domain/library.h @@ -1,7 +1,7 @@ #ifndef DOMAIN_LIBRARY_H #define DOMAIN_LIBRARY_H -#include "addressspace.h" +#include "address_space.h" #include "bus.h" #include "component.h" #include "connection.h" @@ -10,61 +10,75 @@ #include - namespace domain { -using namespace std; + using namespace std; -class Library -{ - std::string name; - std::string libraryInfo; - std::string header; - std::string componentDirectory; - std::optional componentHeader; + class Library { + std::string name; + std::string libraryInfo; + std::string header; + std::string componentDirectory; + std::optional componentHeader; - std::vector addressSpaces; - std::vector components; - std::vector buses; - std::vector connections; + std::vector addressSpaces; + std::vector components; + std::vector buses; + std::vector connections; - std::map messages; + std::map messages; -public: - Library(string name, string libraryInfo, string header, string componentDirectory, std::optional componentHeader, - vector addressSpaces, vector components, vector buses, vector connection, map messages); + public: + Library(string name, string libraryInfo, string header, string componentDirectory, + std::optional componentHeader, + vector addressSpaces, vector components, vector buses, + vector connection, map messages); - std::string getName(); - std::string getLibraryInfo(); - std::string getHeader(); - std::string getComponentDirectory(); - std::optional getComponentHeader(); + std::string getName(); - std::vector getAddressSpaces(); - std::vector getComponents(); - std::vector getBuses(); - std::vector getConnections(); + std::string getLibraryInfo(); - bool hasComponent(std::string name); - bool hasBus(std::string name); + std::string getHeader(); - std::map getMessages(); + std::string getComponentDirectory(); - AddressSpace &getAddressSpace(std::string name); - Component &getComponent(std::string name); - Bus &getBus(std::string bus); - std::string getMessage(std::string key); + std::optional getComponentHeader(); - bool hasConnection(ConnectionComponent component, std::string bus); - std::optional getConnection(ConnectionComponent component, std::string bus); + std::vector getAddressSpaces(); - bool hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent); - std::optional getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent); + std::vector getComponents(); - bool hasConnection(ConnectionComponent component, ConnectionComponent secondComponent); - std::optional getConnection(ConnectionComponent component, ConnectionComponent secondComponent); + std::vector getBuses(); -}; + std::vector getConnections(); + + bool hasComponent(std::string name); + + bool hasBus(std::string name); + + std::map getMessages(); + + AddressSpace &getAddressSpace(std::string name); + + Component &getComponent(std::string name); + + Bus &getBus(std::string bus); + + std::string getMessage(std::string key); + + bool hasConnection(ConnectionComponent component, std::string bus); + + std::optional getConnection(ConnectionComponent component, std::string bus); + + bool hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent); + + std::optional getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent); + + bool hasConnection(ConnectionComponent component, ConnectionComponent secondComponent); + + std::optional getConnection(ConnectionComponent component, ConnectionComponent secondComponent); + + }; } // namespace domain diff --git a/comdel/domain/pin.cpp b/comdel/domain/pin.cpp index c6ede24..37ec0d8 100644 --- a/comdel/domain/pin.cpp +++ b/comdel/domain/pin.cpp @@ -2,40 +2,45 @@ namespace domain { -PinConnection::PinConnection(std::string message, ConnectionType type) - : message(message), type(type) -{} + PinConnection::PinConnection(std::string message, ConnectionType type) + : message(message), type(type) {} -PinConnection::ConnectionType PinConnection::getType() { - return type; -} -std::string PinConnection::getMessage() { - return message; -} + PinConnection::ConnectionType PinConnection::getType() { + return type; + } + + std::string PinConnection::getMessage() { + return message; + } -Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, std::optional> wires) - : name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) -{} + Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, + std::optional> wires) + : name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) {} -std::string &Pin::getName() { - return name; -} -Pin::PinType Pin::getType() { - return type; -} -std::string Pin::getTooltip() { - return tooltip; -} -ui::Pin &Pin::getDisplayPin() { - return displayPin; -} -PinConnection &Pin::getConnection() { - return connection; -} -std::optional> &Pin::getWires() { - return wires; -} + std::string &Pin::getName() { + return name; + } + + Pin::PinType Pin::getType() { + return type; + } + + std::string Pin::getTooltip() { + return tooltip; + } + + ui::Pin &Pin::getDisplayPin() { + return displayPin; + } + + PinConnection &Pin::getConnection() { + return connection; + } + + std::optional> &Pin::getWires() { + return wires; + } } // namespace domain diff --git a/comdel/domain/pin.h b/comdel/domain/pin.h index 87dbe33..e39f1f6 100644 --- a/comdel/domain/pin.h +++ b/comdel/domain/pin.h @@ -7,57 +7,61 @@ #include - namespace domain { -class PinConnection -{ -public: - enum ConnectionType { - REQUIRED, - OPTIONAL + class PinConnection { + public: + enum ConnectionType { + REQUIRED, + OPTIONAL + }; + + private: + std::string message; + ConnectionType type; + + public: + PinConnection(std::string message, ConnectionType type); + + ConnectionType getType(); + + std::string getMessage(); }; -private: - std::string message; - ConnectionType type; + class Pin { + public: + enum PinType { + IN_OUT, + IN, + OUT + }; -public: - PinConnection(std::string message, ConnectionType type); + private: + std::string name; + PinType type; + std::string tooltip; + PinConnection connection; + domain::ui::Pin displayPin; - ConnectionType getType(); - std::string getMessage(); -}; + std::optional> wires; -class Pin -{ -public: - enum PinType { - IN_OUT, - IN, - OUT + public: + Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, + std::optional> wires); + + std::string &getName(); + + PinType getType(); + + std::string getTooltip(); + + ui::Pin &getDisplayPin(); + + PinConnection &getConnection(); + + std::optional> &getWires(); }; -private: - std::string name; - PinType type; - std::string tooltip; - PinConnection connection; - domain::ui::Pin displayPin; - - std::optional> wires; - -public: - Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, std::optional> wires); - - std::string &getName(); - PinType getType(); - std::string getTooltip(); - ui::Pin &getDisplayPin(); - PinConnection &getConnection(); - std::optional> &getWires(); -}; - } // namespace domain #endif // DOMAIN_PIN_H diff --git a/comdel/domain/rule.cpp b/comdel/domain/rule.cpp index 9619235..5c2e8b3 100644 --- a/comdel/domain/rule.cpp +++ b/comdel/domain/rule.cpp @@ -1,62 +1,61 @@ #include "rule.h" +#include + namespace domain { -Condition::Condition(std::string function, std::vector params, bool negated) - : negated(negated), function(function), params(params) -{} + Condition::Condition(std::string function, std::vector params, bool negated) + : negated(negated), function(std::move(function)), params(std::move(params)) {} -bool Condition::evaluate(RuleContext &context) { - std::vector request; - for(unsigned int i=0; i request; + for (auto & param : params) { + if (param.isType(Value::ADDRESS_SPACE_REFERENCE)) { + request.push_back(Value::fromAddressSpace(context.addressSpaces.at(param.asReference()))); + } else if (param.isType(Value::ATTRIBUTE_REFERENCE)) { + request.push_back(context.attributes[param.asReference()]); + } else { + request.push_back(param); + } } + bool result = context.function[function]->validate(request); + return negated ? !result : result; } - bool result = context.function[function]->validate(request); - return negated ? !result : result; -} -Action::Action(ActionType type, std::string message) - : type(type), message(message) -{} + Action::Action(ActionType type, std::string message) + : type(type), message(std::move(message)) {} -Action::ActionType Action::getType() { - return type; -} -std::string Action::getMessage() { - return message; -} - - -IfStatement::IfStatement(Condition condition, Action action) - : condition(condition), action(action) -{} - -std::optional IfStatement::evaluate(RuleContext &context) { - if(condition.evaluate(context)) { - return action; + Action::ActionType Action::getType() { + return type; } - return std::nullopt; -} -Rule::Rule(std::vector statements) - : statements(statements) -{} + std::string Action::getMessage() { + return message; + } -std::optional Rule::evaluate(RuleContext &context) { - for(unsigned int i=0; i IfStatement::evaluate(RuleContext &context) { + if (condition.evaluate(context)) { + return action; } + return std::nullopt; + } + + Rule::Rule(std::vector statements) + : statements(std::move(statements)) {} + + std::optional Rule::evaluate(RuleContext &context) { + for (auto & statement : statements) { + auto response = statement.evaluate(context); + if (response) { + return response; + } + } + return std::nullopt; } - return std::nullopt; -} } // namespace domain diff --git a/comdel/domain/rule.h b/comdel/domain/rule.h index 26caed5..83c906b 100644 --- a/comdel/domain/rule.h +++ b/comdel/domain/rule.h @@ -1,9 +1,9 @@ #ifndef DOMAIN_RULE_H #define DOMAIN_RULE_H -#include "addressspace.h" +#include "address_space.h" #include "value.h" -#include "functionsignature.h" +#include "function_signature.h" #include #include @@ -12,58 +12,58 @@ namespace domain { -struct RuleContext { - std::map addressSpaces; - std::map attributes; - std::map function; -}; - -class Condition { - bool negated; - std::string function; - std::vector params; - -public: - Condition(std::string function, std::vector params, bool negated); - - bool evaluate(RuleContext &context); -}; - -class Action { -public: - enum ActionType { - ERROR, - WARNING + struct RuleContext { + std::map addressSpaces; + std::map attributes; + std::map function; }; -private: - ActionType type; - std::string message; + class Condition { + bool negated; + std::string function; + std::vector params; -public: - Action(ActionType type, std::string message); + public: + Condition(std::string function, std::vector params, bool negated); - ActionType getType(); - std::string getMessage(); -}; + bool evaluate(RuleContext &context); + }; -class IfStatement { - Condition condition; - Action action; -public: - IfStatement(Condition condition, Action action); + class Action { + public: + enum ActionType { + ERROR, + WARNING + }; - std::optional evaluate(RuleContext &context); -}; + private: + ActionType type; + std::string message; -class Rule -{ - std::vector statements; -public: - Rule(std::vector statements); + public: + Action(ActionType type, std::string message); - std::optional evaluate(RuleContext &context); -}; + ActionType getType(); + + std::string getMessage(); + }; + + class IfStatement { + Condition condition; + Action action; + public: + IfStatement(Condition condition, Action action); + + std::optional evaluate(RuleContext &context); + }; + + class Rule { + std::vector statements; + public: + explicit Rule(std::vector statements); + + std::optional evaluate(RuleContext &context); + }; } // namespace domain diff --git a/comdel/domain/schema.cpp b/comdel/domain/schema.cpp index 6e475a8..810a961 100644 --- a/comdel/domain/schema.cpp +++ b/comdel/domain/schema.cpp @@ -2,27 +2,41 @@ namespace domain { -Schema::Schema() -{ -} + bool Schema::hasConnection(string &component, string &pin) { + return getConnection(component, pin) != nullptr; + } -bool Schema::hasConnection(string& component, string& pin) { - return getConnection(component, pin) != nullptr; -} - -ConnectionInstance* Schema::getConnection(string& component, string& pin) { - for(auto& conn: connections) { - if(conn->instance->name == component && conn->connection.getComponent().pin == pin) { - return conn.get(); - } - auto dirConn = dynamic_cast(conn.get()); - if(dirConn != nullptr) { - if(dirConn->secondInstance->name == component && conn->connection.getSecondComponent()->pin == pin) { - return dirConn; + ConnectionInstance *Schema::getConnection(string &component, string &pin) { + for (auto &conn: connections) { + if (conn->instance->name == component && conn->connection.getComponent().pin == pin) { + return conn.get(); + } + auto dirConn = dynamic_cast(conn.get()); + if (dirConn != nullptr) { + if (dirConn->secondInstance->name == component && conn->connection.getSecondComponent()->pin == pin) { + return dirConn; + } } } + return nullptr; + } + + BusInstance *Schema::getBusInstance(string &name) { + for (auto &instance: busInstances) { + if (instance->name == name) { + return instance.get(); + } + } + return nullptr; + } + + ComponentInstance *Schema::getComponentInstance(string &name) { + for (auto &instance: componentInstances) { + if (instance->name == name) { + return instance.get(); + } + } + return nullptr; } - return nullptr; -} } // namespace domain diff --git a/comdel/domain/schema.h b/comdel/domain/schema.h index 7d9ba0b..da72344 100644 --- a/comdel/domain/schema.h +++ b/comdel/domain/schema.h @@ -1,45 +1,27 @@ #ifndef DOMAIN_SCHEMA_H #define DOMAIN_SCHEMA_H -#include "connectioninstance.h" +#include "connection_instance.h" #include "instance.h" -#include "wireinstance.h" #include namespace domain { -class Schema { -public: - Schema(); + class Schema { + public: + Schema() = default; - std::vector> busInstances; - std::vector> componentInstances; + std::vector> busInstances; + std::vector> componentInstances; - std::vector> connections; + std::vector> connections; - BusInstance *getBusInstance(std::string &name) { - for (auto &instance: busInstances) { - if (instance->name == name) { - return instance.get(); - } - } - return nullptr; - } - - ComponentInstance *getComponentInstance(std::string &name) { - for (auto &instance: componentInstances) { - if (instance->name == name) { - return instance.get(); - } - } - return nullptr; - } - - bool hasConnection(string &component, string &pin); - - ConnectionInstance *getConnection(string &component, string &pin); -}; + BusInstance *getBusInstance(std::string &name); + ComponentInstance *getComponentInstance(std::string &name); + bool hasConnection(string &component, string &pin); + ConnectionInstance *getConnection(string &component, string &pin); + }; } // namespace domain diff --git a/comdel/domain/schema_creator.cpp b/comdel/domain/schema_creator.cpp new file mode 100644 index 0000000..5733839 --- /dev/null +++ b/comdel/domain/schema_creator.cpp @@ -0,0 +1,1079 @@ +#include "schema_creator.h" + +#include +#include + +namespace domain { + + + ComdelContext::ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus) + : name(std::move(name)), inComponent(inComponent), inConnection(inConnection), inSingleAutomaticConnection(inSingleAutomaticConnection), inBus(inBus) {} + + bool ComdelContext::doesAttributeExists(std::string name, Value::ValueType type) { + for (auto &attribute: attributes) { + if (attribute.getDefault().getType() == type && attribute.getName() == name) { + return true; + } + } + return false; + } + + bool ComdelContext::doesWireExists(std::string name) { + for (auto &w: wires) { + if (w == name) { + return true; + } + } + return false; + } + + + Component::ComponentType toType(ComponentNode::ComponentType type) { + if (type == ComponentNode::MEMORY) { + return Component::MEMORY; + } else if (type == ComponentNode::PROCESSOR) { + return Component::PROCESSOR; + } + return Component::OTHER; + } + + Action::ActionType toType(ActionNode::ActionType type) { + if (type == ActionNode::ERROR) { + return Action::ERROR; + } + return Action::WARNING; + } + + Wire::WireType toType(WireNode::WireType type) { + switch (type) { + case WireNode::R_WIRE: + return Wire::R_WIRE; + case WireNode::WIRE: + return Wire::WIRE_DEFAULT; + case WireNode::WIRED_AND: + return Wire::WIRED_AND; + case WireNode::WIRED_OR: + return Wire::WIRED_OR; + default: + return Wire::WIRE_DEFAULT; + } + } + + Value::ValueType toType(ValueNode::ValueType type) { + switch (type) { + case ValueNode::BOOL: + return Value::BOOL; + case ValueNode::MEMORY: + return Value::MEMORY_REFERENCE; + case ValueNode::WIRE: + return Value::WIRE_REFERENCE; + case ValueNode::STRING: + return Value::STRING; + case ValueNode::INT: + return Value::INT; + case ValueNode::NIL: + return Value::NIL; + default: + return Value::UNDEFINED; + } + } + + + Value toType(ValueNode node, Value::ValueType type = Value::ValueType::UNDEFINED) { + if (type == Value::MEMORY_REFERENCE) { + if (node.getType() == ValueNode::NIL) { + return Value::fromMemoryReference(nullopt); + } else { + return Value::fromMemoryReference(node.asIdentifier()); + } + } + + if (node.getType() == ValueNode::BOOL) { + return Value::fromBool(node.asBool()); + } else if (node.getType() == ValueNode::INT) { + return Value::fromInt(node.asInt()); + } else if (node.getType() == ValueNode::STRING) { + return Value::fromString(node.asString()); + } else if (node.getType() == ValueNode::NIL) { + return Value::fromNull(); + } + return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); + } + + + Bus::BusType toType(BusNode::BusType type) { + if (type == BusNode::AUTOMATIC) { + return Bus::AUTOMATIC; + } else if (type == BusNode::SINGLE_AUTOMATIC) { + return Bus::SINGLE_AUTOMATIC; + } + return Bus::REGULAR; + } + + + Pin::PinType toType(PinNode::PinType type) { + if (type == PinNode::IN) { + return Pin::IN; + } else if (type == PinNode::OUT) { + return Pin::OUT; + } + return Pin::IN_OUT; + } + + PinConnection::ConnectionType toType(PinConnectionNode::ConnectionType type) { + if (type == PinConnectionNode::OPTIONAL) { + return PinConnection::OPTIONAL; + } + return PinConnection::REQUIRED; + } + + + Popup::PopupType toType(PopupNode::PopupType type) { + if (type == PopupNode::AUTOMATIC) { + return Popup::AUTOMATIC; + } + return Popup::ON_DEMAND; + } + + SchemaCreator::SchemaCreator(std::vector validators) + : validators(std::move(validators)) {} + + std::optional SchemaCreator::loadLibrary(LibraryNode node) { + // library fields + if (!node.name) { + errors.emplace_back(node.span, "missing @name"); + return nullopt; + } else { + name = node.name->asString(); + } + + if (node.componentHeader.has_value()) { + componentHeader = node.componentHeader->asString(); + } + + if (!node.componentDirectory) { + errors.emplace_back(node.span, "missing @componentDirectory"); + return nullopt; + } else { + componentDirectory = node.componentDirectory->asString(); + } + + header = node.header ? node.header->asString() : ""; + + libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; + + for (auto &as: node.addressSpaces) { + addressSpaces.push_back(*loadAddressSpace(as)); + } + + for (auto &comp: node.components) { + std::optional component; + component = loadComponent(comp); + if (component) { + components.push_back(*component); + } + } + + for (auto &buse: node.buses) { + auto bus = loadBus(buse); + if (bus) { + buses.push_back(*bus); + } + } + + for (auto &connection: node.connections) { + auto conn = loadConnection(connection); + if (conn) { + connections.push_back(*conn); + } + } + + for (auto &message: node.messages) { + if (!message.value.is(ValueNode::STRING)) { + errors.emplace_back(message.value.span, "expected `string`"); + } else { + messages[message.key.value] = message.value.asString(); + } + } + + return Library(name, libraryInfo, header, componentDirectory, componentHeader, addressSpaces, components, buses, + connections, messages); + } + + std::optional SchemaCreator::loadBus(BusNode node) { + std::string busName = node.name.value; + + auto count = std::make_pair(1, 1); + if (node.count) { + count = std::make_pair(node.count->first.value, node.count->second.value); + } + if (count.first > count.second || count.first < 0) { + errors.emplace_back(node.count->span, "invalid @size"); + return nullopt; + } + + auto type = toType(node.type.value); + + if (!node.tooltip && type == Bus::REGULAR) { + errors.emplace_back(node.span, "missing @tooltip"); + return nullopt; + } + std::string tooltip = node.tooltip->asString(); + + if (!node.display && type == Bus::REGULAR) { + errors.emplace_back(node.span, "missing @display"); + return nullopt; + } + if (node.display && (type == Bus::AUTOMATIC || type == Bus::SINGLE_AUTOMATIC)) { + errors.emplace_back(node.span, "automatic bus cannot have a @display"); + return nullopt; + } + + optional displayBus; + if (type == Bus::REGULAR) { + auto display = loadDisplay(*node.display); + if (!display) { + return nullopt; + } + if (display->getItems().size() != 1 || !display->getItems()[0].bus.has_value()) { + errors.emplace_back(node.span, "@display must contain only exactly one bus definition"); + return nullopt; + } + displayBus = *display->getItems()[0].bus; + } + + if (node.wires.empty()) { + errors.emplace_back(node.span, "missing @wires"); + return nullopt; + } + std::vector wires; + for (auto &_wire: node.wires) { + auto wire = loadWire(_wire); + if (wire) { + wires.push_back(*wire); + } + } + + if (type == Bus::SINGLE_AUTOMATIC && wires.size() != 1) { + errors.emplace_back(node.span, "singleAutomatic bus must have exactly 1 wire defined"); + return nullopt; + } + + return Bus(busName, tooltip, type, count, wires, displayBus); + } + + + std::optional SchemaCreator::loadAddressSpace(AddressSpaceNode node) { + return AddressSpace(node.name.value, node.start.value, node.end.value); + } + + std::optional SchemaCreator::loadConnection(ConnectionNode node) { + push(ComdelContext("connection", false, true, false, false)); + + std::string bus = node.bus.value; + auto busInstance = getBus(bus); + if (!busInstance) { + errors.emplace_back(node.span, "bus does not exist"); + } + + if (busInstance->getType() == Bus::SINGLE_AUTOMATIC) { + current().inSingleAutomaticConnection = true; + } + + if (busInstance->getType() == Bus::REGULAR) { + ConnectionComponent first{node.first.component.value, node.first.pin.value}; + + auto componentInstance = getComponentPin(first.component, first.pin); + if (!componentInstance) { + errors.emplace_back(node.span, "pin does not exist"); + } + + if (node.second.has_value()) { + errors.emplace_back(node.span, "regular bus doesn't allow direct connections"); + } + + std::set wireNames; + for (auto &wire: busInstance->getWires()) { + wireNames.insert(wire.getName()); + current().wires.push_back(wire.getName()); + } + + std::vector attributes; + for (auto &attribute: node.attributes) { + auto attr = loadAttribute(attribute); + if (!attr) { + return nullopt; + } + attributes.push_back(*attr); + } + + std::set attributeNames; + for (auto attribute: attributes) { + attributeNames.insert(attribute.getName()); + } + + std::vector wires; + for (auto &firstWire: node.firstWires) { + if (firstWire.is(ValueNode::NIL)) { + wires.push_back(Value::fromNull()); + } else if (firstWire.is(ValueNode::INT)) { + wires.push_back(Value::fromInt(firstWire.asInt())); + } else if (firstWire.is(ValueNode::IDENTIFIER)) { + if (attributeNames.count(firstWire.asIdentifier())) { + wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE)); + } else if (wireNames.count(firstWire.asIdentifier())) { + wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE)); + } else { + errors.emplace_back(firstWire.span, "unknown identifier"); + } + } else { + errors.emplace_back(firstWire.span, "unknown value type"); + } + } + + pop(); + + return Connection(first, nullopt, bus, attributes, wires, nullopt); + } else if (busInstance->getType() == Bus::AUTOMATIC || busInstance->getType() == Bus::SINGLE_AUTOMATIC) { + ConnectionComponent first{node.first.component.value, node.first.pin.value}; + + if (!node.second.has_value()) { + errors.emplace_back(node.span, "missing second component"); + } + + ConnectionComponent second{node.second->component.value, node.second->pin.value}; + + auto firstComponentInstance = getComponentPin(first.component, first.pin); + if (!firstComponentInstance) { + errors.emplace_back(node.span, "pin does not exist"); + } + + auto secondComponentInstance = getComponentPin(second.component, second.pin); + if (!secondComponentInstance) { + errors.emplace_back(node.span, "pin does not exist"); + } + + std::set wireNames; + for (auto &wire: busInstance->getWires()) { + wireNames.insert(wire.getName()); + current().wires.push_back(wire.getName()); + } + + if (node.attributes.size() != 2 && busInstance->getType() == Bus::SINGLE_AUTOMATIC) { + errors.emplace_back(node.span, "singleAutomatic must contain 2 attributes"); + } + + std::vector attributes; + for (auto &attribute: node.attributes) { + auto attr = loadAttribute(attribute); + if (!attr) { + return nullopt; + } + attributes.push_back(*attr); + } + + std::set attributeNames; + for (auto attribute: attributes) { + attributeNames.insert(attribute.getName()); + } + + std::vector firstWires; + for (auto &firstWire: node.firstWires) { + if (firstWire.is(ValueNode::NIL)) { + firstWires.push_back(Value::fromNull()); + } else if (firstWire.is(ValueNode::INT)) { + firstWires.push_back(Value::fromInt(firstWire.asInt())); + } else if (firstWire.is(ValueNode::STRING) && busInstance->getType() == Bus::SINGLE_AUTOMATIC) { + firstWires.push_back(Value::fromString(firstWire.asString())); + } else if (firstWire.is(ValueNode::IDENTIFIER) && busInstance->getType() == Bus::AUTOMATIC) { + if (attributeNames.count(firstWire.asIdentifier())) { + firstWires.push_back( + Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE)); + } else if (wireNames.count(firstWire.asIdentifier())) { + firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE)); + } else { + errors.emplace_back(firstWire.span, "unknown identifier"); + } + } else { + errors.emplace_back(firstWire.span, "unsupported value type"); + } + } + + + std::vector secondWires; + for (auto &secondWire: *node.secondWires) { + if (secondWire.is(ValueNode::NIL)) { + secondWires.push_back(Value::fromNull()); + } else if (secondWire.is(ValueNode::INT)) { + secondWires.push_back(Value::fromInt(secondWire.asInt())); + } else if (secondWire.is(ValueNode::STRING) && busInstance->getType() == Bus::SINGLE_AUTOMATIC) { + secondWires.push_back(Value::fromString(secondWire.asString())); + } else if (secondWire.is(ValueNode::IDENTIFIER) && busInstance->getType() == Bus::AUTOMATIC) { + if (attributeNames.count(secondWire.asIdentifier())) { + secondWires.push_back( + Value::fromReference(secondWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE)); + } else if (wireNames.count(secondWire.asIdentifier())) { + secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::WIRE_REFERENCE)); + } else { + errors.emplace_back(secondWire.span, "unknown identifier"); + } + } else { + errors.emplace_back(secondWire.span, "unsupported value type"); + } + } + + if (busInstance->getType() == Bus::SINGLE_AUTOMATIC && attributes.size() == 2) { + if (!attributes[0].getPopup().has_value()) { + errors.emplace_back(node.attributes[0].span, "@popup is required"); + } else if (attributes[0].getDefault().getType() != Value::STRING) { + errors.emplace_back(node.attributes[0].span, "@attribute must be of type string"); + } else { + attributes[0].getPopup()->setEnumeration(createWireEnumeration(firstWires)); + } + + if (!attributes[1].getPopup().has_value()) { + errors.emplace_back(node.attributes[1].span, "@popup is required"); + } else if (attributes[1].getDefault().getType() != Value::STRING) { + errors.emplace_back(node.attributes[1].span, "@attribute must be of type string"); + } else { + attributes[1].getPopup()->setEnumeration(createWireEnumeration(secondWires)); + } + } + + pop(); + + return Connection(first, second, bus, attributes, firstWires, secondWires); + } + pop(); + errors.emplace_back(node.span, "unsupported connection type"); + + return std::nullopt; + } + + std::optional SchemaCreator::loadComponent(ComponentNode node) { + push(ComdelContext(node.name.value, true, false, false, false)); + + std::string componentName = node.name.value; + + if (!node.tooltip) { + errors.emplace_back(node.span, "missing @tooltip"); + pop(); + return nullopt; + } + std::string tooltip = node.tooltip->asString(); + + if (!node.source) { + errors.emplace_back(node.span, "missing @source"); + pop(); + return nullopt; + } + std::string source = node.source->asString(); + + Component::ComponentType type = toType(node.type.value); + + std::vector attributes; + for (auto &a: node.attributes) { + std::optional attribute = loadAttribute(a); + if (attribute) { + attributes.push_back(*attribute); + } + } + if (type == Component::PROCESSOR) { + attributes.push_back(*createMemoryAttribute()); + } + + context[context.size() - 1].attributes = attributes; + + std::vector rules; + for (auto &r: node.rules) { + std::optional rule = loadRule(r); + if (rule) { + rules.push_back(*rule); + } + } + + if (!node.instanceName) { + errors.emplace_back(node.span, "missing @instanceName"); + pop(); + return nullopt; + } + std::string instanceName = node.instanceName->asString(); + + auto count = std::make_pair(1, 1); + if (node.count) { + count = std::make_pair(node.count->first.value, node.count->second.value); + } + if (count.first > count.second || count.first < 0) { + errors.emplace_back(node.count->first.span, "invalid @size"); + pop(); + return nullopt; + } + + if (!node.display) { + errors.emplace_back(node.span, "missing @display"); + pop(); + return nullopt; + } + optional display = loadDisplay(*node.display); + if (!display) { + pop(); + return nullopt; + } + + std::vector pins; + for (auto &p: node.pins) { + auto pin = loadPin(p); + if (!pin) { + pop(); + return nullopt; + } + pins.push_back(*pin); + } + + pop(); + return Component(componentName, tooltip, source, type, rules, instanceName, count, *display, pins, attributes); + } + + std::optional SchemaCreator::loadWire(WireNode node) { + return Wire( + node.name.value, + toType(node.type.value), + node.size.value, + node.hidden, + node.hasTerminateWith, + toType(node.terminateWith) + ); + } + + optional SchemaCreator::loadPin(PinNode node) { + std::string pinName = node.name.value; + Pin::PinType type = toType(node.type.value); + + if (!node.tooltip) { + errors.emplace_back(node.span, "missing @tooltip"); + return nullopt; + } + std::string tooltip = node.tooltip->asString(); + + if (!node.display) { + errors.emplace_back(node.span, "missing @display"); + return nullopt; + } + std::vector attributes; + optional display = loadDisplay(*node.display); + if (!display) { + return nullopt; + } + if (display->getItems().size() != 1 || !display->getItems()[0].pin.has_value()) { + errors.emplace_back(node.span, "@display must contain only exactly one pin definition"); + return nullopt; + } + ui::Pin displayPin = *display->getItems()[0].pin; + + + if (!node.connection) { + errors.emplace_back(node.span, "missing @connection"); + return nullopt; + } + auto connection = loadPinConnection(*node.connection); + + std::optional> wiresOpt = std::nullopt; + if (node.wires.has_value()) { + auto nodeWires = node.wires.value(); + std::vector wires; + for (auto &nodeWire: nodeWires) { + if (nodeWire.is(ValueNode::NIL)) { + wires.push_back(Value::fromNull()); + } else if (nodeWire.is(ValueNode::INT)) { + wires.push_back(Value::fromInt(nodeWire.asInt())); + } else { + errors.emplace_back(node.span, "unknown value type"); + } + } + wiresOpt = wires; + } + + return Pin(pinName, type, tooltip, connection, displayPin, wiresOpt); + } + + std::optional SchemaCreator::loadDisplay(DisplayNode node) { + std::vector items; + for (auto &item: node.items) { + ui::Item displayItem; + std::string type = item.type.value; + if (type == "rect") { + long long int x, y, w, h; + x = item.asInt(&errors, "x"); + y = item.asInt(&errors, "y"); + w = item.asInt(&errors, "w"); + h = item.asInt(&errors, "h"); + displayItem.rect = ui::Rect(x, y, w, h); + } else if (type == "line") { + long long int x1, y1, x2, y2; + x1 = item.asInt(&errors, "x1"); + y1 = item.asInt(&errors, "y1"); + x2 = item.asInt(&errors, "x2"); + y2 = item.asInt(&errors, "y2"); + displayItem.line = ui::Line(x1, y1, x2, y2); + } else if (type == "pin") { + long long int x, y, w, h; + x = item.asInt(&errors, "x"); + y = item.asInt(&errors, "y"); + w = item.asInt(&errors, "w"); + h = item.asInt(&errors, "h"); + std::string _orientation = item.asString(&errors, "orientation", "bottom"); + std::string _pinType = item.asString(&errors, "type", "out"); + + ui::PinOrientation orientation; + if (_orientation == "left") { + orientation = ui::PinOrientation::LEFT; + } else if (_orientation == "right") { + orientation = ui::PinOrientation::RIGHT; + } else if (_orientation == "top") { + orientation = ui::PinOrientation::TOP; + } else if (_orientation == "bottom") { + orientation = ui::PinOrientation::BOTTOM; + } else { + errors.emplace_back(item.span, "unknown pin orientation type '" + _orientation + "'"); + } + + ui::PinType pinType; + if (_pinType == "in") { + pinType = ui::PinType::IN; + } else if (_pinType == "out") { + pinType = ui::PinType::OUT; + } else if (_pinType == "in_out") { + pinType = ui::PinType::IN_OUT; + } else { + errors.emplace_back(item.span, "unknown pin type '" + _pinType + "'"); + } + + displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType); + } else if (type == "bus") { + long long int x, y, w, h; + x = item.asInt(&errors, "x"); + y = item.asInt(&errors, "y"); + w = item.asInt(&errors, "w"); + h = item.asInt(&errors, "h"); + std::string _orientation = item.asString(&errors, "orientation", "bottom"); + + ui::BusOrientation orientation; + if (_orientation == "horizontal") { + orientation = ui::BusOrientation::HORIZONTAL; + } else if (_orientation == "vertical") { + orientation = ui::BusOrientation::VERTICAL; + } else { + errors.emplace_back(item.span, "unknown bus orientation type '" + _orientation + "'"); + } + + displayItem.bus = ui::Bus(x, y, w, h, orientation); + } else { + errors.emplace_back(item.type.span, "unsupported display type"); + } + items.push_back(displayItem); + } + return Display(items); + } + + + PinConnection SchemaCreator::loadPinConnection(PinConnectionNode node) { + std::string message = node.message.asString(); + PinConnection::ConnectionType type = toType(node.type.value); + return {message, type}; + } + + std::optional SchemaCreator::loadAttribute(AttributeNode node) { + std::string name = node.name.value; + pushAdditional(name); + Value value; + + if (current().inComponent) { + if (node.type == ValueNode::INT) { + value = Value::fromInt(node.defaultValue->asInt()); + } else if (node.type == ValueNode::BOOL) { + value = Value::fromBool(node.defaultValue->asBool()); + } else if (node.type == ValueNode::STRING) { + value = Value::fromString(node.defaultValue->asString()); + } else { + errors.emplace_back(node.name.span, "unsupported type"); + } + } + if (current().inConnection && !current().inSingleAutomaticConnection) { // TODO remove identifier + if (node.type == ValueNode::WIRE || node.type == ValueNode::IDENTIFIER) { + if (current().doesWireExists(node.defaultValue->asIdentifier())) { + value = Value::fromReference(node.defaultValue->asIdentifier(), Value::WIRE_REFERENCE); + } else { + value = Value::fromReference("", Value::WIRE_REFERENCE); + errors.emplace_back(node.span, "unknown identifier"); + } + } else { + errors.emplace_back(node.name.span, "unsupported type"); + } + } + if (current().inSingleAutomaticConnection) { + if (node.type == ValueNode::STRING) { + value = Value::fromString(node.defaultValue->asString()); + } else { + errors.emplace_back(node.name.span, "unsupported type"); + } + } + + current().attributes.emplace_back(name, value); + + std::optional popup; + if (node.popup) { + popup = loadPopup(*node.popup, name, value.getType()); + } + + pop(); + return Attribute(name, value, popup); + } + + std::optional SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type) { + auto popupType = toType(node.type.value().value); + + pushAdditional(name); + + current().attributes.clear(); + current().attributes.emplace_back(name, Value::ofType(type)); + + if (!node.title) { + errors.emplace_back(node.span, "missing @title"); + return nullopt; + } + std::string title = node.title->asString(); + + if (!node.text) { + errors.emplace_back(node.span, "missing @text"); + return nullopt; + } + std::string text = node.text->asString(); + + std::vector rules; + for (auto &r: node.rules) { + std::optional rule = loadRule(r); + if (rule) { + rules.push_back(*rule); + } + } + + std::vector enumeration; + if (node.enumerated) { + for (auto &enumNode: node.enumeration) { + if (type == Value::INT || type == Value::STRING || type == Value::BOOL) { + auto value = toType(enumNode.value); + if (value.getType() == type) { + enumeration.emplace_back(enumNode.key.asString(), value); + } else { + errors.emplace_back(enumNode.span, "wrong type"); + } + } else if (type == Value::WIRE_REFERENCE) { + auto value = toType(enumNode.value); + if (value.isType(Value::UNDEFINED)) { + if (current().doesWireExists(value.asReference())) { + value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE); + } else { + errors.emplace_back(enumNode.span, "unknown wire"); + } + } + + if (value.isType(Value::WIRE_REFERENCE) || value.isType(Value::INT) || value.isType(Value::NIL)) { + enumeration.emplace_back(enumNode.key.asString(), value); + } else { + errors.emplace_back(enumNode.span, "wrong type"); + } + } + } + } else { + if (type == Value::WIRE_REFERENCE && !current().inConnection) { + errors.emplace_back(node.span, "@enumeration is required for attributes of type wire"); + } + } + + pop(); + + return Popup(title, text, popupType, rules, enumeration); + } + + std::optional SchemaCreator::loadRule(RuleNode node) { + std::vector statements; + + for (auto &stmt: node.statements) { + auto condition = loadCondition(stmt.condition); + if (condition) { + statements.emplace_back(*condition, + Action(toType(stmt.action.type.value), stmt.action.message.asString())); + } else { + return nullopt; + } + } + + return Rule(statements); + } + + std::optional SchemaCreator::loadCondition(ConditionNode node) { + std::string function = node.functionName.value; + + for (auto &validator: validators) { + if (validator->getName() == function) { + if (validator->getSignature().size() == node.params.size()) { + std::vector params; + for (uint j = 0; j < validator->getSignature().size(); j++) { + bool exists = false; + auto type = toType(node.params[j]); + if (type.getType() == Value::UNDEFINED) { + if (current().doesAttributeExists(type.asReference(), validator->getSignature()[j])) { + exists = true; + type = Value::fromReference(type.asReference(), Value::ATTRIBUTE_REFERENCE); + } + if (validator->getSignature()[j] == Value::ADDRESS_SPACE) { + if (hasAddressSpace(type.asReference())) { + exists = true; + type = Value::fromReference(type.asReference(), Value::ADDRESS_SPACE_REFERENCE); + } + } + + if (!exists) { + errors.emplace_back(node.functionName.span, "unknown reference " + type.asReference()); + } + } + params.push_back(type); + } + return Condition(function, params, node.negated); + } else { + errors.emplace_back(node.functionName.span, "wrong number of parameters"); + } + } + } + + errors.emplace_back(node.functionName.span, "unknown function name"); + return nullopt; + } + + + Schema *SchemaCreator::loadSchema(SchemaNode node, Library &library) { + auto *schema = new Schema(); + + for (auto &instance: node.instances) { + if (library.hasComponent(instance.component.value)) { + schema->componentInstances.push_back(loadComponentInstance(instance, library)); + } + if (library.hasBus(instance.component.value)) { + schema->busInstances.push_back(loadBusInstance(instance, library)); + } + } + + for (auto &conn: node.connections) { + auto firstComponent = schema->getComponentInstance(conn.first.instance.value); + if (firstComponent == nullptr) { + errors.emplace_back(conn.first.instance.span, "unknown component"); + continue; + } + if (!firstComponent->component.hasPin(conn.first.pin.value)) { + errors.emplace_back(conn.first.pin.span, "unknown pin"); + continue; + } + + + ComponentInstance *secondComponent = nullptr; + if (conn.second.has_value()) { + secondComponent = schema->getComponentInstance(conn.second->instance.value); + if (secondComponent == nullptr) { + errors.emplace_back(conn.second->instance.span, "unknown component"); + continue; + } + if (!secondComponent->component.hasPin(conn.second->pin.value)) { + errors.emplace_back(conn.second->pin.span, "unknown pin"); + continue; + } + } + + auto bus = schema->getBusInstance(conn.bus.value); + if (bus == nullptr) { + errors.emplace_back(conn.bus.span, "unknown bus"); + continue; + } + + std::optional connection = std::nullopt; + if (secondComponent != nullptr) { + ConnectionComponent firstConn{firstComponent->component.getName(), conn.first.pin.value}; + ConnectionComponent secondConn{secondComponent->component.getName(), conn.second->pin.value}; + + if (library.hasConnection(firstConn, + bus->bus.getName(), + secondConn)) { + connection = *library.getConnection(firstConn, bus->bus.getName(), secondConn); + } else { + errors.emplace_back(conn.span, "unknown connection"); + continue; + } + } else { + ConnectionComponent firstConn{firstComponent->component.getName(), conn.first.pin.value}; + + if (library.hasConnection(firstConn, + bus->bus.getName())) { + connection = *library.getConnection(firstConn, bus->bus.getName()); + } else { + errors.emplace_back(conn.span, "unknown connection"); + continue; + } + } + + std::vector attributes; + for (auto &attr: conn.attributes) { + if (connection->hasAttribute(attr.name.value)) { + auto attribute = connection->getAttribute(attr.name.value); + auto value = toType(attr.value); + + for (auto &en: attribute.getPopup()->getEnumeration()) { + if (en.getValue().asReference() == value.asReference()) { + value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE); + } + } + if (value.isType(Value::UNDEFINED)) { + errors.emplace_back(attr.span, "invalid value"); + } + + attributes.emplace_back(attribute.getName(), toType(attr.value), attribute); + } else { + errors.emplace_back(attr.name.span, "unknown attribute"); + } + } + + if (secondComponent == nullptr) { + schema->connections.push_back( + std::make_shared(firstComponent, attributes, bus, *connection)); + } else { + schema->connections.push_back( + std::make_shared(firstComponent, secondComponent, attributes, bus, + *connection)); + } + } + + return schema; + } + + shared_ptr SchemaCreator::loadComponentInstance(InstanceNode instance, Library &library) { + + auto componentInstanceName = instance.name.value; + auto position = std::make_pair(instance.position->first.value, instance.position->second.value); + + auto component = library.getComponent(instance.component.value); + + // validate attributes + std::vector attributes; + for (auto &attr: instance.attributes) { + if (component.hasAttribute(attr.name.value, toType(attr.value.getType()))) { + auto attribute = component.getAttribute(attr.name.value); + attributes.emplace_back(attribute.getName(), toType(attr.value, attribute.getDefault().getType()), + attribute); + } else { + errors.emplace_back(SourceError(attr.name.span, "unknown attribute")); + } + } + + if (attributes.size() < component.getAttributes().size()) { + for (auto &attr: component.getAttributes()) { + if (std::count_if(attributes.begin(), attributes.end(), + [&attr](InstanceAttribute &attribute) { return attr.getName() == attribute.name; }) == + 0) { + errors.emplace_back(SourceError(instance.span, "missing attribute '" + attr.getName() + "'")); + } + } + } + + return std::make_shared(componentInstanceName, attributes, position, component); + } + + std::shared_ptr SchemaCreator::loadBusInstance(InstanceNode instance, Library &library) { + + auto busInstanceName = instance.name.value; + auto position = std::make_pair(instance.position->first.value, instance.position->second.value); + + auto bus = library.getBus(instance.component.value); + + long long size = 0; + if (instance.size) { + size = instance.size->value; + } + + return std::make_shared(busInstanceName, position, bus, static_cast(size)); + } + + vector SchemaCreator::createWireEnumeration(vector wireValues) { + vector wires; + for (auto &wire: wireValues) { + if (wire.isType(Value::STRING)) { + wires.emplace_back(wire.asString(), wire); + } + } + return wires; + } + + std::optional SchemaCreator::createMemoryAttribute() { + return Attribute("_memory", Value::fromMemoryReference(std::nullopt), createMemoryPopup()); + } + + std::optional SchemaCreator::createMemoryPopup() { + return Popup("Postavi memoriju", "Postavi memoriju za izabrani procesor", Popup::AUTOMATIC, vector{}, + vector{}); + } + + std::optional SchemaCreator::getBus(std::string name) { + for (auto &bus: buses) { + if (bus.getName() == name) { + return bus; + } + } + return std::nullopt; + } + + std::optional SchemaCreator::getComponentPin(std::string name, std::string pin) { + for (auto &c: components) { + if (c.getName() == name) { + for (auto &p: c.getPins()) { + if (p.getName() == pin) { + return p; + } + } + } + } + return nullopt; + } + + bool SchemaCreator::hasAddressSpace(std::string name) { + for (auto &as: addressSpaces) { + if (as.getName() == name) { + return true; + } + } + return false; + } + + void SchemaCreator::push(ComdelContext context) { + this->context.push_back(context); + } + + void SchemaCreator::pushAdditional(std::string name) { + if (!this->context.empty()) { + this->context.push_back(current()); + current().name = name; + } else { + ComdelContext con(name, false, false, false, false); + push(con); + } + } + + ComdelContext &SchemaCreator::current() { + return this->context[this->context.size() - 1]; + } + + void SchemaCreator::pop() { + this->context.pop_back(); + } + + std::vector SchemaCreator::getErrors() { + return errors; + } + +} // namespace domain diff --git a/comdel/domain/schema_creator.h b/comdel/domain/schema_creator.h new file mode 100644 index 0000000..991db77 --- /dev/null +++ b/comdel/domain/schema_creator.h @@ -0,0 +1,93 @@ +#ifndef DOMAIN_COMDEL_GENERATOR_H +#define DOMAIN_COMDEL_GENERATOR_H + +#include "library.h" +#include "schema.h" + +#include +#include + +#include +#include +#include + +namespace domain { + + struct ComdelContext { + std::vector attributes; + std::vector wires; + std::string name; + bool inComponent; + bool inConnection; + bool inSingleAutomaticConnection; + bool inBus; + + ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus); + + bool doesAttributeExists(std::string name, Value::ValueType type); + bool doesWireExists(std::string name); + + }; + + class SchemaCreator { + std::vector context; + + std::string name; + std::string libraryInfo; + std::string header; + std::string componentDirectory; + std::optional componentHeader = nullopt; + std::vector addressSpaces; + std::vector components; + std::vector buses; + std::vector connections; + std::map messages; + + + std::vector errors; + std::vector validators; + + + std::optional loadAddressSpace(AddressSpaceNode node); + std::optional loadComponent(ComponentNode node); + std::optional loadAttribute(AttributeNode node); + std::optional loadRule(RuleNode node); + std::optional loadCondition(ConditionNode node); + std::optional loadPopup(PopupNode node, std::string name, Value::ValueType type); + std::optional loadDisplay(DisplayNode node); + std::optional loadWire(WireNode node); + std::optional loadPin(PinNode pins); + + PinConnection loadPinConnection(PinConnectionNode node); + + std::optional loadConnection(ConnectionNode node); + std::optional loadBus(BusNode node); + + std::shared_ptr loadComponentInstance(InstanceNode instance, Library &library); + std::shared_ptr loadBusInstance(InstanceNode instance, Library &library); + + std::optional getBus(std::string name); + std::optional getComponentPin(std::string name, std::string pin); + bool hasAddressSpace(std::string name); + + void push(ComdelContext context); + void pushAdditional(std::string name); + ComdelContext ¤t(); + void pop(); + + std::optional createMemoryAttribute(); + vector createWireEnumeration(vector enumeration); + std::optional createMemoryPopup(); + + public: + explicit SchemaCreator(std::vector validators); + + std::vector getErrors(); + + std::optional loadLibrary(LibraryNode node); + Schema *loadSchema(SchemaNode node, Library &library); + }; + +} // namespace domain + +#endif // DOMAIN_COMDEL_GENERATOR_H diff --git a/comdel/domain/schemacreator.cpp b/comdel/domain/schemacreator.cpp deleted file mode 100644 index 089138f..0000000 --- a/comdel/domain/schemacreator.cpp +++ /dev/null @@ -1,1003 +0,0 @@ -#include "schemacreator.h" - -#include -#include - -namespace domain { - -Component::ComponentType toType(ComponentNode::ComponentType type) { - if(type == ComponentNode::MEMORY) { - return Component::MEMORY; - } else if(type == ComponentNode::PROCESSOR) { - return Component::PROCESSOR; - } - return Component::OTHER; -} - -Action::ActionType toType(ActionNode::ActionType type) { - if(type == ActionNode::ERROR) { - return Action::ERROR; - } - return Action::WARNING; -} - -Wire::WireType toType(WireNode::WireType type) { - switch (type) { - case WireNode::R_WIRE: - return Wire::R_WIRE; - case WireNode::WIRE: - return Wire::WIRE_DEFAULT; - case WireNode::WIRED_AND: - return Wire::WIRED_AND; - case WireNode::WIRED_OR: - return Wire::WIRED_OR; - default: - return Wire::WIRE_DEFAULT; - } -} - -Value::ValueType toType(ValueNode::ValueType type) { - switch (type) { - case ValueNode::BOOL: - return Value::BOOL; - case ValueNode::MEMORY: - return Value::MEMORY_REFERENCE; - case ValueNode::WIRE: - return Value::WIRE_REFERENCE; - case ValueNode::STRING: - return Value::STRING; - case ValueNode::INT: - return Value::INT; - case ValueNode::NIL: - return Value::NIL; - default: - return Value::UNDEFINED; - } -} - - -Value toType(ValueNode node, Value::ValueType type = Value::ValueType::UNDEFINED) { - if(type == Value::MEMORY_REFERENCE) { - if(node.getType() == ValueNode::NIL) { - return Value::fromMemoryReference(nullopt); - } else { - return Value::fromMemoryReference(node.asIdentifier()); - } - } - - if(node.getType() == ValueNode::BOOL) { - return Value::fromBool(node.asBool()); - } else if(node.getType() == ValueNode::INT) { - return Value::fromInt(node.asInt()); - } else if(node.getType() == ValueNode::STRING) { - return Value::fromString(node.asString()); - } else if(node.getType() == ValueNode::NIL) { - return Value::fromNull(); - } - return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); -} - - -Bus::BusType toType(BusNode::BusType type) { - if(type == BusNode::AUTOMATIC) { - return Bus::AUTOMATIC; - } else if(type == BusNode::SINGLE_AUTOMATIC) { - return Bus::SINGLE_AUTOMATIC; - } - return Bus::REGULAR; -} - - -Pin::PinType toType(PinNode::PinType type) { - if(type == PinNode::IN) { - return Pin::IN; - } else if(type == PinNode::OUT) { - return Pin::OUT; - } - return Pin::IN_OUT; -} - -PinConnection::ConnectionType toType(PinConnectionNode::ConnectionType type) -{ - if(type == PinConnectionNode::OPTIONAL) { - return PinConnection::OPTIONAL; - } - return PinConnection::REQUIRED; -} - - -Popup::PopupType toType(PopupNode::PopupType type) -{ - if(type == PopupNode::AUTOMATIC) { - return Popup::AUTOMATIC; - } - return Popup::ON_DEMAND; -} - -SchemaCreator::SchemaCreator(std::vector validators) - : validators(std::move(validators)) -{} - -std::optional SchemaCreator::loadLibrary(LibraryNode node) -{ - // library fields - if(!node.name) { - errors.emplace_back(node.span, "missing @name"); - return nullopt; - } else { - name = node.name->asString(); - } - - if(node.componentHeader.has_value()) { - componentHeader = node.componentHeader->asString(); - } - - if(!node.componentDirectory) { - errors.emplace_back(node.span, "missing @componentDirectory"); - return nullopt; - } else { - componentDirectory = node.componentDirectory->asString(); - } - - header = node.header ? node.header->asString() : ""; - - libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; - - for(auto& as: node.addressSpaces) { - addressSpaces.push_back(*loadAddressSpace(as)); - } - - for(auto& comp: node.components) { - std::optional component; - component = loadComponent(comp); - if(component) { - components.push_back(*component); - } - } - - for(auto& buse : node.buses) { - auto bus = loadBus(buse); - if(bus) { - buses.push_back(*bus); - } - } - - for(auto& connection : node.connections) { - auto conn = loadConnection(connection); - if(conn) { - connections.push_back(*conn); - } - } - - for(auto & message : node.messages) { - if(!message.value.is(ValueNode::STRING)) { - errors.emplace_back(message.value.span, "expected `string`"); - } else { - messages[message.key.value] = message.value.asString(); - } - } - - return Library(name, libraryInfo, header, componentDirectory, componentHeader, addressSpaces, components, buses, connections, messages); -} - -std::optional SchemaCreator::loadBus(BusNode node) -{ - std::string name = node.name.value; - - auto count = std::make_pair(1, 1); - if(node.count) { - count = std::make_pair(node.count->first.value, node.count->second.value); - } - if(count.first > count.second || count.first < 0) { - errors.emplace_back(node.count->span, "invalid @size"); - return nullopt; - } - - auto type = toType(node.type.value); - - if(!node.tooltip && type == Bus::REGULAR) { - errors.emplace_back(node.span, "missing @tooltip"); - return nullopt; - } - std::string tooltip = node.tooltip->asString(); - - if(!node.display && type == Bus::REGULAR) { - errors.emplace_back(node.span, "missing @display"); - return nullopt; - } - if(node.display && (type == Bus::AUTOMATIC || type == Bus::SINGLE_AUTOMATIC)) { - errors.emplace_back(node.span, "automatic bus cannot have a @display"); - return nullopt; - } - - optional displayBus; - if(type == Bus::REGULAR) { - auto display = loadDisplay(*node.display); - if(!display) { - return nullopt; - } - if(display->getItems().size() != 1 || !display->getItems()[0].bus.has_value()) { - errors.emplace_back(node.span, "@display must contain only exactly one bus definition"); - return nullopt; - } - displayBus = *display->getItems()[0].bus; - } - - if(node.wires.size() == 0) { - errors.emplace_back(node.span, "missing @wires"); - return nullopt; - } - std::vector wires; - for(auto& _wire: node.wires) { - auto wire = loadWire(_wire); - if(wire) { - wires.push_back(*wire); - } - } - - if(type == Bus::SINGLE_AUTOMATIC && wires.size() != 1) { - errors.emplace_back(node.span, "singleAutomatic bus must have exactly 1 wire defined"); - return nullopt; - } - - return Bus(name, tooltip, type, count, wires, displayBus); -} - - -std::optional SchemaCreator::loadAddressSpace(AddressSpaceNode node) -{ - return AddressSpace(node.name.value, node.start.value, node.end.value); -} - -std::optional SchemaCreator::loadConnection(ConnectionNode node) -{ - push(ComdelContext("connection", false, true, false, false)); - - std::string bus = node.bus.value; - auto busInstance = getBus(bus); - if(!busInstance) { - errors.emplace_back(node.span, "bus does not exist"); - } - - if(busInstance->getType() == Bus::SINGLE_AUTOMATIC) { - current().inSingleAutomaticConnection = true; - } - - if(busInstance->getType() == Bus::REGULAR) { - ConnectionComponent first{node.first.component.value, node.first.pin.value}; - - auto componentInstance = getComponentPin(first.component, first.pin); - if(!componentInstance) { - errors.emplace_back(node.span, "pin does not exist"); - } - - if(node.second.has_value()) { - errors.emplace_back(node.span, "regular bus doesn't allow direct connections"); - } - - std::set wireNames; - for(auto &wire: busInstance->getWires()) { - wireNames.insert(wire.getName()); - current().wires.push_back(wire.getName()); - } - - std::vector attributes; - for(auto & attribute : node.attributes) { - auto attr = loadAttribute(attribute); - if(!attr) { - return nullopt; - } - attributes.push_back(*attr); - } - - std::set attributeNames; - for(auto attribute: attributes) { - attributeNames.insert(attribute.getName()); - } - - std::vector wires; - for(auto & firstWire : node.firstWires) { - if(firstWire.is(ValueNode::NIL)) { - wires.push_back(Value::fromNull()); - } else if(firstWire.is(ValueNode::INT)) { - wires.push_back(Value::fromInt(firstWire.asInt())); - } else if(firstWire.is(ValueNode::IDENTIFIER)) { - if(attributeNames.count(firstWire.asIdentifier())) { - wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE)); - } else if(wireNames.count(firstWire.asIdentifier())) { - wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE)); - } else { - errors.emplace_back(firstWire.span, "unknown identifier"); - } - } else { - errors.emplace_back(firstWire.span, "unknown value type"); - } - } - - pop(); - - return Connection(first, nullopt, bus, attributes, wires, nullopt); - } else if(busInstance->getType() == Bus::AUTOMATIC || busInstance->getType() == Bus::SINGLE_AUTOMATIC) { - ConnectionComponent first{node.first.component.value, node.first.pin.value}; - - if(!node.second.has_value()) { - errors.emplace_back(node.span, "missing second component"); - } - - ConnectionComponent second{node.second->component.value, node.second->pin.value}; - - auto firstComponentInstance = getComponentPin(first.component, first.pin); - if(!firstComponentInstance) { - errors.emplace_back(node.span, "pin does not exist"); - } - - auto secondComponentInstance = getComponentPin(second.component, second.pin); - if(!secondComponentInstance) { - errors.emplace_back(node.span, "pin does not exist"); - } - - std::set wireNames; - for(auto &wire: busInstance->getWires()) { - wireNames.insert(wire.getName()); - current().wires.push_back(wire.getName()); - } - - if(node.attributes.size() != 2 && busInstance->getType() == Bus::SINGLE_AUTOMATIC) { - errors.emplace_back(node.span, "singleAutomatic must contain 2 attributes"); - } - - std::vector attributes; - for(auto & attribute : node.attributes) { - auto attr = loadAttribute(attribute); - if(!attr) { - return nullopt; - } - attributes.push_back(*attr); - } - - std::set attributeNames; - for(auto attribute: attributes) { - attributeNames.insert(attribute.getName()); - } - - std::vector firstWires; - for(auto & firstWire : node.firstWires) { - if(firstWire.is(ValueNode::NIL)) { - firstWires.push_back(Value::fromNull()); - } else if(firstWire.is(ValueNode::INT)) { - firstWires.push_back(Value::fromInt(firstWire.asInt())); - } else if(firstWire.is(ValueNode::STRING) && busInstance->getType() == Bus::SINGLE_AUTOMATIC) { - firstWires.push_back(Value::fromString(firstWire.asString())); - } else if(firstWire.is(ValueNode::IDENTIFIER) && busInstance->getType() == Bus::AUTOMATIC) { - if(attributeNames.count(firstWire.asIdentifier())) { - firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE)); - } else if(wireNames.count(firstWire.asIdentifier())) { - firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE)); - } else { - errors.emplace_back(firstWire.span, "unknown identifier"); - } - } else { - errors.emplace_back(firstWire.span, "unsupported value type"); - } - } - - - std::vector secondWires; - for(auto & secondWire : *node.secondWires) { - if(secondWire.is(ValueNode::NIL)) { - secondWires.push_back(Value::fromNull()); - } else if(secondWire.is(ValueNode::INT)) { - secondWires.push_back(Value::fromInt(secondWire.asInt())); - } else if(secondWire.is(ValueNode::STRING) && busInstance->getType() == Bus::SINGLE_AUTOMATIC) { - secondWires.push_back(Value::fromString(secondWire.asString())); - } else if(secondWire.is(ValueNode::IDENTIFIER) && busInstance->getType() == Bus::AUTOMATIC) { - if(attributeNames.count(secondWire.asIdentifier())) { - secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE)); - } else if(wireNames.count(secondWire.asIdentifier())) { - secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::WIRE_REFERENCE)); - } else { - errors.emplace_back(secondWire.span, "unknown identifier"); - } - } else { - errors.emplace_back(secondWire.span, "unsupported value type"); - } - } - - if(busInstance->getType() == Bus::SINGLE_AUTOMATIC && attributes.size() == 2) { - if(!attributes[0].getPopup().has_value()) { - errors.emplace_back(node.attributes[0].span, "@popup is required"); - } else if(attributes[0].getDefault().getType() != Value::STRING) { - errors.emplace_back(node.attributes[0].span, "@attribute must be of type string"); - } else { - attributes[0].getPopup()->setEnumeration(createWireEnumeration(firstWires)); - } - - if(!attributes[1].getPopup().has_value()) { - errors.emplace_back(node.attributes[1].span, "@popup is required"); - } else if(attributes[1].getDefault().getType() != Value::STRING) { - errors.emplace_back(node.attributes[1].span, "@attribute must be of type string"); - } else { - attributes[1].getPopup()->setEnumeration(createWireEnumeration(secondWires)); - } - } - - pop(); - - return Connection(first, second, bus, attributes, firstWires, secondWires); - } - pop(); - errors.emplace_back(node.span, "unsupported connection type"); - - return std::nullopt; -} - -std::optional SchemaCreator::loadComponent(ComponentNode node) -{ - push(ComdelContext(node.name.value, true, false, false, false)); - - std::string name = node.name.value; - - if(!node.tooltip) { - errors.emplace_back(node.span, "missing @tooltip"); - pop(); - return nullopt; - } - std::string tooltip = node.tooltip->asString(); - - if(!node.source) { - errors.emplace_back(node.span, "missing @source"); - pop(); - return nullopt; - } - std::string source = node.source->asString(); - - Component::ComponentType type = toType(node.type.value); - - std::vector attributes; - for(auto& a: node.attributes) { - std::optional attribute = loadAttribute(a); - if(attribute) { - attributes.push_back(*attribute); - } - } - if(type == Component::PROCESSOR) { - attributes.push_back(*createMemoryAttribute()); - } - - context[context.size() -1 ].attributes = attributes; - - std::vector rules; - for(auto& r: node.rules) { - std::optional rule = loadRule(r); - if(rule) { - rules.push_back(*rule); - } - } - - if(!node.instanceName) { - errors.emplace_back(node.span, "missing @instanceName"); - pop(); - return nullopt; - } - std::string instanceName = node.instanceName->asString(); - - auto count = std::make_pair(1, 1); - if(node.count) { - count = std::make_pair(node.count->first.value, node.count->second.value); - } - if(count.first > count.second || count.first < 0) { - errors.emplace_back(node.count->first.span, "invalid @size"); - pop(); - return nullopt; - } - - if(!node.display) { - errors.emplace_back(node.span, "missing @display"); - pop(); - return nullopt; - } - optional display = loadDisplay(*node.display); - if(!display) { - pop(); - return nullopt; - } - - std::vector pins; - for(auto &p : node.pins) { - auto pin = loadPin(p); - if(!pin) { - pop(); - return nullopt; - } - pins.push_back(*pin); - } - - pop(); - return Component(name, tooltip, source, type, rules, instanceName, count, *display, pins, attributes); -} - -std::optional SchemaCreator::loadWire(WireNode node) { - return Wire( - node.name.value, - toType(node.type.value), - node.size.value, - node.hidden, - node.hasTerminateWith, - toType(node.terminateWith) - ); -} - -optional SchemaCreator::loadPin(PinNode node) -{ - std::string name = node.name.value; - Pin::PinType type = toType(node.type.value); - - if(!node.tooltip) { - errors.emplace_back(node.span, "missing @tooltip"); - return nullopt; - } - std::string tooltip = node.tooltip->asString(); - - if(!node.display) { - errors.emplace_back(node.span, "missing @display"); - return nullopt; - } - std::vector attributes; - optional display = loadDisplay(*node.display); - if(!display) { - return nullopt; - } - if(display->getItems().size() != 1 || !display->getItems()[0].pin.has_value()) { - errors.emplace_back(node.span, "@display must contain only exactly one pin definition"); - return nullopt; - } - ui::Pin displayPin = *display->getItems()[0].pin; - - - if(!node.connection) { - errors.emplace_back(node.span, "missing @connection"); - return nullopt; - } - auto connection = loadPinConnection(*node.connection); - - std::optional> wiresOpt = std::nullopt; - if(node.wires.has_value()) { - auto nodeWires = node.wires.value(); - std::vector wires; - for(auto &nodeWire : nodeWires) { - if(nodeWire.is(ValueNode::NIL)) { - wires.push_back(Value::fromNull()); - } else if(nodeWire.is(ValueNode::INT)) { - wires.push_back(Value::fromInt(nodeWire.asInt())); - } else { - errors.emplace_back(node.span, "unknown value type"); - } - } - wiresOpt = wires; - } - - return Pin(name, type, tooltip, connection, displayPin, wiresOpt); -} - -std::optional SchemaCreator::loadDisplay(DisplayNode node) -{ - std::vector items; - for(auto &item: node.items) { - ui::Item displayItem; - std::string type = item.type.value; - if(type == "rect") { - long long int x, y, w, h; - x = item.asInt(&errors, "x"); - y = item.asInt(&errors, "y"); - w = item.asInt(&errors, "w"); - h = item.asInt(&errors, "h"); - displayItem.rect = ui::Rect(x, y, w, h); - } else if(type == "line") { - long long int x1, y1, x2, y2; - x1 = item.asInt(&errors, "x1"); - y1 = item.asInt(&errors, "y1"); - x2 = item.asInt(&errors, "x2"); - y2 = item.asInt(&errors, "y2"); - displayItem.line = ui::Line(x1, y1, x2, y2); - } else if(type == "pin") { - long long int x, y, w, h; - x = item.asInt(&errors, "x"); - y = item.asInt(&errors, "y"); - w = item.asInt(&errors, "w"); - h = item.asInt(&errors, "h"); - std::string _orientation = item.asString(&errors, "orientation", "bottom"); - std::string _pinType = item.asString(&errors, "type", "out"); - - ui::PinOrientation orientation; - if(_orientation == "left") { - orientation = ui::PinOrientation::LEFT; - } else if(_orientation == "right") { - orientation = ui::PinOrientation::RIGHT; - } else if(_orientation == "top") { - orientation = ui::PinOrientation::TOP; - } else if(_orientation == "bottom") { - orientation = ui::PinOrientation::BOTTOM; - } else { - errors.emplace_back(item.span, "unknown pin orientation type '" + _orientation + "'"); - } - - ui::PinType pinType; - if(_pinType == "in") { - pinType = ui::PinType::IN; - } else if(_pinType == "out") { - pinType = ui::PinType::OUT; - } else if(_pinType == "in_out") { - pinType = ui::PinType::IN_OUT; - } else { - errors.emplace_back(item.span, "unknown pin type '" + _pinType + "'"); - } - - displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType); - } else if(type == "bus") { - long long int x, y, w, h; - x = item.asInt(&errors, "x"); - y = item.asInt(&errors, "y"); - w = item.asInt(&errors, "w"); - h = item.asInt(&errors, "h"); - std::string _orientation = item.asString(&errors, "orientation", "bottom"); - - ui::BusOrientation orientation; - if(_orientation == "horizontal") { - orientation = ui::BusOrientation::HORIZONTAL; - } else if(_orientation == "vertical") { - orientation = ui::BusOrientation::VERTICAL; - } else { - errors.emplace_back(item.span, "unknown bus orientation type '" + _orientation + "'"); - } - - displayItem.bus = ui::Bus(x, y, w, h, orientation); - } else { - errors.emplace_back(item.type.span, "unsupported display type"); - } - items.push_back(displayItem); - } - return Display(items); -} - - -PinConnection SchemaCreator::loadPinConnection(PinConnectionNode node) -{ - std::string message = node.message.asString(); - PinConnection::ConnectionType type = toType(node.type.value); - return {message, type}; -} - -std::optional SchemaCreator::loadAttribute(AttributeNode node) -{ - std::string name = node.name.value; - pushAdditional(name); - Value value; - - if(current().inComponent) { - if(node.type == ValueNode::INT) { - value = Value::fromInt(node.defaultValue->asInt()); - } else if (node.type == ValueNode::BOOL) { - value = Value::fromBool(node.defaultValue->asBool()); - } else if (node.type == ValueNode::STRING) { - value = Value::fromString(node.defaultValue->asString()); - } else { - errors.emplace_back(node.name.span, "unsupported type"); - } - } - if(current().inConnection && !current().inSingleAutomaticConnection) { // TODO remove identifier - if (node.type == ValueNode::WIRE || node.type == ValueNode::IDENTIFIER) { - if(current().doesWireExists(node.defaultValue->asIdentifier())) { - value = Value::fromReference(node.defaultValue->asIdentifier(), Value::WIRE_REFERENCE); - } else { - value = Value::fromReference("", Value::WIRE_REFERENCE); - errors.emplace_back(node.span, "unknown identifier"); - } - } else { - errors.emplace_back(node.name.span, "unsupported type"); - } - } - if(current().inSingleAutomaticConnection) { - if (node.type == ValueNode::STRING) { - value = Value::fromString(node.defaultValue->asString()); - } else { - errors.emplace_back(node.name.span, "unsupported type"); - } - } - - current().attributes.emplace_back(name, value); - - std::optional popup; - if(node.popup) { - popup = loadPopup(*node.popup, name, value.getType()); - } - - pop(); - return Attribute(name, value, popup); -} - -std::optional SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type) -{ - auto popupType = toType(node.type.value().value); - - pushAdditional(name); - - current().attributes.clear(); - current().attributes.emplace_back(name, Value::ofType(type)); - - if(!node.title) { - errors.emplace_back(node.span, "missing @title"); - return nullopt; - } - std::string title = node.title->asString(); - - if(!node.text) { - errors.emplace_back(node.span, "missing @text"); - return nullopt; - } - std::string text = node.text->asString(); - - std::vector rules; - for(auto& r: node.rules) { - std::optional rule = loadRule(r); - if(rule) { - rules.push_back(*rule); - } - } - - std::vector enumeration; - if(node.enumerated) { - for(auto& enumNode : node.enumeration) { - if(type == Value::INT || type == Value::STRING || type == Value::BOOL) { - auto value = toType(enumNode.value); - if(value.getType() == type) { - enumeration.emplace_back(enumNode.key.asString(), value); - } else { - errors.emplace_back(enumNode.span, "wrong type"); - } - } else if(type == Value::WIRE_REFERENCE) { - auto value = toType(enumNode.value); - if(value.isType(Value::UNDEFINED)) { - if(current().doesWireExists(value.asReference())) { - value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE); - } else { - errors.emplace_back(enumNode.span, "unknown wire"); - } - } - - if(value.isType(Value::WIRE_REFERENCE) || value.isType(Value::INT) || value.isType(Value::NIL)) { - enumeration.emplace_back(enumNode.key.asString(), value); - } else { - errors.emplace_back(enumNode.span, "wrong type"); - } - } - } - } else { - if(type == Value::WIRE_REFERENCE && !current().inConnection) { - errors.emplace_back(node.span, "@enumeration is required for attributes of type wire"); - } - } - - pop(); - - return Popup(title, text, popupType, rules, enumeration); -} - -std::optional SchemaCreator::loadRule(RuleNode node) -{ - std::vector statements; - - for(auto& stmt: node.statements) { - auto condition = loadCondition(stmt.condition); - if(condition) { - statements.emplace_back(*condition, Action(toType(stmt.action.type.value), stmt.action.message.asString())); - } else { - return nullopt; - } - } - - return Rule(statements); -} - -std::optional SchemaCreator::loadCondition(ConditionNode node) -{ - std::string function = node.functionName.value; - - for(auto & validator : validators) { - if(validator->getName() == function) { - if(validator->getSignature().size() == node.params.size()) { - std::vector params; - for(uint j=0; jgetSignature().size(); j++) { - bool exists = false; - auto type = toType(node.params[j]); - if (type.getType() == Value::UNDEFINED) { - if(current().doesAttributeExists(type.asReference(), validator->getSignature()[j])) { - exists = true; - type = Value::fromReference(type.asReference(), Value::ATTRIBUTE_REFERENCE); - } - if(validator->getSignature()[j] == Value::ADDRESS_SPACE) { - if(hasAddressSpace(type.asReference())) { - exists = true; - type = Value::fromReference(type.asReference(), Value::ADDRESS_SPACE_REFERENCE); - } - } - - if(!exists) { - errors.emplace_back(node.functionName.span, "unknown reference " + type.asReference()); - } - } - params.push_back(type); - } - return Condition(function, params, node.negated); - } else { - errors.emplace_back(node.functionName.span, "wrong number of parameters"); - } - } - } - - errors.emplace_back(node.functionName.span, "unknown function name"); - return nullopt; -} - - -Schema* SchemaCreator::loadSchema(SchemaNode node, Library &library) -{ - auto *schema = new Schema(); - - for(auto &instance: node.instances) { - if(library.hasComponent(instance.component.value)) { - schema->componentInstances.push_back(loadComponentInstance(instance, library)); - } - if(library.hasBus(instance.component.value)) { - schema->busInstances.push_back(loadBusInstance(instance, library)); - } - } - - for(auto &conn: node.connections) { - auto firstComponent = schema->getComponentInstance(conn.first.instance.value); - if(firstComponent == nullptr) { - errors.emplace_back(conn.first.instance.span, "unknown component"); - continue; - } - if(!firstComponent->component.hasPin(conn.first.pin.value)) { - errors.emplace_back(conn.first.pin.span, "unknown pin"); - continue; - } - - - ComponentInstance *secondComponent = nullptr; - if(conn.second.has_value()) { - secondComponent = schema->getComponentInstance(conn.second->instance.value); - if(secondComponent == nullptr) { - errors.emplace_back(conn.second->instance.span, "unknown component"); - continue; - } - if(!secondComponent->component.hasPin(conn.second->pin.value)) { - errors.emplace_back(conn.second->pin.span, "unknown pin"); - continue; - } - } - - auto bus = schema->getBusInstance(conn.bus.value); - if(bus == nullptr) { - errors.emplace_back(conn.bus.span, "unknown bus"); - continue; - } - - std::optional connection = std::nullopt; - if(secondComponent != nullptr) { - ConnectionComponent firstConn{firstComponent->component.getName(), conn.first.pin.value}; - ConnectionComponent secondConn{secondComponent->component.getName(), conn.second->pin.value}; - - if(library.hasConnection(firstConn, - bus->bus.getName(), - secondConn)) { - connection = *library.getConnection(firstConn, bus->bus.getName(), secondConn); - } else { - errors.emplace_back(conn.span, "unknown connection"); - continue; - } - } else { - ConnectionComponent firstConn{firstComponent->component.getName(), conn.first.pin.value}; - - if(library.hasConnection(firstConn, - bus->bus.getName())) { - connection = *library.getConnection(firstConn, bus->bus.getName()); - } else { - errors.emplace_back(conn.span, "unknown connection"); - continue; - } - } - - std::vector attributes; - for(auto& attr: conn.attributes) { - if(connection->hasAttribute(attr.name.value)) { - auto attribute = connection->getAttribute(attr.name.value); - auto value = toType(attr.value); - - for(auto& en: attribute.getPopup()->getEnumeration()) { - if(en.getValue().asReference() == value.asReference()) { - value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE); - } - } - if(value.isType(Value::UNDEFINED)) { - errors.emplace_back(attr.span, "invalid value"); - } - - attributes.emplace_back(attribute.getName(), toType(attr.value), attribute); - } else { - errors.emplace_back(attr.name.span, "unknown attribute"); - } - } - - if(secondComponent == nullptr) { - schema->connections.push_back(std::make_shared(firstComponent, attributes, bus, *connection)); - } else { - schema->connections.push_back(std::make_shared(firstComponent, secondComponent, attributes, bus, *connection)); - } - } - - return schema; -} - -shared_ptr SchemaCreator::loadComponentInstance(InstanceNode instance, Library &library) { - - auto name = instance.name.value; - auto position = std::make_pair(instance.position->first.value, instance.position->second.value); - - auto component = library.getComponent(instance.component.value); - - // validate attributes - std::vector attributes; - for(auto& attr: instance.attributes) { - if(component.hasAttribute(attr.name.value, toType(attr.value.getType()))) { - auto attribute = component.getAttribute(attr.name.value); - attributes.emplace_back(attribute.getName(), toType(attr.value, attribute.getDefault().getType()), attribute); - } else { - errors.emplace_back(SourceError(attr.name.span, "unknown attribute")); - } - } - - if(attributes.size() < component.getAttributes().size()) { - for(auto& attr: component.getAttributes()) { - if(std::count_if(attributes.begin(), attributes.end(), [&attr](InstanceAttribute& attribute){ return attr.getName() == attribute.name; }) == 0) { - errors.emplace_back(SourceError(instance.span, "missing attribute '" + attr.getName() + "'")); - } - } - } - - return std::make_shared(name, attributes, position, component); -} -std::shared_ptr SchemaCreator::loadBusInstance(InstanceNode instance, Library &library) { - - auto name = instance.name.value; - auto position = std::make_pair(instance.position->first.value, instance.position->second.value); - - auto bus = library.getBus(instance.component.value); - - long long size = 0; - if(instance.size) { - size = instance.size->value; - } - - return std::make_shared(name, position, bus, static_cast(size)); -} - -vector SchemaCreator::createWireEnumeration(vector wireValues) { - vector wires; - for(auto& wire: wireValues) { - if(wire.isType(Value::STRING)) { - wires.emplace_back(wire.asString(), wire); - } - } - return wires; -} - -std::optional SchemaCreator::createMemoryAttribute() { - return Attribute("_memory", Value::fromMemoryReference(std::nullopt), createMemoryPopup()); -} - - std::optional SchemaCreator::createMemoryPopup() { - return Popup("Postavi memoriju", "Postavi memoriju za izabrani procesor", Popup::AUTOMATIC, vector{}, vector{}); - } - -} // namespace domain diff --git a/comdel/domain/schemacreator.h b/comdel/domain/schemacreator.h deleted file mode 100644 index 5c66650..0000000 --- a/comdel/domain/schemacreator.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef DOMAIN_COMDEL_GENERATOR_H -#define DOMAIN_COMDEL_GENERATOR_H - -#include "library.h" -#include "schema.h" - -#include - -#include -#include -#include - -namespace domain { - -struct ComdelContext { - std::vector attributes; - std::vector wires; - std::string name; - bool inComponent; - bool inConnection; - bool inSingleAutomaticConnection; - bool inBus; - - ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus) - : name(name), inComponent(inComponent), inConnection(inConnection), inSingleAutomaticConnection(inSingleAutomaticConnection), inBus(inBus) - {} - - bool doesAttributeExists(std::string name, Value::ValueType type) { - for(auto &attribute: attributes) { - if(attribute.getDefault().getType() == type && attribute.getName() == name) { - return true; - } - } - return false; - } - - bool doesWireExists(std::string name) { - for(auto &w: wires) { - if(w == name) { - return true; - } - } - return false; - } - -}; - -class SchemaCreator -{ - std::vector context; - - std::string name; - std::string libraryInfo; - std::string header; - std::string componentDirectory; - std::optional componentHeader = nullopt; - std::vector addressSpaces; - std::vector components; - std::vector buses; - std::vector connections; - std::map messages; - - - std::vector errors; - std::vector validators; - - std::optional loadAddressSpace(AddressSpaceNode node); - std::optional loadComponent(ComponentNode node); - std::optional loadAttribute(AttributeNode node); - std::optional loadRule(RuleNode node); - std::optional loadCondition(ConditionNode node); - std::optional loadPopup(PopupNode node, std::string name, Value::ValueType type); - std::optional loadDisplay(DisplayNode node); - std::optional loadWire(WireNode node); - std::optional loadPin(PinNode pins); - PinConnection loadPinConnection(PinConnectionNode node); - std::optional loadConnection(ConnectionNode node); - std::optional loadBus(BusNode node); - - std::shared_ptr loadComponentInstance(InstanceNode instance, Library &library); - std::shared_ptr loadBusInstance(InstanceNode instance, Library &library); - - std::optional createMemoryAttribute(); - - std::optional getBus(std::string name) { - for(auto &bus: buses) { - if(bus.getName() == name) { - return bus; - } - } - return std::nullopt; - } - - std::optional getComponentPin(std::string name, std::string pin) { - for(auto &c: components) { - if(c.getName() == name) { - for(auto &p: c.getPins()) { - if(p.getName() == pin) { - return p; - } - } - } - } - return nullopt; - } - - bool hasAddressSpace(std::string name) { - for(auto &as: addressSpaces) { - if(as.getName() == name) { - return true; - } - } - return false; - } - - void push(ComdelContext context) { - this->context.push_back(context); - } - void pushAdditional(std::string name) { - if(!this->context.empty()) { - this->context.push_back(current()); - current().name = name; - } else { - ComdelContext con(name, false, false, false, false); - push(con); - } - } - ComdelContext ¤t() { - return this->context[this->context.size() - 1]; - } - void pop() { - this->context.pop_back(); - } - -public: - SchemaCreator(std::vector validators); - - std::vector getErrors() { - return errors; - } - - std::optional loadLibrary(LibraryNode node); - - Schema* loadSchema(SchemaNode node, Library &library); - - vector createWireEnumeration(vector vector1); - - std::optional createMemoryPopup(); -}; - -} // namespace domain - -#endif // DOMAIN_COMDEL_GENERATOR_H diff --git a/comdel/domain/value.cpp b/comdel/domain/value.cpp index 805342f..c5d0914 100644 --- a/comdel/domain/value.cpp +++ b/comdel/domain/value.cpp @@ -4,173 +4,160 @@ namespace domain { -std::string Value::string() { - switch (type) { - case INT: - return std::to_string(intValue); - case BOOL: - return boolValue ? "true" : "false"; - case STRING: + std::string Value::string() { + switch (type) { + case INT: + return std::to_string(intValue); + case BOOL: + return boolValue ? "true" : "false"; + case STRING: + return stringValue; + case NIL: + return "null"; + case UNDEFINED: + return "undefined"; + case ADDRESS_SPACE: + return "AddressSpace::" + addressSpace->getName(); + case WIRE_REFERENCE: + return "Wire::" + reference; + case ADDRESS_SPACE_REFERENCE: + return "AddressSpace::" + reference; + case ATTRIBUTE_REFERENCE: + return "Attribute::" + reference; + case MEMORY_REFERENCE: + if (memoryReference.has_value()) { + return "Memory::" + *memoryReference; + } else { + return "Memory::null"; + } + default: + return "unknown"; + } + } + + + Value::ValueType Value::getType() { + return type; + } + + bool Value::isType(Value::ValueType _type) { + return type == _type; + } + + long long Value::asInt() { + if (isType(Value::INT)) { + return intValue; + } + throw std::exception(); + } + + std::string Value::asString() { + if (isType(Value::STRING)) { return stringValue; - case NIL: - return "null"; - case UNDEFINED: - return "undefined"; - case ADDRESS_SPACE: - return "AddressSpace::" + addressSpace->getName(); - case WIRE_REFERENCE: - return "Wire::" + reference; - case ADDRESS_SPACE_REFERENCE: - return "AddressSpace::" + reference; - case ATTRIBUTE_REFERENCE: - return "Attribute::" + reference; - default: - return "unknown"; + } + throw std::exception(); } -} + bool Value::asBool() { + if (isType(Value::BOOL)) { + return boolValue; + } + throw std::exception(); + } -Value::ValueType Value::getType() { - return type; -} -bool Value::isType(Value::ValueType type) { - return this->type == type; -} + AddressSpace Value::asAddressSpace() { + if (isType(Value::ADDRESS_SPACE)) { + return *addressSpace; + } + throw std::exception(); + } -long long Value::asInt() { - if(isType(Value::INT)) { - return intValue; + std::string Value::asReference() { + if (isType(Value::WIRE_REFERENCE) || isType(Value::ADDRESS_SPACE_REFERENCE) || + isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) { + return reference; + } + throw std::exception(); } - throw std::exception(); -} -std::string Value::asString() { - if(isType(Value::STRING)) { - return stringValue; - } - throw std::exception(); -} -bool Value::asBool() { - if(isType(Value::BOOL)) { - return boolValue; - } - throw std::exception(); -} -AddressSpace Value::asAddressSpace() { - if(isType(Value::ADDRESS_SPACE)) { - return *addressSpace; - } - throw std::exception(); -} -std::string Value::asReference() { - if(isType(Value::WIRE_REFERENCE) || isType(Value::ADDRESS_SPACE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) { - return reference; - } - throw std::exception(); -} - -std::optional Value::asMemoryReference() { - return memoryReference; -} + std::optional Value::asMemoryReference() { + return memoryReference; + } domain::ComponentInstance *Value::asMemory() { return memory; } -void Value::setInt(long long value) { - if(isType(Value::INT)) { - this->intValue = value; + void Value::setInt(long long value) { + if (isType(Value::INT)) { + this->intValue = value; + } + throw std::exception(); } - throw std::exception(); -} -void Value::setString(std::string value) { - if(isType(Value::STRING)) { - this->stringValue = value; + + void Value::setString(std::string value) { + if (isType(Value::STRING)) { + this->stringValue = value; + } + throw std::exception(); } - throw std::exception(); -} -void Value::setBool(bool value) { - if(isType(Value::BOOL)) { - this->boolValue = value; + + void Value::setBool(bool value) { + if (isType(Value::BOOL)) { + this->boolValue = value; + } + throw std::exception(); } - throw std::exception(); -} -void Value::setReference(std::string value) { - if(isType(Value::WIRE_REFERENCE)) { - this->reference = value; + + void Value::setReference(std::string value) { + if (isType(Value::WIRE_REFERENCE)) { + this->reference = value; + } + throw std::exception(); } - throw std::exception(); -} -Value Value::fromInt(long long value) { - Value val; - val.type = Value::INT; - val.intValue = value; - return val; -} -Value Value::fromString(std::string value) { - Value val; - val.type = Value::STRING; - val.stringValue = value; - return val; -} -Value Value::fromBool(bool value) { - Value val; - val.type = Value::BOOL; - val.boolValue = value; - return val; -} -Value Value::fromAddressSpace(AddressSpace addressSpace) { - Value val; - val.type = Value::ADDRESS_SPACE; - val.addressSpace = addressSpace; - return val; -} -Value Value::fromReference(std::string value, Value::ValueType type) { - Value val; - val.type = type; - val.reference = value; - return val; -} - -Value Value::ofType(Value::ValueType type) { - Value val; - val.type = type; - return val; -} - -Value Value::fromNull() { - Value val; - val.type = Value::NIL; - return val; -} - -std::string Value::stringify() { - switch (type) { - case INT: - return std::to_string(intValue); - case BOOL: - return boolValue ? "true" : "false"; - case STRING: - return "\"" + stringValue + "\""; - case NIL: - return "null"; - case WIRE_REFERENCE: - case ADDRESS_SPACE_REFERENCE: - case ATTRIBUTE_REFERENCE: - return reference; - case MEMORY_REFERENCE: - if(memoryReference.has_value()) { - return memoryReference.value(); - } else { - return "null"; - } - default: - throw std::exception(); + Value Value::fromInt(long long value) { + Value val; + val.type = Value::INT; + val.intValue = value; + return val; + } + + Value Value::fromString(std::string value) { + Value val; + val.type = Value::STRING; + val.stringValue = value; + return val; + } + + Value Value::fromBool(bool value) { + Value val; + val.type = Value::BOOL; + val.boolValue = value; + return val; + } + + Value Value::fromAddressSpace(AddressSpace addressSpace) { + Value val; + val.type = Value::ADDRESS_SPACE; + val.addressSpace = addressSpace; + return val; + } + + Value Value::fromReference(std::string value, Value::ValueType type) { + Value val; + val.type = type; + val.reference = value; + return val; + } + + Value Value::fromNull() { + Value val; + val.type = Value::NIL; + return val; } -} Value Value::fromMemoryReference(std::optional value) { Value val; @@ -179,10 +166,34 @@ std::string Value::stringify() { return val; } - Value Value::fromMemory(domain::ComponentInstance *memory) { + std::string Value::stringify() { + switch (type) { + case INT: + return std::to_string(intValue); + case BOOL: + return boolValue ? "true" : "false"; + case STRING: + return "\"" + stringValue + "\""; + case NIL: + return "null"; + case WIRE_REFERENCE: + case ADDRESS_SPACE_REFERENCE: + case ATTRIBUTE_REFERENCE: + return reference; + case MEMORY_REFERENCE: + if (memoryReference.has_value()) { + return memoryReference.value(); + } else { + return "null"; + } + default: + throw std::exception(); + } + } + + Value Value::ofType(Value::ValueType type) { Value val; - val.type = MEMORY; - val.memory = memory; + val.type = type; return val; } diff --git a/comdel/domain/value.h b/comdel/domain/value.h index c011ef4..70f7807 100644 --- a/comdel/domain/value.h +++ b/comdel/domain/value.h @@ -1,7 +1,7 @@ #ifndef DOMAIN_VALUE_H #define DOMAIN_VALUE_H -#include "addressspace.h" +#include "address_space.h" #include #include @@ -11,96 +11,111 @@ namespace domain { class ComponentInstance; -class Value -{ -public: - enum ValueType { - INT, - STRING, - BOOL, - ADDRESS_SPACE, - ADDRESS_SPACE_REFERENCE, - ATTRIBUTE_REFERENCE, - MEMORY_REFERENCE, - MEMORY, - WIRE_REFERENCE, - NIL, - UNDEFINED, - }; + class Value { + public: + enum ValueType { + INT, + STRING, + BOOL, + ADDRESS_SPACE, + ADDRESS_SPACE_REFERENCE, + ATTRIBUTE_REFERENCE, + MEMORY_REFERENCE, + MEMORY, + WIRE_REFERENCE, + NIL, + UNDEFINED, + }; -private: - long long intValue = 0; - std::string stringValue; - bool boolValue = false; - std::optional addressSpace = std::nullopt; - std::string reference; - domain::ComponentInstance *memory = nullptr; + private: + long long intValue = 0; + std::string stringValue; + bool boolValue = false; + std::optional addressSpace = std::nullopt; + std::string reference; + domain::ComponentInstance *memory = nullptr; - std::optional memoryReference = std::nullopt; + std::optional memoryReference = std::nullopt; - ValueType type = UNDEFINED; + ValueType type = UNDEFINED; -public: + public: - Value() {} + Value() = default; - bool equals(Value value) { - if(value.getType() == type) { - switch (type) { - case INT: - return value.asInt() == intValue; - case STRING: - return value.asString() == stringValue; - case NIL: - case UNDEFINED: - return true; - case WIRE_REFERENCE: - case ATTRIBUTE_REFERENCE: - case ADDRESS_SPACE_REFERENCE: - return value.asReference() == reference; - case MEMORY_REFERENCE: - return value.asMemoryReference() == memoryReference; - case MEMORY: - return value.asMemory() == memory; - case BOOL: - return value.asBool() == boolValue; - default: - return false; + bool equals(Value value) { + if (value.getType() == type) { + switch (type) { + case INT: + return value.asInt() == intValue; + case STRING: + return value.asString() == stringValue; + case NIL: + case UNDEFINED: + return true; + case WIRE_REFERENCE: + case ATTRIBUTE_REFERENCE: + case ADDRESS_SPACE_REFERENCE: + return value.asReference() == reference; + case MEMORY_REFERENCE: + return value.asMemoryReference() == memoryReference; + case MEMORY: + return value.asMemory() == memory; + case BOOL: + return value.asBool() == boolValue; + default: + return false; + } } + return false; } - return false; - } - std::string string(); + std::string string(); - ValueType getType(); - bool isType(ValueType type); + ValueType getType(); - long long asInt(); - std::string asString(); - bool asBool(); - std::string asReference(); - std::optional asMemoryReference(); - domain::ComponentInstance* asMemory(); - AddressSpace asAddressSpace(); + bool isType(ValueType type); - void setInt(long long intValue); - void setString(std::string value); - void setBool(bool value); - void setReference(std::string value); + long long asInt(); - std::string stringify(); + std::string asString(); - static Value fromInt(long long value); - static Value fromString(std::string value); - static Value fromBool(bool value); - static Value fromNull(); - static Value fromAddressSpace(AddressSpace addressSpace); - static Value fromReference(std::string value, ValueType type); - static Value ofType(ValueType type); - static Value fromMemoryReference(std::optional memoryReference); - static Value fromMemory(domain::ComponentInstance *memory); -}; + bool asBool(); + + std::string asReference(); + + std::optional asMemoryReference(); + + domain::ComponentInstance *asMemory(); + + AddressSpace asAddressSpace(); + + void setInt(long long intValue); + + void setString(std::string value); + + void setBool(bool value); + + void setReference(std::string value); + + std::string stringify(); + + static Value fromInt(long long value); + + static Value fromString(std::string value); + + static Value fromBool(bool value); + + static Value fromNull(); + + static Value fromAddressSpace(AddressSpace addressSpace); + + static Value fromReference(std::string value, ValueType type); + + static Value fromMemoryReference(std::optional memoryReference); + + static Value ofType(ValueType type); + }; } // namespace domain diff --git a/comdel/domain/wireinstance.cpp b/comdel/domain/wireinstance.cpp deleted file mode 100644 index 88cb7b0..0000000 --- a/comdel/domain/wireinstance.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "wireinstance.h" - -namespace domain { - -WireInstance::WireInstance(std::string name, Display display, std::pair position) - : name(name), display(display), position(position) -{} - - -} // namespace domain diff --git a/comdel/domain/wireinstance.h b/comdel/domain/wireinstance.h deleted file mode 100644 index 5a24e55..0000000 --- a/comdel/domain/wireinstance.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DOMAIN_WIRE_INSTANCE_H -#define DOMAIN_WIRE_INSTANCE_H - -#include "display.h" - -#include - - - -namespace domain { - -class WireInstance -{ -public: - std::string name; - Display display; - std::pair position; - - WireInstance(std::string name, Display display, std::pair position); -}; - -} // namespace domain - -#endif // DOMAIN_WIREINSTANCE_H diff --git a/comdel/parser/astnode.cpp b/comdel/parser/ast_nodes.cpp similarity index 79% rename from comdel/parser/astnode.cpp rename to comdel/parser/ast_nodes.cpp index a833331..3f3edeb 100644 --- a/comdel/parser/astnode.cpp +++ b/comdel/parser/ast_nodes.cpp @@ -1,4 +1,4 @@ -#include "astnode.h" +#include "ast_nodes.h" /*************************** AST NODE ********************************/ @@ -6,17 +6,17 @@ AstNode::~AstNode() = default; /*************************** NUMBER NODE ********************************/ -NumberNode::NumberNode(const std::string& expression) { - if(expression.size() > 2) { - if(expression.substr(0, 2) == "0x") { - this->value = std::stoll(expression, 0, 16); - } else if(expression.substr(0, 2) == "0b") { - this->value = std::stoll(expression, 0, 2); +NumberNode::NumberNode(const std::string &expression) { + if (expression.size() > 2) { + if (expression.substr(0, 2) == "0x") { + this->value = std::stoll(expression, nullptr, 16); + } else if (expression.substr(0, 2) == "0b") { + this->value = std::stoll(expression, nullptr, 2); } else { - this->value = std::stoll(expression, 0, 10); + this->value = std::stoll(expression, nullptr, 10); } } else { - this->value = std::stoll(expression, 0, 10); + this->value = std::stoll(expression, nullptr, 10); } } @@ -29,28 +29,28 @@ std::string StringNode::asString() { /*************************** VALUE NODE ********************************/ long long ValueNode::asInt() { - if(is(INT)) { + if (is(INT)) { return intValue.value(); } return 0; } std::string ValueNode::asString() { - if(is(STRING)) { + if (is(STRING)) { return stringValue.value(); } return ""; } std::string ValueNode::asIdentifier() { - if(is(IDENTIFIER) || is(WIRE)) { + if (is(IDENTIFIER) || is(WIRE)) { return identifierValue.value(); } return ""; } bool ValueNode::asBool() { - if(is(BOOL)) { + if (is(BOOL)) { return boolValue.value(); } return false; diff --git a/comdel/parser/astnode.h b/comdel/parser/ast_nodes.h similarity index 70% rename from comdel/parser/astnode.h rename to comdel/parser/ast_nodes.h index 54cd2be..65f82ad 100644 --- a/comdel/parser/astnode.h +++ b/comdel/parser/ast_nodes.h @@ -2,8 +2,9 @@ #define AST_NODE_H #include "token.h" -#include "sourceerror.h" +#include "source_error.h" #include +#include #include /** @@ -19,58 +20,60 @@ public: virtual ~AstNode(); - AstNode(AstNode&&) = default; - AstNode& operator=(AstNode&&) = default; - AstNode(const AstNode&) = default; - AstNode& operator=(const AstNode&) = default; + AstNode(AstNode &&) = default; + + AstNode &operator=(AstNode &&) = default; + + AstNode(const AstNode &) = default; + + AstNode &operator=(const AstNode &) = default; }; -template -struct EnumNode: public AstNode -{ +template +struct EnumNode : public AstNode { EnumNode() = default; - explicit EnumNode(T value): value(value) {} + + explicit EnumNode(T value) : value(value) {} T value; }; -struct StringNode: public AstNode -{ +struct StringNode : public AstNode { std::string value; + std::string asString(); }; -struct IdentifierNode: public AstNode -{ +struct IdentifierNode : public AstNode { std::string value; }; -struct NumberNode: public AstNode { +struct NumberNode : public AstNode { long long int value; - explicit NumberNode(const std::string& expression); - NumberNode(): value(0) {} + + explicit NumberNode(const std::string &expression); + + NumberNode() : value(0) {} }; -struct CountNode: public AstNode -{ +struct CountNode : public AstNode { NumberNode first; NumberNode second; - CountNode(NumberNode first, NumberNode second): first(first), second(second) {} + CountNode(NumberNode first, NumberNode second) : first(std::move(first)), second(std::move(second)) {} + CountNode() = default; }; -struct AddressSpaceNode: public AstNode -{ +struct AddressSpaceNode : public AstNode { IdentifierNode name; NumberNode start; NumberNode end; }; -class ValueNode: public AstNode -{ +class ValueNode : public AstNode { public: enum ValueType { INT, @@ -92,33 +95,42 @@ private: public: ValueNode() = default; - ValueType getType() { + ValueType getType() const { return type.value; } + long long asInt(); + std::string asString(); + std::string asIdentifier(); + bool asBool(); bool is(ValueType valueType); static ValueNode ofBool(bool _value); + static ValueNode ofInt(long long _value); + static ValueNode ofString(std::string _value); + static ValueNode ofIdentifier(std::string _value); + static ValueNode ofMemory(std::optional _value); + static ValueNode ofNull(); + static ValueNode ofWire(std::optional _value); }; -struct ConditionNode -{ +struct ConditionNode { bool negated; IdentifierNode functionName; std::vector params; }; -class ActionNode: public AstNode { +class ActionNode : public AstNode { public: enum ActionType { ERROR, @@ -130,25 +142,21 @@ public: }; -struct IfStatementNode: public AstNode -{ +struct IfStatementNode : public AstNode { ConditionNode condition; ActionNode action; }; -struct RuleNode: public AstNode -{ +struct RuleNode : public AstNode { std::vector statements; }; -struct EnumerationNode: public AstNode -{ +struct EnumerationNode : public AstNode { StringNode key; ValueNode value; }; -struct PopupNode: public AstNode -{ +struct PopupNode : public AstNode { enum PopupType { AUTOMATIC, ON_DEMAND @@ -164,24 +172,22 @@ struct PopupNode: public AstNode std::vector rules; }; -struct PropertyNode: public AstNode -{ +struct PropertyNode : public AstNode { IdentifierNode key; ValueNode value; }; -struct DisplayItemNode: public AstNode -{ +struct DisplayItemNode : public AstNode { IdentifierNode type; std::vector values; - long long int asInt(std::vector* errors, const std::string& property, long long int _default = 0) { - for(auto& prop: values) { - if(prop.key.value == property) { - if(prop.value.is(ValueNode::INT)) { + long long int asInt(std::vector *errors, const std::string &property, long long int _default = 0) { + for (auto &prop: values) { + if (prop.key.value == property) { + if (prop.value.is(ValueNode::INT)) { return prop.value.asInt(); } else { - if(errors != nullptr) { + if (errors != nullptr) { errors->emplace_back(prop.value.span, "expected number"); } } @@ -190,13 +196,13 @@ struct DisplayItemNode: public AstNode return _default; } - std::string asIdentifier(std::vector* errors, const std::string& property, std::string _default = "") { - for(auto& prop: values) { - if(prop.key.value == property) { - if(prop.value.is(ValueNode::IDENTIFIER)) { + std::string asIdentifier(std::vector *errors, const std::string &property, std::string _default = "") { + for (auto &prop: values) { + if (prop.key.value == property) { + if (prop.value.is(ValueNode::IDENTIFIER)) { return prop.value.asIdentifier(); } else { - if(errors != nullptr) { + if (errors != nullptr) { errors->emplace_back(prop.value.span, "expected identifier"); } } @@ -206,13 +212,13 @@ struct DisplayItemNode: public AstNode } - std::string asString(std::vector* errors, const std::string& property, std::string _default = "") { - for(auto& prop: values) { - if(prop.key.value == property) { - if(prop.value.is(ValueNode::STRING)) { + std::string asString(std::vector *errors, const std::string &property, std::string _default = "") { + for (auto &prop: values) { + if (prop.key.value == property) { + if (prop.value.is(ValueNode::STRING)) { return prop.value.asString(); } else { - if(errors != nullptr) { + if (errors != nullptr) { errors->emplace_back(prop.value.span, "expected string"); } } @@ -222,13 +228,11 @@ struct DisplayItemNode: public AstNode } }; -struct DisplayNode: public AstNode -{ +struct DisplayNode : public AstNode { std::vector items; }; -struct PinConnectionNode: public AstNode -{ +struct PinConnectionNode : public AstNode { enum ConnectionType { REQUIRED, OPTIONAL @@ -238,8 +242,7 @@ struct PinConnectionNode: public AstNode EnumNode type; }; -struct PinNode: public AstNode -{ +struct PinNode : public AstNode { enum PinType { IN_OUT, IN, @@ -254,8 +257,7 @@ struct PinNode: public AstNode std::optional> wires; }; -struct WireNode: public AstNode -{ +struct WireNode : public AstNode { enum WireType { WIRE, WIRED_AND, @@ -272,22 +274,19 @@ struct WireNode: public AstNode ValueNode terminateWith; }; -struct AttributeNode: public AstNode -{ +struct AttributeNode : public AstNode { ValueNode::ValueType type; IdentifierNode name; std::optional defaultValue; std::optional popup; }; -struct ConnectionComponentNode: public AstNode -{ +struct ConnectionComponentNode : public AstNode { IdentifierNode component; IdentifierNode pin; }; -struct ConnectionNode: public AstNode -{ +struct ConnectionNode : public AstNode { ConnectionComponentNode first; std::optional second; @@ -298,8 +297,7 @@ struct ConnectionNode: public AstNode std::optional> secondWires; }; -struct ComponentNode: public AstNode -{ +struct ComponentNode : public AstNode { enum ComponentType { OTHER, PROCESSOR, @@ -318,8 +316,7 @@ struct ComponentNode: public AstNode std::vector attributes; }; -struct BusNode: public AstNode -{ +struct BusNode : public AstNode { enum BusType { AUTOMATIC, REGULAR, @@ -335,8 +332,7 @@ struct BusNode: public AstNode std::vector wires; }; -struct LibraryNode: public AstNode -{ +struct LibraryNode : public AstNode { std::optional name; std::optional libraryInfo; std::optional header; @@ -353,14 +349,12 @@ struct LibraryNode: public AstNode }; // SCHEMA models -struct InstanceAttributeNode: public AstNode -{ +struct InstanceAttributeNode : public AstNode { IdentifierNode name; ValueNode value; }; -struct InstanceNode: public AstNode -{ +struct InstanceNode : public AstNode { IdentifierNode name; IdentifierNode component; @@ -370,14 +364,12 @@ struct InstanceNode: public AstNode std::optional size; }; -struct ConnectionComponentInstance: public AstNode -{ +struct ConnectionComponentInstance : public AstNode { IdentifierNode instance; IdentifierNode pin; }; -struct ConnectionInstanceNode: public AstNode -{ +struct ConnectionInstanceNode : public AstNode { ConnectionComponentInstance first; std::optional second; @@ -387,8 +379,7 @@ struct ConnectionInstanceNode: public AstNode }; -struct SchemaNode: public AstNode -{ +struct SchemaNode : public AstNode { std::optional source; std::vector instances; diff --git a/comdel/parser/comdelparser.cpp b/comdel/parser/comdel_parser.cpp similarity index 77% rename from comdel/parser/comdelparser.cpp rename to comdel/parser/comdel_parser.cpp index 1fb9ad0..30c694a 100644 --- a/comdel/parser/comdelparser.cpp +++ b/comdel/parser/comdel_parser.cpp @@ -1,7 +1,7 @@ -#include "comdelparser.h" +#include "comdel_parser.h" #include "poly.h" -#include "tokenstype.h" +#include "tokens_type.h" #include #include @@ -9,9 +9,7 @@ #include ComdelParser::ComdelParser(std::vector tokens) - : tokens(std::move(tokens)) - , position(0) -{} + : tokens(std::move(tokens)), position(0) {} // Tries to consume a token, returns an error otherwise. // Unlike the regular consume() call this should be used @@ -27,9 +25,8 @@ ComdelParser::ComdelParser(std::vector tokens) // Checks if the current token matches the argument. // Otherwise, adds the token to the list of expected tokens (used in // error message). -bool ComdelParser::check(TokenType tokenType) -{ - if(current().type == tokenType) +bool ComdelParser::check(TokenType tokenType) { + if (current().type == tokenType) return true; expectedTokens.insert(tokenType); @@ -79,7 +76,7 @@ PError ComdelParser::unexpected() { ss << ": "; } uint token_counter = 0; - for (auto& type : expectedTokens) { + for (auto &type: expectedTokens) { if (type == TokenType::IDENTIFIER || type == TokenType::NUMBER || type == TokenType::STRING || @@ -92,9 +89,9 @@ PError ComdelParser::unexpected() { if (token_counter < expectedTokens.size()) ss << ", "; else - ss <<"."; + ss << "."; } - return PError({current().span, ss.str()}); + return {{current().span, ss.str()}}; } // Parses a list of 'nodes' separated by 'separator'. Parsed nodes @@ -107,21 +104,21 @@ PError ComdelParser::unexpected() { // // 'closeDelim' is mandatory, and it will be consumed. // -// Function 'parse_f' should only parse a single node of type T. +// Function 'parse_f' should only parseLibrary a single node of type T. // // Parameter allowTrailing==true means that the list should end with // 'separator' and otherwise the list should end with 'node'. This // parameter is false in every call-site! -template PResult> +template +PResult> ComdelParser::parseList(std::optional openDelim, TokenType closeDelim, std::optional separator, bool allowTrailing, - const std::function()>& parse_f) -{ + const std::function()> &parse_f) { std::vector vec; - if(openDelim) { + if (openDelim) { RETURN_IF_NOT_TOKEN(*openDelim); } @@ -149,34 +146,33 @@ void ComdelParser::skipUntilNextKeyword() { int depth = 0; bool enteredBlock = false; - while(true) { - if(is_keyword(current().type) && (!enteredBlock || (enteredBlock && depth == 0))) { + while (true) { + if (is_keyword(current().type) && (!enteredBlock || (enteredBlock && depth == 0))) { break; } - if(check(TokenType::LBRACE)) { + if (check(TokenType::LBRACE)) { enteredBlock = true; depth++; - } else if(check(TokenType::RBRACE)) { - if(depth == 0) { + } else if (check(TokenType::RBRACE)) { + if (depth == 0) { break; } depth--; - } else if(check(TokenType::END_OF_FILE)) { + } else if (check(TokenType::END_OF_FILE)) { break; } bump(); } } -const std::vector &ComdelParser::getErrors() -{ +const std::vector &ComdelParser::getErrors() { return errors; } Span &ComdelParser::getPreviousSpan() { static Span span; - if(position == 0) { + if (position == 0) { return span; } else { return tokens[position].span; @@ -184,9 +180,8 @@ Span &ComdelParser::getPreviousSpan() { } // See comment for Spanner -Spanner ComdelParser::getSpanner() -{ - return Spanner(current().span, getPreviousSpan()); +Spanner ComdelParser::getSpanner() { + return {current().span, getPreviousSpan()}; } // utility for reading strings @@ -196,7 +191,7 @@ Spanner ComdelParser::getSpanner() if (!assign_or_return_if_err_temp_) { \ err = PError(assign_or_return_if_err_temp_.error()); \ } else { \ - var = *assign_or_return_if_err_temp_; \ + (var) = *assign_or_return_if_err_temp_; \ } \ } while (0) @@ -207,7 +202,7 @@ Spanner ComdelParser::getSpanner() if (!assign_or_return_if_err_temp_) { \ err = PError(assign_or_return_if_err_temp_.error()); \ } else { \ - var.push_back(*assign_or_return_if_err_temp_); \ + (var).push_back(*assign_or_return_if_err_temp_); \ } \ } while (0) @@ -218,7 +213,7 @@ Spanner ComdelParser::getSpanner() if (!assign_or_return_if_err_temp_) { \ return PError(assign_or_return_if_err_temp_.error()); \ } else { \ - var.push_back(*assign_or_return_if_err_temp_); \ + (var).push_back(*assign_or_return_if_err_temp_); \ } \ } while (0) @@ -229,46 +224,48 @@ Spanner ComdelParser::getSpanner() * ****************************************************************************/ -std::optional ComdelParser::parse() -{ +std::optional ComdelParser::parseLibrary() { auto spanner = getSpanner(); LibraryNode library{}; - while ( ! check(TokenType::END_OF_FILE) ) { + while (!check(TokenType::END_OF_FILE)) { PResult> err; - if(check(TokenType::KW_NAME)){ + if (check(TokenType::KW_NAME)) { bump(); ASSIGN_OR_SET_ERR(library.name, parseString()); - } else if(check(TokenType::KW_HEADER)) { + } else if (check(TokenType::KW_HEADER)) { bump(); ASSIGN_OR_SET_ERR(library.header, parseString()); - } else if(check(TokenType::KW_COMPONENT_HEADER)) { + } else if (check(TokenType::KW_COMPONENT_HEADER)) { bump(); ASSIGN_OR_SET_ERR(library.componentHeader, parseString()); - } else if(check(TokenType::KW_DIRECTORY)) { + } else if (check(TokenType::KW_DIRECTORY)) { bump(); ASSIGN_OR_SET_ERR(library.componentDirectory, parseString()); - } else if(check(TokenType::KW_INFO)) { + } else if (check(TokenType::KW_INFO)) { bump(); ASSIGN_OR_SET_ERR(library.libraryInfo, parseString()); - } else if(check(TokenType::KW_ADDRESS)) { + } else if (check(TokenType::KW_ADDRESS)) { APPEND_OR_SET_ERR(library.addressSpaces, parseAddress()); - } else if(check(TokenType::KW_COMPONENT)) { + } else if (check(TokenType::KW_COMPONENT)) { APPEND_OR_SET_ERR(library.components, parseComponent()); - } else if(check(TokenType::KW_BUS)) { + } else if (check(TokenType::KW_BUS)) { APPEND_OR_SET_ERR(library.buses, parseBus()); - } else if(check(TokenType::KW_CONNECTION)) { + } else if (check(TokenType::KW_CONNECTION)) { APPEND_OR_SET_ERR(library.connections, parseConnection()); - } else if(check(TokenType::KW_MESSAGES)) { + } else if (check(TokenType::KW_MESSAGES)) { bump(); - ASSIGN_OR_SET_ERR(library.messages, parseList(std::optional(TokenType::LBRACE), - TokenType::RBRACE, - std::nullopt, - false, - [this]{return parseProperty(std::optional(TokenType::STRING));} - )); - if(!err.has_value()) { + ASSIGN_OR_SET_ERR(library.messages, parseList(TokenType::LBRACE, + TokenType::RBRACE, + std::nullopt, + false, + [this] { return parseProperty( + std::optional( + TokenType::STRING)); + } + )); + if (!err.has_value()) { skipUntilNextKeyword(); bump(); } @@ -276,13 +273,13 @@ std::optional ComdelParser::parse() err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); } } - if (errors.size()) + if (!errors.empty()) return std::nullopt; return spanner(library); @@ -293,8 +290,7 @@ std::optional ComdelParser::parse() * StringNode := "\"" + CONTENT + "\"" * ****************************************************************************/ -PResult ComdelParser::parseString() -{ +PResult ComdelParser::parseString() { auto spanner = getSpanner(); if (check(TokenType::STRING)) { StringNode node; @@ -312,8 +308,7 @@ PResult ComdelParser::parseString() * IdentifierNode := IDENTIFIER * ****************************************************************************/ -PResult ComdelParser::parseIdentifier() -{ +PResult ComdelParser::parseIdentifier() { auto spanner = getSpanner(); if (check(TokenType::IDENTIFIER)) { IdentifierNode node; @@ -330,8 +325,7 @@ PResult ComdelParser::parseIdentifier() * NumberNode := ('0x' | '0b'){0,1}[0-9]* * ****************************************************************************/ -PResult ComdelParser::parseNumber() -{ +PResult ComdelParser::parseNumber() { auto spanner = getSpanner(); if (check(TokenType::NUMBER)) { NumberNode node{current().text}; @@ -348,19 +342,18 @@ PResult ComdelParser::parseNumber() * CountNode := "@size (" + NumberNode + "," + NumberNode + ")" * ****************************************************************************/ -PResult ComdelParser::parseCount() -{ +PResult ComdelParser::parseCount() { auto spanner = getSpanner(); RETURN_IF_NOT_TOKEN(TokenType::KW_COUNT); RETURN_IF_NOT_TOKEN(TokenType::LPAREN); auto first = parseNumber(); - if(!first.has_value()) { + if (!first.has_value()) { return PError(first.error()); } RETURN_IF_NOT_TOKEN(TokenType::COMMA); auto second = parseNumber(); - if(!second.has_value()) { + if (!second.has_value()) { return PError(second.error()); } RETURN_IF_NOT_TOKEN(TokenType::RPAREN); @@ -373,20 +366,19 @@ PResult ComdelParser::parseCount() * PropertyNode := key: value; * ****************************************************************************/ -PResult ComdelParser::parseProperty(std::optional valueType = std::nullopt) -{ +PResult ComdelParser::parseProperty(std::optional valueType = std::nullopt) { auto spanner = getSpanner(); IdentifierNode key; ASSIGN_OR_RETURN_IF_ERR(key, parseIdentifier()); RETURN_IF_NOT_TOKEN(TokenType::COLON); - if(valueType.has_value()) { - if(valueType == TokenType::BOOL_TYPE) { - if(!(check(TokenType::TRUE) || check(TokenType::FALSE))) { + if (valueType.has_value()) { + if (valueType == TokenType::BOOL_TYPE) { + if (!(check(TokenType::TRUE) || check(TokenType::FALSE))) { return unexpected(); } - } else if(!check(*valueType)) { + } else if (!check(*valueType)) { return unexpected(); } } @@ -407,8 +399,7 @@ PResult ComdelParser::parseProperty(std::optional value * AddressSpaceNode := "@address" + IDENTIFIER "(" + NUMBER + "," + NUMBER + ")" * ****************************************************************************/ -PResult ComdelParser::parseAddress() -{ +PResult ComdelParser::parseAddress() { auto spanner = getSpanner(); AddressSpaceNode addressSpace{}; @@ -431,8 +422,7 @@ PResult ComdelParser::parseAddress() * ComponentNode := "@component" + IDENTIFIER + ("processor" | "memory") { COMPONENT_BLOCK } * ****************************************************************************/ -PResult ComdelParser::parseComponent() -{ +PResult ComdelParser::parseComponent() { auto spanner = getSpanner(); ComponentNode component{}; @@ -440,40 +430,39 @@ PResult ComdelParser::parseComponent() RETURN_IF_NOT_TOKEN(TokenType::KW_COMPONENT); ASSIGN_OR_RETURN_IF_ERR(component.name, parseIdentifier()); - ASSIGN_OR_RETURN_IF_ERR(component.type, parseComponentType()); RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; - if(check(TokenType::KW_INSTANCE_NAME)) { + if (check(TokenType::KW_INSTANCE_NAME)) { bump(); ASSIGN_OR_SET_ERR(component.instanceName, parseString()); - } else if(check(TokenType::KW_TOOLTIP)) { + } else if (check(TokenType::KW_TOOLTIP)) { bump(); ASSIGN_OR_SET_ERR(component.tooltip, parseString()); - } else if(check(TokenType::KW_SOURCE)) { + } else if (check(TokenType::KW_SOURCE)) { bump(); ASSIGN_OR_SET_ERR(component.source, parseString()); - } else if(check(TokenType::KW_COUNT)) { + } else if (check(TokenType::KW_COUNT)) { ASSIGN_OR_SET_ERR(component.count, parseCount()); - } else if(check(TokenType::KW_DISPLAY)) { + } else if (check(TokenType::KW_DISPLAY)) { ASSIGN_OR_SET_ERR(component.display, parseDisplay()); - } else if(check(TokenType::KW_PIN)) { + } else if (check(TokenType::KW_PIN)) { APPEND_OR_SET_ERR(component.pins, parsePin()); - } else if(check(TokenType::KW_ATTRIBUTE)) { + } else if (check(TokenType::KW_ATTRIBUTE)) { APPEND_OR_SET_ERR(component.attributes, parseAttribute()); - } else if(check(TokenType::KW_RULE)) { + } else if (check(TokenType::KW_RULE)) { APPEND_OR_SET_ERR(component.rules, parseRule()); } else { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -489,10 +478,10 @@ PResult> ComdelParser::parseComponentType auto spanner = getSpanner(); - if(check(TokenType::CT_PROCESSOR)) { + if (check(TokenType::CT_PROCESSOR)) { bump(); type = EnumNode(ComponentNode::PROCESSOR); - } else if(check(TokenType::CT_MEMORY)) { + } else if (check(TokenType::CT_MEMORY)) { bump(); type = EnumNode(ComponentNode::MEMORY); } else { @@ -513,7 +502,7 @@ PResult ComdelParser::parseDisplay() { RETURN_IF_NOT_TOKEN(TokenType::KW_DISPLAY); DisplayNode display; RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult item; item = parseDisplayItem(); RETURN_IF_ERR(item); @@ -535,7 +524,7 @@ PResult ComdelParser::parseDisplayItem() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult item{parseProperty()}; RETURN_IF_ERR(item); displayItem.values.push_back(*item); @@ -557,30 +546,26 @@ PResult ComdelParser::parseBus() { RETURN_IF_NOT_TOKEN(TokenType::KW_BUS); ASSIGN_OR_RETURN_IF_ERR(bus.name, parseIdentifier()); - - auto type = parseBusType(); - RETURN_IF_ERR(type); - - bus.type = *type; + ASSIGN_OR_RETURN_IF_ERR(bus.type, parseBusType()); RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; - if(check(TokenType::KW_TOOLTIP)) { + if (check(TokenType::KW_TOOLTIP)) { bump(); ASSIGN_OR_RETURN_IF_ERR(bus.tooltip, parseString()); - } else if(check(TokenType::KW_COUNT)) { + } else if (check(TokenType::KW_COUNT)) { ASSIGN_OR_RETURN_IF_ERR(bus.count, parseCount()); - } else if(check(TokenType::KW_DISPLAY)) { + } else if (check(TokenType::KW_DISPLAY)) { ASSIGN_OR_RETURN_IF_ERR(bus.display, parseDisplay()); - } else if(check(TokenType::KW_WIRES)) { + } else if (check(TokenType::KW_WIRES)) { bump(); RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(check(TokenType::IDENTIFIER)) { + while (check(TokenType::IDENTIFIER)) { APPEND_OR_RETURN_IF_ERR(bus.wires, parseWire()); - if(check(TokenType::COMMA)) { + if (check(TokenType::COMMA)) { RETURN_IF_NOT_TOKEN(TokenType::COMMA); } } @@ -589,10 +574,10 @@ PResult ComdelParser::parseBus() { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -606,13 +591,13 @@ PResult ComdelParser::parseBus() { PResult> ComdelParser::parseBusType() { PResult> type; - if(check(TokenType::IDENTIFIER)) { + if (check(TokenType::IDENTIFIER)) { auto tokenType = parseIdentifier(); - if(tokenType.value().value == "automatic") { + if (tokenType.value().value == "automatic") { type = EnumNode(BusNode::AUTOMATIC); - } else if(tokenType.value().value == "regular") { + } else if (tokenType.value().value == "regular") { type = EnumNode(BusNode::REGULAR); - } else if(tokenType.value().value == "singleAutomatic") { + } else if (tokenType.value().value == "singleAutomatic") { type = EnumNode(BusNode::SINGLE_AUTOMATIC); } else { type = PError(SourceError{current().span, "expected 'automatic', 'singleAutomatic' or 'regular'"}); @@ -635,7 +620,7 @@ PResult ComdelParser::parseWire() { ASSIGN_OR_RETURN_IF_ERR(wire.name, parseIdentifier()); - if(check(TokenType::LT)) { + if (check(TokenType::LT)) { RETURN_IF_NOT_TOKEN(TokenType::LT); ASSIGN_OR_RETURN_IF_ERR(wire.size, parseNumber()); RETURN_IF_NOT_TOKEN(TokenType::GT); @@ -646,31 +631,31 @@ PResult ComdelParser::parseWire() { // default wire.type = EnumNode(WireNode::WIRE); - if(check(TokenType::WIRE_DEFAULT)) { + if (check(TokenType::WIRE_DEFAULT)) { bump(); wire.type = EnumNode(WireNode::WIRE); - } else if(check(TokenType::WIRE_AND)) { + } else if (check(TokenType::WIRE_AND)) { bump(); wire.type = EnumNode(WireNode::WIRED_AND); - } else if(check(TokenType::WIRE_OR)) { + } else if (check(TokenType::WIRE_OR)) { bump(); wire.type = EnumNode(WireNode::WIRED_OR); - } else if(check(TokenType::R_WIRE)) { + } else if (check(TokenType::R_WIRE)) { bump(); wire.type = EnumNode(WireNode::R_WIRE); } - while(true) { - if(check(TokenType::HIDDEN)) { + while (true) { + if (check(TokenType::HIDDEN)) { bump(); wire.hidden = true; - } else if(check(TokenType::TERMINATE_WITH)) { + } else if (check(TokenType::TERMINATE_WITH)) { bump(); wire.hasTerminateWith = true; - if(check(TokenType::NIL)) { + if (check(TokenType::NIL)) { bump(); wire.terminateWith = ValueNode::ofNull(); - } else if(check(TokenType::NUMBER)) { + } else if (check(TokenType::NUMBER)) { auto number = parseNumber(); wire.terminateWith = ValueNode::ofInt(number->value); } else { @@ -703,13 +688,13 @@ PResult ComdelParser::parsePin() { ASSIGN_OR_RETURN_IF_ERR(pin.name, parseIdentifier()); - if(check(TokenType::PIN_IN)) { + if (check(TokenType::PIN_IN)) { bump(); pin.type = EnumNode(PinNode::IN); - } else if(check(TokenType::PIN_OUT)) { + } else if (check(TokenType::PIN_OUT)) { bump(); pin.type = EnumNode(PinNode::OUT); - } else if(check(TokenType::PIN_IN_OUT)) { + } else if (check(TokenType::PIN_IN_OUT)) { bump(); pin.type = EnumNode(PinNode::IN_OUT); } else { @@ -718,7 +703,7 @@ PResult ComdelParser::parsePin() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; if (check(TokenType::KW_TOOLTIP)) { bump(); @@ -727,9 +712,12 @@ PResult ComdelParser::parsePin() { ASSIGN_OR_SET_ERR(pin.display, parseDisplay()); } else if (check(TokenType::KW_CONNECTION)) { ASSIGN_OR_SET_ERR(pin.connection, parsePinConnection()); - } else if (check(TokenType::KW_WIRES)){ + } else if (check(TokenType::KW_WIRES)) { bump(); - auto wires = parseList(std::optional(TokenType::LBRACE), TokenType::RBRACE, std::optional(TokenType::COMMA), false, + auto wires = parseList(TokenType::LBRACE, + TokenType::RBRACE, + TokenType::COMMA, + false, [this] { return parseConnectionWire(); }); RETURN_IF_ERR(wires); pin.wires = *wires; @@ -737,10 +725,10 @@ PResult ComdelParser::parsePin() { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -777,11 +765,11 @@ PResult> ComdelParser::parseConnecti EnumNode type; - if(check(TokenType::IDENTIFIER)) { + if (check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); - if(identifier.value().value == "required") { + if (identifier.value().value == "required") { type = EnumNode(PinConnectionNode::REQUIRED); - } else if(identifier.value().value == "optional") { + } else if (identifier.value().value == "optional") { type = EnumNode(PinConnectionNode::OPTIONAL); } else { return PError(SourceError{current().span, "expected connection type 'required' or 'optional'"}); @@ -804,19 +792,19 @@ PResult ComdelParser::parseAttribute() { RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE); - if(check(TokenType::IDENTIFIER)) { + if (check(TokenType::IDENTIFIER)) { ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier()); } else { return unexpected(); } - if(check(TokenType::INT_TYPE)) { + if (check(TokenType::INT_TYPE)) { attribute.type = ValueNode::INT; - } else if(check(TokenType::STRING_TYPE)) { + } else if (check(TokenType::STRING_TYPE)) { attribute.type = ValueNode::STRING; - } else if(check(TokenType::BOOL_TYPE)) { + } else if (check(TokenType::BOOL_TYPE)) { attribute.type = ValueNode::BOOL; - } else if(check(TokenType::WIRE_TYPE)) { + } else if (check(TokenType::WIRE_TYPE)) { attribute.type = ValueNode::WIRE; } else { return unexpected(); @@ -825,52 +813,52 @@ PResult ComdelParser::parseAttribute() { RETURN_IF_NOT_TOKEN(TokenType::DEFAULT); - if(attribute.type == ValueNode::BOOL) { - if(check(TokenType::TRUE)) { + if (attribute.type == ValueNode::BOOL) { + if (check(TokenType::TRUE)) { bump(); attribute.defaultValue = ValueNode::ofBool(true); - } else if(check(TokenType::FALSE)) { + } else if (check(TokenType::FALSE)) { bump(); attribute.defaultValue = ValueNode::ofBool(false); } else { return unexpected(); } - } else if(attribute.type == ValueNode::INT) { - if(check(TokenType::NUMBER)) { + } else if (attribute.type == ValueNode::INT) { + if (check(TokenType::NUMBER)) { auto number = parseNumber(); attribute.defaultValue = ValueNode::ofInt(number->value); - } else { + } else { return unexpected(); } - } else if(attribute.type == ValueNode::STRING) { - if(check(TokenType::STRING)) { + } else if (attribute.type == ValueNode::STRING) { + if (check(TokenType::STRING)) { auto string = parseString(); attribute.defaultValue = ValueNode::ofString(string->asString()); - } else { + } else { return unexpected(); } - } else if(attribute.type == ValueNode::IDENTIFIER) { - if(check(TokenType::IDENTIFIER)) { + } else if (attribute.type == ValueNode::IDENTIFIER) { + if (check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); attribute.defaultValue = ValueNode::ofIdentifier(identifier->value); - } else { + } else { return unexpected(); } - } else if(attribute.type == ValueNode::MEMORY) { - if(check(TokenType::IDENTIFIER)) { + } else if (attribute.type == ValueNode::MEMORY) { + if (check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); attribute.defaultValue = ValueNode::ofMemory(identifier->value); - } else if(check(TokenType::NIL)) { + } else if (check(TokenType::NIL)) { bump(); attribute.defaultValue = ValueNode::ofMemory(std::nullopt); } else { return unexpected(); } - } else if(attribute.type == ValueNode::WIRE) { - if(check(TokenType::IDENTIFIER)) { + } else if (attribute.type == ValueNode::WIRE) { + if (check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); attribute.defaultValue = ValueNode::ofWire(identifier->value); - } else if(check(TokenType::NIL)) { + } else if (check(TokenType::NIL)) { bump(); attribute.defaultValue = ValueNode::ofWire(std::nullopt); } else { @@ -878,11 +866,11 @@ PResult ComdelParser::parseAttribute() { } } - if(check(TokenType::LBRACE)) { + if (check(TokenType::LBRACE)) { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); PopupNode popup; - if(!check(TokenType::KW_POPUP)) { + if (!check(TokenType::KW_POPUP)) { return unexpected(); } @@ -927,11 +915,11 @@ PResult ComdelParser::parsePopup() { RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP); - if(check(TokenType::IDENTIFIER)) { + if (check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); - if(identifier.value().value == "automatic") { + if (identifier.value().value == "automatic") { popup.type = EnumNode(PopupNode::AUTOMATIC); - } else if(identifier.value().value == "on_demand") { + } else if (identifier.value().value == "on_demand") { popup.type = EnumNode(PopupNode::ON_DEMAND); } else { return PError(SourceError{current().span, "expected type 'automatic', 'on_demand'"}); @@ -942,36 +930,36 @@ PResult ComdelParser::parsePopup() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; - if(check(TokenType::KW_TITLE)) { + if (check(TokenType::KW_TITLE)) { bump(); ASSIGN_OR_SET_ERR(popup.title, parseString()); - } else if(check(TokenType::KW_TEXT)) { + } else if (check(TokenType::KW_TEXT)) { bump(); ASSIGN_OR_SET_ERR(popup.text, parseString()); - } else if(check(TokenType::KW_RULE)) { + } else if (check(TokenType::KW_RULE)) { APPEND_OR_SET_ERR(popup.rules, parseRule()); - } else if(check(TokenType::KW_ENUMERATED)) { + } else if (check(TokenType::KW_ENUMERATED)) { bump(); popup.enumerated = true; ASSIGN_OR_SET_ERR(popup.enumeration, - parseList( - std::optional(TokenType::LBRACE), + parseList( + TokenType::LBRACE, TokenType::RBRACE, - std::optional(TokenType::COMMA), + TokenType::COMMA, true, - [this]{ return parseEnumeration();} - ) + [this] { return parseEnumeration(); } + ) ); } else { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -1000,7 +988,7 @@ PResult ComdelParser::parseConnection() { RETURN_IF_NOT_TOKEN(TokenType::COMMA); ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier()); - if(check(TokenType::COMMA)) { + if (check(TokenType::COMMA)) { auto conn = ConnectionComponentNode{}; RETURN_IF_NOT_TOKEN(TokenType::COMMA); ASSIGN_OR_RETURN_IF_ERR(conn.component, parseIdentifier()); @@ -1015,18 +1003,18 @@ PResult ComdelParser::parseConnection() { int wireCount = 0; - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; if (check(TokenType::KW_ATTRIBUTE)) { APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute()); - } else if(check(TokenType::KW_WIRES)) { + } else if (check(TokenType::KW_WIRES)) { bump(); auto wires = parseList(TokenType::LBRACE, TokenType::RBRACE, TokenType::COMMA, false, - [this] { return parseConnectionWire(); }); + [this] { return parseConnectionWire(); }); RETURN_IF_ERR(wires); - if(wireCount == 0) { + if (wireCount == 0) { connection.firstWires = *wires; - } else if(wireCount == 1 && connection.second.has_value()) { + } else if (wireCount == 1 && connection.second.has_value()) { connection.secondWires = *wires; } else { return unexpected(); @@ -1036,10 +1024,10 @@ PResult ComdelParser::parseConnection() { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -1064,9 +1052,9 @@ PResult ComdelParser::parseRule() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { APPEND_OR_RETURN_IF_ERR(rule.statements, parseIfStatement()); - if(check(TokenType::RBRACE)) { + if (check(TokenType::RBRACE)) { break; } RETURN_IF_NOT_TOKEN(TokenType::ELSE); @@ -1091,7 +1079,7 @@ PResult ComdelParser::parseIfStatement() { RETURN_IF_NOT_TOKEN(TokenType::LPAREN); - if(check(TokenType::NOT)) { + if (check(TokenType::NOT)) { ifStatement.condition.negated = true; bump(); } else { @@ -1100,20 +1088,20 @@ PResult ComdelParser::parseIfStatement() { ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.functionName, parseIdentifier()); - ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList(std::optional(TokenType::LPAREN), - TokenType::RPAREN, - TokenType::COMMA, - false, - [this]{return parseValue();} - )); + ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList(TokenType::LPAREN, + TokenType::RPAREN, + TokenType::COMMA, + false, + [this] { return parseValue(); } + )); RETURN_IF_NOT_TOKEN(TokenType::RPAREN); RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - if(check(TokenType::ERROR)) { + if (check(TokenType::ERROR)) { ifStatement.action.type = EnumNode(ActionNode::ERROR); - } else if(check(TokenType::WARNING)) { + } else if (check(TokenType::WARNING)) { ifStatement.action.type = EnumNode(ActionNode::WARNING); } else { return unexpected(); @@ -1134,19 +1122,19 @@ PResult ComdelParser::parseValue() { auto spanner = getSpanner(); ValueNode value; - if(check(TokenType::IDENTIFIER)) { + if (check(TokenType::IDENTIFIER)) { value = ValueNode::ofIdentifier(parseIdentifier()->value); - } else if(check(TokenType::STRING)) { + } else if (check(TokenType::STRING)) { value = ValueNode::ofString(parseString()->asString()); - } else if(check(TokenType::NUMBER)) { + } else if (check(TokenType::NUMBER)) { value = ValueNode::ofInt(parseNumber()->value); - } else if(check(TokenType::TRUE)) { + } else if (check(TokenType::TRUE)) { bump(); value = ValueNode::ofBool(true); - } else if(check(TokenType::FALSE)) { + } else if (check(TokenType::FALSE)) { bump(); value = ValueNode::ofBool(false); - } else if(check(TokenType::NIL)) { + } else if (check(TokenType::NIL)) { bump(); value = ValueNode::ofNull(); } else { @@ -1160,9 +1148,9 @@ std::optional ComdelParser::parseSchema() { auto spanner = getSpanner(); SchemaNode schema{}; - if(check(TokenType::KW_SOURCE)) { + if (check(TokenType::KW_SOURCE)) { bump(); - if(check(TokenType::STRING)) { + if (check(TokenType::STRING)) { auto source = parseString(); schema.source = *source; } else { @@ -1174,48 +1162,48 @@ std::optional ComdelParser::parseSchema() { return std::nullopt; } - if(!check(TokenType::KW_SCHEMA)) { + if (!check(TokenType::KW_SCHEMA)) { errors.emplace_back(current().span, "expected `@schema`"); return std::nullopt; } bump(); - if(!check(TokenType::LBRACE)) { + if (!check(TokenType::LBRACE)) { errors.emplace_back(current().span, "expected `{`"); return std::nullopt; } bump(); - while ( ! check(TokenType::RBRACE) ) { + while (!check(TokenType::RBRACE)) { PResult> err; - if(check(TokenType::KW_INSTANCE)){ + if (check(TokenType::KW_INSTANCE)) { APPEND_OR_SET_ERR(schema.instances, parseInstance()); - } else if(check(TokenType::KW_CONNECTION)) { + } else if (check(TokenType::KW_CONNECTION)) { APPEND_OR_SET_ERR(schema.connections, parseConnectionInstance()); } else { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { errors.emplace_back(current().span, "expected `}` reached EOF"); return std::nullopt; } } } - if(!check(TokenType::RBRACE)) { + if (!check(TokenType::RBRACE)) { errors.emplace_back(current().span, "expected `}`"); return std::nullopt; } else { bump(); } - if(!check(TokenType::END_OF_FILE)) { + if (!check(TokenType::END_OF_FILE)) { errors.emplace_back(current().span, "expected `EOF`"); } - if (errors.size()) + if (!errors.empty()) return std::nullopt; return spanner(schema); @@ -1226,19 +1214,18 @@ std::optional ComdelParser::parseSchema() { * CountNode := "@position (" + NumberNode + "," + NumberNode + ")" * ****************************************************************************/ -PResult ComdelParser::parsePosition() -{ +PResult ComdelParser::parsePosition() { auto spanner = getSpanner(); RETURN_IF_NOT_TOKEN(TokenType::KW_POSITION); RETURN_IF_NOT_TOKEN(TokenType::LPAREN); auto first = parseNumber(); - if(!first.has_value()) { + if (!first.has_value()) { return PError(first.error()); } RETURN_IF_NOT_TOKEN(TokenType::COMMA); auto second = parseNumber(); - if(!second.has_value()) { + if (!second.has_value()) { return PError(second.error()); } RETURN_IF_NOT_TOKEN(TokenType::RPAREN); @@ -1257,13 +1244,13 @@ PResult ComdelParser::parseInstance() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; - if(check(TokenType::KW_POSITION)) { + if (check(TokenType::KW_POSITION)) { ASSIGN_OR_SET_ERR(instance.position, parsePosition()); - } else if(check(TokenType::KW_ATTRIBUTE)) { + } else if (check(TokenType::KW_ATTRIBUTE)) { APPEND_OR_SET_ERR(instance.attributes, parseInstanceAttribute()); - } else if(check(TokenType::KW_SIZE)) { + } else if (check(TokenType::KW_SIZE)) { bump(); auto number = parseNumber(); RETURN_IF_ERR(number); @@ -1272,10 +1259,10 @@ PResult ComdelParser::parseInstance() { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -1285,6 +1272,7 @@ PResult ComdelParser::parseInstance() { return spanner(instance); } + PResult ComdelParser::parseInstanceAttribute() { auto spanner = getSpanner(); RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE); @@ -1295,6 +1283,7 @@ PResult ComdelParser::parseInstanceAttribute() { return spanner(attribute); } + PResult ComdelParser::parseConnectionInstance() { auto spanner = getSpanner(); RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION); @@ -1308,7 +1297,7 @@ PResult ComdelParser::parseConnectionInstance() { RETURN_IF_NOT_TOKEN(TokenType::COMMA); ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier()); - if(check(TokenType::COMMA)) { + if (check(TokenType::COMMA)) { bump(); ConnectionComponentInstance second; ASSIGN_OR_RETURN_IF_ERR(second.instance, parseIdentifier()); @@ -1321,18 +1310,18 @@ PResult ComdelParser::parseConnectionInstance() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(!check(TokenType::RBRACE)) { + while (!check(TokenType::RBRACE)) { PResult> err; - if(check(TokenType::KW_ATTRIBUTE)) { + if (check(TokenType::KW_ATTRIBUTE)) { APPEND_OR_SET_ERR(connection.attributes, parseInstanceAttribute()); } else { err = unexpected(); bump(); } - if(!err.has_value()) { + if (!err.has_value()) { errors.push_back(err.error()); skipUntilNextKeyword(); - if(check(TokenType::END_OF_FILE)) { + if (check(TokenType::END_OF_FILE)) { return PError({Span(spanner.lo), "Reached EOF"}); } } @@ -1345,14 +1334,14 @@ PResult ComdelParser::parseConnectionInstance() { PResult ComdelParser::parseConnectionWire() { auto spanner = getSpanner(); - if(check(TokenType::NUMBER)) { + if (check(TokenType::NUMBER)) { return spanner(ValueNode::ofInt(parseNumber()->value)); - } else if(check(TokenType::NIL)) { + } else if (check(TokenType::NIL)) { bump(); return spanner(ValueNode::ofNull()); - } else if(check(TokenType::STRING)) { + } else if (check(TokenType::STRING)) { return spanner(ValueNode::ofString(parseString()->value)); - } else if(check(TokenType::IDENTIFIER)) { + } else if (check(TokenType::IDENTIFIER)) { return spanner(ValueNode::ofIdentifier(parseIdentifier()->value)); } else { return unexpected(); diff --git a/comdel/parser/comdelparser.h b/comdel/parser/comdel_parser.h similarity index 74% rename from comdel/parser/comdelparser.h rename to comdel/parser/comdel_parser.h index 82f056e..f050b62 100644 --- a/comdel/parser/comdelparser.h +++ b/comdel/parser/comdel_parser.h @@ -1,10 +1,10 @@ #ifndef COMDEL_PARSER_H #define COMDEL_PARSER_H -#include "sourceerror.h" +#include "source_error.h" #include "presult.h" #include "token.h" -#include "astnode.h" +#include "ast_nodes.h" #include #include @@ -18,23 +18,21 @@ class Spanner { // REFERENCE to the parser's prevSpan. After parsing a node this will // "point" to the span of the last token contained in the node. - const Span& prevSpan; + const Span &prevSpan; public: const Span lo; // the low end of the span, beginning of the node + Spanner(Span lo, Span &prevSpan) : lo(lo), prevSpan(prevSpan) {} - Spanner(Span lo, Span& prevSpan) : lo(lo), prevSpan(prevSpan) {} - - template ::value>> - typename std::remove_reference_t operator()(T&& astNode) const { + template::value>> + typename std::remove_reference_t operator()(T &&astNode) const { astNode.span = lo.to(prevSpan); - return std::move(astNode); + return std::forward(astNode); } }; -class ComdelParser -{ +class ComdelParser { private: std::vector tokens; std::set expectedTokens; @@ -47,6 +45,7 @@ private: void bump(); bool consume(TokenType tokenType); + bool check(TokenType tokenType); void skipUntilNextKeyword(); @@ -57,53 +56,79 @@ private: template PResult> parseList(std::optional openDelim, - TokenType closeDelim, - std::optional separator, - bool allowTrailing, - const std::function ()> &parse_f); + TokenType closeDelim, + std::optional separator, + bool allowTrailing, + const std::function()> &parse_f); Spanner getSpanner(); + // used to parse library and schema PResult parseString(); + PResult parseIdentifier(); + PResult parseNumber(); + PResult parseCount(); + PResult parseProperty(std::optional valueType); + PResult parseEnumeration(); PResult parseConnectionWire(); + PResult parseComponent(); + PResult parseAddress(); + PResult parsePin(); + PResult parseDisplay(); + PResult parsePinConnection(); + PResult parseAttribute(); + PResult parsePopup(); + PResult parseRule(); + PResult parseBus(); + PResult parseWire(); + PResult parseConnection(); + PResult parseDisplayItem(); + PResult parseIfStatement(); + PResult parseValue(); - + // used to parse schema PResult parsePosition(); - PResult parseInstance(); - PResult parseInstanceAttribute(); - PResult parseConnectionInstance(); -public: - ComdelParser(std::vector tokens); - std::optional parseSchema(); - std::optional parse(); - const std::vector& getErrors(); + PResult parseInstance(); + + PResult parseInstanceAttribute(); + + PResult parseConnectionInstance(); PResult> parseComponentType(); PResult> parseBusType(); PResult> parseConnectionType(); + +public: + explicit ComdelParser(std::vector tokens); + + std::optional parseSchema(); + + std::optional parseLibrary(); + + const std::vector &getErrors(); }; #endif // COMDEL_PARSER_H diff --git a/comdel/parser/comdellexer.cpp b/comdel/parser/comdellexer.cpp index e4c2032..bbecfab 100644 --- a/comdel/parser/comdellexer.cpp +++ b/comdel/parser/comdellexer.cpp @@ -1,6 +1,6 @@ #include "comdellexer.h" #include "token.h" -#include "tokenstype.h" +#include "tokens_type.h" #include #include @@ -36,14 +36,13 @@ inline bool isWhitespace(char ch) { *************************************************************************/ ComdelLexer::ComdelLexer(std::string fileName, std::string source, - ParseContext* parseContext) - : source(std::move(source)), - parseContext(parseContext), - // TODO Update this - fileId(this->parseContext->addFile(fileName, this->source)), - position(this->fileId, 1, 1, 0), - ch(this->source[0]) -{} + ParseContext *parseContext) + : source(std::move(source)), + parseContext(parseContext), + // TODO Update this + fileId(this->parseContext->addFile(fileName, this->source)), + position(this->fileId, 1, 1, 0), + ch(this->source[0]) {} LexerResult ComdelLexer::tokenize() { @@ -51,11 +50,11 @@ LexerResult ComdelLexer::tokenize() { tokenBegin = position; auto tokenType = nextTokenType(); - if(!tokenType) { + if (!tokenType) { errors.push_back(tokenType.error()); continue; } - if (tokenType == TokenType::WHITESPACE || tokenType == TokenType::COMMENT) { + if (tokenType == TokenType::WHITESPACE || tokenType == TokenType::COMMENT) { continue; } @@ -67,9 +66,9 @@ LexerResult ComdelLexer::tokenize() { tokens.emplace_back(*tokenType, Span(tokenBegin, position), text); } - tokens.emplace_back( TokenType::END_OF_FILE, Span(position), ""); + tokens.emplace_back(TokenType::END_OF_FILE, Span(position), ""); - return LexerResult { tokens, errors }; + return LexerResult{tokens, errors}; } @@ -86,11 +85,11 @@ LexerResult ComdelLexer::tokenize() { unsigned ComdelLexer::takeNumberInRadix(Radix radix) { unsigned digitsTaken = 0; - while(true) { + while (true) { if (digitIsValid(ch, radix)) { // skip and count real digits bump(); digitsTaken++; - } else if(ch == '_') { // skip underscores + } else if (ch == '_') { // skip underscores bump(); } else { // some other character => end of number return digitsTaken; @@ -103,26 +102,26 @@ bool ComdelLexer::digitIsValid(char ch, Radix radix) { // Check valid digits // digit is 0..1 - if(ch == '1' || ch == '0') { + if (ch == '1' || ch == '0') { // OK for all radixes return true; } //digit is 2..9 - if(isdigit(ch)) { + if (isdigit(ch)) { // OK for decimal and hex radixes - return(radix != Radix::BIN_NUMBER); + return (radix != Radix::BIN_NUMBER); } - // digit is a..f A..F - else if(isxdigit(ch)) { + // digit is a..f A..F + else if (isxdigit(ch)) { // OK only for hex radix - return(radix ==Radix::HEX_NUMBER); + return (radix == Radix::HEX_NUMBER); } // NOT 0..9 a..f A..F return false; } -ComdelLexer::Radix ComdelLexer::takeRadix(){ +ComdelLexer::Radix ComdelLexer::takeRadix() { if (ch == '0') { char nextChar = peek(); if (nextChar == 'x' || nextChar == 'X') { @@ -141,7 +140,7 @@ ComdelLexer::Radix ComdelLexer::takeRadix(){ unsigned ComdelLexer::takeHexColor() { unsigned digitsTaken = 0; - while(true) { + while (true) { if (digitIsValid(ch, Radix::HEX_NUMBER)) { // skip and count hex digits bump(); digitsTaken++; @@ -162,10 +161,10 @@ PResult ComdelLexer::takeString() { // Check escape-sequences \t \n \\ \" but leave them in string. // They will be replaced in the constructor of StringLiteral AST-node. while (ch != '"' && ch != '\n' && !eof()) { - if(ch == '"') { + if (ch == '"') { // possible start of escape-sequence char nextCh = peek(); - if(nextCh == '\\' || nextCh == '\"' || nextCh == 't' || nextCh == 'n') + if (nextCh == '\\' || nextCh == '\"' || nextCh == 't' || nextCh == 'n') bump(); // legal escape-sequence: skip backslash else return PError({Span(lo, position), "illegal escape-sequence (allowed: \\n \\\" \\\\ \\t"}); @@ -177,12 +176,11 @@ PResult ComdelLexer::takeString() { return PError({Span(lo, position), "unterminated string"}); } bump(); // skip closing " - return TokenType::STRING; + return TokenType::STRING; } -PResult ComdelLexer::takeRawString() -{ +PResult ComdelLexer::takeRawString() { Position lo = position; if (ch != '`') @@ -198,7 +196,7 @@ PResult ComdelLexer::takeRawString() return PError({Span(lo, position), "unterminated string"}); } bump(); // skip closing ' - return TokenType::STRING; + return TokenType::STRING; } @@ -237,21 +235,16 @@ bool ComdelLexer::skipMultilineComment() { PResult ComdelLexer::nextTokenType() { - if (isWhitespace(ch)) - { + if (isWhitespace(ch)) { skipWhitespace(); - return TokenType::WHITESPACE; - } - else if (identifierStart(ch)) - { + return TokenType::WHITESPACE; + } else if (identifierStart(ch)) { bump(); while (identifierContinue(ch)) bump(); - return TokenType::IDENTIFIER; - } - else if (numberStart(ch)) - { - if(ch == '-') { + return TokenType::IDENTIFIER; + } else if (numberStart(ch)) { + if (ch == '-') { bump(); } unsigned takenDigits; @@ -259,145 +252,99 @@ PResult ComdelLexer::nextTokenType() { takenDigits = takeNumberInRadix(radix); if (takenDigits == 0) { return PError({Span(tokenBegin, position), - "no digits found for number, or misspelled number"}); + "no digits found for number, or misspelled number"}); } - if( isalnum(ch) ) { + if (isalnum(ch)) { return PError({Span(tokenBegin, position), - "illegal digit or letter found at the end of number"}); + "illegal digit or letter found at the end of number"}); } - return TokenType::NUMBER; - } - else if (ch == '!') - { + return TokenType::NUMBER; + } else if (ch == '!') { bump(); - return TokenType::NOT; - } - - else if (ch == '<') - { + return TokenType::NOT; + } else if (ch == '<') { bump(); - return TokenType::LT; - } - - else if (ch == '>') - { + return TokenType::LT; + } else if (ch == '>') { bump(); - return TokenType::GT; - } - - else if (ch == '#') - { + return TokenType::GT; + } else if (ch == '#') { bump(); if (digitIsValid(ch, Radix::HEX_NUMBER)) { unsigned takenDigits = takeHexColor(); if (takenDigits != 6 && takenDigits != 8) { return PError({Span(tokenBegin, position), - "hex-color must have 6 or 8 hex-digits"}); + "hex-color must have 6 or 8 hex-digits"}); } - if( isalnum(ch) ) { + if (isalnum(ch)) { return PError({Span(tokenBegin, position), - "illegal letter found at the end of hex-color"}); + "illegal letter found at the end of hex-color"}); } - return TokenType::COLOR; + return TokenType::COLOR; } else { return PError({Span(tokenBegin, position), "unexpected #"}); } - } - else if (ch == '@') - { + } else if (ch == '@') { bump(); while (identifierContinue(ch)) bump(); - return TokenType::KEYWORD; - } - else if (ch == '"') - { + return TokenType::KEYWORD; + } else if (ch == '"') { return takeString(); - } - else if (ch == '`') - { + } else if (ch == '`') { return takeRawString(); - } - else if (ch == '(') - { + } else if (ch == '(') { bump(); - return TokenType::LPAREN; - } - else if (ch == ')') - { + return TokenType::LPAREN; + } else if (ch == ')') { bump(); - return TokenType::RPAREN; - } - else if (ch == '[') - { + return TokenType::RPAREN; + } else if (ch == '[') { bump(); return TokenType::LBRACKET; - } - else if (ch == ']') - { + } else if (ch == ']') { bump(); - return TokenType::RBRACKET; - } - else if (ch == '{') - { + return TokenType::RBRACKET; + } else if (ch == '{') { bump(); return TokenType::LBRACE; - } - else if (ch == '}') - { + } else if (ch == '}') { bump(); return TokenType::RBRACE; - } - else if (ch == '/') - { + } else if (ch == '/') { bump(); - if (ch == '/') - { + if (ch == '/') { bump(); skipComment(); return TokenType::COMMENT; - } else if (ch == '*') - { + } else if (ch == '*') { bump(); - if (!skipMultilineComment()) - { + if (!skipMultilineComment()) { return PError({Span(tokenBegin, position), - "unterminated multiline comment"}); + "unterminated multiline comment"}); } return TokenType::COMMENT; } return PError({Span(tokenBegin, position), "unexpected /"}); - } - else if (ch == '.') - { + } else if (ch == '.') { bump(); return TokenType::DOT; - } - else if (ch == ':') - { + } else if (ch == ':') { bump(); return TokenType::COLON; - } - else if (ch == ';') - { + } else if (ch == ';') { bump(); return TokenType::SEMICOLON; - } - else if (ch == ',') - { + } else if (ch == ',') { bump(); return TokenType::COMMA; - } - else if (ch == '=') - { + } else if (ch == '=') { bump(); return TokenType::EQUALS; - } - else - { + } else { std::stringstream message; message << "unexpected character `" << ch << "`"; bump(); @@ -409,11 +356,11 @@ PResult ComdelLexer::nextTokenType() { // Move position to the new character in input file. // Fetch the new character in 'ch' void ComdelLexer::bump(unsigned count) { - for (unsigned i=0; i < count && !eof(); i++) { + for (unsigned i = 0; i < count && !eof(); i++) { if (ch == '\n') { position.line += 1; position.col = 1; - parseContext->getFile(fileId).addLineOffset(position.offset+1); + parseContext->getFile(fileId).addLineOffset(position.offset + 1); } else { position.col += 1; } @@ -427,10 +374,10 @@ void ComdelLexer::bump(unsigned count) { // Fetch does not cross line boundary. // Returns \n when next char does not exist (end of line or end of file) char ComdelLexer::peek() { - if(position.offset+1 == source.size()) // eof + if (position.offset + 1 == source.size()) // eof return '\n'; - return source[position.offset+1]; + return source[position.offset + 1]; } diff --git a/comdel/parser/comdellexer.h b/comdel/parser/comdellexer.h index 7ca9b35..0d07484 100644 --- a/comdel/parser/comdellexer.h +++ b/comdel/parser/comdellexer.h @@ -1,9 +1,9 @@ #ifndef COMDEL_LEXER_H #define COMDEL_LEXER_H -#include "parsecontext.h" +#include "parse_context.h" #include "presult.h" -#include "sourceerror.h" +#include "source_error.h" #include "token.h" @@ -16,8 +16,7 @@ struct LexerResult { std::vector errors; }; -class ComdelLexer -{ +class ComdelLexer { enum Radix { BIN_NUMBER = 2, @@ -28,19 +27,23 @@ class ComdelLexer std::string source; std::vector tokens; std::vector errors; - ParseContext* parseContext; + ParseContext *parseContext; unsigned fileId; public: - ComdelLexer(std::string fileName, std::string source, ParseContext* parseContext); + ComdelLexer(std::string fileName, std::string source, ParseContext *parseContext); + LexerResult tokenize(); private: void skipWhitespace(); unsigned takeNumberInRadix(Radix radix); + unsigned takeHexColor(); + bool digitIsValid(char ch, Radix radix); + Radix takeRadix(); PResult nextTokenType(); @@ -50,13 +53,17 @@ private: char ch; void skipComment(); + bool skipMultilineComment(); PResult takeString(); + PResult takeRawString(); void bump(unsigned count = 1); + char peek(); + bool eof(); }; diff --git a/comdel/parser/expected.h b/comdel/parser/expected.h index 2eba6ad..bc73afe 100644 --- a/comdel/parser/expected.h +++ b/comdel/parser/expected.h @@ -34,25 +34,25 @@ #define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ !defined(__clang__)) /// \exclude #define TL_EXPECTED_GCC49 #endif -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \ !defined(__clang__)) /// \exclude #define TL_EXPECTED_GCC54 #endif -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \ !defined(__clang__)) /// \exclude #define TL_EXPECTED_GCC55 #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \ !defined(__clang__)) // GCC < 5 doesn't support overloading on const&& for member functions /// \exclude @@ -73,7 +73,7 @@ // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector // for non-copyable types -#elif (defined(__GNUC__) && __GNUC__ < 8 && \ +#elif (defined(__GNUC__) && __GNUC__ < 8 && \ !defined(__clang__)) #ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX #define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX @@ -118,7 +118,7 @@ namespace tl { #define TL_EXPECTED_GCC49_CONSTEXPR constexpr #endif -#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \ +#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \ defined(TL_EXPECTED_GCC49)) /// \exclude #define TL_EXPECTED_11_CONSTEXPR @@ -128,219 +128,242 @@ namespace tl { #endif namespace tl { -template class expected; + template + class expected; #ifndef TL_MONOSTATE_INPLACE_MUTEX #define TL_MONOSTATE_INPLACE_MUTEX + /// \brief Used to represent an expected with no data -class monostate {}; + class monostate { + }; /// \brief A tag type to tell expected to construct its value in-place -struct in_place_t { - explicit in_place_t() = default; -}; + struct in_place_t { + explicit in_place_t() = default; + }; + /// \brief A tag to tell expected to construct its value in-place -static constexpr in_place_t in_place{}; + static constexpr in_place_t in_place{}; #endif /// Used as a wrapper to store the unexpected value -template class unexpected { -public: - static_assert(!std::is_same::value, "E must not be void"); + template + class unexpected { + public: + static_assert(!std::is_same::value, "E must not be void"); - unexpected() = delete; - constexpr unexpected(const E &e) : m_val(e) {} + unexpected() = delete; - constexpr unexpected(E &&e) : m_val(std::move(e)) {} + constexpr unexpected(const E &e) : m_val(e) {} - /// \returns the contained value - /// \group unexpected_value - constexpr const E &value() const & { return m_val; } - /// \group unexpected_value - TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } - /// \group unexpected_value - TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } - /// \exclude - constexpr const E &&value() const && { return std::move(m_val); } + constexpr unexpected(E &&e) : m_val(std::move(e)) {} -private: - E m_val; -}; + /// \returns the contained value + /// \group unexpected_value + constexpr const E &value() const &{ return m_val; } + /// \group unexpected_value + TL_EXPECTED_11_CONSTEXPR E &value() &{ return m_val; } + /// \group unexpected_value + TL_EXPECTED_11_CONSTEXPR E &&value() &&{ return std::move(m_val); } + + /// \exclude + constexpr const E &&value() const &&{ return std::move(m_val); } + + private: + E m_val; + }; /// \brief Compares two unexpected objects /// \details Simply compares lhs.value() to rhs.value() /// \group unexpected_relop -template -constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { - return lhs.value() == rhs.value(); -} + template + constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() == rhs.value(); + } + /// \group unexpected_relop -template -constexpr bool operator!=(const unexpected &lhs, const unexpected &rhs) { - return lhs.value() != rhs.value(); -} + template + constexpr bool operator!=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() != rhs.value(); + } + /// \group unexpected_relop -template -constexpr bool operator<(const unexpected &lhs, const unexpected &rhs) { - return lhs.value() < rhs.value(); -} + template + constexpr bool operator<(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() < rhs.value(); + } + /// \group unexpected_relop -template -constexpr bool operator<=(const unexpected &lhs, const unexpected &rhs) { - return lhs.value() <= rhs.value(); -} + template + constexpr bool operator<=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() <= rhs.value(); + } + /// \group unexpected_relop -template -constexpr bool operator>(const unexpected &lhs, const unexpected &rhs) { - return lhs.value() > rhs.value(); -} + template + constexpr bool operator>(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() > rhs.value(); + } + /// \group unexpected_relop -template -constexpr bool operator>=(const unexpected &lhs, const unexpected &rhs) { - return lhs.value() >= rhs.value(); -} + template + constexpr bool operator>=(const unexpected &lhs, const unexpected &rhs) { + return lhs.value() >= rhs.value(); + } /// Create an `unexpected` from `e`, deducing the return type /// /// *Example:* /// auto e1 = tl::make_unexpected(42); /// unexpected e2 (42); //same semantics -template -unexpected::type> make_unexpected(E &&e) { - return unexpected::type>(std::forward(e)); -} + template + unexpected::type> make_unexpected(E &&e) { + return unexpected::type>(std::forward(e)); + } /// \brief A tag type to tell expected to construct the unexpected value -struct unexpect_t { - unexpect_t() = default; -}; + struct unexpect_t { + unexpect_t() = default; + }; + /// \brief A tag to tell expected to construct the unexpected value -static constexpr unexpect_t unexpect{}; + static constexpr unexpect_t unexpect{}; /// \exclude -namespace detail { -template -[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { + namespace detail { + template + [[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - throw std::forward(e); + throw std::forward(e); #else - (void)e; - #ifdef _MSC_VER - __assume(0); - #else - __builtin_unreachable(); - #endif + (void)e; +#ifdef _MSC_VER + __assume(0); +#else + __builtin_unreachable(); #endif -} +#endif + } #ifndef TL_TRAITS_MUTEX #define TL_TRAITS_MUTEX // C++14-style aliases for brevity -template using remove_const_t = typename std::remove_const::type; -template -using remove_reference_t = typename std::remove_reference::type; -template using decay_t = typename std::decay::type; -template -using enable_if_t = typename std::enable_if::type; -template -using conditional_t = typename std::conditional::type; + template using remove_const_t = typename std::remove_const::type; + template + using remove_reference_t = typename std::remove_reference::type; + template using decay_t = typename std::decay::type; + template + using enable_if_t = typename std::enable_if::type; + template + using conditional_t = typename std::conditional::type; // std::conjunction from C++17 -template struct conjunction : std::true_type {}; -template struct conjunction : B {}; -template -struct conjunction - : std::conditional, B>::type {}; + template + struct conjunction : std::true_type { + }; + template + struct conjunction : B { + }; + template + struct conjunction + : std::conditional, B>::type { + }; // std::invoke from C++17 // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround -template >{}>, - int = 0> -constexpr auto invoke(Fn &&f, Args &&... args) noexcept( - noexcept(std::mem_fn(f)(std::forward(args)...))) - -> decltype(std::mem_fn(f)(std::forward(args)...)) { - return std::mem_fn(f)(std::forward(args)...); -} + template>{}>, + int = 0> + constexpr auto invoke(Fn &&f, Args &&... args) noexcept( + noexcept(std::mem_fn(f)(std::forward(args)...))) + -> decltype(std::mem_fn(f)(std::forward(args)...)) { + return std::mem_fn(f)(std::forward(args)...); + } -template >{}>> -constexpr auto invoke(Fn &&f, Args &&... args) noexcept( - noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) { - return std::forward(f)(std::forward(args)...); -} + template>{}>> + constexpr auto invoke(Fn &&f, Args &&... args) noexcept( + noexcept(std::forward(f)(std::forward(args)...))) + -> decltype(std::forward(f)(std::forward(args)...)) { + return std::forward(f)(std::forward(args)...); + } // std::invoke_result from C++17 -template struct invoke_result_impl; + template + struct invoke_result_impl; -template -struct invoke_result_impl< - F, decltype(detail::invoke(std::declval(), std::declval()...), void()), - Us...> { - using type = decltype(detail::invoke(std::declval(), std::declval()...)); -}; + template + struct invoke_result_impl< + F, decltype(detail::invoke(std::declval(), std::declval()...), void()), + Us...> { + using type = decltype(detail::invoke(std::declval(), std::declval()...)); + }; -template -using invoke_result = invoke_result_impl; + template + using invoke_result = invoke_result_impl; -template -using invoke_result_t = typename invoke_result::type; + template + using invoke_result_t = typename invoke_result::type; #endif // Trait for checking if a type is a tl::expected -template struct is_expected_impl : std::false_type {}; -template -struct is_expected_impl> : std::true_type {}; -template using is_expected = is_expected_impl>; + template + struct is_expected_impl : std::false_type { + }; + template + struct is_expected_impl> : std::true_type { + }; + template using is_expected = is_expected_impl>; -template -using expected_enable_forward_value = detail::enable_if_t< - std::is_constructible::value && - !std::is_same, in_place_t>::value && - !std::is_same, detail::decay_t>::value && - !std::is_same, detail::decay_t>::value>; + template + using expected_enable_forward_value = detail::enable_if_t< + std::is_constructible::value && + !std::is_same, in_place_t>::value && + !std::is_same, detail::decay_t>::value && + !std::is_same, detail::decay_t>::value>; -template -using expected_enable_from_other = detail::enable_if_t< - std::is_constructible::value && - std::is_constructible::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value>; + template + using expected_enable_from_other = detail::enable_if_t< + std::is_constructible::value && + std::is_constructible::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value>; -template -using is_void_or = conditional_t::value, std::true_type, U>; + template + using is_void_or = conditional_t::value, std::true_type, U>; -template -using is_copy_constructible_or_void = - is_void_or>; + template + using is_copy_constructible_or_void = + is_void_or>; -template -using is_move_constructible_or_void = - is_void_or>; + template + using is_move_constructible_or_void = + is_void_or>; -template -using is_copy_assignable_or_void = - is_void_or>; + template + using is_copy_assignable_or_void = + is_void_or>; -template -using is_move_assignable_or_void = - is_void_or>; + template + using is_move_assignable_or_void = + is_void_or>; -} // namespace detail + } // namespace detail /// \exclude -namespace detail { -struct no_init_t {}; -static constexpr no_init_t no_init{}; + namespace detail { + struct no_init_t { + }; + static constexpr no_init_t no_init{}; // Implements the storage of the values, and ensures that the destructor is // trivial if it can be. @@ -348,511 +371,557 @@ static constexpr no_init_t no_init{}; // This specialization is for where neither `T` nor `E` is trivially // destructible, so the destructors must be called on destruction of the // `expected` -template ::value, - bool = std::is_trivially_destructible::value> -struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + template::value, + bool = std::is_trivially_destructible::value> + struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) - : m_val(std::forward(args)...), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) - : m_val(il, std::forward(args)...), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) - : m_unexpect(std::forward(args)...), m_has_val(false) {} + template::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&... args) + : m_val(std::forward(args)...), m_has_val(true) {} - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, - std::initializer_list il, - Args &&... args) - : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&... args) + : m_val(il, std::forward(args)...), m_has_val(true) {} - ~expected_storage_base() { - if (m_has_val) { - m_val.~T(); - } else { - m_unexpect.~unexpected(); - } - } - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - bool m_has_val; -}; + template::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&... args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } else { + m_unexpect.~unexpected(); + } + } + + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; + }; // This specialization is for when both `T` and `E` are trivially-destructible, // so the destructor of the `expected` can be trivial. -template struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + template + struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) - : m_val(std::forward(args)...), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) - : m_val(il, std::forward(args)...), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) - : m_unexpect(std::forward(args)...), m_has_val(false) {} + template::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&... args) + : m_val(std::forward(args)...), m_has_val(true) {} - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, - std::initializer_list il, - Args &&... args) - : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&... args) + : m_val(il, std::forward(args)...), m_has_val(true) {} - ~expected_storage_base() = default; - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - bool m_has_val; -}; + template::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&... args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() = default; + + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; + }; // T is trivial, E is not. -template struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) - : m_no_init(), m_has_val(false) {} + template + struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) - : m_val(std::forward(args)...), m_has_val(true) {} + TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) + : m_no_init(), m_has_val(false) {} - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) - : m_val(il, std::forward(args)...), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) - : m_unexpect(std::forward(args)...), m_has_val(false) {} + template::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&... args) + : m_val(std::forward(args)...), m_has_val(true) {} - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, - std::initializer_list il, - Args &&... args) - : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&... args) + : m_val(il, std::forward(args)...), m_has_val(true) {} - ~expected_storage_base() { - if (!m_has_val) { - m_unexpect.~unexpected(); - } - } + template::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - bool m_has_val; -}; + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&... args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (!m_has_val) { + m_unexpect.~unexpected(); + } + } + + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; + }; // E is trivial, T is not. -template struct expected_storage_base { - constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} + template + struct expected_storage_base { + constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr expected_storage_base(in_place_t, Args &&... args) - : m_val(std::forward(args)...), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} - template &, Args &&...>::value> * = nullptr> - constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&... args) - : m_val(il, std::forward(args)...), m_has_val(true) {} - template ::value> * = - nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) - : m_unexpect(std::forward(args)...), m_has_val(false) {} + template::value> * = + nullptr> + constexpr expected_storage_base(in_place_t, Args &&... args) + : m_val(std::forward(args)...), m_has_val(true) {} - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, - std::initializer_list il, - Args &&... args) - : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + template &, Args &&...>::value> * = nullptr> + constexpr expected_storage_base(in_place_t, std::initializer_list il, + Args &&... args) + : m_val(il, std::forward(args)...), m_has_val(true) {} - ~expected_storage_base() { - if (m_has_val) { - m_val.~T(); - } - } - union { - T m_val; - unexpected m_unexpect; - char m_no_init; - }; - bool m_has_val; -}; + template::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} + + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&... args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() { + if (m_has_val) { + m_val.~T(); + } + } + + union { + T m_val; + unexpected m_unexpect; + char m_no_init; + }; + bool m_has_val; + }; // `T` is `void`, `E` is trivially-destructible -template struct expected_storage_base { - TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base() : m_has_val(true) {} - constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} + template + struct expected_storage_base { + TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base() : m_has_val(true) {} - constexpr expected_storage_base(in_place_t) : m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {} - template ::value> * = - nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) - : m_unexpect(std::forward(args)...), m_has_val(false) {} + constexpr expected_storage_base(in_place_t) : m_has_val(true) {} - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, - std::initializer_list il, - Args &&... args) - : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + template::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} - ~expected_storage_base() = default; - struct dummy {}; - union { - unexpected m_unexpect; - dummy m_val; - }; - bool m_has_val; -}; + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&... args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + + ~expected_storage_base() = default; + + struct dummy { + }; + union { + unexpected m_unexpect; + dummy m_val; + }; + bool m_has_val; + }; // `T` is `void`, `E` is not trivially-destructible -template struct expected_storage_base { - constexpr expected_storage_base() : m_dummy(), m_has_val(true) {} - constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {} + template + struct expected_storage_base { + constexpr expected_storage_base() : m_dummy(), m_has_val(true) {} - constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {} - template ::value> * = - nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&... args) - : m_unexpect(std::forward(args)...), m_has_val(false) {} + constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, - std::initializer_list il, - Args &&... args) - : m_unexpect(il, std::forward(args)...), m_has_val(false) {} + template::value> * = + nullptr> + constexpr explicit expected_storage_base(unexpect_t, Args &&... args) + : m_unexpect(std::forward(args)...), m_has_val(false) {} - ~expected_storage_base() { - if (!m_has_val) { - m_unexpect.~unexpected(); - } - } + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected_storage_base(unexpect_t, + std::initializer_list il, + Args &&... args) + : m_unexpect(il, std::forward(args)...), m_has_val(false) {} - union { - unexpected m_unexpect; - char m_dummy; - }; - bool m_has_val; -}; + ~expected_storage_base() { + if (!m_has_val) { + m_unexpect.~unexpected(); + } + } + + union { + unexpected m_unexpect; + char m_dummy; + }; + bool m_has_val; + }; // This base class provides some handy member functions which can be used in // further derived classes -template -struct expected_operations_base : expected_storage_base { - using expected_storage_base::expected_storage_base; + template + struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; - template void construct(Args &&... args) noexcept { - new (std::addressof(this->m_val)) T(std::forward(args)...); - this->m_has_val = true; - } + template + void construct(Args &&... args) noexcept { + new(std::addressof(this->m_val)) T(std::forward(args)...); + this->m_has_val = true; + } - template void construct_with(Rhs &&rhs) noexcept { - new (std::addressof(this->m_val)) T(std::forward(rhs).get()); - this->m_has_val = true; - } + template + void construct_with(Rhs &&rhs) noexcept { + new(std::addressof(this->m_val)) T(std::forward(rhs).get()); + this->m_has_val = true; + } - template void construct_error(Args &&... args) noexcept { - new (std::addressof(this->m_unexpect)) - unexpected(std::forward(args)...); - this->m_has_val = false; - } + template + void construct_error(Args &&... args) noexcept { + new(std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); + this->m_has_val = false; + } - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - // These assign overloads ensure that the most efficient assignment - // implementation is used while maintaining the strong exception guarantee. - // The problematic case is where rhs has a value, but *this does not. - // - // This overload handles the case where we can just copy-construct `T` - // directly into place without throwing. - template ::value> - * = nullptr> - void assign(const expected_operations_base &rhs) noexcept { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(rhs.get()); - } else { - assign_common(rhs); - } - } + // These assign overloads ensure that the most efficient assignment + // implementation is used while maintaining the strong exception guarantee. + // The problematic case is where rhs has a value, but *this does not. + // + // This overload handles the case where we can just copy-construct `T` + // directly into place without throwing. + template::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } - // This overload handles the case where we can attempt to create a copy of - // `T`, then no-throw move it into place if the copy was successful. - template ::value && - std::is_nothrow_move_constructible::value> - * = nullptr> - void assign(const expected_operations_base &rhs) noexcept { - if (!this->m_has_val && rhs.m_has_val) { - T tmp = rhs.get(); - geterr().~unexpected(); - construct(std::move(tmp)); - } else { - assign_common(rhs); - } - } + // This overload handles the case where we can attempt to create a copy of + // `T`, then no-throw move it into place if the copy was successful. + template::value && + std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + T tmp = rhs.get(); + geterr().~unexpected(); + construct(std::move(tmp)); + } else { + assign_common(rhs); + } + } - // This overload is the worst-case, where we have to move-construct the - // unexpected value into temporary storage, then try to copy the T into place. - // If the construction succeeds, then everything is fine, but if it throws, - // then we move the old unexpected value back into place before rethrowing the - // exception. - template ::value && - !std::is_nothrow_move_constructible::value> - * = nullptr> - void assign(const expected_operations_base &rhs) { - if (!this->m_has_val && rhs.m_has_val) { - auto tmp = std::move(geterr()); - geterr().~unexpected(); + // This overload is the worst-case, where we have to move-construct the + // unexpected value into temporary storage, then try to copy the T into place. + // If the construction succeeds, then everything is fine, but if it throws, + // then we move the old unexpected value back into place before rethrowing the + // exception. + template::value && + !std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) { + if (!this->m_has_val && rhs.m_has_val) { + auto tmp = std::move(geterr()); + geterr().~unexpected(); - try { - construct(rhs.get()); - } catch (...) { - geterr() = std::move(tmp); - throw; - } - } else { - assign_common(rhs); - } - } + try { + construct(rhs.get()); + } catch (...) { + geterr() = std::move(tmp); + throw; + } + } else { + assign_common(rhs); + } + } - // These overloads do the same as above, but for rvalues - template ::value> - * = nullptr> - void assign(expected_operations_base &&rhs) noexcept { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(std::move(rhs).get()); - } else { - assign_common(std::move(rhs)); - } - } + // These overloads do the same as above, but for rvalues + template::value> + * = nullptr> + void assign(expected_operations_base &&rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(std::move(rhs)); + } + } - template ::value> - * = nullptr> - void assign(expected_operations_base &&rhs) { - if (!this->m_has_val && rhs.m_has_val) { - auto tmp = std::move(geterr()); - geterr().~unexpected(); - try { - construct(std::move(rhs).get()); - } catch (...) { - geterr() = std::move(tmp); - throw; - } - } else { - assign_common(std::move(rhs)); - } - } + template::value> + * = nullptr> + void assign(expected_operations_base &&rhs) { + if (!this->m_has_val && rhs.m_has_val) { + auto tmp = std::move(geterr()); + geterr().~unexpected(); + try { + construct(std::move(rhs).get()); + } catch (...) { + geterr() = std::move(tmp); + throw; + } + } else { + assign_common(std::move(rhs)); + } + } - #else +#else - // If exceptions are disabled then we can just copy-construct - void assign(const expected_operations_base &rhs) noexcept { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(rhs.get()); - } else { - assign_common(rhs); - } - } + // If exceptions are disabled then we can just copy-construct + void assign(const expected_operations_base &rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(rhs.get()); + } else { + assign_common(rhs); + } + } - void assign(expected_operations_base &&rhs) noexcept { - if (!this->m_has_val && rhs.m_has_val) { - geterr().~unexpected(); - construct(std::move(rhs).get()); - } else { - assign_common(rhs); - } - } + void assign(expected_operations_base &&rhs) noexcept { + if (!this->m_has_val && rhs.m_has_val) { + geterr().~unexpected(); + construct(std::move(rhs).get()); + } else { + assign_common(rhs); + } + } - #endif - - // The common part of move/copy assigning - template void assign_common(Rhs &&rhs) { - if (this->m_has_val) { - if (rhs.m_has_val) { - get() = std::forward(rhs).get(); - } else { - destroy_val(); - construct_error(std::forward(rhs).geterr()); - } - } else { - if (!rhs.m_has_val) { - geterr() = std::forward(rhs).geterr(); - } - } - } - - bool has_value() const { return this->m_has_val; } - - TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } - constexpr const T &get() const & { return this->m_val; } - TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); } -#ifndef TL_EXPECTED_NO_CONSTRR - constexpr const T &&get() const && { return std::move(this->m_val); } #endif - TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { - return this->m_unexpect; - } - constexpr const unexpected &geterr() const & { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { - return std::move(this->m_unexpect); - } + // The common part of move/copy assigning + template + void assign_common(Rhs &&rhs) { + if (this->m_has_val) { + if (rhs.m_has_val) { + get() = std::forward(rhs).get(); + } else { + destroy_val(); + construct_error(std::forward(rhs).geterr()); + } + } else { + if (!rhs.m_has_val) { + geterr() = std::forward(rhs).geterr(); + } + } + } + + bool has_value() const { return this->m_has_val; } + + TL_EXPECTED_11_CONSTEXPR T &get() &{ return this->m_val; } + + constexpr const T &get() const &{ return this->m_val; } + + TL_EXPECTED_11_CONSTEXPR T &&get() &&{ return std::move(this->m_val); } + #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected &&geterr() const && { - return std::move(this->m_unexpect); - } + + constexpr const T &&get() const &&{ return std::move(this->m_val); } + #endif - TL_EXPECTED_11_CONSTEXPR void destroy_val() { - get().~T(); - } -}; + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() &{ + return this->m_unexpect; + } + + constexpr const unexpected &geterr() const &{ return this->m_unexpect; } + + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() &&{ + return std::move(this->m_unexpect); + } + +#ifndef TL_EXPECTED_NO_CONSTRR + + constexpr const unexpected &&geterr() const &&{ + return std::move(this->m_unexpect); + } + +#endif + + TL_EXPECTED_11_CONSTEXPR void destroy_val() { + get().~T(); + } + }; // This base class provides some handy member functions which can be used in // further derived classes -template -struct expected_operations_base : expected_storage_base { - using expected_storage_base::expected_storage_base; + template + struct expected_operations_base : expected_storage_base { + using expected_storage_base::expected_storage_base; - template void construct() noexcept { this->m_has_val = true; } + template + void construct() noexcept { this->m_has_val = true; } - // This function doesn't use its argument, but needs it so that code in - // levels above this can work independently of whether T is void - template void construct_with(Rhs &&) noexcept { - this->m_has_val = true; - } + // This function doesn't use its argument, but needs it so that code in + // levels above this can work independently of whether T is void + template + void construct_with(Rhs &&) noexcept { + this->m_has_val = true; + } - template void construct_error(Args &&... args) noexcept { - new (std::addressof(this->m_unexpect)) - unexpected(std::forward(args)...); - this->m_has_val = false; - } + template + void construct_error(Args &&... args) noexcept { + new(std::addressof(this->m_unexpect)) + unexpected(std::forward(args)...); + this->m_has_val = false; + } - template void assign(Rhs &&rhs) noexcept { - if (!this->m_has_val) { - if (rhs.m_has_val) { - geterr().~unexpected(); - construct(); - } else { - geterr() = std::forward(rhs).geterr(); - } - } else { - if (!rhs.m_has_val) { - construct_error(std::forward(rhs).geterr()); - } - } - } + template + void assign(Rhs &&rhs) noexcept { + if (!this->m_has_val) { + if (rhs.m_has_val) { + geterr().~unexpected(); + construct(); + } else { + geterr() = std::forward(rhs).geterr(); + } + } else { + if (!rhs.m_has_val) { + construct_error(std::forward(rhs).geterr()); + } + } + } - bool has_value() const { return this->m_has_val; } + bool has_value() const { return this->m_has_val; } + + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() &{ + return this->m_unexpect; + } + + constexpr const unexpected &geterr() const &{ return this->m_unexpect; } + + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() &&{ + return std::move(this->m_unexpect); + } - TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { - return this->m_unexpect; - } - constexpr const unexpected &geterr() const & { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { - return std::move(this->m_unexpect); - } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected &&geterr() const && { - return std::move(this->m_unexpect); - } + + constexpr const unexpected &&geterr() const &&{ + return std::move(this->m_unexpect); + } + #endif - TL_EXPECTED_11_CONSTEXPR void destroy_val() { - //no-op - } -}; + TL_EXPECTED_11_CONSTEXPR void destroy_val() { + //no-op + } + }; // This class manages conditionally having a trivial copy constructor // This specialization is for when T and E are trivially copy constructible -template :: - value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> -struct expected_copy_base : expected_operations_base { - using expected_operations_base::expected_operations_base; -}; + template:: + value && TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> + struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; + }; // This specialization is for when T or E are not trivially copy constructible -template -struct expected_copy_base : expected_operations_base { - using expected_operations_base::expected_operations_base; + template + struct expected_copy_base : expected_operations_base { + using expected_operations_base::expected_operations_base; - expected_copy_base() = default; - expected_copy_base(const expected_copy_base &rhs) - : expected_operations_base(no_init) { - if (rhs.has_value()) { - this->construct_with(rhs); - } else { - this->construct_error(rhs.geterr()); - } - } + expected_copy_base() = default; - expected_copy_base(expected_copy_base &&rhs) = default; - expected_copy_base &operator=(const expected_copy_base &rhs) = default; - expected_copy_base &operator=(expected_copy_base &&rhs) = default; -}; + expected_copy_base(const expected_copy_base &rhs) + : expected_operations_base(no_init) { + if (rhs.has_value()) { + this->construct_with(rhs); + } else { + this->construct_error(rhs.geterr()); + } + } + + expected_copy_base(expected_copy_base &&rhs) = default; + + expected_copy_base &operator=(const expected_copy_base &rhs) = default; + + expected_copy_base &operator=(expected_copy_base &&rhs) = default; + }; // This class manages conditionally having a trivial move constructor // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it @@ -860,63 +929,70 @@ struct expected_copy_base : expected_operations_base { // have to make do with a non-trivial move constructor even if T is trivially // move constructible #ifndef TL_EXPECTED_GCC49 -template >::value - &&std::is_trivially_move_constructible::value> -struct expected_move_base : expected_copy_base { - using expected_copy_base::expected_copy_base; -}; + template>::value + && std::is_trivially_move_constructible::value> + struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; + }; #else -template struct expected_move_base; + template struct expected_move_base; #endif -template -struct expected_move_base : expected_copy_base { - using expected_copy_base::expected_copy_base; - expected_move_base() = default; - expected_move_base(const expected_move_base &rhs) = default; + template + struct expected_move_base : expected_copy_base { + using expected_copy_base::expected_copy_base; - expected_move_base(expected_move_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value) - : expected_copy_base(no_init) { - if (rhs.has_value()) { - this->construct_with(std::move(rhs)); - } else { - this->construct_error(std::move(rhs.geterr())); - } - } - expected_move_base &operator=(const expected_move_base &rhs) = default; - expected_move_base &operator=(expected_move_base &&rhs) = default; -}; + expected_move_base() = default; + + expected_move_base(const expected_move_base &rhs) = default; + + expected_move_base(expected_move_base &&rhs) noexcept( + std::is_nothrow_move_constructible::value) + : expected_copy_base(no_init) { + if (rhs.has_value()) { + this->construct_with(std::move(rhs)); + } else { + this->construct_error(std::move(rhs.geterr())); + } + } + + expected_move_base &operator=(const expected_move_base &rhs) = default; + + expected_move_base &operator=(expected_move_base &&rhs) = default; + }; // This class manages conditionally having a trivial copy assignment operator -template >::value - &&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value - &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value - &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> -struct expected_copy_assign_base : expected_move_base { - using expected_move_base::expected_move_base; -}; + template>::value + && TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value + && TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value + && TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> + struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; + }; -template -struct expected_copy_assign_base : expected_move_base { - using expected_move_base::expected_move_base; + template + struct expected_copy_assign_base : expected_move_base { + using expected_move_base::expected_move_base; - expected_copy_assign_base() = default; - expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; + expected_copy_assign_base() = default; - expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; - expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) { - this->assign(rhs); - return *this; - } - expected_copy_assign_base & - operator=(expected_copy_assign_base &&rhs) = default; -}; + expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; + + expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; + + expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) { + this->assign(rhs); + return *this; + } + + expected_copy_assign_base & + operator=(expected_copy_assign_base &&rhs) = default; + }; // This class manages conditionally having a trivial move assignment operator // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it @@ -924,210 +1000,256 @@ struct expected_copy_assign_base : expected_move_base { // to make do with a non-trivial move assignment operator even if T is trivially // move assignable #ifndef TL_EXPECTED_GCC49 -template , - std::is_trivially_move_constructible, - std::is_trivially_move_assignable>>:: - value &&std::is_trivially_destructible::value - &&std::is_trivially_move_constructible::value - &&std::is_trivially_move_assignable::value> -struct expected_move_assign_base : expected_copy_assign_base { - using expected_copy_assign_base::expected_copy_assign_base; -}; + template, + std::is_trivially_move_constructible, + std::is_trivially_move_assignable>>:: + value && std::is_trivially_destructible::value + && std::is_trivially_move_constructible::value + && std::is_trivially_move_assignable::value> + struct expected_move_assign_base : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; + }; #else -template struct expected_move_assign_base; + template struct expected_move_assign_base; #endif -template -struct expected_move_assign_base - : expected_copy_assign_base { - using expected_copy_assign_base::expected_copy_assign_base; + template + struct expected_move_assign_base + : expected_copy_assign_base { + using expected_copy_assign_base::expected_copy_assign_base; - expected_move_assign_base() = default; - expected_move_assign_base(const expected_move_assign_base &rhs) = default; + expected_move_assign_base() = default; - expected_move_assign_base(expected_move_assign_base &&rhs) = default; + expected_move_assign_base(const expected_move_assign_base &rhs) = default; - expected_move_assign_base & - operator=(const expected_move_assign_base &rhs) = default; + expected_move_assign_base(expected_move_assign_base &&rhs) = default; - expected_move_assign_base & - operator=(expected_move_assign_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_assignable::value) { - this->assign(std::move(rhs)); - return *this; - } -}; + expected_move_assign_base & + operator=(const expected_move_assign_base &rhs) = default; + + expected_move_assign_base & + operator=(expected_move_assign_base &&rhs) noexcept( + std::is_nothrow_move_constructible::value + && std::is_nothrow_move_assignable::value) { + this->assign(std::move(rhs)); + return *this; + } + }; // expected_delete_ctor_base will conditionally delete copy and move // constructors depending on whether T is copy/move constructible -template ::value && - std::is_copy_constructible::value), - bool EnableMove = (is_move_constructible_or_void::value && - std::is_move_constructible::value)> -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base & - operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base & - operator=(expected_delete_ctor_base &&) noexcept = default; -}; + template::value && + std::is_copy_constructible::value), + bool EnableMove = (is_move_constructible_or_void::value && + std::is_move_constructible::value)> + struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; -template -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base & - operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base & - operator=(expected_delete_ctor_base &&) noexcept = default; -}; + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; -template -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base & - operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base & - operator=(expected_delete_ctor_base &&) noexcept = default; -}; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; -template -struct expected_delete_ctor_base { - expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base & - operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base & - operator=(expected_delete_ctor_base &&) noexcept = default; -}; + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; + }; + + template + struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; + }; + + template + struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; + }; + + template + struct expected_delete_ctor_base { + expected_delete_ctor_base() = default; + + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + + expected_delete_ctor_base & + operator=(const expected_delete_ctor_base &) = default; + + expected_delete_ctor_base & + operator=(expected_delete_ctor_base &&) noexcept = default; + }; // expected_delete_assign_base will conditionally delete copy and move // constructors depending on whether T and E are copy/move constructible + // assignable -template ::value && - std::is_copy_constructible::value && - is_copy_assignable_or_void::value && - std::is_copy_assignable::value), - bool EnableMove = (is_move_constructible_or_void::value && - std::is_move_constructible::value && - is_move_assignable_or_void::value && - std::is_move_assignable::value)> -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base & - operator=(const expected_delete_assign_base &) = default; - expected_delete_assign_base & - operator=(expected_delete_assign_base &&) noexcept = default; -}; + template::value && + std::is_copy_constructible::value && + is_copy_assignable_or_void::value && + std::is_copy_assignable::value), + bool EnableMove = (is_move_constructible_or_void::value && + std::is_move_constructible::value && + is_move_assignable_or_void::value && + std::is_move_assignable::value)> + struct expected_delete_assign_base { + expected_delete_assign_base() = default; -template -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base & - operator=(const expected_delete_assign_base &) = default; - expected_delete_assign_base & - operator=(expected_delete_assign_base &&) noexcept = delete; -}; + expected_delete_assign_base(const expected_delete_assign_base &) = default; -template -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base & - operator=(const expected_delete_assign_base &) = delete; - expected_delete_assign_base & - operator=(expected_delete_assign_base &&) noexcept = default; -}; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; -template -struct expected_delete_assign_base { - expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base & - operator=(const expected_delete_assign_base &) = delete; - expected_delete_assign_base & - operator=(expected_delete_assign_base &&) noexcept = delete; -}; + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; + }; + + template + struct expected_delete_assign_base { + expected_delete_assign_base() = default; + + expected_delete_assign_base(const expected_delete_assign_base &) = default; + + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = default; + + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; + }; + + template + struct expected_delete_assign_base { + expected_delete_assign_base() = default; + + expected_delete_assign_base(const expected_delete_assign_base &) = default; + + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = default; + }; + + template + struct expected_delete_assign_base { + expected_delete_assign_base() = default; + + expected_delete_assign_base(const expected_delete_assign_base &) = default; + + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + + expected_delete_assign_base & + operator=(const expected_delete_assign_base &) = delete; + + expected_delete_assign_base & + operator=(expected_delete_assign_base &&) noexcept = delete; + }; // This is needed to be able to construct the expected_default_ctor_base which // follows, while still conditionally deleting the default constructor. -struct default_constructor_tag { - explicit constexpr default_constructor_tag() = default; -}; + struct default_constructor_tag { + explicit constexpr default_constructor_tag() = default; + }; // expected_default_ctor_base will ensure that expected has a deleted default // consturctor if T is not default constructible. // This specialization is for when T is default constructible -template ::value || std::is_void::value> -struct expected_default_ctor_base { - constexpr expected_default_ctor_base() noexcept = default; - constexpr expected_default_ctor_base( - expected_default_ctor_base const &) noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = - default; - expected_default_ctor_base & - operator=(expected_default_ctor_base const &) noexcept = default; - expected_default_ctor_base & - operator=(expected_default_ctor_base &&) noexcept = default; + template::value || std::is_void::value> + struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = default; - constexpr explicit expected_default_ctor_base(default_constructor_tag) {} -}; + constexpr expected_default_ctor_base( + expected_default_ctor_base const &) noexcept = default; + + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + default; + + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; + + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; + + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} + }; // This specialization is for when T is not default constructible -template struct expected_default_ctor_base { - constexpr expected_default_ctor_base() noexcept = delete; - constexpr expected_default_ctor_base( - expected_default_ctor_base const &) noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = - default; - expected_default_ctor_base & - operator=(expected_default_ctor_base const &) noexcept = default; - expected_default_ctor_base & - operator=(expected_default_ctor_base &&) noexcept = default; + template + struct expected_default_ctor_base { + constexpr expected_default_ctor_base() noexcept = delete; - constexpr explicit expected_default_ctor_base(default_constructor_tag) {} -}; -} // namespace detail + constexpr expected_default_ctor_base( + expected_default_ctor_base const &) noexcept = default; -template class bad_expected_access : public std::exception { -public: - explicit bad_expected_access(E e) : m_val(std::move(e)) {} + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + default; - virtual const char *what() const noexcept override { - return "Bad expected access"; - } + expected_default_ctor_base & + operator=(expected_default_ctor_base const &) noexcept = default; - const E &error() const & { return m_val; } - E &error() & { return m_val; } - const E &&error() const && { return std::move(m_val); } - E &&error() && { return std::move(m_val); } + expected_default_ctor_base & + operator=(expected_default_ctor_base &&) noexcept = default; -private: - E m_val; -}; + constexpr explicit expected_default_ctor_base(default_constructor_tag) {} + }; + } // namespace detail + + template + class bad_expected_access : public std::exception { + public: + explicit bad_expected_access(E e) : m_val(std::move(e)) {} + + virtual const char *what() const noexcept override { + return "Bad expected access"; + } + + const E &error() const &{ return m_val; } + + E &error() &{ return m_val; } + + const E &&error() const &&{ return std::move(m_val); } + + E &&error() &&{ return std::move(m_val); } + + private: + E m_val; + }; /// An `expected` object is an object that contains the storage for /// another object and manages the lifetime of this contained object `T`. @@ -1136,1147 +1258,1211 @@ private: /// has been initialized, and may not be destroyed before the expected object /// has been destroyed. The initialization state of the contained object is /// tracked by the expected object. -template -class expected : private detail::expected_move_assign_base, - private detail::expected_delete_ctor_base, - private detail::expected_delete_assign_base, - private detail::expected_default_ctor_base { - static_assert(!std::is_reference::value, "T must not be a reference"); - static_assert(!std::is_same>::value, - "T must not be in_place_t"); - static_assert(!std::is_same>::value, - "T must not be unexpect_t"); - static_assert(!std::is_same>>::value, - "T must not be unexpected"); - static_assert(!std::is_reference::value, "E must not be a reference"); + template + class expected : private detail::expected_move_assign_base, + private detail::expected_delete_ctor_base, + private detail::expected_delete_assign_base, + private detail::expected_default_ctor_base { + static_assert(!std::is_reference::value, "T must not be a reference"); + static_assert(!std::is_same>::value, + "T must not be in_place_t"); + static_assert(!std::is_same>::value, + "T must not be unexpect_t"); + static_assert(!std::is_same>>::value, + "T must not be unexpected"); + static_assert(!std::is_reference::value, "E must not be a reference"); - T *valptr() { return std::addressof(this->m_val); } - const T *valptr() const { return std::addressof(this->m_val); } - unexpected *errptr() { return std::addressof(this->m_unexpect); } - const unexpected *errptr() const { return std::addressof(this->m_unexpect); } + T *valptr() { return std::addressof(this->m_val); } - template ::value> * = nullptr> - U &val() { - return this->m_val; - } - unexpected &err() { return this->m_unexpect; } + const T *valptr() const { return std::addressof(this->m_val); } - template ::value> * = nullptr> - const U &val() const { - return this->m_val; - } - const unexpected &err() const { return this->m_unexpect; } + unexpected *errptr() { return std::addressof(this->m_unexpect); } - using impl_base = detail::expected_move_assign_base; - using ctor_base = detail::expected_default_ctor_base; + const unexpected *errptr() const { return std::addressof(this->m_unexpect); } -public: - typedef T value_type; - typedef E error_type; - typedef unexpected unexpected_type; + template::value> * = nullptr> + U &val() { + return this->m_val; + } -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ + unexpected &err() { return this->m_unexpect; } + + template::value> * = nullptr> + const U &val() const { + return this->m_val; + } + + const unexpected &err() const { return this->m_unexpect; } + + using impl_base = detail::expected_move_assign_base; + using ctor_base = detail::expected_default_ctor_base; + + public: + typedef T value_type; + typedef E error_type; + typedef unexpected unexpected_type; + +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - /// \group and_then - /// Carries out some operation which returns an expected on the stored object - /// if there is one. \requires `std::invoke(std::forward(f), value())` - /// returns an `expected` for some `U`. \returns Let `U` be the result - /// of `std::invoke(std::forward(f), value())`. Returns an - /// `expected`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { - return and_then_impl(*this, std::forward(f)); - } - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { - return and_then_impl(std::move(*this), std::forward(f)); - } + /// \group and_then + /// Carries out some operation which returns an expected on the stored object + /// if there is one. \requires `std::invoke(std::forward(f), value())` + /// returns an `expected` for some `U`. \returns Let `U` be the result + /// of `std::invoke(std::forward(f), value())`. Returns an + /// `expected`. The return value is empty if `*this` is empty, + /// otherwise the return value of `std::invoke(std::forward(f), value())` + /// is returned. + /// \synopsis template \nconstexpr auto and_then(F &&f) &; + template + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) &{ + return and_then_impl(*this, std::forward(f)); + } - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template constexpr auto and_then(F &&f) const & { - return and_then_impl(*this, std::forward(f)); - } + /// \group and_then + /// \synopsis template \nconstexpr auto and_then(F &&f) &&; + template + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) &&{ + return and_then_impl(std::move(*this), std::forward(f)); + } + + /// \group and_then + /// \synopsis template \nconstexpr auto and_then(F &&f) const &; + template + constexpr auto and_then(F &&f) const &{ + return and_then_impl(*this, std::forward(f)); + } #ifndef TL_EXPECTED_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template constexpr auto and_then(F &&f) const && { - return and_then_impl(std::move(*this), std::forward(f)); - } + + /// \group and_then + /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; + template + constexpr auto and_then(F &&f) const &&{ + return and_then_impl(std::move(*this), std::forward(f)); + } + #endif #else - /// \group and_then - /// Carries out some operation which returns an expected on the stored object - /// if there is one. \requires `std::invoke(std::forward(f), value())` - /// returns an `expected` for some `U`. \returns Let `U` be the result - /// of `std::invoke(std::forward(f), value())`. Returns an - /// `expected`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - TL_EXPECTED_11_CONSTEXPR auto - and_then(F &&f) & -> decltype(and_then_impl(std::declval(), std::forward(f))) { - return and_then_impl(*this, std::forward(f)); - } + /// \group and_then + /// Carries out some operation which returns an expected on the stored object + /// if there is one. \requires `std::invoke(std::forward(f), value())` + /// returns an `expected` for some `U`. \returns Let `U` be the result + /// of `std::invoke(std::forward(f), value())`. Returns an + /// `expected`. The return value is empty if `*this` is empty, + /// otherwise the return value of `std::invoke(std::forward(f), value())` + /// is returned. + /// \synopsis template \nconstexpr auto and_then(F &&f) &; + template + TL_EXPECTED_11_CONSTEXPR auto + and_then(F &&f) & -> decltype(and_then_impl(std::declval(), std::forward(f))) { + return and_then_impl(*this, std::forward(f)); + } - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype( - and_then_impl(std::declval(), std::forward(f))) { - return and_then_impl(std::move(*this), std::forward(f)); - } + /// \group and_then + /// \synopsis template \nconstexpr auto and_then(F &&f) &&; + template + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype( + and_then_impl(std::declval(), std::forward(f))) { + return and_then_impl(std::move(*this), std::forward(f)); + } - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr auto and_then(F &&f) const & -> decltype( - and_then_impl(std::declval(), std::forward(f))) { - return and_then_impl(*this, std::forward(f)); - } + /// \group and_then + /// \synopsis template \nconstexpr auto and_then(F &&f) const &; + template + constexpr auto and_then(F &&f) const & -> decltype( + and_then_impl(std::declval(), std::forward(f))) { + return and_then_impl(*this, std::forward(f)); + } #ifndef TL_EXPECTED_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr auto and_then(F &&f) const && -> decltype( - and_then_impl(std::declval(), std::forward(f))) { - return and_then_impl(std::move(*this), std::forward(f)); - } + /// \group and_then + /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; + template + constexpr auto and_then(F &&f) const && -> decltype( + and_then_impl(std::declval(), std::forward(f))) { + return and_then_impl(std::move(*this), std::forward(f)); + } #endif #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. If `U` is `void`, returns an `expected, otherwise - // returns an `expected`. If `*this` is unexpected, the - /// result is `*this`, otherwise an `expected` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template constexpr auto map(F &&f) &; - template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { - return expected_map_impl(*this, std::forward(f)); - } - /// \group map - /// \synopsis template constexpr auto map(F &&f) &&; - template TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { - return expected_map_impl(std::move(*this), std::forward(f)); - } + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward(f), + /// value())`. If `U` is `void`, returns an `expected, otherwise + // returns an `expected`. If `*this` is unexpected, the + /// result is `*this`, otherwise an `expected` is constructed from the + /// return value of `std::invoke(std::forward(f), value())` and is + /// returned. + /// + /// \group map + /// \synopsis template constexpr auto map(F &&f) &; + template + TL_EXPECTED_11_CONSTEXPR auto map(F &&f) &{ + return expected_map_impl(*this, std::forward(f)); + } - /// \group map - /// \synopsis template constexpr auto map(F &&f) const &; - template constexpr auto map(F &&f) const & { - return expected_map_impl(*this, std::forward(f)); - } + /// \group map + /// \synopsis template constexpr auto map(F &&f) &&; + template + TL_EXPECTED_11_CONSTEXPR auto map(F &&f) &&{ + return expected_map_impl(std::move(*this), std::forward(f)); + } + + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &; + template + constexpr auto map(F &&f) const &{ + return expected_map_impl(*this, std::forward(f)); + } + + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &&; + template + constexpr auto map(F &&f) const &&{ + return expected_map_impl(std::move(*this), std::forward(f)); + } - /// \group map - /// \synopsis template constexpr auto map(F &&f) const &&; - template constexpr auto map(F &&f) const && { - return expected_map_impl(std::move(*this), std::forward(f)); - } #else - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. If `U` is `void`, returns an `expected, otherwise - // returns an `expected`. If `*this` is unexpected, the - /// result is `*this`, otherwise an `expected` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template constexpr auto map(F &&f) &; - template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) - map(F &&f) & { - return expected_map_impl(*this, std::forward(f)); - } + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward(f), + /// value())`. If `U` is `void`, returns an `expected, otherwise + // returns an `expected`. If `*this` is unexpected, the + /// result is `*this`, otherwise an `expected` is constructed from the + /// return value of `std::invoke(std::forward(f), value())` and is + /// returned. + /// + /// \group map + /// \synopsis template constexpr auto map(F &&f) &; + template + TL_EXPECTED_11_CONSTEXPR decltype( + expected_map_impl(std::declval(), std::declval())) + map(F &&f) & { + return expected_map_impl(*this, std::forward(f)); + } - /// \group map - /// \synopsis template constexpr auto map(F &&f) &&; - template - TL_EXPECTED_11_CONSTEXPR decltype( - expected_map_impl(std::declval(), std::declval())) - map(F &&f) && { - return expected_map_impl(std::move(*this), std::forward(f)); - } + /// \group map + /// \synopsis template constexpr auto map(F &&f) &&; + template + TL_EXPECTED_11_CONSTEXPR decltype( + expected_map_impl(std::declval(), std::declval())) + map(F &&f) && { + return expected_map_impl(std::move(*this), std::forward(f)); + } - /// \group map - /// \synopsis template constexpr auto map(F &&f) const &; - template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) const & { - return expected_map_impl(*this, std::forward(f)); - } + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &; + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const & { + return expected_map_impl(*this, std::forward(f)); + } #ifndef TL_EXPECTED_NO_CONSTRR - /// \group map - /// \synopsis template constexpr auto map(F &&f) const &&; - template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) const && { - return expected_map_impl(std::move(*this), std::forward(f)); - } + /// \group map + /// \synopsis template constexpr auto map(F &&f) const &&; + template + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const && { + return expected_map_impl(std::move(*this), std::forward(f)); + } #endif #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) - /// \brief Carries out some operation on the stored unexpected object if there - /// is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. If `U` is `void`, returns an `expected`, otherwise - /// returns an `expected`. If `*this` has an expected - /// value, the result is `*this`, otherwise an `expected` is constructed - /// from `make_unexpected(std::invoke(std::forward(f), value()))` and is - /// returned. - /// - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) &; - template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { - return map_error_impl(*this, std::forward(f)); - } - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) &&; - template TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { - return map_error_impl(std::move(*this), std::forward(f)); - } + /// \brief Carries out some operation on the stored unexpected object if there + /// is one. + /// \returns Let `U` be the result of `std::invoke(std::forward(f), + /// value())`. If `U` is `void`, returns an `expected`, otherwise + /// returns an `expected`. If `*this` has an expected + /// value, the result is `*this`, otherwise an `expected` is constructed + /// from `make_unexpected(std::invoke(std::forward(f), value()))` and is + /// returned. + /// + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &; + template + TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) &{ + return map_error_impl(*this, std::forward(f)); + } - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) const &; - template constexpr auto map_error(F &&f) const & { - return map_error_impl(*this, std::forward(f)); - } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &&; + template + TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) &&{ + return map_error_impl(std::move(*this), std::forward(f)); + } + + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &; + template + constexpr auto map_error(F &&f) const &{ + return map_error_impl(*this, std::forward(f)); + } + + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &&; + template + constexpr auto map_error(F &&f) const &&{ + return map_error_impl(std::move(*this), std::forward(f)); + } - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) const &&; - template constexpr auto map_error(F &&f) const && { - return map_error_impl(std::move(*this), std::forward(f)); - } #else - /// \brief Carries out some operation on the stored unexpected object if there - /// is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns an `expected`. If `*this` has an expected - /// value, the result is `*this`, otherwise an `expected` is constructed - /// from `make_unexpected(std::invoke(std::forward(f), value()))` and is - /// returned. - /// - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) &; - template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) & { - return map_error_impl(*this, std::forward(f)); - } + /// \brief Carries out some operation on the stored unexpected object if there + /// is one. + /// \returns Let `U` be the result of `std::invoke(std::forward(f), + /// value())`. Returns an `expected`. If `*this` has an expected + /// value, the result is `*this`, otherwise an `expected` is constructed + /// from `make_unexpected(std::invoke(std::forward(f), value()))` and is + /// returned. + /// + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &; + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) & { + return map_error_impl(*this, std::forward(f)); + } - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) &&; - template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) && { - return map_error_impl(std::move(*this), std::forward(f)); - } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) &&; + template + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) && { + return map_error_impl(std::move(*this), std::forward(f)); + } - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) const &; - template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) const & { - return map_error_impl(*this, std::forward(f)); - } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &; + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const & { + return map_error_impl(*this, std::forward(f)); + } #ifndef TL_EXPECTED_NO_CONSTRR - /// \group map_error - /// \synopsis template constexpr auto map_error(F &&f) const &&; - template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) const && { - return map_error_impl(std::move(*this), std::forward(f)); - } + /// \group map_error + /// \synopsis template constexpr auto map_error(F &&f) const &&; + template + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const && { + return map_error_impl(std::move(*this), std::forward(f)); + } #endif #endif - /// \brief Calls `f` if the expectd is in the unexpected state - /// \requires `F` is invokable with `E`, and `std::invoke_result_t` - /// must be void or convertible to `expcted`. - /// \effects If `*this` has a value, returns `*this`. - /// Otherwise, if `f` returns `void`, calls `std::forward(f)(E)` and returns - /// `std::nullopt`. Otherwise, returns `std::forward(f)(E)`. - /// - /// \group or_else - template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { - return or_else_impl(*this, std::forward(f)); - } + /// \brief Calls `f` if the expectd is in the unexpected state + /// \requires `F` is invokable with `E`, and `std::invoke_result_t` + /// must be void or convertible to `expcted`. + /// \effects If `*this` has a value, returns `*this`. + /// Otherwise, if `f` returns `void`, calls `std::forward(f)(E)` and returns + /// `std::nullopt`. Otherwise, returns `std::forward(f)(E)`. + /// + /// \group or_else + template + expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &{ + return or_else_impl(*this, std::forward(f)); + } - template expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { - return or_else_impl(std::move(*this), std::forward(f)); - } + template + expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &&{ + return or_else_impl(std::move(*this), std::forward(f)); + } - template expected constexpr or_else(F &&f) const & { - return or_else_impl(*this, std::forward(f)); - } + template + expected constexpr or_else(F &&f) const &{ + return or_else_impl(*this, std::forward(f)); + } #ifndef TL_EXPECTED_NO_CONSTRR - template expected constexpr or_else(F &&f) const && { - return or_else_impl(std::move(*this), std::forward(f)); - } -#endif - constexpr expected() = default; - constexpr expected(const expected &rhs) = default; - constexpr expected(expected &&rhs) = default; - expected &operator=(const expected &rhs) = default; - expected &operator=(expected &&rhs) = default; - template ::value> * = + template + expected constexpr or_else(F &&f) const &&{ + return or_else_impl(std::move(*this), std::forward(f)); + } + +#endif + + constexpr expected() = default; + + constexpr expected(const expected &rhs) = default; + + constexpr expected(expected &&rhs) = default; + + expected &operator=(const expected &rhs) = default; + + expected &operator=(expected &&rhs) = default; + + template::value> * = nullptr> - constexpr expected(in_place_t, Args &&... args) - : impl_base(in_place, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) {} + constexpr expected(in_place_t, Args &&... args) + : impl_base(in_place, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} - template &, Args &&...>::value> * = nullptr> - constexpr expected(in_place_t, std::initializer_list il, Args &&... args) - : impl_base(in_place, il, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) {} + template &, Args &&...>::value> * = nullptr> + constexpr expected(in_place_t, std::initializer_list il, Args &&... args) + : impl_base(in_place, il, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} - /// \group unexpected_ctor - /// \synopsis EXPLICIT constexpr expected(const unexpected &e); - template ::value> * = + /// \group unexpected_ctor + /// \synopsis EXPLICIT constexpr expected(const unexpected &e); + template::value> * = nullptr, - detail::enable_if_t::value> * = + detail::enable_if_t::value> * = nullptr> - explicit constexpr expected(const unexpected &e) - : impl_base(unexpect, e.value()), - ctor_base(detail::default_constructor_tag{}) {} + explicit constexpr expected(const unexpected &e) + : impl_base(unexpect, e.value()), + ctor_base(detail::default_constructor_tag{}) {} - /// \exclude - template < - class G = E, - detail::enable_if_t::value> * = - nullptr, - detail::enable_if_t::value> * = nullptr> - constexpr expected(unexpected const &e) - : impl_base(unexpect, e.value()), - ctor_base(detail::default_constructor_tag{}) {} - - /// \group unexpected_ctor - /// \synopsis EXPLICIT constexpr expected(unexpected &&e); - template < - class G = E, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - explicit constexpr expected(unexpected &&e) noexcept( - std::is_nothrow_constructible::value) - : impl_base(unexpect, std::move(e.value())), - ctor_base(detail::default_constructor_tag{}) {} - - /// \exclude - template < - class G = E, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - constexpr expected(unexpected &&e) noexcept( - std::is_nothrow_constructible::value) - : impl_base(unexpect, std::move(e.value())), - ctor_base(detail::default_constructor_tag{}) {} - - template ::value> * = - nullptr> - constexpr explicit expected(unexpect_t, Args &&... args) - : impl_base(unexpect, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) {} - - /// \exclude - template &, Args &&...>::value> * = nullptr> - constexpr explicit expected(unexpect_t, std::initializer_list il, - Args &&... args) - : impl_base(unexpect, il, std::forward(args)...), - ctor_base(detail::default_constructor_tag{}) {} - - template ::value && - std::is_convertible::value)> * = + /// \exclude + template< + class G = E, + detail::enable_if_t::value> * = nullptr, - detail::expected_enable_from_other + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected const &e) + : impl_base(unexpect, e.value()), + ctor_base(detail::default_constructor_tag{}) {} + + /// \group unexpected_ctor + /// \synopsis EXPLICIT constexpr expected(unexpected &&e); + template< + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + explicit constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : impl_base(unexpect, std::move(e.value())), + ctor_base(detail::default_constructor_tag{}) {} + + /// \exclude + template< + class G = E, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) + : impl_base(unexpect, std::move(e.value())), + ctor_base(detail::default_constructor_tag{}) {} + + template::value> * = + nullptr> + constexpr explicit expected(unexpect_t, Args &&... args) + : impl_base(unexpect, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + /// \exclude + template &, Args &&...>::value> * = nullptr> + constexpr explicit expected(unexpect_t, std::initializer_list il, + Args &&... args) + : impl_base(unexpect, il, std::forward(args)...), + ctor_base(detail::default_constructor_tag{}) {} + + template::value && + std::is_convertible::value)> * = + nullptr, + detail::expected_enable_from_other * = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) - : ctor_base(detail::default_constructor_tag{}) { - if (rhs.has_value()) { - this->construct(*rhs); - } else { - this->construct_error(rhs.error()); - } - } + explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } - /// \exclude - template ::value && - std::is_convertible::value)> * = + /// \exclude + template::value && + std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other + detail::expected_enable_from_other * = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) - : ctor_base(detail::default_constructor_tag{}) { - if (rhs.has_value()) { - this->construct(*rhs); - } else { - this->construct_error(rhs.error()); - } - } + TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(*rhs); + } else { + this->construct_error(rhs.error()); + } + } - template < - class U, class G, - detail::enable_if_t::value && - std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) - : ctor_base(detail::default_constructor_tag{}) { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } else { - this->construct_error(std::move(rhs.error())); - } - } + template< + class U, class G, + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } - /// \exclude - template < - class U, class G, - detail::enable_if_t<(std::is_convertible::value && - std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) - : ctor_base(detail::default_constructor_tag{}) { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } else { - this->construct_error(std::move(rhs.error())); - } - } + /// \exclude + template< + class U, class G, + detail::enable_if_t<(std::is_convertible::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + : ctor_base(detail::default_constructor_tag{}) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } else { + this->construct_error(std::move(rhs.error())); + } + } - template < - class U = T, - detail::enable_if_t::value> * = nullptr, - detail::expected_enable_forward_value * = nullptr> - explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) - : expected(in_place, std::forward(v)) {} + template< + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + : expected(in_place, std::forward(v)) {} - /// \exclude - template < - class U = T, - detail::enable_if_t::value> * = nullptr, - detail::expected_enable_forward_value * = nullptr> - TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) - : expected(in_place, std::forward(v)) {} + /// \exclude + template< + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + : expected(in_place, std::forward(v)) {} - template < - class U = T, class G = T, - detail::enable_if_t::value> * = - nullptr, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t< - (!std::is_same, detail::decay_t>::value && - !detail::conjunction, - std::is_same>>::value && - std::is_constructible::value && - std::is_assignable::value && - std::is_nothrow_move_constructible::value)> * = nullptr> - expected &operator=(U &&v) { - if (has_value()) { - val() = std::forward(v); - } else { - err().~unexpected(); - ::new (valptr()) T(std::forward(v)); - this->m_has_val = true; - } + template< + class U = T, class G = T, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t< + (!std::is_same, detail::decay_t>::value && + !detail::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { + if (has_value()) { + val() = std::forward(v); + } else { + err().~unexpected(); + ::new(valptr()) T(std::forward(v)); + this->m_has_val = true; + } - return *this; - } + return *this; + } - /// \exclude - template < - class U = T, class G = T, - detail::enable_if_t::value> * = - nullptr, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t< - (!std::is_same, detail::decay_t>::value && - !detail::conjunction, - std::is_same>>::value && - std::is_constructible::value && - std::is_assignable::value && - std::is_nothrow_move_constructible::value)> * = nullptr> - expected &operator=(U &&v) { - if (has_value()) { - val() = std::forward(v); - } else { - auto tmp = std::move(err()); - err().~unexpected(); + /// \exclude + template< + class U = T, class G = T, + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t< + (!std::is_same, detail::decay_t>::value && + !detail::conjunction, + std::is_same>>::value && + std::is_constructible::value && + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { + if (has_value()) { + val() = std::forward(v); + } else { + auto tmp = std::move(err()); + err().~unexpected(); - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (valptr()) T(std::move(v)); - this->m_has_val = true; - } catch (...) { - err() = std::move(tmp); - throw; - } - #else - ::new (valptr()) T(std::move(v)); - this->m_has_val = true; - #endif - } +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new(valptr()) T(std::move(v)); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(std::move(v)); + this->m_has_val = true; +#endif + } - return *this; - } + return *this; + } - template ::value && - std::is_assignable::value> * = nullptr> - expected &operator=(const unexpected &rhs) { - if (!has_value()) { - err() = rhs; - } else { - this->destroy_val(); - ::new (errptr()) unexpected(rhs); - this->m_has_val = false; - } + template::value && + std::is_assignable::value> * = nullptr> + expected &operator=(const unexpected &rhs) { + if (!has_value()) { + err() = rhs; + } else { + this->destroy_val(); + ::new(errptr()) unexpected(rhs); + this->m_has_val = false; + } - return *this; - } + return *this; + } - template ::value && - std::is_move_assignable::value> * = nullptr> - expected &operator=(unexpected &&rhs) noexcept { - if (!has_value()) { - err() = std::move(rhs); - } else { - this->destroy_val(); - ::new (errptr()) unexpected(std::move(rhs)); - this->m_has_val = false; - } + template::value && + std::is_move_assignable::value> * = nullptr> + expected &operator=(unexpected &&rhs) noexcept { + if (!has_value()) { + err() = std::move(rhs); + } else { + this->destroy_val(); + ::new(errptr()) unexpected(std::move(rhs)); + this->m_has_val = false; + } - return *this; - } + return *this; + } - template ::value> * = nullptr> - void emplace(Args &&... args) { - if (has_value()) { - val() = T(std::forward(args)...); - } else { - err().~unexpected(); - ::new (valptr()) T(std::forward(args)...); - this->m_has_val = true; - } - } + template::value> * = nullptr> + void emplace(Args &&... args) { + if (has_value()) { + val() = T(std::forward(args)...); + } else { + err().~unexpected(); + ::new(valptr()) T(std::forward(args)...); + this->m_has_val = true; + } + } - /// \exclude - template ::value> * = nullptr> - void emplace(Args &&... args) { - if (has_value()) { - val() = T(std::forward(args)...); - } else { - auto tmp = std::move(err()); - err().~unexpected(); + /// \exclude + template::value> * = nullptr> + void emplace(Args &&... args) { + if (has_value()) { + val() = T(std::forward(args)...); + } else { + auto tmp = std::move(err()); + err().~unexpected(); - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (valptr()) T(std::forward(args)...); - this->m_has_val = true; - } catch (...) { - err() = std::move(tmp); - throw; - } - #else - ::new (valptr()) T(std::forward(args)...); - this->m_has_val = true; - #endif - } - } +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new(valptr()) T(std::forward(args)...); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(std::forward(args)...); + this->m_has_val = true; +#endif + } + } - template &, Args &&...>::value> * = nullptr> - void emplace(std::initializer_list il, Args &&... args) { - if (has_value()) { - T t(il, std::forward(args)...); - val() = std::move(t); - } else { - err().~unexpected(); - ::new (valptr()) T(il, std::forward(args)...); - this->m_has_val = true; - } - } + template &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&... args) { + if (has_value()) { + T t(il, std::forward(args)...); + val() = std::move(t); + } else { + err().~unexpected(); + ::new(valptr()) T(il, std::forward(args)...); + this->m_has_val = true; + } + } - /// \exclude - template &, Args &&...>::value> * = nullptr> - void emplace(std::initializer_list il, Args &&... args) { - if (has_value()) { - T t(il, std::forward(args)...); - val() = std::move(t); - } else { - auto tmp = std::move(err()); - err().~unexpected(); + /// \exclude + template &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&... args) { + if (has_value()) { + T t(il, std::forward(args)...); + val() = std::move(t); + } else { + auto tmp = std::move(err()); + err().~unexpected(); - #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED - try { - ::new (valptr()) T(il, std::forward(args)...); - this->m_has_val = true; - } catch (...) { - err() = std::move(tmp); - throw; - } - #else - ::new (valptr()) T(il, std::forward(args)...); - this->m_has_val = true; - #endif - } - } +#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED + try { + ::new(valptr()) T(il, std::forward(args)...); + this->m_has_val = true; + } catch (...) { + err() = std::move(tmp); + throw; + } +#else + ::new (valptr()) T(il, std::forward(args)...); + this->m_has_val = true; +#endif + } + } - // TODO SFINAE - void swap(expected &rhs) noexcept( - std::is_nothrow_move_constructible::value &&noexcept( - swap(std::declval(), std::declval())) && - std::is_nothrow_move_constructible::value && - noexcept(swap(std::declval(), std::declval()))) { - if (has_value() && rhs.has_value()) { - using std::swap; - swap(val(), rhs.val()); - } else if (!has_value() && rhs.has_value()) { - using std::swap; - swap(err(), rhs.err()); - } else if (has_value()) { - auto temp = std::move(rhs.err()); - ::new (rhs.valptr()) T(val()); - ::new (errptr()) unexpected_type(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } else { - auto temp = std::move(this->err()); - ::new (valptr()) T(rhs.val()); - ::new (errptr()) unexpected_type(std::move(temp)); - std::swap(this->m_has_val, rhs.m_has_val); - } - } + // TODO SFINAE + void swap(expected &rhs) noexcept( + std::is_nothrow_move_constructible::value && noexcept( + swap(std::declval(), std::declval())) && + std::is_nothrow_move_constructible::value && + noexcept(swap(std::declval(), std::declval()))) { + if (has_value() && rhs.has_value()) { + using std::swap; + swap(val(), rhs.val()); + } else if (!has_value() && rhs.has_value()) { + using std::swap; + swap(err(), rhs.err()); + } else if (has_value()) { + auto temp = std::move(rhs.err()); + ::new(rhs.valptr()) T(val()); + ::new(errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } else { + auto temp = std::move(this->err()); + ::new(valptr()) T(rhs.val()); + ::new(errptr()) unexpected_type(std::move(temp)); + std::swap(this->m_has_val, rhs.m_has_val); + } + } - /// \returns a pointer to the stored value - /// \requires a value is stored - /// \group pointer - constexpr const T *operator->() const { return valptr(); } - /// \group pointer - TL_EXPECTED_11_CONSTEXPR T *operator->() { return valptr(); } + /// \returns a pointer to the stored value + /// \requires a value is stored + /// \group pointer + constexpr const T *operator->() const { return valptr(); } + /// \group pointer + TL_EXPECTED_11_CONSTEXPR T *operator->() { return valptr(); } - /// \returns the stored value - /// \requires a value is stored - /// \group deref - template ::value> * = nullptr> - constexpr const U &operator*() const & { - return val(); - } - /// \group deref - template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &operator*() & { - return val(); - } - /// \group deref - template ::value> * = nullptr> - constexpr const U &&operator*() const && { - return std::move(val()); - } - /// \group deref - template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &&operator*() && { - return std::move(val()); - } + /// \returns the stored value + /// \requires a value is stored + /// \group deref + template::value> * = nullptr> + constexpr const U &operator*() const &{ + return val(); + } - /// \returns whether or not the optional has a value - /// \group has_value - constexpr bool has_value() const noexcept { return this->m_has_val; } - /// \group has_value - constexpr explicit operator bool() const noexcept { return this->m_has_val; } + /// \group deref + template::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &operator*() &{ + return val(); + } - /// \returns the contained value if there is one, otherwise throws - /// [bad_expected_access] - /// - /// \group value - template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR const U &value() const & { - if (!has_value()) - detail::throw_exception(bad_expected_access(err().value())); - return val(); - } - /// \group value - template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &value() & { - if (!has_value()) - detail::throw_exception(bad_expected_access(err().value())); - return val(); - } - /// \group value - template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR const U &&value() const && { - if (!has_value()) - detail::throw_exception(bad_expected_access(err().value())); - return std::move(val()); - } - /// \group value - template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &&value() && { - if (!has_value()) - detail::throw_exception(bad_expected_access(err().value())); - return std::move(val()); - } + /// \group deref + template::value> * = nullptr> + constexpr const U &&operator*() const &&{ + return std::move(val()); + } - /// \returns the unexpected value - /// \requires there is an unexpected value - /// \group error - constexpr const E &error() const & { return err().value(); } - /// \group error - TL_EXPECTED_11_CONSTEXPR E &error() & { return err().value(); } - /// \group error - constexpr const E &&error() const && { return std::move(err().value()); } - /// \group error - TL_EXPECTED_11_CONSTEXPR E &&error() && { return std::move(err().value()); } + /// \group deref + template::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&operator*() &&{ + return std::move(val()); + } - /// \returns the stored value if there is one, otherwise returns `u` - /// \group value_or - template constexpr T value_or(U &&v) const & { - static_assert(std::is_copy_constructible::value && - std::is_convertible::value, - "T must be copy-constructible and convertible to from U&&"); - return bool(*this) ? **this : static_cast(std::forward(v)); - } - /// \group value_or - template TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { - static_assert(std::is_move_constructible::value && - std::is_convertible::value, - "T must be move-constructible and convertible to from U&&"); - return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); - } -}; + /// \returns whether or not the optional has a value + /// \group has_value + constexpr bool has_value() const noexcept { return this->m_has_val; } + + /// \group has_value + constexpr explicit operator bool() const noexcept { return this->m_has_val; } + + /// \returns the contained value if there is one, otherwise throws + /// [bad_expected_access] + /// + /// \group value + template::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &value() const &{ + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return val(); + } + + /// \group value + template::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &value() &{ + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return val(); + } + + /// \group value + template::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &&value() const &&{ + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return std::move(val()); + } + + /// \group value + template::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&value() &&{ + if (!has_value()) + detail::throw_exception(bad_expected_access(err().value())); + return std::move(val()); + } + + /// \returns the unexpected value + /// \requires there is an unexpected value + /// \group error + constexpr const E &error() const &{ return err().value(); } + /// \group error + TL_EXPECTED_11_CONSTEXPR E &error() &{ return err().value(); } + + /// \group error + constexpr const E &&error() const &&{ return std::move(err().value()); } + /// \group error + TL_EXPECTED_11_CONSTEXPR E &&error() &&{ return std::move(err().value()); } + + /// \returns the stored value if there is one, otherwise returns `u` + /// \group value_or + template + constexpr T value_or(U &&v) const &{ + static_assert(std::is_copy_constructible::value && + std::is_convertible::value, + "T must be copy-constructible and convertible to from U&&"); + return bool(*this) ? **this : static_cast(std::forward(v)); + } + + /// \group value_or + template + TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) &&{ + static_assert(std::is_move_constructible::value && + std::is_convertible::value, + "T must be move-constructible and convertible to from U&&"); + return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); + } + }; /// \exclude -namespace detail { -template using exp_t = typename detail::decay_t::value_type; -template using err_t = typename detail::decay_t::error_type; -template using ret_t = expected>; + namespace detail { + template using exp_t = typename detail::decay_t::value_type; + template using err_t = typename detail::decay_t::error_type; + template using ret_t = expected>; #ifdef TL_EXPECTED_CXX14 -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - *std::declval()))> -constexpr auto and_then_impl(Exp &&exp, F &&f) { - static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() - ? detail::invoke(std::forward(f), *std::forward(exp)) - : Ret(unexpect, std::forward(exp).error()); -} + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval()))> + constexpr auto and_then_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval()))> -constexpr auto and_then_impl(Exp &&exp, F &&f) { - static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() + ? detail::invoke(std::forward(f), *std::forward(exp)) + : Ret(unexpect, std::forward(exp).error()); + } + + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval()))> + constexpr auto and_then_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + + return exp.has_value() ? detail::invoke(std::forward(f)) + : Ret(unexpect, std::forward(exp).error()); + } - return exp.has_value() ? detail::invoke(std::forward(f)) - : Ret(unexpect, std::forward(exp).error()); -} #else -template struct TC; -template (), - *std::declval())), - detail::enable_if_t>::value> * = nullptr> -auto and_then_impl(Exp &&exp, F &&f) -> Ret { - static_assert(detail::is_expected::value, "F must return an expected"); + template struct TC; + template (), + *std::declval())), + detail::enable_if_t>::value> * = nullptr> + auto and_then_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() - ? detail::invoke(std::forward(f), *std::forward(exp)) - : Ret(unexpect, std::forward(exp).error()); -} + return exp.has_value() + ? detail::invoke(std::forward(f), *std::forward(exp)) + : Ret(unexpect, std::forward(exp).error()); + } -template ())), - detail::enable_if_t>::value> * = nullptr> -constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { - static_assert(detail::is_expected::value, "F must return an expected"); + template ())), + detail::enable_if_t>::value> * = nullptr> + constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() ? detail::invoke(std::forward(f)) - : Ret(unexpect, std::forward(exp).error()); -} + return exp.has_value() ? detail::invoke(std::forward(f)) + : Ret(unexpect, std::forward(exp).error()); + } #endif #ifdef TL_EXPECTED_CXX14 -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - *std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) { - using result = ret_t>; - return exp.has_value() ? result(detail::invoke(std::forward(f), - *std::forward(exp))) - : result(unexpect, std::forward(exp).error()); -} -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - *std::declval())), - detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) { - using result = expected>; - if (exp.has_value()) { - detail::invoke(std::forward(f), *std::forward(exp)); - return result(); - } + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> + constexpr auto expected_map_impl(Exp &&exp, F &&f) { + using result = ret_t>; + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); + } - return result(unexpect, std::forward(exp).error()); -} + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> + auto expected_map_impl(Exp &&exp, F &&f) { + using result = expected>; + if (exp.has_value()) { + detail::invoke(std::forward(f), *std::forward(exp)); + return result(); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) { - using result = ret_t>; - return exp.has_value() ? result(detail::invoke(std::forward(f))) - : result(unexpect, std::forward(exp).error()); -} + return result(unexpect, std::forward(exp).error()); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) { - using result = expected>; - if (exp.has_value()) { - detail::invoke(std::forward(f)); - return result(); - } + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> + constexpr auto expected_map_impl(Exp &&exp, F &&f) { + using result = ret_t>; + return exp.has_value() ? result(detail::invoke(std::forward(f))) + : result(unexpect, std::forward(exp).error()); + } + + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> + auto expected_map_impl(Exp &&exp, F &&f) { + using result = expected>; + if (exp.has_value()) { + detail::invoke(std::forward(f)); + return result(); + } + + return result(unexpect, std::forward(exp).error()); + } - return result(unexpect, std::forward(exp).error()); -} #else -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - *std::declval())), - detail::enable_if_t::value> * = nullptr> + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) - -> ret_t> { - using result = ret_t>; + constexpr auto expected_map_impl(Exp &&exp, F &&f) + -> ret_t> { + using result = ret_t>; - return exp.has_value() ? result(detail::invoke(std::forward(f), - *std::forward(exp))) - : result(unexpect, std::forward(exp).error()); -} + return exp.has_value() ? result(detail::invoke(std::forward(f), + *std::forward(exp))) + : result(unexpect, std::forward(exp).error()); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - *std::declval())), - detail::enable_if_t::value> * = nullptr> + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + *std::declval())), + detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) -> expected> { - if (exp.has_value()) { - detail::invoke(std::forward(f), *std::forward(exp)); - return {}; - } + auto expected_map_impl(Exp &&exp, F &&f) -> expected> { + if (exp.has_value()) { + detail::invoke(std::forward(f), *std::forward(exp)); + return {}; + } - return unexpected>(std::forward(exp).error()); -} + return unexpected>(std::forward(exp).error()); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) - -> ret_t> { - using result = ret_t>; + constexpr auto expected_map_impl(Exp &&exp, F &&f) + -> ret_t> { + using result = ret_t>; - return exp.has_value() ? result(detail::invoke(std::forward(f))) - : result(unexpect, std::forward(exp).error()); -} + return exp.has_value() ? result(detail::invoke(std::forward(f))) + : result(unexpect, std::forward(exp).error()); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval())), + detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) -> expected> { - if (exp.has_value()) { - detail::invoke(std::forward(f)); - return {}; - } + auto expected_map_impl(Exp &&exp, F &&f) -> expected> { + if (exp.has_value()) { + detail::invoke(std::forward(f)); + return {}; + } - return unexpected>(std::forward(exp).error()); -} + return unexpected>(std::forward(exp).error()); + } #endif -#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ +#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) { - using result = expected, detail::decay_t>; - return exp.has_value() - ? result(*std::forward(exp)) - : result(unexpect, detail::invoke(std::forward(f), - std::forward(exp).error())); -} -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) { - using result = expected, monostate>; - if (exp.has_value()) { - return result(*std::forward(exp)); - } - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) { - using result = expected, detail::decay_t>; - return exp.has_value() - ? result() - : result(unexpect, detail::invoke(std::forward(f), - std::forward(exp).error())); -} -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) { - using result = expected, monostate>; - if (exp.has_value()) { - return result(); - } + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); + } + + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(*std::forward(exp)); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); + } + + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + constexpr auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, detail::decay_t>; + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); + } + + template>::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + auto map_error_impl(Exp &&exp, F &&f) { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } + + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); + } - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} #else -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) - -> expected, detail::decay_t> { - using result = expected, detail::decay_t>; + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; - return exp.has_value() - ? result(*std::forward(exp)) - : result(unexpect, detail::invoke(std::forward(f), - std::forward(exp).error())); -} + return exp.has_value() + ? result(*std::forward(exp)) + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { - using result = expected, monostate>; - if (exp.has_value()) { - return result(*std::forward(exp)); - } + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(*std::forward(exp)); + } - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) - -> expected, detail::decay_t> { - using result = expected, detail::decay_t>; + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + constexpr auto map_error_impl(Exp &&exp, F &&f) + -> expected, detail::decay_t> { + using result = expected, detail::decay_t>; - return exp.has_value() - ? result() - : result(unexpect, detail::invoke(std::forward(f), - std::forward(exp).error())); -} + return exp.has_value() + ? result() + : result(unexpect, detail::invoke(std::forward(f), + std::forward(exp).error())); + } -template >::value> * = nullptr, - class Ret = decltype(detail::invoke(std::declval(), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { - using result = expected, monostate>; - if (exp.has_value()) { - return result(); - } + template >::value> * = nullptr, + class Ret = decltype(detail::invoke(std::declval(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + using result = expected, monostate>; + if (exp.has_value()) { + return result(); + } - detail::invoke(std::forward(f), std::forward(exp).error()); - return result(unexpect, monostate{}); -} + detail::invoke(std::forward(f), std::forward(exp).error()); + return result(unexpect, monostate{}); + } #endif #ifdef TL_EXPECTED_CXX14 -template (), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto or_else_impl(Exp &&exp, F &&f) { - static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() - ? std::forward(exp) - : detail::invoke(std::forward(f), std::forward(exp).error()); -} -template (), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -detail::decay_t or_else_impl(Exp &&exp, F &&f) { - return exp.has_value() - ? std::forward(exp) - : (detail::invoke(std::forward(f), std::forward(exp).error()), - std::forward(exp)); -} + template(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + constexpr auto or_else_impl(Exp &&exp, F &&f) { + static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() + ? std::forward(exp) + : detail::invoke(std::forward(f), std::forward(exp).error()); + } + + template(), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + detail::decay_t or_else_impl(Exp &&exp, F &&f) { + return exp.has_value() + ? std::forward(exp) + : (detail::invoke(std::forward(f), std::forward(exp).error()), + std::forward(exp)); + } + #else -template (), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto or_else_impl(Exp &&exp, F &&f) -> Ret { - static_assert(detail::is_expected::value, "F must return an expected"); - return exp.has_value() - ? std::forward(exp) - : detail::invoke(std::forward(f), std::forward(exp).error()); -} + template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + auto or_else_impl(Exp &&exp, F &&f) -> Ret { + static_assert(detail::is_expected::value, "F must return an expected"); + return exp.has_value() + ? std::forward(exp) + : detail::invoke(std::forward(f), std::forward(exp).error()); + } -template (), - std::declval().error())), - detail::enable_if_t::value> * = nullptr> -detail::decay_t or_else_impl(Exp &&exp, F &&f) { - return exp.has_value() - ? std::forward(exp) - : (detail::invoke(std::forward(f), std::forward(exp).error()), - std::forward(exp)); -} + template (), + std::declval().error())), + detail::enable_if_t::value> * = nullptr> + detail::decay_t or_else_impl(Exp &&exp, F &&f) { + return exp.has_value() + ? std::forward(exp) + : (detail::invoke(std::forward(f), std::forward(exp).error()), + std::forward(exp)); + } #endif -} // namespace detail + } // namespace detail -template -constexpr bool operator==(const expected &lhs, - const expected &rhs) { - return (lhs.has_value() != rhs.has_value()) - ? false - : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); -} -template -constexpr bool operator!=(const expected &lhs, - const expected &rhs) { - return (lhs.has_value() != rhs.has_value()) - ? true - : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); -} + template + constexpr bool operator==(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? false + : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); + } -template -constexpr bool operator==(const expected &x, const U &v) { - return x.has_value() ? *x == v : false; -} -template -constexpr bool operator==(const U &v, const expected &x) { - return x.has_value() ? *x == v : false; -} -template -constexpr bool operator!=(const expected &x, const U &v) { - return x.has_value() ? *x != v : true; -} -template -constexpr bool operator!=(const U &v, const expected &x) { - return x.has_value() ? *x != v : true; -} + template + constexpr bool operator!=(const expected &lhs, + const expected &rhs) { + return (lhs.has_value() != rhs.has_value()) + ? true + : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); + } -template -constexpr bool operator==(const expected &x, const unexpected &e) { - return x.has_value() ? false : x.error() == e.value(); -} -template -constexpr bool operator==(const unexpected &e, const expected &x) { - return x.has_value() ? false : x.error() == e.value(); -} -template -constexpr bool operator!=(const expected &x, const unexpected &e) { - return x.has_value() ? true : x.error() != e.value(); -} -template -constexpr bool operator!=(const unexpected &e, const expected &x) { - return x.has_value() ? true : x.error() != e.value(); -} + template + constexpr bool operator==(const expected &x, const U &v) { + return x.has_value() ? *x == v : false; + } + + template + constexpr bool operator==(const U &v, const expected &x) { + return x.has_value() ? *x == v : false; + } + + template + constexpr bool operator!=(const expected &x, const U &v) { + return x.has_value() ? *x != v : true; + } + + template + constexpr bool operator!=(const U &v, const expected &x) { + return x.has_value() ? *x != v : true; + } + + template + constexpr bool operator==(const expected &x, const unexpected &e) { + return x.has_value() ? false : x.error() == e.value(); + } + + template + constexpr bool operator==(const unexpected &e, const expected &x) { + return x.has_value() ? false : x.error() == e.value(); + } + + template + constexpr bool operator!=(const expected &x, const unexpected &e) { + return x.has_value() ? true : x.error() != e.value(); + } + + template + constexpr bool operator!=(const unexpected &e, const expected &x) { + return x.has_value() ? true : x.error() != e.value(); + } // TODO is_swappable -template ::value && - std::is_move_constructible::value> * = nullptr> -void swap(expected &lhs, - expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { - lhs.swap(rhs); -} + template::value && + std::is_move_constructible::value> * = nullptr> + void swap(expected &lhs, + expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { + lhs.swap(rhs); + } } // namespace tl #define TL_OPTIONAL_EXPECTED_MUTEX diff --git a/comdel/parser/parsecontext.cpp b/comdel/parser/parse_context.cpp similarity index 70% rename from comdel/parser/parsecontext.cpp rename to comdel/parser/parse_context.cpp index a1ad8c3..3a872bd 100644 --- a/comdel/parser/parsecontext.cpp +++ b/comdel/parser/parse_context.cpp @@ -1,4 +1,4 @@ -#include "parsecontext.h" +#include "parse_context.h" #include "assert.h" #include @@ -6,31 +6,29 @@ #include -ParseContext::ParseContext() -{ +ParseContext::ParseContext() { applicationDir = std::string(); } -unsigned ParseContext::addFile(const std::string& fileName, - const std::string& source) -{ - fileMap.push_back(SourceFile(fileName, source)); +unsigned ParseContext::addFile(const std::string &fileName, + const std::string &source) { + fileMap.emplace_back(fileName, source); return fileMap.size(); } -SourceFile& ParseContext::getFile(unsigned fileId) -{ - return fileMap[fileId-1]; +SourceFile &ParseContext::getFile(unsigned fileId) { + return fileMap[fileId - 1]; } struct pad { - char ch; int count; + char ch; + int count; pad(char ch, int count) : ch(ch), count(count) {} }; -std::ostream& operator<<(std::ostream& stream, const pad& p) { +std::ostream &operator<<(std::ostream &stream, const pad &p) { for (int i = 0; i < p.count; i++) { stream << p.ch; } @@ -40,16 +38,13 @@ std::ostream& operator<<(std::ostream& stream, const pad& p) { #define ATLAS_ASSERT(x) \ do {} while(0) -void ParseContext::formatError(const SourceError& sourceError, - std::ostream& stream, - const std::string& ErrorOrWarning) -{ +void ParseContext::formatError(const SourceError &sourceError, + std::ostream &stream, + const std::string &errorOrWarning) { ATLAS_ASSERT(sourceError.span.lo.col != 0 && sourceError.span.hi.col != 0); - SourceFile sourceFile = getFile(sourceError.span.lo.fileId); - - stream << ErrorOrWarning << sourceError.message << std::endl; + stream << errorOrWarning << sourceError.message << std::endl; Span span = sourceError.span; @@ -100,21 +95,17 @@ void ParseContext::formatError(const SourceError& sourceError, } - SourceFile::SourceFile(std::string fileName, std::string source) - : fileName(std::move(fileName)), source(std::move(source)) -{ + : fileName(std::move(fileName)), source(std::move(source)) { lineOffsets.push_back(0); } -const std::string& SourceFile::getFileName() const -{ +const std::string &SourceFile::getFileName() const { return fileName; } -const std::string SourceFile::getLine(unsigned line) const -{ - auto lineOffset = lineOffsets[line-1]; +std::string SourceFile::getLine(unsigned line) const { + auto lineOffset = lineOffsets[line - 1]; auto nextLF = source.find('\n', lineOffset); auto nextCR = source.find('\r', lineOffset); auto nl = std::min(nextCR, nextLF); @@ -122,7 +113,6 @@ const std::string SourceFile::getLine(unsigned line) const return source.substr(lineOffset, nl - lineOffset); } -void SourceFile::addLineOffset(unsigned offset) -{ +void SourceFile::addLineOffset(unsigned offset) { lineOffsets.push_back(offset); } diff --git a/comdel/parser/parsecontext.h b/comdel/parser/parse_context.h similarity index 53% rename from comdel/parser/parsecontext.h rename to comdel/parser/parse_context.h index 38a232a..b7d294e 100644 --- a/comdel/parser/parsecontext.h +++ b/comdel/parser/parse_context.h @@ -2,40 +2,39 @@ #define PARSE_CONTEXT_H -#include "sourceerror.h" +#include "source_error.h" #include #include - class SourceFile { std::string fileName; std::string source; std::vector lineOffsets; public: - // qqq source je CIJELI comdel fajl, - // za inicijalizaciju source se koristi std::move, a možda treba biti referenca??? SourceFile(std::string fileName, std::string source); - const std::string& getFileName() const; - const std::string getLine(unsigned line) const; + const std::string &getFileName() const; + + std::string getLine(unsigned line) const; + void addLineOffset(unsigned offset); }; -class ParseContext -{ +class ParseContext { std::string applicationDir; std::vector fileMap; public: ParseContext(); - unsigned addFile(const std::string& fileName, const std::string& source); - SourceFile& getFile(unsigned file); + unsigned addFile(const std::string &fileName, const std::string &source); - void formatError(const SourceError &sourceError, std::ostream &stream, const std::string& ErrorOrWarning); + SourceFile &getFile(unsigned file); + + void formatError(const SourceError &sourceError, std::ostream &stream, const std::string &errorOrWarning); }; diff --git a/comdel/parser/parserutil.cpp b/comdel/parser/parser_util.cpp similarity index 64% rename from comdel/parser/parserutil.cpp rename to comdel/parser/parser_util.cpp index a6dddab..8b1ad1b 100644 --- a/comdel/parser/parserutil.cpp +++ b/comdel/parser/parser_util.cpp @@ -1,18 +1,17 @@ #include "comdellexer.h" -#include "comdelparser.h" -#include "parserutil.h" +#include "comdel_parser.h" +#include "parser_util.h" #include #include #include #include -std::optional loadLibraryFromFile(ParseContext * parseContext, - const char* name, - std::ostream& stream) -{ +std::optional load_library_from_file(ParseContext *parseContext, + const char *name, + std::ostream &stream) { std::ifstream in(name, std::ios::in | std::ios::binary); - if( ! in ) { + if (!in) { stream << "ERROR: cannot open file '" << name << "' (file does not exist or is unreadable)" << std::endl; return std::nullopt; @@ -23,17 +22,17 @@ std::optional loadLibraryFromFile(ParseContext * parseContext, ComdelLexer lexer(name, source, parseContext); LexerResult lexerResult = lexer.tokenize(); - if (lexerResult.errors.size()) { - for (auto& error : lexerResult.errors) { + if (!lexerResult.errors.empty()) { + for (auto &error: lexerResult.errors) { parseContext->formatError(error, stream, "ERROR: "); } - return std::nullopt; // if lexer has found errors => don't parse + return std::nullopt; // if lexer has found errors => don't parseLibrary } ComdelParser parser(lexerResult.tokens); - auto unit = parser.parse(); + auto unit = parser.parseLibrary(); if (!unit) { - for (auto& error : parser.getErrors()) { + for (auto &error: parser.getErrors()) { parseContext->formatError(error, stream, "ERROR: "); } return std::nullopt; @@ -43,12 +42,11 @@ std::optional loadLibraryFromFile(ParseContext * parseContext, } -std::optional loadSchemaFromFile(ParseContext * parseContext, - const char* name, - std::ostream& stream) -{ +std::optional load_schema_from_file(ParseContext *parseContext, + const char *name, + std::ostream &stream) { std::ifstream in(name, std::ios::in | std::ios::binary); - if( ! in ) { + if (!in) { stream << "ERROR: cannot open file '" << name << "' (file does not exist or is unreadable)" << std::endl; return std::nullopt; @@ -59,32 +57,32 @@ std::optional loadSchemaFromFile(ParseContext * parseContext, ComdelLexer lexer(name, source, parseContext); LexerResult lexerResult = lexer.tokenize(); - if (lexerResult.errors.size()) { - for (auto& error : lexerResult.errors) { + if (!lexerResult.errors.empty()) { + for (auto &error: lexerResult.errors) { parseContext->formatError(error, stream, "ERROR: "); } - return std::nullopt; // if lexer has found errors => don't parse + return std::nullopt; // if lexer has found errors => don't parseLibrary } ComdelParser parser(lexerResult.tokens); auto unit = parser.parseSchema(); if (!unit) { - for (auto& error : parser.getErrors()) { + for (auto &error: parser.getErrors()) { parseContext->formatError(error, stream, "ERROR: "); } return std::nullopt; } - if(unit->source) { + if (unit->source) { QFileInfo info(name); auto filepath = info.absolutePath(); - QDir dir; - dir.setCurrent(filepath); + QDir::setCurrent(filepath); + QDir dir; auto libraryPath = dir.absoluteFilePath(QString::fromStdString(unit->source->asString())); - unit->library = loadLibraryFromFile(parseContext, libraryPath.toUtf8().data(), stream); - if(unit->library == std::nullopt) { + unit->library = load_library_from_file(parseContext, libraryPath.toUtf8().data(), stream); + if (unit->library == std::nullopt) { return std::nullopt; } } diff --git a/comdel/parser/parser_util.h b/comdel/parser/parser_util.h new file mode 100644 index 0000000..eeea75b --- /dev/null +++ b/comdel/parser/parser_util.h @@ -0,0 +1,15 @@ +#ifndef PARSER_UTIL_H +#define PARSER_UTIL_H + +#include "ast_nodes.h" +#include "parse_context.h" + +std::optional load_library_from_file(ParseContext *parseContext, + const char *name, + std::ostream &stream); + +std::optional load_schema_from_file(ParseContext *parseContext, + const char *name, + std::ostream &stream); + +#endif // PARSER_UTIL_H diff --git a/comdel/parser/parserutil.h b/comdel/parser/parserutil.h deleted file mode 100644 index 7ba8908..0000000 --- a/comdel/parser/parserutil.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef PARSER_UTIL_H -#define PARSER_UTIL_H - -#include "astnode.h" -#include "parsecontext.h" - -std::optional loadLibraryFromFile(ParseContext * parseContext, - const char* name, - std::ostream& stream); - -std::optional loadSchemaFromFile(ParseContext * parseContext, - const char* name, - std::ostream& stream); - -#endif // PARSERUTIL_H diff --git a/comdel/parser/poly.h b/comdel/parser/poly.h index a05cbd3..a692244 100644 --- a/comdel/parser/poly.h +++ b/comdel/parser/poly.h @@ -30,142 +30,119 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -namespace detail -{ +namespace detail { //////////////////////////////////////////////////////////////////////////// // Implementation detail classes //////////////////////////////////////////////////////////////////////////// - template - struct default_copy - { - T* operator()(const T& t) const - { + template + struct default_copy { + T *operator()(const T &t) const { return new T(t); } }; - template - struct default_delete - { - void operator()(const T* t) const - { + template + struct default_delete { + void operator()(const T *t) const { delete t; } }; - template - struct control_block - { + template + struct control_block { virtual ~control_block() = default; virtual std::unique_ptr clone() const = 0; - virtual T* ptr() = 0; + virtual T *ptr() = 0; }; - template - class direct_control_block : public control_block - { + template + class direct_control_block : public control_block { static_assert(!std::is_reference::value, ""); U u_; public: - template - explicit direct_control_block(Ts&&... ts) : u_(U(std::forward(ts)...)) - { + template + explicit direct_control_block(Ts &&... ts) : u_(U(std::forward(ts)...)) { } - std::unique_ptr> clone() const override - { + std::unique_ptr> clone() const override { return std::make_unique(*this); } - T* ptr() override - { + T *ptr() override { return std::addressof(u_); } }; - template , - class D = default_delete> - class pointer_control_block : public control_block, public C - { + template, + class D = default_delete> + class pointer_control_block : public control_block, public C { std::unique_ptr p_; public: - explicit pointer_control_block(U* u, C c = C{}, D d = D{}) - : C(std::move(c)), p_(u, std::move(d)) - { + explicit pointer_control_block(U *u, C c = C{}, D d = D{}) + : C(std::move(c)), p_(u, std::move(d)) { } explicit pointer_control_block(std::unique_ptr p, C c = C{}) - : C(std::move(c)), p_(std::move(p)) - { + : C(std::move(c)), p_(std::move(p)) { } - std::unique_ptr> clone() const override - { + std::unique_ptr> clone() const override { assert(p_); return std::make_unique( - C::operator()(*p_), static_cast(*this), p_.get_deleter()); + C::operator()(*p_), static_cast(*this), p_.get_deleter()); } - T* ptr() override - { + T *ptr() override { return p_.get(); } }; - template - class delegating_control_block : public control_block - { + template + class delegating_control_block : public control_block { std::unique_ptr> delegate_; public: explicit delegating_control_block(std::unique_ptr> b) - : delegate_(std::move(b)) - { + : delegate_(std::move(b)) { } - std::unique_ptr> clone() const override - { + std::unique_ptr> clone() const override { return std::make_unique(delegate_->clone()); } - T* ptr() override - { - return static_cast(delegate_->ptr()); + T *ptr() override { + return static_cast(delegate_->ptr()); } }; } // end namespace detail -class bad_poly_construction : std::exception -{ +class bad_poly_construction : std::exception { public: bad_poly_construction() noexcept = default; - const char* what() const noexcept override - { + const char *what() const noexcept override { return "Dynamic and static type mismatch in poly " - "construction"; + "construction"; } }; -template +template class poly; -template -struct is_poly : std::false_type -{ +template +struct is_poly : std::false_type { }; -template -struct is_poly> : std::true_type -{ +template +struct is_poly> : std::true_type { }; @@ -173,23 +150,25 @@ struct is_poly> : std::true_type // `poly` class definition //////////////////////////////////////////////////////////////////////////////// -template -class poly -{ +template +class poly { static_assert(!std::is_union::value, ""); static_assert(std::is_class::value, ""); - template - friend class poly; + template + friend + class poly; - template - friend poly make_poly(Ts&&... ts); - template - friend poly make_poly(Ts&&... ts); - template + template + friend poly make_poly(Ts &&... ts); + + template + friend poly make_poly(Ts &&... ts); + + template friend poly poly_cast(poly p); - T* ptr_ = nullptr; + T *ptr_ = nullptr; std::unique_ptr> cb_; public: @@ -204,17 +183,14 @@ public: // Constructors // - poly() - { + poly() { } - template , - class D = detail::default_delete, - class V = std::enable_if_t::value>> - explicit poly(U* u, C copier = C{}, D deleter = D{}) - { - if (!u) - { + template, + class D = detail::default_delete, + class V = std::enable_if_t::value>> + explicit poly(U *u, C copier = C{}, D deleter = D{}) { + if (!u) { return; } @@ -227,7 +203,7 @@ public: std::unique_ptr p(u, std::move(deleter)); cb_ = std::make_unique>( - std::move(p), std::move(copier)); + std::move(p), std::move(copier)); ptr_ = u; } @@ -236,10 +212,8 @@ public: // Copy-constructors // - poly(const poly& p) - { - if (!p) - { + poly(const poly &p) { + if (!p) { return; } auto tmp_cb = p.cb_->clone(); @@ -251,8 +225,7 @@ public: // Move-constructors // - poly(poly&& p) noexcept - { + poly(poly &&p) noexcept { ptr_ = p.ptr_; cb_ = std::move(p.cb_); p.ptr_ = nullptr; @@ -262,25 +235,23 @@ public: // Converting constructors // - template ::value && - std::is_convertible::value>> - poly(const poly& p) - { + template::value && + std::is_convertible::value>> + poly(const poly &p) { poly tmp(p); ptr_ = tmp.ptr_; cb_ = std::make_unique>( - std::move(tmp.cb_)); + std::move(tmp.cb_)); } - template ::value && - std::is_convertible::value>> - poly(poly&& p) - { + template::value && + std::is_convertible::value>> + poly(poly &&p) { ptr_ = p.ptr_; cb_ = std::make_unique>( - std::move(p.cb_)); + std::move(p.cb_)); p.ptr_ = nullptr; } @@ -288,14 +259,13 @@ public: // Forwarding constructor // - template *, T*>::value && - !is_poly>::value>> - poly(U&& u) - : cb_(std::make_unique< - detail::direct_control_block>>( - std::forward(u))) - { + template *, T *>::value && + !is_poly>::value>> + poly(U &&u) + : cb_(std::make_unique< + detail::direct_control_block>>( + std::forward(u))) { ptr_ = cb_->ptr(); } @@ -303,15 +273,12 @@ public: // Assignment // - poly& operator=(const poly& p) - { - if (std::addressof(p) == this) - { + poly &operator=(const poly &p) { + if (std::addressof(p) == this) { return *this; } - if (!p) - { + if (!p) { cb_.reset(); ptr_ = nullptr; return *this; @@ -328,10 +295,8 @@ public: // Move-assignment // - poly& operator=(poly&& p) noexcept - { - if (std::addressof(p) == this) - { + poly &operator=(poly &&p) noexcept { + if (std::addressof(p) == this) { return *this; } @@ -346,8 +311,7 @@ public: // Modifiers // - void swap(poly& p) noexcept - { + void swap(poly &p) noexcept { using std::swap; swap(ptr_, p.ptr_); swap(cb_, p.cb_); @@ -358,31 +322,26 @@ public: // Observers // - explicit operator bool() const - { - return (bool)cb_; + explicit operator bool() const { + return (bool) cb_; } - const T* operator->() const - { + const T *operator->() const { assert(ptr_); return ptr_; } - const T& operator*() const - { + const T &operator*() const { assert(*this); return *ptr_; } - T* operator->() - { + T *operator->() { assert(*this); return ptr_; } - T& operator*() - { + T &operator*() { assert(*this); return *ptr_; } @@ -391,18 +350,17 @@ public: // // poly creation // -template -poly make_poly(Ts&&... ts) -{ +template +poly make_poly(Ts &&... ts) { poly p; p.cb_ = std::make_unique>( std::forward(ts)...); p.ptr_ = p.cb_->ptr(); return std::move(p); } -template -poly make_poly(Ts&&... ts) -{ + +template +poly make_poly(Ts &&... ts) { poly p; p.cb_ = std::make_unique>( std::forward(ts)...); @@ -410,32 +368,30 @@ poly make_poly(Ts&&... ts) return std::move(p); } -template -const T* poly_view(const poly& p) { +template +const T *poly_view(const poly &p) { if (p) { - return dynamic_cast(&*p); - } - else { + return dynamic_cast(&*p); + } else { return nullptr; } } -template -T* poly_view(poly& p) { +template +T *poly_view(poly &p) { if (p) { - return dynamic_cast(&*p); - } - else { + return dynamic_cast(&*p); + } else { return nullptr; } } -template +template poly poly_cast(poly p) { poly ret; - if (T* ptr = dynamic_cast(&*p)) { + if (T *ptr = dynamic_cast(&*p)) { ret.cb_ = std::make_unique>( - std::move(p.cb_)); + std::move(p.cb_)); ret.ptr_ = ret.cb_->ptr(); } return ret; diff --git a/comdel/parser/presult.h b/comdel/parser/presult.h index 8dfd28c..2d06e49 100644 --- a/comdel/parser/presult.h +++ b/comdel/parser/presult.h @@ -2,7 +2,7 @@ #define PRESULT_H #include "expected.h" -#include "sourceerror.h" +#include "source_error.h" #include @@ -32,19 +32,18 @@ using PError = tl::unexpected; /// Holds either an AST node or an error /// The value MUST be checked before usage, e.g. using RETURN_IF_ERR -template +template struct PResult : tl::expected { using tl::expected::expected; /// Implicit conversion from PResult to PResult /// if U is convertible to T - template , T>::value>> + template, T>::value>> PResult(PResult presult) : - tl::expected(presult ? PResult(*presult) : PError(presult.error())) - {} + tl::expected(presult ? PResult(*presult) : PError(presult.error())) {} }; -/// Alternative to PResult that is returned from parse* functions +/// Alternative to PResult that is returned from parseLibrary* functions /// that only consume one token so they can fail without affecting /// the parser state template diff --git a/comdel/parser/source_error.cpp b/comdel/parser/source_error.cpp new file mode 100644 index 0000000..2423bee --- /dev/null +++ b/comdel/parser/source_error.cpp @@ -0,0 +1,5 @@ +#include "source_error.h" + + +SourceError::SourceError(Span span, std::string message) + : span(span), message(std::move(message)) {} diff --git a/comdel/parser/sourceerror.h b/comdel/parser/source_error.h similarity index 100% rename from comdel/parser/sourceerror.h rename to comdel/parser/source_error.h diff --git a/comdel/parser/sourceerror.cpp b/comdel/parser/sourceerror.cpp deleted file mode 100644 index d80a3e1..0000000 --- a/comdel/parser/sourceerror.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "sourceerror.h" - - -SourceError::SourceError(Span span, std::string message) - : span(std::move(span)), message(std::move(message)) -{} diff --git a/comdel/parser/token.cpp b/comdel/parser/token.cpp index 1ca7f32..ced99ee 100644 --- a/comdel/parser/token.cpp +++ b/comdel/parser/token.cpp @@ -4,32 +4,23 @@ Position::Position() - : fileId(0), line(0), col(0), offset(0) -{} + : fileId(0), line(0), col(0), offset(0) {} Position::Position(unsigned file, unsigned line, unsigned col, unsigned offset) - : fileId(file), line(line), col(col), offset(offset) -{} + : fileId(file), line(line), col(col), offset(offset) {} Span::Span() - : lo(0, 0, 0, 0), hi(0, 0, 0, 0) -{} + : lo(0, 0, 0, 0), hi(0, 0, 0, 0) {} Span::Span(Position begin, Position end) - : lo(begin), hi(end) -{} + : lo(begin), hi(end) {} Span::Span(Position begin) - : Span(begin, Position(begin.fileId, begin.line, begin.col+1, begin.offset+1)) -{} + : Span(begin, Position(begin.fileId, begin.line, begin.col + 1, begin.offset + 1)) {} -Span Span::to(const Span &span) const -{ - return Span(this->lo, span.hi); +Span Span::to(const Span &span) const { + return {this->lo, span.hi}; } Token::Token(TokenType type, Span span, std::string text) - : type(type) - , span(std::move(span)) - , text(std::move(text)) -{} + : type(type), span(span), text(std::move(text)) {} diff --git a/comdel/parser/token.h b/comdel/parser/token.h index e52838e..18b5903 100644 --- a/comdel/parser/token.h +++ b/comdel/parser/token.h @@ -12,6 +12,7 @@ struct Position { unsigned offset; Position(); + Position(unsigned fileId, unsigned line, unsigned col, unsigned offset); }; @@ -23,10 +24,12 @@ struct Span { Position hi; Span(); + Span(Position lo, Position hi); + Span(Position lo); - Span to(const Span& span) const; + Span to(const Span &span) const; }; enum class TokenType { diff --git a/comdel/parser/tokens_type.cpp b/comdel/parser/tokens_type.cpp new file mode 100644 index 0000000..8edf78d --- /dev/null +++ b/comdel/parser/tokens_type.cpp @@ -0,0 +1,173 @@ +#include "tokens_type.h" + +enum TokenClass { + KEYWORD_NAME = 4, + TOKENIZABLE = 8 +}; + + +struct TokenInfo { + std::string text; + unsigned short attributes; +}; + + +struct TokenTables { + std::unordered_map allTokensInfo; + std::unordered_map keywords; + + TokenType tokenize(std::string value, TokenType initial); + + bool is_keyword(TokenType token); + + void add(TokenType tokenType, const std::string &txt, + unsigned short attribs = 0); + + TokenTables(); +}; + + +static TokenTables tokenTables; + +void TokenTables::add(TokenType tokenType, const std::string &txt, + unsigned short attribs) { + allTokensInfo[tokenType] = TokenInfo{txt, attribs}; + if (attribs & KEYWORD_NAME) + keywords[txt] = tokenType; +} + +TokenTables::TokenTables() { + + add(TokenType::IDENTIFIER, "identifier"); + add(TokenType::KEYWORD, "keyword", KEYWORD_NAME); + + // Literals (bool is not here, it has two keywords: false and true) + add(TokenType::NUMBER, "number"); + add(TokenType::STRING, "string"); + add(TokenType::COLOR, "color"); + + // Parentheses of all kinds + add(TokenType::LPAREN, "("); + add(TokenType::RPAREN, ")"); + add(TokenType::LBRACKET, "["); + add(TokenType::RBRACKET, "]"); + add(TokenType::LBRACE, "{"); + add(TokenType::RBRACE, "}"); + add(TokenType::LT, "<"); + add(TokenType::GT, ">"); + + // assignments + add(TokenType::EQUALS, "="); + + // miscellaneous + add(TokenType::DOT, "."); + add(TokenType::COLON, ":"); + add(TokenType::SEMICOLON, ";"); + add(TokenType::COMMA, ","); + add(TokenType::WHITESPACE, "whitespace"); + add(TokenType::COMMENT, "comment"); + + add(TokenType::TRUE, "true", TOKENIZABLE); + add(TokenType::FALSE, "false", TOKENIZABLE); + + add(TokenType::IF, "if", TOKENIZABLE); + add(TokenType::ELSE, "else", TOKENIZABLE); + + add(TokenType::DEFAULT, "default", TOKENIZABLE); + add(TokenType::NIL, "null", TOKENIZABLE); + + // all keywords + add(TokenType::KW_NAME, "@name", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_INFO, "@info", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_HEADER, "@header", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_COMPONENT_HEADER, "@componentHeader", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_LIBRARY, "@library", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_ADDRESS, "@address", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_COMPONENT, "@component", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_MESSAGES, "@messages", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_COUNT, "@count", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_DISPLAY, "@display", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_PIN, "@pin", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_CONNECTION, "@connection", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_SOURCE, "@source", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_POPUP, "@popup", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_RULE, "@rule", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_TITLE, "@title", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_TEXT, "@text", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_BUS, "@bus", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_WIRES, "@wires", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_WIRE, "@wire", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_INSTANCE, "@instance", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME); + add(TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME); + + // All types + add(TokenType::INT_TYPE, "int", TOKENIZABLE); + add(TokenType::STRING_TYPE, "string", TOKENIZABLE); + add(TokenType::BOOL_TYPE, "bool", TOKENIZABLE); + add(TokenType::WIRE_TYPE, "wire", TOKENIZABLE); + + // WireNode types + add(TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE); + add(TokenType::WIRE_AND, "wired_and", TOKENIZABLE); + add(TokenType::WIRE_OR, "wired_or", TOKENIZABLE); + add(TokenType::R_WIRE, "r_wire", TOKENIZABLE); + + // ComponentNode types + add(TokenType::CT_MEMORY, "memory", TOKENIZABLE); + add(TokenType::CT_PROCESSOR, "processor", TOKENIZABLE); + + // PinNode type + add(TokenType::PIN_IN, "in", TOKENIZABLE); + add(TokenType::PIN_OUT, "out", TOKENIZABLE); + add(TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE); + + // ActionNode types + add(TokenType::ERROR, "error", TOKENIZABLE); + add(TokenType::WARNING, "warning", TOKENIZABLE); + + + // WireNode settings types + add(TokenType::HIDDEN, "hidden", TOKENIZABLE); + add(TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE); + + // Miscelaneous + add(TokenType::END_OF_FILE, "eof"); +} + + +const std::string &tokenTypeToString(TokenType tokenType) { + return tokenTables.allTokensInfo[tokenType].text; +} + +TokenType TokenTables::tokenize(std::string value, TokenType initial) { + for (auto &[key, param]: allTokensInfo) { + if (param.attributes & TOKENIZABLE && param.text == value) { + return key; + } + } + return initial; +} + +bool TokenTables::is_keyword(TokenType token) { + for (auto &[key, param]: allTokensInfo) { + if (param.attributes & KEYWORD_NAME && key == token) { + return true; + } + } + return false; +} + +TokenType from_token(std::string value, TokenType initial) { + return tokenTables.tokenize(value, initial); +} + +bool is_keyword(TokenType tokenType) { + return tokenTables.is_keyword(tokenType); +} \ No newline at end of file diff --git a/comdel/parser/tokenstype.h b/comdel/parser/tokens_type.h similarity index 79% rename from comdel/parser/tokenstype.h rename to comdel/parser/tokens_type.h index 30a4b68..46af38a 100644 --- a/comdel/parser/tokenstype.h +++ b/comdel/parser/tokens_type.h @@ -6,7 +6,7 @@ #include #include -const std::string& tokenTypeToString(TokenType tokenType); +const std::string &tokenTypeToString(TokenType tokenType); TokenType from_token(std::string value, TokenType initial); diff --git a/comdel/parser/tokenstype.cpp b/comdel/parser/tokenstype.cpp deleted file mode 100644 index 517b89e..0000000 --- a/comdel/parser/tokenstype.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "tokenstype.h" - -enum TokenClass { - BUILT_IN_FUNC = 1, - DATA_TYPE = 2, - KEYWORD_NAME = 4, - TOKENIZABLE = 8 -}; - - -struct TokenInfo { - std::string text; - unsigned short attributes; -}; - - - -struct TokenTables { - std::unordered_map allTokensInfo; - std::unordered_map keywords; - - TokenType tokenize(std::string value, TokenType initial); - bool is_keyword(TokenType token); - - void add(TokenType tokenType, const std::string& txt, - unsigned short attribs = 0); - - TokenTables(); -}; - - -static TokenTables tokenTables; - -void TokenTables::add (TokenType tokenType, const std::string& txt, - unsigned short attribs) -{ - allTokensInfo[tokenType] = TokenInfo{txt, attribs}; - if(attribs & KEYWORD_NAME) - keywords[txt] = tokenType; -} - -TokenTables::TokenTables() { - - add( TokenType::IDENTIFIER, "identifier" ); - add( TokenType::KEYWORD, "keyword" , KEYWORD_NAME); - - // Literals (bool is not here, it has two keywords: false and true) - add( TokenType::NUMBER, "number"); - add( TokenType::STRING, "string"); - add( TokenType::COLOR, "color"); - - // Parentheses of all kinds - add( TokenType::LPAREN, "(" ); - add( TokenType::RPAREN, ")" ); - add( TokenType::LBRACKET, "[" ); - add( TokenType::RBRACKET, "]" ); - add( TokenType::LBRACE, "{" ); - add( TokenType::RBRACE, "}" ); - add( TokenType::LT, "<" ); - add( TokenType::GT, ">" ); - - // assignments - add( TokenType::EQUALS, "=" ); - - // miscellaneous - add( TokenType::DOT, "." ); - add( TokenType::COLON, ":" ); - add( TokenType::SEMICOLON, ";" ); - add( TokenType::COMMA, "," ); - add( TokenType::WHITESPACE, "whitespace" ); - add( TokenType::COMMENT, "comment" ); - - add( TokenType::TRUE, "true", TOKENIZABLE ), - add( TokenType::FALSE, "false", TOKENIZABLE), - - add( TokenType::IF, "if", TOKENIZABLE ), - add( TokenType::ELSE, "else", TOKENIZABLE), - - add( TokenType::DEFAULT, "default", TOKENIZABLE), - add( TokenType::NIL, "null", TOKENIZABLE), - - // all keywords - add( TokenType::KW_NAME, "@name", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_INFO, "@info", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_HEADER, "@header", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_COMPONENT_HEADER, "@componentHeader", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_LIBRARY, "@library", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_ADDRESS, "@address", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_COMPONENT, "@component", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_MESSAGES, "@messages", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_COUNT, "@count", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_DISPLAY, "@display", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_PIN, "@pin", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_CONNECTION, "@connection", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_SOURCE, "@source", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_POPUP, "@popup", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_RULE, "@rule", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_TITLE, "@title", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_TEXT, "@text", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_BUS, "@bus", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_WIRES, "@wires", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_WIRE, "@wire", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_INSTANCE, "@instance", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME), - add( TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME), - - // All types - add( TokenType::INT_TYPE, "int", TOKENIZABLE), - add( TokenType::STRING_TYPE, "string", TOKENIZABLE), - add( TokenType::BOOL_TYPE, "bool", TOKENIZABLE), - add( TokenType::WIRE_TYPE, "wire", TOKENIZABLE), - - // WireNode types - add( TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE), - add( TokenType::WIRE_AND, "wired_and", TOKENIZABLE), - add( TokenType::WIRE_OR, "wired_or", TOKENIZABLE), - add( TokenType::R_WIRE, "r_wire", TOKENIZABLE), - - // ComponentNode types - add( TokenType::CT_MEMORY, "memory", TOKENIZABLE), - add( TokenType::CT_PROCESSOR, "processor", TOKENIZABLE), - - // PinNode type - add( TokenType::PIN_IN, "in", TOKENIZABLE), - add( TokenType::PIN_OUT, "out", TOKENIZABLE), - add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE), - - // ActionNode types - add( TokenType::ERROR, "error", TOKENIZABLE), - add( TokenType::WARNING, "warning", TOKENIZABLE), - - - // WireNode settings types - add( TokenType::HIDDEN, "hidden", TOKENIZABLE), - add( TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE), - - // Miscelaneous - add( TokenType::END_OF_FILE, "eof" ); -} - - -const std::string &tokenTypeToString(TokenType tokenType) { - return tokenTables.allTokensInfo[tokenType].text; -} - -TokenType TokenTables::tokenize(std::string value, TokenType initial) { - for(auto& [key, param]: allTokensInfo) { - if(param.attributes & TOKENIZABLE && param.text == value) { - return key; - } - } - return initial; -} - -bool TokenTables::is_keyword(TokenType token) { - for(auto& [key, param]: allTokensInfo) { - if(param.attributes & KEYWORD_NAME && key == token) { - return true; - } - } - return false; -} - -TokenType from_token(std::string value, TokenType initial) { - return tokenTables.tokenize(value, initial); -} - -bool is_keyword(TokenType tokenType) { - return tokenTables.is_keyword(tokenType); -} \ No newline at end of file diff --git a/examples/simplified FRISC model/comdel.system b/examples/simplified FRISC model/comdel.system index 2d81486..5a8c258 100644 --- a/examples/simplified FRISC model/comdel.system +++ b/examples/simplified FRISC model/comdel.system @@ -7,10 +7,6 @@ component System { clock 100MHz; - //directRam - wire INT; - - //glavnaSabirnica wire<32> ADR; wire<32> DATA; @@ -27,27 +23,31 @@ component System wire --BACK; + //directRam + wire INT; + + // components -------------------------------------------- subcomponent Memorija memorija(ADR, DATA, READ, WRITE, SIZE, WAIT, INT); subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT) uses memorija; display { - component { x: -12; y: 68; ref: "memorija"; } - component { x: -206; y: -76; ref: "procesor"; } - - // directRam bus - + component { x: -582; y: -296; ref: "procesor"; } + component { x: -446; y: -12; ref: "memorija"; } // glavnaSabirnica bus rectangle { - x: -222; y: 130; + x: -581; y: -37; w: 100; h: 20; } - line {x1:-28; y1:96; x2:-90; y2:-26;} - line {x1:38; y1:52; x2:-171; y2:140;} - line {x1:-156; y1:40; x2:-171; y2:140;} + // directRam bus + + + line {x1:-532; y1:-180; x2:-530; y2:-26;} + line {x1:-462; y1:16; x2:-466; y2:-246;} + line {x1:-396; y1:-28; x2:-530; y2:-26;} } } \ No newline at end of file diff --git a/examples/simplified FRISC model/schema3.csl b/examples/simplified FRISC model/schema3.csl index 9ce8028..984a346 100644 --- a/examples/simplified FRISC model/schema3.csl +++ b/examples/simplified FRISC model/schema3.csl @@ -1,8 +1,13 @@ @source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl" @schema { + @instance procesor FRISC { + @position (-76, -97) + @attribute _memory memorija + } + @instance memorija Memorija { - @position (-12, 68) + @position (52, 119) @attribute sinkroniziran false @attribute brzina 1 @attribute kapacitet 65536 @@ -10,9 +15,9 @@ @attribute pocetnaAdresa 0 } - @instance procesor FRISC { - @position (-206, -76) - @attribute _memory memorija + @instance glavnaSabirnica glavnaSabirnica { + @position (-78, 88) + @size 100 } @instance directRam directRam { @@ -20,15 +25,10 @@ @size 0 } - @instance glavnaSabirnica glavnaSabirnica { - @position (-222, 130) - @size 50 - } - - @connection (memorija.memDirect, directRam, procesor.memDirect) { - } @connection (memorija.glavniPin, glavnaSabirnica) { } @connection (procesor.glavniPin, glavnaSabirnica) { } + @connection (memorija.memDirect, directRam, procesor.memDirect) { + } } diff --git a/mainwindow.cpp b/mainwindow.cpp index 1094f7e..77241a3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -4,13 +4,13 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include -#include +#include #include #include @@ -82,7 +82,7 @@ void MainWindow::onLoadLibrary() { clear(); ParseContext parseContext; - auto libraryNode = loadLibraryFromFile(&parseContext, filename.toStdString().c_str(), buffer); + auto libraryNode = load_library_from_file(&parseContext, filename.toStdString().c_str(), buffer); if(libraryNode) { domain::SchemaCreator generator(validators); library = generator.loadLibrary(*libraryNode); @@ -119,13 +119,13 @@ void MainWindow::onLoadSchema() { clear(); ParseContext parseContext; - auto schemaNode = loadSchemaFromFile(&parseContext, filename.toStdString().c_str(), buffer); + auto schemaNode = load_schema_from_file(&parseContext, filename.toStdString().c_str(), buffer); if(schemaNode) { domain::SchemaCreator generator(validators); library = generator.loadLibrary(*schemaNode->library); - librarySource = schemaNode->source->value; + librarySource = schemaNode->source->asString(); for (auto& error : generator.getErrors()) { parseContext.formatError(error, buffer, "ERROR: "); @@ -163,7 +163,7 @@ void MainWindow::onStoreScheme() { std::ostringstream buffer; - domain::generateSchemaFile(librarySource, schema, buffer); + domain::generate_schema(librarySource, schema, buffer); std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); out< #include #include -#include +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; }