semantics mostly done
This commit is contained in:
parent
72461740eb
commit
0836610b3d
465
compiler.py
465
compiler.py
|
|
@ -1974,6 +1974,11 @@ class ContextNamespace:
|
||||||
return self._parent.lookup_func(function)
|
return self._parent.lookup_func(function)
|
||||||
|
|
||||||
|
|
||||||
|
class ContextNamespaceNull(ContextNamespace):
|
||||||
|
|
||||||
|
def __init__(self): pass
|
||||||
|
|
||||||
|
|
||||||
class ContextExpression:
|
class ContextExpression:
|
||||||
|
|
||||||
_file_info: FileInfo
|
_file_info: FileInfo
|
||||||
|
|
@ -2265,20 +2270,6 @@ class ContextFunctionCall(ContextExpression):
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ContextFunction:
|
|
||||||
|
|
||||||
_context: "Context"
|
|
||||||
_values: "dict[str, ContextAnimation | ContextExpression]"
|
|
||||||
|
|
||||||
|
|
||||||
def value(self, context: ContextNamespace) -> int | float:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ContextAnimation:
|
class ContextAnimation:
|
||||||
|
|
||||||
_file_info: FileInfo
|
_file_info: FileInfo
|
||||||
|
|
@ -2315,6 +2306,10 @@ class ContextAnimation:
|
||||||
@property
|
@property
|
||||||
def file_info(self) -> FileInfo: return self._file_info
|
def file_info(self) -> FileInfo: return self._file_info
|
||||||
|
|
||||||
|
@property
|
||||||
|
def as_context_literal(self) -> ContextLiteral:
|
||||||
|
return ContextLiteral(self.file_info, str(self._current))
|
||||||
|
|
||||||
def step(self, context: ContextNamespace) -> int | float:
|
def step(self, context: ContextNamespace) -> int | float:
|
||||||
if self._direction == AnimationDirection.Increase or (
|
if self._direction == AnimationDirection.Increase or (
|
||||||
self._direction == AnimationDirection.Bounce and not self._reversed
|
self._direction == AnimationDirection.Bounce and not self._reversed
|
||||||
|
|
@ -2373,36 +2368,39 @@ class ColorSpace(Enum):
|
||||||
|
|
||||||
class ContextGraph:
|
class ContextGraph:
|
||||||
|
|
||||||
_x: None | ContextFunction | ContextAnimation
|
_file_info: FileInfo
|
||||||
_y: None | ContextFunction | ContextAnimation
|
_x: None | ContextExpression | ContextAnimation
|
||||||
|
_y: None | ContextExpression | ContextAnimation
|
||||||
_t: None | ContextAnimation
|
_t: None | ContextAnimation
|
||||||
_r: None | ContextFunction
|
_r: None | ContextExpression
|
||||||
_theta: None | ContextAnimation
|
_theta: None | ContextAnimation
|
||||||
_color_alpha: None | ContextFunction
|
_color_alpha: None | ContextExpression
|
||||||
_color_grey: None | ContextFunction
|
_color_grey: None | ContextExpression
|
||||||
_color_red: None | ContextFunction
|
_color_red: None | ContextExpression
|
||||||
_color_green: None | ContextFunction
|
_color_green: None | ContextExpression
|
||||||
_color_blue: None | ContextFunction
|
_color_blue: None | ContextExpression
|
||||||
_color_hue: None | ContextFunction
|
_color_hue: None | ContextExpression
|
||||||
_color_saturation: None | ContextFunction
|
_color_saturation: None | ContextExpression
|
||||||
_color_luminosity: None | ContextFunction
|
_color_luminosity: None | ContextExpression
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
x: None | ContextFunction | ContextAnimation,
|
file_info: FileInfo,
|
||||||
y: None | ContextFunction | ContextAnimation,
|
x: None | ContextExpression | ContextAnimation,
|
||||||
|
y: None | ContextExpression | ContextAnimation,
|
||||||
t: None | ContextAnimation,
|
t: None | ContextAnimation,
|
||||||
r: None | ContextFunction,
|
r: None | ContextExpression,
|
||||||
theta: None | ContextAnimation,
|
theta: None | ContextAnimation,
|
||||||
color_alpha: None | ContextFunction,
|
color_alpha: None | ContextExpression,
|
||||||
color_grey: None | ContextFunction,
|
color_grey: None | ContextExpression,
|
||||||
color_red: None | ContextFunction,
|
color_red: None | ContextExpression,
|
||||||
color_green: None | ContextFunction,
|
color_green: None | ContextExpression,
|
||||||
color_blue: None | ContextFunction,
|
color_blue: None | ContextExpression,
|
||||||
color_hue: None | ContextFunction,
|
color_hue: None | ContextExpression,
|
||||||
color_saturation: None | ContextFunction,
|
color_saturation: None | ContextExpression,
|
||||||
color_luminosity: None | ContextFunction,
|
color_luminosity: None | ContextExpression,
|
||||||
):
|
):
|
||||||
|
self._file_info = file_info
|
||||||
self._x = x
|
self._x = x
|
||||||
self._y = y
|
self._y = y
|
||||||
self._t = t
|
self._t = t
|
||||||
|
|
@ -2417,6 +2415,45 @@ class ContextGraph:
|
||||||
self._color_saturation = color_saturation
|
self._color_saturation = color_saturation
|
||||||
self._color_luminosity = color_luminosity
|
self._color_luminosity = color_luminosity
|
||||||
|
|
||||||
|
@property
|
||||||
|
def file_info(self) -> FileInfo: return self._file_info
|
||||||
|
|
||||||
|
def _local_ns(
|
||||||
|
self,
|
||||||
|
context: ContextNamespace,
|
||||||
|
skip: list[str] | None = None,
|
||||||
|
) -> ContextNamespace:
|
||||||
|
skip = skip or []
|
||||||
|
namespace: dict[\
|
||||||
|
str, int | float | ContextExpression | ContextAnimation] = {}
|
||||||
|
if self._x is not None and 'x' not in skip:
|
||||||
|
namespace['x'] = self._x
|
||||||
|
if self._y is not None and 'y' not in skip:
|
||||||
|
namespace['y'] = self._y
|
||||||
|
if self._t is not None and 't' not in skip:
|
||||||
|
namespace['t'] = self._t
|
||||||
|
if self._r is not None and 'r' not in skip:
|
||||||
|
namespace['r'] = self._r
|
||||||
|
if self._theta is not None and 'θ' not in skip:
|
||||||
|
namespace['θ'] = self._theta
|
||||||
|
if self._color_alpha is not None and 'c_a' not in skip:
|
||||||
|
namespace['c_a'] = self._color_alpha
|
||||||
|
if self._color_grey is not None and 'c_w' not in skip:
|
||||||
|
namespace['c_w'] = self._color_grey
|
||||||
|
if self._color_red is not None and 'c_r' not in skip:
|
||||||
|
namespace['c_r'] = self._color_red
|
||||||
|
if self._color_green is not None and 'c_g' not in skip:
|
||||||
|
namespace['c_g'] = self._color_green
|
||||||
|
if self._color_blue is not None and 'c_b' not in skip:
|
||||||
|
namespace['c_b'] = self._color_blue
|
||||||
|
if self._color_hue is not None and 'c_h' not in skip:
|
||||||
|
namespace['c_h'] = self._color_hue
|
||||||
|
if self._color_saturation is not None and 'c_s' not in skip:
|
||||||
|
namespace['c_s'] = self._color_saturation
|
||||||
|
if self._color_luminosity is not None and 'c_l' not in skip:
|
||||||
|
namespace['c_l'] = self._color_luminosity
|
||||||
|
return ContextNamespace(context, namespace)
|
||||||
|
|
||||||
def step(self, context: ContextNamespace) -> tuple[
|
def step(self, context: ContextNamespace) -> tuple[
|
||||||
int | float,
|
int | float,
|
||||||
int | float,
|
int | float,
|
||||||
|
|
@ -2426,26 +2463,26 @@ class ContextGraph:
|
||||||
]:
|
]:
|
||||||
match self.graph_type:
|
match self.graph_type:
|
||||||
case GraphType.X_Independent:
|
case GraphType.X_Independent:
|
||||||
x_last = self._x.value(context) # type: ignore
|
x_last = self._x.value(self._local_ns(context, ['x'])) # type: ignore
|
||||||
y_last = self._y.value(context) # type: ignore
|
y_last = self._y.value(self._local_ns(context, ['y'])) # type: ignore
|
||||||
x = self._x.step(context) # type: ignore
|
x = self._x.step(self._local_ns(context, ['x'])) # type: ignore
|
||||||
y = self._y.value(context) # type: ignore
|
y = self._y.value(self._local_ns(context, ['y'])) # type: ignore
|
||||||
case GraphType.Y_Independent:
|
case GraphType.Y_Independent:
|
||||||
y_last = self._y.value(context) # type: ignore
|
y_last = self._y.value(self._local_ns(context, ['y'])) # type: ignore
|
||||||
x_last = self._x.value(context) # type: ignore
|
x_last = self._x.value(self._local_ns(context, ['x'])) # type: ignore
|
||||||
y = self._y.step(context) # type: ignore
|
y = self._y.step(self._local_ns(context, ['y'])) # type: ignore
|
||||||
x = self._x.value(context) # type: ignore
|
x = self._x.value(self._local_ns(context, ['x'])) # type: ignore
|
||||||
case GraphType.Parametric:
|
case GraphType.Parametric:
|
||||||
x_last = self._x.value(context) # type: ignore
|
x_last = self._x.value(self._local_ns(context, ['x'])) # type: ignore
|
||||||
y_last = self._y.value(context) # type: ignore
|
y_last = self._y.value(self._local_ns(context, ['y'])) # type: ignore
|
||||||
self._t.step(context) # type: ignore
|
self._t.step(self._local_ns(context, ['t'])) # type: ignore
|
||||||
x = self._x.value(context) # type: ignore
|
x = self._x.value(self._local_ns(context, ['x'])) # type: ignore
|
||||||
y = self._y.value(context) # type: ignore
|
y = self._y.value(self._local_ns(context, ['y'])) # type: ignore
|
||||||
case GraphType.Polar:
|
case GraphType.Polar:
|
||||||
theta_last = self._theta.value(context) # type: ignore
|
theta_last = self._theta.value(self._local_ns(context, ['θ'])) # type: ignore
|
||||||
r_last = self._r.value(context) # type: ignore
|
r_last = self._r.value(self._local_ns(context, ['r'])) # type: ignore
|
||||||
theta = self._theta.step(context) # type: ignore
|
theta = self._theta.step(self._local_ns(context, ['θ'])) # type: ignore
|
||||||
r = self._r.value(context) # type: ignore
|
r = self._r.value(self._local_ns(context, ['r'])) # type: ignore
|
||||||
x_last = r_last * math.cos(theta_last)
|
x_last = r_last * math.cos(theta_last)
|
||||||
y_last = r_last * math.sin(theta_last)
|
y_last = r_last * math.sin(theta_last)
|
||||||
x = r * math.cos(theta)
|
x = r * math.cos(theta)
|
||||||
|
|
@ -2463,21 +2500,21 @@ class ContextGraph:
|
||||||
elif isinstance(self._theta, ContextAnimation):
|
elif isinstance(self._theta, ContextAnimation):
|
||||||
return GraphType.Polar
|
return GraphType.Polar
|
||||||
else:
|
else:
|
||||||
raise SemanticsError("Invalid Function Type.")
|
raise GraphRuntimeError("Invalid Graph.", self.file_info)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def color_space(self) -> ColorSpace:
|
def color_space(self) -> ColorSpace:
|
||||||
if isinstance(self._color_red, ContextFunction):
|
if isinstance(self._color_red, ContextExpression):
|
||||||
return ColorSpace.RGB
|
return ColorSpace.RGB
|
||||||
elif isinstance(self._color_green, ContextFunctionCallable):
|
elif isinstance(self._color_green, ContextExpression):
|
||||||
return ColorSpace.RGB
|
return ColorSpace.RGB
|
||||||
elif isinstance(self._color_blue, ContextFunctionCallable):
|
elif isinstance(self._color_blue, ContextExpression):
|
||||||
return ColorSpace.RGB
|
return ColorSpace.RGB
|
||||||
elif isinstance(self._color_hue, ContextFunctionCallable):
|
elif isinstance(self._color_hue, ContextExpression):
|
||||||
return ColorSpace.HSL
|
return ColorSpace.HSL
|
||||||
elif isinstance(self._color_saturation, ContextFunctionCallable):
|
elif isinstance(self._color_saturation, ContextExpression):
|
||||||
return ColorSpace.HSL
|
return ColorSpace.HSL
|
||||||
elif isinstance(self._color_luminosity, ContextFunctionCallable):
|
elif isinstance(self._color_luminosity, ContextExpression):
|
||||||
return ColorSpace.HSL
|
return ColorSpace.HSL
|
||||||
else:
|
else:
|
||||||
return ColorSpace.Grey
|
return ColorSpace.Grey
|
||||||
|
|
@ -2485,23 +2522,23 @@ class ContextGraph:
|
||||||
def color(
|
def color(
|
||||||
self, context: ContextNamespace) -> tuple[float,float,float,float,]:
|
self, context: ContextNamespace) -> tuple[float,float,float,float,]:
|
||||||
if self._color_alpha is not None:
|
if self._color_alpha is not None:
|
||||||
a = self._color_alpha.value(context)
|
a = self._color_alpha.value(self._local_ns(context, ['c_a']))
|
||||||
else: a = 1
|
else: a = 1
|
||||||
match self.color_space:
|
match self.color_space:
|
||||||
case ColorSpace.Grey:
|
case ColorSpace.Grey:
|
||||||
if self._color_grey is not None:
|
if self._color_grey is not None:
|
||||||
c = self._color_grey.value(context)
|
c = self._color_grey.value(self._local_ns(context, ['c_w']))
|
||||||
else: c = 1
|
else: c = 1
|
||||||
r, g, b = c, c, c
|
r, g, b = c, c, c
|
||||||
case ColorSpace.RGB:
|
case ColorSpace.RGB:
|
||||||
if self._color_red is not None:
|
if self._color_red is not None:
|
||||||
r = self._color_red.value(context)
|
r = self._color_red.value(self._local_ns(context, ['c_r']))
|
||||||
else: r = 1
|
else: r = 1
|
||||||
if self._color_green is not None:
|
if self._color_green is not None:
|
||||||
g = self._color_green.value(context)
|
g = self._color_green.value(self._local_ns(context, ['c_g']))
|
||||||
else: g = 1
|
else: g = 1
|
||||||
if self._color_blue is not None:
|
if self._color_blue is not None:
|
||||||
b = self._color_blue.value(context)
|
b = self._color_blue.value(self._local_ns(context, ['c_b']))
|
||||||
else: b = 1
|
else: b = 1
|
||||||
case ColorSpace.HSL:
|
case ColorSpace.HSL:
|
||||||
r,g,b = 1,1,1
|
r,g,b = 1,1,1
|
||||||
|
|
@ -2510,22 +2547,43 @@ class ContextGraph:
|
||||||
def value(self, context: ContextNamespace) -> int | float:
|
def value(self, context: ContextNamespace) -> int | float:
|
||||||
match self.graph_type:
|
match self.graph_type:
|
||||||
case GraphType.X_Independent:
|
case GraphType.X_Independent:
|
||||||
return self._x.value(context) # type: ignore
|
return self._x.value(self._local_ns(context, ['x'])) # type: ignore
|
||||||
case GraphType.Y_Independent:
|
case GraphType.Y_Independent:
|
||||||
return self._y.value(context) # type: ignore
|
return self._y.value(self._local_ns(context, ['y'])) # type: ignore
|
||||||
case GraphType.Parametric:
|
case GraphType.Parametric:
|
||||||
return self._t.value(context) # type: ignore
|
return self._t.value(self._local_ns(context, ['t'])) # type: ignore
|
||||||
case GraphType.Polar:
|
case GraphType.Polar:
|
||||||
return self._theta.value(context) # type: ignore
|
return self._theta.value(self._local_ns(context, ['θ'])) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
|
|
||||||
|
_file_info: FileInfo
|
||||||
|
_screen: Screen
|
||||||
_constants: dict[str, int | float]
|
_constants: dict[str, int | float]
|
||||||
_functions: dict[str, ContextFunctionCallable]
|
_functions: dict[str, ContextFunctionCallable]
|
||||||
_animations: dict[str, ContextAnimation]
|
_animations: dict[str, ContextAnimation]
|
||||||
_graphs: list[ContextGraph]
|
_graphs: list[ContextGraph]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
file_info: FileInfo,
|
||||||
|
screen: Screen,
|
||||||
|
constants: dict[str, int | float],
|
||||||
|
functions: dict[str, ContextFunctionCallable],
|
||||||
|
animations: dict[str, ContextAnimation],
|
||||||
|
graphs: list[ContextGraph],
|
||||||
|
):
|
||||||
|
self._file_info = file_info
|
||||||
|
self._screen = screen
|
||||||
|
self._constants = constants
|
||||||
|
self._functions = functions
|
||||||
|
self._animations = animations
|
||||||
|
self._graphs = graphs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def file_info(self) -> FileInfo: return self._file_info
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
for anim in self._animations.values():
|
for anim in self._animations.values():
|
||||||
anim.step(ContextNamespace(self))
|
anim.step(ContextNamespace(self))
|
||||||
|
|
@ -2546,6 +2604,16 @@ class Context:
|
||||||
return self._functions[function.identifier]
|
return self._functions[function.identifier]
|
||||||
|
|
||||||
|
|
||||||
|
def _constants_and_animations(
|
||||||
|
constants: dict[str, ContextLiteral],
|
||||||
|
animations: dict[str, ContextAnimation],
|
||||||
|
) -> dict[str, ContextLiteral]:
|
||||||
|
combined: dict[str, ContextLiteral] = {}
|
||||||
|
for key, value in constants.items(): combined[key] = value
|
||||||
|
for key, value in animations.items():
|
||||||
|
combined[key] = value.as_context_literal
|
||||||
|
return combined
|
||||||
|
|
||||||
def _simplify_expression(
|
def _simplify_expression(
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
constants: dict[str, ContextLiteral],
|
constants: dict[str, ContextLiteral],
|
||||||
|
|
@ -2604,8 +2672,8 @@ def _simplify_expression(
|
||||||
isinstance(value1, ContextLiteral) and
|
isinstance(value1, ContextLiteral) and
|
||||||
isinstance(value2, ContextLiteral)
|
isinstance(value2, ContextLiteral)
|
||||||
):
|
):
|
||||||
value1 = float(value1._value)
|
value1 = math.pi if value1._value == 'π' else float(value1._value)
|
||||||
value2 = float(value2._value)
|
value2 = math.pi if value2._value == 'π' else float(value2._value)
|
||||||
match expression.operator:
|
match expression.operator:
|
||||||
case BinaryOperator.Exponential:
|
case BinaryOperator.Exponential:
|
||||||
return ContextLiteral(
|
return ContextLiteral(
|
||||||
|
|
@ -2681,7 +2749,7 @@ def _simplify_expression(
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if all(isinstance(a, ContextLiteral) for a in args):
|
if all(isinstance(a, ContextLiteral) for a in args):
|
||||||
args = [a._value for a in args] # type: ignore
|
args = [math.pi if a._value == 'π' else float(a._value) for a in args] # type: ignore
|
||||||
bad_arg, domain = func.check_domain(args)
|
bad_arg, domain = func.check_domain(args)
|
||||||
if bad_arg > 0:
|
if bad_arg > 0:
|
||||||
raise FunctionDomainError(
|
raise FunctionDomainError(
|
||||||
|
|
@ -2708,7 +2776,6 @@ def _simplify_expression(
|
||||||
)
|
)
|
||||||
else: raise SemanticError("Expression Error", expression.file_info)
|
else: raise SemanticError("Expression Error", expression.file_info)
|
||||||
|
|
||||||
|
|
||||||
def _simplify_animation(
|
def _simplify_animation(
|
||||||
animation: Animation | InlineAnimation,
|
animation: Animation | InlineAnimation,
|
||||||
constants: dict[str, ContextLiteral],
|
constants: dict[str, ContextLiteral],
|
||||||
|
|
@ -2729,6 +2796,7 @@ def _simplify_animation(
|
||||||
if not isinstance(step, ContextLiteral):
|
if not isinstance(step, ContextLiteral):
|
||||||
raise UnderDefinedConstantDefinition(animation.step.file_info, None)
|
raise UnderDefinedConstantDefinition(animation.step.file_info, None)
|
||||||
return ContextAnimation(
|
return ContextAnimation(
|
||||||
|
animation.file_info,
|
||||||
start_value,
|
start_value,
|
||||||
range_start,
|
range_start,
|
||||||
animation.range_start_inclusive,
|
animation.range_start_inclusive,
|
||||||
|
|
@ -2738,6 +2806,140 @@ def _simplify_animation(
|
||||||
animation.direction,
|
animation.direction,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _check_graph(graph, name, anim, yes_none, not_none):
|
||||||
|
for i in anim:
|
||||||
|
if isinstance(i, ContextAnimation):
|
||||||
|
raise MultipleAnimationsInGraph(
|
||||||
|
i.file_info,
|
||||||
|
graph.file_info
|
||||||
|
)
|
||||||
|
for i, j in yes_none:
|
||||||
|
if i is not None:
|
||||||
|
raise InvalidGraphDefinition(
|
||||||
|
f"{j} cannot be defined in a {name} Graph",
|
||||||
|
i.file_info,
|
||||||
|
graph.file_info
|
||||||
|
)
|
||||||
|
for i, j in not_none:
|
||||||
|
if i is None:
|
||||||
|
raise InvalidGraphDefinition(
|
||||||
|
f"{j} must be defined in a {name} Graph",
|
||||||
|
graph.file_info
|
||||||
|
)
|
||||||
|
|
||||||
|
def _simplify_graph(
|
||||||
|
graph: Graph,
|
||||||
|
constants: dict[str, ContextLiteral],
|
||||||
|
functions: dict[str, ContextFunctionCallable],
|
||||||
|
) -> ContextGraph:
|
||||||
|
x = None
|
||||||
|
y = None
|
||||||
|
t = None
|
||||||
|
r = None
|
||||||
|
theta = None
|
||||||
|
color_alpha = None
|
||||||
|
color_grey = None
|
||||||
|
color_red = None
|
||||||
|
color_green = None
|
||||||
|
color_blue = None
|
||||||
|
color_hue = None
|
||||||
|
color_saturation = None
|
||||||
|
color_luminosity = None
|
||||||
|
if graph.x is not None:
|
||||||
|
if isinstance(graph.x, InlineAnimation):
|
||||||
|
x = _simplify_animation(
|
||||||
|
graph.x, constants, functions)
|
||||||
|
else:
|
||||||
|
x = _simplify_expression(
|
||||||
|
graph.x, constants, functions)
|
||||||
|
if graph.y is not None:
|
||||||
|
if isinstance(graph.y, InlineAnimation):
|
||||||
|
y = _simplify_animation(
|
||||||
|
graph.y, constants, functions)
|
||||||
|
else:
|
||||||
|
y = _simplify_expression(
|
||||||
|
graph.y, constants, functions)
|
||||||
|
if graph.t is not None:
|
||||||
|
t = _simplify_animation(
|
||||||
|
graph.t, constants, functions)
|
||||||
|
if graph.r is not None:
|
||||||
|
r = _simplify_expression(
|
||||||
|
graph.r, constants, functions)
|
||||||
|
if graph.theta is not None:
|
||||||
|
theta = _simplify_animation(
|
||||||
|
graph.theta, constants, functions)
|
||||||
|
if graph.color_alpha is not None:
|
||||||
|
color_alpha = _simplify_expression(
|
||||||
|
graph.color_alpha, constants, functions)
|
||||||
|
if graph.color_grey is not None:
|
||||||
|
color_grey = _simplify_expression(
|
||||||
|
graph.color_grey, constants, functions)
|
||||||
|
if graph.color_red is not None:
|
||||||
|
color_red = _simplify_expression(
|
||||||
|
graph.color_red, constants, functions)
|
||||||
|
if graph.color_green is not None:
|
||||||
|
color_green = _simplify_expression(
|
||||||
|
graph.color_green, constants, functions)
|
||||||
|
if graph.color_blue is not None:
|
||||||
|
color_blue = _simplify_expression(
|
||||||
|
graph.color_blue, constants, functions)
|
||||||
|
if graph.color_hue is not None:
|
||||||
|
color_hue = _simplify_expression(
|
||||||
|
graph.color_hue, constants, functions)
|
||||||
|
if graph.color_saturation is not None:
|
||||||
|
color_saturation = _simplify_expression(
|
||||||
|
graph.color_saturation, constants, functions)
|
||||||
|
if graph.color_luminosity is not None:
|
||||||
|
color_luminosity = _simplify_expression(
|
||||||
|
graph.color_luminosity, constants, functions)
|
||||||
|
|
||||||
|
if isinstance(x, ContextAnimation):
|
||||||
|
_check_graph(
|
||||||
|
graph,
|
||||||
|
"X-Independent",
|
||||||
|
[y, t, theta,],
|
||||||
|
[(t, 'T'),(r, 'R'),(theta, 'θ'),],
|
||||||
|
[(y, 'Y'),]
|
||||||
|
)
|
||||||
|
elif isinstance(y, ContextAnimation):
|
||||||
|
_check_graph(
|
||||||
|
graph,
|
||||||
|
"Y-Independent",
|
||||||
|
[x, t, theta,],
|
||||||
|
[(t, 'T'),(r, 'R'),(theta, 'θ'),],
|
||||||
|
[(x, 'X'),]
|
||||||
|
)
|
||||||
|
elif isinstance(t, ContextAnimation):
|
||||||
|
_check_graph(
|
||||||
|
graph,
|
||||||
|
"Parametric",
|
||||||
|
[x, y, theta,],
|
||||||
|
[(r, 'R'),(theta, 'θ'),],
|
||||||
|
[(x, 'X'),(y, 'Y'),]
|
||||||
|
)
|
||||||
|
elif isinstance(theta, ContextAnimation):
|
||||||
|
_check_graph(
|
||||||
|
graph,
|
||||||
|
"Polar",
|
||||||
|
[x, y, t,],
|
||||||
|
[(x, 'X'),(y, 'Y'),(t, 'T'),],
|
||||||
|
[(r, 'R'),]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise InvalidGraphDefinition(
|
||||||
|
"A graph must have at least one animation.",
|
||||||
|
graph.file_info
|
||||||
|
)
|
||||||
|
|
||||||
|
return ContextGraph(
|
||||||
|
graph.file_info,
|
||||||
|
x, y, t,
|
||||||
|
r, theta,
|
||||||
|
color_alpha, color_grey,
|
||||||
|
color_red, color_green, color_blue,
|
||||||
|
color_hue, color_saturation, color_luminosity,
|
||||||
|
)
|
||||||
|
|
||||||
def semantics_analyzer(file: File) -> Context:
|
def semantics_analyzer(file: File) -> Context:
|
||||||
screen: Screen | None = None
|
screen: Screen | None = None
|
||||||
constants: dict[str, ContextLiteral] = {}
|
constants: dict[str, ContextLiteral] = {}
|
||||||
|
|
@ -2761,7 +2963,7 @@ def semantics_analyzer(file: File) -> Context:
|
||||||
elif isinstance(child, Constant):
|
elif isinstance(child, Constant):
|
||||||
value = _simplify_expression(
|
value = _simplify_expression(
|
||||||
child.expression,
|
child.expression,
|
||||||
constants,
|
_constants_and_animations(constants,animations),
|
||||||
functions,
|
functions,
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
|
|
@ -2770,105 +2972,29 @@ def semantics_analyzer(file: File) -> Context:
|
||||||
constants[child.identifier.value] = value
|
constants[child.identifier.value] = value
|
||||||
elif isinstance(child, Animation):
|
elif isinstance(child, Animation):
|
||||||
animations[child.identifier.value] = _simplify_animation(
|
animations[child.identifier.value] = _simplify_animation(
|
||||||
child, constants, functions)
|
child,
|
||||||
|
_constants_and_animations(constants,animations),
|
||||||
|
functions,
|
||||||
|
)
|
||||||
elif isinstance(child, Graph):
|
elif isinstance(child, Graph):
|
||||||
x = None
|
graphs.append(_simplify_graph(
|
||||||
y = None
|
child,
|
||||||
t = None
|
_constants_and_animations(constants,animations),
|
||||||
r = None
|
functions,
|
||||||
theta = None
|
|
||||||
color_alpha = None
|
|
||||||
color_grey = None
|
|
||||||
color_red = None
|
|
||||||
color_green = None
|
|
||||||
color_blue = None
|
|
||||||
color_hue = None
|
|
||||||
color_saturation = None
|
|
||||||
color_luminosity = None
|
|
||||||
if child.x is not None:
|
|
||||||
if isinstance(child.x, InlineAnimation):
|
|
||||||
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):
|
|
||||||
y = _simplify_animation(
|
|
||||||
child.y, constants, functions)
|
|
||||||
else:
|
|
||||||
y = _simplify_expression(
|
|
||||||
child.y, constants, functions, True)
|
|
||||||
if child.t is not None:
|
|
||||||
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:
|
|
||||||
theta = _simplify_animation(
|
|
||||||
child.theta, constants, functions)
|
|
||||||
if child.color_alpha is not None:
|
|
||||||
color_alpha = _simplify_expression(
|
|
||||||
child.color_alpha, constants, functions, True)
|
|
||||||
if child.color_grey is not None:
|
|
||||||
color_grey = _simplify_expression(
|
|
||||||
child.color_grey, constants, functions, True)
|
|
||||||
if child.color_red is not None:
|
|
||||||
color_red = _simplify_expression(
|
|
||||||
child.color_red, constants, functions, True)
|
|
||||||
if child.color_green is not None:
|
|
||||||
color_green = _simplify_expression(
|
|
||||||
child.color_green, constants, functions, True)
|
|
||||||
if child.color_blue is not None:
|
|
||||||
color_blue = _simplify_expression(
|
|
||||||
child.color_blue, constants, functions, True)
|
|
||||||
if child.color_hue is not None:
|
|
||||||
color_hue = _simplify_expression(
|
|
||||||
child.color_hue, constants, functions, True)
|
|
||||||
if child.color_saturation is not None:
|
|
||||||
color_saturation = _simplify_expression(
|
|
||||||
child.color_saturation, constants, functions, True)
|
|
||||||
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,
|
|
||||||
color_luminosity,
|
|
||||||
))
|
))
|
||||||
if screen is None:
|
if screen is None:
|
||||||
screen = Screen(file.file_info)
|
screen = Screen(file.file_info)
|
||||||
|
context_constants: dict[str, int | float] = {}
|
||||||
|
for key, value in constants.items():
|
||||||
|
context_constants[key] = value.value(ContextNamespaceNull())
|
||||||
|
return Context(
|
||||||
|
file.file_info,
|
||||||
|
screen,
|
||||||
|
context_constants,
|
||||||
|
functions,
|
||||||
|
animations,
|
||||||
|
graphs,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
@ -2881,6 +3007,7 @@ if __name__ == '__main__':
|
||||||
syntax_tree = syntactical_analyzer(tokens)
|
syntax_tree = syntactical_analyzer(tokens)
|
||||||
with open("syntax.txt", 'w', encoding='utf-8') as file:
|
with open("syntax.txt", 'w', encoding='utf-8') as file:
|
||||||
file.write(syntax_tree.tree_str())
|
file.write(syntax_tree.tree_str())
|
||||||
|
context = semantics_analyzer(syntax_tree)
|
||||||
except CompilerError as err:
|
except CompilerError as err:
|
||||||
print(err.compiler_error())
|
print(err.compiler_error())
|
||||||
# raise
|
# raise
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue