Implemented domain

This commit is contained in:
Borna Rajkovic 2022-04-05 23:48:07 +02:00
parent f4450494d8
commit e416743908
29 changed files with 920 additions and 72 deletions

View File

@ -15,12 +15,17 @@ SOURCES += \
comdel/domain/comdelgenerator.cpp \
comdel/domain/component.cpp \
comdel/domain/connection.cpp \
comdel/domain/connectioninstance.cpp \
comdel/domain/display.cpp \
comdel/domain/functionsignature.cpp \
comdel/domain/instance.cpp \
comdel/domain/instanceattribute.cpp \
comdel/domain/library.cpp \
comdel/domain/pin.cpp \
comdel/domain/rule.cpp \
comdel/domain/schema.cpp \
comdel/domain/value.cpp \
comdel/domain/wireinstance.cpp \
comdel/parser/assert.cpp \
comdel/parser/astnode.cpp \
comdel/parser/comdellexer.cpp \
@ -40,12 +45,17 @@ HEADERS += \
comdel/domain/comdelgenerator.h \
comdel/domain/component.h \
comdel/domain/connection.h \
comdel/domain/connectioninstance.h \
comdel/domain/display.h \
comdel/domain/functionsignature.h \
comdel/domain/instance.h \
comdel/domain/instanceattribute.h \
comdel/domain/library.h \
comdel/domain/pin.h \
comdel/domain/rule.h \
comdel/domain/schema.h \
comdel/domain/value.h \
comdel/domain/wireinstance.h \
comdel/parser/assert.h \
comdel/parser/astnode.h \
comdel/parser/comdellexer.h \

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 6.0.2, 2022-03-30T08:39:47. -->
<!-- Written by QtCreator 6.0.2, 2022-04-05T08:22:13. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@ -2,8 +2,33 @@
namespace domain {
Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::optional<Display> display)
: name(name), tooltip(tooltip), type(type), count(count), display(display)
Wire::Wire(std::string name, WireType type, int width, bool hidden, bool hasTermination, long long ifUnterminated)
: name(name), type(type), width(width), hidden(hidden), hasTermination(hasTermination), ifUnterminated(ifUnterminated)
{}
std::string Wire::getName() {
return name;
}
int Wire::getWidth() {
return width;
}
bool Wire::isHidden() {
return hidden;
}
bool Wire::getHasTermination() {
return hasTermination;
}
long long Wire::getIfUnterminated() {
return ifUnterminated;
}
Wire::WireType Wire::getType() {
return type;
}
Bus::Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires, std::optional<Display> display)
: name(name), tooltip(tooltip), type(type), count(count), wires(wires), display(display)
{}
std::string Bus::getName() {
@ -21,6 +46,9 @@ std::pair<int, int> Bus::getCount() {
std::optional<Display> Bus::getDisplay() {
return display;
}
std::vector<Wire> Bus::getWires() {
return wires;
}
} // namespace domain

View File

@ -5,16 +5,48 @@
#include <string>
#include <optional>
#include <vector>
namespace domain {
class Wire
{
public:
enum WireType {
WIRE_DEFAULT,
WIRED_AND,
WIRED_OR,
R_WIRE
};
private:
std::string name;
WireType type;
int width;
bool hidden;
bool hasTermination;
long long ifUnterminated;
public:
Wire(std::string name, WireType type, int width, bool hidden, bool hasTermination, long long ifUnterminated);
std::string getName();
int getWidth();
bool isHidden();
bool getHasTermination();
long long getIfUnterminated();
WireType getType();
};
class Bus
{
public:
enum BusType {
AUTOMATIC,
REGULAR
REGULAR,
AUTOMATIC_SINGLE
};
private:
std::string name;
@ -23,16 +55,17 @@ private:
std::pair<int, int> count;
std::optional<Display> display;
std::vector<Wire> wires;
public:
Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::optional<Display> display = std::nullopt);
Bus(std::string name, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires, std::optional<Display> display = std::nullopt);
std::string getName();
std::string getTooltip();
BusType getType();
std::pair<int, int> getCount();
std::vector<Wire> getWires();
std::optional<Display> getDisplay();
};
} // namespace domain

View File

