[BACKEND] partial resolve support

This commit is contained in:
Jesse Bannon 2026-01-04 00:08:43 -08:00
parent b2056bec5d
commit e86e414ad9
4 changed files with 118 additions and 0 deletions

View file

@ -11,6 +11,7 @@ from ytdl_sub.script.types.resolvable import NonHashable
from ytdl_sub.script.types.resolvable import Resolvable
from ytdl_sub.script.types.resolvable import ResolvableToJson
from ytdl_sub.script.types.variable import Variable
from ytdl_sub.script.types.variable_dependency import TypeT
from ytdl_sub.script.types.variable_dependency import VariableDependency
@ -47,6 +48,25 @@ class UnresolvedArray(_Array, VariableDependency, FutureResolvable):
]
)
def partial_resolve(
self,
resolved_variables: Dict[Variable, Resolvable],
custom_functions: Dict[str, "VariableDependency"],
) -> "UnresolvedArray" | Resolvable:
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
args=self.value,
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
if is_resolvable:
return self.resolve(
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
return UnresolvedArray(value=maybe_resolvable_values)
def future_resolvable_type(self) -> Type[Resolvable]:
return Array

View file

@ -22,6 +22,7 @@ from ytdl_sub.script.types.resolvable import ReturnableArgumentA
from ytdl_sub.script.types.resolvable import ReturnableArgumentB
from ytdl_sub.script.types.variable import FunctionArgument
from ytdl_sub.script.types.variable import Variable
from ytdl_sub.script.types.variable_dependency import TypeT
from ytdl_sub.script.types.variable_dependency import VariableDependency
from ytdl_sub.script.utils.exception_formatters import FunctionArgumentsExceptionFormatter
from ytdl_sub.script.utils.exceptions import UNREACHABLE
@ -38,6 +39,25 @@ class Function(FunctionType, VariableDependency, ABC):
def _iterable_arguments(self) -> List[Argument]:
return self.args
def partial_resolve(
self: TypeT,
resolved_variables: Dict[Variable, Resolvable],
custom_functions: Dict[str, "VariableDependency"],
) -> TypeT | Resolvable:
maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve(
args=self.value,
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
if is_resolvable:
return self.resolve(
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
return BuiltInFunction(name=self.name, args=maybe_resolvable_values)
class CustomFunction(Function, NamedCustomFunction):
def resolve(

View file

@ -55,6 +55,31 @@ class UnresolvedMap(_Map, VariableDependency, FutureResolvable):
return Map(output)
def partial_resolve(
self,
resolved_variables: Dict[Variable, Resolvable],
custom_functions: Dict[str, "VariableDependency"],
) -> "UnresolvedMap" | Resolvable:
maybe_resolvable_keys, is_keys_resolvable = VariableDependency.try_partial_resolve(
args=self.value.keys(),
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
maybe_resolvable_values, is_values_resolvable = VariableDependency.try_partial_resolve(
args=self.value.values(),
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
if is_keys_resolvable and is_values_resolvable:
return self.resolve(
resolved_variables=resolved_variables,
custom_functions=custom_functions,
)
return UnresolvedMap(value=dict(zip(maybe_resolvable_keys, maybe_resolvable_values)))
def future_resolvable_type(self) -> Type[Resolvable]:
return Map

View file

@ -5,6 +5,7 @@ from typing import Dict
from typing import Iterable
from typing import List
from typing import Set
from typing import Tuple
from typing import Type
from typing import TypeVar
from typing import final
@ -138,6 +139,25 @@ class VariableDependency(ABC):
Resolved value
"""
@abstractmethod
def partial_resolve(
self: TypeT,
resolved_variables: Dict[Variable, Resolvable],
custom_functions: Dict[str, "VariableDependency"],
) -> TypeT | Resolvable:
"""
Parameters
----------
resolved_variables
Lookup of variables that have been resolved
custom_functions
Lookup of any custom functions that have been parsed
Returns
-------
Either a fully resolved value or partially resolved value of the same type.
"""
@classmethod
def _resolve_argument_type(
cls,
@ -222,3 +242,36 @@ class VariableDependency(ABC):
):
return True
return len(self.variables.intersection(variables)) > 0
@classmethod
def try_partial_resolve(
cls,
args: Iterable[Argument],
resolved_variables: Dict[Variable, Resolvable],
custom_functions: Dict[str, "VariableDependency"],
) -> Tuple[List[Argument], bool]:
maybe_resolvable_args: List[Resolvable | Argument] = []
is_resolvable = True
for arg in args:
if isinstance(arg, Lambda) and arg.value in custom_functions:
maybe_resolvable_args.append(arg)
if not custom_functions[arg.value].is_subset_of(
variables=resolved_variables,
custom_function_definitions=custom_functions,
):
is_resolvable = False
elif isinstance(arg, VariableDependency):
maybe_resolvable_args.append(
arg.partial_resolve(
resolved_variables=resolved_variables, custom_functions=custom_functions
)
)
if not isinstance(maybe_resolvable_args[-1], Resolvable):
is_resolvable = False
else:
maybe_resolvable_args.append(arg)
return maybe_resolvable_args, is_resolvable