32 "D" : ["DINT", "UDINT", "REAL", "DWORD"], |
34 "D" : ["DINT", "UDINT", "REAL", "DWORD"], |
33 "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} |
35 "L" : ["LINT", "ULINT", "LREAL", "LWORD"]} |
34 |
36 |
35 _ = lambda x:x |
37 _ = lambda x:x |
36 |
38 |
37 # Helper for emulate join on element list |
|
38 def JoinList(separator, mylist): |
|
39 if len(mylist) > 0 : |
|
40 return reduce(lambda x, y: x + separator + y, mylist) |
|
41 else : |
|
42 return mylist |
|
43 |
|
44 def generate_block(generator, block, block_infos, body, link, order=False, to_inout=False): |
|
45 body_type = body.getcontent()["name"] |
|
46 name = block.getinstanceName() |
|
47 type = block.gettypeName() |
|
48 executionOrderId = block.getexecutionOrderId() |
|
49 input_variables = block.inputVariables.getvariable() |
|
50 output_variables = block.outputVariables.getvariable() |
|
51 inout_variables = {} |
|
52 for input_variable in input_variables: |
|
53 for output_variable in output_variables: |
|
54 if input_variable.getformalParameter() == output_variable.getformalParameter(): |
|
55 inout_variables[input_variable.getformalParameter()] = "" |
|
56 input_names = [input[0] for input in block_infos["inputs"]] |
|
57 output_names = [output[0] for output in block_infos["outputs"]] |
|
58 if block_infos["type"] == "function": |
|
59 if not generator.ComputedBlocks.get(block, False) and not order: |
|
60 generator.ComputedBlocks[block] = True |
|
61 connected_vars = [] |
|
62 if not block_infos["extensible"]: |
|
63 input_connected = dict([("EN", None)] + |
|
64 [(input_name, None) for input_name in input_names]) |
|
65 for variable in input_variables: |
|
66 parameter = variable.getformalParameter() |
|
67 if input_connected.has_key(parameter): |
|
68 input_connected[parameter] = variable |
|
69 if input_connected["EN"] is None: |
|
70 input_connected.pop("EN") |
|
71 input_parameters = input_names |
|
72 else: |
|
73 input_parameters = ["EN"] + input_names |
|
74 else: |
|
75 input_connected = dict([(variable.getformalParameter(), variable) |
|
76 for variable in input_variables]) |
|
77 input_parameters = [variable.getformalParameter() |
|
78 for variable in input_variables] |
|
79 one_input_connected = False |
|
80 all_input_connected = True |
|
81 for i, parameter in enumerate(input_parameters): |
|
82 variable = input_connected.get(parameter) |
|
83 if variable is not None: |
|
84 input_info = (generator.TagName, "block", block.getlocalId(), "input", i) |
|
85 connections = variable.connectionPointIn.getconnections() |
|
86 if connections is not None: |
|
87 if parameter != "EN": |
|
88 one_input_connected = True |
|
89 if inout_variables.has_key(parameter): |
|
90 expression = generator.ComputeExpression(body, connections, executionOrderId > 0, True) |
|
91 if expression is not None: |
|
92 inout_variables[parameter] = value |
|
93 else: |
|
94 expression = generator.ComputeExpression(body, connections, executionOrderId > 0) |
|
95 if expression is not None: |
|
96 connected_vars.append(([(parameter, input_info), (" := ", ())], |
|
97 generator.ExtractModifier(variable, expression, input_info))) |
|
98 else: |
|
99 all_input_connected = False |
|
100 else: |
|
101 all_input_connected = False |
|
102 if len(output_variables) > 1 or not all_input_connected: |
|
103 vars = [name + value for name, value in connected_vars] |
|
104 else: |
|
105 vars = [value for name, value in connected_vars] |
|
106 if one_input_connected: |
|
107 for i, variable in enumerate(output_variables): |
|
108 parameter = variable.getformalParameter() |
|
109 if not inout_variables.has_key(parameter) and parameter in output_names + ["", "ENO"]: |
|
110 if variable.getformalParameter() == "": |
|
111 variable_name = "%s%d"%(type, block.getlocalId()) |
|
112 else: |
|
113 variable_name = "%s%d_%s"%(type, block.getlocalId(), parameter) |
|
114 if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] is not None or generator.Interface[-1][2]: |
|
115 generator.Interface.append(("VAR", None, False, [])) |
|
116 if variable.connectionPointOut in generator.ConnectionTypes: |
|
117 generator.Interface[-1][3].append((generator.ConnectionTypes[variable.connectionPointOut], variable_name, None, None)) |
|
118 else: |
|
119 generator.Interface[-1][3].append(("ANY", variable_name, None, None)) |
|
120 if len(output_variables) > 1 and parameter not in ["", "OUT"]: |
|
121 vars.append([(parameter, (generator.TagName, "block", block.getlocalId(), "output", i)), |
|
122 (" => %s"%variable_name, ())]) |
|
123 else: |
|
124 output_info = (generator.TagName, "block", block.getlocalId(), "output", i) |
|
125 output_name = variable_name |
|
126 generator.Program += [(generator.CurrentIndent, ()), |
|
127 (output_name, output_info), |
|
128 (" := ", ()), |
|
129 (type, (generator.TagName, "block", block.getlocalId(), "type")), |
|
130 ("(", ())] |
|
131 generator.Program += JoinList([(", ", ())], vars) |
|
132 generator.Program += [(");\n", ())] |
|
133 else: |
|
134 generator.Warnings.append(_("\"%s\" function cancelled in \"%s\" POU: No input connected")%(type, generator.TagName.split("::")[-1])) |
|
135 elif block_infos["type"] == "functionBlock": |
|
136 if not generator.ComputedBlocks.get(block, False) and not order: |
|
137 generator.ComputedBlocks[block] = True |
|
138 vars = [] |
|
139 offset_idx = 0 |
|
140 for variable in input_variables: |
|
141 parameter = variable.getformalParameter() |
|
142 if parameter in input_names or parameter == "EN": |
|
143 if parameter == "EN": |
|
144 input_idx = 0 |
|
145 offset_idx = 1 |
|
146 else: |
|
147 input_idx = offset_idx + input_names.index(parameter) |
|
148 input_info = (generator.TagName, "block", block.getlocalId(), "input", input_idx) |
|
149 connections = variable.connectionPointIn.getconnections() |
|
150 if connections is not None: |
|
151 expression = generator.ComputeExpression(body, connections, executionOrderId > 0, inout_variables.has_key(parameter)) |
|
152 if expression is not None: |
|
153 vars.append([(parameter, input_info), |
|
154 (" := ", ())] + generator.ExtractModifier(variable, expression, input_info)) |
|
155 generator.Program += [(generator.CurrentIndent, ()), |
|
156 (name, (generator.TagName, "block", block.getlocalId(), "name")), |
|
157 ("(", ())] |
|
158 generator.Program += JoinList([(", ", ())], vars) |
|
159 generator.Program += [(");\n", ())] |
|
160 |
|
161 if link: |
|
162 connectionPoint = link.getposition()[-1] |
|
163 output_parameter = link.getformalParameter() |
|
164 else: |
|
165 connectionPoint = None |
|
166 output_parameter = None |
|
167 |
|
168 output_variable = None |
|
169 output_idx = 0 |
|
170 if output_parameter is not None: |
|
171 if output_parameter in output_names or output_parameter == "ENO": |
|
172 for variable in output_variables: |
|
173 if variable.getformalParameter() == output_parameter: |
|
174 output_variable = variable |
|
175 if output_parameter != "ENO": |
|
176 output_idx = output_names.index(output_parameter) |
|
177 else: |
|
178 for i, variable in enumerate(output_variables): |
|
179 blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY() |
|
180 if (not connectionPoint or |
|
181 block.getx() + blockPointx == connectionPoint.getx() and |
|
182 block.gety() + blockPointy == connectionPoint.gety()): |
|
183 output_variable = variable |
|
184 output_parameter = variable.getformalParameter() |
|
185 output_idx = i |
|
186 |
|
187 if output_variable is not None: |
|
188 if block_infos["type"] == "function": |
|
189 output_info = (generator.TagName, "block", block.getlocalId(), "output", output_idx) |
|
190 if inout_variables.has_key(output_parameter): |
|
191 output_value = inout_variables[output_parameter] |
|
192 else: |
|
193 if output_parameter == "": |
|
194 output_name = "%s%d"%(type, block.getlocalId()) |
|
195 else: |
|
196 output_name = "%s%d_%s"%(type, block.getlocalId(), output_parameter) |
|
197 output_value = [(output_name, output_info)] |
|
198 return generator.ExtractModifier(output_variable, output_value, output_info) |
|
199 |
|
200 if block_infos["type"] == "functionBlock": |
|
201 output_info = (generator.TagName, "block", block.getlocalId(), "output", output_idx) |
|
202 output_name = generator.ExtractModifier(output_variable, [("%s.%s"%(name, output_parameter), output_info)], output_info) |
|
203 if to_inout: |
|
204 variable_name = "%s_%s"%(name, output_parameter) |
|
205 if not generator.IsAlreadyDefined(variable_name): |
|
206 if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] is not None or generator.Interface[-1][2]: |
|
207 generator.Interface.append(("VAR", None, False, [])) |
|
208 if variable.connectionPointOut in generator.ConnectionTypes: |
|
209 generator.Interface[-1][3].append( |
|
210 (generator.ConnectionTypes[output_variable.connectionPointOut], variable_name, None, None)) |
|
211 else: |
|
212 generator.Interface[-1][3].append(("ANY", variable_name, None, None)) |
|
213 generator.Program += [(generator.CurrentIndent, ()), |
|
214 ("%s := "%variable_name, ())] |
|
215 generator.Program += output_name |
|
216 generator.Program += [(";\n", ())] |
|
217 return [(variable_name, ())] |
|
218 return output_name |
|
219 if link is not None: |
|
220 if output_parameter is None: |
|
221 output_parameter = "" |
|
222 if name: |
|
223 blockname = "%s(%s)" % (name, type) |
|
224 else: |
|
225 blockname = type |
|
226 raise ValueError, _("No output %s variable found in block %s in POU %s. Connection must be broken") % \ |
|
227 (output_parameter, blockname, generator.Name) |
|
228 |
|
229 def initialise_block(type, name, block = None): |
|
230 return [(type, name, None, None)] |
|
231 |
|
232 #------------------------------------------------------------------------------- |
39 #------------------------------------------------------------------------------- |
233 # Function Block Types definitions |
40 # Function Block Types definitions |
234 #------------------------------------------------------------------------------- |
41 #------------------------------------------------------------------------------- |
235 |
42 |
|
43 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0] |
|
44 |
|
45 StdBlockLibrary, error = LoadProject( |
|
46 os.path.join(ScriptDirectory, "Standard_Function_Blocks.xml")) |
|
47 AddnlBlockLibrary, error = LoadProject( |
|
48 os.path.join(ScriptDirectory, "Additional_Function_Blocks.xml")) |
|
49 |
|
50 StdBlockComments = { |
|
51 "SR": _("SR bistable\nThe SR bistable is a latch where the Set dominates."), |
|
52 "RS": _("RS bistable\nThe RS bistable is a latch where the Reset dominates."), |
|
53 "SEMA": _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."), |
|
54 "R_TRIG": _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected."), |
|
55 "F_TRIG": _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected."), |
|
56 "CTU": _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."), |
|
57 "CTD": _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."), |
|
58 "CTUD": _("Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input and down on the other."), |
|
59 "TP": _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."), |
|
60 "TON": _("On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true."), |
|
61 "TOF": _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."), |
|
62 "RTC": _("Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on."), |
|
63 "INTEGRAL": _("Integral\nThe integral function block integrates the value of input XIN over time."), |
|
64 "DERIVATIVE": _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."), |
|
65 "PID": _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."), |
|
66 "RAMP": _("Ramp\nThe RAMP function block is modelled on example given in the standard."), |
|
67 "HYSTERESIS": _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."), |
|
68 } |
|
69 |
|
70 for block_type in ["CTU", "CTD", "CTUD"]: |
|
71 for return_type in ["DINT", "LINT", "UDINT", "ULINT"]: |
|
72 StdBlockComments["%s_%s" % (block_type, return_type)] = StdBlockComments[block_type] |
|
73 |
|
74 def GetBlockInfos(pou): |
|
75 infos = pou.getblockInfos() |
|
76 infos["comment"] = StdBlockComments[infos["name"]] |
|
77 infos["inputs"] = [ |
|
78 (var_name, var_type, "rising") |
|
79 if var_name in ["CU", "CD"] |
|
80 else (var_name, var_type, var_modifier) |
|
81 for var_name, var_type, var_modifier in infos["inputs"]] |
|
82 return infos |
236 |
83 |
237 """ |
84 """ |
238 Ordored list of common Function Blocks defined in the IEC 61131-3 |
85 Ordored list of common Function Blocks defined in the IEC 61131-3 |
239 Each block have this attributes: |
86 Each block have this attributes: |
240 - "name" : The block name |
87 - "name" : The block name |
248 - The name |
95 - The name |
249 - The data type |
96 - The data type |
250 - The default modifier which can be "none", "negated", "rising" or "falling" |
97 - The default modifier which can be "none", "negated", "rising" or "falling" |
251 """ |
98 """ |
252 |
99 |
253 BlockTypes = [{"name" : _("Standard function blocks"), "list": |
100 StdBlckLst = [{"name" : _("Standard function blocks"), "list": |
254 [{"name" : "SR", "type" : "functionBlock", "extensible" : False, |
101 [GetBlockInfos(pou) for pou in StdBlockLibrary.getpous()]}, |
255 "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], |
|
256 "outputs" : [("Q1","BOOL","none")], |
|
257 "comment" : _("SR bistable\nThe SR bistable is a latch where the Set dominates."), |
|
258 "generate" : generate_block, "initialise" : initialise_block}, |
|
259 {"name" : "RS", "type" : "functionBlock", "extensible" : False, |
|
260 "inputs" : [("S","BOOL","none"),("R1","BOOL","none")], |
|
261 "outputs" : [("Q1","BOOL","none")], |
|
262 "comment" : _("RS bistable\nThe RS bistable is a latch where the Reset dominates."), |
|
263 "generate" : generate_block, "initialise" : initialise_block}, |
|
264 {"name" : "SEMA", "type" : "functionBlock", "extensible" : False, |
|
265 "inputs" : [("CLAIM","BOOL","none"),("RELEASE","BOOL","none")], |
|
266 "outputs" : [("BUSY","BOOL","none")], |
|
267 "comment" : _("Semaphore\nThe semaphore provides a mechanism to allow software elements mutually exclusive access to certain ressources."), |
|
268 "generate" : generate_block, "initialise" : initialise_block}, |
|
269 {"name" : "R_TRIG", "type" : "functionBlock", "extensible" : False, |
|
270 "inputs" : [("CLK","BOOL","none")], |
|
271 "outputs" : [("Q","BOOL","none")], |
|
272 "comment" : _("Rising edge detector\nThe output produces a single pulse when a rising edge is detected."), |
|
273 "generate" : generate_block, "initialise" : initialise_block}, |
|
274 {"name" : "F_TRIG", "type" : "functionBlock", "extensible" : False, |
|
275 "inputs" : [("CLK","BOOL","none")], |
|
276 "outputs" : [("Q","BOOL","none")], |
|
277 "comment" : _("Falling edge detector\nThe output produces a single pulse when a falling edge is detected."), |
|
278 "generate" : generate_block, "initialise" : initialise_block}, |
|
279 {"name" : "CTU", "type" : "functionBlock", "extensible" : False, |
|
280 "inputs" : [("CU","BOOL","rising"),("R","BOOL","none"),("PV","INT","none")], |
|
281 "outputs" : [("Q","BOOL","none"),("CV","INT","none")], |
|
282 "comment" : _("Up-counter\nThe up-counter can be used to signal when a count has reached a maximum value."), |
|
283 "generate" : generate_block, "initialise" : initialise_block}, |
|
284 {"name" : "CTD", "type" : "functionBlock", "extensible" : False, |
|
285 "inputs" : [("CD","BOOL","rising"),("LD","BOOL","none"),("PV","INT","none")], |
|
286 "outputs" : [("Q","BOOL","none"),("CV","INT","none")], |
|
287 "comment" : _("Down-counter\nThe down-counter can be used to signal when a count has reached zero, on counting down from a preset value."), |
|
288 "generate" : generate_block, "initialise" : initialise_block}, |
|
289 {"name" : "CTUD", "type" : "functionBlock", "extensible" : False, |
|
290 "inputs" : [("CU","BOOL","rising"),("CD","BOOL","rising"),("R","BOOL","none"),("LD","BOOL","none"),("PV","INT","none")], |
|
291 "outputs" : [("QU","BOOL","none"),("QD","BOOL","none"),("CV","INT","none")], |
|
292 "comment" : _("Up-down counter\nThe up-down counter has two inputs CU and CD. It can be used to both count up on one input and down on the other."), |
|
293 "generate" : generate_block, "initialise" : initialise_block}, |
|
294 {"name" : "TP", "type" : "functionBlock", "extensible" : False, |
|
295 "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], |
|
296 "outputs" : [("Q","BOOL","none"),("ET","TIME","none")], |
|
297 "comment" : _("Pulse timer\nThe pulse timer can be used to generate output pulses of a given time duration."), |
|
298 "generate" : generate_block, "initialise" : initialise_block}, |
|
299 {"name" : "TON", "type" : "functionBlock", "extensible" : False, |
|
300 "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], |
|
301 "outputs" : [("Q","BOOL","none"),("ET","TIME","none")], |
|
302 "comment" : _("On-delay timer\nThe on-delay timer can be used to delay setting an output true, for fixed period after an input becomes true."), |
|
303 "generate" : generate_block, "initialise" : initialise_block}, |
|
304 {"name" : "TOF", "type" : "functionBlock", "extensible" : False, |
|
305 "inputs" : [("IN","BOOL","none"),("PT","TIME","none")], |
|
306 "outputs" : [("Q","BOOL","none"),("ET","TIME","none")], |
|
307 "comment" : _("Off-delay timer\nThe off-delay timer can be used to delay setting an output false, for fixed period after input goes false."), |
|
308 "generate" : generate_block, "initialise" : initialise_block}, |
|
309 ]}, |
|
310 {"name" : _("Additional function blocks"), "list": |
102 {"name" : _("Additional function blocks"), "list": |
311 [{"name" : "RTC", "type" : "functionBlock", "extensible" : False, |
103 [GetBlockInfos(pou) for pou in AddnlBlockLibrary.getpous()]}, |
312 "inputs" : [("IN","BOOL","none"),("PDT","DATE_AND_TIME","none")], |
|
313 "outputs" : [("Q","BOOL","none"),("CDT","DATE_AND_TIME","none")], |
|
314 "comment" : _("Real time clock\nThe real time clock has many uses including time stamping, setting dates and times of day in batch reports, in alarm messages and so on."), |
|
315 "generate" : generate_block, "initialise" : initialise_block}, |
|
316 {"name" : "INTEGRAL", "type" : "functionBlock", "extensible" : False, |
|
317 "inputs" : [("RUN","BOOL","none"),("R1","BOOL","none"),("XIN","REAL","none"),("X0","REAL","none"),("CYCLE","TIME","none")], |
|
318 "outputs" : [("Q","BOOL","none"),("XOUT","REAL","none")], |
|
319 "comment" : _("Integral\nThe integral function block integrates the value of input XIN over time."), |
|
320 "generate" : generate_block, "initialise" : initialise_block}, |
|
321 {"name" : "DERIVATIVE", "type" : "functionBlock", "extensible" : False, |
|
322 "inputs" : [("RUN","BOOL","none"),("XIN","REAL","none"),("CYCLE","TIME","none")], |
|
323 "outputs" : [("XOUT","REAL","none")], |
|
324 "comment" : _("Derivative\nThe derivative function block produces an output XOUT proportional to the rate of change of the input XIN."), |
|
325 "generate" : generate_block, "initialise" : initialise_block}, |
|
326 {"name" : "PID", "type" : "functionBlock", "extensible" : False, |
|
327 "inputs" : [("AUTO","BOOL","none"),("PV","REAL","none"),("SP","REAL","none"),("X0","REAL","none"),("KP","REAL","none"),("TR","REAL","none"),("TD","REAL","none"),("CYCLE","TIME","none")], |
|
328 "outputs" : [("XOUT","REAL","none")], |
|
329 "comment" : _("PID\nThe PID (proportional, Integral, Derivative) function block provides the classical three term controller for closed loop control."), |
|
330 "generate" : generate_block, "initialise" : initialise_block}, |
|
331 {"name" : "RAMP", "type" : "functionBlock", "extensible" : False, |
|
332 "inputs" : [("RUN","BOOL","none"),("X0","REAL","none"),("X1","REAL","none"),("TR","TIME","none"),("CYCLE","TIME","none")], |
|
333 "outputs" : [("BUSY","BOOL","none"),("XOUT","REAL","none")], |
|
334 "comment" : _("Ramp\nThe RAMP function block is modelled on example given in the standard."), |
|
335 "generate" : generate_block, "initialise" : initialise_block}, |
|
336 {"name" : "HYSTERESIS", "type" : "functionBlock", "extensible" : False, |
|
337 "inputs" : [("XIN1","REAL","none"),("XIN2","REAL","none"),("EPS","REAL","none")], |
|
338 "outputs" : [("Q","BOOL","none")], |
|
339 "comment" : _("Hysteresis\nThe hysteresis function block provides a hysteresis boolean output driven by the difference of two floating point (REAL) inputs XIN1 and XIN2."), |
|
340 "generate" : generate_block, "initialise" : initialise_block}, |
|
341 ## {"name" : "RATIO_MONITOR", "type" : "functionBlock", "extensible" : False, |
|
342 ## "inputs" : [("PV1","REAL","none"),("PV2","REAL","none"),("RATIO","REAL","none"),("TIMON","TIME","none"),("TIMOFF","TIME","none"),("TOLERANCE","BOOL","none"),("RESET","BOOL","none"),("CYCLE","TIME","none")], |
|
343 ## "outputs" : [("ALARM","BOOL","none"),("TOTAL_ERR","BOOL","none")], |
|
344 ## "comment" : _("Ratio monitor\nThe ratio_monitor function block checks that one process value PV1 is always a given ratio (defined by input RATIO) of a second process value PV2."), |
|
345 ## "generate" : generate_block, "initialise" : initialise_block} |
|
346 ]}, |
|
347 ] |
104 ] |
348 |
105 |
349 |
106 |
350 #------------------------------------------------------------------------------- |
107 #------------------------------------------------------------------------------- |
351 # Data Types definitions |
108 # Data Types definitions |
659 else: |
414 else: |
660 raise "First function must be in a category" |
415 raise "First function must be in a category" |
661 |
416 |
662 return Standard_Functions_Decl |
417 return Standard_Functions_Decl |
663 |
418 |
664 std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(os.path.split(__file__)[0],"iec_std.csv"))))#, True) |
419 std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(ScriptDirectory,"iec_std.csv"))))#, True) |
665 |
420 |
666 BlockTypes.extend(std_decl) |
421 StdBlckLst.extend(std_decl) |
667 |
422 |
668 for section in BlockTypes: |
423 # Dictionary to speedup block type fetching by name |
|
424 StdBlckDct = OrderedDict() |
|
425 |
|
426 for section in StdBlckLst: |
669 for desc in section["list"]: |
427 for desc in section["list"]: |
670 words = desc["comment"].split('"') |
428 words = desc["comment"].split('"') |
671 if len(words) > 1: |
429 if len(words) > 1: |
672 desc["comment"] = words[1] |
430 desc["comment"] = words[1] |
673 desc["usage"] = ( |
431 desc["usage"] = ("\n (%s) => (%s)" % |
674 "\n (" + |
432 (", ".join(["%s:%s" % (input[1], input[0]) |
675 str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["inputs"]]).strip("[]").replace("'",'') + |
433 for input in desc["inputs"]]), |
676 " ) => (" + |
434 ", ".join(["%s:%s" % (output[1], output[0]) |
677 str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["outputs"]]).strip("[]").replace("'",'') + |
435 for output in desc["outputs"]]))) |
678 " )") |
436 BlkLst = StdBlckDct.setdefault(desc["name"],[]) |
679 |
437 BlkLst.append((section["name"], desc)) |
680 |
438 |
681 #------------------------------------------------------------------------------- |
439 #------------------------------------------------------------------------------- |
682 # Languages Keywords |
440 # Languages Keywords |
683 #------------------------------------------------------------------------------- |
441 #------------------------------------------------------------------------------- |
684 |
442 |
685 |
443 |
686 # Keywords for Pou Declaration |
444 # Keywords for Pou Declaration |
687 POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"] |
445 POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"] |
688 POU_BLOCK_END_KEYWORDS = ["END_FUNCTION", "END_FUNCTION_BLOCK", "END_PROGRAM"] |
446 POU_BLOCK_END_KEYWORDS = ["END_FUNCTION", "END_FUNCTION_BLOCK", "END_PROGRAM"] |
689 POU_KEYWORDS = ["EN", "ENO", "F_EDGE", "R_EDGE"] + POU_BLOCK_START_KEYWORDS + POU_BLOCK_END_KEYWORDS |
447 POU_KEYWORDS = ["EN", "ENO", "F_EDGE", "R_EDGE"] + POU_BLOCK_START_KEYWORDS + POU_BLOCK_END_KEYWORDS |
690 for category in BlockTypes: |
448 for category in StdBlckLst: |
691 for block in category["list"]: |
449 for block in category["list"]: |
692 if block["name"] not in POU_KEYWORDS: |
450 if block["name"] not in POU_KEYWORDS: |
693 POU_KEYWORDS.append(block["name"]) |
451 POU_KEYWORDS.append(block["name"]) |
694 |
452 |
695 |
453 |