Skip to content

Commit 6d5c4ea

Browse files
committed
Working on AST Generation
1 parent b23188c commit 6d5c4ea

File tree

2 files changed

+151
-27
lines changed

2 files changed

+151
-27
lines changed

pylasu/lionweb/ast_generation.py

+119-27
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,40 @@
11
import ast
2+
import keyword
23
from pathlib import Path
34
from typing import cast, List, Dict
45

56
import astor # Install with `pip install astor`
67
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
810
from lionwebpython.language.enumeration import Enumeration
911
from lionwebpython.language.primitive_type import PrimitiveType
12+
from lionwebpython.language.reference import Reference
1013
from lionwebpython.lionweb_version import LionWebVersion
1114
from lionwebpython.serialization.serialization_provider import SerializationProvider
1215

1316
from 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)

pylasu/model/metamodel.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from abc import ABC
2+
3+
4+
class Expression(ABC):
5+
pass
6+
7+
class PlaceholderElement(ABC):
8+
pass
9+
10+
class TypeAnnotation(ABC):
11+
pass
12+
13+
class Parameter(ABC):
14+
pass
15+
16+
class Statement(ABC):
17+
pass
18+
19+
class EntityDeclaration(ABC):
20+
pass
21+
22+
class BehaviorDeclaration(ABC):
23+
pass
24+
25+
class Documentation(ABC):
26+
pass
27+
28+
class Named(ABC):
29+
30+
@property
31+
def name(self) -> str:
32+
pass

0 commit comments

Comments
 (0)