robotransform 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
robotransform/__init__.py CHANGED
@@ -0,0 +1,7 @@
1
+ from robotransform.main import Store, MapleKStore, dump_messages, dump_logical
2
+ __all__ = (
3
+ "Store",
4
+ "MapleKStore",
5
+ "dump_messages",
6
+ "dump_logical",
7
+ )
robotransform/concepts.py CHANGED
@@ -1,225 +1,510 @@
1
1
  from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
2
4
  from typing import Type as ClassType, Any, List, Optional, Union
3
5
 
4
6
 
5
- # TODO Flatten this a little bit
7
+ @dataclass
8
+ class ControllerDef:
9
+ name: str
10
+ uses: List[QualifiedName]
11
+ provides: List[QualifiedName]
12
+ requires: List[QualifiedName]
13
+ connections: List[Connection]
14
+ machines: List[Union[StateMachineDef, StateMachineRef]]
15
+ events: List[Event]
16
+ operations: List[Operation]
17
+ variables: List[Variable]
18
+ parent: Any
6
19
 
7
- class Node:
8
- def __init__(self, parent: Optional[Any] = None):
9
- self.parent = parent
10
20
 
21
+ @dataclass
22
+ class Connection:
23
+ source: QualifiedName
24
+ event_source: QualifiedName
25
+ target: QualifiedName
26
+ event_target: QualifiedName
27
+ asynchronous: bool
28
+ bidirectional: bool
29
+ parent: Any
11
30
 
12
- class ControllerDef(Node):
13
- def __init__(self, name, uses, provides, requires, connections, machines, events, operations, variables,
14
- parent: Any):
15
- super().__init__(parent)
16
- self.name = name
17
- self.uses = uses
18
- self.provides = provides
19
- self.requires = requires
20
- self.connections = connections
21
- self.machines = machines
22
- self.events = events
23
- self.operations = operations
24
- self.variables = variables
25
31
 
26
- def __repr__(self):
27
- use_count = len(self.uses)
28
- provide_count = len(self.provides)
29
- require_count = len(self.requires)
30
- connection_count = len(self.connections)
31
- machine_count = len(self.machines)
32
- event_count = len(self.events)
33
- operation_count = len(self.operations)
34
- variable_count = len(self.variables)
35
- return f"{self.name}: ({use_count} uses), ({provide_count} provides), ({require_count} requires), ({connection_count} connections), ({machine_count} machines, ({event_count} events), ({operation_count} operations), ({variable_count} variables)"
36
-
37
-
38
- class Variable(Node):
39
- def __init__(self, name: str, kind, initial, parent: Any):
40
- super().__init__(parent)
41
- self.name = name
42
- self.type = kind
43
- self.initial = initial
44
-
45
-
46
- class Type(Node):
47
- def __init__(self, source: FunctionType, target: Optional[Type], parent: Any):
48
- super().__init__(parent)
49
- self.source = source
50
- self.target = target
32
+ @dataclass
33
+ class StateMachineRef:
34
+ name: str
35
+ ref: QualifiedName
36
+ parent: Any
37
+
38
+
39
+ @dataclass
40
+ class Operation:
41
+ operation: Union[OperationRef, OperationDef]
42
+ parent: Any
43
+
44
+
45
+ @dataclass
46
+ class OperationRef:
47
+ name: str
48
+ ref: QualifiedName
49
+ parent: Any
50
+
51
+
52
+ @dataclass
53
+ class Variable:
54
+ name: str
55
+ type: Type
56
+ parent: Any
57
+ initial: Optional[Expression] = None
58
+ modifier: Optional[VariableModifier] = None
59
+
60
+
61
+ @dataclass
62
+ class Expression:
63
+ expression: Union[ForAll, Exists, LambdaExp, Iff]
64
+ parent: Any
65
+
66
+
67
+ @dataclass
68
+ class ForAll:
69
+ variables: List[Variable]
70
+ predicate: Expression
71
+ parent: Any
72
+ suchthat: Optional[Expression]
73
+
74
+
75
+ @dataclass
76
+ class Exists:
77
+ variables: List[Variable]
78
+ unique: bool
79
+ predicate: Expression
80
+ parent: Any
81
+ suchthat: Optional[Expression]
82
+
83
+
84
+ @dataclass
85
+ class LambdaExp:
86
+ variables: List[Variable]
87
+ predicate: Expression
88
+ parent: Any
89
+ suchthat: Optional[Expression]
90
+
91
+
92
+ @dataclass
93
+ class Iff:
94
+ left: Implies
95
+ right: List[Implies]
96
+ parent: Any
97
+
98
+
99
+ @dataclass
100
+ class Implies:
101
+ left: Or
102
+ right: List[Or]
103
+ parent: Any
104
+
105
+
106
+ @dataclass
107
+ class Or:
108
+ left: And
109
+ right: List[And]
110
+ parent: Any
111
+
112
+
113
+ @dataclass
114
+ class And:
115
+ left: Not
116
+ right: List[Not]
117
+ parent: Any
118
+
119
+
120
+ @dataclass
121
+ class Not:
122
+ exp: Union[Not, Comp]
123
+ parent: Any
124
+
125
+
126
+ @dataclass
127
+ class Comp:
128
+ left: DefiniteDescription
129
+
130
+ parent: Any
131
+ comp: Optional[Comparison] # TODO Unify these
132
+ right: Optional[DefiniteDescription] # TODO Unify these
133
+ set: Optional[DefiniteDescription] # TODO Unify these
134
+
135
+
136
+ @dataclass
137
+ class DefiniteDescription:
138
+ variables: List[Variable]
139
+ expression: Union[Expression, LetExpression]
140
+ parent: Any
141
+ suchthat: Optional[Expression]
142
+
143
+
144
+ @dataclass
145
+ class Comparison:
146
+ operator: str
147
+ right: DefiniteDescription
148
+ parent: Any
149
+
150
+
151
+ @dataclass
152
+ class LetExpression:
153
+ declarations: List[Declaration]
154
+ expression: Union[LetExpression, IfExpression]
155
+ parent: Any
156
+
157
+
158
+ @dataclass
159
+ class Declaration:
160
+ name: str
161
+ expression: Expression
162
+ parent: Any
163
+
164
+
165
+ @dataclass
166
+ class IfExpression:
167
+ condition: Expression
168
+ ifexp: Expression
169
+ elseexp: Expression
170
+ expression: TypedExpression
171
+ parent: Any
172
+
173
+
174
+ @dataclass
175
+ class TypedExpression:
176
+ expression: PlusMinus
177
+
178
+ parent: Any
179
+ type: Optional[Type]
180
+
181
+
182
+ @dataclass
183
+ class PlusMinus:
184
+ expression: MultDivMod
185
+ right: List[MultDivMod]
186
+ parent: Any
187
+
188
+
189
+ @dataclass
190
+ class MultDivMod:
191
+ expression: CatExp
192
+ right: List[CatExp]
193
+ parent: Any
194
+
195
+
196
+ @dataclass
197
+ class CatExp:
198
+ expression: Neg
199
+ right: List[Neg]
200
+ parent: Any
201
+
202
+
203
+ @dataclass
204
+ class Neg:
205
+ expression: Union[Neg, Selection]
206
+ parent: Any
207
+
208
+
209
+ @dataclass
210
+ class Selection:
211
+ expression: ArrayExp
212
+ member: List[QualifiedName]
213
+ parent: Any
214
+
215
+
216
+ @dataclass
217
+ class ArrayExp:
218
+ expression: CallExp
219
+ parameters: List[Expression]
220
+ parent: Any
221
+
222
+
223
+ @dataclass
224
+ class CallExp:
225
+ expression: Atomic
226
+ args: List[Expression]
227
+ parent: Any
228
+
229
+
230
+ @dataclass
231
+ class Atomic: # TODO Add subs
232
+ value: Union[str, int, float, bool]
233
+ parent: Any
234
+
235
+
236
+ @dataclass
237
+ class Node: # TODO Add subs
238
+ parent: Any
239
+
240
+
241
+ @dataclass
242
+ class Type:
243
+ source: FunctionType
244
+ target: Optional[Type] = None
245
+ parent: Any = None
51
246
 
