From 90d6e888e76adeed8be64adacd8d4027e9bc9b70 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Sun, 11 Jan 2026 15:11:39 -0800 Subject: [PATCH] conditionals working --- src/ytdl_sub/script/script.py | 29 +++++------ src/ytdl_sub/script/types/function.py | 74 +++++++++++++++++++++------ 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/src/ytdl_sub/script/script.py b/src/ytdl_sub/script/script.py index 56cf39e5..55002218 100644 --- a/src/ytdl_sub/script/script.py +++ b/src/ytdl_sub/script/script.py @@ -8,6 +8,7 @@ from typing import Set from ytdl_sub.script.functions import Functions from ytdl_sub.script.parser import parse from ytdl_sub.script.script_output import ScriptOutput +from ytdl_sub.script.types.resolvable import Argument from ytdl_sub.script.types.resolvable import BuiltInFunctionType from ytdl_sub.script.types.resolvable import Lambda from ytdl_sub.script.types.resolvable import Resolvable @@ -726,7 +727,7 @@ class Script: If specifying a filter of variable to resolve, and one of them does not. """ resolved: Dict[Variable, Resolvable] = {} - unresolved: Dict[Variable, VariableDependency] = {} + unresolved: Dict[Variable, Argument] = {} unresolvable: Set[Variable] = {Variable(name) for name in (unresolvable or {})} for variable_name, definition in self._variables.items(): @@ -739,17 +740,6 @@ class Script: if isinstance(arg, Resolvable): resolved[variable] = arg - elif isinstance(arg, Variable): - while isinstance(arg, Variable): - if arg in unresolvable: - break - arg = self._variables[arg.name] - - if resolved_arg := arg.maybe_resolvable: - resolved[variable] = resolved_arg - else: - assert isinstance(arg, SyntaxTree) - unresolved[variable] = arg.ast[0] else: unresolved[variable] = arg @@ -761,11 +751,16 @@ class Script: for variable in list(unresolved.keys()): definition = unresolved[variable] - maybe_resolved = definition.partial_resolve( - resolved_variables=resolved, - unresolved_variables=unresolved, - custom_functions=self._functions, - ) + if isinstance(definition, Variable): + maybe_resolved = resolved.get(definition, unresolved[definition]) + else: + assert isinstance(definition, VariableDependency) + maybe_resolved = definition.partial_resolve( + resolved_variables=resolved, + unresolved_variables=unresolved, + custom_functions=self._functions, + ) + if isinstance(maybe_resolved, Resolvable): resolved[variable] = maybe_resolved del unresolved[variable] diff --git a/src/ytdl_sub/script/types/function.py b/src/ytdl_sub/script/types/function.py index 54d89f22..8f8fbd85 100644 --- a/src/ytdl_sub/script/types/function.py +++ b/src/ytdl_sub/script/types/function.py @@ -11,6 +11,7 @@ from ytdl_sub.script.functions import Functions from ytdl_sub.script.types.array import Array from ytdl_sub.script.types.array import UnresolvedArray from ytdl_sub.script.types.resolvable import Argument +from ytdl_sub.script.types.resolvable import Boolean from ytdl_sub.script.types.resolvable import BuiltInFunctionType from ytdl_sub.script.types.resolvable import FunctionType from ytdl_sub.script.types.resolvable import FutureResolvable @@ -337,6 +338,50 @@ class BuiltInFunction(Function, BuiltInFunctionType): f"Runtime error occurred when executing the function %{self.name}: {str(exc)}" ) from exc + def _partial_resolve_conditional( + self, + resolved_variables: Dict[Variable, Resolvable], + unresolved_variables: Dict[Variable, Argument], + custom_functions: Dict[str, "VariableDependency"], + ): + if self.is_subset_of( + variables=resolved_variables, custom_function_definitions=custom_functions + ): + return self.resolve( + resolved_variables=resolved_variables, + custom_functions=custom_functions, + ) + + if self.name == "if": + maybe_resolvable_arg, is_resolvable = VariableDependency.try_partial_resolve( + args=[self.args[0]], + resolved_variables=resolved_variables, + unresolved_variables=unresolved_variables, + custom_functions=custom_functions, + ) + if is_resolvable: + boolean_output = maybe_resolvable_arg[0] + assert isinstance(boolean_output, Boolean) + return self.args[1] if boolean_output.native else self.args[2] + + if self.name == "elif": + for idx in range(0, len(self.args), 2): + maybe_resolvable_arg, is_resolvable = VariableDependency.try_partial_resolve( + args=[self.args[idx]], + resolved_variables=resolved_variables, + unresolved_variables=unresolved_variables, + custom_functions=custom_functions, + ) + if is_resolvable: + boolean_output = maybe_resolvable_arg[0] + assert isinstance(boolean_output, Boolean) + if boolean_output.native: + return self.args[idx + 1] + else: + break + + return self + def partial_resolve( self, resolved_variables: Dict[Variable, Resolvable], @@ -349,27 +394,24 @@ class BuiltInFunction(Function, BuiltInFunctionType): # If the function is conditional, only run if its entirety is resolvable if conditional_return_args: - if self.is_subset_of( - variables=resolved_variables, custom_function_definitions=custom_functions - ): - return self.resolve( - resolved_variables=resolved_variables, - custom_functions=custom_functions, - ) - return self - else: - maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve( - args=self.args, + return self._partial_resolve_conditional( resolved_variables=resolved_variables, unresolved_variables=unresolved_variables, custom_functions=custom_functions, ) - if is_resolvable: - return self.resolve( - resolved_variables=resolved_variables, - custom_functions=custom_functions, - ) + maybe_resolvable_values, is_resolvable = VariableDependency.try_partial_resolve( + args=self.args, + resolved_variables=resolved_variables, + unresolved_variables=unresolved_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)