Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 8 additions & 147 deletions mathics/builtin/symbol/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
Symbol Properties
"""

from typing import Callable, Optional

from mathics_scanner.tokeniser import NAMES_WILDCARDS

from mathics.core.atoms import String
Expand All @@ -12,35 +10,20 @@
A_HOLD_FIRST,
A_PROTECTED,
A_READ_PROTECTED,
attributes_bitset_to_list,
)
from mathics.core.builtin import Builtin, PrefixOperator, Test
from mathics.core.convert.expression import to_mathics_list
from mathics.core.element import BaseElement
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.list import ListExpression
from mathics.core.rules import RewriteRule, is_rule
from mathics.core.symbols import (
Symbol,
SymbolFalse,
SymbolHoldForm,
SymbolNull,
SymbolTrue,
SymbolUpSet,
)
from mathics.core.rules import is_rule
from mathics.core.symbols import Symbol, SymbolFalse, SymbolNull, SymbolTrue
from mathics.core.systemsymbols import (
SymbolAttributes,
SymbolDefinition,
SymbolFormat,
SymbolGrid,
SymbolInfix,
SymbolInputForm,
SymbolLeft,
SymbolMissing,
SymbolOptions,
SymbolRule,
SymbolSet,
SymbolUnknownSymbol,
)
from mathics.doc.online import online_doc_string
Expand All @@ -49,131 +32,12 @@
eval_Information,
eval_Information_with_property,
eval_values,
gather_and_format_definition_rules,
get_matching_names,
missing_symbol,
)


# FIXME: gather_and_format_definition_rules is crap and needs to be revised, rewritten and put in
# mathics.eval.symbols.properties
def gather_and_format_definition_rules(
symbol: Symbol, evaluation: Evaluation
) -> Optional[list[Expression]]:
"""Return a list of lines describing the definition of `symbol`"""
lines = []

def rhs_format(expr):
if expr.has_form(SymbolInfix, None):
expr = Expression(Expression(SymbolHoldForm, expr.head), *expr.elements)
return expr

def format_rule(
rule: RewriteRule,
up: bool = False,
lhs: Callable = lambda k: k,
rhs: Callable = lambda r: r,
):
"""
Add a line showing `rule`
"""
evaluation.check_stopped()
if isinstance(rule, RewriteRule):
lhs_pat = Expression(SymbolInputForm, lhs(rule.pattern.expr))
repl_expr = rhs(
rule.replace.replace_vars(
{"System`Definition": Expression(SymbolHoldForm, SymbolDefinition)}
)
)
repl_expr = Expression(SymbolInputForm, repl_expr)
lines.append(
Expression(
SymbolHoldForm,
Expression(up and SymbolUpSet or SymbolSet, lhs_pat, repl_expr),
)
)

def gather_rules(definition: Definition):
"""
Add to the description all the rules associated
to a definition object
"""
for rule in definition.ownvalues:
format_rule(rule)
for rule in definition.downvalues:
format_rule(rule)
for rule in definition.subvalues:
format_rule(rule)
for rule in definition.upvalues:
format_rule(rule, up=True)
for rule in definition.nvalues:
format_rule(rule)
formats = sorted(definition.formatvalues.items())
for form_name, rules in formats:
for rule in rules:

def lhs_format(expr):
return Expression(SymbolFormat, expr, Symbol(form_name))

format_rule(rule, lhs=lhs_format, rhs=rhs_format)

name = symbol.get_name()
if not name:
evaluation.message("Definition", "sym", symbol, 1)
return

try:
all = evaluation.definitions.get_definition(name)
attributes = all.attributes
all_options = all.options
all_defaultvalues = all.defaultvalues

if attributes:
attributes_list = attributes_bitset_to_list(attributes)
lines.append(
Expression(
SymbolHoldForm,
Expression(
SymbolSet,
Expression(SymbolAttributes, symbol),
to_mathics_list(
*attributes_list, elements_conversion_fn=Symbol
),
),
)
)
except KeyError:
attributes = 0
all_options = {}
all_defaultvalues = []

if not A_READ_PROTECTED & attributes:
try:
gather_rules(evaluation.definitions.get_user_definition(name, create=False))
except KeyError:
pass

for rule in all_defaultvalues:
format_rule(rule)
if all_options:
options = sorted(all_options.items())
lines.append(
Expression(
SymbolHoldForm,
Expression(
SymbolSet,
Expression(SymbolOptions, symbol),
ListExpression(
*(
Expression(SymbolRule, Symbol(name), value)
for name, value in options
)
),
),
)
)
return lines


class Definition(Builtin):
"""
<url>:WMA link:
Expand Down Expand Up @@ -410,10 +274,6 @@ class Information(PrefixOperator):
}
summary_text = "get information about all assignments for a symbol"

def eval(self, expr, evaluation: Evaluation, options: dict):
"Information[expr_, OptionsPattern[Information]]"
return eval_Information(expr, evaluation)

