Merge branch 'master' into j/resolution-level

This commit is contained in:
Jesse Bannon 2026-01-23 10:59:14 -08:00
commit 9c2a187778

View file

@ -1,4 +1,5 @@
# pylint: disable=missing-raises-doc # pylint: disable=missing-raises-doc
from collections import defaultdict
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional from typing import Optional
@ -37,13 +38,9 @@ class Script:
``{ %custom_function: syntax }`` ``{ %custom_function: syntax }``
""" """
def _ensure_no_cycle( def _throw_cycle_error(
self, name: str, dep: str, deps: List[str], definitions: Dict[str, SyntaxTree] self, name: str, dep: str, deps: List[str], definitions: Dict[str, SyntaxTree]
): ):
if dep not in definitions:
return # does not exist, will throw downstream in parser
if name in deps + [dep]:
type_name, pre = ( type_name, pre = (
("custom functions", "%") if definitions is self._functions else ("variables", "") ("custom functions", "%") if definitions is self._functions else ("variables", "")
) )
@ -57,39 +54,55 @@ class Script:
variable_name: str, variable_name: str,
variable_dependency: SyntaxTree, variable_dependency: SyntaxTree,
deps: List[str], deps: List[str],
ensured: Dict[str, Set[str]],
) -> None: ) -> None:
for dep in variable_dependency.variables: for dep in variable_dependency.variables:
self._ensure_no_cycle( if variable_name == dep.name:
self._throw_cycle_error(
name=variable_name, dep=dep.name, deps=deps, definitions=self._variables name=variable_name, dep=dep.name, deps=deps, definitions=self._variables
) )
if dep.name in ensured[variable_name]:
continue
self._traverse_variable_dependencies( self._traverse_variable_dependencies(
variable_name=variable_name, variable_name=variable_name,
variable_dependency=self._variables[dep.name], variable_dependency=self._variables[dep.name],
deps=deps + [dep.name], deps=deps + [dep.name],
ensured=ensured,
) )
ensured[variable_name].add(dep.name)
for custom_func in variable_dependency.custom_function_dependencies( for custom_func in variable_dependency.custom_function_dependencies(
custom_function_definitions=self._functions custom_function_definitions=self._functions
): ):
for dep in self._functions[custom_func.name].variables: for dep in self._functions[custom_func.name].variables:
self._ensure_no_cycle( if variable_name == dep.name:
self._throw_cycle_error(
name=variable_name, name=variable_name,
dep=dep.name, dep=dep.name,
deps=deps + [custom_func.definition_name()], deps=deps + [custom_func.definition_name()],
definitions=self._variables, definitions=self._variables,
) )
if dep.name in ensured[variable_name]:
continue
self._traverse_variable_dependencies( self._traverse_variable_dependencies(
variable_name=variable_name, variable_name=variable_name,
variable_dependency=self._variables[dep.name], variable_dependency=self._variables[dep.name],
deps=deps + [custom_func.definition_name(), dep.name], deps=deps + [custom_func.definition_name(), dep.name],
ensured=ensured,
) )
ensured[variable_name].add(dep.name)
def _ensure_no_variable_cycles(self, variables: Dict[str, SyntaxTree]): def _ensure_no_variable_cycles(self, variables: Dict[str, SyntaxTree]):
ensured: Dict[str, Set[str]] = defaultdict(set)
for variable_name, variable_definition in variables.items(): for variable_name, variable_definition in variables.items():
self._traverse_variable_dependencies( self._traverse_variable_dependencies(
variable_name=variable_name, variable_name=variable_name,
variable_dependency=variable_definition, variable_dependency=variable_definition,
deps=[], deps=[],
ensured=ensured,
) )
def _traverse_custom_function_dependencies( def _traverse_custom_function_dependencies(
@ -99,7 +112,8 @@ class Script:
deps: List[str], deps: List[str],
) -> None: ) -> None:
for dep in custom_function_dependency.custom_functions: for dep in custom_function_dependency.custom_functions:
self._ensure_no_cycle( if custom_function_name == dep.name:
self._throw_cycle_error(
name=custom_function_name, dep=dep.name, deps=deps, definitions=self._functions name=custom_function_name, dep=dep.name, deps=deps, definitions=self._functions
) )
self._traverse_custom_function_dependencies( self._traverse_custom_function_dependencies(