1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Francois Bobot, Haniel Barbosa |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Definition of TPTP parser. |
14 |
|
*/ |
15 |
|
|
16 |
|
// Do not #include "parser/antlr_input.h" directly. Rely on the header. |
17 |
|
#include "parser/tptp/tptp.h" |
18 |
|
|
19 |
|
#include <algorithm> |
20 |
|
#include <set> |
21 |
|
|
22 |
|
#include "api/cpp/cvc5.h" |
23 |
|
#include "base/check.h" |
24 |
|
#include "options/options.h" |
25 |
|
#include "parser/parser.h" |
26 |
|
#include "smt/command.h" |
27 |
|
|
28 |
|
// ANTLR defines these, which is really bad! |
29 |
|
#undef true |
30 |
|
#undef false |
31 |
|
|
32 |
|
namespace cvc5 { |
33 |
|
namespace parser { |
34 |
|
|
35 |
43 |
Tptp::Tptp(api::Solver* solver, |
36 |
|
SymbolManager* sm, |
37 |
|
bool strictMode, |
38 |
43 |
bool parseOnly) |
39 |
43 |
: Parser(solver, sm, strictMode, parseOnly), d_cnf(false), d_fof(false) |
40 |
|
{ |
41 |
43 |
addTheory(Tptp::THEORY_CORE); |
42 |
|
|
43 |
|
/* Try to find TPTP dir */ |
44 |
|
// From tptp4x FileUtilities |
45 |
|
//----Try the TPTP directory, and TPTP variations |
46 |
43 |
char* home = getenv("TPTP"); |
47 |
43 |
if(home == NULL) { |
48 |
43 |
home = getenv("TPTP_HOME"); |
49 |
|
// //----If no TPTP_HOME, try the tptp user (aaargh) |
50 |
|
// if(home == NULL && (PasswdEntry = getpwnam("tptp")) != NULL) { |
51 |
|
// home = PasswdEntry->pw_dir; |
52 |
|
// } |
53 |
|
//----Now look in the TPTP directory from there |
54 |
43 |
if(home != NULL) { |
55 |
|
d_tptpDir = home; |
56 |
|
d_tptpDir.append("/TPTP/"); |
57 |
|
} |
58 |
|
} else { |
59 |
|
d_tptpDir = home; |
60 |
|
//add trailing "/" |
61 |
|
if(d_tptpDir[d_tptpDir.size() - 1] != '/') { |
62 |
|
d_tptpDir.append("/"); |
63 |
|
} |
64 |
|
} |
65 |
43 |
d_hasConjecture = false; |
66 |
43 |
} |
67 |
|
|
68 |
129 |
Tptp::~Tptp() { |
69 |
50 |
for( unsigned i=0; i<d_in_created.size(); i++ ){ |
70 |
7 |
d_in_created[i]->free(d_in_created[i]); |
71 |
|
} |
72 |
86 |
} |
73 |
|
|
74 |
43 |
void Tptp::addTheory(Theory theory) { |
75 |
43 |
switch(theory) { |
76 |
43 |
case THEORY_CORE: |
77 |
|
//TPTP (CNF and FOF) is unsorted so we define this common type |
78 |
|
{ |
79 |
86 |
std::string d_unsorted_name = "$$unsorted"; |
80 |
43 |
d_unsorted = d_solver->mkUninterpretedSort(d_unsorted_name); |
81 |
86 |
preemptCommand(new DeclareSortCommand(d_unsorted_name, 0, d_unsorted)); |
82 |
|
} |
83 |
|
// propositionnal |
84 |
43 |
defineType("Bool", d_solver->getBooleanSort()); |
85 |
43 |
defineVar("$true", d_solver->mkTrue()); |
86 |
43 |
defineVar("$false", d_solver->mkFalse()); |
87 |
43 |
addOperator(api::AND); |
88 |
43 |
addOperator(api::EQUAL); |
89 |
43 |
addOperator(api::IMPLIES); |
90 |
|
// addOperator(api::ITE); //only for tff thf |
91 |
43 |
addOperator(api::NOT); |
92 |
43 |
addOperator(api::OR); |
93 |
43 |
addOperator(api::XOR); |
94 |
43 |
addOperator(api::APPLY_UF); |
95 |
|
//Add quantifiers? |
96 |
43 |
break; |
97 |
|
|
98 |
|
default: |
99 |
|
std::stringstream ss; |
100 |
|
ss << "internal error: Tptp::addTheory(): unhandled theory " << theory; |
101 |
|
throw ParserException(ss.str()); |
102 |
|
} |
103 |
43 |
} |
104 |
|
|
105 |
|
|
106 |
|
/* The include are managed in the lexer but called in the parser */ |
107 |
|
// Inspired by http://www.antlr3.org/api/C/interop.html |
108 |
|
|
109 |
7 |
bool newInputStream(std::string fileName, pANTLR3_LEXER lexer, std::vector< pANTLR3_INPUT_STREAM >& inc ) { |
110 |
7 |
Debug("parser") << "Including " << fileName << std::endl; |
111 |
|
// Create a new input stream and take advantage of built in stream stacking |
112 |
|
// in C target runtime. |
113 |
|
// |
114 |
|
pANTLR3_INPUT_STREAM in; |
115 |
|
#ifdef CVC5_ANTLR3_OLD_INPUT_STREAM |
116 |
|
in = antlr3AsciiFileStreamNew((pANTLR3_UINT8) fileName.c_str()); |
117 |
|
#else /* CVC5_ANTLR3_OLD_INPUT_STREAM */ |
118 |
7 |
in = antlr3FileStreamNew((pANTLR3_UINT8) fileName.c_str(), ANTLR3_ENC_8BIT); |
119 |
|
#endif /* CVC5_ANTLR3_OLD_INPUT_STREAM */ |
120 |
7 |
if(in == NULL) { |
121 |
|
Debug("parser") << "Can't open " << fileName << std::endl; |
122 |
|
return false; |
123 |
|
} |
124 |
|
// Same thing as the predefined PUSHSTREAM(in); |
125 |
7 |
lexer->pushCharStream(lexer,in); |
126 |
|
// restart it |
127 |
|
//lexer->rec->state->tokenStartCharIndex = -10; |
128 |
|
//lexer->emit(lexer); |
129 |
|
|
130 |
|
// Note that the input stream is not closed when it EOFs, I don't bother |
131 |
|
// to do it here, but it is up to you to track streams created like this |
132 |
|
// and destroy them when the whole parse session is complete. Remember that you |
133 |
|
// don't want to do this until all tokens have been manipulated all the way through |
134 |
|
// your tree parsers etc as the token does not store the text it just refers |
135 |
|
// back to the input stream and trying to get the text for it will abort if you |
136 |
|
// close the input stream too early. |
137 |
|
// |
138 |
7 |
inc.push_back( in ); |
139 |
|
|
140 |
|
//TODO what said before |
141 |
7 |
return true; |
142 |
|
} |
143 |
|
|
144 |
7 |
void Tptp::includeFile(std::string fileName) { |
145 |
|
// security for online version |
146 |
7 |
if(!canIncludeFile()) { |
147 |
|
parseError("include-file feature was disabled for this run."); |
148 |
|
} |
149 |
|
|
150 |
|
// Get the lexer |
151 |
7 |
AntlrInput * ai = static_cast<AntlrInput *>(getInput()); |
152 |
7 |
pANTLR3_LEXER lexer = ai->getAntlr3Lexer(); |
153 |
|
|
154 |
|
// push the inclusion scope; will be popped by our special popCharStream |
155 |
|
// would be necessary for handling symbol filtering in inclusions |
156 |
|
//pushScope(); |
157 |
|
|
158 |
|
// get the name of the current stream "Does it work inside an include?" |
159 |
7 |
const std::string inputName = ai->getInputStreamName(); |
160 |
|
|
161 |
|
// Test in the directory of the actual parsed file |
162 |
7 |
std::string currentDirFileName; |
163 |
7 |
if(inputName != "<stdin>") { |
164 |
|
// TODO: Use dirname or Boost::filesystem? |
165 |
7 |
size_t pos = inputName.rfind('/'); |
166 |
7 |
if(pos != std::string::npos) { |
167 |
|
currentDirFileName = std::string(inputName, 0, pos + 1); |
168 |
|
} |
169 |
7 |
currentDirFileName.append(fileName); |
170 |
7 |
if(newInputStream(currentDirFileName,lexer, d_in_created)) { |
171 |
7 |
return; |
172 |
|
} |
173 |
|
} else { |
174 |
|
currentDirFileName = "<unknown current directory for stdin>"; |
175 |
|
} |
176 |
|
|
177 |
|
if(d_tptpDir.empty()) { |
178 |
|
parseError("Couldn't open included file: " + fileName |
179 |
|
+ " at " + currentDirFileName + " and the TPTP directory is not specified (environment variable TPTP)"); |
180 |
|
}; |
181 |
|
|
182 |
|
std::string tptpDirFileName = d_tptpDir + fileName; |
183 |
|
if(! newInputStream(tptpDirFileName,lexer, d_in_created)) { |
184 |
|
parseError("Couldn't open included file: " + fileName |
185 |
|
+ " at " + currentDirFileName + " or " + tptpDirFileName); |
186 |
|
} |
187 |
|
} |
188 |
|
|
189 |
3 |
void Tptp::checkLetBinding(const std::vector<api::Term>& bvlist, |
190 |
|
api::Term lhs, |
191 |
|
api::Term rhs, |
192 |
|
bool formula) |
193 |
|
{ |
194 |
3 |
if (lhs.getKind() != api::APPLY_UF) |
195 |
|
{ |
196 |
|
parseError("malformed let: LHS must be a flat function application"); |
197 |
|
} |
198 |
6 |
const std::multiset<api::Term> vars{lhs.begin(), lhs.end()}; |
199 |
3 |
if (formula && !lhs.getSort().isBoolean()) |
200 |
|
{ |
201 |
|
parseError("malformed let: LHS must be formula"); |
202 |
|
} |
203 |
11 |
for (const cvc5::api::Term& var : vars) |
204 |
|
{ |
205 |
8 |
if (var.hasOp()) |
206 |
|
{ |
207 |
|
parseError("malformed let: LHS must be flat, illegal child: " + |
208 |
|
var.toString()); |
209 |
|
} |
210 |
|
} |
211 |
|
|
212 |
|
// ensure all let-bound variables appear on the LHS, and appear only once |
213 |
8 |
for (const api::Term& bound_var : bvlist) |
214 |
|
{ |
215 |
5 |
const size_t count = vars.count(bound_var); |
216 |
5 |
if (count == 0) { |
217 |
|
parseError( |
218 |
|
"malformed let: LHS must make use of all quantified variables, " |
219 |
|
"missing `" + |
220 |
|
bound_var.toString() + "'"); |
221 |
5 |
} else if (count >= 2) { |
222 |
|
parseError("malformed let: LHS cannot use same bound variable twice: " + |
223 |
|
bound_var.toString()); |
224 |
|
} |
225 |
|
} |
226 |
3 |
} |
227 |
|
|
228 |
5258 |
api::Term Tptp::parseOpToExpr(ParseOp& p) |
229 |
|
{ |
230 |
10516 |
api::Term expr; |
231 |
5258 |
if (!p.d_expr.isNull()) |
232 |
|
{ |
233 |
|
return p.d_expr; |
234 |
|
} |
235 |
|
// if it has a kind, it's a builtin one and this function should not have been |
236 |
|
// called |
237 |
5258 |
Assert(p.d_kind == api::NULL_EXPR); |
238 |
5258 |
if (isDeclared(p.d_name)) |
239 |
|
{ // already appeared |
240 |
5174 |
expr = getVariable(p.d_name); |
241 |
|
} |
242 |
|
else |
243 |
|
{ |
244 |
|
api::Sort t = |
245 |
168 |
p.d_type == d_solver->getBooleanSort() ? p.d_type : d_unsorted; |
246 |
84 |
expr = bindVar(p.d_name, t, true); // must define at level zero |
247 |
84 |
preemptCommand(new DeclareFunctionCommand(p.d_name, expr, t)); |
248 |
|
} |
249 |
5258 |
return expr; |
250 |
|
} |
251 |
|
|
252 |
896 |
api::Term Tptp::applyParseOp(ParseOp& p, std::vector<api::Term>& args) |
253 |
|
{ |
254 |
896 |
if (Debug.isOn("parser")) |
255 |
|
{ |
256 |
|
Debug("parser") << "applyParseOp: " << p << " to:" << std::endl; |
257 |
|
for (std::vector<api::Term>::iterator i = args.begin(); i != args.end(); |
258 |
|
++i) |
259 |
|
{ |
260 |
|
Debug("parser") << "++ " << *i << std::endl; |
261 |
|
} |
262 |
|
} |
263 |
896 |
Assert(!args.empty()); |
264 |
|
// If operator already defined, just build application |
265 |
896 |
if (!p.d_expr.isNull()) |
266 |
|
{ |
267 |
|
// this happens with some arithmetic kinds, which are wrapped around |
268 |
|
// lambdas. |
269 |
27 |
args.insert(args.begin(), p.d_expr); |
270 |
27 |
return d_solver->mkTerm(api::APPLY_UF, args); |
271 |
|
} |
272 |
869 |
bool isBuiltinKind = false; |
273 |
|
// the builtin kind of the overall return expression |
274 |
869 |
api::Kind kind = api::NULL_EXPR; |
275 |
|
// First phase: piece operator together |
276 |
869 |
if (p.d_kind == api::NULL_EXPR) |
277 |
|
{ |
278 |
|
// A non-built-in function application, get the expression |
279 |
1010 |
api::Term v; |
280 |
505 |
if (isDeclared(p.d_name)) |
281 |
|
{ // already appeared |
282 |
439 |
v = getVariable(p.d_name); |
283 |
|
} |
284 |
|
else |
285 |
|
{ |
286 |
132 |
std::vector<api::Sort> sorts(args.size(), d_unsorted); |
287 |
|
api::Sort t = |
288 |
132 |
p.d_type == d_solver->getBooleanSort() ? p.d_type : d_unsorted; |
289 |
66 |
t = d_solver->mkFunctionSort(sorts, t); |
290 |
66 |
v = bindVar(p.d_name, t, true); // must define at level zero |
291 |
66 |
preemptCommand(new DeclareFunctionCommand(p.d_name, v, t)); |
292 |
|
} |
293 |
|
// args might be rationals, in which case we need to create |
294 |
|
// distinct constants of the "unsorted" sort to represent them |
295 |
1213 |
for (size_t i = 0; i < args.size(); ++i) |
296 |
|
{ |
297 |
2124 |
if (args[i].getSort().isReal() |
298 |
2124 |
&& v.getSort().getFunctionDomainSorts()[i] == d_unsorted) |
299 |
|
{ |
300 |
|
args[i] = convertRatToUnsorted(args[i]); |
301 |
|
} |
302 |
|
} |
303 |
505 |
Assert(!v.isNull()); |
304 |
505 |
checkFunctionLike(v); |
305 |
505 |
kind = getKindForFunction(v); |
306 |
505 |
args.insert(args.begin(), v); |
307 |
|
} |
308 |
|
else |
309 |
|
{ |
310 |
364 |
kind = p.d_kind; |
311 |
364 |
isBuiltinKind = true; |
312 |
|
} |
313 |
869 |
Assert(kind != api::NULL_EXPR); |
314 |
869 |
const Options& opts = d_solver->getOptions(); |
315 |
|
// Second phase: apply parse op to the arguments |
316 |
869 |
if (isBuiltinKind) |
317 |
|
{ |
318 |
364 |
if (!opts.getUfHo() && (kind == api::EQUAL || kind == api::DISTINCT)) |
319 |
|
{ |
320 |
|
// need --uf-ho if these operators are applied over function args |
321 |
201 |
for (std::vector<api::Term>::iterator i = args.begin(); i != args.end(); |
322 |
|
++i) |
323 |
|
{ |
324 |
134 |
if ((*i).getSort().isFunction()) |
325 |
|
{ |
326 |
|
parseError( |
327 |
|
"Cannot apply equalty to functions unless --uf-ho is set."); |
328 |
|
} |
329 |
|
} |
330 |
|
} |
331 |
1092 |
if (!strictModeEnabled() && (kind == api::AND || kind == api::OR) |
332 |
426 |
&& args.size() == 1) |
333 |
|
{ |
334 |
|
// Unary AND/OR can be replaced with the argument. |
335 |
|
return args[0]; |
336 |
|
} |
337 |
364 |
if (kind == api::MINUS && args.size() == 1) |
338 |
|
{ |
339 |
|
return d_solver->mkTerm(api::UMINUS, args[0]); |
340 |
|
} |
341 |
364 |
if (kind == api::TO_REAL) |
342 |
|
{ |
343 |
|
// If the type is real, this is a no-op. We require this special |
344 |
|
// case in the TPTP parser since TO_REAL is designed to match the |
345 |
|
// SMT-LIB operator, meaning it can only be applied to integers, whereas |
346 |
|
// the TPTP to_real / to_rat do not have the same semantics. |
347 |
11 |
api::Sort s = args[0].getSort(); |
348 |
8 |
if (s.isReal()) |
349 |
|
{ |
350 |
5 |
return args[0]; |
351 |
|
} |
352 |
|
} |
353 |
359 |
return d_solver->mkTerm(kind, args); |
354 |
|
} |
355 |
|
|
356 |
|
// check if partially applied function, in this case we use HO_APPLY |
357 |
505 |
if (args.size() >= 2) |
358 |
|
{ |
359 |
1010 |
api::Sort argt = args[0].getSort(); |
360 |
505 |
if (argt.isFunction()) |
361 |
|
{ |
362 |
505 |
unsigned arity = argt.getFunctionArity(); |
363 |
505 |
if (args.size() - 1 < arity) |
364 |
|
{ |
365 |
|
if (!opts.getUfHo()) |
366 |
|
{ |
367 |
|
parseError("Cannot partially apply functions unless --uf-ho is set."); |
368 |
|
} |
369 |
|
Debug("parser") << "Partial application of " << args[0]; |
370 |
|
Debug("parser") << " : #argTypes = " << arity; |
371 |
|
Debug("parser") << ", #args = " << args.size() - 1 << std::endl; |
372 |
|
// must curry the partial application |
373 |
|
return d_solver->mkTerm(api::HO_APPLY, args); |
374 |
|
} |
375 |
|
} |
376 |
|
} |
377 |
505 |
return d_solver->mkTerm(kind, args); |
378 |
|
} |
379 |
|
|
380 |
70 |
api::Term Tptp::mkDecimal( |
381 |
|
std::string& snum, std::string& sden, bool pos, size_t exp, bool posE) |
382 |
|
{ |
383 |
|
// the numerator and the denominator |
384 |
140 |
std::stringstream ssn; |
385 |
140 |
std::stringstream ssd; |
386 |
70 |
if (exp != 0) |
387 |
|
{ |
388 |
16 |
if (posE) |
389 |
|
{ |
390 |
|
// see if we need to pad zeros on the end, e.g. 1.2E5 ---> 120000 |
391 |
10 |
if (exp >= sden.size()) |
392 |
|
{ |
393 |
10 |
ssn << snum << sden; |
394 |
4953 |
for (size_t i = 0, nzero = (exp - sden.size()); i < nzero; i++) |
395 |
|
{ |
396 |
4943 |
ssn << "0"; |
397 |
|
} |
398 |
10 |
ssd << "0"; |
399 |
|
} |
400 |
|
else |
401 |
|
{ |
402 |
|
ssn << snum << sden.substr(0, exp); |
403 |
|
ssd << sden.substr(exp); |
404 |
|
} |
405 |
|
} |
406 |
|
else |
407 |
|
{ |
408 |
|
// see if we need to pad zeros on the beginning, e.g. 1.2E-5 ---> 0.000012 |
409 |
6 |
if (exp >= snum.size()) |
410 |
|
{ |
411 |
6 |
ssn << "0"; |
412 |
3300 |
for (size_t i = 0, nzero = (exp - snum.size()); i < nzero; i++) |
413 |
|
{ |
414 |
3294 |
ssd << "0"; |
415 |
|
} |
416 |
6 |
ssd << snum << sden; |
417 |
|
} |
418 |
|
else |
419 |
|
{ |
420 |
|
ssn << snum.substr(0, exp); |
421 |
|
ssd << snum.substr(exp) << sden; |
422 |
|
} |
423 |
|
} |
424 |
|
} |
425 |
|
else |
426 |
|
{ |
427 |
54 |
ssn << snum; |
428 |
54 |
ssd << sden; |
429 |
|
} |
430 |
140 |
std::stringstream ss; |
431 |
70 |
if (!pos) |
432 |
|
{ |
433 |
11 |
ss << "-"; |
434 |
|
} |
435 |
70 |
ss << ssn.str() << "." << ssd.str(); |
436 |
140 |
return d_solver->mkReal(ss.str()); |
437 |
|
} |
438 |
|
|
439 |
1 |
void Tptp::forceLogic(const std::string& logic) |
440 |
|
{ |
441 |
1 |
Parser::forceLogic(logic); |
442 |
1 |
preemptCommand(new SetBenchmarkLogicCommand(logic)); |
443 |
1 |
} |
444 |
|
|
445 |
59 |
void Tptp::addFreeVar(api::Term var) |
446 |
|
{ |
447 |
59 |
Assert(cnf()); |
448 |
59 |
d_freeVar.push_back(var); |
449 |
59 |
} |
450 |
|
|
451 |
85 |
std::vector<api::Term> Tptp::getFreeVar() |
452 |
|
{ |
453 |
85 |
Assert(cnf()); |
454 |
85 |
std::vector<api::Term> r; |
455 |
85 |
r.swap(d_freeVar); |
456 |
85 |
return r; |
457 |
|
} |
458 |
|
|
459 |
42 |
api::Term Tptp::convertRatToUnsorted(api::Term expr) |
460 |
|
{ |
461 |
|
// Create the conversion function If they doesn't exists |
462 |
42 |
if (d_rtu_op.isNull()) { |
463 |
12 |
api::Sort t; |
464 |
|
// Conversion from rational to unsorted |
465 |
6 |
t = d_solver->mkFunctionSort(d_solver->getRealSort(), d_unsorted); |
466 |
6 |
d_rtu_op = d_solver->mkConst(t, "$$rtu"); |
467 |
6 |
preemptCommand(new DeclareFunctionCommand("$$rtu", d_rtu_op, t)); |
468 |
|
// Conversion from unsorted to rational |
469 |
6 |
t = d_solver->mkFunctionSort(d_unsorted, d_solver->getRealSort()); |
470 |
6 |
d_utr_op = d_solver->mkConst(t, "$$utr"); |
471 |
6 |
preemptCommand(new DeclareFunctionCommand("$$utr", d_utr_op, t)); |
472 |
|
} |
473 |
|
// Add the inverse in order to show that over the elements that |
474 |
|
// appear in the problem there is a bijection between unsorted and |
475 |
|
// rational |
476 |
84 |
api::Term ret = d_solver->mkTerm(api::APPLY_UF, d_rtu_op, expr); |
477 |
42 |
if (d_r_converted.find(expr) == d_r_converted.end()) { |
478 |
32 |
d_r_converted.insert(expr); |
479 |
32 |
api::Term eq = d_solver->mkTerm( |
480 |
64 |
api::EQUAL, expr, d_solver->mkTerm(api::APPLY_UF, d_utr_op, ret)); |
481 |
32 |
preemptCommand(new AssertCommand(eq)); |
482 |
|
} |
483 |
84 |
return api::Term(ret); |
484 |
|
} |
485 |
|
|
486 |
6 |
api::Term Tptp::convertStrToUnsorted(std::string str) |
487 |
|
{ |
488 |
6 |
api::Term& e = d_distinct_objects[str]; |
489 |
6 |
if (e.isNull()) |
490 |
|
{ |
491 |
6 |
e = d_solver->mkConst(d_unsorted, str); |
492 |
|
} |
493 |
6 |
return e; |
494 |
|
} |
495 |
|
|
496 |
1 |
api::Term Tptp::mkLambdaWrapper(api::Kind k, api::Sort argType) |
497 |
|
{ |
498 |
2 |
Debug("parser") << "mkLambdaWrapper: kind " << k << " and type " << argType |
499 |
1 |
<< "\n"; |
500 |
2 |
std::vector<api::Term> lvars; |
501 |
2 |
std::vector<api::Sort> domainTypes = argType.getFunctionDomainSorts(); |
502 |
2 |
for (unsigned i = 0, size = domainTypes.size(); i < size; ++i) |
503 |
|
{ |
504 |
|
// the introduced variable is internal (not parsable) |
505 |
2 |
std::stringstream ss; |
506 |
1 |
ss << "_lvar_" << i; |
507 |
2 |
api::Term v = d_solver->mkVar(domainTypes[i], ss.str()); |
508 |
1 |
lvars.push_back(v); |
509 |
|
} |
510 |
|
// apply body of lambda to variables |
511 |
|
api::Term wrapper = |
512 |
1 |
d_solver->mkTerm(api::LAMBDA, |
513 |
2 |
d_solver->mkTerm(api::BOUND_VAR_LIST, lvars), |
514 |
3 |
d_solver->mkTerm(k, lvars)); |
515 |
|
|
516 |
2 |
return wrapper; |
517 |
|
} |
518 |
|
|
519 |
1319 |
api::Term Tptp::getAssertionExpr(FormulaRole fr, api::Term expr) |
520 |
|
{ |
521 |
1319 |
switch (fr) { |
522 |
1292 |
case FR_AXIOM: |
523 |
|
case FR_HYPOTHESIS: |
524 |
|
case FR_DEFINITION: |
525 |
|
case FR_ASSUMPTION: |
526 |
|
case FR_LEMMA: |
527 |
|
case FR_THEOREM: |
528 |
|
case FR_NEGATED_CONJECTURE: |
529 |
|
case FR_PLAIN: |
530 |
|
// it's a usual assert |
531 |
1292 |
return expr; |
532 |
24 |
case FR_CONJECTURE: |
533 |
|
// it should be negated when asserted |
534 |
24 |
return d_solver->mkTerm(api::NOT, expr); |
535 |
3 |
case FR_UNKNOWN: |
536 |
|
case FR_FI_DOMAIN: |
537 |
|
case FR_FI_FUNCTORS: |
538 |
|
case FR_FI_PREDICATES: |
539 |
|
case FR_TYPE: |
540 |
|
// it does not correspond to an assertion |
541 |
3 |
return d_nullExpr; |
542 |
|
break; |
543 |
|
} |
544 |
|
Assert(false); // unreachable |
545 |
|
return d_nullExpr; |
546 |
|
} |
547 |
|
|
548 |
43 |
api::Term Tptp::getAssertionDistinctConstants() |
549 |
|
{ |
550 |
86 |
std::vector<api::Term> constants; |
551 |
49 |
for (std::pair<const std::string, api::Term>& cs : d_distinct_objects) |
552 |
|
{ |
553 |
6 |
constants.push_back(cs.second); |
554 |
|
} |
555 |
43 |
if (constants.size() > 1) |
556 |
|
{ |
557 |
3 |
return d_solver->mkTerm(api::DISTINCT, constants); |
558 |
|
} |
559 |
40 |
return d_nullExpr; |
560 |
|
} |
561 |
|
|
562 |
1319 |
Command* Tptp::makeAssertCommand(FormulaRole fr, |
563 |
|
api::Term expr, |
564 |
|
bool cnf, |
565 |
|
bool inUnsatCore) |
566 |
|
{ |
567 |
|
// For SZS ontology compliance. |
568 |
|
// if we're in cnf() though, conjectures don't result in "Theorem" or |
569 |
|
// "CounterSatisfiable". |
570 |
1319 |
if (!cnf && (fr == FR_NEGATED_CONJECTURE || fr == FR_CONJECTURE)) { |
571 |
24 |
d_hasConjecture = true; |
572 |
24 |
Assert(!expr.isNull()); |
573 |
|
} |
574 |
1319 |
if( expr.isNull() ){ |
575 |
3 |
return new EmptyCommand("Untreated role for expression"); |
576 |
|
}else{ |
577 |
1316 |
return new AssertCommand(expr, inUnsatCore); |
578 |
|
} |
579 |
|
} |
580 |
|
|
581 |
|
} // namespace parser |
582 |
28179 |
} // namespace cvc5 |