@ -20,6 +20,21 @@ Action::ActionType toType(ActionNode::ActionType type) {
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:
@ -86,31 +101,31 @@ ComdelGenerator::ComdelGenerator(std::vector<FunctionSignature> signatures)
: signatures(signatures)
{}
std::optional<Library> ComdelGenerator::loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream)
std::optional<Library> ComdelGenerator::loadLibrary(LibraryNode node)
{
// library fields
if(!node.name) {
errors.push_back(SourceError{node.span, "missing @name"});
return nullopt;
} else {
name = node.name->asString();
}
std::string name = node.name->asString();
if(!node.componentDirectory) {
errors.push_back(SourceError{node.span, "missing @componentDirectory"});
return nullopt;
} else {
componentDirectory = node.componentDirectory->asString();
}
std::string componentDirectory = node.componentDirectory->asString();
std::string header = node.header ? node.header->asString() : "";
header = node.header ? node.header->asString() : "";
std::string libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : "";
libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : "";
std::vector<AddressSpace> addressSpaces;
for(auto& as: node.addressSpaces) {
addressSpaces.push_back(*loadAddressSpace(as));
}
std::vector<Component> components;
for(auto& comp: node.components) {
std::optional<Component> component;
component = loadComponent(comp);
@ -119,29 +134,25 @@ std::optional<Library> ComdelGenerator::loadLibrary(LibraryNode node, ParseConte
}
}
std::vector<Connection> connections;
for(uint i=0; i<node.connections.size(); i++) {
auto conn = loadConnection(node.connections[i]);
if(!conn) {
return nullopt;
}
connections.push_back(*conn);
}
std::map<std::string, std::string> messages;
for(uint i=0; i<node.messages.size(); i++) {
if(!node.messages[i].value.is(ValueNode::STRING)) {
errors.push_back(SourceError{node.messages[i].key.span, "expected `string`"});
return nullopt;
}
messages[node.messages[i].key.value] = node.messages[i].value.asString();
}
std::vector<Bus> buses;
for(uint i=0; i<node.buses.size(); i++) {
auto bus = loadBus(node.buses[i]);
if(!bus) {
return nullopt;
if(bus) {
buses.push_back(*bus);
}
}
for(uint i=0; i<node.connections.size(); i++) {
auto conn = loadConnection(node.connections[i]);
if(conn) {
connections.push_back(*conn);
}
}
for(uint i=0; i<node.messages.size(); i++) {
if(!node.messages[i].value.is(ValueNode::STRING)) {
errors.push_back(SourceError{node.messages[i].span, "expected `string`"});
} else {
messages[node.messages[i].key.value] = node.messages[i].value.asString();
}
}
@ -157,7 +168,7 @@ std::optional<Bus> ComdelGenerator::loadBus(BusNode node)
count = std::make_pair<int, int>(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"});
errors.push_back(SourceError{node.count->span, "invalid @size"});
return nullopt;
}
@ -173,12 +184,11 @@ std::optional<Bus> ComdelGenerator::loadBus(BusNode node)
errors.push_back(SourceError{node.span, "missing @display"});
return nullopt;
}
if(node.display && type == Bus::AUTOMATIC) {
if(node.display && (type == Bus::AUTOMATIC || type == Bus::AUTOMATIC_SINGLE)) {
errors.push_back(SourceError{node.span, "automatic bus cannot have a @display"});
return nullopt;
}
optional<Display> display;
if(Bus::REGULAR) {
display = loadDisplay(*node.display);
@ -187,7 +197,19 @@ std::optional<Bus> ComdelGenerator::loadBus(BusNode node)
}
}
return Bus(name, tooltip, type, count, display);
if(node.wires.size() == 0) {
errors.push_back(SourceError{node.span, "missing @wires"});
return nullopt;
}
std::vector<Wire> wires;
for(auto& _wire: node.wires) {
auto wire = loadWire(_wire);
if(wire) {
wires.push_back(*wire);
}
}
return Bus(name, tooltip, type, count, wires, display);
}
@ -198,10 +220,28 @@ std::optional<AddressSpace> ComdelGenerator::loadAddressSpace(AddressSpaceNode n
std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
{
push(ComdelContext("connection", false, true, false));
std::string component = node.component.value;
std::string pin = node.pin.value;
std::string bus = node.bus.value;
auto componentInstance = getComponentPin(component, pin);
if(!componentInstance) {
errors.push_back(SourceError(node.span, "pin does not exist"));
}
auto busInstance = getBus(bus);
if(!busInstance) {
errors.push_back(SourceError(node.span, "bus does not exist"));
}
std::set<std::string> wireNames;
for(auto &wire: busInstance->getWires()) {
wireNames.insert(wire.getName());
current().wires.push_back(wire.getName());
}
std::vector<Attribute> attributes;
for(uint i=0; i<node.attributes.size(); i++) {
auto attr = loadAttribute(node.attributes[i]);
@ -220,26 +260,34 @@ std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
for(uint i=0; i<node.wires.size(); i++) {
if(attributeNames.count(node.wires[i].value)) {
wires.push_back(Value::fromReference(node.wires[i].value, Value::ATTRIBUTE_REFERENCE));
} else {
} else if(wireNames.count(node.wires[i].value)) {
wires.push_back(Value::fromReference(node.wires[i].value, Value::WIRE_REFERENCE));
} else {
errors.push_back(SourceError(node.wires[i].span, "unknown identifier"));
}
}
pop();
return Connection(component, pin, bus, attributes, wires);
}
std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
{
push(ComdelContext(node.name.value, true, false, false));
std::string name = node.name.value;
if(!node.tooltip) {
errors.push_back(SourceError{node.span, "missing @tooltip"});
pop();
return nullopt;
}
std::string tooltip = node.tooltip->asString();
if(!node.source) {
errors.push_back(SourceError{node.span, "missing @source"});
pop();
return nullopt;
}
std::string source = node.source->asString();
@ -254,6 +302,8 @@ std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
}
}
context[context.size() -1 ].attributes = attributes;
std::vector<Rule> rules;
for(auto& r: node.rules) {
std::optional<Rule> rule = loadRule(r);
@ -264,6 +314,7 @@ std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
if(!node.instanceName) {
errors.push_back(SourceError{node.span, "missing @instanceName"});
pop();
return nullopt;
}
std::string instanceName = node.instanceName->asString();
@ -274,15 +325,18 @@ std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
}
if(count.first > count.second || count.first < 0) {
errors.push_back(SourceError{node.count->first.span, "invalid @size"});
pop();
return nullopt;
}
if(!node.display) {
errors.push_back(SourceError{node.span, "missing @display"});
pop();
return nullopt;
}
optional<Display> display = loadDisplay(*node.display);
if(!display) {
pop();
return nullopt;
}
@ -290,13 +344,27 @@ std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
for(uint i=0; i<node.pins.size(); i++) {
auto pin = loadPin(node.pins[i]);
if(!pin) {
pop();
return nullopt;
}
pins.push_back(*pin);
}
pop();
return Component(name, tooltip, source, type, rules, instanceName, count, *display, pins, attributes);
}
std::optional<Wire> ComdelGenerator::loadWire(WireNode node) {
return Wire(
node.name.value,
toType(node.type),
node.size.value,
node.hidden,
node.hasTermination,
node.isUnterminated
);
}
optional<Pin> ComdelGenerator::loadPin(PinNode node)
{
std::string name = node.name.value;
@ -344,22 +412,41 @@ PinConnection ComdelGenerator::loadPinConnection(PinConnectionNode node)
std::optional<Attribute> ComdelGenerator::loadAttribute(AttributeNode node)
{
std::string name = node.name.value;
pushAdditional(name);
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);
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.push_back(SourceError{node.name.span, "unsupported type"});
}
}
if(current().inConnection) { // 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.push_back(SourceError{node.span, "unknown identifier"});
}
} else {
errors.push_back(SourceError{node.name.span, "unsupported type"});
}
}
current().attributes.push_back(Attribute(name, value));
std::optional<Popup> popup;
if(node.popup) {
popup = loadPopup(*node.popup, name, value.getType());
}
pop();
return Attribute(name, value, popup);
}
@ -367,6 +454,11 @@ std::optional<Popup> ComdelGenerator::loadPopup(PopupNode node, std::string name
{
auto popupType = toType(*node.type);
pushAdditional(name);
current().attributes.clear();
current().attributes.push_back(Attribute(name, Value::ofType(type)));
if(!node.title) {
errors.push_back(SourceError{node.span, "missing @title"});
return nullopt;
@ -379,9 +471,6 @@ std::optional<Popup> ComdelGenerator::loadPopup(PopupNode node, std::string name
}
std::string text = node.text->asString();
std::vector<Attribute> attributes;
attributes.push_back(Attribute(name, Value::ofType(type)));
std::vector<Rule> rules;
for(auto& r: node.rules) {
std::optional<Rule> rule = loadRule(r);
@ -394,14 +483,29 @@ std::optional<Popup> ComdelGenerator::loadPopup(PopupNode node, std::string name
if(node.enumerated) {
for(uint i=0; i<node.enumeration.size(); i++) {
if(toType(node.enumeration[i].value.getType()) != type) {
errors.push_back(SourceError{node.enumeration[i].span, "wrong type"});
return nullopt;
}
enumeration.push_back(Enumeration(node.enumeration[i].key.asString(),
toType(node.enumeration[i].value)));
auto value = toType(node.enumeration[i].value);
if(value.isType(Value::UNDEFINED) && current().doesWireExists(value.asReference())) {
value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE);
} else {
errors.push_back(SourceError{node.enumeration[i].span, "unknown wire"});
}
if(value.getType() != type) {
errors.push_back(SourceError{node.enumeration[i].span, "wrong type"});
}
enumeration.push_back(Enumeration(node.enumeration[i].key.asString(), value));
}
} else {
if(type == Value::WIRE_REFERENCE && !current().inConnection) {
errors.push_back(SourceError{node.span, "@enumeration is required for atributes of type wire"});
}
}
pop();
return Popup(title, text, popupType, rules, enumeration);
}
@ -429,17 +533,165 @@ std::optional<Condition> ComdelGenerator::loadCondition(ConditionNode node)
if(signatures[i].name == function) {
if(signatures[i].params.size() == node.params.size()) {
std::vector<Value> params;
for(int j=0; j<signatures[i].params[i]; j++) {
params.push_back(toType(node.params[i]));
for(uint j=0; j<signatures[i].params.size(); j++) {
bool exists = false;
auto type = toType(node.params[j]);
if (type.getType() == Value::UNDEFINED) {
if(current().doesAttributeExists(type.asReference(), signatures[i].params[j])) {
exists = true;
type = Value::fromReference(type.asReference(), Value::ATTRIBUTE_REFERENCE);
}
if(signatures[i].params[j] == Value::ADDRESS_SPACE) {
if(hasAddressSpace(type.asReference())) {
exists = true;
type = Value::fromReference(type.asReference(), Value::ADDRESS_SPACE);
}
}
if(!exists) {
errors.push_back(SourceError{node.functionName.span, "unknown reference " + type.asReference()});
}
}
params.push_back(type);
}
return Condition(function,params, node.negated);
return Condition(function, params, node.negated);
} else {
errors.push_back(SourceError{node.functionName.span, "wrong number of parametars"});
}
}
}
errors.push_back(SourceError{node.functionName.span, "unknown function name"});
return nullopt;
}
std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &library)
{
Schema schema;
for(auto &instance: node.instances) {
if(library.hasComponent(instance.component.value)) {
schema.instances.push_back(loadComponentInstance(instance, library));
}
if(library.hasBus(instance.component.value)) {
schema.instances.push_back(loadBusInstance(instance, library));
}
}
for(auto &wire: node.wires) {
auto w = loadWireInstance(wire);
if(w) {
schema.wires.push_back(*w);
}
}
for(auto &conn: node.connections) {
auto component = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.instance.value));
if(component == NULL) {
errors.push_back(SourceError{conn.instance.span, "unknown component"});
continue;
}
if(!component->component.hasPin(conn.pin.value)) {
errors.push_back(SourceError{conn.pin.span, "unknown pin"});
continue;
}
auto bus = dynamic_cast<BusInstance*>(schema.getInstance(conn.bus.value));
if(bus == NULL) {
errors.push_back(SourceError{conn.bus.span, "unknown bus"});
continue;
}
if(!library.hasConnection(component->component.getName(), conn.pin.value, bus->bus.getName())) {
errors.push_back(SourceError{conn.span, "unknown connection"});
continue;
}
auto connection = *library.getConnection(component->component.getName(), conn.pin.value, bus->bus.getName());
if(!conn.wire) {
errors.push_back(SourceError{conn.span, "missing @wire"});
continue;
}
if(!schema.hasWire(conn.wire->value)) {
errors.push_back(SourceError{conn.wire->span, "unknown wire"});
continue;
}
auto wire = schema.getWire(conn.wire->value);
std::vector<InstanceAttribute*> 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.push_back(SourceError{attr.span, "invalid value"});
}
attributes.push_back(new InstanceAttribute(attribute.getName(), toType(attr.value), attribute));
} else {
errors.push_back(SourceError(attr.name.span, "unknown attribute"));
}
}
schema.connections.push_back(new BusConnectionInstance(component, attributes, bus, wire, connection));
}
return schema;
}
ComponentInstance *ComdelGenerator::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<InstanceAttribute*> attributes;
for(auto& attr: instance.attributes) {
if(component.hasAttribute(attr.name.value, toType(attr.value.getType()))) {
auto attribute = component.getAttribute(attr.name.value);
attributes.push_back(new InstanceAttribute(attribute.getName(), toType(attr.value), attribute));
} else {
errors.push_back(SourceError(attr.name.span, "unknown attribute"));
}
}
return new ComponentInstance(name, attributes, position, component);
}
BusInstance *ComdelGenerator::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 new BusInstance(name, position, bus, size);
}
std::optional<WireInstance*> ComdelGenerator::loadWireInstance(WireInstanceNode node) {
if(!node.display) {
errors.push_back(SourceError{node.span, "missing @text"});
return nullopt;
}
auto display = loadDisplay(*node.display);
if(!display) {
return nullopt;
}
return std::optional<WireInstance*>(new WireInstance(node.name.value, *display));
}
} // namespace domain

