Tweak the way scopes work

Should make it clearer what a "variable" is and allow more flexibility
in what a variable can be (previously it could only be an object, but
now it can be e.g. a reference to the template or a special shortcut)
This commit is contained in:
James Westman 2022-07-18 15:43:39 -05:00
parent d7155981b1
commit ae40f8416f
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
4 changed files with 37 additions and 12 deletions

View file

@ -35,11 +35,29 @@ OBJECT_CONTENT_HOOKS = AnyOf()
VALUE_HOOKS = AnyOf()
class Scope:
def get_variables(self) -> T.Iterator[str]:
yield from self.get_objects().keys()
class ScopeVariable:
def __init__(self, name: str, gir_class: gir.GirType, xml_func):
self._name = name
self._gir_class = gir_class
self._xml_func = xml_func
def get_objects(self) -> T.Dict[str, T.Any]:
@property
def name(self) -> str:
return self._name
@property
def gir_class(self) -> gir.GirType:
return self._gir_class
def emit_xml(self, xml: XmlEmitter):
if f := self._xml_func:
f(xml)
else:
raise NotImplementedError()
class Scope:
@property
def variables(self) -> T.Dict[str, ScopeVariable]:
raise NotImplementedError()
@property
@ -53,4 +71,3 @@ class Scope:
@property
def this_type_glib_name(self) -> T.Optional[str]:
return None

View file

@ -49,9 +49,7 @@ class IdentExpr(AstNode):
if self.is_this:
raise CompilerBugError()
xml.start_tag("constant")
xml.put_text(self.tokens["ident"])
xml.end_tag()
self.parent_by_type(Scope).variables[self.tokens["ident"]].emit_xml(xml)
class LookupOp(InfixExpr):

View file

@ -38,9 +38,10 @@ class Lambda(Value, Scope):
for child in self.children:
child.emit_xml(xml)
def get_objects(self):
@property
def variables(self) -> T.Dict[str, ScopeVariable]:
return {
**self.parent.parent_by_type(Scope).get_objects(),
**self.parent.parent_by_type(Scope).variables,
self.tokens["argument"]: None,
}

View file

@ -62,8 +62,17 @@ class UI(AstNode, Scope):
def objects_by_id(self):
return { obj.tokens["id"]: obj for obj in self.iterate_children_recursive() if obj.tokens["id"] is not None }
def get_objects(self):
return self.objects_by_id
@property
def variables(self):
def emit_xml(xml: XmlEmitter, obj_id: str):
xml.start_tag("constant")
xml.put_text(obj_id)
xml.end_tag()
return {
id: ScopeVariable(id, obj.gir_class, lambda xml: emit_xml(xml, id))
for id, obj in self.objects_by_id.items()
}
@validate()
def gir_errors(self):