#include "comdelgenerator.h" #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; } Value::ValueType toType(ValueNode::ValueType type) { switch (type) { case ValueNode::BOOL: return Value::BOOL; case ValueNode::WIRE: return Value::WIRE_REFERENCE; case ValueNode::STRING: return Value::STRING; case ValueNode::INT: return Value::INT; default: return Value::UNDEFINED; } } Value toType(ValueNode node) { 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()); } return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); } Bus::BusType toType(BusNode::BusType type) { if(type == BusNode::AUTOMATIC) { return Bus::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::AUTOMATICALLY) { return PinConnection::AUTOMATICALLY; } return PinConnection::CHECK_ONLY; } Popup::PopupType toType(PopupNode::PopupType type) { if(type == PopupNode::AUTOMATIC) { return Popup::AUTOMATIC; } return Popup::ON_DEMAND; } ComdelGenerator::ComdelGenerator(std::vector signatures) : signatures(signatures) {} std::optional ComdelGenerator::loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream) { // library fields if(!node.name) { errors.push_back(SourceError{node.span, "missing @name"}); return nullopt; } std::string name = node.name->asString(); if(!node.componentDirectory) { errors.push_back(SourceError{node.span, "missing @componentDirectory"}); return nullopt; } std::string componentDirectory = node.componentDirectory->asString(); std::string header = node.header ? node.header->asString() : ""; std::string libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; std::vector addressSpaces; for(auto& as: node.addressSpaces) { addressSpaces.push_back(*loadAddressSpace(as)); } std::vector components; for(auto& comp: node.components) { std::optional component; component = loadComponent(comp); if(component) { components.push_back(*component); } } std::vector connections; for(uint i=0; i messages; for(uint i=0; i buses; for(uint i=0; i ComdelGenerator::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.push_back(SourceError{node.count->span, "invalid @size (min, max) := min <= max && min >= 0"}); return nullopt; } auto type = toType(node.type); if(!node.tooltip && type == Bus::REGULAR) { errors.push_back(SourceError{node.span, "missing @tooltip"}); return nullopt; } std::string tooltip = node.tooltip->asString(); if(!node.display && type == Bus::REGULAR) { errors.push_back(SourceError{node.span, "missing @display"}); return nullopt; } if(node.display && type == Bus::AUTOMATIC) { errors.push_back(SourceError{node.span, "automatic bus cannot have a @display"}); return nullopt; } optional display; if(Bus::REGULAR) { display = loadDisplay(*node.display); if(!display) { return nullopt; } } return Bus(name, tooltip, type, count, display); } std::optional ComdelGenerator::loadAddressSpace(AddressSpaceNode node) { return AddressSpace(node.name.value, node.start.value, node.end.value); } std::optional ComdelGenerator::loadConnection(ConnectionNode node) { std::string component = node.component.value; std::string pin = node.pin.value; std::string bus = node.bus.value; std::vector attributes; for(uint i=0; i attributeNames; for(auto attribute: attributes) { attributeNames.insert(attribute.getName()); } std::vector wires; for(uint i=0; i ComdelGenerator::loadComponent(ComponentNode node) { std::string name = node.name.value; if(!node.tooltip) { errors.push_back(SourceError{node.span, "missing @tooltip"}); return nullopt; } std::string tooltip = node.tooltip->asString(); if(!node.source) { errors.push_back(SourceError{node.span, "missing @source"}); return nullopt; } std::string source = node.source->asString(); Component::ComponentType type = toType(node.type); std::vector attributes; for(auto& a: node.attributes) { std::optional attribute = loadAttribute(a); if(attribute) { attributes.push_back(*attribute); } } std::vector rules; for(auto& r: node.rules) { std::optional rule = loadRule(r); if(rule) { rules.push_back(*rule); } } if(!node.instanceName) { errors.push_back(SourceError{node.span, "missing @instanceName"}); 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.push_back(SourceError{node.count->first.span, "invalid @size"}); return nullopt; } if(!node.display) { errors.push_back(SourceError{node.span, "missing @display"}); return nullopt; } optional display = loadDisplay(*node.display); if(!display) { return nullopt; } std::vector pins; for(uint i=0; i ComdelGenerator::loadPin(PinNode node) { std::string name = node.name.value; Pin::PinType type = toType(node.type); if(!node.tooltip) { errors.push_back(SourceError{node.span, "missing @tooltip"}); return nullopt; } std::string tooltip = node.tooltip->asString(); if(!node.display) { errors.push_back(SourceError{node.span, "missing @display"}); return nullopt; } std::vector attributes; optional display = loadDisplay(*node.display); if(!display) { return nullopt; } if(!node.connection) { errors.push_back(SourceError{node.span, "missing @connection"}); return nullopt; } auto connection = loadPinConnection(*node.connection); return Pin(name, type, tooltip, connection, *display); } std::optional ComdelGenerator::loadDisplay(DisplayNode node) { return Display(); } PinConnection ComdelGenerator::loadPinConnection(PinConnectionNode node) { std::string message = node.message.asString(); PinConnection::ConnectionType type = toType(node.type); return PinConnection(message, type); } std::optional ComdelGenerator::loadAttribute(AttributeNode node) { std::string name = node.name.value; Value value; 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 if (node.type == ValueNode::WIRE) { value = Value::fromReference(node.defaultValue->asIdentifier(), Value::WIRE_REFERENCE); } std::optional popup; if(node.popup) { popup = loadPopup(*node.popup, name, value.getType()); } return Attribute(name, value, popup); } std::optional ComdelGenerator::loadPopup(PopupNode node, std::string name, Value::ValueType type) { auto popupType = toType(*node.type); if(!node.title) { errors.push_back(SourceError{node.span, "missing @title"}); return nullopt; } std::string title = node.title->asString(); if(!node.text) { errors.push_back(SourceError{node.span, "missing @text"}); return nullopt; } std::string text = node.text->asString(); std::vector attributes; attributes.push_back(Attribute(name, Value::ofType(type))); 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(uint i=0; i ComdelGenerator::loadRule(RuleNode node) { std::vector statements; for(auto& stmt: node.statements) { auto condition = loadCondition(stmt.condition); if(condition) { statements.push_back(IfStatement(*condition, Action(toType(stmt.action.type), stmt.action.message.asString()))); } else { return nullopt; } } return Rule(statements); } std::optional ComdelGenerator::loadCondition(ConditionNode node) { std::string function = node.functionName.value; for(uint i=0; i params; for(int j=0; j