language: Support boxed types and GType

- Add support for type checking boxed types
- Remove support for converting string and number literals
- Add the `typeof()` operator for GType literals
This commit is contained in:
James Westman 2022-09-16 22:33:49 -05:00
parent ee2b9b2950
commit c0c40b1577
No known key found for this signature in database
GPG key ID: CE2DBA0ADB654EA6
12 changed files with 140 additions and 26 deletions

View file

@ -18,7 +18,7 @@ from .gtkbuilder_child import Child
from .gtkbuilder_template import Template
from .imports import GtkDirective, Import
from .ui import UI
from .values import IdentValue, TranslatedStringValue, FlagsValue, LiteralValue
from .values import TypeValue, IdentValue, TranslatedStringValue, FlagsValue, QuotedValue, NumberValue
from .common import *
@ -43,8 +43,10 @@ OBJECT_CONTENT_HOOKS.children = [
]
VALUE_HOOKS.children = [
TypeValue,
TranslatedStringValue,
FlagsValue,
IdentValue,
LiteralValue,
QuotedValue,
NumberValue,
]

View file

@ -19,6 +19,7 @@
from .common import *
from .types import TypeName
class Value(AstNode):
@ -55,11 +56,68 @@ class TranslatedStringValue(Value):
xml.put_text(self.tokens["value"])
class LiteralValue(Value):
grammar = AnyOf(
UseNumber("value"),
UseQuoted("value"),
)
class TypeValue(Value):
grammar = [
"typeof",
"(",
to_parse_node(TypeName).expected("type name"),
Match(")").expected(),
]
@property
def type_name(self):
return self.children[TypeName][0]
def emit_xml(self, xml: XmlEmitter):
xml.put_text(self.type_name.glib_type_name)
@validate()
def validate_for_type(self):
type = self.parent.value_type
if type is not None and not isinstance(type, gir.TypeType):
raise CompileError(f"Cannot convert GType to {type.full_name}")
class QuotedValue(Value):
grammar = UseQuoted("value")
def emit_xml(self, xml: XmlEmitter):
xml.put_text(self.tokens["value"])
@validate()
def validate_for_type(self):
type = self.parent.value_type
if isinstance(type, gir.IntType) or isinstance(type, gir.UIntType) or isinstance(type, gir.FloatType):
raise CompileError(f"Cannot convert string to number")
elif isinstance(type, gir.StringType):
pass
elif isinstance(type, gir.Class) or isinstance(type, gir.Interface) or isinstance(type, gir.Boxed):
parseable_types = [
"Gdk.Paintable",
"Gdk.Texture",
"Gdk.Pixbuf",
"GLib.File",
"Gtk.ShortcutTrigger",
"Gtk.ShortcutAction",
"Gdk.RGBA",
"Gdk.ContentFormats",
"Gsk.Transform",
"GLib.Variant",
]
if type.full_name not in parseable_types:
hints = []
if isinstance(type, gir.TypeType):
hints.append(f"use the typeof operator: 'typeof({self.tokens('value')})'")
raise CompileError(f"Cannot convert string to {type.full_name}", hints=hints)
elif type is not None:
raise CompileError(f"Cannot convert string to {type.full_name}")
class NumberValue(Value):
grammar = UseNumber("value")
def emit_xml(self, xml: XmlEmitter):
xml.put_text(self.tokens["value"])
@ -87,23 +145,8 @@ class LiteralValue(Value):
except:
raise CompileError(f"Cannot convert {self.group.tokens['value']} to float")
elif isinstance(type, gir.StringType):
pass
elif isinstance(type, gir.Class) or isinstance(type, gir.Interface):
parseable_types = [
"Gdk.Paintable",
"Gdk.Texture",
"Gdk.Pixbuf",
"GLib.File",
"Gtk.ShortcutTrigger",
"Gtk.ShortcutAction",
]
if type.full_name not in parseable_types:
raise CompileError(f"Cannot convert {self.group.tokens['value']} to {type.full_name}")
elif type is not None:
raise CompileError(f"Cannot convert {self.group.tokens['value']} to {type.full_name}")
raise CompileError(f"Cannot convert number to {type.full_name}")
class Flag(AstNode):