52
247
  def __repr__(self):
53
248
  if self.target:
54
249
  return f"{self.source} <-> {self.target}"
55
250
  return f"{self.source}"
56
251
 
252
+ @dataclass
253
+ class Field:
254
+ name: str
255
+ type: Type
256
+ parent: Any
257
+
258
+
259
+ @dataclass
260
+ class RecordType:
261
+ name: str
262
+ fields: List[Field]
263
+ parent: Any
264
+
265
+ @dataclass
266
+ class Parameter:
267
+ name: str
268
+ type: Type
269
+ parent: Any
270
+
271
+ @dataclass
272
+ class Function:
273
+ name: str
274
+ parameters: List[Parameter]
275
+ type: Type
276
+ body: Body
277
+ parent: Any
278
+
279
+
280
+ @dataclass
281
+ class Body:
282
+ elements: List[BodyContent]
283
+ parent: Any
284
+
285
+
286
+ @dataclass
287
+ class BodyContent:
288
+ parent: Any
289
+
290
+
291
+ @dataclass
292
+ class Module:
293
+ name: str
294
+ connections: List[Connection]
295
+ nodes: List[ConnectionNode]
296
+ parent: Any
297
+
298
+
299
+ @dataclass
300
+ class VariableModifier:
301
+ parent: Any
302
+
303
+
304
+ @dataclass
305
+ class Interface:
306
+ name: str
307
+ operations: List[OperationSig]
308
+ events: List[Event]
309
+ parent: Any
310
+ clocks: List[Clock]
311
+ variables: List[Variable]
312
+
313
+
314
+ @dataclass
315
+ class Clock:
316
+ name: str
317
+
318
+
319
+ @dataclass
320
+ class OperationSig:
321
+ name: str
322
+ parameters: List[Parameter]
323
+ terminates: bool
324
+ parent: Any
325
+
326
+
327
+ @dataclass
328
+ class RoboticPlatformDef:
329
+ name: str
330
+ uses: List[QualifiedName]
331
+ provides: List[QualifiedName]
332
+ requires: List[QualifiedName]
333
+ operations: List[OperationSig]
334
+ events: List[Event]
335
+ parent: Any
336
+ variables: List[Variable]
337
+
338
+
339
+ @dataclass
340
+ class OperationDef:
341
+ name: str
342
+ parameters: List[Parameter]
343
+ terminates: str
344
+ preconditions: List[Expression]
345
+ postconditions: List[Expression]
346
+ uses: List[QualifiedName]
347
+ provides: List[QualifiedName]
348
+ variables: List[Variable]
349
+ events: List[Event]
350
+ nodes: List[Node]
351
+ transitions: List[Transition]
352
+ clock: List[Transition]
353
+ parent: Any
354
+
355
+
356
+ @dataclass
357
+ class Package:
358
+ name: QualifiedName
359
+ imports: List[Import]
360
+ controllers: List[ControllerDef]
361
+ modules: List[Module]
362
+ functions: List[Function]
363
+ types: List[RecordType]
364
+ machines: List[StateMachineDef]
365
+ interfaces: List[Interface]
366
+ robots: List[RoboticPlatformDef]
367
+ operations: List[OperationDef]
368
+
369
+
370
+ @dataclass
371
+ class ConnectionNode: # TODO add subs
372
+ parent: Any
373
+
374
+
375
+ @dataclass
376
+ class QualifiedName:
377
+ parts: List[str]
378
+ parent: Any
379
+
380
+ def __hash__(self):
381
+ return hash(str(self.parts))
57
382
 
58
- class Field(Node):
59
- def __init__(self, name: str, kind: Type, parent: Any):
60
- super().__init__(parent)
61
- self.name = name
62
- self.type = kind
383
+ def __repr__(self):
384
+ return "::".join(self.parts)
63
385
 
