From 96c5760eafecb538e7fc6c698a65bbd97e7fbc4e Mon Sep 17 00:00:00 2001 From: jgcodes2020 Date: Tue, 24 Dec 2024 09:49:53 -0500 Subject: [PATCH] debug variant parsing --- blueprintcompiler/language/values.py | 33 ++++++++++++++++++++++++++- blueprintcompiler/language/variant.py | 7 ++++-- blueprintcompiler/utils.py | 15 ++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 4c7aab9..4d355c9 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -28,6 +28,10 @@ from .gobject_object import Object from .types import TypeName from .variant import VarContent +import gi +gi.require_version("GLib", "2.0") +from gi.repository import GLib + class Translated(AstNode): grammar = AnyOf( @@ -373,8 +377,17 @@ class IdentLiteral(AstNode): return None + class VariantValue(AstNode): - grammar = ["variant", "<", UseQuoted("type"), ">", "(", VarContent, ")"] + grammar = [ + "variant", + "<", + UseQuoted("type"), + ">", + "(", + Err(VarContent, "Invalid variant content!"), + ")", + ] @property def var_type(self) -> str: @@ -407,6 +420,24 @@ class VariantValue(AstNode): raise CompileError(f"Cannot convert variant into {expected_type.full_name}") pass + @validate("type") + def validate_type(self): + if not GLib.VariantType.string_is_valid(self.var_type): + raise CompileError(f"`{self.var_type}` is not a valid variant type") + + @validate() + def validate_content(self): + if not GLib.VariantType.string_is_valid(self.var_type): + return + + try: + var_ty = GLib.VariantType.new(self.var_type) + var_val = GLib.Variant.parse(var_ty, self.var_value) + except GLib.GError as error: + raise CompileError(f"Variant did not match specified type: {error}") + + pass + class Literal(AstNode): grammar = AnyOf( diff --git a/blueprintcompiler/language/variant.py b/blueprintcompiler/language/variant.py index 62c8458..bc0988f 100644 --- a/blueprintcompiler/language/variant.py +++ b/blueprintcompiler/language/variant.py @@ -38,7 +38,7 @@ class VarContentString(AstNode): @property def content(self) -> str: - return self.tokens["value"] + return utils.escape_quote(self.tokens["value"]) class VarContentNumber(AstNode): @@ -80,7 +80,10 @@ class VarContentDict(AstNode): @property def content(self) -> str: - inner = ", ".join(child.content for child in self.children) + inner = ", ".join( + f"{key.content}: {value.content}" + for (key, value) in utils.iter_batched(self.children, 2, strict=True) + ) return f"{{{inner}}}" diff --git a/blueprintcompiler/utils.py b/blueprintcompiler/utils.py index ea8102e..f579ea4 100644 --- a/blueprintcompiler/utils.py +++ b/blueprintcompiler/utils.py @@ -19,6 +19,7 @@ import typing as T from dataclasses import dataclass +import itertools class Colors: @@ -154,3 +155,17 @@ def unescape_quote(string: str) -> str: i += 1 return result + +def iter_batched(iterable, n, *, strict=False): + """ + Replacement for `itertools.batched()` since the testing infrastructure + uses Python 3.9 at the moment. Copied directly off of the Python docs. + """ + # batched('ABCDEFG', 3) → ABC DEF G + if n < 1: + raise ValueError('n must be at least one') + iterator = iter(iterable) + while batch := tuple(itertools.islice(iterator, n)): + if strict and len(batch) != n: + raise ValueError('batched(): incomplete batch') + yield batch \ No newline at end of file