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