def build_missing(self, expression: BaseElement) -> Expression:
"""Evaluate ?? F[x][y].. as -> Missing[UnknownSymbol, F][x][y]"""
if isinstance(expression, Expression):
Expand Down Expand Up @@ -447,11 +307,12 @@ def build_list_of_matching_symbols(
result = Expression(Symbol("System`TableForm"), ListExpression(*rows))
return result

def eval(self, expr, evaluation: Evaluation, options: dict):
"Information[expr_, OptionsPattern[Information]]"
return eval_Information(expr, evaluation, options)

def eval_with_property(self, expr, prop, evaluation: Evaluation, options: dict):
"Information[expr_, prop_, OptionsPattern[Information]]"
if is_rule(prop):
# FIXME we have an option here.
return
"Information[expr_, prop_String, OptionsPattern[Information]]"
if not isinstance(prop, String):
return Expression(SymbolMissing, SymbolUnknownSymbol, prop)

Expand Down
2 changes: 1 addition & 1 deletion mathics/core/atoms/associations.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def update(self, e: Iterable):
self._hash = None


def association_from_mathics3_kv_dict(d: dict[BaseElement, BaseElement]) -> Association:
def association_from_mathics3_kv_dict(d: dict) -> Association:
"""
Given a Python dictionary contianing Mathics3 keys and values, return
and Assocation for that.
Expand Down
1 change: 1 addition & 0 deletions mathics/core/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ def eval_with_options(x, evaluation: Evaluation, options: dict):
name: Optional[str] = None
options: dict[str, Any] = {}
rules: dict[str, Any] = {}
summary_text = ""

def __getnewargs_ex__(self):
return tuple(), {
Expand Down
2 changes: 1 addition & 1 deletion mathics/core/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def __init__(
self.ownvalues = rules_dict.get("ownvalues", [])
self.subvalues = rules_dict.get("subvalues", [])
self.upvalues = rules_dict.get("upvalues", [])
self.options: dict[str, str] = rules_dict.get("options", {})
self.options: dict[str, BaseElement] = rules_dict.get("options", {})
self.messages = rules_dict.get("messages", [])

self.is_numeric = is_numeric
Expand Down
21 changes: 13 additions & 8 deletions mathics/core/parser/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
So we have mathics.core.expression.Atom vs. mathics.core.parser.Atom
"""

from typing import Optional
from typing import Final, Optional


class Node:
Expand Down Expand Up @@ -163,7 +163,9 @@ class String(Atom):
The display of a String is surrounded by double quotes.
"""

def __repr__(self):
value: str

def __repr__(self) -> str:
return '"' + self.value + '"'


Expand All @@ -173,12 +175,15 @@ class Filename(Atom):
However, like String, it doesn't have any other properties.
"""

def __repr__(self):
value: str

def __repr__(self) -> str:
return self.value


# Some common literals
NullSymbol = Symbol("Null")
NullString = String("")
Number1 = Number("1")
NumberM1 = Number("1", sign=-1)
# Some literals.
LongForm: Final[Symbol] = Symbol("LongForm")
NullSymbol: Final[Symbol] = Symbol("Null")
NullString: Final[String] = String("")
Number1: Final[Number] = Number("1")
NumberM1: Final[Number] = Number("1", sign=-1)
11 changes: 10 additions & 1 deletion mathics/core/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from mathics.core.convert.op import builtin_constants
from mathics.core.parser.ast import (
Filename,
LongForm,
Node,
NullString,
NullSymbol,
Expand Down Expand Up @@ -592,6 +593,14 @@ def parse_expr(self, precedence: int) -> Optional[Node]:
return result

def parse_information_common(self, token: Token, want_long_form: bool) -> Node:
"""Create an Information[] node expression. The variable "

want_long_form" is "True" when given prefix expression "??"
is parsed, and it is False, when prefix expression "?" is
parsed. Although, in current WMA, the LongForm option is not
documented, it controls how much data filled in to a
InformationData structure.
"""
self.consume()

pattern_token = self.parse_name_pattern()
Expand All @@ -609,7 +618,7 @@ def parse_information_common(self, token: Token, want_long_form: bool) -> Node:
return Node(
"Information",
pattern_arg,
Node("Rule", Symbol("LongForm"), long_form),
Node("Rule", LongForm, long_form),
)

@track_location
Expand Down
1 change: 1 addition & 0 deletions mathics/core/systemsymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@
SymbolLog: Final[Symbol] = Symbol("System`Log")
SymbolLog10: Final[Symbol] = Symbol("System`Log10")
SymbolLogPlot: Final[Symbol] = Symbol("System`LogPlot")
SymbolLongForm: Final[Symbol] = Symbol("System`LongForm")
SymbolLongest: Final[Symbol] = Symbol("System`Longest")
SymbolMachinePrecision: Final[Symbol] = Symbol("System`MachinePrecision")
SymbolMakeBoxes: Final[Symbol] = Symbol("System`MakeBoxes")
Expand Down
2 changes: 1 addition & 1 deletion mathics/eval/numbers/algebra/polynomial.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def coeff_power(
# ###### Auxiliary functions #########
def key_powers(lst: list) -> Union[int, float]:
key = Expression(SymbolPlus, *lst).evaluate(evaluation)
if key is not None and is_numeric(key, evaluation):
if is_numeric(key, evaluation):
return key.to_python()
return 0

Expand Down
Loading
Loading