11import ast
2+ import keyword
23from pathlib import Path
34from typing import cast , List , Dict
45
56import astor # Install with `pip install astor`
67import 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
810from lionwebpython .language .enumeration import Enumeration
911from lionwebpython .language .primitive_type import PrimitiveType
12+ from lionwebpython .language .reference import Reference
1013from lionwebpython .lionweb_version import LionWebVersion
1114from lionwebpython .serialization .serialization_provider import SerializationProvider
1215
1316from pylasu .lionweb .starlasu import StarLasuBaseLanguage
1417
1518
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 }
1821
1922 # 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 ()
2438
2539 visited = set ()
2640 sorted_list = []
@@ -29,12 +43,14 @@ def visit(name: str):
2943 if name in visited :
3044 return
3145 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 ])
3551
36- for el in concepts :
37- visit (el .get_id ())
52+ for c in classifiers :
53+ visit (c .get_id ())
3854
3955 return sorted_list
4056
@@ -65,12 +81,30 @@ def main(dependencies, lionweb_language, output):
6581 names = [ast .alias (name = 'ABC' , asname = None )],
6682 level = 0
6783 )
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+ )
68102 import_node = ast .ImportFrom (
69103 module = 'pylasu.model' ,
70104 names = [ast .alias (name = 'Node' , asname = None )],
71105 level = 0
72106 )
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 = [])
74108
75109
76110 for element in language .get_elements ():
@@ -85,21 +119,79 @@ def main(dependencies, lionweb_language, output):
85119 else :
86120 raise ValueError (f"Unsupported { element } " )
87121
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 )
94193 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 ()
103195
104196 click .echo (f"📂 Saving results to: { output } " )
105197 generated_code = astor .to_source (module )
0 commit comments