-
-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathformtest.py
More file actions
112 lines (87 loc) · 3.7 KB
/
formtest.py
File metadata and controls
112 lines (87 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
"""
Example to show how new Format-directed Boxing might work.
This is a minimal example so we can discuss feasiblity.
"""
from mathics.builtin.forms.base import box
from mathics.core.atoms import IntegerM1, Integer1, Integer2, Rational
from mathics.core.expression import Expression
from mathics.core.parser import parse, MathicsSingleLineFeeder
from mathics.core.symbols import SymbolDivide
from mathics.core.systemsymbols import (
SymbolFractionBox,
SymbolMakeBoxes,
SymbolPower,
SymbolSqrt,
SymbolStandardForm,
)
from mathics.session import MathicsSession
session = MathicsSession(character_encoding="ASCII")
# Hacky pseudo boxing rules.
# Currently in MakeBox rule rewriting occurs via MakeBox rewrite rules
# which are attached to various Builtin classes.
# The rewrite is performed as a part of rewriting portion of Expression evaluation.
# We probably want to segregate these rules from other kinds of rules.
#
# The below hacky code is to simulate the rule behavior for
# just a few kinds of things so we don't have to hook into the
# complex rewrite mechanism in use in general evaluation. The implementation we use
# is just good enough for the new kinds of things we need.
# It is not intended to be used in a final implementation.
def fractionbox_fn(expr):
# To be continued...
return Expression(SymbolFractionBox, *expr.elements)
def sqrtbox_fn(expr):
return Expression(SymbolSqrt, expr.elements[0])
def powerbox_fn(expr):
new_expr = expr.elements[0]
if new_expr.elements[-1] == IntegerM1:
return Expression(SymbolDivide, Integer1, new_expr.elements[0])
elif new_expr.elements[-1] in (Rational(1, 2), Integer1 * (Integer2**IntegerM1)):
return Expression(SymbolSqrt, new_expr.elements[0])
return new_expr
boxform_rules = {
# SymbolTimes: fractionbox_fn,
SymbolPower: powerbox_fn,
SymbolSqrt: sqrtbox_fn,
}
def apply_formatvalues_rules(expr, evaluation):
"""
Hacky replacement for rules() found in Expression rewrite_apply_eval().
Note, we need to add builtin FormatValues() and the internals that go with that.
"""
if expr.elements[-1] not in (SymbolStandardForm,): # Or more generally $BoxForms
# For other forms, there might be other transformations too, and this should
# be discussed.
# For simplicity, we will just handle a small number of $BoxForms rules
return expr
# Remove the Form from expression "expr"
unboxed_expr = expr.elements[0]
if unboxed_expr.head in boxform_rules:
new_expr = boxform_rules[unboxed_expr.head](expr)
return new_expr
return unboxed_expr
# Begin demo code.
for expr_str in (
# FIXME;
# "1 / x", # Show off "Division" boxing
"a ^ b", # Show off "Power" boxing
"Sqrt[a]", # "Square-root boxing"
"a ^ (1/2)", # "Square-root boxing"
):
print("expression: ", expr_str)
# Parse, but don't evaluate expression.
expr = parse(session.definitions, MathicsSingleLineFeeder(expr_str))
print("Parsed expression: ", expr)
# Here is how Mathics currently evaluates MakeBoxes
boxed_expr = Expression(SymbolMakeBoxes, expr, SymbolStandardForm)
print("Mathics MakeBoxes: ", boxed_expr)
# Evaluate to get final printed/rendered form
print("Eval'd Makeboxes: ", boxed_expr.evaluate(session.evaluation))
# Here is how Mathics might better box an expression.
# First we apply MakeBox boxing transformation rules.
# This handles expression rewriting.
transformed_boxed_expr = apply_formatvalues_rules(boxed_expr, session.evaluation)
boxed_expr2 = box(transformed_boxed_expr, session.evaluation, SymbolStandardForm)
print("New MakeBoxes: ", boxed_expr2)
print("-" * 30)
print("")