64
- @property
65
- def typename(self) -> str:
66
- return str(self.type)
67
386
 
68
- def __repr__(self):
69
- return f"{self.name}[{self.type}]"
387
+ @dataclass
388
+ class StateMachineDef:
389
+ name: str
390
+ uses: List[QualifiedName]
391
+ provides: List[QualifiedName]
392
+ requires: List[QualifiedName]
393
+ events: List[Event]
394
+ nodes: List[Node]
395
+ transitions: List[Transition]
396
+ clocks: List[Clock]
397
+ parent: Any
398
+ variables: List[Variable]
70
399
 
71
400
 
72
- class RecordType(Node):
73
- def __init__(self, name: str, fields: List[Field], parent: Any):
74
- # Can be datatype or record
75
- super().__init__(parent)
76
- self.name = name
77
- self.fields = fields
401
+ @dataclass
402
+ class Transition:
403
+ name: str
404
+ source: QualifiedName
405
+ target: QualifiedName
78
406
 
79
- def __repr__(self):
80
- return f"{self.name}({self.fields})"
81
-
82
-
83
- class Function(Node):
84
- def __init__(self, name: str, parameters, kind, body, parent: Any):
85
- super().__init__(parent)
86
- self.name = name
87
- self.parameters = parameters
88
- self.kind = kind
89
- self.body = body
90
-
91
-
92
- class RCModule(Node):
93
- def __init__(self, name: str, connections, nodes, parent: Any):
94
- super().__init__(parent)
95
- self.name = name
96
- self.connections = connections
97
- self.nodes = nodes
98
-
99
-
100
- class VariableList(Node):
101
- def __init__(self, modifier, variables, parent: Any):
102
- super().__init__(parent)
103
- self.modifier = modifier
104
- self.variables = variables
105
-
106
-
107
- class Interface(Node):
108
- def __init__(self, name: str, operations, events, variables: List[VariableList], clocks, parent: Any):
109
- super().__init__(parent)
110
- self.name = name
111
- self.operations = operations
112
- self.events = events
113
- self._variables = variables
114
- self.clocks = clocks
115
-
116
- @property
117
- def variables(self) -> List[Variable]:
118
- return [var for v in self._variables for var in v.variables]
119
-
120
-
121
- class RoboticPlatformDef(Node):
122
- def __init__(self, name: str, uses, provides, requires, variables, operations, events, parent: Any):
123
- super().__init__(parent)
124
- self.name = name
125
- self.uses = uses
126
- self.provides = provides
127
- self.requires = requires
128
- self._variables = variables
129
- self.operations = operations
130
- self.events = events
131
-
132
- @property
133
- def variables(self) -> List[Variable]:
134
- return [var for v in self._variables for var in v.variables]
135
-
136
-
137
- class OperationDef(Node):
138
- def __init__(self, name: str, parent: Any):
139
- super().__init__(parent)
140
- self.name = name
141
-
142
-
143
- class RCPackage(Node):
144
- def __init__(self, name: QualifiedName, imports: List[Import], controllers: List[ControllerDef],
145
- modules: List[RCModule], functions: List[Function], types: List[RecordType],
146
- machines: List[StateMachineDef], interfaces: List[Interface], robots: List[RoboticPlatformDef],
147
- operations: List[OperationDef]):
148
- super().__init__()
149
- self.name = name
150
- self.imports = imports
151
- self.controllers = controllers
152
- self.modules = modules
153
- self.functions = functions
154
- self.types = types
155
- self.machines = machines
156
- self.interfaces = interfaces
157
- self.robots = robots
158
- self.operations = operations
407
+ reset: List[ClockReset]
159
408
 
160
- def __repr__(self):
161
- return f"{self.name}"
409
+ parent: Any
410
+ trigger: Optional[Trigger]
411
+ deadline: Optional[Expression]
412
+ condition: Optional[ConditionExpr]
413
+ action: Optional[Statement]
162
414
 
163
415
 
164
- class QualifiedName(Node):
165
- def __init__(self, parts: List[str], parent: Any):
166
- super().__init__(parent)
167
- self.parts = parts
416
+ @dataclass
417
+ class ConditionExpr: # TODO
418
+ parent: Any
419
+
420
+
421
+ @dataclass
422
+ class Statement:
423
+ statements: List[EndStatement]
424
+ parent: Any
425
+
426
+
427
+ @dataclass
428
+ class EndStatement: # TODO
429
+ parent: Any
430
+ deadline: Optional[Expression]
431
+
432
+
433
+ @dataclass
434
+ class ClockReset:
435
+ clock: QualifiedName
436
+ parent: Any
437
+
438
+
439
+ @dataclass
440
+ class Trigger:
441
+ trigger: Communication
442
+ probability: Expression
443
+ parent: Any
444
+
445
+
446
+ @dataclass
447
+ class CommunicationStmt:
448
+ communication: Communication
449
+ parent: Any
168
450
 
169
- def __repr__(self):
170
- return "".join(self.parts)
171
451
 
452
+ @dataclass
453
+ class Communication:
454
+ event: QualifiedName
455
+ source: QualifiedName
456
+ predicate: List[Expression]
457
+ type: Union[InputType, OutputType, SyncType]
458
+ parent: Any
172
459
 
173
- class StateMachineDef(Node):
174
- def __init__(self, name, interfaces, provides, requires, variables, events, nodes, transitions, clocks,
175
- parent: Any):
176
- super().__init__(parent)
177
- self.name = name
178
- self.interfaces = interfaces
179
- self.provides = provides
180
- self.requires = requires
181
- self._variables = variables
182
- self.events = events
183
- self.nodes = nodes
184
- self.clocks = clocks
185
- self.transitions = transitions
186
460
 
187
- @property
188
- def variables(self) -> List[Variable]:
189
- return [var for v in self._variables for var in v.variables]
461
+ @dataclass
462
+ class InputType:
463
+ parameter: QualifiedName
464
+ parent: Any
190
465
 
191
466
 
