1
1
import ast
2
+ import keyword
2
3
from pathlib import Path
3
4
from typing import cast , List , Dict
4
5
5
6
import astor # Install with `pip install astor`
6
7
import click
7
- from lionwebpython .language import Language , Concept , Interface
8
+ from lionwebpython .language import Language , Concept , Interface , Containment , Property
9
+ from lionwebpython .language .classifier import Classifier
8
10
from lionwebpython .language .enumeration import Enumeration
9
11
from lionwebpython .language .primitive_type import PrimitiveType
12
+ from lionwebpython .language .reference import Reference
10
13
from lionwebpython .lionweb_version import LionWebVersion
11
14
from lionwebpython .serialization .serialization_provider import SerializationProvider
12
15
13
16
from pylasu .lionweb .starlasu import StarLasuBaseLanguage
14
17
15
18
16
- def topological_concepts_sort ( concepts : List [Concept ]) -> List [Concept ]:
17
- id_to_concept = {el .get_id (): el for el in concepts }
19
+ def topological_classifiers_sort ( classifiers : List [Classifier ]) -> List [Classifier ]:
20
+ id_to_concept = {el .get_id (): el for el in classifiers }
18
21
19
22
# Build graph edges: child -> [parents]
20
- graph : Dict [str , List [str ]] = {el .get_id (): [] for el in concepts }
21
- for el in concepts :
22
- if el .get_extended_concept () and el .get_extended_concept ().get_id () in id_to_concept :
23
- graph [el .get_id ()].append (el .get_extended_concept ().get_id ())
23
+ graph : Dict [str , List [str ]] = {el .get_id (): [] for el in classifiers }
24
+ for c in classifiers :
25
+ if isinstance (c , Concept ):
26
+ if c .get_extended_concept () and c .get_extended_concept ().get_id () in id_to_concept :
27
+ graph [c .get_id ()].append (c .get_extended_concept ().get_id ())
28
+ for i in c .get_implemented ():
29
+ graph [c .get_id ()].append (i .get_id ())
30
+ for f in c .get_features ():
31
+ if isinstance (f , Containment ):
32
+ if f .get_type () and f .get_type ().get_id () in id_to_concept :
33
+ graph [c .get_id ()].append (f .get_type ().get_id ())
34
+ elif isinstance (c , Interface ):
35
+ pass
36
+ else :
37
+ raise ValueError ()
24
38
25
39
visited = set ()
26
40
sorted_list = []
@@ -29,12 +43,14 @@ def visit(name: str):
29
43
if name in visited :
30
44
return
31
45
visited .add (name )
32
- for dep in graph [name ]:
33
- visit (dep )
34
- sorted_list .append (id_to_concept [name ])
46
+ if name in graph :
47
+ for dep in graph [name ]:
48
+ visit (dep )
49
+ if name in id_to_concept :
50
+ sorted_list .append (id_to_concept [name ])
35
51
36
- for el in concepts :
37
- visit (el .get_id ())
52
+ for c in classifiers :
53
+ visit (c .get_id ())
38
54
39
55
return sorted_list
40
56
@@ -65,12 +81,30 @@ def main(dependencies, lionweb_language, output):
65
81
names = [ast .alias (name = 'ABC' , asname = None )],
66
82
level = 0
67
83
)
84
+ import_dataclass = ast .ImportFrom (
85
+ module = 'dataclasses' ,
86
+ names = [ast .alias (name = 'dataclass' , asname = None )],
87
+ level = 0
88
+ )
89
+ import_starlasu = ast .ImportFrom (
90
+ module = 'pylasu.model.metamodel' ,
91
+ names = [ast .alias (name = 'Expression' , asname = 'StarLasuExpression' ),
92
+ ast .alias (name = 'PlaceholderElement' , asname = 'StarLasuPlaceholderElement' ),
93
+ ast .alias (name = 'Named' , asname = 'StarLasuNamed' ),
94
+ ast .alias (name = 'TypeAnnotation' , asname = 'StarLasuTypeAnnotation' ),
95
+ ast .alias (name = 'Parameter' , asname = 'StarLasuParameter' ),
96
+ ast .alias (name = 'Statement' , asname = 'StarLasuStatement' ),
97
+ ast .alias (name = 'EntityDeclaration' , asname = 'StarLasuEntityDeclaration' ),
98
+ ast .alias (name = 'BehaviorDeclaration' , asname = 'StarLasuBehaviorDeclaration' ),
99
+ ast .alias (name = 'Documentation' , asname = 'StarLasuDocumentation' )],
100
+ level = 0
101
+ )
68
102
import_node = ast .ImportFrom (
69
103
module = 'pylasu.model' ,
70
104
names = [ast .alias (name = 'Node' , asname = None )],
71
105
level = 0
72
106
)
73
- module = ast .Module (body = [import_abc , import_node ], type_ignores = [])
107
+ module = ast .Module (body = [import_abc , import_dataclass , import_starlasu , import_node ], type_ignores = [])
74
108
75
109
76
110
for element in language .get_elements ():
@@ -85,21 +119,79 @@ def main(dependencies, lionweb_language, output):
85
119
else :
86
120
raise ValueError (f"Unsupported { element } " )
87
121
88
- sorted_concepts = topological_concepts_sort ([c for c in language .get_elements () if isinstance (c , Concept )])
89
-
90
- for concept in sorted_concepts :
91
- bases = []
92
- if concept .get_extended_concept ().id == StarLasuBaseLanguage .get_astnode (LionWebVersion .V2023_1 ).id :
93
- bases .append ('Node' )
122
+ sorted_classifier = topological_classifiers_sort ([c for c in language .get_elements () if isinstance (c , Classifier )])
123
+
124
+ for classifier in sorted_classifier :
125
+ if isinstance (classifier , Concept ):
126
+ bases = []
127
+ if classifier .get_extended_concept ().id == StarLasuBaseLanguage .get_astnode (LionWebVersion .V2023_1 ).id :
128
+ bases .append ('Node' )
129
+ else :
130
+ bases .append (classifier .get_extended_concept ().get_name ())
131
+ for i in classifier .get_implemented ():
132
+ if i .get_id () == 'com-strumenta-StarLasu-Expression-id' :
133
+ bases .append ('StarLasuExpression' )
134
+ elif i .get_id () == 'com-strumenta-StarLasu-Statement-id' :
135
+ bases .append ('StarLasuStatement' )
136
+ elif i .get_id () == 'com-strumenta-StarLasu-PlaceholderElement-id' :
137
+ bases .append ('StarLasuPlaceholderElement' )
138
+ elif i .get_id () == 'com-strumenta-StarLasu-Parameter-id' :
139
+ bases .append ('StarLasuParameter' )
140
+ elif i .get_id () == 'com-strumenta-StarLasu-Documentation-id' :
141
+ bases .append ('StarLasuDocumentation' )
142
+ elif i .get_id () == 'com-strumenta-StarLasu-TypeAnnotation-id' :
143
+ bases .append ('StarLasuTypeAnnotation' )
144
+ elif i .get_id () == 'com-strumenta-StarLasu-BehaviorDeclaration-id' :
145
+ bases .append ('StarLasuBehaviorDeclaration' )
146
+ elif i .get_id () == 'com-strumenta-StarLasu-EntityDeclaration-id' :
147
+ bases .append ('StarLasuEntityDeclaration' )
148
+ elif i .get_id () == 'LionCore-builtins-INamed' :
149
+ bases .append ('StarLasuNamed' )
150
+ else :
151
+ bases .append (i .get_name ())
152
+ if classifier .is_abstract ():
153
+ bases .append ('ABC' )
154
+ dataclass_decorator = ast .Name (id = "dataclass" , ctx = ast .Load ())
155
+ classdef = ast .ClassDef (classifier .get_name (), bases = bases ,
156
+ keywords = [],
157
+ body = [ast .Pass ()],
158
+ decorator_list = [dataclass_decorator ])
159
+
160
+ for feature in classifier .get_features ():
161
+ if isinstance (feature , Containment ):
162
+ field_name = feature .get_name ()
163
+ if field_name in keyword .kwlist :
164
+ field_name = f"{ field_name } _"
165
+ field = ast .AnnAssign (
166
+ target = ast .Name (id = field_name , ctx = ast .Store ()),
167
+ annotation = ast .Constant (value = feature .get_type ().get_name ()),
168
+ value = None ,
169
+ simple = 1 ,
170
+ )
171
+ if len (classdef .body ) == 1 and isinstance (classdef .body [0 ], ast .Pass ):
172
+ classdef .body = []
173
+ classdef .body .append (field )
174
+ elif isinstance (feature , Reference ):
175
+ pass
176
+ elif isinstance (feature , Property ):
177
+ pass
178
+ else :
179
+ raise ValueError ()
180
+
181
+ module .body .append (classdef )
182
+ elif isinstance (classifier , Interface ):
183
+ bases = []
184
+ if len (classifier .get_extended_interfaces ()) == 0 :
185
+ bases .append ("Node" )
186
+ bases .append ("ABC" )
187
+
188
+ classdef = ast .ClassDef (classifier .get_name (), bases = bases ,
189
+ keywords = [],
190
+ body = [ast .Pass ()],
191
+ decorator_list = [])
192
+ module .body .append (classdef )
94
193
else :
95
- bases .append (concept .get_extended_concept ().get_name ())
96
- if concept .is_abstract ():
97
- bases .append ('ABC' )
98
- classdef = ast .ClassDef (concept .get_name (), bases = bases ,
99
- keywords = [],
100
- body = [ast .Pass ()],
101
- decorator_list = [])
102
- module .body .append (classdef )
194
+ raise ValueError ()
103
195
104
196
click .echo (f"📂 Saving results to: { output } " )
105
197
generated_code = astor .to_source (module )
0 commit comments