View File

@ -2,6 +2,9 @@
#define DOMAIN_COMDELGENERATOR_H
#include "library.h"
#include "schema.h"
#include <set>
#include <comdel/parser/astnode.h>
#include <comdel/parser/parsecontext.h>
@ -9,8 +12,53 @@
namespace domain {
struct ComdelContext {
std::vector<Attribute> attributes;
std::vector<std::string> wires;
std::string name;
bool inComponent;
bool inConnection;
bool inBus;
ComdelContext(std::string name, bool inComponent, bool inConnection, bool inBus)
: name(name), inComponent(inComponent), inConnection(inConnection), 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 ComdelGenerator
{
std::vector<ComdelContext> context;
std::string name;
std::string libraryInfo;
std::string header;
std::string componentDirectory;
std::vector<AddressSpace> addressSpaces;
std::vector<Component> components;
std::vector<Bus> buses;
std::vector<Connection> connections;
std::map<std::string, std::string> messages;
std::vector<SourceError> errors;
std::vector<FunctionSignature> signatures;
@ -21,11 +69,66 @@ class ComdelGenerator
std::optional<Condition> loadCondition(ConditionNode node);
std::optional<Popup> loadPopup(PopupNode node, std::string name, Value::ValueType type);
std::optional<Display> loadDisplay(DisplayNode node);
std::optional<Wire> loadWire(WireNode node);
std::optional<Pin> loadPin(PinNode pins);
PinConnection loadPinConnection(PinConnectionNode node);
std::optional<Connection> loadConnection(ConnectionNode node);
std::optional<Bus> loadBus(BusNode node);
ComponentInstance *loadComponentInstance(InstanceNode instance, Library &library);
BusInstance *loadBusInstance(InstanceNode instance, Library &library);
std::optional<WireInstance*> loadWireInstance(WireInstanceNode node);
std::optional<Bus> getBus(std::string name) {
for(auto &bus: buses) {
if(bus.getName() == name) {
return bus;
}
}
return std::nullopt;
}
std::optional<Pin> 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.size() > 0) {
this->context.push_back(current());
current().name = name;
} else {
ComdelContext con(name, false, false, false);
push(con);
}
}
ComdelContext &current() {
return this->context[this->context.size() - 1];
}
void pop() {
this->context.pop_back();
}
public:
ComdelGenerator(std::vector<FunctionSignature> signatures);
@ -33,7 +136,9 @@ public:
return errors;
}
std::optional<Library> loadLibrary(LibraryNode node, ParseContext* parseContext, std::ostream& stream);
std::optional<Library> loadLibrary(LibraryNode node);
std::optional<Schema> loadSchema(SchemaNode node, Library &library);
};
} // namespace domain

