Skip to content

Commit

Permalink
Merge pull request #1565 from mathics/quickpatterntest
Browse files Browse the repository at this point in the history
More fixes
  • Loading branch information
rocky authored Aug 29, 2021
2 parents 8a90e51 + 1f0acd0 commit 58dc698
Show file tree
Hide file tree
Showing 17 changed files with 67 additions and 48 deletions.
2 changes: 1 addition & 1 deletion mathics/builtin/arithfns/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class CubeRoot(Builtin):
}

rules = {
"CubeRoot[n_?NumericQ]": "If[n > 0, Power[n, Divide[1, 3]], Times[-1, Power[Times[-1, n], Divide[1, 3]]]]",
"CubeRoot[n_?NumberQ]": "If[n > 0, Power[n, Divide[1, 3]], Times[-1, Power[Times[-1, n], Divide[1, 3]]]]",
"CubeRoot[n_]": "Power[n, Divide[1, 3]]",
"MakeBoxes[CubeRoot[x_], f:StandardForm|TraditionalForm]": (
"RadicalBox[MakeBoxes[x, f], 3]"
Expand Down
4 changes: 0 additions & 4 deletions mathics/builtin/datentime.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,10 +899,6 @@ class DateString(_DateFormat):

rules = {
"DateString[]": "DateString[DateList[], $DateStringFormat]",
"DateString[epochtime_?(VectorQ[#1, NumericQ]&)]": (
"DateString[epochtime, $DateStringFormat]"
),
"DateString[epochtime_?NumericQ]": ("DateString[epochtime, $DateStringFormat]"),
"DateString[format_?(VectorQ[#1, StringQ]&)]": (
"DateString[DateList[], format]"
),
Expand Down
15 changes: 11 additions & 4 deletions mathics/builtin/drawing/graphics3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from mathics.version import __version__ # noqa used in loading to check consistency.

from mathics.core.expression import Expression, Real
from mathics.core.expression import Expression, Real, Integer, Rational

from mathics.builtin.base import BoxConstructError, Builtin, InstanceableBuiltin
from mathics.builtin.colors.color_directives import RGBColor
Expand Down Expand Up @@ -301,18 +301,25 @@ class Cylinder(Builtin):
= -Graphics3D-
"""

messages = {"oddn": "The number of points must be even."}
messages = {
"oddn": "The number of points must be even.",
"nrr": "The radius must be a real number",
}

rules = {
"Cylinder[]": "Cylinder[{{0, 0, 0}, {1, 1, 1}}, 1]",
"Cylinder[positions_List]": "Cylinder[positions, 1]",
}

def apply_check(self, positions, radius, evaluation):
"Cylinder[positions_List, radius_?NumericQ]"
"Cylinder[positions_List, radius_]"

if len(positions.get_leaves()) % 2 == 1:
# The number of points is odd, so abort.
evaluation.error("Cylinder", "oddn", positions)
if not isinstance(radius, (Integer, Rational, Real)):
nradius = Expression(SymbolN, radius).evaluate(evaluation)
if not isinstance(nradius, (Integer, Rational, Real)):
evaluation.error("Cylinder", "nrr", radius)

return Expression("Cylinder", positions, radius)
return
2 changes: 1 addition & 1 deletion mathics/builtin/drawing/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ImageImport(_ImageBuiltin):
"""

def apply(self, path, evaluation):
"""ImageImport[path_?StringQ]"""
"""ImageImport[path_String]"""
pillow = PIL.Image.open(path.get_string_value())
pixels = numpy.asarray(pillow)
is_rgb = len(pixels.shape) >= 3 and pixels.shape[2] >= 3
Expand Down
18 changes: 9 additions & 9 deletions mathics/builtin/drawing/uniform_polyhedra.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class UniformPolyhedron(Builtin):
}

def apply(self, name, positions, edgelength, evaluation):
"UniformPolyhedron[name_String, positions_List, edgelength_?NumericQ]"
"UniformPolyhedron[name_String, positions_List, edgelength_?NumberQ]"

if name.to_python(string_quotes=False) not in uniform_polyhedra_set:
evaluation.error("UniformPolyhedron", "argtype", name)
Expand All @@ -63,8 +63,8 @@ class Dodecahedron(Builtin):

rules = {
"Dodecahedron[]": """UniformPolyhedron["dodecahedron"]""",
"Dodecahedron[l_?NumericQ]": """UniformPolyhedron["dodecahedron", {{0, 0, 0}}, l]""",
"Dodecahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["dodecahedron", positions, l]""",
"Dodecahedron[l_?NumberQ]": """UniformPolyhedron["dodecahedron", {{0, 0, 0}}, l]""",
"Dodecahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["dodecahedron", positions, l]""",
}


Expand All @@ -81,8 +81,8 @@ class Icosahedron(Builtin):

rules = {
"Icosahedron[]": """UniformPolyhedron["icosahedron"]""",
"Icosahedron[l_?NumericQ]": """UniformPolyhedron["icosahedron", {{0, 0, 0}}, l]""",
"Icosahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["icosahedron", positions, l]""",
"Icosahedron[l_?NumberQ]": """UniformPolyhedron["icosahedron", {{0, 0, 0}}, l]""",
"Icosahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["icosahedron", positions, l]""",
}


Expand All @@ -99,8 +99,8 @@ class Octahedron(Builtin):

rules = {
"Octahedron[]": """UniformPolyhedron["octahedron"]""",
"Octahedron[l_?NumericQ]": """UniformPolyhedron["octahedron", {{0, 0, 0}}, l]""",
"Octahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["octahedron", positions, l]""",
"Octahedron[l_?NumberQ]": """UniformPolyhedron["octahedron", {{0, 0, 0}}, l]""",
"Octahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["octahedron", positions, l]""",
}


Expand All @@ -117,8 +117,8 @@ class Tetrahedron(Builtin):

rules = {
"Tetrahedron[]": """UniformPolyhedron["tetrahedron"]""",
"Tetrahedron[l_?NumericQ]": """UniformPolyhedron["tetrahedron", {{0, 0, 0}}, l]""",
"Tetrahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["tetrahedron", positions, l]""",
"Tetrahedron[l_?NumberQ]": """UniformPolyhedron["tetrahedron", {{0, 0, 0}}, l]""",
"Tetrahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["tetrahedron", positions, l]""",
}

def apply_with_length(self, length, evaluation):
Expand Down
6 changes: 3 additions & 3 deletions mathics/builtin/files_io/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ class FileNameJoin(Builtin):
}

def apply(self, pathlist, evaluation, options):
"FileNameJoin[pathlist_?ListQ, OptionsPattern[FileNameJoin]]"
"FileNameJoin[pathlist_List, OptionsPattern[FileNameJoin]]"

py_pathlist = pathlist.to_python()
if not all(isinstance(p, str) and p[0] == p[-1] == '"' for p in py_pathlist):
Expand Down Expand Up @@ -2217,8 +2217,8 @@ class ToFileName(Builtin):

rules = {
"ToFileName[dir_String, name_String]": "FileNameJoin[{dir, name}]",
"ToFileName[dirs_?ListQ, name_String]": "FileNameJoin[Append[dirs, name]]",
"ToFileName[dirs_?ListQ]": "FileNameJoin[dirs]",
"ToFileName[dirs_List, name_String]": "FileNameJoin[Append[dirs, name]]",
"ToFileName[dirs_List]": "FileNameJoin[dirs]",
}


Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/inout.py
Original file line number Diff line number Diff line change
Expand Up @@ -2526,7 +2526,7 @@ def default_NumberFormat(man, base, exp, options):
return man

def apply_list_n(self, expr, n, evaluation, options) -> Expression:
"NumberForm[expr_?ListQ, n_, OptionsPattern[NumberForm]]"
"NumberForm[expr_List, n_, OptionsPattern[NumberForm]]"
options = [
Expression("RuleDelayed", Symbol(key), value)
for key, value in options.items()
Expand All @@ -2537,7 +2537,7 @@ def apply_list_n(self, expr, n, evaluation, options) -> Expression:
)

def apply_list_nf(self, expr, n, f, evaluation, options) -> Expression:
"NumberForm[expr_?ListQ, {n_, f_}, OptionsPattern[NumberForm]]"
"NumberForm[expr_List, {n_, f_}, OptionsPattern[NumberForm]]"
options = [
Expression("RuleDelayed", Symbol(key), value)
for key, value in options.items()
Expand Down
6 changes: 3 additions & 3 deletions mathics/builtin/intfns/combinatorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ class Subsets(Builtin):
"""

rules = {
"Subsets[list_ , Pattern[n,_?ListQ|All|DirectedInfinity[1]], spec_]": "Take[Subsets[list, n], spec]",
"Subsets[list_ , Pattern[n,_List|All|DirectedInfinity[1]], spec_]": "Take[Subsets[list, n], spec]",
}

messages = {
Expand Down Expand Up @@ -421,7 +421,7 @@ def apply_1(self, list, n, evaluation):
return Expression("List", *nested_list)

def apply_2(self, list, n, evaluation):
"Subsets[list_, Pattern[n,_?ListQ|All|DirectedInfinity[1]]]"
"Subsets[list_, Pattern[n,_List|All|DirectedInfinity[1]]]"

expr = Expression("Subsets", list, n)

Expand Down Expand Up @@ -495,7 +495,7 @@ def apply_2(self, list, n, evaluation):
return Expression("List", *nested_list)

def apply_3(self, list, n, spec, evaluation):
"Subsets[list_?AtomQ, Pattern[n,_?ListQ|All|DirectedInfinity[1]], spec_]"
"Subsets[list_?AtomQ, Pattern[n,_List|All|DirectedInfinity[1]], spec_]"

return evaluation.message(
"Subsets", "normal", Expression("Subsets", list, n, spec)
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def check_options(self, expr, evaluation, options):
return None

def apply(self, list1, list2, evaluation, options={}):
"ContainsOnly[list1_?ListQ, list2_?ListQ, OptionsPattern[ContainsOnly]]"
"ContainsOnly[list1_List, list2_List, OptionsPattern[ContainsOnly]]"

same_test = self.get_option(options, "SameTest", evaluation)

Expand Down Expand Up @@ -1320,7 +1320,7 @@ def apply(self, mlist, func, evaluation):
return outer([inner(l) for l in result])

def apply_multiple(self, mlist, funcs, evaluation):
"SplitBy[mlist_, funcs_?ListQ]"
"SplitBy[mlist_, funcs_List]"
expr = Expression("Split", mlist, funcs)

if mlist.is_atom():
Expand Down
2 changes: 1 addition & 1 deletion mathics/builtin/numbers/calculus.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ class Solve(Builtin):
"Cases[Solve[eqs, vars], {Rule[x_,y_?RealNumberQ]}]"
),
"Solve[eqs_, vars_, Integers]": (
"Cases[Solve[eqs, vars], {Rule[x_,y_?IntegerQ]}]"
"Cases[Solve[eqs, vars], {Rule[x_,y_Integer]}]"
),
}

Expand Down
12 changes: 5 additions & 7 deletions mathics/builtin/numbers/numbertheory.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class FromContinuedFraction(SympyFunction):
attributes = ("NumericFunction",)

def apply_1(self, expr, evaluation):
"%(name)s[expr_?ListQ]"
"%(name)s[expr_List]"
nums = expr.to_python()
if all(isinstance(i, int) for i in nums):
return from_sympy(sympy.continued_fraction_reduce(nums))
Expand Down Expand Up @@ -487,7 +487,7 @@ class NextPrime(Builtin):
}

def apply(self, n, k, evaluation):
"NextPrime[n_?NumericQ, k_?IntegerQ]"
"NextPrime[n_?NumericQ, k_Integer]"
py_k = k.to_python(n_evaluation=evaluation)
py_n = n.to_python(n_evaluation=evaluation)

Expand Down Expand Up @@ -711,10 +711,8 @@ class RandomPrime(Builtin):

rules = {
"RandomPrime[imax_?NotListQ]": "RandomPrime[{1, imax}, 1]",
"RandomPrime[int_?ListQ]": "RandomPrime[int, 1]",
"RandomPrime[imax_?ListQ, n_?ArrayQ]": (
"ConstantArray[RandomPrime[imax, 1], n]"
),
"RandomPrime[int_List]": "RandomPrime[int, 1]",
"RandomPrime[imax_List, n_?ArrayQ]": ("ConstantArray[RandomPrime[imax, 1], n]"),
"RandomPrime[imax_?NotListQ, n_?ArrayQ]": (
"ConstantArray[RandomPrime[{1, imax}, 1], n]"
),
Expand All @@ -723,7 +721,7 @@ class RandomPrime(Builtin):
# TODO: Use random state as in other randomised methods within mathics

def apply(self, interval, n, evaluation):
"RandomPrime[interval_?ListQ, n_]"
"RandomPrime[interval_List, n_]"

if not isinstance(n, Integer):
evaluation.message("RandomPrime", "posdim", n)
Expand Down
6 changes: 3 additions & 3 deletions mathics/builtin/numbers/randomnumbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ def apply(self, rmin, rmax, evaluation):
return Integer(rand.randint(rmin, rmax))

def apply_list(self, rmin, rmax, ns, evaluation):
"RandomInteger[{rmin_, rmax_}, ns_?ListQ]"
"RandomInteger[{rmin_, rmax_}, ns_List]"
if not isinstance(rmin, Integer) or not isinstance(rmax, Integer):
return evaluation.message(
"RandomInteger", "unifr", Expression("List", rmin, rmax)
Expand Down Expand Up @@ -406,7 +406,7 @@ def apply(self, xmin, xmax, evaluation):
return Real(rand.randreal(min_value, max_value))

def apply_list(self, xmin, xmax, ns, evaluation):
"RandomReal[{xmin_, xmax_}, ns_?ListQ]"
"RandomReal[{xmin_, xmax_}, ns_List]"

if not (
isinstance(xmin, (Real, Integer)) and isinstance(xmax, (Real, Integer))
Expand Down Expand Up @@ -717,7 +717,7 @@ class Random(Builtin):
"Random[Real, {zmin_Real, zmax_Real}]": "RandomReal[{zmin, zmax}]",
"Random[Complex]": "RandomComplex[]",
"Random[Complex, zmax_Complex]": "RandomComplex[zmax]",
"Random[Complex, {zmin_?NumericQ, zmax_?NumericQ}]": "RandomComplex[{zmin, zmax}]",
"Random[Complex, {zmin_?NumberQ, zmax_?NumberQ}]": "RandomComplex[{zmin, zmax}]",
}


Expand Down
6 changes: 3 additions & 3 deletions mathics/builtin/optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def apply_onevariable(self, f, x, evaluation):
)

def apply_multiplevariable(self, f, vars, evaluation):
"Minimize[f_?NotListQ, vars_?ListQ]"
"Minimize[f_?NotListQ, vars_List]"

head_name = vars.get_head_name()
vars_or = vars
Expand Down Expand Up @@ -149,7 +149,7 @@ def apply_multiplevariable(self, f, vars, evaluation):
)

def apply_constraints(self, f, vars, evaluation):
"Minimize[f_?ListQ, vars_?ListQ]"
"Minimize[f_List, vars_List]"
head_name = vars.get_head_name()
vars_or = vars
vars = vars.leaves
Expand Down Expand Up @@ -380,7 +380,7 @@ def apply(self, f, vars, evaluation):
return from_python(solutions)

def apply_constraints(self, f, vars, evaluation):
"Maximize[f_?ListQ, vars_]"
"Maximize[f_List, vars_]"

constraints = [function for function in f.leaves]
constraints[0] = from_sympy(constraints[0].to_sympy() * -1)
Expand Down
18 changes: 18 additions & 0 deletions mathics/builtin/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
Real,
SymbolFalse,
SymbolList,
SymbolN,
SymbolTrue,
)
from mathics.core.rules import Rule
Expand Down Expand Up @@ -476,21 +477,38 @@ def init(self, expr):
def quick_pattern_test(self, candidate, test, evaluation):
if test == "System`NumberQ":
return isinstance(candidate, Number)
if test == "System`NumericQ":
if isinstance(candidate, Number):
return True
# Otherwise, follow the standard evaluation
elif test == "System`RealNumberQ":
if isinstance(candidate, (Integer, Rational, Real)):
return True
candidate = Expression(SymbolN, candidate).evaluate(evaluation)
if isinstance(candidate, Real):
return True
return False
# pass
elif test == "System`Positive":
if isinstance(candidate, (Integer, Rational, Real)):
return candidate.value > 0
return False
# pass
elif test == "System`NonPositive":
if isinstance(candidate, (Integer, Rational, Real)):
return candidate.value <= 0
return False
# pass
elif test == "System`Negative":
if isinstance(candidate, (Integer, Rational, Real)):
return candidate.value < 0
return False
# pass
elif test == "System`NonNegative":
if isinstance(candidate, (Integer, Rational, Real)):
return candidate.value >= 0
return False
# pass
elif test == "System`NegativePowerQ":
return (
candidate.has_form("Power", 2)
Expand Down
2 changes: 1 addition & 1 deletion mathics/builtin/physchemdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def apply_name(self, name, prop, evaluation):
return self.apply_int(from_python(indx), prop, evaluation)

def apply_int(self, n, prop, evaluation):
"ElementData[n_?IntegerQ, prop_]"
"ElementData[n_Integer, prop_]"

py_n = n.to_python()
py_prop = prop.to_python()
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/quantities.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def validate(self, unit, evaluation):
return True

def apply_makeboxes(self, mag, unit, f, evaluation):
"MakeBoxes[Quantity[mag_, unit_?StringQ], f:StandardForm|TraditionalForm|OutputForm|InputForm]"
"MakeBoxes[Quantity[mag_, unit_String], f:StandardForm|TraditionalForm|OutputForm|InputForm]"

q_unit = unit.get_string_value().lower()
if self.validate(unit, evaluation):
Expand All @@ -200,7 +200,7 @@ def apply_makeboxes(self, mag, unit, f, evaluation):
)

def apply_n(self, mag, unit, evaluation):
"Quantity[mag_, unit_?StringQ]"
"Quantity[mag_, unit_String]"

if self.validate(unit, evaluation):
if mag.has_form("List", None):
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class Environment(Builtin):
"""

def apply(self, var, evaluation):
"Environment[var_?StringQ]"
"Environment[var_String]"
env_var = var.get_string_value()
if env_var not in os.environ:
return SymbolFailed
Expand Down Expand Up @@ -358,7 +358,7 @@ class Run(Builtin):
"""

def apply(self, command, evaluation):
"Run[command_?StringQ]"
"Run[command_String]"
command_str = command.to_python()
return Integer(subprocess.call(command_str, shell=True))

Expand Down

0 comments on commit 58dc698

Please sign in to comment.