wneuper@4856
|
1 |
package isac.gui.mawen.scalaterm
|
wneuper@4856
|
2 |
|
S1420454023@4913
|
3 |
import isac.gui.mawen.termtree.TreeNodeContent
|
wneuper@4907
|
4 |
import javax.swing.tree.DefaultMutableTreeNode
|
wneuper@4900
|
5 |
|
wneuper@4859
|
6 |
import edu.tum.cs.isabelle.api.XML
|
wneuper@4856
|
7 |
import edu.tum.cs.isabelle.pure._
|
wneuper@4859
|
8 |
import edu.tum.cs.isabelle._ // for Codec
|
wneuper@4856
|
9 |
|
wneuper@4856
|
10 |
object Util {
|
wneuper@4856
|
11 |
|
wneuper@4856
|
12 |
def int(s: String): Integer = new Integer(s)
|
wneuper@4856
|
13 |
|
wneuper@4856
|
14 |
/* Data for presentation of Const which are not contained in (Scala-) Term:
|
wneuper@4856
|
15 |
* _1: string as shown by Isabelle's pretty printing
|
wneuper@4856
|
16 |
* _2: string in LaTeX format with place-holders "#d", where d is a digit:
|
wneuper@4856
|
17 |
* number of place-holders determine arity;
|
wneuper@4856
|
18 |
* pre/post/mix-fix is read out from here also for _1
|
wneuper@4856
|
19 |
* _3: infixl | infixr | prefix | postfix: the latter two are redundant with _2
|
wneuper@4856
|
20 |
* _4: priority, which determines parentheses to be set
|
wneuper@4856
|
21 |
* TODO: reconsider data representation: record, ...
|
wneuper@4856
|
22 |
*/
|
wneuper@4856
|
23 |
val present = Map (
|
wneuper@4856
|
24 |
"HOL.eq" -> (" = ", "#1=#2", "infixl", 50), //see ~~/src/HOL/HOL.thy
|
wneuper@4856
|
25 |
"Groups.plus_class.plus" -> (" + ", "#1+#2", "infixl", 65), //see ~~/src/HOL/Groups.thy
|
wneuper@4856
|
26 |
"Groups.plus_class.minus" -> (" - ", "#1-#2", "infixl", 65), //see ~~/src/HOL/Groups.thy
|
wneuper@4856
|
27 |
"Groups.plus_class.uminus" -> (" -", "#1-#2", "prefix", 80), //see ~~/src/HOL/Groups.thy
|
wneuper@4856
|
28 |
"Groups.times_class.times" -> (" * ", "#1.#2", "infixl", 70), //see ~~/src/HOL/Groups.thy
|
wneuper@4856
|
29 |
//"Groups.plus_class.times"->("*", "#1\cdot#2", "infixl", 70),
|
wneuper@4856
|
30 |
//...ERROR: implicit conversion found: Groups.plus_class.times => ...
|
wneuper@4867
|
31 |
"Fields.inverse_class.divide" -> (" / ", "\frac{#1}{#2}", "infixl", 70), //see ~~/src/HOL/Fields.thy
|
wneuper@4856
|
32 |
"Power.power_class.power" -> (" ^ ", "#1^{#2}", "infixr", 80) //see ~~/src/HOL/Transcendental.thy
|
wneuper@4856
|
33 |
//"Transcendental.sin" -> ("sin ", "\sin{#1}", "infixl", 70)
|
wneuper@4856
|
34 |
//...ERROR: implicit conversion found: ...
|
wneuper@4856
|
35 |
)
|
wneuper@4856
|
36 |
/* so not every constant needs to be in Util.present */
|
wneuper@4856
|
37 |
def ST_isa(str: String): String = {
|
wneuper@4856
|
38 |
present.get(str) match {
|
wneuper@4856
|
39 |
case Some((isa, _, _, _)) => isa
|
wneuper@4856
|
40 |
case None => str.substring(str.lastIndexOf(".") + 1) + " "}}
|
wneuper@4856
|
41 |
def ST_latex(str: String): String = {
|
wneuper@4856
|
42 |
present.get(str) match {
|
wneuper@4856
|
43 |
case Some((_, latex, _, _)) => latex
|
wneuper@4856
|
44 |
case None => str.substring(str.lastIndexOf(".") + 1) + " "}}
|
wneuper@4856
|
45 |
def ST_fix(str: String): String = {
|
wneuper@4856
|
46 |
present.get(str) match {
|
wneuper@4856
|
47 |
case Some((_, _, fix, _)) => fix
|
wneuper@4856
|
48 |
case None => "prefix"}}
|
wneuper@4856
|
49 |
def ST_prior(str: String): Int = {
|
wneuper@4856
|
50 |
present.get(str) match {
|
wneuper@4856
|
51 |
case Some((_, _, _, prior)) => prior
|
wneuper@4856
|
52 |
case None => 99}}
|
wneuper@4856
|
53 |
|
wneuper@4856
|
54 |
/* transform a Term into a String, which corresponds to Isabelle's
|
wneuper@4856
|
55 |
* pretty_printing within Isac's Knowledge.
|
wneuper@4856
|
56 |
* mawen uses this for string representation of Terms.
|
wneuper@4856
|
57 |
*/
|
wneuper@4857
|
58 |
def str_of(t: Term, prior: Int, l_r: String): String = t match {
|
wneuper@4856
|
59 |
case App(App(Const("Product_Type.Pair", _), t1), t2)
|
wneuper@4857
|
60 |
=> str_of(t1, prior, "none") + ", " + str_of(t2, prior, "none")
|
wneuper@4856
|
61 |
case App(App(Const(str, _), t1), t2)
|
wneuper@4856
|
62 |
=> { val pri = ST_prior(str)
|
wneuper@4856
|
63 |
if (prior > pri) {
|
wneuper@4856
|
64 |
ST_fix(str) match {
|
wneuper@4857
|
65 |
case "infixl" => "(" + str_of(t1, pri, "left") + ST_isa(str) + str_of(t2, pri, "right") + ")"
|
wneuper@4857
|
66 |
case "infixr" => "(" + str_of(t1, pri, "left") + ST_isa(str) + str_of(t2, pri, "right") + ")"
|
wneuper@4857
|
67 |
case "prefix" => "(" + ST_isa(str) + str_of(t1, pri, "left") + " (2" + str_of(t2, pri, "right") + "2)" + ")"}
|
wneuper@4856
|
68 |
}else{
|
wneuper@4856
|
69 |
ST_fix(str) match {
|
wneuper@4856
|
70 |
case "infixl" => {
|
wneuper@4857
|
71 |
if (prior == pri & l_r == "right") {
|
wneuper@4857
|
72 |
"(" + str_of(t1, pri, "left") + ST_isa(str) + str_of(t2, pri, "right") + ")"
|
wneuper@4857
|
73 |
}else{
|
wneuper@4857
|
74 |
str_of(t1, pri, "left") + ST_isa(str) + str_of(t2, pri, "right")
|
wneuper@4856
|
75 |
}
|
wneuper@4857
|
76 |
}
|
wneuper@4857
|
77 |
case "infixr" => {
|
wneuper@4857
|
78 |
if (prior == pri & l_r == "left") {
|
wneuper@4857
|
79 |
"(" + str_of(t1, pri, "left") + ST_isa(str) + str_of(t2, pri, "right") + ")"
|
wneuper@4857
|
80 |
}else{
|
wneuper@4857
|
81 |
str_of(t1, pri, "left") + ST_isa(str) + str_of(t2, pri, "right")
|
wneuper@4857
|
82 |
}
|
wneuper@4857
|
83 |
}
|
wneuper@4857
|
84 |
case "prefix" => ST_isa(str) + str_of(t1, pri, "none") + " " + str_of(t2, pri, "none")}
|
wneuper@4856
|
85 |
}}
|
wneuper@4857
|
86 |
case App(Const(str, _), t1) => ST_isa(str) + "(" + str_of(t1, prior, "none") + ")"
|
wneuper@4857
|
87 |
case Free(str, _) => str
|
wneuper@4856
|
88 |
case Const(str, _) => str
|
wneuper@4856
|
89 |
case _ => throw new IllegalArgumentException("str_of WRONG arg: " + t)
|
wneuper@4856
|
90 |
}
|
wneuper@4857
|
91 |
// infix: "left" or "right" argument ----------vvvv
|
wneuper@4857
|
92 |
def string_of(t: Term): String = str_of(t, 0, "none")
|
wneuper@4859
|
93 |
|
wneuper@4859
|
94 |
def wrap_term (t: Term): XML.Tree =
|
wneuper@4859
|
95 |
XML.Elem(("MATHML", Nil), List(
|
wneuper@4859
|
96 |
XML.Elem(("ISA", Nil), List(XML.Text("aaa + bbb::real"))),
|
wneuper@4859
|
97 |
XML.Elem(("TERM", Nil), List(Codec[Term].encode(t)))))
|
wneuper@4897
|
98 |
|
wneuper@4907
|
99 |
def insert_nodes(t: Term, n: DefaultMutableTreeNode): DefaultMutableTreeNode = t match {
|
wneuper@4900
|
100 |
case App(App(Const("Product_Type.Pair", _), t1), t2)
|
wneuper@4908
|
101 |
=> n //TODO
|
S1420454023@4913
|
102 |
case App(App(Const(str, typ), t1), t2)
|
S1420454023@4913
|
103 |
=> { val tmp1 = n.clone().asInstanceOf[DefaultMutableTreeNode]
|
S1420454023@4913
|
104 |
n.setUserObject(new TreeNodeContent(ST_isa(str), Util.string_of(App(App(Const(str, typ), t1), t2))))
|
S1420454023@4913
|
105 |
n.add(insert_nodes(t1, tmp1))
|
S1420454023@4913
|
106 |
val tmp2 = n.clone().asInstanceOf[DefaultMutableTreeNode]
|
S1420454023@4913
|
107 |
n.add(insert_nodes(t2, tmp2))
|
wneuper@4907
|
108 |
n
|
wneuper@4907
|
109 |
}
|
S1420454023@4913
|
110 |
case App(Const(str, typ), t1)
|
wneuper@4907
|
111 |
=> { val tmp = n.clone().asInstanceOf[DefaultMutableTreeNode]
|
S1420454023@4913
|
112 |
n.setUserObject(new TreeNodeContent(ST_isa(str), Util.string_of(App(Const(str, typ), t1))))
|
wneuper@4907
|
113 |
n.add(insert_nodes(t1, tmp))
|
wneuper@4907
|
114 |
n
|
wneuper@4907
|
115 |
}
|
wneuper@4907
|
116 |
case Free(str, _) => { n.setUserObject(str); n }
|
wneuper@4907
|
117 |
case Const(str, _) => { n.setUserObject(str); n }
|
wneuper@4900
|
118 |
case _ => throw new IllegalArgumentException("jtree_of WRONG arg: " + t)
|
wneuper@4900
|
119 |
}
|
wneuper@4907
|
120 |
def jtree_of(t: Term): DefaultMutableTreeNode = insert_nodes(t, new DefaultMutableTreeNode)
|
S1420454023@4925
|
121 |
|
wneuper@4923
|
122 |
def sound_of_sub(t: Term, line: Integer, indent: Integer): Unit = t match {
|
wneuper@4923
|
123 |
case App(App(Const("Product_Type.Pair", _), t1), t2)
|
S1420454023@4925
|
124 |
=> isac.gui.mawen.SoundUtils.tone(261, 500)
|
wneuper@4923
|
125 |
case App(App(Const(str, typ), t1), t2)
|
S1420454023@4925
|
126 |
=> { isac.gui.mawen.SoundUtils.repeatTone(261+(10*line), 500,indent) //tonhoehe: line, wiederholung: intent
|
wneuper@4923
|
127 |
sound_of_sub(t1, line + 1, indent + 1)
|
wneuper@4923
|
128 |
sound_of_sub(t2, line + 1, indent + 1)
|
wneuper@4923
|
129 |
}
|
wneuper@4923
|
130 |
case App(Const(str, typ), t1)
|
S1420454023@4925
|
131 |
=> { isac.gui.mawen.SoundUtils.repeatTone(261+(10*line), 500,indent) //tonhoehe: line, wiederholung: intent
|
wneuper@4923
|
132 |
sound_of_sub(t1, line + 1, indent + 1)
|
wneuper@4923
|
133 |
}
|
wneuper@4923
|
134 |
case Free(str, _) => {
|
S1420454023@4925
|
135 |
isac.gui.mawen.SoundUtils.repeatTone(1000+(10*line), 500,indent)
|
wneuper@4923
|
136 |
}
|
wneuper@4923
|
137 |
case Const(str, _) => {
|
S1420454023@4925
|
138 |
isac.gui.mawen.SoundUtils.repeatTone(2000+(10*line), 500,indent)
|
wneuper@4923
|
139 |
}
|
wneuper@4923
|
140 |
case _ => throw new IllegalArgumentException("sound_of WRONG arg: " + t)
|
wneuper@4923
|
141 |
}
|
wneuper@4923
|
142 |
def sound_of(t: Term) = sound_of_sub(t, 0, 0)
|
wneuper@4923
|
143 |
|
wneuper@4923
|
144 |
|
wneuper@4920
|
145 |
def is_numeral(s: String): Boolean = {
|
wneuper@4920
|
146 |
try {
|
wneuper@4920
|
147 |
s.toInt; true
|
wneuper@4920
|
148 |
} catch {
|
wneuper@4920
|
149 |
case e: Exception => false
|
wneuper@4920
|
150 |
}
|
wneuper@4920
|
151 |
}
|
wneuper@4920
|
152 |
def matml_of(t: Term, prior: Int, l_r: String): String = t match {
|
wneuper@4920
|
153 |
case App(App(Const("Product_Type.Pair", _), t1), t2)
|
wneuper@4920
|
154 |
=> matml_of(t1, prior, "none") + ", " + matml_of(t2, prior, "none")
|
wneuper@4920
|
155 |
case App(App(Const("Fields.inverse_class.divide", _), t1), t2)
|
wneuper@4920
|
156 |
=> {
|
wneuper@4920
|
157 |
val str = "Fields.inverse_class.divide"
|
wneuper@4920
|
158 |
val pri = ST_prior(str)
|
wneuper@4920
|
159 |
"<mfrac><mrow>" + matml_of(t1, pri, "left") + "</mrow><mrow>" + matml_of(t2, pri, "right") + "</mrow></mfrac>"
|
wneuper@4920
|
160 |
}
|
wneuper@4920
|
161 |
case App(App(Const(str, _), t1), t2)
|
wneuper@4920
|
162 |
=> { val pri = ST_prior(str)
|
wneuper@4920
|
163 |
if (prior > pri) {
|
wneuper@4920
|
164 |
ST_fix(str) match {
|
wneuper@4920
|
165 |
case "prefix" => "<mfenced separators=\'\'>" + "<mo>" + ST_isa(str) + "</mo>" + matml_of(t1, pri, "left") +
|
wneuper@4920
|
166 |
"<mfenced separators=\'\'>" + matml_of(t2, pri, "right") + "</mfenced>" + "</mfenced>"
|
wneuper@4920
|
167 |
case _ => "<mfenced separators=\'\'>" + matml_of(t1, pri, "left") + "<mo>" +
|
wneuper@4920
|
168 |
ST_isa(str) + "</mo>" + matml_of(t2, pri, "right") + "</mfenced>"
|
wneuper@4920
|
169 |
}
|
wneuper@4920
|
170 |
}else{
|
wneuper@4920
|
171 |
ST_fix(str) match {
|
wneuper@4920
|
172 |
case "prefix" => "<mo>" + ST_isa(str) + "</mo>" + matml_of(t1, pri, "none") + " " + matml_of(t2, pri, "none")
|
wneuper@4920
|
173 |
case _ => {
|
wneuper@4920
|
174 |
if (prior == pri & l_r == "right") {
|
S1420454023@4922
|
175 |
matml_of(t1, pri, "left") + "<mo>" + ST_isa(str) + "</mo>" + matml_of(t2, pri, "right")
|
wneuper@4920
|
176 |
}else{
|
wneuper@4920
|
177 |
matml_of(t1, pri, "left") + "<mo>" + ST_isa(str) + "</mo>" + matml_of(t2, pri, "right")
|
wneuper@4920
|
178 |
}
|
wneuper@4920
|
179 |
}}
|
wneuper@4920
|
180 |
}
|
wneuper@4920
|
181 |
}
|
wneuper@4920
|
182 |
case App(Const(str, _), t1) => "<mo>" + ST_isa(str) + "</mo>" + "<mfenced separators=\'\'>" + matml_of(t1, prior, "none") + "</mfenced>"
|
wneuper@4920
|
183 |
case Free(str, _) => if (is_numeral(str)) "<mn>" + str + "</mn>" else "<mi>" + str + "</mi>"
|
wneuper@4920
|
184 |
case Const(str, _) => str
|
wneuper@4920
|
185 |
case _ => throw new IllegalArgumentException("matml_of WRONG arg: " + t)
|
wneuper@4920
|
186 |
}
|
S1420454023@4922
|
187 |
def mathml_of(t: Term): String = "<math xmlns="+"\"&mathml;\""+"><mrow>" + matml_of(t, 0, "none") + "</mrow></math>"
|
wneuper@4920
|
188 |
|
wneuper@4856
|
189 |
} |