View File

@ -0,0 +1,18 @@
#include "comdelvalidator.h"
namespace domain {
ComdelValidator::ComdelValidator(std::vector<FunctionSignature> signatures)
: signatures(signatures)
{}
std::vector<SourceError> ComdelValidator::getErrors() {
return errors;
}
void validateLibrary(Library library, ParseContext* parseContext, std::ostream& stream) {
}
} // namespace domain

View File

@ -0,0 +1,34 @@
#ifndef DOMAIN_COMDELVALIDATOR_H
#define DOMAIN_COMDELVALIDATOR_H
#include "functionsignature.h"
#include "library.h"
#include <vector>
#include <comdel/parser/parsecontext.h>
#include <comdel/parser/sourceerror.h>
namespace domain {
class ComdelValidator
{
private:
std::vector<SourceError> errors;
std::vector<FunctionSignature> signatures;
public:
ComdelValidator(std::vector<FunctionSignature> signatures);
std::vector<SourceError> getErrors() {
return errors;
}
void validateLibrary(Library library, ParseContext* parseContext, std::ostream& stream);
};
} // namespace domain
#endif // DOMAIN_COMDELVALIDATOR_H

View File

@ -45,6 +45,15 @@ Pin Component::getPin(std::string pin) {
throw std::exception();
}
bool Component::hasPin(std::string name) {
for(auto pin: pins) {
if(pin.getName() == name) {
return true;
}
}
return false;
}
std::vector<Attribute> Component::getAttributes() {
return attributes;
}
@ -55,8 +64,16 @@ Attribute Component::getAttribute(std::string attribute) {
}
}
throw std::exception();
}
bool Component::hasAttribute(std::string name, Value::ValueType type) {
for(uint i=0; i<attributes.size(); i++) {
if(attributes[i].getName() == name && attributes[i].getDefault().getType() == type) {
return true;
}
}
return false;
}
} // namespace domain

View File

@ -55,6 +55,9 @@ public:
std::vector<Attribute> getAttributes();
Attribute getAttribute(std::string attribute);
bool hasAttribute(std::string name, Value::ValueType type);
bool hasPin(std::string name);
};

View File

@ -36,4 +36,13 @@ Attribute Connection::getAttribute(std::string name) {
throw std::exception();
}
bool Connection::hasAttribute(std::string name) {
for(uint i=0; i<attributes.size(); i++) {
if(attributes[i].getName() == name) {
return true;
}
}
return false;
}
} // namespace domain

View File

@ -29,6 +29,7 @@ public:
std::vector<Value> getWires();
Attribute getAttribute(std::string name);
bool hasAttribute(std::string name);
};
} // namespace domain

View File

@ -0,0 +1,18 @@
#include "connectioninstance.h"
namespace domain {
ConnectionInstance::ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute*> attributes, WireInstance *wire, Connection connection)
: instance(instance), attributes(attributes), connection(connection), wire(wire)
{}
BusConnectionInstance::BusConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute*> attributes, BusInstance *bus, WireInstance *wire, Connection connection)
: ConnectionInstance(instance, attributes, wire, connection), bus(bus)
{}
DirectConnectionInstance::DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, std::vector<InstanceAttribute*> attributes, BusInstance *bus, WireInstance *wire, Connection connection)
: ConnectionInstance(instance, attributes, wire, connection), secondInstance(secondInstance), bus(bus)
{}
} // namespace domain

View File

@ -0,0 +1,46 @@
#ifndef DOMAIN_CONNECTIONINSTANCE_H
#define DOMAIN_CONNECTIONINSTANCE_H
#include "connection.h"
#include "instance.h"
#include "wireinstance.h"
namespace domain {
class ConnectionInstance
{
public:
ComponentInstance *instance;
Connection connection;
WireInstance *wire;
std::vector<InstanceAttribute*> attributes;
ConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute*> attributes, WireInstance *wire, Connection connection);
};
class BusConnectionInstance: public ConnectionInstance
{
public:
BusInstance *bus;
BusConnectionInstance(ComponentInstance *instance, std::vector<InstanceAttribute*> attributes, BusInstance *bus, WireInstance *wire, Connection connection);
};
class DirectConnectionInstance: public ConnectionInstance
{
public:
BusInstance *bus;
ComponentInstance *secondInstance;
DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, std::vector<InstanceAttribute*> attributes, BusInstance *bus, WireInstance *wire, Connection connection);
};
} // namespace domain
#endif // DOMAIN_CONNECTIONINSTANCE_H

View File

@ -0,0 +1,17 @@
#include "instance.h"
namespace domain {
Instance::Instance(std::string name, std::vector<InstanceAttribute*> attributes, std::pair<int, int> position)
: name(name), attributes(attributes), position(position)
{}
BusInstance::BusInstance(std::string name, std::pair<int, int> position, Bus bus, int size)
: Instance(name, vector<InstanceAttribute*>(), position), bus(bus), size(size)
{}
ComponentInstance::ComponentInstance(std::string name, std::vector<InstanceAttribute*> attributes, std::pair<int, int> position, Component component)
: Instance(name, attributes, position), component(component)
{}
} // namespace domain

54
comdel/domain/instance.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef DOMAIN_INSTANCE_H
#define DOMAIN_INSTANCE_H
#include "bus.h"
#include "component.h"
#include "instanceattribute.h"
#include <string>
#include <vector>
namespace domain {
class Instance
{
public:
std::string name;
std::vector<InstanceAttribute*> attributes;
std::pair<int, int> position;
virtual ~Instance() {};
Instance(std::string name, std::vector<InstanceAttribute*> attributes, std::pair<int, int> position);
};
class BusInstance: public Instance
{
public:
Bus bus;
int size;
BusInstance(std::string name, std::pair<int, int> position, Bus bus, int size);
virtual ~BusInstance() {
Instance::~Instance();
}
};
class ComponentInstance: public Instance
{
public:
Component component;
ComponentInstance(std::string name, std::vector<InstanceAttribute*> attributes, std::pair<int, int> position, Component component);
virtual ~ComponentInstance() {
Instance::~Instance();
}
};
} // namespace domain
#endif // DOMAIN_INSTANCE_H

View File

@ -0,0 +1,9 @@
#include "instanceattribute.h"
namespace domain {
InstanceAttribute::InstanceAttribute(std::string name, Value value, Attribute attribute)
: name(name), value(value), attribute(attribute)
{}
} // namespace domain

View File

@ -0,0 +1,26 @@
#ifndef DOMAIN_INSTANCEATTRIBUTE_H
#define DOMAIN_INSTANCEATTRIBUTE_H
#include "attribute.h"
#include "value.h"
#include <string>
namespace domain {
class InstanceAttribute
{
public:
InstanceAttribute(std::string name, Value value, Attribute attribute);
std::string name;
Value value;
Attribute attribute;
};
} // namespace domain
#endif // DOMAIN_INSTANCEATTRIBUTE_H

View File

@ -38,6 +38,24 @@ std::map<std::string, std::string> 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;
}
AddressSpace &Library::getAddressSpace(std::string addressSpace) {
for(uint i=0; i<addressSpaces.size(); i++) {
if(addressSpaces[i].getName() == addressSpace) {
@ -71,6 +89,10 @@ std::optional<Connection> Library::getConnection(std::string component, std::str
}
return nullopt;
}
bool Library::hasConnection(std::string component, std::string pin, std::string bus) {
return getConnection(component, pin, bus).has_value();
}
std::string Library::getMessage(std::string key) {
return messages[key];
}

View File

@ -43,6 +43,10 @@ public:
std::vector<Bus> getBuses();
std::vector<Connection> getConnections();
bool hasComponent(std::string name);
bool hasBus(std::string name);
bool hasConnection(std::string component, std::string pin, std::string bus);
std::map<std::string, std::string> getMessages();
AddressSpace &getAddressSpace(std::string name);
@ -51,6 +55,8 @@ public:
std::optional<Connection> getConnection(std::string component, std::string pin, std::string bus);
std::string getMessage(std::string key);
};
} // namespace domain

9
comdel/domain/schema.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "schema.h"
namespace domain {
Schema::Schema()
{
}
} // namespace domain

47
comdel/domain/schema.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef DOMAIN_SCHEMA_H
#define DOMAIN_SCHEMA_H
#include "connectioninstance.h"
#include "instance.h"
#include "wireinstance.h"
#include <vector>
namespace domain {
class Schema
{
public:
Schema();
std::vector<Instance*> instances;
std::vector<ConnectionInstance*> connections;
std::vector<WireInstance*> wires;
WireInstance *getWire(std::string name) {
for(auto wire: wires) {
if (wire->name == name) {
return wire;
}
}
return nullptr;
}
bool hasWire(std::string name) {
return getWire(name) != NULL;
}
Instance *getInstance(std::string name) {
for(auto instance: instances) {
if (instance->name == name) {
return instance;
}
}
return nullptr;
}
};
} // namespace domain
#endif // DOMAIN_SCHEMA_H

View File

