1 /*
2
3 This file is part of the Maude 2 interpreter.
4
5 Copyright 1997-2003 SRI International, Menlo Park, CA 94025, USA.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21 */
22
23 //
24 // Implementation for class SuccSymbol.
25 //
26
27 // utility stuff
28 #include "macros.hh"
29 #include "vector.hh"
30
31 // forward declarations
32 #include "interface.hh"
33 #include "core.hh"
34 #include "freeTheory.hh"
35 #include "S_Theory.hh"
36
37 // interface class definitions
38 #include "term.hh"
39
40 // core class definitions
41 #include "rewritingContext.hh"
42 #include "symbolMap.hh"
43
44 // S theory class definitions
45 #include "S_Symbol.hh"
46 #include "S_DagNode.hh"
47 #include "S_Term.hh"
48
49 // built in stuff
50 #include "bindingMacros.hh"
51 #include "succSymbol.hh"
52
SuccSymbol(int id)53 SuccSymbol::SuccSymbol(int id)
54 : S_Symbol(id)
55 {
56 }
57
58 bool
attachData(const Vector<Sort * > & opDeclaration,const char * purpose,const Vector<const char * > & data)59 SuccSymbol::attachData(const Vector<Sort*>& opDeclaration,
60 const char* purpose,
61 const Vector<const char*>& data)
62 {
63 NULL_DATA(purpose, SuccSymbol, data);
64 return S_Symbol::attachData(opDeclaration, purpose, data);
65 }
66
67 bool
attachTerm(const char * purpose,Term * term)68 SuccSymbol::attachTerm(const char* purpose, Term* term)
69 {
70 BIND_TERM(purpose, term, zeroTerm);
71 return S_Symbol::attachTerm(purpose, term);
72 }
73
74 void
copyAttachments(Symbol * original,SymbolMap * map)75 SuccSymbol::copyAttachments(Symbol* original, SymbolMap* map)
76 {
77 SuccSymbol* orig = safeCast(SuccSymbol*, original);
78 COPY_TERM(orig, zeroTerm, map);
79 S_Symbol::copyAttachments(original, map);
80 }
81
82 void
getDataAttachments(const Vector<Sort * > & opDeclaration,Vector<const char * > & purposes,Vector<Vector<const char * >> & data)83 SuccSymbol::getDataAttachments(const Vector<Sort*>& opDeclaration,
84 Vector<const char*>& purposes,
85 Vector<Vector<const char*> >& data)
86 {
87 APPEND_DATA(purposes, data, SuccSymbol);
88 S_Symbol::getDataAttachments(opDeclaration, purposes, data);
89 }
90
91 void
getTermAttachments(Vector<const char * > & purposes,Vector<Term * > & terms)92 SuccSymbol::getTermAttachments(Vector<const char*>& purposes,
93 Vector<Term*>& terms)
94 {
95 APPEND_TERM(purposes, terms, zeroTerm);
96 S_Symbol::getTermAttachments(purposes, terms);
97 }
98
99 void
postInterSymbolPass()100 SuccSymbol::postInterSymbolPass()
101 {
102 PREPARE_TERM(zeroTerm);
103 }
104
105 void
reset()106 SuccSymbol::reset()
107 {
108 zeroTerm.reset(); // so zero dag can be garbage collected
109 S_Symbol::reset(); // parents reset() tasks
110 }
111
112 Term*
makeNatTerm(const mpz_class & nat)113 SuccSymbol::makeNatTerm(const mpz_class& nat)
114 {
115 Assert(zeroTerm.getTerm() != 0,
116 "zero not defined for " << this);
117 Term* zero = zeroTerm.getTerm()->deepCopy();
118 return (nat == 0) ? zero : (new S_Term(this, nat, zero));
119 }
120
121 DagNode*
makeNatDag(const mpz_class & nat)122 SuccSymbol::makeNatDag(const mpz_class& nat)
123 {
124 Assert(zeroTerm.getTerm() != 0, "zero not defined");
125 DagNode* zero = zeroTerm.getDag();
126 return (nat == 0) ? zero : (new S_DagNode(this, nat, zero));
127 }
128
129 bool
isNat(const Term * term) const130 SuccSymbol::isNat(const Term* term) const
131 {
132 const Symbol* s = term->symbol();
133 return zeroTerm.getTerm()->
134 equal((s != this) ? term :
135 safeCast(const S_Term*, term)->getArgument());
136 }
137
138 bool
isNat(const DagNode * dagNode) const139 SuccSymbol::isNat(const DagNode* dagNode) const
140 {
141 const Symbol* s = dagNode->symbol();
142 return zeroTerm.getTerm()->
143 equal((s != this) ? dagNode :
144 safeCast(const S_DagNode*, dagNode)->getArgument());
145 }
146
147 const mpz_class&
getNat(const Term * term) const148 SuccSymbol::getNat(const Term* term) const
149 {
150 static mpz_class zero(0);
151
152 const Symbol* s = term->symbol();
153 if (s != this)
154 {
155 Assert(zeroTerm.getTerm()->equal(term), "not a nat");
156 return zero;
157 }
158 const S_Term* st = safeCast(const S_Term*, term);
159 Assert(zeroTerm.getTerm()->equal(st->getArgument()), "arg not zero");
160 return st->getNumber();
161 }
162
163 const mpz_class&
getNat(const DagNode * dagNode) const164 SuccSymbol::getNat(const DagNode* dagNode) const
165 {
166 static mpz_class zero(0);
167
168 const Symbol* s = dagNode->symbol();
169 if (s != this)
170 {
171 Assert(zeroTerm.getTerm()->equal(dagNode), "not a nat");
172 return zero;
173 }
174 const S_DagNode* sd = safeCast(const S_DagNode*, dagNode);
175 Assert(zeroTerm.getTerm()->equal(sd->getArgument()), "arg not zero");
176 return sd->getNumber();
177 }
178
179 bool
getSignedInt(const DagNode * dagNode,int & value) const180 SuccSymbol::getSignedInt(const DagNode* dagNode, int& value) const
181 {
182 if (isNat(dagNode))
183 {
184 const mpz_class& n = getNat(dagNode);
185 if (n.fits_sint_p())
186 {
187 value = n.get_si();
188 return true;
189 }
190 }
191 return false;
192 }
193
194 bool
getSignedInt64(const DagNode * dagNode,Int64 & value) const195 SuccSymbol::getSignedInt64(const DagNode* dagNode, Int64& value) const
196 {
197 if (isNat(dagNode))
198 {
199 const mpz_class& n = getNat(dagNode);
200 mpz_class u = n >> BITS_PER_UINT;
201 if (u.fits_sint_p())
202 {
203 value = u.get_si();
204 value <<= BITS_PER_UINT;
205 value |= n.get_ui();
206 return true;
207 }
208 }
209 return false;
210 }
211 bool
rewriteToNat(DagNode * subject,RewritingContext & context,const mpz_class & result)212 SuccSymbol::rewriteToNat(DagNode* subject, RewritingContext& context, const mpz_class& result)
213 {
214 Assert(result >= 0, "-ve");
215 Assert(zeroTerm.getTerm() != 0, "zero not defined");
216
217 DagNode* zero = zeroTerm.getDag();
218 if (result == 0)
219 return context.builtInReplace(subject, zero);
220
221 bool trace = RewritingContext::getTraceStatus();
222 if (trace)
223 {
224 context.tracePreEqRewrite(subject, 0, RewritingContext::BUILTIN);
225 if (context.traceAbort())
226 return false;
227 }
228 (void) new(subject) S_DagNode(this, result, zero);
229 context.incrementEqCount();
230 if (trace)
231 context.tracePostEqRewrite(subject);
232 return true;
233 }
234