From ae40f8416f79a17a274d057f4d7f4fc3aacb6dc3 Mon Sep 17 00:00:00 2001 From: James Westman Date: Mon, 18 Jul 2022 15:43:39 -0500 Subject: [PATCH] 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) --- blueprintcompiler/language/common.py | 27 +++++++++++++++++++----- blueprintcompiler/language/expression.py | 4 +--- blueprintcompiler/language/lambdas.py | 5 +++-- blueprintcompiler/language/ui.py | 13 ++++++++++-- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/blueprintcompiler/language/common.py b/blueprintcompiler/language/common.py index 8cf07ce..7f524c2 100644 --- a/blueprintcompiler/language/common.py +++ b/blueprintcompiler/language/common.py @@ -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 - diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index 8f3bf1b..182d536 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -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): diff --git a/blueprintcompiler/language/lambdas.py b/blueprintcompiler/language/lambdas.py index 495659b..25dfd73 100644 --- a/blueprintcompiler/language/lambdas.py +++ b/blueprintcompiler/language/lambdas.py @@ -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, } diff --git a/blueprintcompiler/language/ui.py b/blueprintcompiler/language/ui.py index 9191120..541fd24 100644 --- a/blueprintcompiler/language/ui.py +++ b/blueprintcompiler/language/ui.py @@ -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):