@ -36,12 +36,38 @@ AddressSpace Value::asAddressSpace() {
throw std::exception();
}
std::string Value::asReference() {
if(isType(Value::WIRE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE)) {
if(isType(Value::WIRE_REFERENCE) || isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) {
return reference;
}
throw std::exception();
}
void Value::setInt(long long value) {
if(isType(Value::INT)) {
this->intValue = value;
}
throw std::exception();
}
void Value::setString(std::string value) {
if(isType(Value::STRING)) {
this->stringValue = value;
}
throw std::exception();
}
void Value::setBool(bool value) {
if(isType(Value::BOOL)) {
this->boolValue = value;
}
throw std::exception();
}
void Value::setReference(std::string value) {
if(isType(Value::WIRE_REFERENCE)) {
this->reference = value;
}
throw std::exception();
}
Value Value::fromInt(long long value) {
Value val;
val.type = Value::INT;

View File

@ -45,6 +45,11 @@ public:
std::string asReference();
AddressSpace asAddressSpace();
void setInt(long long intValue);
void setString(std::string value);
void setBool(bool value);
void setReference(std::string value);
static Value fromInt(long long value);
static Value fromString(std::string value);
static Value fromBool(bool value);

View File

@ -0,0 +1,10 @@
#include "wireinstance.h"
namespace domain {
WireInstance::WireInstance(std::string name, Display display)
: name(name), display(display)
{}
} // namespace domain

View File

@ -0,0 +1,23 @@
#ifndef DOMAIN_WIREINSTANCE_H
#define DOMAIN_WIREINSTANCE_H
#include "display.h"
#include <string>
namespace domain {
class WireInstance
{
public:
std::string name;
Display display;
WireInstance(std::string name, Display display);
};
} // namespace domain
#endif // DOMAIN_WIREINSTANCE_H

View File

@ -104,7 +104,7 @@ public:
throw "cannot convert type to string";
}
std::string asIdentifier() {
if(is(IDENTIFIER)) {
if(is(IDENTIFIER) || is(WIRE)) {
return identifierValue.value();
}
throw "cannot convert type to identifier";
@ -271,13 +271,11 @@ struct WireNode: public AstNode
WireType type;
IdentifierNode name;
NumberNode size;
/*
bool isTerminatedWith;
long terminatedWith;
bool isIfUntrminated;
long ifUnterminated;
*/
bool hidden;
bool hasTermination;
long long isUnterminated;
};

View File

@ -144,7 +144,7 @@ ComdelParser::parseList(std::optional<TokenType> openDelim,
vec.push_back(*item);
}
return std::move(vec);
return vec;
}
const std::vector<SourceError> &ComdelParser::getErrors()
@ -703,7 +703,7 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
} else if(check(TokenType::BOOL_TYPE)) {
attribute.type = ValueNode::BOOL;
} else if(check(TokenType::WIRE_TYPE)) {
attribute.type = ValueNode::IDENTIFIER;
attribute.type = ValueNode::WIRE;
} else {
return unexpected();
}
@ -729,7 +729,7 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
} else if(attribute.type == ValueNode::STRING) {
if(check(TokenType::STRING)) {
auto string = parseString();
attribute.defaultValue = ValueNode::ofString(string->value);
attribute.defaultValue = ValueNode::ofString(string->asString());
} else {
return unexpected();
}
@ -740,6 +740,13 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
} else {
return unexpected();
}
} else if(attribute.type == ValueNode::WIRE) {
if(check(TokenType::IDENTIFIER)) {
auto identifier = parseIdentifier();
attribute.defaultValue = ValueNode::ofWire(identifier->value);
} else {
return unexpected();
}
}
if(check(TokenType::LBRACE)) {
@ -964,7 +971,7 @@ PResult<ValueNode> ComdelParser::parseValue() {
if(check(TokenType::IDENTIFIER)) {
value = ValueNode::ofIdentifier(parseIdentifier()->value);
} else if(check(TokenType::STRING)) {
value = ValueNode::ofString(parseString()->value);
value = ValueNode::ofString(parseString()->asString());
} else if(check(TokenType::NUMBER)) {
value = ValueNode::ofInt(parseNumber()->value);
} else if(check(TokenType::TRUE)) {

View File

@ -23,13 +23,28 @@ int main(int argc, char *argv[])
if(schema) {
std::vector<domain::FunctionSignature> signatures;
signatures.push_back(domain::FunctionSignature("divisible", std::vector<domain::Value::ValueType>{domain::Value::INT, domain::Value::INT}));
signatures.push_back(domain::FunctionSignature("less_then", std::vector<domain::Value::ValueType>{domain::Value::INT, domain::Value::INT}));
signatures.push_back(domain::FunctionSignature("greater_then", std::vector<domain::Value::ValueType>{domain::Value::INT, domain::Value::INT}));
signatures.push_back(domain::FunctionSignature("contains_address", std::vector<domain::Value::ValueType>{domain::Value::ADDRESS_SPACE, domain::Value::INT}));
signatures.push_back(domain::FunctionSignature("contains", std::vector<domain::Value::ValueType>{domain::Value::ADDRESS_SPACE, domain::Value::INT, domain::Value::INT}));
signatures.push_back(domain::FunctionSignature("unique", std::vector<domain::Value::ValueType>{domain::Value::ADDRESS_SPACE, domain::Value::INT, domain::Value::INT}));
domain::ComdelGenerator generator(signatures);
generator.loadLibrary(*schema->library, &parseContext, std::cout);
auto library = generator.loadLibrary(*schema->library);
for (auto& error : generator.getErrors()) {
parseContext.formatError(error, std::cout, "ERROR: ");
}
if(library) {
auto instance = generator.loadSchema(*schema, *library);
for (auto& error : generator.getErrors()) {
parseContext.formatError(error, std::cout, "ERROR: ");
}
}
}
}