192
- class Transition(Node):
193
- def __init__(self, name, source, target, trigger, reset, deadline, condition, action, parent: Any):
194
- super().__init__(parent)
195
- self.name = name
196
- self.source = source
197
- self.target = target
467
+ @dataclass
468
+ class OutputType:
469
+ value: CallExp
470
+ parent: Any
198
471
 
199
472
 
200
- class QualifiedNameWithWildcard(Node):
201
- def __init__(self, name, parent: Any):
202
- super().__init__(parent)
203
- self.name = name
473
+ @dataclass
474
+ class SyncType:
475
+ value: CallExp
476
+ parent: Any
477
+
478
+
479
+ @dataclass
480
+ class QualifiedNameWithWildcard:
481
+ name: QualifiedName
482
+ parent: Any
483
+
484
+ def __hash__(self):
485
+ return hash(str(self.name))
204
486
 
205
487
  def __repr__(self):
206
488
  return str(self.name) + "::*"
207
489
 
208
490
 
209
- class Import(Node):
210
- def __init__(self, name, parent: Any):
211
- super().__init__(parent)
212
- self.name = name
491
+ @dataclass
492
+ class Import:
493
+ name: QualifiedNameWithWildcard
494
+ parent: Any
213
495
 
214
496
  def __repr__(self):
215
497
  return str(self.name)
216
498
 
217
499
 
218
- class FunctionType(Node):
219
- def __init__(self, source: ProductType, target: Optional[FunctionType], parent: Any):
220
- super().__init__(parent)
221
- self.source = source
222
- self.target = target
500
+ @dataclass
501
+ class FunctionType:
502
+ source: ProductType
503
+ parent: Any
504
+ target: Optional[FunctionType]
505
+ # added by processor
506
+ source_chain: list = field(default_factory=list)
507
+ final_target: Any = None
223
508
 
224
509
  def __repr__(self):
225
510
  if self.target:
@@ -227,29 +512,56 @@ class FunctionType(Node):
227
512
  return f"{self.source}"
228
513
 
229
514
 
230
- class TypeRef(Node):
231
- def __init__(self, kind, parent: Any):
232
- super().__init__(parent)
233
- self.type = kind
515
+ @dataclass
516
+ class SetType:
517
+ domain: Type
518
+ parent: Any
519
+
520
+
521
+ @dataclass
522
+ class AnyType:
523
+ identifier: str
524
+ parent: Any
525
+
526
+
527
+ @dataclass
528
+ class TypeRef:
529
+ type: Union[SetType, SeqType, AnyType, Type, QualifiedName]
530
+ parent: Any
234
531
 
235
532
  def __repr__(self):
236
533
  return f"{self.type}"
237
534
 
238
535
 
239
- class VectorType(Node):
240
- # def __init__(self, source: Union[VectorDef, MatrixDef, TypeRef], parent: Any):
241
- def __init__(self, source: Union[TypeRef], parent: Any):
242
- super().__init__(parent)
243
- self.source = source
536
+ @dataclass
537
+ class VectorDef:
538
+ base: Type
539
+ size: int # TODO Add processor to set this to into from Atomic
540
+ parent: Any
541
+
542
+
543
+ @dataclass
544
+ class MatrixDef:
545
+ base: Type
546
+ rows: Atomic
547
+ columns: Atomic
548
+ parent: Any
549
+
550
+
551
+ @dataclass
552
+ class VectorType:
553
+ source: Union[VectorDef, MatrixDef, TypeRef]
554
+ parent: Any
244
555
 
245
556
  def __repr__(self):
246
557
  return f"{self.source}"
247
558
 
248
559
 
249
- class ProductType(Node):
250
- def __init__(self, types: List[Union[VectorType, TypeRef]], parent: Any):
251
- super().__init__(parent)
252
- self.types = types
560
+ @dataclass
561
+ class ProductType:
562
+ types: List[Union[VectorType, TypeRef]]
563
+ flat_types: List[VectorType] = field(default_factory=list)
564
+ parent: Any = None
253
565
 
254
566
  def __repr__(self):
255
567
  if len(self.types) > 1:
@@ -258,21 +570,21 @@ class ProductType(Node):
258
570
  return f"{self.types[0]}"
259
571
 
260
572
 
261
- class SeqType(Node):
262
- def __init__(self, domain, parent: Any):
263
- super().__init__(parent)
264
- self.domain = domain
573
+ @dataclass
574
+ class SeqType:
575
+ domain: Type
576
+ parent: Any
265
577
 
266
578
  def __repr__(self):
267
579
  return f"Seq({self.domain})"
268
580
 
269
581
 
270
- class Event(Node):
271
- def __init__(self, name: str, broadcast: bool, kind: Type, parent: Any):
272
- super().__init__(parent)
273
- self.name = name
274
- self.broadcast = broadcast
275
- self.type = kind
582
+ @dataclass
583
+ class Event:
584
+ name: str
585
+ broadcast: bool
586
+ type: Type
587
+ parent: Any
276
588
 
277
589
  def __repr__(self):
278
590
  return f"Event: {self.name} {self.broadcast, self.type}"
robotransform/filters.py CHANGED
@@ -1,12 +1,29 @@
1
- def typename_to_port(type_name: str) -> str:
2
- event_types = {"event"}
1
+ def type_to_port(type) -> str:
2
+ # TODO this is wrong
3
+ typename = str(type)
3
4
  data_types = {"int", "integer", "real", "float", "double", "string"}
4
5
  mixed_types = {"event_data", "event data"}
5
6
 
6
- if type_name in event_types:
7
- return "event"
8
- if type_name in data_types:
7
+ if typename in data_types:
9
8
  return "data"
10
- if type_name in mixed_types:
9
+ if typename in mixed_types:
11
10
  return "event data"
12
11
  return "data"
12
+
13
+ def type_to_aadl_type(type) -> str:
14
+ typename = str(type)
15
+ # Boolean,
16
+ # Character,
17
+ # Float, Float_32, Float_64,
18
+ # Integer, Integer_8, Integer_16, Integer_32, Integer_64,
19
+ # Natural,
20
+ # String,
21
+ # Unsigned_8, Unsigned_16, Unsigned_32, Unsigned_64
22
+ mapping = {
23
+ "boolean": "Base_Types::Boolean",
24
+ "nat": "Base_Types::Natural",
25
+ "real": "Base_Types::Float",
26
+ }
27
+ # TODO Seq -> Array[...]
28
+ # TODO Matrix to Array[Array[...]]
29
+ return mapping.get(typename, f"messages::{typename}")
robotransform/main.py CHANGED
@@ -8,8 +8,9 @@ from jinja2 import Environment, FileSystemLoader, Template
8
8
  import io
9
9
  from typing import Union, Optional, Iterable, Iterator
10
10
 
11
- from robotransform.concepts import all_concepts, RCPackage
12
- from robotransform.filters import typename_to_port
11
+ from robotransform.concepts import all_concepts, Package
12
+ from robotransform.filters import type_to_port, type_to_aadl_type
13
+ from robotransform.processors import processors
13
14
 
14
15
 
15
16
  @dataclass
@@ -28,7 +29,7 @@ class Store:
28
29
  yield item
29
30
  continue
30
31
 
31
- def parse_imports(self, package: RCPackage, parent_path: Path, visited):
32
+ def parse_imports(self, package: Package, parent_path: Path, visited):
32
33
  stack = [package]
33
34
  while stack:
34
35
  package = stack.pop()
@@ -40,12 +41,12 @@ class Store:
40
41
  if not path.exists():
41
42
  arklog.debug(f"Can't import {path}.")
42
43
  continue
43
- subpkg = parse_robochart(path)
44
- visited[path] = subpkg
45
- stack.append(subpkg)
44
+ sub_package = parse_robochart(path)
45
+ visited[path] = sub_package
46
+ stack.append(sub_package)
46
47
  return visited
47
48
 
48
- def load(self, imports: bool = True) -> dict[Path, RCPackage]:
49
+ def load(self, imports: bool = True) -> dict[Path, Package]:
49
50
  visited = {}
50
51
  for path in self:
51
52
  package = parse_robochart(path)
@@ -85,11 +86,12 @@ def get_robochart_metamodel(name: str = "robochart.tx"):
85
86
  arklog.debug(f"Loading ({name}) metamodel.")
86
87
  metamodel_path = Path(__file__).resolve().parent / name
87
88
  metamodel = metamodel_from_str(metamodel_path.read_text(), classes=all_concepts(), memoization=True)
89
+ metamodel.register_obj_processors(processors)
88
90
  return metamodel
89
91
 
90
92
 
91
93
  @lru_cache(maxsize=1)
92
- def parse_robochart(source: Path | str) -> RCPackage:
94
+ def parse_robochart(source: Path | str) -> Package:
93
95
  arklog.debug(f"Parsing ({source}).")
94
96
  metamodel = get_robochart_metamodel()
95
97
  data = source.read_text() if isinstance(source, Path) else source
@@ -99,8 +101,9 @@ def parse_robochart(source: Path | str) -> RCPackage:
99
101
  @lru_cache(maxsize=2)
100
102
  def get_template(name: str) -> Template:
101
103
  environment = Environment(loader=FileSystemLoader(Path(__file__).resolve().parent / "templates"))
