Laurent@814: #!/usr/bin/env python Laurent@814: # -*- coding: utf-8 -*- Edouard@1957: # This file is part of Beremiz. andrej@1571: # See COPYING file for copyrights details. andrej@1850: andrej@1881: from __future__ import absolute_import edouard@1959: from collections import OrderedDict, namedtuple Edouard@1957: from plcopen.XSLTModelQuery import XSLTModelQuery, _StringValue, _BoolValue, _translate_args andrej@1832: andrej@1782: # ------------------------------------------------------------------------------- Laurent@1338: # Helpers object for generating pou block instances list andrej@1782: # ------------------------------------------------------------------------------- Laurent@1338: andrej@1749: Laurent@1338: _Point = namedtuple("Point", ["x", "y"]) Laurent@1338: andrej@1768: _BlockInstanceInfos = namedtuple( andrej@1768: "BlockInstanceInfos", Laurent@1338: ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"]) Laurent@1338: Laurent@1338: _BlockSpecificValues = ( Edouard@1411: namedtuple("BlockSpecificValues", Laurent@1338: ["name", "execution_order"]), Laurent@1378: [_StringValue, int]) Laurent@1338: _VariableSpecificValues = ( Edouard@1411: namedtuple("VariableSpecificValues", Laurent@1338: ["name", "value_type", "execution_order"]), Laurent@1378: [_StringValue, _StringValue, int]) Laurent@1338: _ConnectionSpecificValues = ( Laurent@1338: namedtuple("ConnectionSpecificValues", ["name"]), Laurent@1378: [_StringValue]) Laurent@1338: Laurent@1338: _PowerRailSpecificValues = ( Laurent@1338: namedtuple("PowerRailSpecificValues", ["connectors"]), Laurent@1338: [int]) Laurent@1338: Laurent@1338: _LDElementSpecificValues = ( Edouard@1411: namedtuple("LDElementSpecificValues", Laurent@1338: ["name", "negated", "edge", "storage", "execution_order"]), Laurent@1378: [_StringValue, _BoolValue, _StringValue, _StringValue, int]) Laurent@1338: Laurent@1338: _DivergenceSpecificValues = ( Laurent@1338: namedtuple("DivergenceSpecificValues", ["connectors"]), Laurent@1338: [int]) Laurent@1338: Laurent@1338: _SpecificValuesTuples = { Laurent@1338: "comment": ( Laurent@1338: namedtuple("CommentSpecificValues", ["content"]), Laurent@1378: [_StringValue]), Laurent@1338: "input": _VariableSpecificValues, Laurent@1338: "output": _VariableSpecificValues, Laurent@1338: "inout": _VariableSpecificValues, Laurent@1338: "connector": _ConnectionSpecificValues, Laurent@1338: "continuation": _ConnectionSpecificValues, Laurent@1338: "leftPowerRail": _PowerRailSpecificValues, Laurent@1338: "rightPowerRail": _PowerRailSpecificValues, Laurent@1338: "contact": _LDElementSpecificValues, Laurent@1338: "coil": _LDElementSpecificValues, Laurent@1338: "step": ( Laurent@1338: namedtuple("StepSpecificValues", ["name", "initial", "action"]), Laurent@1378: [_StringValue, _BoolValue, lambda x: x]), Laurent@1338: "transition": ( Edouard@1411: namedtuple("TransitionSpecificValues", Laurent@1338: ["priority", "condition_type", "condition", "connection"]), Laurent@1378: [int, _StringValue, _StringValue, lambda x: x]), Laurent@1338: "selectionDivergence": _DivergenceSpecificValues, Laurent@1338: "selectionConvergence": _DivergenceSpecificValues, Laurent@1338: "simultaneousDivergence": _DivergenceSpecificValues, Laurent@1338: "simultaneousConvergence": _DivergenceSpecificValues, Laurent@1338: "jump": ( Laurent@1338: namedtuple("JumpSpecificValues", ["target"]), Laurent@1378: [_StringValue]), Laurent@1338: "actionBlock": ( Laurent@1338: namedtuple("ActionBlockSpecificValues", ["actions"]), Laurent@1338: [lambda x: x]), Laurent@1338: } Laurent@1338: andrej@1768: _InstanceConnectionInfos = namedtuple( andrej@1768: "InstanceConnectionInfos", Laurent@1338: ["name", "negated", "edge", "position", "links"]) Laurent@1338: andrej@1768: _ConnectionLinkInfos = namedtuple( andrej@1768: "ConnectionLinkInfos", Laurent@1338: ["refLocalId", "formalParameter", "points"]) Laurent@1338: andrej@1736: Laurent@1341: class _ActionInfos(object): Laurent@1339: __slots__ = ["qualifier", "type", "value", "duration", "indicator"] andrej@1751: Laurent@1339: def __init__(self, *args): Laurent@1339: for attr, value in zip(self.__slots__, args): Laurent@1339: setattr(self, attr, value if value is not None else "") andrej@1751: Laurent@1339: def copy(self): Laurent@1339: return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__]) Laurent@1338: andrej@1736: andrej@1831: class BlockInstanceFactory(object): Edouard@1411: Laurent@1338: def __init__(self, block_instances): Laurent@1338: self.BlockInstances = block_instances Laurent@1338: self.CurrentInstance = None Laurent@1338: self.SpecificValues = None Laurent@1338: self.CurrentConnection = None Laurent@1338: self.CurrentLink = None Edouard@1411: Laurent@1338: def SetSpecificValues(self, context, *args): Laurent@1338: self.SpecificValues = list(args) Laurent@1338: self.CurrentInstance = None Laurent@1338: self.CurrentConnection = None Laurent@1338: self.CurrentLink = None Edouard@1411: Laurent@1338: def AddBlockInstance(self, context, *args): Laurent@1338: specific_values_tuple, specific_values_translation = \ Laurent@1338: _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues) Edouard@1411: andrej@1774: if args[0][0] == "step" and len(self.SpecificValues) < 3 or \ andrej@1766: args[0][0] == "transition" and len(self.SpecificValues) < 4: Laurent@1338: self.SpecificValues.append([None]) Laurent@1338: elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1: Laurent@1338: self.SpecificValues.append([[]]) Laurent@1338: specific_values = specific_values_tuple(*_translate_args( Laurent@1338: specific_values_translation, self.SpecificValues)) Laurent@1338: self.SpecificValues = None Edouard@1411: Laurent@1338: self.CurrentInstance = _BlockInstanceInfos( Edouard@1411: *(_translate_args([_StringValue, int] + [float] * 4, args) + Laurent@1338: [specific_values, [], []])) Edouard@1411: Laurent@1338: self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance Edouard@1411: Laurent@1338: def AddInstanceConnection(self, context, *args): Laurent@1338: connection_args = _translate_args( Laurent@1378: [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args) Edouard@1411: Laurent@1338: self.CurrentConnection = _InstanceConnectionInfos( Laurent@1338: *(connection_args[1:4] + [ Laurent@1338: _Point(*connection_args[4:6]), []])) Edouard@1411: Laurent@1338: if self.CurrentInstance is not None: Laurent@1338: if connection_args[0] == "input": Laurent@1338: self.CurrentInstance.inputs.append(self.CurrentConnection) Laurent@1338: else: Laurent@1338: self.CurrentInstance.outputs.append(self.CurrentConnection) Laurent@1338: else: Laurent@1338: self.SpecificValues.append([self.CurrentConnection]) Edouard@1411: Laurent@1338: def AddConnectionLink(self, context, *args): Laurent@1338: self.CurrentLink = _ConnectionLinkInfos( Laurent@1378: *(_translate_args([int, _StringValue], args) + [[]])) Laurent@1338: self.CurrentConnection.links.append(self.CurrentLink) Edouard@1411: Laurent@1338: def AddLinkPoint(self, context, *args): Laurent@1338: self.CurrentLink.points.append(_Point( Laurent@1373: *_translate_args([float] * 2, args))) Edouard@1411: Laurent@1338: def AddAction(self, context, *args): Laurent@1338: if len(self.SpecificValues) == 0: Laurent@1338: self.SpecificValues.append([[]]) Laurent@1378: translated_args = _translate_args([_StringValue] * 5, args) Laurent@1338: self.SpecificValues[0][0].append(_ActionInfos(*translated_args)) Edouard@1411: andrej@1749: Edouard@1957: class BlockInstanceCollector(XSLTModelQuery): Edouard@1957: """ object for collecting instances path list""" Edouard@1957: def __init__(self, controller): Edouard@1957: XSLTModelQuery.__init__(self, Edouard@1957: controller, Edouard@1957: "pou_block_instances.xslt", Edouard@1957: [(name, self.FactoryCaller(name)) Edouard@1957: for name in ["AddBlockInstance", Edouard@1957: "SetSpecificValues", Edouard@1957: "AddInstanceConnection", Edouard@1957: "AddConnectionLink", Edouard@1957: "AddLinkPoint", Edouard@1957: "AddAction"]]) Laurent@1338: Edouard@1957: def FactoryCaller(self, funcname): Edouard@1957: def CallFactory(*args): Edouard@1957: return getattr(self.factory, funcname)(*args) Edouard@1957: return CallFactory Laurent@814: Edouard@1957: def Collect(self, root, debug): Laurent@1338: element_instances = OrderedDict() Edouard@1957: self.factory = BlockInstanceFactory(element_instances) Edouard@1957: self._process_xslt(root, debug) Edouard@1957: self.factory = None Laurent@1338: return element_instances