Add lambda values

This commit is contained in:
James Westman 2022-07-09 19:20:15 -05:00
parent 30f0deea34
commit d7155981b1
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
8 changed files with 119 additions and 4 deletions

View file

@ -16,6 +16,7 @@ from .gtk_string_list import Strings
from .gtk_styles import Styles from .gtk_styles import Styles
from .gtkbuilder_child import Child from .gtkbuilder_child import Child
from .gtkbuilder_template import Template from .gtkbuilder_template import Template
from .lambdas import Lambda
from .imports import GtkDirective, Import from .imports import GtkDirective, Import
from .ui import UI from .ui import UI
from .values import IdentValue, TranslatedStringValue, FlagsValue, LiteralValue from .values import IdentValue, TranslatedStringValue, FlagsValue, LiteralValue
@ -47,4 +48,5 @@ VALUE_HOOKS.children = [
FlagsValue, FlagsValue,
IdentValue, IdentValue,
LiteralValue, LiteralValue,
Lambda,
] ]

View file

@ -33,3 +33,24 @@ from ..xml_emitter import XmlEmitter
OBJECT_HOOKS = AnyOf() OBJECT_HOOKS = AnyOf()
OBJECT_CONTENT_HOOKS = AnyOf() OBJECT_CONTENT_HOOKS = AnyOf()
VALUE_HOOKS = AnyOf() VALUE_HOOKS = AnyOf()
class Scope:
def get_variables(self) -> T.Iterator[str]:
yield from self.get_objects().keys()
def get_objects(self) -> T.Dict[str, T.Any]:
raise NotImplementedError()
@property
def this_name(self) -> T.Optional[str]:
return None
@property
def this_type(self) -> T.Optional[str]:
return None
@property
def this_type_glib_name(self) -> T.Optional[str]:
return None

View file

@ -41,7 +41,14 @@ class InfixExpr(AstNode):
class IdentExpr(AstNode): class IdentExpr(AstNode):
grammar = UseIdent("ident") grammar = UseIdent("ident")
@property
def is_this(self):
return self.parent_by_type(Scope).this_name == self.tokens["ident"]
def emit_xml(self, xml: XmlEmitter): def emit_xml(self, xml: XmlEmitter):
if self.is_this:
raise CompilerBugError()
xml.start_tag("constant") xml.start_tag("constant")
xml.put_text(self.tokens["ident"]) xml.put_text(self.tokens["ident"])
xml.end_tag() xml.end_tag()
@ -51,6 +58,9 @@ class LookupOp(InfixExpr):
grammar = [".", UseIdent("property")] grammar = [".", UseIdent("property")]
def emit_xml(self, xml: XmlEmitter): def emit_xml(self, xml: XmlEmitter):
if isinstance(self.lhs, IdentExpr) and self.lhs.is_this:
xml.put_self_closing("lookup", name=self.tokens["property"], type=self.parent_by_type(Scope).this_type)
else:
xml.start_tag("lookup", name=self.tokens["property"]) xml.start_tag("lookup", name=self.tokens["property"])
self.lhs.emit_xml(xml) self.lhs.emit_xml(xml)
xml.end_tag() xml.end_tag()

View file

@ -0,0 +1,54 @@
# lambdas.py
#
# Copyright 2022 James Westman <james@jwestman.net>
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: LGPL-3.0-or-later
from .types import TypeName
from .expression import Expr
from .values import Value
from .common import *
class Lambda(Value, Scope):
grammar = [
"(",
TypeName,
UseIdent("argument"),
")",
"=>",
Expr,
]
def emit_xml(self, xml: XmlEmitter):
for child in self.children:
child.emit_xml(xml)
def get_objects(self):
return {
**self.parent.parent_by_type(Scope).get_objects(),
self.tokens["argument"]: None,
}
@property
def this_name(self) -> str:
return self.tokens["argument"]
@property
def this_type(self) -> str:
return self.children[TypeName][0].gir_type

View file

@ -24,7 +24,7 @@ from .gtkbuilder_template import Template
from .common import * from .common import *
class UI(AstNode): class UI(AstNode, Scope):
""" The AST node for the entire file """ """ The AST node for the entire file """
grammar = [ grammar = [
@ -62,6 +62,8 @@ class UI(AstNode):
def objects_by_id(self): def objects_by_id(self):
return { obj.tokens["id"]: obj for obj in self.iterate_children_recursive() if obj.tokens["id"] is not None } 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
@validate() @validate()
def gir_errors(self): def gir_errors(self):

9
tests/samples/lambda.blp Normal file
View file

@ -0,0 +1,9 @@
using Gtk 4.0;
Gtk.BoolFilter filter {
expression: (Gtk.Label object) => object.visible;
}
Gtk.BoolFilter {
expression: (Gtk.Label object) => filter.invert;
}

16
tests/samples/lambda.ui Normal file
View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkBoolFilter" id="filter">
<property name="expression">
<lookup name="visible" type="GtkLabel"/>
</property>
</object>
<object class="GtkBoolFilter">
<property name="expression">
<lookup name="invert">
<constant>filter</constant>
</lookup>
</property>
</object>
</interface>

View file

@ -141,6 +141,7 @@ class TestSamples(unittest.TestCase):
self.assert_sample("flags") self.assert_sample("flags")
self.assert_sample("id_prop") self.assert_sample("id_prop")
self.assert_sample("inline_menu") self.assert_sample("inline_menu")
self.assert_sample("lambda")
self.assert_sample("layout") self.assert_sample("layout")
self.assert_sample("menu") self.assert_sample("menu")
self.assert_sample("numbers") self.assert_sample("numbers")