Merge branch 'variant-literal' into 'main'

Draft: Syntax for variants

See merge request jwestman/blueprint-compiler!224
This commit is contained in:
jgcodes2020 2025-01-04 16:29:46 +00:00
commit 79e3e4d8ab
9 changed files with 338 additions and 14 deletions

View file

@ -19,6 +19,8 @@
import typing as T
import gi
from blueprintcompiler.gir import ArrayType
from blueprintcompiler.lsp_utils import SemanticToken
@ -26,6 +28,10 @@ from .common import *
from .contexts import ScopeCtx, ValueTypeCtx
from .gobject_object import Object
from .types import TypeName
from .variant import VarContent
gi.require_version("GLib", "2.0")
from gi.repository import GLib
class Translated(AstNode):
@ -372,6 +378,67 @@ class IdentLiteral(AstNode):
return None
class VariantValue(AstNode):
grammar = [
"variant",
"<",
UseQuoted("type"),
">",
"(",
Err(VarContent, "Invalid variant content!"),
")",
]
@property
def var_type(self) -> str:
return self.tokens["type"]
@property
def var_value(self) -> str:
return self.children[0].content
@validate()
def validate_for_type(self) -> None:
expected_type = self.context[ValueTypeCtx].value_type
if expected_type is None:
pass
elif (
isinstance(expected_type, gir.IntType)
or isinstance(expected_type, gir.UIntType)
or isinstance(expected_type, gir.FloatType)
or isinstance(expected_type, gir.FloatType)
):
raise CompileError(f"Cannot convert variant to number")
elif isinstance(expected_type, gir.StringType):
raise CompileError("Cannot convert variant to string")
elif (
isinstance(expected_type, gir.Boxed)
and expected_type.full_name == "GLib.Variant"
):
pass
else:
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(
TypeLiteral,