author | Edouard Tisserant |
Fri, 23 May 2014 18:28:57 +0200 | |
changeset 1408 | eb2aa27602b7 |
parent 1358 | fe7770a30527 |
child 1418 | c97dc5281419 |
permissions | -rw-r--r-- |
814 | 1 |
#!/usr/bin/env python |
2 |
# -*- coding: utf-8 -*- |
|
3 |
||
4 |
#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
|
5 |
#based on the plcopen standard. |
|
6 |
# |
|
7 |
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
|
8 |
# |
|
9 |
#See COPYING file for copyrights details. |
|
10 |
# |
|
11 |
#This library is free software; you can redistribute it and/or |
|
12 |
#modify it under the terms of the GNU General Public |
|
13 |
#License as published by the Free Software Foundation; either |
|
14 |
#version 2.1 of the License, or (at your option) any later version. |
|
15 |
# |
|
16 |
#This library is distributed in the hope that it will be useful, |
|
17 |
#but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 |
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 |
#General Public License for more details. |
|
20 |
# |
|
21 |
#You should have received a copy of the GNU General Public |
|
22 |
#License along with this library; if not, write to the Free Software |
|
23 |
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
24 |
||
1297 | 25 |
from plcopen import PLCOpenParser |
814 | 26 |
from plcopen.structures import * |
27 |
from types import * |
|
28 |
import re |
|
29 |
||
30 |
# Dictionary associating PLCOpen variable categories to the corresponding |
|
31 |
# IEC 61131-3 variable categories |
|
32 |
varTypeNames = {"localVars" : "VAR", "tempVars" : "VAR_TEMP", "inputVars" : "VAR_INPUT", |
|
33 |
"outputVars" : "VAR_OUTPUT", "inOutVars" : "VAR_IN_OUT", "externalVars" : "VAR_EXTERNAL", |
|
34 |
"globalVars" : "VAR_GLOBAL", "accessVars" : "VAR_ACCESS"} |
|
35 |
||
36 |
||
37 |
# Dictionary associating PLCOpen POU categories to the corresponding |
|
38 |
# IEC 61131-3 POU categories |
|
39 |
pouTypeNames = {"function" : "FUNCTION", "functionBlock" : "FUNCTION_BLOCK", "program" : "PROGRAM"} |
|
40 |
||
41 |
||
42 |
errorVarTypes = { |
|
43 |
"VAR_INPUT": "var_input", |
|
44 |
"VAR_OUTPUT": "var_output", |
|
45 |
"VAR_INOUT": "var_inout", |
|
46 |
} |
|
47 |
||
48 |
# Helper function for reindenting text |
|
49 |
def ReIndentText(text, nb_spaces): |
|
50 |
compute = "" |
|
51 |
lines = text.splitlines() |
|
52 |
if len(lines) > 0: |
|
53 |
line_num = 0 |
|
54 |
while line_num < len(lines) and len(lines[line_num].strip()) == 0: |
|
55 |
line_num += 1 |
|
56 |
if line_num < len(lines): |
|
57 |
spaces = 0 |
|
58 |
while lines[line_num][spaces] == " ": |
|
59 |
spaces += 1 |
|
60 |
indent = "" |
|
61 |
for i in xrange(spaces, nb_spaces): |
|
62 |
indent += " " |
|
63 |
for line in lines: |
|
64 |
if line != "": |
|
65 |
compute += "%s%s\n"%(indent, line) |
|
66 |
else: |
|
67 |
compute += "\n" |
|
68 |
return compute |
|
69 |
||
70 |
def SortInstances(a, b): |
|
71 |
ax, ay = int(a.getx()), int(a.gety()) |
|
72 |
bx, by = int(b.getx()), int(b.gety()) |
|
73 |
if abs(ay - by) < 10: |
|
74 |
return cmp(ax, bx) |
|
75 |
else: |
|
76 |
return cmp(ay, by) |
|
77 |
||
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
78 |
# Helper for emulate join on element list |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
79 |
def JoinList(separator, mylist): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
80 |
if len(mylist) > 0 : |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
81 |
return reduce(lambda x, y: x + separator + y, mylist) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
82 |
else : |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
83 |
return mylist |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
84 |
|
814 | 85 |
#------------------------------------------------------------------------------- |
86 |
# Specific exception for PLC generating errors |
|
87 |
#------------------------------------------------------------------------------- |
|
88 |
||
89 |
||
90 |
class PLCGenException(Exception): |
|
91 |
pass |
|
92 |
||
93 |
||
94 |
#------------------------------------------------------------------------------- |
|
95 |
# Generator of PLC program |
|
96 |
#------------------------------------------------------------------------------- |
|
97 |
||
98 |
||
99 |
class ProgramGenerator: |
|
100 |
||
101 |
# Create a new PCL program generator |
|
102 |
def __init__(self, controler, project, errors, warnings): |
|
103 |
# Keep reference of the controler and project |
|
104 |
self.Controler = controler |
|
105 |
self.Project = project |
|
106 |
# Reset the internal variables used to generate PLC programs |
|
107 |
self.Program = [] |
|
108 |
self.DatatypeComputed = {} |
|
109 |
self.PouComputed = {} |
|
110 |
self.Errors = errors |
|
111 |
self.Warnings = warnings |
|
112 |
||
113 |
# Compute value according to type given |
|
114 |
def ComputeValue(self, value, var_type): |
|
115 |
base_type = self.Controler.GetBaseType(var_type) |
|
1032
c4989e53f9c3
Fix bug defining string initial value using quotes
Laurent Bessard
parents:
893
diff
changeset
|
116 |
if base_type == "STRING" and not value.startswith("'") and not value.endswith("'"): |
814 | 117 |
return "'%s'"%value |
1032
c4989e53f9c3
Fix bug defining string initial value using quotes
Laurent Bessard
parents:
893
diff
changeset
|
118 |
elif base_type == "WSTRING" and not value.startswith('"') and not value.endswith('"'): |
814 | 119 |
return "\"%s\""%value |
120 |
return value |
|
121 |
||
122 |
# Generate a data type from its name |
|
123 |
def GenerateDataType(self, datatype_name): |
|
124 |
# Verify that data type hasn't been generated yet |
|
125 |
if not self.DatatypeComputed.get(datatype_name, True): |
|
126 |
# If not mark data type as computed |
|
127 |
self.DatatypeComputed[datatype_name] = True |
|
128 |
||
129 |
# Getting datatype model from project |
|
130 |
datatype = self.Project.getdataType(datatype_name) |
|
131 |
tagname = self.Controler.ComputeDataTypeName(datatype.getname()) |
|
132 |
datatype_def = [(" ", ()), |
|
133 |
(datatype.getname(), (tagname, "name")), |
|
134 |
(" : ", ())] |
|
135 |
basetype_content = datatype.baseType.getcontent() |
|
1297 | 136 |
basetype_content_type = basetype_content.getLocalTag() |
814 | 137 |
# Data type derived directly from a user defined type |
1297 | 138 |
if basetype_content_type == "derived": |
139 |
basetype_name = basetype_content.getname() |
|
814 | 140 |
self.GenerateDataType(basetype_name) |
141 |
datatype_def += [(basetype_name, (tagname, "base"))] |
|
142 |
# Data type is a subrange |
|
1297 | 143 |
elif basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]: |
144 |
base_type = basetype_content.baseType.getcontent() |
|
145 |
base_type_type = base_type.getLocalTag() |
|
814 | 146 |
# Subrange derived directly from a user defined type |
1297 | 147 |
if base_type_type == "derived": |
148 |
basetype_name = base_type_type.getname() |
|
814 | 149 |
self.GenerateDataType(basetype_name) |
150 |
# Subrange derived directly from an elementary type |
|
151 |
else: |
|
1297 | 152 |
basetype_name = base_type_type |
153 |
min_value = basetype_content.range.getlower() |
|
154 |
max_value = basetype_content.range.getupper() |
|
814 | 155 |
datatype_def += [(basetype_name, (tagname, "base")), |
156 |
(" (", ()), |
|
157 |
("%s"%min_value, (tagname, "lower")), |
|
158 |
("..", ()), |
|
159 |
("%s"%max_value, (tagname, "upper")), |
|
160 |
(")",())] |
|
161 |
# Data type is an enumerated type |
|
1297 | 162 |
elif basetype_content_type == "enum": |
814 | 163 |
values = [[(value.getname(), (tagname, "value", i))] |
1297 | 164 |
for i, value in enumerate( |
165 |
basetype_content.xpath("ppx:values/ppx:value", |
|
166 |
namespaces=PLCOpenParser.NSMAP))] |
|
814 | 167 |
datatype_def += [("(", ())] |
168 |
datatype_def += JoinList([(", ", ())], values) |
|
169 |
datatype_def += [(")", ())] |
|
170 |
# Data type is an array |
|
1297 | 171 |
elif basetype_content_type == "array": |
172 |
base_type = basetype_content.baseType.getcontent() |
|
173 |
base_type_type = base_type.getLocalTag() |
|
814 | 174 |
# Array derived directly from a user defined type |
1297 | 175 |
if base_type_type == "derived": |
176 |
basetype_name = base_type.getname() |
|
814 | 177 |
self.GenerateDataType(basetype_name) |
178 |
# Array derived directly from an elementary type |
|
179 |
else: |
|
1297 | 180 |
basetype_name = base_type_type.upper() |
814 | 181 |
dimensions = [[("%s"%dimension.getlower(), (tagname, "range", i, "lower")), |
182 |
("..", ()), |
|
183 |
("%s"%dimension.getupper(), (tagname, "range", i, "upper"))] |
|
1297 | 184 |
for i, dimension in enumerate(basetype_content.getdimension())] |
814 | 185 |
datatype_def += [("ARRAY [", ())] |
186 |
datatype_def += JoinList([(",", ())], dimensions) |
|
187 |
datatype_def += [("] OF " , ()), |
|
188 |
(basetype_name, (tagname, "base"))] |
|
189 |
# Data type is a structure |
|
1297 | 190 |
elif basetype_content_type == "struct": |
814 | 191 |
elements = [] |
1297 | 192 |
for i, element in enumerate(basetype_content.getvariable()): |
814 | 193 |
element_type = element.type.getcontent() |
1297 | 194 |
element_type_type = element_type.getLocalTag() |
814 | 195 |
# Structure element derived directly from a user defined type |
1297 | 196 |
if element_type_type == "derived": |
197 |
elementtype_name = element_type.getname() |
|
814 | 198 |
self.GenerateDataType(elementtype_name) |
1297 | 199 |
elif element_type_type == "array": |
200 |
base_type = element_type.baseType.getcontent() |
|
201 |
base_type_type = base_type.getLocalTag() |
|
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
854
diff
changeset
|
202 |
# Array derived directly from a user defined type |
1297 | 203 |
if base_type_type == "derived": |
204 |
basetype_name = base_type.getname() |
|
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
854
diff
changeset
|
205 |
self.GenerateDataType(basetype_name) |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
854
diff
changeset
|
206 |
# Array derived directly from an elementary type |
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
854
diff
changeset
|
207 |
else: |
1297 | 208 |
basetype_name = base_type_type.upper() |
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
854
diff
changeset
|
209 |
dimensions = ["%s..%s" % (dimension.getlower(), dimension.getupper()) |
1297 | 210 |
for dimension in element_type.getdimension()] |
864
bf4f7f0801b9
Adding support for direct array declaration in structure element declaration
Laurent Bessard
parents:
854
diff
changeset
|
211 |
elementtype_name = "ARRAY [%s] OF %s" % (",".join(dimensions), basetype_name) |
814 | 212 |
# Structure element derived directly from an elementary type |
213 |
else: |
|
1297 | 214 |
elementtype_name = element_type_type.upper() |
814 | 215 |
element_text = [("\n ", ()), |
216 |
(element.getname(), (tagname, "struct", i, "name")), |
|
217 |
(" : ", ()), |
|
218 |
(elementtype_name, (tagname, "struct", i, "type"))] |
|
219 |
if element.initialValue is not None: |
|
220 |
element_text.extend([(" := ", ()), |
|
221 |
(self.ComputeValue(element.initialValue.getvalue(), elementtype_name), (tagname, "struct", i, "initial value"))]) |
|
222 |
element_text.append((";", ())) |
|
223 |
elements.append(element_text) |
|
224 |
datatype_def += [("STRUCT", ())] |
|
225 |
datatype_def += JoinList([("", ())], elements) |
|
226 |
datatype_def += [("\n END_STRUCT", ())] |
|
227 |
# Data type derived directly from a elementary type |
|
228 |
else: |
|
1297 | 229 |
datatype_def += [(basetype_content_type.upper(), (tagname, "base"))] |
814 | 230 |
# Data type has an initial value |
231 |
if datatype.initialValue is not None: |
|
232 |
datatype_def += [(" := ", ()), |
|
233 |
(self.ComputeValue(datatype.initialValue.getvalue(), datatype_name), (tagname, "initial value"))] |
|
234 |
datatype_def += [(";\n", ())] |
|
235 |
self.Program += datatype_def |
|
236 |
||
237 |
# Generate a POU from its name |
|
238 |
def GeneratePouProgram(self, pou_name): |
|
239 |
# Verify that POU hasn't been generated yet |
|
240 |
if not self.PouComputed.get(pou_name, True): |
|
241 |
# If not mark POU as computed |
|
242 |
self.PouComputed[pou_name] = True |
|
243 |
||
244 |
# Getting POU model from project |
|
245 |
pou = self.Project.getpou(pou_name) |
|
246 |
pou_type = pou.getpouType() |
|
247 |
# Verify that POU type exists |
|
248 |
if pouTypeNames.has_key(pou_type): |
|
249 |
# Create a POU program generator |
|
250 |
pou_program = PouProgramGenerator(self, pou.getname(), pouTypeNames[pou_type], self.Errors, self.Warnings) |
|
251 |
program = pou_program.GenerateProgram(pou) |
|
252 |
self.Program += program |
|
253 |
else: |
|
254 |
raise PLCGenException, _("Undefined pou type \"%s\"")%pou_type |
|
255 |
||
256 |
# Generate a POU defined and used in text |
|
257 |
def GeneratePouProgramInText(self, text): |
|
258 |
for pou_name in self.PouComputed.keys(): |
|
259 |
model = re.compile("(?:^|[^0-9^A-Z])%s(?:$|[^0-9^A-Z])"%pou_name.upper()) |
|
260 |
if model.search(text) is not None: |
|
261 |
self.GeneratePouProgram(pou_name) |
|
262 |
||
263 |
# Generate a configuration from its model |
|
264 |
def GenerateConfiguration(self, configuration): |
|
265 |
tagname = self.Controler.ComputeConfigurationName(configuration.getname()) |
|
266 |
config = [("\nCONFIGURATION ", ()), |
|
267 |
(configuration.getname(), (tagname, "name")), |
|
268 |
("\n", ())] |
|
269 |
var_number = 0 |
|
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
270 |
|
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
271 |
varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()] |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
272 |
|
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
273 |
extra_variables = self.Controler.GetConfigurationExtraVariables() |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
274 |
extra_global_vars = None |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
275 |
if len(extra_variables) > 0 and len(varlists) == 0: |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
276 |
extra_global_vars = PLCOpenParser.CreateElement("globalVars", "interface") |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
277 |
configuration.setglobalVars([extra_global_vars]) |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
278 |
varlists = [(extra_global_vars, [])] |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
279 |
|
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
280 |
for variable in extra_variables: |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
281 |
varlists[-1][0].appendvariable(variable) |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
282 |
varlists[-1][1].append(variable) |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
283 |
|
814 | 284 |
# Generate any global variable in configuration |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
285 |
for varlist, varlist_variables in varlists: |
814 | 286 |
variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local") |
287 |
# Generate variable block with modifier |
|
288 |
config += [(" VAR_GLOBAL", ())] |
|
289 |
if varlist.getconstant(): |
|
290 |
config += [(" CONSTANT", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "constant"))] |
|
291 |
elif varlist.getretain(): |
|
292 |
config += [(" RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "retain"))] |
|
293 |
elif varlist.getnonretain(): |
|
294 |
config += [(" NON_RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "non_retain"))] |
|
295 |
config += [("\n", ())] |
|
296 |
# Generate any variable of this block |
|
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
297 |
for var in varlist_variables: |
814 | 298 |
vartype_content = var.gettype().getcontent() |
1297 | 299 |
if vartype_content.getLocalTag() == "derived": |
300 |
var_type = vartype_content.getname() |
|
814 | 301 |
self.GenerateDataType(var_type) |
302 |
else: |
|
303 |
var_type = var.gettypeAsText() |
|
304 |
||
305 |
config += [(" ", ()), |
|
306 |
(var.getname(), (tagname, variable_type, var_number, "name")), |
|
307 |
(" ", ())] |
|
308 |
# Generate variable address if exists |
|
309 |
address = var.getaddress() |
|
310 |
if address: |
|
311 |
config += [("AT ", ()), |
|
312 |
(address, (tagname, variable_type, var_number, "location")), |
|
313 |
(" ", ())] |
|
314 |
config += [(": ", ()), |
|
315 |
(var.gettypeAsText(), (tagname, variable_type, var_number, "type"))] |
|
316 |
# Generate variable initial value if exists |
|
317 |
initial = var.getinitialValue() |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
318 |
if initial is not None: |
814 | 319 |
config += [(" := ", ()), |
320 |
(self.ComputeValue(initial.getvalue(), var_type), (tagname, variable_type, var_number, "initial value"))] |
|
321 |
config += [(";\n", ())] |
|
322 |
var_number += 1 |
|
323 |
config += [(" END_VAR\n", ())] |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
324 |
|
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
325 |
if extra_global_vars is not None: |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
326 |
configuration.remove(extra_global_vars) |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
327 |
else: |
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
328 |
for variable in extra_variables: |
1358
fe7770a30527
Fixed bug when building project with configuration extra variables
Laurent Bessard
parents:
1322
diff
changeset
|
329 |
varlists[-1][0].remove(variable) |
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
330 |
|
814 | 331 |
# Generate any resource in the configuration |
332 |
for resource in configuration.getresource(): |
|
333 |
config += self.GenerateResource(resource, configuration.getname()) |
|
334 |
config += [("END_CONFIGURATION\n", ())] |
|
335 |
return config |
|
336 |
||
337 |
# Generate a resource from its model |
|
338 |
def GenerateResource(self, resource, config_name): |
|
339 |
tagname = self.Controler.ComputeConfigurationResourceName(config_name, resource.getname()) |
|
340 |
resrce = [("\n RESOURCE ", ()), |
|
341 |
(resource.getname(), (tagname, "name")), |
|
342 |
(" ON PLC\n", ())] |
|
343 |
var_number = 0 |
|
344 |
# Generate any global variable in configuration |
|
345 |
for varlist in resource.getglobalVars(): |
|
346 |
variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local") |
|
347 |
# Generate variable block with modifier |
|
348 |
resrce += [(" VAR_GLOBAL", ())] |
|
349 |
if varlist.getconstant(): |
|
350 |
resrce += [(" CONSTANT", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "constant"))] |
|
351 |
elif varlist.getretain(): |
|
352 |
resrce += [(" RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "retain"))] |
|
353 |
elif varlist.getnonretain(): |
|
354 |
resrce += [(" NON_RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "non_retain"))] |
|
355 |
resrce += [("\n", ())] |
|
356 |
# Generate any variable of this block |
|
357 |
for var in varlist.getvariable(): |
|
358 |
vartype_content = var.gettype().getcontent() |
|
1297 | 359 |
if vartype_content.getLocalTag() == "derived": |
360 |
var_type = vartype_content.getname() |
|
814 | 361 |
self.GenerateDataType(var_type) |
362 |
else: |
|
363 |
var_type = var.gettypeAsText() |
|
364 |
||
365 |
resrce += [(" ", ()), |
|
366 |
(var.getname(), (tagname, variable_type, var_number, "name")), |
|
367 |
(" ", ())] |
|
368 |
address = var.getaddress() |
|
369 |
# Generate variable address if exists |
|
370 |
if address: |
|
371 |
resrce += [("AT ", ()), |
|
372 |
(address, (tagname, variable_type, var_number, "location")), |
|
373 |
(" ", ())] |
|
374 |
resrce += [(": ", ()), |
|
375 |
(var.gettypeAsText(), (tagname, variable_type, var_number, "type"))] |
|
376 |
# Generate variable initial value if exists |
|
377 |
initial = var.getinitialValue() |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
378 |
if initial is not None: |
814 | 379 |
resrce += [(" := ", ()), |
380 |
(self.ComputeValue(initial.getvalue(), var_type), (tagname, variable_type, var_number, "initial value"))] |
|
381 |
resrce += [(";\n", ())] |
|
382 |
var_number += 1 |
|
383 |
resrce += [(" END_VAR\n", ())] |
|
384 |
# Generate any task in the resource |
|
385 |
tasks = resource.gettask() |
|
386 |
task_number = 0 |
|
387 |
for task in tasks: |
|
388 |
# Task declaration |
|
389 |
resrce += [(" TASK ", ()), |
|
390 |
(task.getname(), (tagname, "task", task_number, "name")), |
|
391 |
("(", ())] |
|
392 |
args = [] |
|
393 |
single = task.getsingle() |
|
394 |
# Single argument if exists |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
395 |
if single is not None: |
814 | 396 |
resrce += [("SINGLE := ", ()), |
397 |
(single, (tagname, "task", task_number, "single")), |
|
398 |
(",", ())] |
|
399 |
# Interval argument if exists |
|
400 |
interval = task.getinterval() |
|
1315
ff14a66bbd12
Fixed Beremiz for working with new xmlclass support using lxml
Laurent Bessard
parents:
1310
diff
changeset
|
401 |
if interval is not None: |
814 | 402 |
resrce += [("INTERVAL := ", ()), |
403 |
(interval, (tagname, "task", task_number, "interval")), |
|
404 |
(",", ())] |
|
405 |
## resrce += [("INTERVAL := t#", ())] |
|
406 |
## if interval.hour != 0: |
|
407 |
## resrce += [("%dh"%interval.hour, (tagname, "task", task_number, "interval", "hour"))] |
|
408 |
## if interval.minute != 0: |
|
409 |
## resrce += [("%dm"%interval.minute, (tagname, "task", task_number, "interval", "minute"))] |
|
410 |
## if interval.second != 0: |
|
411 |
## resrce += [("%ds"%interval.second, (tagname, "task", task_number, "interval", "second"))] |
|
412 |
## if interval.microsecond != 0: |
|
413 |
## resrce += [("%dms"%(interval.microsecond / 1000), (tagname, "task", task_number, "interval", "millisecond"))] |
|
414 |
## resrce += [(",", ())] |
|
415 |
# Priority argument |
|
416 |
resrce += [("PRIORITY := ", ()), |
|
417 |
("%d"%task.getpriority(), (tagname, "task", task_number, "priority")), |
|
418 |
(");\n", ())] |
|
419 |
task_number += 1 |
|
420 |
instance_number = 0 |
|
421 |
# Generate any program assign to each task |
|
422 |
for task in tasks: |
|
423 |
for instance in task.getpouInstance(): |
|
424 |
resrce += [(" PROGRAM ", ()), |
|
425 |
(instance.getname(), (tagname, "instance", instance_number, "name")), |
|
426 |
(" WITH ", ()), |
|
427 |
(task.getname(), (tagname, "instance", instance_number, "task")), |
|
428 |
(" : ", ()), |
|
429 |
(instance.gettypeName(), (tagname, "instance", instance_number, "type")), |
|
430 |
(";\n", ())] |
|
431 |
instance_number += 1 |
|
432 |
# Generate any program assign to no task |
|
433 |
for instance in resource.getpouInstance(): |
|
434 |
resrce += [(" PROGRAM ", ()), |
|
435 |
(instance.getname(), (tagname, "instance", instance_number, "name")), |
|
436 |
(" : ", ()), |
|
437 |
(instance.gettypeName(), (tagname, "instance", instance_number, "type")), |
|
438 |
(";\n", ())] |
|
439 |
instance_number += 1 |
|
440 |
resrce += [(" END_RESOURCE\n", ())] |
|
441 |
return resrce |
|
442 |
||
443 |
# Generate the entire program for current project |
|
444 |
def GenerateProgram(self): |
|
445 |
# Find all data types defined |
|
446 |
for datatype in self.Project.getdataTypes(): |
|
447 |
self.DatatypeComputed[datatype.getname()] = False |
|
448 |
# Find all data types defined |
|
449 |
for pou in self.Project.getpous(): |
|
450 |
self.PouComputed[pou.getname()] = False |
|
451 |
# Generate data type declaration structure if there is at least one data |
|
452 |
# type defined |
|
453 |
if len(self.DatatypeComputed) > 0: |
|
454 |
self.Program += [("TYPE\n", ())] |
|
455 |
# Generate every data types defined |
|
456 |
for datatype_name in self.DatatypeComputed.keys(): |
|
457 |
self.GenerateDataType(datatype_name) |
|
458 |
self.Program += [("END_TYPE\n\n", ())] |
|
459 |
# Generate every POUs defined |
|
460 |
for pou_name in self.PouComputed.keys(): |
|
461 |
self.GeneratePouProgram(pou_name) |
|
462 |
# Generate every configurations defined |
|
463 |
for config in self.Project.getconfigurations(): |
|
464 |
self.Program += self.GenerateConfiguration(config) |
|
465 |
||
466 |
# Return generated program |
|
467 |
def GetGeneratedProgram(self): |
|
468 |
return self.Program |
|
469 |
||
470 |
||
471 |
#------------------------------------------------------------------------------- |
|
472 |
# Generator of POU programs |
|
473 |
#------------------------------------------------------------------------------- |
|
474 |
||
1297 | 475 |
[ConnectorClass, ContinuationClass, ActionBlockClass] = [ |
476 |
PLCOpenParser.GetElementClass(instance_name, "commonObjects") |
|
477 |
for instance_name in ["connector", "continuation", "actionBlock"]] |
|
478 |
[InVariableClass, InOutVariableClass, OutVariableClass, BlockClass] = [ |
|
479 |
PLCOpenParser.GetElementClass(instance_name, "fbdObjects") |
|
480 |
for instance_name in ["inVariable", "inOutVariable", "outVariable", "block"]] |
|
481 |
[ContactClass, CoilClass, LeftPowerRailClass, RightPowerRailClass] = [ |
|
482 |
PLCOpenParser.GetElementClass(instance_name, "ldObjects") |
|
483 |
for instance_name in ["contact", "coil", "leftPowerRail", "rightPowerRail"]] |
|
484 |
[StepClass, TransitionClass, JumpStepClass, |
|
485 |
SelectionConvergenceClass, SelectionDivergenceClass, |
|
486 |
SimultaneousConvergenceClass, SimultaneousDivergenceClass] = [ |
|
487 |
PLCOpenParser.GetElementClass(instance_name, "sfcObjects") |
|
488 |
for instance_name in ["step", "transition", "jumpStep", |
|
489 |
"selectionConvergence", "selectionDivergence", |
|
490 |
"simultaneousConvergence", "simultaneousDivergence"]] |
|
491 |
TransitionObjClass = PLCOpenParser.GetElementClass("transition", "transitions") |
|
492 |
ActionObjClass = PLCOpenParser.GetElementClass("action", "actions") |
|
814 | 493 |
|
494 |
class PouProgramGenerator: |
|
495 |
||
496 |
# Create a new POU program generator |
|
497 |
def __init__(self, parent, name, type, errors, warnings): |
|
498 |
# Keep Reference to the parent generator |
|
499 |
self.ParentGenerator = parent |
|
500 |
self.Name = name |
|
501 |
self.Type = type |
|
502 |
self.TagName = self.ParentGenerator.Controler.ComputePouName(name) |
|
503 |
self.CurrentIndent = " " |
|
504 |
self.ReturnType = None |
|
505 |
self.Interface = [] |
|
506 |
self.InitialSteps = [] |
|
507 |
self.ComputedBlocks = {} |
|
508 |
self.ComputedConnectors = {} |
|
509 |
self.ConnectionTypes = {} |
|
510 |
self.RelatedConnections = [] |
|
511 |
self.SFCNetworks = {"Steps":{}, "Transitions":{}, "Actions":{}} |
|
512 |
self.SFCComputedBlocks = [] |
|
513 |
self.ActionNumber = 0 |
|
514 |
self.Program = [] |
|
515 |
self.Errors = errors |
|
516 |
self.Warnings = warnings |
|
517 |
||
518 |
def GetBlockType(self, type, inputs=None): |
|
519 |
return self.ParentGenerator.Controler.GetBlockType(type, inputs) |
|
520 |
||
521 |
def IndentLeft(self): |
|
522 |
if len(self.CurrentIndent) >= 2: |
|
523 |
self.CurrentIndent = self.CurrentIndent[:-2] |
|
524 |
||
525 |
def IndentRight(self): |
|
526 |
self.CurrentIndent += " " |
|
527 |
||
528 |
# Generator of unique ID for inline actions |
|
529 |
def GetActionNumber(self): |
|
530 |
self.ActionNumber += 1 |
|
531 |
return self.ActionNumber |
|
532 |
||
533 |
# Test if a variable has already been defined |
|
534 |
def IsAlreadyDefined(self, name): |
|
535 |
for list_type, option, located, vars in self.Interface: |
|
536 |
for var_type, var_name, var_address, var_initial in vars: |
|
537 |
if name == var_name: |
|
538 |
return True |
|
539 |
return False |
|
540 |
||
541 |
# Return the type of a variable defined in interface |
|
542 |
def GetVariableType(self, name): |
|
543 |
parts = name.split('.') |
|
544 |
current_type = None |
|
545 |
if len(parts) > 0: |
|
546 |
name = parts.pop(0) |
|
547 |
for list_type, option, located, vars in self.Interface: |
|
548 |
for var_type, var_name, var_address, var_initial in vars: |
|
549 |
if name == var_name: |
|
550 |
current_type = var_type |
|
551 |
break |
|
552 |
while current_type is not None and len(parts) > 0: |
|
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
553 |
blocktype = self.ParentGenerator.Controler.GetBlockType(current_type) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
554 |
if blocktype is not None: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
555 |
name = parts.pop(0) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
556 |
current_type = None |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
557 |
for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
558 |
if var_name == name: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
559 |
current_type = var_type |
814 | 560 |
break |
883
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
561 |
else: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
562 |
tagname = self.ParentGenerator.Controler.ComputeDataTypeName(current_type) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
563 |
infos = self.ParentGenerator.Controler.GetDataTypeInfos(tagname) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
564 |
if infos is not None and infos["type"] == "Structure": |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
565 |
name = parts.pop(0) |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
566 |
current_type = None |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
567 |
for element in infos["elements"]: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
568 |
if element["Name"] == name: |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
569 |
current_type = element["Type"] |
235a9ec83b95
Adding support for defining specific global variables for ConfTreeNodes
Laurent Bessard
parents:
864
diff
changeset
|
570 |
break |
814 | 571 |
return current_type |
572 |
||
573 |
# Return connectors linked by a connection to the given connector |
|
574 |
def GetConnectedConnector(self, connector, body): |
|
575 |
links = connector.getconnections() |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
576 |
if links is not None and len(links) == 1: |
814 | 577 |
return self.GetLinkedConnector(links[0], body) |
578 |
return None |
|
579 |
||
580 |
def GetLinkedConnector(self, link, body): |
|
581 |
parameter = link.getformalParameter() |
|
582 |
instance = body.getcontentInstance(link.getrefLocalId()) |
|
1297 | 583 |
if isinstance(instance, (InVariableClass, InOutVariableClass, |
584 |
ContinuationClass, ContactClass, CoilClass)): |
|
814 | 585 |
return instance.connectionPointOut |
1297 | 586 |
elif isinstance(instance, BlockClass): |
814 | 587 |
outputvariables = instance.outputVariables.getvariable() |
588 |
if len(outputvariables) == 1: |
|
589 |
return outputvariables[0].connectionPointOut |
|
590 |
elif parameter: |
|
591 |
for variable in outputvariables: |
|
592 |
if variable.getformalParameter() == parameter: |
|
593 |
return variable.connectionPointOut |
|
594 |
else: |
|
595 |
point = link.getposition()[-1] |
|
596 |
for variable in outputvariables: |
|
597 |
relposition = variable.connectionPointOut.getrelPositionXY() |
|
598 |
blockposition = instance.getposition() |
|
599 |
if point.x == blockposition.x + relposition[0] and point.y == blockposition.y + relposition[1]: |
|
600 |
return variable.connectionPointOut |
|
1297 | 601 |
elif isinstance(instance, LeftPowerRailClass): |
814 | 602 |
outputconnections = instance.getconnectionPointOut() |
603 |
if len(outputconnections) == 1: |
|
604 |
return outputconnections[0] |
|
605 |
else: |
|
606 |
point = link.getposition()[-1] |
|
607 |
for outputconnection in outputconnections: |
|
608 |
relposition = outputconnection.getrelPositionXY() |
|
609 |
powerrailposition = instance.getposition() |
|
610 |
if point.x == powerrailposition.x + relposition[0] and point.y == powerrailposition.y + relposition[1]: |
|
611 |
return outputconnection |
|
612 |
return None |
|
613 |
||
614 |
def ExtractRelatedConnections(self, connection): |
|
615 |
for i, related in enumerate(self.RelatedConnections): |
|
616 |
if connection in related: |
|
617 |
return self.RelatedConnections.pop(i) |
|
618 |
return [connection] |
|
619 |
||
620 |
def ComputeInterface(self, pou): |
|
621 |
interface = pou.getinterface() |
|
622 |
if interface is not None: |
|
623 |
body = pou.getbody() |
|
624 |
if isinstance(body, ListType): |
|
625 |
body = body[0] |
|
626 |
body_content = body.getcontent() |
|
1297 | 627 |
body_type = body_content.getLocalTag() |
814 | 628 |
if self.Type == "FUNCTION": |
629 |
returntype_content = interface.getreturnType().getcontent() |
|
1297 | 630 |
returntype_content_type = returntype_content.getLocalTag() |
631 |
if returntype_content_type == "derived": |
|
632 |
self.ReturnType = returntype_content.getname() |
|
633 |
else: |
|
634 |
self.ReturnType = returntype_content_type.upper() |
|
814 | 635 |
for varlist in interface.getcontent(): |
636 |
variables = [] |
|
637 |
located = [] |
|
1297 | 638 |
varlist_type = varlist.getLocalTag() |
639 |
for var in varlist.getvariable(): |
|
814 | 640 |
vartype_content = var.gettype().getcontent() |
1297 | 641 |
if vartype_content.getLocalTag() == "derived": |
642 |
var_type = vartype_content.getname() |
|
814 | 643 |
blocktype = self.GetBlockType(var_type) |
644 |
if blocktype is not None: |
|
645 |
self.ParentGenerator.GeneratePouProgram(var_type) |
|
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
646 |
variables.append((var_type, var.getname(), None, None)) |
814 | 647 |
else: |
648 |
self.ParentGenerator.GenerateDataType(var_type) |
|
649 |
initial = var.getinitialValue() |
|
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
650 |
if initial is not None: |
814 | 651 |
initial_value = initial.getvalue() |
652 |
else: |
|
653 |
initial_value = None |
|
654 |
address = var.getaddress() |
|
655 |
if address is not None: |
|
1297 | 656 |
located.append((vartype_content.getname(), var.getname(), address, initial_value)) |
814 | 657 |
else: |
1297 | 658 |
variables.append((vartype_content.getname(), var.getname(), None, initial_value)) |
814 | 659 |
else: |
660 |
var_type = var.gettypeAsText() |
|
661 |
initial = var.getinitialValue() |
|
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
662 |
if initial is not None: |
814 | 663 |
initial_value = initial.getvalue() |
664 |
else: |
|
665 |
initial_value = None |
|
666 |
address = var.getaddress() |
|
667 |
if address is not None: |
|
668 |
located.append((var_type, var.getname(), address, initial_value)) |
|
669 |
else: |
|
670 |
variables.append((var_type, var.getname(), None, initial_value)) |
|
1297 | 671 |
if varlist.getconstant(): |
814 | 672 |
option = "CONSTANT" |
1297 | 673 |
elif varlist.getretain(): |
814 | 674 |
option = "RETAIN" |
1297 | 675 |
elif varlist.getnonretain(): |
814 | 676 |
option = "NON_RETAIN" |
677 |
else: |
|
678 |
option = None |
|
679 |
if len(variables) > 0: |
|
1297 | 680 |
self.Interface.append((varTypeNames[varlist_type], option, False, variables)) |
814 | 681 |
if len(located) > 0: |
1297 | 682 |
self.Interface.append((varTypeNames[varlist_type], option, True, located)) |
1181
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
683 |
|
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
684 |
LITERAL_TYPES = { |
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
685 |
"T": "TIME", |
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
686 |
"D": "DATE", |
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
687 |
"TOD": "TIME_OF_DAY", |
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
688 |
"DT": "DATE_AND_TIME", |
1183
a01618805821
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1181
diff
changeset
|
689 |
"2": None, |
a01618805821
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1181
diff
changeset
|
690 |
"8": None, |
a01618805821
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1181
diff
changeset
|
691 |
"16": None, |
1181
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
692 |
} |
814 | 693 |
def ComputeConnectionTypes(self, pou): |
694 |
body = pou.getbody() |
|
695 |
if isinstance(body, ListType): |
|
696 |
body = body[0] |
|
697 |
body_content = body.getcontent() |
|
1297 | 698 |
body_type = body_content.getLocalTag() |
814 | 699 |
if body_type in ["FBD", "LD", "SFC"]: |
700 |
undefined_blocks = [] |
|
701 |
for instance in body.getcontentInstances(): |
|
1297 | 702 |
if isinstance(instance, (InVariableClass, OutVariableClass, |
703 |
InOutVariableClass)): |
|
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
704 |
expression = instance.getexpression() |
814 | 705 |
var_type = self.GetVariableType(expression) |
1297 | 706 |
if (isinstance(pou, TransitionObjClass) |
707 |
and expression == pou.getname()): |
|
822
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
708 |
var_type = "BOOL" |
1297 | 709 |
elif (not isinstance(pou, (TransitionObjClass, ActionObjClass)) and |
822
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
710 |
pou.getpouType() == "function" and expression == pou.getname()): |
814 | 711 |
returntype_content = pou.interface.getreturnType().getcontent() |
1297 | 712 |
returntype_content_type = returntype_content.getLocalTag() |
713 |
if returntype_content_type == "derived": |
|
714 |
var_type = returntype_content.getname() |
|
814 | 715 |
else: |
1297 | 716 |
var_type = returntype_content_type.upper() |
814 | 717 |
elif var_type is None: |
718 |
parts = expression.split("#") |
|
719 |
if len(parts) > 1: |
|
1181
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
720 |
literal_prefix = parts[0].upper() |
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
721 |
var_type = self.LITERAL_TYPES.get(literal_prefix, |
21e6db77eb29
Fixed bug in PLC code generated with binary, octal and hexadecimal literals
Laurent Bessard
parents:
1134
diff
changeset
|
722 |
literal_prefix) |
814 | 723 |
elif expression.startswith("'"): |
724 |
var_type = "STRING" |
|
725 |
elif expression.startswith('"'): |
|
726 |
var_type = "WSTRING" |
|
727 |
if var_type is not None: |
|
1297 | 728 |
if isinstance(instance, (InVariableClass, InOutVariableClass)): |
814 | 729 |
for connection in self.ExtractRelatedConnections(instance.connectionPointOut): |
730 |
self.ConnectionTypes[connection] = var_type |
|
1297 | 731 |
if isinstance(instance, (OutVariableClass, InOutVariableClass)): |
814 | 732 |
self.ConnectionTypes[instance.connectionPointIn] = var_type |
733 |
connected = self.GetConnectedConnector(instance.connectionPointIn, body) |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
734 |
if connected is not None and not self.ConnectionTypes.has_key(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
735 |
for related in self.ExtractRelatedConnections(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
736 |
self.ConnectionTypes[related] = var_type |
1297 | 737 |
elif isinstance(instance, (ContactClass, CoilClass)): |
814 | 738 |
for connection in self.ExtractRelatedConnections(instance.connectionPointOut): |
739 |
self.ConnectionTypes[connection] = "BOOL" |
|
740 |
self.ConnectionTypes[instance.connectionPointIn] = "BOOL" |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
741 |
for link in instance.connectionPointIn.getconnections(): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
742 |
connected = self.GetLinkedConnector(link, body) |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
743 |
if connected is not None and not self.ConnectionTypes.has_key(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
744 |
for related in self.ExtractRelatedConnections(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
745 |
self.ConnectionTypes[related] = "BOOL" |
1297 | 746 |
elif isinstance(instance, LeftPowerRailClass): |
814 | 747 |
for connection in instance.getconnectionPointOut(): |
748 |
for related in self.ExtractRelatedConnections(connection): |
|
749 |
self.ConnectionTypes[related] = "BOOL" |
|
1297 | 750 |
elif isinstance(instance, RightPowerRailClass): |
814 | 751 |
for connection in instance.getconnectionPointIn(): |
752 |
self.ConnectionTypes[connection] = "BOOL" |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
753 |
for link in connection.getconnections(): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
754 |
connected = self.GetLinkedConnector(link, body) |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
755 |
if connected is not None and not self.ConnectionTypes.has_key(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
756 |
for related in self.ExtractRelatedConnections(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
757 |
self.ConnectionTypes[related] = "BOOL" |
1297 | 758 |
elif isinstance(instance, TransitionClass): |
759 |
content = instance.getconditionContent() |
|
760 |
if content["type"] == "connection": |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
761 |
self.ConnectionTypes[content["value"]] = "BOOL" |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
762 |
for link in content["value"].getconnections(): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
763 |
connected = self.GetLinkedConnector(link, body) |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
764 |
if connected is not None and not self.ConnectionTypes.has_key(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
765 |
for related in self.ExtractRelatedConnections(connected): |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
766 |
self.ConnectionTypes[related] = "BOOL" |
1297 | 767 |
elif isinstance(instance, ContinuationClass): |
814 | 768 |
name = instance.getname() |
769 |
connector = None |
|
770 |
var_type = "ANY" |
|
771 |
for element in body.getcontentInstances(): |
|
1297 | 772 |
if isinstance(element, ConnectorClass) and element.getname() == name: |
814 | 773 |
if connector is not None: |
774 |
raise PLCGenException, _("More than one connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name) |
|
775 |
connector = element |
|
776 |
if connector is not None: |
|
777 |
undefined = [instance.connectionPointOut, connector.connectionPointIn] |
|
778 |
connected = self.GetConnectedConnector(connector.connectionPointIn, body) |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
779 |
if connected is not None: |
814 | 780 |
undefined.append(connected) |
781 |
related = [] |
|
782 |
for connection in undefined: |
|
783 |
if self.ConnectionTypes.has_key(connection): |
|
784 |
var_type = self.ConnectionTypes[connection] |
|
785 |
else: |
|
786 |
related.extend(self.ExtractRelatedConnections(connection)) |
|
787 |
if var_type.startswith("ANY") and len(related) > 0: |
|
788 |
self.RelatedConnections.append(related) |
|
789 |
else: |
|
790 |
for connection in related: |
|
791 |
self.ConnectionTypes[connection] = var_type |
|
792 |
else: |
|
793 |
raise PLCGenException, _("No connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name) |
|
1297 | 794 |
elif isinstance(instance, BlockClass): |
814 | 795 |
block_infos = self.GetBlockType(instance.gettypeName(), "undefined") |
796 |
if block_infos is not None: |
|
797 |
self.ComputeBlockInputTypes(instance, block_infos, body) |
|
798 |
else: |
|
799 |
for variable in instance.inputVariables.getvariable(): |
|
800 |
connected = self.GetConnectedConnector(variable.connectionPointIn, body) |
|
801 |
if connected is not None: |
|
802 |
var_type = self.ConnectionTypes.get(connected, None) |
|
803 |
if var_type is not None: |
|
804 |
self.ConnectionTypes[variable.connectionPointIn] = var_type |
|
805 |
else: |
|
806 |
related = self.ExtractRelatedConnections(connected) |
|
807 |
related.append(variable.connectionPointIn) |
|
808 |
self.RelatedConnections.append(related) |
|
809 |
undefined_blocks.append(instance) |
|
810 |
for instance in undefined_blocks: |
|
811 |
block_infos = self.GetBlockType(instance.gettypeName(), tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in instance.inputVariables.getvariable() if variable.getformalParameter() != "EN"])) |
|
812 |
if block_infos is not None: |
|
813 |
self.ComputeBlockInputTypes(instance, block_infos, body) |
|
814 |
else: |
|
815 |
raise PLCGenException, _("No informations found for \"%s\" block")%(instance.gettypeName()) |
|
822
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
816 |
if body_type == "SFC": |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
817 |
previous_tagname = self.TagName |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
818 |
for action in pou.getactionList(): |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
819 |
self.TagName = self.ParentGenerator.Controler.ComputePouActionName(self.Name, action.getname()) |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
820 |
self.ComputeConnectionTypes(action) |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
821 |
for transition in pou.gettransitionList(): |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
822 |
self.TagName = self.ParentGenerator.Controler.ComputePouTransitionName(self.Name, transition.getname()) |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
823 |
self.ComputeConnectionTypes(transition) |
050045c32d98
Fix bug in PLCGenerator connection types not computed for SFC actions and transitions body
laurent
parents:
814
diff
changeset
|
824 |
self.TagName = previous_tagname |
814 | 825 |
|
826 |
def ComputeBlockInputTypes(self, instance, block_infos, body): |
|
827 |
undefined = {} |
|
828 |
for variable in instance.outputVariables.getvariable(): |
|
829 |
output_name = variable.getformalParameter() |
|
830 |
if output_name == "ENO": |
|
831 |
for connection in self.ExtractRelatedConnections(variable.connectionPointOut): |
|
832 |
self.ConnectionTypes[connection] = "BOOL" |
|
833 |
else: |
|
834 |
for oname, otype, oqualifier in block_infos["outputs"]: |
|
835 |
if output_name == oname: |
|
836 |
if otype.startswith("ANY"): |
|
837 |
if not undefined.has_key(otype): |
|
838 |
undefined[otype] = [] |
|
839 |
undefined[otype].append(variable.connectionPointOut) |
|
840 |
elif not self.ConnectionTypes.has_key(variable.connectionPointOut): |
|
841 |
for connection in self.ExtractRelatedConnections(variable.connectionPointOut): |
|
842 |
self.ConnectionTypes[connection] = otype |
|
843 |
for variable in instance.inputVariables.getvariable(): |
|
844 |
input_name = variable.getformalParameter() |
|
845 |
if input_name == "EN": |
|
846 |
for connection in self.ExtractRelatedConnections(variable.connectionPointIn): |
|
847 |
self.ConnectionTypes[connection] = "BOOL" |
|
848 |
else: |
|
849 |
for iname, itype, iqualifier in block_infos["inputs"]: |
|
850 |
if input_name == iname: |
|
851 |
connected = self.GetConnectedConnector(variable.connectionPointIn, body) |
|
852 |
if itype.startswith("ANY"): |
|
853 |
if not undefined.has_key(itype): |
|
854 |
undefined[itype] = [] |
|
855 |
undefined[itype].append(variable.connectionPointIn) |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
856 |
if connected is not None: |
814 | 857 |
undefined[itype].append(connected) |
858 |
else: |
|
859 |
self.ConnectionTypes[variable.connectionPointIn] = itype |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
860 |
if connected is not None and not self.ConnectionTypes.has_key(connected): |
814 | 861 |
for connection in self.ExtractRelatedConnections(connected): |
862 |
self.ConnectionTypes[connection] = itype |
|
863 |
for var_type, connections in undefined.items(): |
|
864 |
related = [] |
|
865 |
for connection in connections: |
|
854
c10f2092c43a
Fixing bug in PLCGenerator with user defined functions and standard overloaded function
Laurent Bessard
parents:
822
diff
changeset
|
866 |
connection_type = self.ConnectionTypes.get(connection) |
c10f2092c43a
Fixing bug in PLCGenerator with user defined functions and standard overloaded function
Laurent Bessard
parents:
822
diff
changeset
|
867 |
if connection_type and not connection_type.startswith("ANY"): |
c10f2092c43a
Fixing bug in PLCGenerator with user defined functions and standard overloaded function
Laurent Bessard
parents:
822
diff
changeset
|
868 |
var_type = connection_type |
814 | 869 |
else: |
870 |
related.extend(self.ExtractRelatedConnections(connection)) |
|
871 |
if var_type.startswith("ANY") and len(related) > 0: |
|
872 |
self.RelatedConnections.append(related) |
|
873 |
else: |
|
874 |
for connection in related: |
|
875 |
self.ConnectionTypes[connection] = var_type |
|
876 |
||
877 |
def ComputeProgram(self, pou): |
|
878 |
body = pou.getbody() |
|
879 |
if isinstance(body, ListType): |
|
880 |
body = body[0] |
|
881 |
body_content = body.getcontent() |
|
1297 | 882 |
body_type = body_content.getLocalTag() |
814 | 883 |
if body_type in ["IL","ST"]: |
1297 | 884 |
text = body_content.getanyText() |
814 | 885 |
self.ParentGenerator.GeneratePouProgramInText(text.upper()) |
886 |
self.Program = [(ReIndentText(text, len(self.CurrentIndent)), |
|
887 |
(self.TagName, "body", len(self.CurrentIndent)))] |
|
888 |
elif body_type == "SFC": |
|
889 |
self.IndentRight() |
|
890 |
for instance in body.getcontentInstances(): |
|
1297 | 891 |
if isinstance(instance, StepClass): |
814 | 892 |
self.GenerateSFCStep(instance, pou) |
1297 | 893 |
elif isinstance(instance, ActionBlockClass): |
814 | 894 |
self.GenerateSFCStepActions(instance, pou) |
1297 | 895 |
elif isinstance(instance, TransitionClass): |
814 | 896 |
self.GenerateSFCTransition(instance, pou) |
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
897 |
elif isinstance(instance, JumpStepClass): |
814 | 898 |
self.GenerateSFCJump(instance, pou) |
899 |
if len(self.InitialSteps) > 0 and len(self.SFCComputedBlocks) > 0: |
|
900 |
action_name = "COMPUTE_FUNCTION_BLOCKS" |
|
901 |
action_infos = {"qualifier" : "S", "content" : action_name} |
|
902 |
self.SFCNetworks["Steps"][self.InitialSteps[0]]["actions"].append(action_infos) |
|
903 |
self.SFCNetworks["Actions"][action_name] = (self.SFCComputedBlocks, ()) |
|
904 |
self.Program = [] |
|
905 |
self.IndentLeft() |
|
906 |
for initialstep in self.InitialSteps: |
|
907 |
self.ComputeSFCStep(initialstep) |
|
908 |
else: |
|
909 |
otherInstances = {"outVariables&coils" : [], "blocks" : [], "connectors" : []} |
|
910 |
orderedInstances = [] |
|
911 |
for instance in body.getcontentInstances(): |
|
1297 | 912 |
if isinstance(instance, (OutVariableClass, InOutVariableClass, BlockClass)): |
814 | 913 |
executionOrderId = instance.getexecutionOrderId() |
914 |
if executionOrderId > 0: |
|
915 |
orderedInstances.append((executionOrderId, instance)) |
|
1297 | 916 |
elif isinstance(instance, (OutVariableClass, InOutVariableClass)): |
814 | 917 |
otherInstances["outVariables&coils"].append(instance) |
1297 | 918 |
elif isinstance(instance, BlockClass): |
814 | 919 |
otherInstances["blocks"].append(instance) |
1297 | 920 |
elif isinstance(instance, ConnectorClass): |
814 | 921 |
otherInstances["connectors"].append(instance) |
1297 | 922 |
elif isinstance(instance, CoilClass): |
814 | 923 |
otherInstances["outVariables&coils"].append(instance) |
924 |
orderedInstances.sort() |
|
925 |
otherInstances["outVariables&coils"].sort(SortInstances) |
|
926 |
otherInstances["blocks"].sort(SortInstances) |
|
927 |
instances = [instance for (executionOrderId, instance) in orderedInstances] |
|
1048
b450202605ab
Fixed bug in program elements computation order in PLCGenerator
Laurent Bessard
parents:
1032
diff
changeset
|
928 |
instances.extend(otherInstances["outVariables&coils"] + otherInstances["blocks"] + otherInstances["connectors"]) |
814 | 929 |
for instance in instances: |
1297 | 930 |
if isinstance(instance, (OutVariableClass, InOutVariableClass)): |
814 | 931 |
connections = instance.connectionPointIn.getconnections() |
932 |
if connections is not None: |
|
933 |
expression = self.ComputeExpression(body, connections) |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
934 |
if expression is not None: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
935 |
self.Program += [(self.CurrentIndent, ()), |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
936 |
(instance.getexpression(), (self.TagName, "io_variable", instance.getlocalId(), "expression")), |
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
937 |
(" := ", ())] |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
938 |
self.Program += expression |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
939 |
self.Program += [(";\n", ())] |
1297 | 940 |
elif isinstance(instance, BlockClass): |
814 | 941 |
block_type = instance.gettypeName() |
942 |
self.ParentGenerator.GeneratePouProgram(block_type) |
|
943 |
block_infos = self.GetBlockType(block_type, tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in instance.inputVariables.getvariable() if variable.getformalParameter() != "EN"])) |
|
944 |
if block_infos is None: |
|
945 |
block_infos = self.GetBlockType(block_type) |
|
946 |
if block_infos is None: |
|
947 |
raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name) |
|
1134
1c7a4ad86aa1
Fixed PLC code generator when interface of an already used POU has changed
Laurent Bessard
parents:
1048
diff
changeset
|
948 |
try: |
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
949 |
self.GenerateBlock(instance, block_infos, body, None) |
1134
1c7a4ad86aa1
Fixed PLC code generator when interface of an already used POU has changed
Laurent Bessard
parents:
1048
diff
changeset
|
950 |
except ValueError, e: |
1c7a4ad86aa1
Fixed PLC code generator when interface of an already used POU has changed
Laurent Bessard
parents:
1048
diff
changeset
|
951 |
raise PLCGenException, e.message |
1297 | 952 |
elif isinstance(instance, ConnectorClass): |
814 | 953 |
connector = instance.getname() |
954 |
if self.ComputedConnectors.get(connector, None): |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
955 |
continue |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
956 |
expression = self.ComputeExpression(body, instance.connectionPointIn.getconnections()) |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
957 |
if expression is not None: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
958 |
self.ComputedConnectors[connector] = expression |
1297 | 959 |
elif isinstance(instance, CoilClass): |
814 | 960 |
connections = instance.connectionPointIn.getconnections() |
961 |
if connections is not None: |
|
962 |
coil_info = (self.TagName, "coil", instance.getlocalId()) |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
963 |
expression = self.ComputeExpression(body, connections) |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
964 |
if expression is not None: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
965 |
expression = self.ExtractModifier(instance, expression, coil_info) |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
966 |
self.Program += [(self.CurrentIndent, ())] |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
967 |
self.Program += [(instance.getvariable(), coil_info + ("reference",))] |
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
968 |
self.Program += [(" := ", ())] + expression + [(";\n", ())] |
814 | 969 |
|
970 |
def FactorizePaths(self, paths): |
|
971 |
same_paths = {} |
|
972 |
uncomputed_index = range(len(paths)) |
|
973 |
factorized_paths = [] |
|
974 |
for num, path in enumerate(paths): |
|
975 |
if type(path) == ListType: |
|
976 |
if len(path) > 1: |
|
977 |
str_path = str(path[-1:]) |
|
978 |
same_paths.setdefault(str_path, []) |
|
979 |
same_paths[str_path].append((path[:-1], num)) |
|
980 |
else: |
|
981 |
factorized_paths.append(path) |
|
982 |
uncomputed_index.remove(num) |
|
983 |
for same_path, elements in same_paths.items(): |
|
984 |
if len(elements) > 1: |
|
985 |
elements_paths = self.FactorizePaths([path for path, num in elements]) |
|
986 |
if len(elements_paths) > 1: |
|
987 |
factorized_paths.append([tuple(elements_paths)] + eval(same_path)) |
|
988 |
else: |
|
989 |
factorized_paths.append(elements_paths + eval(same_path)) |
|
990 |
for path, num in elements: |
|
991 |
uncomputed_index.remove(num) |
|
992 |
for num in uncomputed_index: |
|
993 |
factorized_paths.append(paths[num]) |
|
994 |
factorized_paths.sort() |
|
995 |
return factorized_paths |
|
996 |
||
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
997 |
def GenerateBlock(self, block, block_infos, body, link, order=False, to_inout=False): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
998 |
body_type = body.getcontent().getLocalTag() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
999 |
name = block.getinstanceName() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1000 |
type = block.gettypeName() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1001 |
executionOrderId = block.getexecutionOrderId() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1002 |
input_variables = block.inputVariables.getvariable() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1003 |
output_variables = block.outputVariables.getvariable() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1004 |
inout_variables = {} |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1005 |
for input_variable in input_variables: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1006 |
for output_variable in output_variables: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1007 |
if input_variable.getformalParameter() == output_variable.getformalParameter(): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1008 |
inout_variables[input_variable.getformalParameter()] = "" |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1009 |
input_names = [input[0] for input in block_infos["inputs"]] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1010 |
output_names = [output[0] for output in block_infos["outputs"]] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1011 |
if block_infos["type"] == "function": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1012 |
if not self.ComputedBlocks.get(block, False) and not order: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1013 |
self.ComputedBlocks[block] = True |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1014 |
connected_vars = [] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1015 |
if not block_infos["extensible"]: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1016 |
input_connected = dict([("EN", None)] + |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1017 |
[(input_name, None) for input_name in input_names]) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1018 |
for variable in input_variables: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1019 |
parameter = variable.getformalParameter() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1020 |
if input_connected.has_key(parameter): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1021 |
input_connected[parameter] = variable |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1022 |
if input_connected["EN"] is None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1023 |
input_connected.pop("EN") |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1024 |
input_parameters = input_names |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1025 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1026 |
input_parameters = ["EN"] + input_names |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1027 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1028 |
input_connected = dict([(variable.getformalParameter(), variable) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1029 |
for variable in input_variables]) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1030 |
input_parameters = [variable.getformalParameter() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1031 |
for variable in input_variables] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1032 |
one_input_connected = False |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1033 |
all_input_connected = True |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1034 |
for i, parameter in enumerate(input_parameters): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1035 |
variable = input_connected.get(parameter) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1036 |
if variable is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1037 |
input_info = (self.TagName, "block", block.getlocalId(), "input", i) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1038 |
connections = variable.connectionPointIn.getconnections() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1039 |
if connections is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1040 |
if parameter != "EN": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1041 |
one_input_connected = True |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1042 |
if inout_variables.has_key(parameter): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1043 |
expression = self.ComputeExpression(body, connections, executionOrderId > 0, True) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1044 |
if expression is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1045 |
inout_variables[parameter] = value |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1046 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1047 |
expression = self.ComputeExpression(body, connections, executionOrderId > 0) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1048 |
if expression is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1049 |
connected_vars.append(([(parameter, input_info), (" := ", ())], |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1050 |
self.ExtractModifier(variable, expression, input_info))) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1051 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1052 |
all_input_connected = False |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1053 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1054 |
all_input_connected = False |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1055 |
if len(output_variables) > 1 or not all_input_connected: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1056 |
vars = [name + value for name, value in connected_vars] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1057 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1058 |
vars = [value for name, value in connected_vars] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1059 |
if one_input_connected: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1060 |
for i, variable in enumerate(output_variables): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1061 |
parameter = variable.getformalParameter() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1062 |
if not inout_variables.has_key(parameter) and parameter in output_names + ["", "ENO"]: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1063 |
if variable.getformalParameter() == "": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1064 |
variable_name = "%s%d"%(type, block.getlocalId()) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1065 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1066 |
variable_name = "%s%d_%s"%(type, block.getlocalId(), parameter) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1067 |
if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] is not None or self.Interface[-1][2]: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1068 |
self.Interface.append(("VAR", None, False, [])) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1069 |
if variable.connectionPointOut in self.ConnectionTypes: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1070 |
self.Interface[-1][3].append((self.ConnectionTypes[variable.connectionPointOut], variable_name, None, None)) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1071 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1072 |
self.Interface[-1][3].append(("ANY", variable_name, None, None)) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1073 |
if len(output_variables) > 1 and parameter not in ["", "OUT"]: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1074 |
vars.append([(parameter, (self.TagName, "block", block.getlocalId(), "output", i)), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1075 |
(" => %s"%variable_name, ())]) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1076 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1077 |
output_info = (self.TagName, "block", block.getlocalId(), "output", i) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1078 |
output_name = variable_name |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1079 |
self.Program += [(self.CurrentIndent, ()), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1080 |
(output_name, output_info), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1081 |
(" := ", ()), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1082 |
(type, (self.TagName, "block", block.getlocalId(), "type")), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1083 |
("(", ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1084 |
self.Program += JoinList([(", ", ())], vars) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1085 |
self.Program += [(");\n", ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1086 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1087 |
self.Warnings.append(_("\"%s\" function cancelled in \"%s\" POU: No input connected")%(type, self.TagName.split("::")[-1])) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1088 |
elif block_infos["type"] == "functionBlock": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1089 |
if not self.ComputedBlocks.get(block, False) and not order: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1090 |
self.ComputedBlocks[block] = True |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1091 |
vars = [] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1092 |
offset_idx = 0 |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1093 |
for variable in input_variables: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1094 |
parameter = variable.getformalParameter() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1095 |
if parameter in input_names or parameter == "EN": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1096 |
if parameter == "EN": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1097 |
input_idx = 0 |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1098 |
offset_idx = 1 |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1099 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1100 |
input_idx = offset_idx + input_names.index(parameter) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1101 |
input_info = (self.TagName, "block", block.getlocalId(), "input", input_idx) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1102 |
connections = variable.connectionPointIn.getconnections() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1103 |
if connections is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1104 |
expression = self.ComputeExpression(body, connections, executionOrderId > 0, inout_variables.has_key(parameter)) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1105 |
if expression is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1106 |
vars.append([(parameter, input_info), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1107 |
(" := ", ())] + self.ExtractModifier(variable, expression, input_info)) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1108 |
self.Program += [(self.CurrentIndent, ()), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1109 |
(name, (self.TagName, "block", block.getlocalId(), "name")), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1110 |
("(", ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1111 |
self.Program += JoinList([(", ", ())], vars) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1112 |
self.Program += [(");\n", ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1113 |
|
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1114 |
if link is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1115 |
connectionPoint = link.getposition()[-1] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1116 |
output_parameter = link.getformalParameter() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1117 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1118 |
connectionPoint = None |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1119 |
output_parameter = None |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1120 |
|
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1121 |
output_variable = None |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1122 |
output_idx = 0 |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1123 |
if output_parameter is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1124 |
if output_parameter in output_names or output_parameter == "ENO": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1125 |
for variable in output_variables: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1126 |
if variable.getformalParameter() == output_parameter: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1127 |
output_variable = variable |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1128 |
if output_parameter != "ENO": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1129 |
output_idx = output_names.index(output_parameter) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1130 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1131 |
for i, variable in enumerate(output_variables): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1132 |
blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1133 |
if (connectionPoint is None or |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1134 |
block.getx() + blockPointx == connectionPoint.getx() and |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1135 |
block.gety() + blockPointy == connectionPoint.gety()): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1136 |
output_variable = variable |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1137 |
output_parameter = variable.getformalParameter() |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1138 |
output_idx = i |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1139 |
|
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1140 |
if output_variable is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1141 |
if block_infos["type"] == "function": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1142 |
output_info = (self.TagName, "block", block.getlocalId(), "output", output_idx) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1143 |
if inout_variables.has_key(output_parameter): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1144 |
output_value = inout_variables[output_parameter] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1145 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1146 |
if output_parameter == "": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1147 |
output_name = "%s%d"%(type, block.getlocalId()) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1148 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1149 |
output_name = "%s%d_%s"%(type, block.getlocalId(), output_parameter) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1150 |
output_value = [(output_name, output_info)] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1151 |
return self.ExtractModifier(output_variable, output_value, output_info) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1152 |
|
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1153 |
if block_infos["type"] == "functionBlock": |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1154 |
output_info = (self.TagName, "block", block.getlocalId(), "output", output_idx) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1155 |
output_name = self.ExtractModifier(output_variable, [("%s.%s"%(name, output_parameter), output_info)], output_info) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1156 |
if to_inout: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1157 |
variable_name = "%s_%s"%(name, output_parameter) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1158 |
if not self.IsAlreadyDefined(variable_name): |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1159 |
if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] is not None or self.Interface[-1][2]: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1160 |
self.Interface.append(("VAR", None, False, [])) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1161 |
if variable.connectionPointOut in self.ConnectionTypes: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1162 |
self.Interface[-1][3].append( |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1163 |
(self.ConnectionTypes[output_variable.connectionPointOut], variable_name, None, None)) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1164 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1165 |
self.Interface[-1][3].append(("ANY", variable_name, None, None)) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1166 |
self.Program += [(self.CurrentIndent, ()), |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1167 |
("%s := "%variable_name, ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1168 |
self.Program += output_name |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1169 |
self.Program += [(";\n", ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1170 |
return [(variable_name, ())] |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1171 |
return output_name |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1172 |
if link is not None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1173 |
if output_parameter is None: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1174 |
output_parameter = "" |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1175 |
if name: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1176 |
blockname = "%s(%s)" % (name, type) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1177 |
else: |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1178 |
blockname = type |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1179 |
raise ValueError, _("No output %s variable found in block %s in POU %s. Connection must be broken") % \ |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1180 |
(output_parameter, blockname, self.Name) |
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1181 |
|
814 | 1182 |
def GeneratePaths(self, connections, body, order = False, to_inout = False): |
1183 |
paths = [] |
|
1184 |
for connection in connections: |
|
1185 |
localId = connection.getrefLocalId() |
|
1186 |
next = body.getcontentInstance(localId) |
|
1297 | 1187 |
if isinstance(next, LeftPowerRailClass): |
814 | 1188 |
paths.append(None) |
1297 | 1189 |
elif isinstance(next, (InVariableClass, InOutVariableClass)): |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1190 |
paths.append(str([(next.getexpression(), (self.TagName, "io_variable", localId, "expression"))])) |
1297 | 1191 |
elif isinstance(next, BlockClass): |
814 | 1192 |
block_type = next.gettypeName() |
1193 |
self.ParentGenerator.GeneratePouProgram(block_type) |
|
1194 |
block_infos = self.GetBlockType(block_type, tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in next.inputVariables.getvariable() if variable.getformalParameter() != "EN"])) |
|
1195 |
if block_infos is None: |
|
1196 |
block_infos = self.GetBlockType(block_type) |
|
1197 |
if block_infos is None: |
|
1198 |
raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name) |
|
1134
1c7a4ad86aa1
Fixed PLC code generator when interface of an already used POU has changed
Laurent Bessard
parents:
1048
diff
changeset
|
1199 |
try: |
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1200 |
paths.append(str(self.GenerateBlock(next, block_infos, body, connection, order, to_inout))) |
1134
1c7a4ad86aa1
Fixed PLC code generator when interface of an already used POU has changed
Laurent Bessard
parents:
1048
diff
changeset
|
1201 |
except ValueError, e: |
1c7a4ad86aa1
Fixed PLC code generator when interface of an already used POU has changed
Laurent Bessard
parents:
1048
diff
changeset
|
1202 |
raise PLCGenException, e.message |
1297 | 1203 |
elif isinstance(next, ContinuationClass): |
814 | 1204 |
name = next.getname() |
1205 |
computed_value = self.ComputedConnectors.get(name, None) |
|
1206 |
if computed_value != None: |
|
1207 |
paths.append(str(computed_value)) |
|
1208 |
else: |
|
1209 |
connector = None |
|
1210 |
for instance in body.getcontentInstances(): |
|
1297 | 1211 |
if isinstance(instance, ConnectorClass) and instance.getname() == name: |
814 | 1212 |
if connector is not None: |
1213 |
raise PLCGenException, _("More than one connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name) |
|
1214 |
connector = instance |
|
1215 |
if connector is not None: |
|
1216 |
connections = connector.connectionPointIn.getconnections() |
|
1217 |
if connections is not None: |
|
1218 |
expression = self.ComputeExpression(body, connections, order) |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1219 |
if expression is not None: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1220 |
self.ComputedConnectors[name] = expression |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1221 |
paths.append(str(expression)) |
814 | 1222 |
else: |
1223 |
raise PLCGenException, _("No connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name) |
|
1297 | 1224 |
elif isinstance(next, ContactClass): |
814 | 1225 |
contact_info = (self.TagName, "contact", next.getlocalId()) |
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1226 |
variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info)) |
814 | 1227 |
result = self.GeneratePaths(next.connectionPointIn.getconnections(), body, order) |
1228 |
if len(result) > 1: |
|
1229 |
factorized_paths = self.FactorizePaths(result) |
|
1230 |
if len(factorized_paths) > 1: |
|
1231 |
paths.append([variable, tuple(factorized_paths)]) |
|
1232 |
else: |
|
1233 |
paths.append([variable] + factorized_paths) |
|
1234 |
elif type(result[0]) == ListType: |
|
1235 |
paths.append([variable] + result[0]) |
|
1236 |
elif result[0] is not None: |
|
1237 |
paths.append([variable, result[0]]) |
|
1238 |
else: |
|
1239 |
paths.append(variable) |
|
1297 | 1240 |
elif isinstance(next, CoilClass): |
814 | 1241 |
paths.append(str(self.GeneratePaths(next.connectionPointIn.getconnections(), body, order))) |
1242 |
return paths |
|
1243 |
||
1244 |
def ComputePaths(self, paths, first = False): |
|
1245 |
if type(paths) == TupleType: |
|
1246 |
if None in paths: |
|
1247 |
return [("TRUE", ())] |
|
1248 |
else: |
|
1249 |
vars = [self.ComputePaths(path) for path in paths] |
|
1250 |
if first: |
|
1251 |
return JoinList([(" OR ", ())], vars) |
|
1252 |
else: |
|
1253 |
return [("(", ())] + JoinList([(" OR ", ())], vars) + [(")", ())] |
|
1254 |
elif type(paths) == ListType: |
|
1255 |
vars = [self.ComputePaths(path) for path in paths] |
|
1256 |
return JoinList([(" AND ", ())], vars) |
|
1257 |
elif paths is None: |
|
1258 |
return [("TRUE", ())] |
|
1259 |
else: |
|
1260 |
return eval(paths) |
|
1261 |
||
1262 |
def ComputeExpression(self, body, connections, order = False, to_inout = False): |
|
1263 |
paths = self.GeneratePaths(connections, body, order, to_inout) |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1264 |
if len(paths) == 0: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1265 |
return None |
814 | 1266 |
if len(paths) > 1: |
1267 |
factorized_paths = self.FactorizePaths(paths) |
|
1268 |
if len(factorized_paths) > 1: |
|
1269 |
paths = tuple(factorized_paths) |
|
1270 |
else: |
|
1271 |
paths = factorized_paths[0] |
|
1272 |
else: |
|
1273 |
paths = paths[0] |
|
1274 |
return self.ComputePaths(paths, True) |
|
1275 |
||
1276 |
def ExtractModifier(self, variable, expression, var_info): |
|
1277 |
if variable.getnegated(): |
|
1278 |
return [("NOT(", var_info + ("negated",))] + expression + [(")", ())] |
|
1279 |
else: |
|
1280 |
storage = variable.getstorage() |
|
1281 |
if storage in ["set", "reset"]: |
|
1282 |
self.Program += [(self.CurrentIndent + "IF ", var_info + (storage,))] + expression |
|
1283 |
self.Program += [(" THEN\n ", ())] |
|
1284 |
if storage == "set": |
|
1285 |
return [("TRUE; (*set*)\n" + self.CurrentIndent + "END_IF", ())] |
|
1286 |
else: |
|
1287 |
return [("FALSE; (*reset*)\n" + self.CurrentIndent + "END_IF", ())] |
|
1288 |
edge = variable.getedge() |
|
1289 |
if edge == "rising": |
|
1290 |
return self.AddTrigger("R_TRIG", expression, var_info + ("rising",)) |
|
1291 |
elif edge == "falling": |
|
1292 |
return self.AddTrigger("F_TRIG", expression, var_info + ("falling",)) |
|
1293 |
return expression |
|
1294 |
||
1295 |
def AddTrigger(self, edge, expression, var_info): |
|
1296 |
if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] is not None or self.Interface[-1][2]: |
|
1297 |
self.Interface.append(("VAR", None, False, [])) |
|
1298 |
i = 1 |
|
1299 |
name = "%s%d"%(edge, i) |
|
1300 |
while self.IsAlreadyDefined(name): |
|
1301 |
i += 1 |
|
1302 |
name = "%s%d"%(edge, i) |
|
1303 |
self.Interface[-1][3].append((edge, name, None, None)) |
|
1304 |
self.Program += [(self.CurrentIndent, ()), (name, var_info), ("(CLK := ", ())] |
|
1305 |
self.Program += expression |
|
1306 |
self.Program += [(");\n", ())] |
|
1307 |
return [("%s.Q"%name, var_info)] |
|
1308 |
||
1309 |
def ExtractDivergenceInput(self, divergence, pou): |
|
1310 |
connectionPointIn = divergence.getconnectionPointIn() |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1311 |
if connectionPointIn is not None: |
814 | 1312 |
connections = connectionPointIn.getconnections() |
1313 |
if connections is not None and len(connections) == 1: |
|
1314 |
instanceLocalId = connections[0].getrefLocalId() |
|
1315 |
body = pou.getbody() |
|
1316 |
if isinstance(body, ListType): |
|
1317 |
body = body[0] |
|
1318 |
return body.getcontentInstance(instanceLocalId) |
|
1319 |
return None |
|
1320 |
||
1321 |
def ExtractConvergenceInputs(self, convergence, pou): |
|
1322 |
instances = [] |
|
1323 |
for connectionPointIn in convergence.getconnectionPointIn(): |
|
1324 |
connections = connectionPointIn.getconnections() |
|
1325 |
if connections is not None and len(connections) == 1: |
|
1326 |
instanceLocalId = connections[0].getrefLocalId() |
|
1327 |
body = pou.getbody() |
|
1328 |
if isinstance(body, ListType): |
|
1329 |
body = body[0] |
|
1330 |
instances.append(body.getcontentInstance(instanceLocalId)) |
|
1331 |
return instances |
|
1332 |
||
1333 |
def GenerateSFCStep(self, step, pou): |
|
1334 |
step_name = step.getname() |
|
1335 |
if step_name not in self.SFCNetworks["Steps"].keys(): |
|
1336 |
if step.getinitialStep(): |
|
1337 |
self.InitialSteps.append(step_name) |
|
1338 |
step_infos = {"id" : step.getlocalId(), |
|
1339 |
"initial" : step.getinitialStep(), |
|
1340 |
"transitions" : [], |
|
1341 |
"actions" : []} |
|
889
ac18acb6917f
Fix bug when using feedback loop in SFC program instead of jump
Laurent Bessard
parents:
883
diff
changeset
|
1342 |
self.SFCNetworks["Steps"][step_name] = step_infos |
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1343 |
if step.connectionPointIn is not None: |
814 | 1344 |
instances = [] |
1345 |
connections = step.connectionPointIn.getconnections() |
|
1346 |
if connections is not None and len(connections) == 1: |
|
1347 |
instanceLocalId = connections[0].getrefLocalId() |
|
1348 |
body = pou.getbody() |
|
1349 |
if isinstance(body, ListType): |
|
1350 |
body = body[0] |
|
1351 |
instance = body.getcontentInstance(instanceLocalId) |
|
1297 | 1352 |
if isinstance(instance, TransitionClass): |
814 | 1353 |
instances.append(instance) |
1297 | 1354 |
elif isinstance(instance, SelectionConvergenceClass): |
814 | 1355 |
instances.extend(self.ExtractConvergenceInputs(instance, pou)) |
1297 | 1356 |
elif isinstance(instance, SimultaneousDivergenceClass): |
814 | 1357 |
transition = self.ExtractDivergenceInput(instance, pou) |
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1358 |
if transition is not None: |
1297 | 1359 |
if isinstance(transition, TransitionClass): |
814 | 1360 |
instances.append(transition) |
1297 | 1361 |
elif isinstance(transition, SelectionConvergenceClass): |
814 | 1362 |
instances.extend(self.ExtractConvergenceInputs(transition, pou)) |
1363 |
for instance in instances: |
|
1364 |
self.GenerateSFCTransition(instance, pou) |
|
1365 |
if instance in self.SFCNetworks["Transitions"].keys(): |
|
1366 |
target_info = (self.TagName, "transition", instance.getlocalId(), "to", step_infos["id"]) |
|
1367 |
self.SFCNetworks["Transitions"][instance]["to"].append([(step_name, target_info)]) |
|
1368 |
||
1369 |
def GenerateSFCJump(self, jump, pou): |
|
1370 |
jump_target = jump.gettargetName() |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1371 |
if jump.connectionPointIn is not None: |
814 | 1372 |
instances = [] |
1373 |
connections = jump.connectionPointIn.getconnections() |
|
1374 |
if connections is not None and len(connections) == 1: |
|
1375 |
instanceLocalId = connections[0].getrefLocalId() |
|
1376 |
body = pou.getbody() |
|
1377 |
if isinstance(body, ListType): |
|
1378 |
body = body[0] |
|
1379 |
instance = body.getcontentInstance(instanceLocalId) |
|
1297 | 1380 |
if isinstance(instance, TransitionClass): |
814 | 1381 |
instances.append(instance) |
1297 | 1382 |
elif isinstance(instance, SelectionConvergenceClass): |
814 | 1383 |
instances.extend(self.ExtractConvergenceInputs(instance, pou)) |
1297 | 1384 |
elif isinstance(instance, SimultaneousDivergenceClass): |
814 | 1385 |
transition = self.ExtractDivergenceInput(instance, pou) |
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1386 |
if transition is not None: |
1297 | 1387 |
if isinstance(transition, TransitionClass): |
814 | 1388 |
instances.append(transition) |
1297 | 1389 |
elif isinstance(transition, SelectionConvergenceClass): |
814 | 1390 |
instances.extend(self.ExtractConvergenceInputs(transition, pou)) |
1391 |
for instance in instances: |
|
1392 |
self.GenerateSFCTransition(instance, pou) |
|
1393 |
if instance in self.SFCNetworks["Transitions"].keys(): |
|
1394 |
target_info = (self.TagName, "jump", jump.getlocalId(), "target") |
|
1395 |
self.SFCNetworks["Transitions"][instance]["to"].append([(jump_target, target_info)]) |
|
1396 |
||
1397 |
def GenerateSFCStepActions(self, actionBlock, pou): |
|
1398 |
connections = actionBlock.connectionPointIn.getconnections() |
|
1399 |
if connections is not None and len(connections) == 1: |
|
1400 |
stepLocalId = connections[0].getrefLocalId() |
|
1401 |
body = pou.getbody() |
|
1402 |
if isinstance(body, ListType): |
|
1403 |
body = body[0] |
|
1404 |
step = body.getcontentInstance(stepLocalId) |
|
1405 |
self.GenerateSFCStep(step, pou) |
|
1406 |
step_name = step.getname() |
|
1407 |
if step_name in self.SFCNetworks["Steps"].keys(): |
|
1408 |
actions = actionBlock.getactions() |
|
1409 |
for i, action in enumerate(actions): |
|
1410 |
action_infos = {"id" : actionBlock.getlocalId(), |
|
1411 |
"qualifier" : action["qualifier"], |
|
1412 |
"content" : action["value"], |
|
1413 |
"num" : i} |
|
1414 |
if "duration" in action: |
|
1415 |
action_infos["duration"] = action["duration"] |
|
1416 |
if "indicator" in action: |
|
1417 |
action_infos["indicator"] = action["indicator"] |
|
1418 |
if action["type"] == "reference": |
|
1419 |
self.GenerateSFCAction(action["value"], pou) |
|
1420 |
else: |
|
1421 |
action_name = "%s_INLINE%d"%(step_name.upper(), self.GetActionNumber()) |
|
1422 |
self.SFCNetworks["Actions"][action_name] = ([(self.CurrentIndent, ()), |
|
1423 |
(action["value"], (self.TagName, "action_block", action_infos["id"], "action", i, "inline")), |
|
1424 |
("\n", ())], ()) |
|
1425 |
action_infos["content"] = action_name |
|
1426 |
self.SFCNetworks["Steps"][step_name]["actions"].append(action_infos) |
|
1427 |
||
1428 |
def GenerateSFCAction(self, action_name, pou): |
|
1429 |
if action_name not in self.SFCNetworks["Actions"].keys(): |
|
1430 |
actionContent = pou.getaction(action_name) |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1431 |
if actionContent is not None: |
814 | 1432 |
previous_tagname = self.TagName |
1433 |
self.TagName = self.ParentGenerator.Controler.ComputePouActionName(self.Name, action_name) |
|
1434 |
self.ComputeProgram(actionContent) |
|
1435 |
self.SFCNetworks["Actions"][action_name] = (self.Program, (self.TagName, "name")) |
|
1436 |
self.Program = [] |
|
1437 |
self.TagName = previous_tagname |
|
1438 |
||
1439 |
def GenerateSFCTransition(self, transition, pou): |
|
1440 |
if transition not in self.SFCNetworks["Transitions"].keys(): |
|
1441 |
steps = [] |
|
1442 |
connections = transition.connectionPointIn.getconnections() |
|
1443 |
if connections is not None and len(connections) == 1: |
|
1444 |
instanceLocalId = connections[0].getrefLocalId() |
|
1445 |
body = pou.getbody() |
|
1446 |
if isinstance(body, ListType): |
|
1447 |
body = body[0] |
|
1448 |
instance = body.getcontentInstance(instanceLocalId) |
|
1297 | 1449 |
if isinstance(instance, StepClass): |
814 | 1450 |
steps.append(instance) |
1297 | 1451 |
elif isinstance(instance, SelectionDivergenceClass): |
814 | 1452 |
step = self.ExtractDivergenceInput(instance, pou) |
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1453 |
if step is not None: |
1297 | 1454 |
if isinstance(step, StepClass): |
814 | 1455 |
steps.append(step) |
1297 | 1456 |
elif isinstance(step, SimultaneousConvergenceClass): |
814 | 1457 |
steps.extend(self.ExtractConvergenceInputs(step, pou)) |
1297 | 1458 |
elif isinstance(instance, SimultaneousConvergenceClass): |
814 | 1459 |
steps.extend(self.ExtractConvergenceInputs(instance, pou)) |
1460 |
transition_infos = {"id" : transition.getlocalId(), |
|
1461 |
"priority": transition.getpriority(), |
|
1462 |
"from": [], |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1463 |
"to" : [], |
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1464 |
"content": []} |
889
ac18acb6917f
Fix bug when using feedback loop in SFC program instead of jump
Laurent Bessard
parents:
883
diff
changeset
|
1465 |
self.SFCNetworks["Transitions"][transition] = transition_infos |
814 | 1466 |
transitionValues = transition.getconditionContent() |
1467 |
if transitionValues["type"] == "inline": |
|
1468 |
transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ()), |
|
1469 |
(transitionValues["value"], (self.TagName, "transition", transition.getlocalId(), "inline")), |
|
1470 |
(";\n", ())] |
|
1471 |
elif transitionValues["type"] == "reference": |
|
1472 |
transitionContent = pou.gettransition(transitionValues["value"]) |
|
1473 |
transitionType = transitionContent.getbodyType() |
|
1474 |
transitionBody = transitionContent.getbody() |
|
1475 |
previous_tagname = self.TagName |
|
1476 |
self.TagName = self.ParentGenerator.Controler.ComputePouTransitionName(self.Name, transitionValues["value"]) |
|
1477 |
if transitionType == "IL": |
|
1478 |
transition_infos["content"] = [(":\n", ()), |
|
1297 | 1479 |
(ReIndentText(transitionBody.getanyText(), len(self.CurrentIndent)), (self.TagName, "body", len(self.CurrentIndent)))] |
814 | 1480 |
elif transitionType == "ST": |
1481 |
transition_infos["content"] = [("\n", ()), |
|
1297 | 1482 |
(ReIndentText(transitionBody.getanyText(), len(self.CurrentIndent)), (self.TagName, "body", len(self.CurrentIndent)))] |
814 | 1483 |
else: |
1484 |
for instance in transitionBody.getcontentInstances(): |
|
1322
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1485 |
if isinstance(instance, OutVariableClass) and instance.getexpression() == transitionValues["value"]\ |
0a9227f743b3
Fixed xmlclass for working with included files, adding support for SimpleType elements and solving ambiguity in extension class when different elements share the same name and parent name
Laurent Bessard
parents:
1315
diff
changeset
|
1486 |
or isinstance(instance, CoilClass) and instance.getvariable() == transitionValues["value"]: |
814 | 1487 |
connections = instance.connectionPointIn.getconnections() |
1488 |
if connections is not None: |
|
1489 |
expression = self.ComputeExpression(transitionBody, connections) |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1490 |
if expression is not None: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1491 |
transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())] |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1492 |
self.SFCComputedBlocks += self.Program |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1493 |
self.Program = [] |
814 | 1494 |
if not transition_infos.has_key("content"): |
1495 |
raise PLCGenException, _("Transition \"%s\" body must contain an output variable or coil referring to its name") % transitionValues["value"] |
|
1496 |
self.TagName = previous_tagname |
|
1497 |
elif transitionValues["type"] == "connection": |
|
1498 |
body = pou.getbody() |
|
1499 |
if isinstance(body, ListType): |
|
1500 |
body = body[0] |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1501 |
connections = transitionValues["value"].getconnections() |
814 | 1502 |
if connections is not None: |
1503 |
expression = self.ComputeExpression(body, connections) |
|
1239
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1504 |
if expression is not None: |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1505 |
transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())] |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1506 |
self.SFCComputedBlocks += self.Program |
d1f6ea56555d
Fixed bug when generating ST code and connection is broken in POU using graphical language
Laurent Bessard
parents:
1183
diff
changeset
|
1507 |
self.Program = [] |
814 | 1508 |
for step in steps: |
1509 |
self.GenerateSFCStep(step, pou) |
|
1510 |
step_name = step.getname() |
|
1511 |
if step_name in self.SFCNetworks["Steps"].keys(): |
|
1512 |
transition_infos["from"].append([(step_name, (self.TagName, "transition", transition.getlocalId(), "from", step.getlocalId()))]) |
|
1513 |
self.SFCNetworks["Steps"][step_name]["transitions"].append(transition) |
|
1514 |
||
1515 |
def ComputeSFCStep(self, step_name): |
|
1516 |
if step_name in self.SFCNetworks["Steps"].keys(): |
|
1517 |
step_infos = self.SFCNetworks["Steps"].pop(step_name) |
|
1518 |
self.Program += [(self.CurrentIndent, ())] |
|
1519 |
if step_infos["initial"]: |
|
1520 |
self.Program += [("INITIAL_", ())] |
|
1521 |
self.Program += [("STEP ", ()), |
|
1522 |
(step_name, (self.TagName, "step", step_infos["id"], "name")), |
|
1523 |
(":\n", ())] |
|
1524 |
actions = [] |
|
1525 |
self.IndentRight() |
|
1526 |
for action_infos in step_infos["actions"]: |
|
1527 |
if action_infos.get("id", None) is not None: |
|
1528 |
action_info = (self.TagName, "action_block", action_infos["id"], "action", action_infos["num"]) |
|
1529 |
else: |
|
1530 |
action_info = () |
|
1531 |
actions.append(action_infos["content"]) |
|
1532 |
self.Program += [(self.CurrentIndent, ()), |
|
1533 |
(action_infos["content"], action_info + ("reference",)), |
|
1534 |
("(", ()), |
|
1535 |
(action_infos["qualifier"], action_info + ("qualifier",))] |
|
1536 |
if "duration" in action_infos: |
|
1537 |
self.Program += [(", ", ()), |
|
1538 |
(action_infos["duration"], action_info + ("duration",))] |
|
1539 |
if "indicator" in action_infos: |
|
1540 |
self.Program += [(", ", ()), |
|
1541 |
(action_infos["indicator"], action_info + ("indicator",))] |
|
1542 |
self.Program += [(");\n", ())] |
|
1543 |
self.IndentLeft() |
|
1544 |
self.Program += [("%sEND_STEP\n\n"%self.CurrentIndent, ())] |
|
1545 |
for action in actions: |
|
1546 |
self.ComputeSFCAction(action) |
|
1547 |
for transition in step_infos["transitions"]: |
|
1548 |
self.ComputeSFCTransition(transition) |
|
1549 |
||
1550 |
def ComputeSFCAction(self, action_name): |
|
1551 |
if action_name in self.SFCNetworks["Actions"].keys(): |
|
1552 |
action_content, action_info = self.SFCNetworks["Actions"].pop(action_name) |
|
1553 |
self.Program += [("%sACTION "%self.CurrentIndent, ()), |
|
1554 |
(action_name, action_info), |
|
1298
f034fb2b1aab
Fixed SFC block edition and SFC to SFC_textual code generating
Laurent Bessard
parents:
1297
diff
changeset
|
1555 |
(":\n", ())] |
814 | 1556 |
self.Program += action_content |
1557 |
self.Program += [("%sEND_ACTION\n\n"%self.CurrentIndent, ())] |
|
1558 |
||
1559 |
def ComputeSFCTransition(self, transition): |
|
1560 |
if transition in self.SFCNetworks["Transitions"].keys(): |
|
1561 |
transition_infos = self.SFCNetworks["Transitions"].pop(transition) |
|
1562 |
self.Program += [("%sTRANSITION"%self.CurrentIndent, ())] |
|
1563 |
if transition_infos["priority"] != None: |
|
1564 |
self.Program += [(" (PRIORITY := ", ()), |
|
1565 |
("%d"%transition_infos["priority"], (self.TagName, "transition", transition_infos["id"], "priority")), |
|
1566 |
(")", ())] |
|
1567 |
self.Program += [(" FROM ", ())] |
|
1568 |
if len(transition_infos["from"]) > 1: |
|
1569 |
self.Program += [("(", ())] |
|
1570 |
self.Program += JoinList([(", ", ())], transition_infos["from"]) |
|
1571 |
self.Program += [(")", ())] |
|
1572 |
elif len(transition_infos["from"]) == 1: |
|
1573 |
self.Program += transition_infos["from"][0] |
|
1574 |
else: |
|
1575 |
raise PLCGenException, _("Transition with content \"%s\" not connected to a previous step in \"%s\" POU")%(transition_infos["content"], self.Name) |
|
1576 |
self.Program += [(" TO ", ())] |
|
1577 |
if len(transition_infos["to"]) > 1: |
|
1578 |
self.Program += [("(", ())] |
|
1579 |
self.Program += JoinList([(", ", ())], transition_infos["to"]) |
|
1580 |
self.Program += [(")", ())] |
|
1581 |
elif len(transition_infos["to"]) == 1: |
|
1582 |
self.Program += transition_infos["to"][0] |
|
1583 |
else: |
|
1584 |
raise PLCGenException, _("Transition with content \"%s\" not connected to a next step in \"%s\" POU")%(transition_infos["content"], self.Name) |
|
1585 |
self.Program += transition_infos["content"] |
|
1586 |
self.Program += [("%sEND_TRANSITION\n\n"%self.CurrentIndent, ())] |
|
1587 |
for [(step_name, step_infos)] in transition_infos["to"]: |
|
1588 |
self.ComputeSFCStep(step_name) |
|
1589 |
||
1590 |
def GenerateProgram(self, pou): |
|
1591 |
self.ComputeInterface(pou) |
|
1592 |
self.ComputeConnectionTypes(pou) |
|
1593 |
self.ComputeProgram(pou) |
|
1594 |
||
1595 |
program = [("%s "%self.Type, ()), |
|
1596 |
(self.Name, (self.TagName, "name"))] |
|
1310
3d7fa2257b24
Removed obsolete process for customizing block code generated in extensions
Laurent Bessard
parents:
1298
diff
changeset
|
1597 |
if self.ReturnType is not None: |
814 | 1598 |
program += [(" : ", ()), |
1599 |
(self.ReturnType, (self.TagName, "return"))] |
|
1600 |
program += [("\n", ())] |
|
1601 |
if len(self.Interface) == 0: |
|
1602 |
raise PLCGenException, _("No variable defined in \"%s\" POU")%self.Name |
|
1603 |
if len(self.Program) == 0 : |
|
1604 |
raise PLCGenException, _("No body defined in \"%s\" POU")%self.Name |
|
1605 |
var_number = 0 |
|
1606 |
for list_type, option, located, variables in self.Interface: |
|
1607 |
variable_type = errorVarTypes.get(list_type, "var_local") |
|
1608 |
program += [(" %s"%list_type, ())] |
|
1609 |
if option is not None: |
|
1610 |
program += [(" %s"%option, (self.TagName, variable_type, (var_number, var_number + len(variables)), option.lower()))] |
|
1611 |
program += [("\n", ())] |
|
1612 |
for var_type, var_name, var_address, var_initial in variables: |
|
1613 |
program += [(" ", ())] |
|
1614 |
if var_name: |
|
1615 |
program += [(var_name, (self.TagName, variable_type, var_number, "name")), |
|
1616 |
(" ", ())] |
|
1617 |
if var_address != None: |
|
1618 |
program += [("AT ", ()), |
|
1619 |
(var_address, (self.TagName, variable_type, var_number, "location")), |
|
1620 |
(" ", ())] |
|
1621 |
program += [(": ", ()), |
|
1622 |
(var_type, (self.TagName, variable_type, var_number, "type"))] |
|
1623 |
if var_initial != None: |
|
1624 |
program += [(" := ", ()), |
|
1625 |
(self.ParentGenerator.ComputeValue(var_initial, var_type), (self.TagName, variable_type, var_number, "initial value"))] |
|
1626 |
program += [(";\n", ())] |
|
1627 |
var_number += 1 |
|
1628 |
program += [(" END_VAR\n", ())] |
|
1629 |
program += [("\n", ())] |
|
1630 |
program += self.Program |
|
1631 |
program += [("END_%s\n\n"%self.Type, ())] |
|
1632 |
return program |
|
1633 |
||
1634 |
def GenerateCurrentProgram(controler, project, errors, warnings): |
|
1635 |
generator = ProgramGenerator(controler, project, errors, warnings) |
|
1636 |
generator.GenerateProgram() |
|
1637 |
return generator.GetGeneratedProgram() |
|
1638 |