102
- environment.filters["typename_to_port"] = typename_to_port # For use with pipes
103
- # environment.globals["typename_to_port"] = typename_to_port # For use as a function
104
+ environment.filters["type_to_port"] = type_to_port # For use with pipes
105
+ environment.filters["type_to_aadl_type"] = type_to_aadl_type # For use with pipes
106
+ # environment.globals["type_to_port"] = type_to_port # For use as a function
104
107
  templates = {
105
108
  "messages": "messages.aadl",
106
109
  "logical": "logical.aadl",
@@ -108,7 +111,7 @@ def get_template(name: str) -> Template:
108
111
  if found := templates.get(name):
109
112
  return environment.get_template(found)
110
113
  else:
111
- raise ValueError(f"No template found for name '{name}'")
114
+ raise ValueError(f"No template found for name ({name}).")
112
115
 
113
116
 
114
117
  def write_output(data: str, output: Optional[Union[io.TextIOBase, Path, str]] = None) -> str:
@@ -122,7 +125,7 @@ def write_output(data: str, output: Optional[Union[io.TextIOBase, Path, str]] =
122
125
  output.write(data)
123
126
  output.flush()
124
127
  else:
125
- raise TypeError(f"Unsupported output type: {type(output)}.")
128
+ raise TypeError(f"Unsupported output type ({type(output)}).")
126
129
  return data
127
130
 
128
131
 
@@ -0,0 +1,59 @@
1
+ from robotransform.concepts import Variable, VectorDef, MatrixDef, TypeRef
2
+
3
+
4
+ def flatten_function_type(function_type):
5
+ current = function_type
6
+ linear = []
7
+
8
+ while current is not None:
9
+ linear.append(current.source)
10
+ current = current.target
11
+
12
+ function_type.source_chain = linear[:-1]
13
+ function_type.final_target = linear[-1]
14
+ return function_type
15
+
16
+
17
+ def flatten_product_type(obj):
18
+ flat = [obj.types[0]] if obj.types else []
19
+ for t in obj.types[1:]:
20
+ flat.append(t)
21
+ obj.flat_types = flat
22
+ return obj
23
+
24
+
25
+ def flatten_variable_list(var_list_obj):
26
+ flat_vars = []
27
+ for variable in var_list_obj.variables:
28
+ variable.modifier = var_list_obj.modifier
29
+ flat_vars.append(variable)
30
+ assert (len(flat_vars) == 1) # TODO Is this always the case?
31
+ return flat_vars[0]
32
+
33
+
34
+ def flatten_vector_type(obj):
35
+ if isinstance(obj.source, VectorDef):
36
+ obj.flattened = [obj.source.base]
37
+ elif isinstance(obj.source, MatrixDef):
38
+ obj.flattened = [obj.source.base]
39
+ elif isinstance(obj.source, TypeRef):
40
+ obj.flattened = [obj.source.type]
41
+ return obj
42
+
43
+
44
+ def convert_variable_no_init(variable_no_init):
45
+ return Variable(
46
+ name=variable_no_init.name,
47
+ type=variable_no_init.type,
48
+ initial=None,
49
+ parent=variable_no_init.parent
50
+ )
51
+
52
+
53
+ processors = {
54
+ "ProductType": flatten_product_type,
55
+ "FunctionType": flatten_function_type,
56
+ "VariableList": flatten_variable_list,
57
+ "VariableNoInit": convert_variable_no_init,
58
+ "VectorType": flatten_vector_type,
59
+ }
@@ -1,4 +1,4 @@
1
- RCPackage:
1
+ Package:
2
2
  'package' name=QualifiedName? (
3
3
  'diagram' ID
4
4
  | imports+=Import
@@ -9,7 +9,7 @@ RCPackage:
9
9
  | machines+=StateMachineDef
10
10
  | operations+=OperationDef
11
11
  | functions+=Function
12
- | modules+=RCModule
12
+ | modules+=Module
13
13
  )*
14
14
  ;
15
15
 
@@ -19,12 +19,12 @@ Import: 'import' name=QualifiedNameWithWildcard;
19
19
 
20
20
  QualifiedNameWithWildcard: name=QualifiedName ('::*')?;
21
21
 
22
- RCModule:
22
+ Module:
23
23
  'module' name=ID '{' (connections+=Connection | nodes+=ConnectionNode)* '}'
24
24
  ;
25
25
 
26
26
  Connection:
27
- 'connection' from=QualifiedName 'on' efrom=QualifiedName 'to' to=QualifiedName 'on' eto=QualifiedName ('(' async?='_async' ')')? ('[' bidirec?='mult' ']')?
27
+ 'connection' source=QualifiedName 'on' event_source=QualifiedName 'to' target=QualifiedName 'on' event_target=QualifiedName ('(' asynchronous?='_async' ')')? ('[' bidirectional?='mult' ']')?
28
28
  ;
29
29
 
30
30
  ConnectionNode: Controller | StateMachine | RoboticPlatform;
@@ -51,7 +51,7 @@ VariableList:
51
51
  VariableModifier: 'var' | 'const';
52
52
 
53
53
  Variable:
54
- name=ID ':' kind=Type ('=' initial=Expression)?
54
+ name=ID ':' type=Type ('=' initial=Expression)?
55
55
  ;
56
56
 
57
57
  Type: source=FunctionType ('<->' target=Type)?;
@@ -70,7 +70,7 @@ VectorDef: 'vector' '(' base=Type ',' size=Atomic ')';
70
70
 
71
71
  MatrixDef: 'matrix' '(' base=Type ',' rows=Atomic ',' columns=Atomic ')';
72
72
 
73
- TypeRef: kind=SetType | kind=SeqType | kind=AnyType | '(' kind=Type ')' | kind=QualifiedName;
73
+ TypeRef: type=SetType | type=SeqType | type=AnyType | '(' type=Type ')' | type=QualifiedName;
74
74
 
75
75
  SetType: 'Set(' domain=Type ')';
76
76
 
@@ -101,7 +101,7 @@ Atomic:
101
101
  | TupleExp
102
102
  ;
103
103
 
104
- TypeLit: kind=QualifiedName '::' literal=QualifiedName;
104
+ TypeLit: type=QualifiedName '::' literal=QualifiedName;
105
105
  EqualDelim: '<' (values+=PlusMinus[','])? '>';
106
106
 
107
107
  RefExp:
@@ -117,14 +117,22 @@ FieldDefinition:
117
117
  ;
118
118
 
119
119
  Expression:
120
+ expression=ForAll
121
+ | expression=Exists
122
+ | expression=LambdaExp
123
+ | expression=Iff
124
+ ;
125
+
126
+ ForAll:
120
127
  'forall' variables+=VariableNoInit[','] ('|' suchthat=Expression)? '@' predicate=Expression
121
- | ('exists' | unique?='exists1') variables+=VariableNoInit[','] ('|' suchthat=Expression)? '@' predicate=Expression
122
- | LambdaExp
123
- | Iff
128
+ ;
129
+
130
+ Exists:
131
+ ('exists' | unique?='exists1') variables+=VariableNoInit[','] ('|' suchthat=Expression)? '@' predicate=Expression
124
132
  ;
125
133
 
126
134
  VariableNoInit:
127
- name=ID ':' kind=Type
135
+ name=ID ':' type=Type
128
136
  ;
129
137
 
130
138
  LambdaExp:
@@ -151,7 +159,7 @@ Not:
151
159
  'not' exp=Not | exp=Comp
152
160
  ;
153
161
 
154
- Comp: left=DefiniteDescription (Comparison right=DefiniteDescription | 'in' set=DefiniteDescription)*;
162
+ Comp: left=DefiniteDescription (comp=Comparison right=DefiniteDescription | 'in' set=DefiniteDescription)*;
155
163
 
156
164
  DefiniteDescription:
157
165
  'the' variables+=VariableNoInit[','] ('|' suchthat=Expression)? '@' expression=DefiniteDescription
@@ -164,7 +172,7 @@ LetExpression:
164
172
  ;
165
173
 
166
174
  Declaration:
167
- name=ID '==' value=Expression
175
+ name=ID '==' expression=Expression
168
176
  ;
169
177
 
170
178
  IfExpression:
@@ -173,7 +181,7 @@ IfExpression:
173
181
  ;
174
182
 
175
183
  TypedExpression:
176
- expression=PlusMinus ('as' kind=Type | 'is' kind=Type)?
184
+ expression=PlusMinus ('as' type=Type | 'is' type=Type)?
177
185
  ;
178
186
 
179
187
  PlusMinus:
@@ -188,7 +196,7 @@ CatExp:
188
196
  expression=Neg ('cat' right=Neg | '^' right=Neg)*
189
197
  ;
190
198
 
191
- Neg: '-' exp=Neg | exp=Selection;
199
+ Neg: '-' expression=Neg | expression=Selection;
192
200
 
193
201
  Selection:
194
202
  expression=ArrayExp ('.' member=QualifiedName)*
@@ -227,18 +235,18 @@ TupleExp:
227
235
  ;
228
236
 
229
237
  Comparison:
230
- '==' right=DefiniteDescription
231
- | '!=' right=DefiniteDescription
232
- | '>' right=DefiniteDescription
233
- | '>=' right=DefiniteDescription
234
- | '<' right=DefiniteDescription
235
- | '<=' right=DefiniteDescription
236
- | 'in' set=DefiniteDescription
238
+ operator='==' right=DefiniteDescription
239
+ | operator='!=' right=DefiniteDescription
240
+ | operator='>' right=DefiniteDescription
241
+ | operator='>=' right=DefiniteDescription
242
+ | operator='<' right=DefiniteDescription
243
+ | operator='<=' right=DefiniteDescription
244
+ | operator='in' set=DefiniteDescription
237
245
  ;
238
246
 
239
- Event: broadcast?='_broadcast'? 'event' name=ID (':' kind=Type)?;
247
+ Event: broadcast?='_broadcast'? 'event' name=ID (':' type=Type)?;
240
248
 
241
- Operation: OperationRef | OperationDef;
249
+ Operation: operation=OperationRef | operation=OperationDef;
242
250
 
243
251
  OperationDef:
244
252
  'operation' name=ID '(' (parameters+=Parameter[','])? ')' '{' (
@@ -258,14 +266,14 @@ OperationDef:
258
266
  ;
259
267
 
260
268
  Parameter:
261
- name=ID ':' kind=Type
269
+ name=ID ':' type=Type
262
270
  ;
263
271
 
264
272
  Node: State | Initial | Junction | Final | ProbabilisticJunction;
265
273
 
266
274
  State:
267
275
  'state' name=ID '{'
268
- body=StateBody
276
+ body=Body
269
277
  //(
270
278
  // nodes+=Node
271
279
  // | transitions+=Transition
@@ -273,10 +281,6 @@ State:
273
281
  //)*
274
282
  '}'
275
283
  ;
276
- StateBody: elements*=StateBodyContent;
277
- StateBodyContent: /[^{}]+/ | NestedStateBlock;
278
- NestedStateBlock: '{' body=StateBody '}';
279
-
280
284
 
281
285
  Initial:
282
286
  'initial' name=QualifiedName
@@ -312,23 +316,23 @@ Communication:
312
316
  (
313
317
  '[|'
314
318
  (
315
- _from=QualifiedName '=' 'from'
316
- ( '|]' | '|' _predicate=Expression '|]' )
317
- | _predicate=Expression? '|]'
319
+ source=QualifiedName '=' 'from'
320
+ ( '|]' | '|' predicate=Expression '|]' )
321
+ | predicate=Expression? '|]'
318
322
  )
319
323
  )?
320
324
  (
321
- kind=InputType parameter=QualifiedName
322
- | kind=OutputType value=CallExp
323
- | kind=SyncType value=CallExp
325
+ type=InputType
326
+ | type=OutputType
327
+ | type=SyncType
324
328
  )?
325
329
  ;
326
330
 
327
- InputType: '?';
331
+ InputType: '?' parameter=QualifiedName;
328
332
 
329
- OutputType: '!';
333
+ OutputType: '!' value=CallExp;
330
334
 
331
- SyncType: '.';
335
+ SyncType: '.' value=CallExp;
332
336
 
333
337
  ClockReset: '#' clock=QualifiedName;
334
338
 
@@ -413,7 +417,7 @@ StateMachine: StateMachineDef | StateMachineRef;
413
417
  StateMachineDef:
414
418
  'stm' name=ID '{'
415
419
  (
416
- 'uses' interfaces+=QualifiedName[',']
420
+ 'uses' uses+=QualifiedName[',']
417
421
  | 'provides' provides+=QualifiedName[',']
418
422
  | 'requires' requires+=QualifiedName[',']
419
423
  | variables+=VariableList
@@ -474,7 +478,7 @@ RecordType:
474
478
  ;
475
479
 
476
480
  Field:
477
- name=ID ':' kind=Type
481
+ name=ID ':' type=Type
478
482
  ;
479
483
 
480
484
  Enumeration:
@@ -493,14 +497,14 @@ NamedExpression:
493
497
 
494
498
  // TODO The FunctionBody is there to parse all contents of the function and replaces the pre and post condition parsing to simplify the translation to textx
495
499
  Function:
496
- 'function' name=ID '(' (parameters+=Parameter[','])? ')' ':' kind=Type
497
- '{' body=FunctionBody
500
+ 'function' name=ID '(' (parameters+=Parameter[','])? ')' ':' type=Type
501
+ '{' body=Body
498
502
  //( 'precondition' preconditions+=Expression | 'postcondition' postconditions+=Expression)*
499
503
  '}'
500
504
  ;
501
- FunctionBody: elements*=FunctionBodyContent;
502
- FunctionBodyContent: /[^{}]+/ | NestedBlock;
503
- NestedBlock: '{' body=FunctionBody '}';
505
+ Body: elements*=BodyContent;
506
+ BodyContent: /[^{}]+/ | NestedBlock;
507
+ NestedBlock: '{' body=Body '}';
504
508
 
505
509
  Comment:
506
510
  /\/\/.*$/
@@ -1,5 +1,5 @@
1
- {%- macro render_port(name, direction, typename) -%}
2
- {{ name }}: {{ direction }} {{ typename | typename_to_port }} port messages::{{ typename }};
1
+ {%- macro render_port(name, direction, type) -%}
2
+ {{ name }}: {{ direction }} {{ type | type_to_port }} port {{ type | type_to_aadl_type}};
3
3
  {%- endmacro -%}
4
4
 
5
5
  {%- macro render_state_threads(machine) -%}
@@ -19,7 +19,7 @@ end {{ state.name }}.impl;
19
19
 
20
20
  package LogicalArchitecture
21
21
  public
22
- with messages, Base_Types, MBED;
22
+ with messages, Base_Types;
23
23
  {%- for package in packages %}
24
24
  process {{package.name}}
25
25
  {%- set interface_vars = package.interfaces | map(attribute="variables") | sum(start=[]) -%}
@@ -28,12 +28,12 @@ public
28
28
  features
29
29
  {%- for interface in package.interfaces -%}
30
30
  {%- for variable in interface.variables %}
31
- {{ render_port(variable.name, 'in', variable.type) }}
31
+ {{ render_port(variable.name, "in", variable.type) }}
32
32
  {%- endfor %}
33
33
  {%- endfor %}
34
34
  {%- for machine in package.machines -%}
35
35
  {%- for variable in machine.variables %}
36
- {{ render_port(variable.name, 'in', variable.type) }}
36
+ {{ render_port(variable.name, "in", variable.type) }}
37
37
  {%- endfor %}
38
38
  {%- endfor -%}
39
39
  {%- endif %}
@@ -6,20 +6,7 @@ public
6
6
  data {{ type.name }}
7
7
  features
8
8
  {%- for field in type.fields %}
9
- {%- if field.typename in ['real', 'float', 'double'] %}
10
- {{ field.name }}: provides data access Base_Types::Float_64;
11
- {%- elif field.typename in ['int', 'integer', 'long'] %}
12
- {{ field.name }}: provides data access Base_Types::Integer_64;
13
- {%- elif field.typename in ['bool', 'boolean'] %}
14
- {{ field.name }}: provides data access Base_Types::Boolean;
15
- {%- elif field.typename in ['string', 'text'] %}
16
- {{ field.name }}: provides data access Data_Model::String;
17
- {%- elif field.typename in ['byte', 'bytes'] %}
18
- {{ field.name }}: provides data access Base_Types::Unsigned_8;
19
- {%- else %}
20
- -- Unknown type '{{ field.typename }}'; adjust mapping
21
- {{ field.name }}: provides data access Data_Model::Generic_Type;
22
- {%- endif %}
9
+ {{ field.name }}: provides data access {{ field.type | type_to_aadl_type }};
23
10
  {%- endfor %}
24
11
  end {{type.name}};
25
12
  {%- endfor %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotransform
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: Perform model transformations for the RoboSapiens project.
5
5
  Keywords: transformation
6
6
  Author: Arkadiusz Michał Ryś
@@ -0,0 +1,12 @@
1
+ robotransform/__init__.py,sha256=8IkQ3Astb5vWt6yKgB0e3FqniYWPy9wufasZR9OwXmI,166
2
+ robotransform/concepts.py,sha256=ZhJKyb9m6_0tYOorRHOPsbOV_kDkSgE__xcLD2FPqJQ,9937
3
+ robotransform/filters.py,sha256=ltHlb_SQ5310g4YQ8WuN5eAakb_dAK_Itg4ofeml-tg,872
4
+ robotransform/main.py,sha256=afE30HpVo5weXeBO60LOpkCDS4cZ0EKo-nuD0xUG5cI,5025
5
+ robotransform/processors.py,sha256=8NaNFTAm3iaNAzbp5D8-Uv_qIWyxVklIbmGtXi5--nM,1578
6
+ robotransform/robochart.tx,sha256=dz_4hr-reu9ubuXdZR4WNKkp-gs_txgzyRvR-p7nphA,10227
7
+ robotransform/templates/logical.aadl,sha256=wxdtAHWFqou9qPZ4LJzWWSYWwWpl02L8-vOnjbncnvA,2270
8
+ robotransform/templates/messages.aadl,sha256=gSEULreDkIM-ukODyD1WnaV1qFTw_j5EAM2Z9u-Xkmo,383
9
+ robotransform-0.0.4.dist-info/WHEEL,sha256=3id4o64OvRm9dUknh3mMJNcfoTRK08ua5cU6DFyVy-4,79
10
+ robotransform-0.0.4.dist-info/entry_points.txt,sha256=NvmK-01oEE7ji06NbIxr7pZGUEJwbwMLjjfHssOVmB0,52
11
+ robotransform-0.0.4.dist-info/METADATA,sha256=eWK8D9-tRY3ntWv_sB9S7-cICZ7_QR1ya5VdAeQlrUU,42563
12
+ robotransform-0.0.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.10
2
+ Generator: uv 0.9.13
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,11 +0,0 @@
1
- robotransform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- robotransform/concepts.py,sha256=pkJQuTWVpZI0JSjmRIfIuu4IojLZh_epDJHS1NwHttQ,8290
3
- robotransform/filters.py,sha256=-awbQ7MYp3hCpAMnZQxDLiTeURfNjgWChg9BmCOrBKg,383
4
- robotransform/main.py,sha256=tcaAZLLLIgzjvQ4Z7KceUZvPJ-2lYreFhL1lleF_OaY,4833
5
- robotransform/robochart.tx,sha256=wBS9wFyTbSq52awMECg7qB31x4qL7GGntVD_lkPqvtE,10188
6
- robotransform/templates/logical.aadl,sha256=LXgApAli_gLmNly4ejjD2LZaDoHi_IC-fnG2UNZcT6w,2283
7
- robotransform/templates/messages.aadl,sha256=kCTTtRe93EoewwW76sAfQuUPw-pGuT52pxjweD9IIAE,1135
8
- robotransform-0.0.2.dist-info/WHEEL,sha256=ZHijuPszqKbNczrBXkSuoxdxocbxgFghqnequ9ZQlVk,79
9
- robotransform-0.0.2.dist-info/entry_points.txt,sha256=NvmK-01oEE7ji06NbIxr7pZGUEJwbwMLjjfHssOVmB0,52
10
- robotransform-0.0.2.dist-info/METADATA,sha256=N841GJf56KUgWRLUEs4JjMx6kx0Ns9Q2bbL40D59bxU,42563
11
- robotransform-0.0.2.dist-info/RECORD,,