From 773be6487c5e66f52530c396b81ac90de56b6af0 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 2 Jan 2023 22:00:51 -0500 Subject: [PATCH] apply->eval reduction and style stuff --- mathics/builtin/colors/color_directives.py | 70 ++++++++----- mathics/builtin/compilation.py | 10 +- mathics/builtin/distance/numeric.py | 64 ++++++++---- mathics/builtin/distance/stringdata.py | 9 +- mathics/builtin/drawing/graphics3d.py | 8 +- mathics/builtin/drawing/uniform_polyhedra.py | 101 ++++++++++--------- 6 files changed, 155 insertions(+), 107 deletions(-) diff --git a/mathics/builtin/colors/color_directives.py b/mathics/builtin/colors/color_directives.py index b9fe2c174..8bdacddfa 100644 --- a/mathics/builtin/colors/color_directives.py +++ b/mathics/builtin/colors/color_directives.py @@ -1,7 +1,9 @@ """ Color Directives -There are many different way to specify color; we support all of the color formats below and will convert between the different color formats. +There are many different way to specify color, and we support many of these. + +We can convert between the different color formats. """ from math import atan2, cos, exp, pi, radians, sin, sqrt @@ -119,6 +121,24 @@ def _euclidean_distance(a, b): return sqrt(sum((x1 - x2) * (x1 - x2) for x1, x2 in zip(a, b))) +def color_to_expression(components, colorspace): + if colorspace == "Grayscale": + converted_color_name = "GrayLevel" + elif colorspace == "HSB": + converted_color_name = "Hue" + else: + converted_color_name = colorspace + "Color" + + return to_expression(converted_color_name, *components) + + +def expression_to_color(color): + try: + return _ColorObject.create(color) + except ColorError: + return None + + class _ColorObject(_GraphicsDirective, ImmutableValueMixin): formats = { # we are adding ImageSizeMultipliers in the rule below, because we do _not_ want color boxes to @@ -306,7 +326,7 @@ class ColorDistance(Builtin): / 100, } - def apply(self, c1, c2, evaluation, options): + def eval(self, c1, c2, evaluation, options): "ColorDistance[c1_, c2_, OptionsPattern[ColorDistance]]" distance_function = options.get("System`DistanceFunction") @@ -431,7 +451,9 @@ class ColorError(BoxExpressionError): class GrayLevel(_ColorObject): """ - :WMA link:https://reference.wolfram.com/language/ref/GrayLevel.html + + :WMA link: + https://reference.wolfram.com/language/ref/GrayLevel.html
'GrayLevel[$g$]' @@ -449,7 +471,9 @@ class GrayLevel(_ColorObject): class Hue(_ColorObject): """ - :WMA link:https://reference.wolfram.com/language/ref/Hue.html + + :WMA link: + https://reference.wolfram.com/language/ref/Hue.html
'Hue[$h$, $s$, $l$, $a$]' @@ -509,7 +533,9 @@ def trans(t): class LABColor(_ColorObject): """ - :WMA link:https://reference.wolfram.com/language/ref/LABColor.html + + :WMA link: + https://reference.wolfram.com/language/ref/LABColor.html
'LABColor[$l$, $a$, $b$]' @@ -525,7 +551,9 @@ class LABColor(_ColorObject): class LCHColor(_ColorObject): """ - :WMA link:https://reference.wolfram.com/language/ref/LCHColor.html + + :WMA link: + https://reference.wolfram.com/language/ref/LCHColor.html
'LCHColor[$l$, $c$, $h$]' @@ -556,7 +584,9 @@ class LUVColor(_ColorObject): class Opacity(_GraphicsDirective): """ - :WMA link:https://reference.wolfram.com/language/ref/Opacity.html + + :WMA link: + https://reference.wolfram.com/language/ref/Opacity.html
'Opacity[$level$]' @@ -592,7 +622,9 @@ def create_as_style(klass, graphics, item): class RGBColor(_ColorObject): """ - :WMA link:https://reference.wolfram.com/language/ref/RGBColor.html + + :WMA link: + https://reference.wolfram.com/language/ref/RGBColor.html
'RGBColor[$r$, $g$, $b$]' @@ -620,7 +652,9 @@ def to_rgba(self): class XYZColor(_ColorObject): """ - :WMA link:https://reference.wolfram.com/language/ref/XYZColor.html + + :WMA link: + https://reference.wolfram.com/language/ref/XYZColor.html
'XYZColor[$x$, $y$, $z$]' @@ -631,21 +665,3 @@ class XYZColor(_ColorObject): color_space = "XYZ" components_sizes = [3, 4] default_components = [0, 0, 0, 1] - - -def expression_to_color(color): - try: - return _ColorObject.create(color) - except ColorError: - return None - - -def color_to_expression(components, colorspace): - if colorspace == "Grayscale": - converted_color_name = "GrayLevel" - elif colorspace == "HSB": - converted_color_name = "Hue" - else: - converted_color_name = colorspace + "Color" - - return to_expression(converted_color_name, *components) diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index 0a3570121..54bb7e21e 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -3,7 +3,8 @@ Code compilation allows Mathics functions to be run faster. -When LLVM and Python libraries are available, compilation produces LLVM code. +When LLVM and Python libraries are available, compilation \ +produces LLVM code. """ # This tells documentation how to sort this module @@ -25,6 +26,7 @@ ) from mathics.core.convert.python import from_python from mathics.core.element import ImmutableValueMixin +from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression, SymbolCompiledFunction from mathics.core.symbols import Atom, Symbol, SymbolFalse, SymbolTrue @@ -98,7 +100,7 @@ class Compile(Builtin): requires = ("llvmlite",) summary_text = "compile an expression" - def apply(self, vars, expr, evaluation): + def eval(self, vars, expr, evaluation: Evaluation): "Compile[vars_, expr_]" if not vars.has_form("List", None): @@ -174,7 +176,7 @@ def to_sympy(self, *args, **kwargs): def __hash__(self): return hash(("CompiledCode", ctypes.addressof(self.cfunc))) # XXX hack - def atom_to_boxes(self, f, evaluation): + def atom_to_boxes(self, f, evaluation: Evaluation): return CompiledCodeBox(String(self.__str__()), evaluation=evaluation) @@ -199,7 +201,7 @@ class CompiledFunction(Builtin): messages = {"argerr": "Invalid argument `1` should be Integer, Real or boolean."} summary_text = "A CompiledFunction object." - def apply(self, argnames, expr, code, args, evaluation): + def eval(self, argnames, expr, code, args, evaluation: Evaluation): "CompiledFunction[argnames_, expr_, code_CompiledCode][args__]" argseq = args.get_sequence() diff --git a/mathics/builtin/distance/numeric.py b/mathics/builtin/distance/numeric.py index 491aaf4db..e29841685 100644 --- a/mathics/builtin/distance/numeric.py +++ b/mathics/builtin/distance/numeric.py @@ -4,7 +4,7 @@ from mathics.builtin.base import Builtin from mathics.core.atoms import Integer1, Integer2 -from mathics.core.expression import Expression +from mathics.core.expression import Evaluation, Expression from mathics.core.symbols import ( SymbolAbs, SymbolDivide, @@ -21,7 +21,7 @@ ) -def _norm_calc(head, u, v, evaluation): +def _norm_calc(head, u, v, evaluation: Evaluation): expr = Expression(head, u, v) old_quiet_all = evaluation.quiet_all try: @@ -38,8 +38,11 @@ def _norm_calc(head, u, v, evaluation): class BrayCurtisDistance(Builtin): """ - :Bray-Curtis Dissimilarity:https://en.wikipedia.org/wiki/Bray%E2%80%93Curtis_dissimilarity \ - (:WMA link:https://reference.wolfram.com/language/ref/BrayCurtisDistance.html) + + :Bray-Curtis Dissimilarity: + https://en.wikipedia.org/wiki/Bray%E2%80%93Curtis_dissimilarity \ + (:WMA: + https://reference.wolfram.com/language/ref/BrayCurtisDistance.html)
'BrayCurtisDistance[$u$, $v$]' @@ -56,7 +59,7 @@ class BrayCurtisDistance(Builtin): summary_text = "Bray-Curtis distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "BrayCurtisDistance[u_, v_]" t = _norm_calc(SymbolSubtract, u, v, evaluation) if t is not None: @@ -71,8 +74,12 @@ def apply(self, u, v, evaluation): class CanberraDistance(Builtin): """ - :Canberra distance:https://en.wikipedia.org/wiki/Canberra_distance \ - (:WMA link:https://reference.wolfram.com/language/ref/CanberraDistance.html) + + :Canberra distance: + https://en.wikipedia.org/wiki/Canberra_distance \ + ( + :WMA: + https://reference.wolfram.com/language/ref/CanberraDistance.html)
'CanberraDistance[$u$, $v$]' @@ -88,7 +95,7 @@ class CanberraDistance(Builtin): summary_text = "Canberra distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "CanberraDistance[u_, v_]" t = _norm_calc(SymbolSubtract, u, v, evaluation) if t is not None: @@ -107,7 +114,9 @@ def apply(self, u, v, evaluation): class ChessboardDistance(Builtin): """ :Chebyshev distance:https://en.wikipedia.org/wiki/Chebyshev_distance \ - (:WMA link:https://reference.wolfram.com/language/ref/ChessboardDistance.html) + ( + :WMA: + https://reference.wolfram.com/language/ref/ChessboardDistance.html)
'ChessboardDistance[$u$, $v$]' @@ -123,7 +132,7 @@ class ChessboardDistance(Builtin): summary_text = "chessboard distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "ChessboardDistance[u_, v_]" t = _norm_calc(SymbolSubtract, u, v, evaluation) if t is not None: @@ -132,8 +141,11 @@ def apply(self, u, v, evaluation): class CosineDistance(Builtin): r""" - :Cosine similarity:https://en.wikipedia.org/wiki/Cosine_similarity \ - (:WMA link:https://reference.wolfram.com/language/ref/CosineDistance.html) + + :Cosine similarity: + https://en.wikipedia.org/wiki/Cosine_similarity \ + (:WMA: + https://reference.wolfram.com/language/ref/CosineDistance.html)
'CosineDistance[$u$, $v$]' @@ -152,7 +164,7 @@ class CosineDistance(Builtin): summary_text = "cosine distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "CosineDistance[u_, v_]" dot = _norm_calc(SymbolDot, u, v, evaluation) if dot is not None: @@ -173,8 +185,12 @@ def apply(self, u, v, evaluation): class EuclideanDistance(Builtin): """ - :Euclidean similarity:https://en.wikipedia.org/wiki/Euclidean_distance \ - (:WMA link:https://reference.wolfram.com/language/ref/EuclideanDistance.html) + + :Euclidean similarity: + https://en.wikipedia.org/wiki/Euclidean_distance \ + ( + :WMA: + https://reference.wolfram.com/language/ref/EuclideanDistance.html)
'EuclideanDistance[$u$, $v$]' @@ -193,7 +209,7 @@ class EuclideanDistance(Builtin): summary_text = "euclidean distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "EuclideanDistance[u_, v_]" t = _norm_calc(SymbolSubtract, u, v, evaluation) if t is not None: @@ -202,8 +218,12 @@ def apply(self, u, v, evaluation): class ManhattanDistance(Builtin): """ - :Manhattan distance:https://en.wikipedia.org/wiki/Taxicab_geometry \ - (:WMA link:https://reference.wolfram.com/language/ref/ManhattanDistance.html) + + :Manhattan distance: + https://en.wikipedia.org/wiki/Taxicab_geometry \ + ( + :WMA: + https://reference.wolfram.com/language/ref/ManhattanDistance.html)
'ManhattanDistance[$u$, $v$]' @@ -219,7 +239,7 @@ class ManhattanDistance(Builtin): summary_text = "Manhattan distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "ManhattanDistance[u_, v_]" t = _norm_calc(SymbolSubtract, u, v, evaluation) if t is not None: @@ -228,7 +248,9 @@ def apply(self, u, v, evaluation): class SquaredEuclideanDistance(Builtin): """ - :WMA link:https://reference.wolfram.com/language/ref/SquaredEuclideanDistance.html + + :WMA link: + https://reference.wolfram.com/language/ref/SquaredEuclideanDistance.html
'SquaredEuclideanDistance[$u$, $v$]' @@ -244,7 +266,7 @@ class SquaredEuclideanDistance(Builtin): summary_text = "square of the euclidean distance" - def apply(self, u, v, evaluation): + def eval(self, u, v, evaluation: Evaluation): "SquaredEuclideanDistance[u_, v_]" t = _norm_calc(SymbolSubtract, u, v, evaluation) if t is not None: diff --git a/mathics/builtin/distance/stringdata.py b/mathics/builtin/distance/stringdata.py index 7b44523d0..cab3a8044 100644 --- a/mathics/builtin/distance/stringdata.py +++ b/mathics/builtin/distance/stringdata.py @@ -8,6 +8,7 @@ from mathics.builtin.base import Builtin from mathics.core.atoms import Integer, String, Symbol +from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.symbols import SymbolTrue @@ -117,7 +118,7 @@ def _levenshtein_like_or_border_cases(s1, s2, sameQ: Callable[..., bool], comput class _StringDistance(Builtin): options = {"IgnoreCase": "False"} - def apply(self, a, b, evaluation, options): + def eval(self, a, b, evaluation, options): "%(name)s[a_, b_, OptionsPattern[%(name)s]]" if isinstance(a, String) and isinstance(b, String): py_a = a.get_string_value() @@ -255,20 +256,20 @@ class HammingDistance(Builtin): summary_text = "Hamming distance" @staticmethod - def _compute(u, v, sameQ, evaluation): + def _compute(u, v, sameQ, evaluation: Evaluation): if len(u) != len(v): evaluation.message("HammingDistance", "idim", u, v) return None else: return Integer(sum(0 if sameQ(x, y) else 1 for x, y in zip(u, v))) - def apply_list(self, u, v, evaluation): + def eval_list(self, u, v, evaluation: Evaluation): "HammingDistance[u_List, v_List]" return HammingDistance._compute( u.elements, v.elements, lambda x, y: x.sameQ(y), evaluation ) - def apply_string(self, u, v, evaluation, options): + def eval_string(self, u, v, evaluation, options): "HammingDistance[u_String, v_String, OptionsPattern[HammingDistance]]" ignore_case = self.get_option(options, "IgnoreCase", evaluation) py_u = u.get_string_value() diff --git a/mathics/builtin/drawing/graphics3d.py b/mathics/builtin/drawing/graphics3d.py index 55b5b876c..3cb3e7bbf 100644 --- a/mathics/builtin/drawing/graphics3d.py +++ b/mathics/builtin/drawing/graphics3d.py @@ -18,7 +18,7 @@ _GraphicsElements, ) from mathics.core.atoms import Integer, Rational, Real -from mathics.core.expression import Expression +from mathics.core.expression import Evaluation, Expression from mathics.core.symbols import SymbolN from mathics.eval.nevaluator import eval_N @@ -242,7 +242,7 @@ class Cone(Builtin): "Cone[positions_List]": "Cone[positions, 1]", } - def apply_check(self, positions, radius, evaluation): + def eval_check(self, positions, radius, evaluation: Evaluation): "Cone[positions_List, radius_]" if len(positions.elements) % 2 == 1: @@ -300,7 +300,7 @@ class Cuboid(Builtin): summary_text = "unit cube" - def apply_check(self, positions, evaluation): + def eval_check(self, positions, evaluation: Evaluation): "Cuboid[positions_List]" if len(positions.elements) % 2 == 1: @@ -343,7 +343,7 @@ class Cylinder(Builtin): "Cylinder[positions_List]": "Cylinder[positions, 1]", } - def apply_check(self, positions, radius, evaluation): + def eval_check(self, positions, radius, evaluation: Evaluation): "Cylinder[positions_List, radius_]" if len(positions.elements) % 2 == 1: diff --git a/mathics/builtin/drawing/uniform_polyhedra.py b/mathics/builtin/drawing/uniform_polyhedra.py index 2c69fb93d..03f6d10e9 100644 --- a/mathics/builtin/drawing/uniform_polyhedra.py +++ b/mathics/builtin/drawing/uniform_polyhedra.py @@ -3,7 +3,8 @@ """ Uniform Polyhedra -Uniform polyhedra is the grouping of platonic solids, Archimedean solids, and regular star polyhedra. +Uniform polyhedra is the grouping of platonic solids, Archimedean solids,\ +and regular star polyhedra. """ # This tells documentation how to sort this module @@ -11,52 +12,16 @@ sort_order = "mathics.builtin.uniform-polyhedra" from mathics.builtin.base import Builtin +from mathics.core.evaluation import Evaluation uniform_polyhedra_names = "tetrahedron, octahedron, dodecahedron, icosahedron" uniform_polyhedra_set = frozenset(uniform_polyhedra_names.split(", ")) -class UniformPolyhedron(Builtin): - """ - :WMA link:https://reference.wolfram.com/language/ref/UniformPolyhedron.html - -
-
'UniformPolyhedron["name"]' -
return a uniform polyhedron with the given name. -
Names are "tetrahedron", "octahedron", "dodecahedron", or "icosahedron". -
- - >> Graphics3D[UniformPolyhedron["octahedron"]] - = -Graphics3D- - - >> Graphics3D[UniformPolyhedron["dodecahedron"]] - = -Graphics3D- - - >> Graphics3D[{"Brown", UniformPolyhedron["tetrahedron"]}] - = -Graphics3D- - """ - - summary_text = "platonic polyhedra by name" - messages = { - "argtype": f"Argument `1` is not one of: {uniform_polyhedra_names}", - } - - rules = { - "UniformPolyhedron[name_String]": "UniformPolyhedron[name, {{0, 0, 0}}, 1]", - } - - def apply(self, name, positions, edgelength, evaluation): - "UniformPolyhedron[name_String, positions_List, edgelength_?NumberQ]" - - if name.to_python(string_quotes=False) not in uniform_polyhedra_set: - evaluation.error("UniformPolyhedron", "argtype", name) - - return - - class Dodecahedron(Builtin): """ - :WMA link:https://reference.wolfram.com/language/ref/Dodecahedron.html + :WMA link: + https://reference.wolfram.com/language/ref/Dodecahedron.html
'Dodecahedron[]' @@ -77,7 +42,8 @@ class Dodecahedron(Builtin): class Icosahedron(Builtin): """ - :WMA link:https://reference.wolfram.com/language/ref/Icosahedron.html + :WMA link: + https://reference.wolfram.com/language/ref/Icosahedron.html
'Icosahedron[]' @@ -88,17 +54,18 @@ class Icosahedron(Builtin): = -Graphics3D- """ - summary_text = "an icosahedron" rules = { "Icosahedron[]": """UniformPolyhedron["icosahedron"]""", "Icosahedron[l_?NumberQ]": """UniformPolyhedron["icosahedron", {{0, 0, 0}}, l]""", "Icosahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["icosahedron", positions, l]""", } + summary_text = "an icosahedron" class Octahedron(Builtin): """ - :WMA link:https://reference.wolfram.com/language/ref/Octahedron.html + :WMA link + :https://reference.wolfram.com/language/ref/Octahedron.html
'Octahedron[]' @@ -109,17 +76,18 @@ class Octahedron(Builtin): = -Graphics3D- """ - summary_text = "an octahedron" rules = { "Octahedron[]": """UniformPolyhedron["octahedron"]""", "Octahedron[l_?NumberQ]": """UniformPolyhedron["octahedron", {{0, 0, 0}}, l]""", "Octahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["octahedron", positions, l]""", } + summary_text = "an octahedron" class Tetrahedron(Builtin): """ - :WMA link:https://reference.wolfram.com/language/ref/Tetrahedron.html + :WMA link + :https://reference.wolfram.com/language/ref/Tetrahedron.html
'Tetrahedron[]' @@ -130,12 +98,51 @@ class Tetrahedron(Builtin): = -Graphics3D- """ - summary_text = "a tetrahedron" rules = { "Tetrahedron[]": """UniformPolyhedron["tetrahedron"]""", "Tetrahedron[l_?NumberQ]": """UniformPolyhedron["tetrahedron", {{0, 0, 0}}, l]""", "Tetrahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["tetrahedron", positions, l]""", } + summary_text = "a tetrahedron" - def apply_with_length(self, length, evaluation): + def eval_with_length(self, length, evaluation: Evaluation): "Tetrahedron[l_?Numeric]" + + +class UniformPolyhedron(Builtin): + """ + :WMA link: + https://reference.wolfram.com/language/ref/UniformPolyhedron.html + +
+
'UniformPolyhedron["name"]' +
return a uniform polyhedron with the given name. +
Names are "tetrahedron", "octahedron", "dodecahedron", or "icosahedron". +
+ + >> Graphics3D[UniformPolyhedron["octahedron"]] + = -Graphics3D- + + >> Graphics3D[UniformPolyhedron["dodecahedron"]] + = -Graphics3D- + + >> Graphics3D[{"Brown", UniformPolyhedron["tetrahedron"]}] + = -Graphics3D- + """ + + messages = { + "argtype": f"Argument `1` is not one of: {uniform_polyhedra_names}", + } + + rules = { + "UniformPolyhedron[name_String]": "UniformPolyhedron[name, {{0, 0, 0}}, 1]", + } + summary_text = "platonic polyhedra by name" + + def eval(self, name, positions, edgelength, evaluation: Evaluation): + "UniformPolyhedron[name_String, positions_List, edgelength_?NumberQ]" + + if name.value not in uniform_polyhedra_set: + evaluation.error("UniformPolyhedron", "argtype", name) + + return