Worked on semantics for graphs

This commit is contained in:
Kyler Olsen 2025-02-12 11:23:55 -07:00
parent 02c10b48f4
commit 72461740eb
1 changed files with 106 additions and 41 deletions

View File

@ -741,6 +741,24 @@ class InlineAnimation:
@property
def file_info(self) -> FileInfo: return self._file_info
@property
def range_start(self) -> Expression: return self._range_start
@property
def range_start_inclusive(self) -> bool: return self._range_start_inclusive
@property
def range_end(self) -> Expression: return self._range_end
@property
def range_end_inclusive(self) -> bool: return self._range_end_inclusive
@property
def step(self) -> Expression: return self._step
@property
def direction(self) -> AnimationDirection: return self._direction
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
s: str = f"{pre} Inline Animation\n"
s += f"{pre_cont}├─ Range Start \
@ -1850,6 +1868,19 @@ class UnderDefinedConstantDefinition(SemanticError):
)
class InvalidGraphDefinition(SemanticError): pass
class MultipleAnimationsInGraph(InvalidGraphDefinition):
def __init__(self, file_info: FileInfo, file_info_context: FileInfo | None):
super().__init__(
"Only one animation is allowed in a graph.",
file_info,
file_info_context,
)
class GraphRuntimeError(CompilerError):
@ -2250,6 +2281,7 @@ class ContextFunction:
class ContextAnimation:
_file_info: FileInfo
_current: int | float
_range_start: ContextExpression
_range_start_inclusive: bool
@ -2261,6 +2293,7 @@ class ContextAnimation:
def __init__(
self,
file_info: FileInfo,
start_value: int | float,
range_start: ContextExpression,
range_start_inclusive: bool,
@ -2269,6 +2302,7 @@ class ContextAnimation:
step: ContextExpression,
direction: AnimationDirection,
):
self._file_info = file_info
self._current = start_value
self._range_start = range_start
self._range_start_inclusive = range_start_inclusive
@ -2278,6 +2312,9 @@ class ContextAnimation:
self._direction = direction
self._reversed = direction == AnimationDirection.Decrease
@property
def file_info(self) -> FileInfo: return self._file_info
def step(self, context: ContextNamespace) -> int | float:
if self._direction == AnimationDirection.Increase or (
self._direction == AnimationDirection.Bounce and not self._reversed
@ -2672,6 +2709,35 @@ def _simplify_expression(
else: raise SemanticError("Expression Error", expression.file_info)
def _simplify_animation(
animation: Animation | InlineAnimation,
constants: dict[str, ContextLiteral],
functions: dict[str, ContextFunctionCallable],
) -> ContextAnimation:
range_start = _simplify_expression(
animation.range_start, constants, functions, True)
if not isinstance(range_start, ContextLiteral):
raise UnderDefinedConstantDefinition(
animation.range_start.file_info, None)
start_value = float(range_start._value)
range_end = _simplify_expression(
animation.range_end, constants, functions, True)
if not isinstance(range_end, ContextLiteral):
raise UnderDefinedConstantDefinition(
animation.range_end.file_info, None)
step = _simplify_expression(animation.step, constants, functions, True)
if not isinstance(step, ContextLiteral):
raise UnderDefinedConstantDefinition(animation.step.file_info, None)
return ContextAnimation(
start_value,
range_start,
animation.range_start_inclusive,
range_end,
animation.range_end_inclusive,
step,
animation.direction,
)
def semantics_analyzer(file: File) -> Context:
screen: Screen | None = None
constants: dict[str, ContextLiteral] = {}
@ -2703,43 +2769,8 @@ def semantics_analyzer(file: File) -> Context:
raise UnderDefinedConstantDefinition(child.file_info, None)
constants[child.identifier.value] = value
elif isinstance(child, Animation):
range_start = _simplify_expression(
child.range_start,
constants,
functions,
True,
)
if not isinstance(range_start, ContextLiteral):
raise UnderDefinedConstantDefinition(
child.range_start.file_info, None)
start_value = float(range_start._value)
range_end = _simplify_expression(
child.range_end,
constants,
functions,
True,
)
if not isinstance(range_end, ContextLiteral):
raise UnderDefinedConstantDefinition(
child.range_end.file_info, None)
step = _simplify_expression(
child.step,
constants,
functions,
True,
)
if not isinstance(step, ContextLiteral):
raise UnderDefinedConstantDefinition(
child.step.file_info, None)
animations[child.identifier.value] = ContextAnimation(
start_value,
range_start,
child.range_start_inclusive,
range_end,
child.range_end_inclusive,
step,
child.direction,
)
animations[child.identifier.value] = _simplify_animation(
child, constants, functions)
elif isinstance(child, Graph):
x = None
y = None
@ -2756,23 +2787,27 @@ def semantics_analyzer(file: File) -> Context:
color_luminosity = None
if child.x is not None:
if isinstance(child.x, InlineAnimation):
pass
x = _simplify_animation(
child.x, constants, functions)
else:
x = _simplify_expression(
child.x, constants, functions, True)
if child.y is not None:
if isinstance(child.y, InlineAnimation):
pass
y = _simplify_animation(
child.y, constants, functions)
else:
y = _simplify_expression(
child.y, constants, functions, True)
if child.t is not None:
pass
t = _simplify_animation(
child.t, constants, functions)
if child.r is not None:
r = _simplify_expression(
child.r, constants, functions, True)
if child.theta is not None:
pass
theta = _simplify_animation(
child.theta, constants, functions)
if child.color_alpha is not None:
color_alpha = _simplify_expression(
child.color_alpha, constants, functions, True)
@ -2797,6 +2832,36 @@ def semantics_analyzer(file: File) -> Context:
if child.color_luminosity is not None:
color_luminosity = _simplify_expression(
child.color_luminosity, constants, functions, True)
if isinstance(x, ContextAnimation):
for i in [y, t, theta]:
if isinstance(i, ContextAnimation):
raise MultipleAnimationsInGraph(
i.file_info,
child.file_info
)
for i, j in [(t, 'T'),(r, 'R'),(theta, 'θ')]:
if i is not None:
raise InvalidGraphDefinition(
f"{j} cannot be defined in an X-Independent Graph",
i.file_info,
child.file_info
)
if isinstance(y, ContextAnimation):
for i in [t, theta]:
if isinstance(i, ContextAnimation):
raise MultipleAnimationsInGraph(
i.file_info,
child.file_info
)
for i, j in [(t, 'T'),(r, 'R'),(theta, 'θ')]:
if i is not None:
raise InvalidGraphDefinition(
f"{j} cannot be defined in an Y-Independent Graph",
i.file_info,
child.file_info
)
graphs.append(ContextGraph(
x, y, t, r, theta, color_alpha, color_grey, color_red,
color_green, color_blue, color_hue, color_saturation,