Last active
May 3, 2024 02:04
-
-
Save aranega/b7ac11ca2554385ea4896545f6b5de0d to your computer and use it in GitHub Desktop.
Micro reflexive MDE-like kernel in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MList(object): | |
def __init__(self, owner, feature): | |
self.innerlist = [] | |
self.owner = owner | |
self.feature = feature | |
def size(self): | |
return len(self.innerlist) | |
def append(self, value, update_opposite=True): | |
if self.feature.get('composite'): | |
value.container = self.owner | |
self.innerlist.append(value) | |
opposite = self.feature.get('opposite') | |
if update_opposite and opposite: | |
if opposite.get('upper') < 0: | |
value.get(opposite.get('name')).append(self.owner, update_opposite=False) | |
else: | |
value.set(opposite.get('name'), self.owner, update_opposite=False) | |
def extend(self, iterable, update_opposite=True): | |
if self.feature.get('composite'): | |
for value in iterable: | |
value.container = self.owner | |
opposite = self.feature.get('opposite') | |
if update_opposite and opposite: | |
if opposite.get('upper') < 0: | |
value.get(opposite.get('name')).append(self.owner, update_opposite=False) | |
else: | |
value.set(opposite.get('name'), self.owner, update_opposite=False) | |
self.innerlist.extend(iterable) | |
def remove(self, value, update_opposite=True): | |
try: | |
self.innerlist.remove(value) | |
if self.feature.get('composite'): | |
value.container = None | |
opposite = self.feature.get('opposite') | |
if update_opposite and opposite: | |
if opposite.get('upper') < 0: | |
value.get(opposite.get('name')).remove(self.owner, update_opposite=False) | |
else: | |
value.set(opposite.get('name'), self.owner, update_opposite=False) | |
except Exception: | |
raise | |
def __iter__(self): | |
return iter(self.innerlist) | |
def __getitem__(self, index): | |
return self.innerlist[index] | |
def __repr__(self): | |
return repr(self.innerlist) | |
class MObject(object): | |
def __init__(self, metaclass=None): | |
self.mclass = metaclass | |
self.container = None | |
self.values = {} | |
def withValues(self, vals): | |
self.values.update(vals) | |
return self | |
def new(self, **kwargs): | |
instance = self.__class__(self) | |
for k, v in kwargs.items(): | |
instance.set(k, v) | |
## init trick | |
if k == 'opposite': | |
v.set('opposite', instance, update_opposite=False) | |
return instance | |
def get(self, name): | |
try: | |
return self.values[name] | |
except KeyError: | |
all_superclasses = self.mclass.all_inheritance() | |
features = {feature.get('name'): feature for superclass in all_superclasses for feature in superclass.get('features')} | |
if name not in features: | |
raise Exception(f"Feature {name} does not exist for {self.mclass.get('name')}") | |
feature = features[name] | |
if feature.get('upper') < 0: | |
self.values[name] = MList(self, feature) | |
else: | |
self.values[name] = feature.get('default') | |
return self.values[name] | |
def set(self, name, value, update_opposite=True): | |
all_superclasses = self.mclass.all_inheritance() | |
features = {feature.get('name'): feature for superclass in all_superclasses for feature in superclass.get('features')} | |
if name not in features: | |
raise Exception(f"Feature {name} does not exist for {self.mclass.get('name')}") | |
feature = features[name] | |
if feature.get('composite'): | |
value.container = self | |
self.values[name] = value | |
opposite = feature.get('opposite') | |
if update_opposite and opposite: | |
if opposite.get('upper') < 0: | |
value.get(opposite.get('name')).append(self, update_opposite=False) | |
else: | |
value.set(opposite.get('name'), self, update_opposite=False) | |
def all_inheritance(self): | |
res = [self] | |
for superclass in self.get('superclasses'): | |
res.extend(superclass.all_inheritance()) | |
return res | |
def instanceof(self, other): | |
if self.mclass is other: | |
return True | |
all_superclasses = self.mclass.all_inheritance() | |
return other in all_superclasses | |
## Create M3 level | |
M3Class = MObject() | |
M3Class.mclass = M3Class | |
M3Property = MObject(M3Class) | |
M3Property.values.update({ | |
'name': 'M3Property', | |
'superclasses': [], | |
'features': [ | |
MObject(M3Property).withValues({ | |
'name': 'name', | |
'type': str, | |
'upper': 1, | |
'composite': False, | |
'default': None, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'type', | |
'type': M3Class, | |
'upper': 1, | |
'composite': False, | |
'default': None, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'upper', | |
'type': int, | |
'upper': 1, | |
'composite': False, | |
'default': 1, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'composite', | |
'type': bool, | |
'upper': 1, | |
'composite': False, | |
'default': False, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'default', | |
'type': object, | |
'upper': 1, | |
'composite': False, | |
'default': None, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'opposite', | |
'type': M3Property, | |
'upper': 1, | |
'composite': False, | |
'default': None, | |
'opposite': None, | |
}), | |
] | |
}) | |
M3Class.values.update({ | |
'name': 'M3Class', | |
'superclasses': [], | |
'features': [ | |
MObject(M3Property).withValues({ | |
'name': 'name', | |
'type': str, | |
'upper': 1, | |
'composite': False, | |
'default': None, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'features', | |
'type': M3Property, | |
'upper': -1, | |
'composite': True, | |
'default': None, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'abstract', | |
'type': bool, | |
'upper': 1, | |
'composite': False, | |
'default': False, | |
'opposite': None, | |
}), | |
MObject(M3Property).withValues({ | |
'name': 'superclasses', | |
'type': M3Class, | |
'upper': -1, | |
'composite': False, | |
'default': False, | |
'opposite': None, | |
}), | |
] | |
}) | |
## Usage example | |
## Creating a M2 model (metamodel) | |
NamedElement = M3Class.new(name='NamedElement') | |
NamedElement.get('features').append( | |
M3Property.new(name='name', type=str) | |
) | |
Repository = M3Class.new(name='Repository') | |
Commit = M3Class.new(name='Commit') | |
Repository.get('superclasses').append(NamedElement) | |
Commit.get('superclasses').append(NamedElement) | |
commitsFeature = M3Property.new(name='commits', type=Commit, upper=-1, composite=True) | |
Repository.get('features').extend(( | |
M3Property.new(name='url', type=str), | |
commitsFeature | |
)) | |
Commit.get('features').extend(( | |
M3Property.new(name='repository', type=Repository, opposite=commitsFeature), | |
)) | |
## Creating M1 model instance of the defined M2 metamodel | |
r1 = Repository.new(url='http://github.com/stuff/truc', name='truc') | |
r1.get('commits').append(Commit.new(name='MYCOMMIT')) | |
print(commitsFeature.get('opposite')) | |
print(r1.get('commits')[0].get('name')) | |
print(r1.instanceof(NamedElement)) | |
print(r1.get('commits')) | |
print(r1.get('commits')[0].get('repository')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment