• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SRI-CSL / yices2 / 12367760548

17 Dec 2024 06:41AM UTC coverage: 65.285% (-0.6%) from 65.92%
12367760548

push

github

web-flow
Fixes GitHub coverage issue (#544)

* Update action.yml

* Update action.yml

81020 of 124102 relevant lines covered (65.29%)

1509382.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/parser_utils/term_stack2.h
1
/*
2
 * This file is part of the Yices SMT Solver.
3
 * Copyright (C) 2017 SRI International.
4
 *
5
 * Yices is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * Yices is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
/*
20
 * Stack-based API for building terms and types.
21
 * Intended to support parsing.
22
 *
23
 * The stack contains a nested sequence of frames.  Each frame
24
 * consists of an operator (term or type constructor) and a sequence
25
 * of arguments. The arguments are string (that may denote symbols),
26
 * bindings, rationals or bitvector constants, buffers, terms, or types.
27
 *
28
 * Bindings are pairs <name, term>. They record temporary bindings from
29
 * names to terms (for let, forall, exists). The binding of name to term
30
 * is erased when the binding is deleted.
31
 *
32
 * Added May 27, 2013: to support the (as ...) construct in SMTLIB2, we
33
 * can also store op codes as arguments.
34
 *
35
 * To help reporting errors, each element on the stack has location
36
 * information.
37
 *
38
 * Each operation is defined by an op code and implemented by two functions:
39
 * - one for checking types and number of arguments
40
 * - one for applying the operation to the arguments
41
 * Both have the following signature:
42
 * - void check_op(tstack_t *stack, stack_elem_t *f, uint32_t n)
43
 * - void eval_op(tstack_t *stack, stack_elem_t *f, uint32_t n)
44
 * f is the start of a frame in stack->elem
45
 * n = the size of the frame = number of arguments
46
 *
47
 * For example, if the stack contains a frame with operator code MK_AND
48
 * and 4 arguments, then the top frame is [MK_AND <arg1> ... <arg4>]
49
 *
50
 * tstack_eval will invoke eval_mk_and(stack, f, n)
51
 * with f pointing to array [<arg1> .... <arg4>] and n = 4
52
 *
53
 * The check function must raise an exception if the arguments or
54
 * frame are incorrect. The eval function must replace the frame
55
 * by the result of the operation.
56
 *
57
 * The module implements basic operations. More can be added.
58
 */
59

60
#ifndef __TERM_STACK2_H
61
#define __TERM_STACK2_H
62

63
#include <stdint.h>
64
#include <stdbool.h>
65
#include <setjmp.h>
66

67
#include "frontend/smt2/attribute_values.h"
68
#include "terms/bvlogic_buffers.h"
69
#include "terms/terms.h"
70
#include "utils/arena.h"
71

72

73
/*
74
 * Objects on the stack
75
 * - tag = identifies the object's type
76
 * - val = union type
77
 * - loc = location information for error reporting
78
 *
79
 * For operators, we record an opcode, a multiplicity index (for associative
80
 * operators), and the index of the previous operator on the stack.
81
 *
82
 * Note: an opcode is stored as just an integer (different from TAG_OP)
83
 *
84
 * Added 2018/05/31: a new tag to record that a term requires special processing.
85
 * ----------------
86
 * This is used in the SMT2 front-end to handle named assertions and unsat cores.
87
 * In a named assertion: (assert (! <term> :named xxx)), we  mark <term>
88
 * as special so that it is can be treated as an assumption and not as a regular
89
 * assertion. The only operation that introduces a SPECIAL_TERM is set_special_term_result.
90
 *
91
 * Added 2018/06/02: another new tag to handle the check-sat-assuming command.
92
 * ----------------
93
 * The arguments to check-sat-assuming is a list of assumptions. Each assumption
94
 * can be either a SYMBOL or of the form (not SYMBOL). We add TAG_NOT_SYMBOL just
95
 * for the latter.
96
 */
97
typedef enum tag_enum {
98
  TAG_NONE,
99
  TAG_OP,               // operator
100
  TAG_OPCODE,           // opcode as argument
101
  TAG_SYMBOL,           // symbol
102
  TAG_NOT_SYMBOL,       // negation of a symbol
103
  TAG_STRING,           // string constant
104
  TAG_BV64,             // bit-vector constant (1 to 64 bits)
105
  TAG_BV,               // bit-vector constant (more than 64 bits)
106
  TAG_RATIONAL,         // rational constant
107
  TAG_FINITEFIELD,      // finite field constant (non-negative integer rational)
108
  TAG_TERM,             // term index + polarity (from the global term table)
109
  TAG_SPECIAL_TERM,     // a term marked for special processing
110
  TAG_TYPE,             // type index (from the global type table)
111
  TAG_MACRO,            // type macro (index in the type table)
112
  TAG_ATTRIBUTE,        // attribute value (index in an attribute value table)
113
  TAG_ARITH_BUFFER,     // polynomial buffer (rational coefficients)
114
  TAG_ARITH_FF_BUFFER,  // polynomial buffer (finite field coefficients)
115
  TAG_BVARITH64_BUFFER, // polynomial buffer (bitvector coefficients, 1 to 64 bits)
116
  TAG_BVARITH_BUFFER,   // polynomial buffer (bitvector coefficients, more than 64 bits)
117
  TAG_BVLOGIC_BUFFER,   // array of bits
118
  TAG_BINDING,          // pair <name, term>
119
  TAG_TYPE_BINDING,     // pair <name, type>
120
} tag_t;
121

122
#define NUM_TAGS (TAG_TYPE_BINDING+1)
123

124
// operator
125
typedef struct opval_s {
126
  int32_t opcode;
127
  uint32_t multiplicity;
128
  uint32_t prev;
129
} opval_t;
130

131
// binding
132
typedef struct binding_s {
133
  term_t term;
134
  char *symbol;
135
} binding_t;
136

137
// type binding
138
typedef struct type_binding_s {
139
  type_t type;
140
  char *symbol;
141
} type_binding_t;
142

143
// location: line + column number
144
typedef struct loc_s {
145
  uint32_t line;
146
  uint32_t column;
147
} loc_t;
148

149
// two variant representations for bitvector constants
150
// one for bitsize between 1 and 64
151
// one for bitsize > 64
152
typedef struct bv64_s {
153
  uint32_t bitsize; // size in bits
154
  uint64_t value;   // value (padded to 64 bits)
155
} bv64_t;
156

157
typedef struct bv_s {
158
  uint32_t bitsize; // size in bits
159
  uint32_t *data;   // value as an array of 32bit words
160
} bv_t;
161

162
typedef struct ff_s {
163
  rational_t val;
164
  rational_t mod;
165
} ff_t;
166

167
typedef struct mod_rba_buffer_s {
168
  rba_buffer_t *b;
169
  rational_t mod;
170
} mod_rba_buffer_t;
171

172
// element on the stack
173
typedef struct stack_elem_s {
174
  tag_t tag;
175
  union {
176
    opval_t opval;
177
    char *string;
178
    bv64_t bv64;
179
    bv_t bv;
180
    ff_t ff;
181
    rational_t rational;
182
    int32_t op;
183
    term_t term;
184
    type_t type;
185
    int32_t macro;
186
    aval_t aval;
187
    rba_buffer_t *arith_buffer;
188
    mod_rba_buffer_t mod_arith_buffer;
189
    bvarith64_buffer_t *bvarith64_buffer;
190
    bvarith_buffer_t *bvarith_buffer;
191
    bvlogic_buffer_t *bvlogic_buffer;
192
    binding_t binding;
193
    type_binding_t type_binding;
194
  } val;
195
  loc_t loc;
196
} stack_elem_t ;
197

198

199
/*
200
 * Symbols/negated symbol in the symbol buffer
201
 * - polarity true means 'symbol'
202
 * - polarity false means 'not symbol'
203
 */
204
typedef struct signed_symbol_s {
205
  const char *name;
206
  bool polarity;
207
} signed_symbol_t;
208

209
#define MAX_SBUFFER_SIZE (UINT32_MAX/sizeof(signed_symbol_t))
210

211
/*
212
 * Operator table
213
 * - num ops = number of operators
214
 * - for each op:
215
 *   assoc[op] = true if op is to be treated as an associative operator
216
 *   check[op] = check function
217
 *   eval[op] = evaluation function
218
 * - size = size of arrays assoc, check, and eval
219
 */
220
typedef struct tstack_s tstack_t;
221
// type of evaluator and check functions
222
typedef void (*eval_fun_t)(tstack_t *stack, stack_elem_t *f, uint32_t n);
223
typedef eval_fun_t check_fun_t;
224

225
typedef struct op_table_s {
226
  uint8_t *assoc;
227
  eval_fun_t *eval;
228
  check_fun_t *check;
229
  uint32_t num_ops;
230
  uint32_t size;
231
} op_table_t;
232

233
#define MAX_OP_TABLE_SIZE (UINT32_MAX/sizeof(eval_fun_t))
234

235
/*
236
 * Stack:
237
 * - array of stack_elements
238
 * - top = top of the stack
239
 *   elements are stored at indices 0 ... top-1
240
 *   a bottom marker is stored at index 0
241
 * - frame = index of the top-frame, element at that index must be an operator
242
 * - top_op = opcode of the element at index frame
243
 *
244
 * - mem = arena for allocation of strings/symbols
245
 *
246
 * - auxiliary buffers for internal computations
247
 * - a global counter for creating fresh variables
248
 * - a longjmp buffer for simulating exceptions
249
 *
250
 * - some operations store a term or type result in
251
 *   stack->result.term or stack->result.type
252
 *
253
 * - optional component: if attribute-values are used, then
254
 *   the stack must have a pointer to the attribute-value table
255
 *   (for refcounts).
256
 *
257
 * - diagnosis data for error reporting is stored in
258
 *   error_loc = loc[i] if error occurred on element i
259
 *   error_op = operator being evaluated when the error occurred
260
 *          (or NO_OP if the error occurred on a push operation)
261
 *   error_string = null-terminated string value if the erroneous
262
 *          argument is a string (or NULL).
263
 */
264
struct tstack_s {
265
  stack_elem_t *elem;
266

267
  uint32_t top;
268
  uint32_t size;
269
  uint32_t frame;
270
  int32_t top_op;
271

272
  // operator table
273
  op_table_t op_table;
274

275
  // arena
276
  arena_t mem;
277

278
  // vector to store types or terms
279
  int32_t *aux_buffer;
280
  uint32_t aux_size;
281

282
  // vector to store symbols/negated symbols
283
  signed_symbol_t *sbuffer;
284
  uint32_t sbuffer_size;
285

286
  // vector to store names (i.e., symbols)
287
  char **name_buffer;
288
  uint32_t name_buffer_size;
289

290
  // buffer to convert stack elements to bitvector constants
291
  bvconstant_t bvconst_buffer;
292

293
  // dynamically allocated buffers
294
  rba_buffer_t *abuffer;
295
  bvarith64_buffer_t *bva64buffer;
296
  bvarith_buffer_t *bvabuffer;
297
  bvlogic_buffer_t *bvlbuffer;
298

299
  // counter for type-variable creation
300
  uint32_t tvar_id;
301

302
  // result of BUILD_TERM/BUILD_TYPE
303
  union {
304
    term_t term;
305
    type_t type;
306
  } result;
307

308
  // external table (NULL by default)
309
  attr_vtbl_t *avtbl;
310

311
  // exceptions/errors
312
  jmp_buf env;
313
  loc_t error_loc;
314
  int32_t error_op;
315
  char *error_string;
316
};
317

318

319
/*
320
 * Default and maximal size
321
 */
322
#define DEFAULT_TERM_STACK_SIZE 256
323
#define MAX_TERM_STACK_SIZE (UINT32_MAX/sizeof(stack_elem_t))
324

325
/*
326
 * Default and maximal size of the aux vector
327
 */
328
#define DEFAULT_AUX_SIZE 256
329
#define MAX_AUX_SIZE (UINT32_MAX/4)
330

331
/*
332
 * Maximal size of the name vector
333
 */
334
#define MAX_NAME_BUFFER_SIZE (UINT32_MAX/sizeof(char*))
335

336

337
/*
338
 * Exception handling via setjmp and longjmp:
339
 * -----------------------------------------
340
 * To set the handler call setjmp(stack->env)
341
 * The exception handler is called on any error
342
 * via longjmp(stack->env, error_code).
343
 *
344
 * When an exception is raised, the stack may be in an inconsistent
345
 * state. Do not do any operations on the stack without calling
346
 * tstack_reset first.
347
 */
348

349
/*
350
 * Error codes (for Yices and SMT-LIB 1.2)
351
 * SMT-LIB 2 adds more exception codes.
352
 */
353
typedef enum tstack_error_s {
354
  TSTACK_NO_ERROR = 0,
355
  TSTACK_INTERNAL_ERROR,
356
  TSTACK_OP_NOT_IMPLEMENTED,
357
  TSTACK_UNDEF_TERM,
358
  TSTACK_UNDEF_TYPE,
359
  TSTACK_UNDEF_MACRO,
360
  TSTACK_RATIONAL_FORMAT,
361
  TSTACK_FLOAT_FORMAT,
362
  TSTACK_BVBIN_FORMAT,
363
  TSTACK_BVHEX_FORMAT,
364
  TSTACK_TYPENAME_REDEF,
365
  TSTACK_TERMNAME_REDEF,
366
  TSTACK_MACRO_REDEF,
367
  TSTACK_DUPLICATE_SCALAR_NAME,
368
  TSTACK_DUPLICATE_VAR_NAME,
369
  TSTACK_DUPLICATE_TYPE_VAR_NAME,
370
  TSTACK_INVALID_OP,
371
  TSTACK_INVALID_FRAME,
372
  TSTACK_INTEGER_OVERFLOW,
373
  TSTACK_NEGATIVE_EXPONENT,
374
  TSTACK_NOT_AN_INTEGER,
375
  TSTACK_NOT_A_STRING,
376
  TSTACK_NOT_A_SYMBOL,
377
  TSTACK_NOT_A_RATIONAL,
378
  TSTACK_NOT_A_TYPE,
379
  TSTACK_ARITH_ERROR,
380
  TSTACK_DIVIDE_BY_ZERO,
381
  TSTACK_NON_CONSTANT_DIVISOR,
382
  TSTACK_NONPOSITIVE_BVSIZE,
383
  TSTACK_INCOMPATIBLE_BVSIZES,
384
  TSTACK_INVALID_BVCONSTANT,
385
  TSTACK_BVARITH_ERROR,
386
  TSTACK_BVLOGIC_ERROR,
387
  TSTACK_INVALID_FFCONSTANT,
388
  TSTACK_INVALID_FFSIZE,
389
  TSTACK_INCOMPATIBLE_FFSIZES,
390
  TSTACK_TYPE_ERROR_IN_DEFTERM,
391
  TSTACK_STRINGS_ARE_NOT_TERMS,  // this can be raised only in the SMT2 lib context
392
  TSTACK_VARIABLES_VALUES_NOT_MATCHING,
393
  TSTACK_NOT_A_CONSTANT,
394
  TSTACK_NOT_A_VARIABLE,
395
  TSTACK_YICES_ERROR,
396
} tstack_error_t;
397

398
#define NUM_TSTACK_ERRORS (TSTACK_YICES_ERROR+1)
399

400

401
/*
402
 * PREDEFINED OPERATIONS
403
 */
404
enum base_opcodes {
405
  NO_OP,              // used as a marker
406

407
  // global definitions
408
  DEFINE_TYPE,        // [define-type <symbol>] or [define-type <symbol> <type>]
409
  DEFINE_TERM,        // [define-term <symbol> <type>] or [define-term <symbol> <type> <value> ]
410

411
  // bindings
412
  BIND,               // [bind <symbol> <term> ... <symbol> <term> ]
413
  DECLARE_VAR,        // [declare-var <symbol> <type> ]
414
  DECLARE_TYPE_VAR,   // [declare-type-var <symbol> ]
415
  LET,                // [let <binding> ... <binding> <term> ]
416

417
  // type constructors
418
  MK_BV_TYPE,         // [mk-bv-type <rational> ]
419
  MK_FF_TYPE,         // [mk-ff-type <rational> ]
420
  MK_SCALAR_TYPE,     // [mk-scalar-type <symbol> ... <symbol> ]
421
  MK_TUPLE_TYPE,      // [mk-tuple-type <type> ... <type> ]
422
  MK_FUN_TYPE,        // [mk-fun-type <type> ... <type> ]
423
  MK_APP_TYPE,        // [mk-app-type <macro> <type> ... <type> ]
424

425
  // basic term constructors
426
  MK_APPLY,           // [mk-apply <term> ... <term> ]
427
  MK_ITE,             // [mk-ite <term> <term> <term> ]
428
  MK_EQ,              // [mk-eq <term> <term> ]
429
  MK_DISEQ,           // [mk-diseq <term> <term> ]
430
  MK_DISTINCT,        // [mk-distinct <term> ... <term> ]
431
  MK_NOT,             // [mk-not <term> ]
432
  MK_OR,              // [mk-or <term> ... <term> ]
433
  MK_AND,             // [mk-and <term> ... <term> ]
434
  MK_XOR,             // [mk-xor <term> ... <term> ]
435
  MK_IFF,             // [mk-iff <term> <term> ]
436
  MK_IMPLIES,         // [mk-implies <term> <term> ]
437
  MK_TUPLE,           // [mk-tuple <term> ... <term> ]
438
  MK_SELECT,          // [mk-select <term> <rational> ]
439
  MK_TUPLE_UPDATE,    // [mk-tuple-update <term> <rational> <term> ]
440
  MK_UPDATE,          // [mk-update <term> <term> .... <term> ]
441
  MK_FORALL,          // [mk-forall <binding> ... <binding> <term> ]
442
  MK_EXISTS,          // [mk-exists <binding> ... <binding> <term> ]
443
  MK_LAMBDA,          // [mk-lambda <binding> ... <binding> <term> ]
444

445
  // arithmetic
446
  MK_ADD,             // [mk-add <arith> ... <arith> ]
447
  MK_SUB,             // [mk-sub <arith> ... <arith> ]
448
  MK_NEG,             // [mk-neg <arith> ]
449
  MK_MUL,             // [mk-mul <arith> ... <arith> ]
450
  MK_DIVISION,        // [mk-division <arith> <arith> ]
451
  MK_POW,             // [mk-pow <arith> <integer> ]
452
  MK_GE,              // [mk-ge <arith> <arith> ]
453
  MK_GT,              // [mk-gt <arith> <arith> ]
454
  MK_LE,              // [mk-le <arith> <arith> ]
455
  MK_LT,              // [mk-lt <arith> <arith> ]
456

457
  // bitvector arithmetic
458
  MK_BV_CONST,        // [mk-bv-const <size> <value> ]
459
  MK_BV_ADD,          // [mk-bv-add <bv> ... <bv> ]
460
  MK_BV_SUB,          // [mk-bv-sub <bv> ... <bv> ]
461
  MK_BV_MUL,          // [mk-bv-mul <bv> ... <bv> ]
462
  MK_BV_NEG,          // [mk-bv-neg <bv> ]
463
  MK_BV_POW,          // [mk-bv-pow <bv> <integer> ]
464
  MK_BV_DIV,          // [mk-bv-div <bv> <bv> ]
465
  MK_BV_REM,          // [mk-bv-rem <bv> <bv> ]
466
  MK_BV_SDIV,         // [mk-bv-sdiv <bv> <bv> ]
467
  MK_BV_SREM,         // [mk-bv-srem <bv> <bv> ]
468
  MK_BV_SMOD,         // [mk-bv-smod <bv> <bv> ]
469

470
  MK_BV_NOT,          // [mk-bv-not <bv> ]
471
  MK_BV_AND,          // [mk-bv-and <bv> ... <bv> ]
472
  MK_BV_OR,           // [mk-bv-or <bv> ... <bv> ]
473
  MK_BV_XOR,          // [mk-bv-xor <bv> ... <bv> ]
474
  MK_BV_NAND,         // [mk-bv-nand <bv> ... <bv> ]
475
  MK_BV_NOR,          // [mk-bv-nor <bv> ... <bv> ]
476
  MK_BV_XNOR,         // [mk-bv-xnor <bv> ... <bv> ]
477

478
  MK_BV_SHIFT_LEFT0,   // [mk-bv-shift-left0 <bv> <integer> ]
479
  MK_BV_SHIFT_LEFT1,   // [mk-bv-shift-left1 <bv> <integer> ]
480
  MK_BV_SHIFT_RIGHT0,  // [mk-bv-shift-right0 <bv> <integer> ]
481
  MK_BV_SHIFT_RIGHT1,  // [mk-bv-shift-right1 <bv> <integer> ]
482
  MK_BV_ASHIFT_RIGHT,  // [mk-bv-ashift-right <bv> <integer> ]
483
  MK_BV_ROTATE_LEFT,   // [mk-bv-rotate-left <bv> <rational> ]
484
  MK_BV_ROTATE_RIGHT,  // [mk-bv-rotate-right <bv> <rational> ]
485

486
  MK_BV_SHL,          // [mk-bv-shl <bv> <bv> ]
487
  MK_BV_LSHR,         // [mk-bv-lshr <bv> <bv> ]
488
  MK_BV_ASHR,         // [mk-bv-ashr <bv> <bv> ]
489

490
  MK_BV_EXTRACT,      // [mk-bv-extract <rational> <rational> <bv> ]
491
  MK_BV_CONCAT,       // [mk-bv-concat <bv> ... <bv> ]
492
  MK_BV_REPEAT,       // [mk-bv-repeat <bv> <rational> ]
493
  MK_BV_SIGN_EXTEND,  // [mk-bv-sign-extend <bv> <rational> ]
494
  MK_BV_ZERO_EXTEND,  // [mk-bv-zero-extend <bv> <rational> ]
495

496
  MK_BV_REDAND,       // [mk-bv-redand <bv> ]
497
  MK_BV_REDOR,        // [mk-bv-redor <bv> ]
498
  MK_BV_COMP,         // [mk-bv-comp <bv> <bv> ]
499

500
  MK_BV_GE,           // [mk-bv-ge <bv> <bv> ]
501
  MK_BV_GT,           // [mk-bv-gt <bv> <bv> ]
502
  MK_BV_LE,           // [mk-bv-le <bv> <bv> ]
503
  MK_BV_LT,           // [mk-bv-lt <bv> <bv> ]
504
  MK_BV_SGE,          // [mk-bv-sge <bv> <bv> ]
505
  MK_BV_SGT,          // [mk-bv-sgt <bv> <bv> ]
506
  MK_BV_SLE,          // [mk-bv-sle <bv> <bv> ]
507
  MK_BV_SLT,          // [mk-bv-slt <bv> <bv> ]
508

509
  MK_BOOL_TO_BV,      // [mk-bool-to-bv <bool> .... <bool>]
510
  MK_BIT,             // [mk-bit <bv> <index>]
511

512
  MK_FLOOR,           // [mk-floor <arith> ]
513
  MK_CEIL,            // [mk-ceil <arith> ]
514
  MK_ABS,             // [mk-abs <arith> ]
515
  MK_IDIV,            // [mk-idiv <arith> <arith> ]
516
  MK_MOD,             // [mk-idiv <arith> <arith> ]
517
  MK_DIVIDES,         // [mk-divides <arith> <arith> ]
518
  MK_IS_INT,          // [mk-is-int <arith> ]
519

520
  MK_FF_CONST,        // [mk-ff-const <field> <value> ]
521
  MK_FF_ADD,          // [mk-ff-add <ff> ... <ff> ]
522
  MK_FF_MUL,          // [mk-ff-mul <ff> ... <ff> ]
523

524
  // collect result
525
  BUILD_TERM,         // [build-term <term> ]
526
  BUILD_TYPE,         // [build-type <type> ]
527
};
528

529

530
#define NUM_BASE_OPCODES (BUILD_TYPE + 1)
531

532

533
/*
534
 * Initialization
535
 * - n = size of the operator table (must be >= NUM_BASE_OPCODES)
536
 * - the op_table is initialized: all default operators are defined
537
 */
538
extern void init_tstack(tstack_t *stack, uint32_t n);
539

540

541
/*
542
 * Add an attribute-value table
543
 * - must be done after init_tstack and before any operation
544
 *   that add attribute values
545
 */
546
static inline void tstack_set_avtbl(tstack_t *stack, attr_vtbl_t *table) {
1,579✔
547
  assert(stack->avtbl == NULL);
548
  stack->avtbl = table;
1,579✔
549
}
1,579✔
550

551

552
/*
553
 * Add or replace an operator
554
 * - op = operator code
555
 * - asssoc = whether op is associative or not
556
 * - eval. check = evaluator and checker functions
557
 * - op must be non-negative and less than the operator's table size
558
 *   (set in init_tstack)
559
 *
560
 * If op is between 0 and stack->op_table.num_ops then the
561
 * current values for op are replaced. If op is larger than
562
 * num_ops, then a new operation is added.
563
 */
564
extern void tstack_add_op(tstack_t *stack, int32_t op, bool assoc, eval_fun_t eval, check_fun_t check);
565

566
/*
567
 * Empty the stack
568
 */
569
extern void tstack_reset(tstack_t *stack);
570

571
/*
572
 * Delete all
573
 */
574
extern void delete_tstack(tstack_t *stack);
575

576

577
/*
578
 * Free all the internal buffers
579
 */
580
extern void tstack_reset_buffers(tstack_t *stack);
581

582

583
/*
584
 * PUSH DATA OR OPERATOR
585
 */
586

587
/*
588
 * Push an operator op
589
 * - op = opcode
590
 * - loc = location
591
 * op is considered valid if it's between 0 and num_ops
592
 *
593
 * This starts a new frame.
594
 *
595
 * In DEBUG mode: raise exception TSTACK_INVALID_OP if op is invalid and set
596
 *  stack->error_loc = loc
597
 *  stack->error_op = op
598
 *  stack->error_string = NULL
599
 */
600
extern void tstack_push_op(tstack_t *stack, int32_t op, loc_t *loc);
601

602
/*
603
 * Push opcode op (to be used as argument to another operation)
604
 * - this does not modify the current frame, just push op on top of the current frame.
605
 *
606
 * In DEBUG mode, raise exception TSTACK_INVALID_OP if op is invalid (same as above)
607
 */
608
extern void tstack_push_opcode(tstack_t *stack, int32_t op, loc_t *loc);
609

610
/*
611
 * Push a string or symbol of length n
612
 * - tag should be either TAG_SYMBOL or TAG_STRING
613
 * - copy s[0] ... s[n-1] and add '\0'
614
 * - s must be terminated by '\0'
615
 */
616
extern void tstack_push_str(tstack_t *stack, tag_t tag, char *s, uint32_t n, loc_t *loc);
617

618
static inline void tstack_push_string(tstack_t *stack, char *s, uint32_t n, loc_t *loc) {
1,239✔
619
  tstack_push_str(stack, TAG_STRING, s, n, loc);
1,239✔
620
}
1,239✔
621

622
static inline void tstack_push_symbol(tstack_t *stack, char *s, uint32_t n, loc_t *loc) {
311,065✔
623
  tstack_push_str(stack, TAG_SYMBOL, s, n, loc);
311,065✔
624
}
311,065✔
625

626
static inline void tstack_push_not_symbol(tstack_t *stack, char *s, uint32_t n, loc_t *loc) {
14✔
627
  tstack_push_str(stack, TAG_NOT_SYMBOL, s, n, loc);
14✔
628
}
14✔
629

630

631
/*
632
 * These functions are like push_symbol but they raise an exception if
633
 * the name s is already used (TSTACK_TYPENAME_REDEF,
634
 * TSTACK_TERMNAME_REDEF, or TSTACK_MACRO_REDEF)
635
 */
636
extern void tstack_push_free_typename(tstack_t *stack, char *s, uint32_t n, loc_t *loc);
637
extern void tstack_push_free_termname(tstack_t *stack, char *s, uint32_t n, loc_t *loc);
638
extern void tstack_push_free_macroname(tstack_t *stack, char *s, uint32_t n, loc_t *loc);
639

640
/*
641
 * Variant: raise exception (TSTACK_TYPENAME_REDEF) if s is already
642
 * used either as a type or as a macro name
643
 */
644
extern void tstack_push_free_type_or_macro_name(tstack_t *stack, char *s, uint32_t n, loc_t *loc);
645

646

647
/*
648
 * Find the term or type of name s and push that term or type on the stack
649
 *
650
 * raise exception TSTACK_UNDEF_TERM, TSTACK_UNDEF_TYPE, or TSTACK_UNDEF_MACRO
651
 * if the name is not mapped to a term, type, or macro.
652
 */
653
extern void tstack_push_type_by_name(tstack_t *stack, char *s, loc_t *loc);
654
extern void tstack_push_term_by_name(tstack_t *stack, char *s, loc_t *loc);
655
extern void tstack_push_macro_by_name(tstack_t *stack, char *s, loc_t *loc);
656

657
/*
658
 * Convert a string to a rational and push that
659
 * - s must be null-terminated and of rational or floating point formats
660
 *  (cf. rational.h, yices.h)
661
 *
662
 * raise exception TSTACK_FORMAT_... if the string s does not have
663
 * the right format, and set
664
 *   stack->error_loc = loc
665
 *   stack->error_op = NO_OP
666
 *   stack->error_string = s
667
 */
668
extern void tstack_push_rational(tstack_t *stack, char *s, loc_t *loc);
669
extern void tstack_push_float(tstack_t *stack, char *s, loc_t *loc);
670

671
/*
672
 * Convert a string to a bitvector constant an push that
673
 * - n = length of the string
674
 * - s must be a string of binary or hexadecimal digits (no prefix)
675
 *
676
 * raise exception TSTACK_FORMAT_... if the string s does not have
677
 * the right format, and set
678
 *   stack->error_loc = loc
679
 *   stack->error_op = NO_OP
680
 *   stack->error_string = s
681
 */
682
extern void tstack_push_bvbin(tstack_t *stack, char *s, uint32_t n, loc_t *loc);
683
extern void tstack_push_bvhex(tstack_t *stack, char *s, uint32_t n, loc_t *loc);
684

685
/*
686
 * Push primitive types or terms
687
 */
688
extern void tstack_push_bool_type(tstack_t *stack, loc_t *loc);
689
extern void tstack_push_int_type(tstack_t *stack, loc_t *loc);
690
extern void tstack_push_real_type(tstack_t *stack, loc_t *loc);
691
extern void tstack_push_true(tstack_t *stack, loc_t *loc);
692
extern void tstack_push_false(tstack_t *stack, loc_t *loc);
693

694
/*
695
 * Push integer constants
696
 */
697
extern void tstack_push_int32(tstack_t *stack, int32_t val, loc_t *loc);
698

699
/*
700
 * Push terms or types built by other means:
701
 * use these functions for predefined SMT-LIB terms and types
702
 */
703
extern void tstack_push_term(tstack_t *stack, term_t t, loc_t *loc);
704
extern void tstack_push_type(tstack_t *stack, type_t tau, loc_t *loc);
705
extern void tstack_push_macro(tstack_t *stack, int32_t id, loc_t *loc);
706

707

708
/*
709
 * EVALUATION
710
 */
711

712
/*
713
 * Eval: execute the operation defined by the top-level operator OP,
714
 * applied to all the arguments on top of OP on the stack.
715
 *
716
 * Replace [op arg1 ... argn] by the result of the operation.
717
 */
718
extern void tstack_eval(tstack_t *stack);
719

720
/*
721
 * Check whether the stack is empty
722
 */
723
static inline bool tstack_is_empty(tstack_t *stack) {
724
  return stack->top == 1;
725
}
726

727
/*
728
 * Read result.
729
 *
730
 * Call sequence to use these functions:
731
 * 1) tstack_push_op(stack, BUILD_TERM, xxx)
732
 * 2) sequence of push/eval to build the term
733
 * 3) when tstack_eval evaluates the BUILD_TERM command,
734
 *    stack->result.term is available.
735
 *
736
 * Same thing for types, but replace by BUILD_TYPE.
737
 */
738
static inline term_t tstack_get_term(tstack_t *stack) {
56✔
739
  return stack->result.term;
56✔
740
}
741

742
static inline term_t tstack_get_type(tstack_t *stack) {
×
743
  return stack->result.type;
×
744
}
745

746
#ifndef NDEBUG
747
extern void print_elem(tstack_t *stack, stack_elem_t *e);
748
#endif
749

750
#endif /* __TERM_STACK2_H */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc