mirror of
https://github.com/Z3Prover/z3
synced 2025-06-03 04:41:21 +00:00
Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable
This commit is contained in:
commit
dee21c6656
15 changed files with 11110 additions and 10967 deletions
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -1 +1,4 @@
|
||||||
|
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||||
|
* text=auto
|
||||||
|
|
||||||
src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf
|
src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,134 +1,134 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2011 Microsoft Corporation
|
Copyright (c) 2011 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
duality_profiling.cpp
|
duality_profiling.cpp
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
collection performance information for duality
|
collection performance information for duality
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Ken McMillan (kenmcmil)
|
Ken McMillan (kenmcmil)
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#pragma warning(disable:4996)
|
#pragma warning(disable:4996)
|
||||||
#pragma warning(disable:4800)
|
#pragma warning(disable:4800)
|
||||||
#pragma warning(disable:4267)
|
#pragma warning(disable:4267)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "duality_wrapper.h"
|
#include "duality_wrapper.h"
|
||||||
#include "iz3profiling.h"
|
#include "iz3profiling.h"
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
void show_time(){
|
void show_time(){
|
||||||
output_time(std::cout,current_time());
|
output_time(std::cout,current_time());
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::map<const char*, struct node> nmap;
|
typedef std::map<const char*, struct node> nmap;
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
std::string name;
|
std::string name;
|
||||||
clock_t time;
|
clock_t time;
|
||||||
clock_t start_time;
|
clock_t start_time;
|
||||||
nmap sub;
|
nmap sub;
|
||||||
struct node *parent;
|
struct node *parent;
|
||||||
|
|
||||||
node();
|
node();
|
||||||
} top;
|
} top;
|
||||||
|
|
||||||
node::node(){
|
node::node(){
|
||||||
time = 0;
|
time = 0;
|
||||||
parent = 0;
|
parent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *current;
|
struct node *current;
|
||||||
|
|
||||||
struct init {
|
struct init {
|
||||||
init(){
|
init(){
|
||||||
top.name = "TOTAL";
|
top.name = "TOTAL";
|
||||||
current = ⊤
|
current = ⊤
|
||||||
}
|
}
|
||||||
} initializer;
|
} initializer;
|
||||||
|
|
||||||
struct time_entry {
|
struct time_entry {
|
||||||
clock_t t;
|
clock_t t;
|
||||||
time_entry(){t = 0;};
|
time_entry(){t = 0;};
|
||||||
void add(clock_t incr){t += incr;}
|
void add(clock_t incr){t += incr;}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ltstr
|
struct ltstr
|
||||||
{
|
{
|
||||||
bool operator()(const char* s1, const char* s2) const
|
bool operator()(const char* s1, const char* s2) const
|
||||||
{
|
{
|
||||||
return strcmp(s1, s2) < 0;
|
return strcmp(s1, s2) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<const char*, time_entry, ltstr> tmap;
|
typedef std::map<const char*, time_entry, ltstr> tmap;
|
||||||
|
|
||||||
static std::ostream *pfs;
|
static std::ostream *pfs;
|
||||||
|
|
||||||
void print_node(node &top, int indent, tmap &totals){
|
void print_node(node &top, int indent, tmap &totals){
|
||||||
for(int i = 0; i < indent; i++) (*pfs) << " ";
|
for(int i = 0; i < indent; i++) (*pfs) << " ";
|
||||||
(*pfs) << top.name;
|
(*pfs) << top.name;
|
||||||
int dots = 70 - 2 * indent - top.name.size();
|
int dots = 70 - 2 * indent - top.name.size();
|
||||||
for(int i = 0; i <dots; i++) (*pfs) << ".";
|
for(int i = 0; i <dots; i++) (*pfs) << ".";
|
||||||
output_time(*pfs, top.time);
|
output_time(*pfs, top.time);
|
||||||
(*pfs) << std::endl;
|
(*pfs) << std::endl;
|
||||||
if(indent != 0)totals[top.name.c_str()].add(top.time);
|
if(indent != 0)totals[top.name.c_str()].add(top.time);
|
||||||
for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++)
|
for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++)
|
||||||
print_node(it->second,indent+1,totals);
|
print_node(it->second,indent+1,totals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_profile(std::ostream &os) {
|
void print_profile(std::ostream &os) {
|
||||||
pfs = &os;
|
pfs = &os;
|
||||||
top.time = 0;
|
top.time = 0;
|
||||||
for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++)
|
for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++)
|
||||||
top.time += it->second.time;
|
top.time += it->second.time;
|
||||||
tmap totals;
|
tmap totals;
|
||||||
print_node(top,0,totals);
|
print_node(top,0,totals);
|
||||||
(*pfs) << "TOTALS:" << std::endl;
|
(*pfs) << "TOTALS:" << std::endl;
|
||||||
for(tmap::iterator it = totals.begin(); it != totals.end(); it++){
|
for(tmap::iterator it = totals.begin(); it != totals.end(); it++){
|
||||||
(*pfs) << (it->first) << " ";
|
(*pfs) << (it->first) << " ";
|
||||||
output_time(*pfs, it->second.t);
|
output_time(*pfs, it->second.t);
|
||||||
(*pfs) << std::endl;
|
(*pfs) << std::endl;
|
||||||
}
|
}
|
||||||
profiling::print(os); // print the interpolation stats
|
profiling::print(os); // print the interpolation stats
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_start(const char *name){
|
void timer_start(const char *name){
|
||||||
node &child = current->sub[name];
|
node &child = current->sub[name];
|
||||||
if(child.name.empty()){ // a new node
|
if(child.name.empty()){ // a new node
|
||||||
child.parent = current;
|
child.parent = current;
|
||||||
child.name = name;
|
child.name = name;
|
||||||
}
|
}
|
||||||
child.start_time = current_time();
|
child.start_time = current_time();
|
||||||
current = &child;
|
current = &child;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_stop(const char *name){
|
void timer_stop(const char *name){
|
||||||
if(current->name != name || !current->parent){
|
if(current->name != name || !current->parent){
|
||||||
std::cerr << "imbalanced timer_start and timer_stop";
|
std::cerr << "imbalanced timer_start and timer_stop";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
current->time += (current_time() - current->start_time);
|
current->time += (current_time() - current->start_time);
|
||||||
current = current->parent;
|
current = current->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2011 Microsoft Corporation
|
Copyright (c) 2011 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
duality_profiling.h
|
duality_profiling.h
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
collection performance information for duality
|
collection performance information for duality
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Ken McMillan (kenmcmil)
|
Ken McMillan (kenmcmil)
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#ifndef DUALITYPROFILING_H
|
#ifndef DUALITYPROFILING_H
|
||||||
#define DUALITYPROFILING_H
|
#define DUALITYPROFILING_H
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
/** Start a timer with given name */
|
/** Start a timer with given name */
|
||||||
void timer_start(const char *);
|
void timer_start(const char *);
|
||||||
/** Stop a timer with given name */
|
/** Stop a timer with given name */
|
||||||
void timer_stop(const char *);
|
void timer_stop(const char *);
|
||||||
/** Print out timings */
|
/** Print out timings */
|
||||||
void print_profile(std::ostream &s);
|
void print_profile(std::ostream &s);
|
||||||
/** Show the current time. */
|
/** Show the current time. */
|
||||||
void show_time();
|
void show_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -340,6 +340,12 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
||||||
params p;
|
params p;
|
||||||
return simplify(p);
|
return simplify(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr context::make_var(int idx, const sort &s){
|
||||||
|
::sort * a = to_sort(s.raw());
|
||||||
|
return cook(m().mk_var(idx,a));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
expr expr::qe_lite() const {
|
expr expr::qe_lite() const {
|
||||||
::qe_lite qe(m());
|
::qe_lite qe(m());
|
||||||
|
@ -374,6 +380,12 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
||||||
return q.ctx().cook(q.m().update_quantifier(thing, is_forall, num_patterns, &_patterns[0], to_expr(b.raw())));
|
return q.ctx().cook(q.m().update_quantifier(thing, is_forall, num_patterns, &_patterns[0], to_expr(b.raw())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr clone_quantifier(decl_kind dk, const expr &q, const expr &b){
|
||||||
|
quantifier *thing = to_quantifier(q.raw());
|
||||||
|
bool is_forall = dk == Forall;
|
||||||
|
return q.ctx().cook(q.m().update_quantifier(thing, is_forall, to_expr(b.raw())));
|
||||||
|
}
|
||||||
|
|
||||||
void expr::get_patterns(std::vector<expr> &pats) const {
|
void expr::get_patterns(std::vector<expr> &pats) const {
|
||||||
quantifier *thing = to_quantifier(raw());
|
quantifier *thing = to_quantifier(raw());
|
||||||
unsigned num_patterns = thing->get_num_patterns();
|
unsigned num_patterns = thing->get_num_patterns();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,195 +1,195 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2011 Microsoft Corporation
|
Copyright (c) 2011 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
iz3base.h
|
iz3base.h
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
Base class for interpolators. Includes an AST manager and a scoping
|
Base class for interpolators. Includes an AST manager and a scoping
|
||||||
object as bases.
|
object as bases.
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Ken McMillan (kenmcmil)
|
Ken McMillan (kenmcmil)
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#ifndef IZ3BASE_H
|
#ifndef IZ3BASE_H
|
||||||
#define IZ3BASE_H
|
#define IZ3BASE_H
|
||||||
|
|
||||||
#include "iz3mgr.h"
|
#include "iz3mgr.h"
|
||||||
#include "iz3scopes.h"
|
#include "iz3scopes.h"
|
||||||
|
|
||||||
namespace hash_space {
|
namespace hash_space {
|
||||||
template <>
|
template <>
|
||||||
class hash<func_decl *> {
|
class hash<func_decl *> {
|
||||||
public:
|
public:
|
||||||
size_t operator()(func_decl * const &s) const {
|
size_t operator()(func_decl * const &s) const {
|
||||||
return (size_t) s;
|
return (size_t) s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base class for interpolators. Includes an AST manager and a scoping
|
/* Base class for interpolators. Includes an AST manager and a scoping
|
||||||
object as bases. */
|
object as bases. */
|
||||||
|
|
||||||
class iz3base : public iz3mgr, public scopes {
|
class iz3base : public iz3mgr, public scopes {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Get the range in which an expression occurs. This is the
|
/** Get the range in which an expression occurs. This is the
|
||||||
smallest subtree containing all occurrences of the
|
smallest subtree containing all occurrences of the
|
||||||
expression. */
|
expression. */
|
||||||
range &ast_range(ast);
|
range &ast_range(ast);
|
||||||
|
|
||||||
/** Get the scope of an expression. This is the set of tree nodes in
|
/** Get the scope of an expression. This is the set of tree nodes in
|
||||||
which all of the expression's symbols are in scope. */
|
which all of the expression's symbols are in scope. */
|
||||||
range &ast_scope(ast);
|
range &ast_scope(ast);
|
||||||
|
|
||||||
/** Get the range of a symbol. This is the smallest subtree containing
|
/** Get the range of a symbol. This is the smallest subtree containing
|
||||||
all occurrences of the symbol. */
|
all occurrences of the symbol. */
|
||||||
range &sym_range(symb);
|
range &sym_range(symb);
|
||||||
|
|
||||||
/** Is an expression local (in scope in some frame)? */
|
/** Is an expression local (in scope in some frame)? */
|
||||||
|
|
||||||
bool is_local(ast node){
|
bool is_local(ast node){
|
||||||
return !range_is_empty(ast_scope(node));
|
return !range_is_empty(ast_scope(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Simplify an expression */
|
/** Simplify an expression */
|
||||||
|
|
||||||
ast simplify(ast);
|
ast simplify(ast);
|
||||||
|
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
|
|
||||||
iz3base(ast_manager &_m_manager,
|
iz3base(ast_manager &_m_manager,
|
||||||
const std::vector<ast> &_cnsts,
|
const std::vector<ast> &_cnsts,
|
||||||
const std::vector<int> &_parents,
|
const std::vector<int> &_parents,
|
||||||
const std::vector<ast> &_theory)
|
const std::vector<ast> &_theory)
|
||||||
: iz3mgr(_m_manager), scopes(_parents) {
|
: iz3mgr(_m_manager), scopes(_parents) {
|
||||||
initialize(_cnsts,_parents,_theory);
|
initialize(_cnsts,_parents,_theory);
|
||||||
weak = false;
|
weak = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
iz3base(const iz3mgr& other,
|
iz3base(const iz3mgr& other,
|
||||||
const std::vector<ast> &_cnsts,
|
const std::vector<ast> &_cnsts,
|
||||||
const std::vector<int> &_parents,
|
const std::vector<int> &_parents,
|
||||||
const std::vector<ast> &_theory)
|
const std::vector<ast> &_theory)
|
||||||
: iz3mgr(other), scopes(_parents) {
|
: iz3mgr(other), scopes(_parents) {
|
||||||
initialize(_cnsts,_parents,_theory);
|
initialize(_cnsts,_parents,_theory);
|
||||||
weak = false;
|
weak = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
iz3base(const iz3mgr& other,
|
iz3base(const iz3mgr& other,
|
||||||
const std::vector<std::vector<ast> > &_cnsts,
|
const std::vector<std::vector<ast> > &_cnsts,
|
||||||
const std::vector<int> &_parents,
|
const std::vector<int> &_parents,
|
||||||
const std::vector<ast> &_theory)
|
const std::vector<ast> &_theory)
|
||||||
: iz3mgr(other), scopes(_parents) {
|
: iz3mgr(other), scopes(_parents) {
|
||||||
initialize(_cnsts,_parents,_theory);
|
initialize(_cnsts,_parents,_theory);
|
||||||
weak = false;
|
weak = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
iz3base(const iz3mgr& other)
|
iz3base(const iz3mgr& other)
|
||||||
: iz3mgr(other), scopes() {
|
: iz3mgr(other), scopes() {
|
||||||
weak = false;
|
weak = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set our options */
|
/* Set our options */
|
||||||
void set_option(const std::string &name, const std::string &value){
|
void set_option(const std::string &name, const std::string &value){
|
||||||
if(name == "weak" && value == "1") weak = true;
|
if(name == "weak" && value == "1") weak = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Are we doing weak interpolants? */
|
/* Are we doing weak interpolants? */
|
||||||
bool weak_mode(){return weak;}
|
bool weak_mode(){return weak;}
|
||||||
|
|
||||||
/** Print interpolation problem to an SMTLIB format file */
|
/** Print interpolation problem to an SMTLIB format file */
|
||||||
void print(const std::string &filename);
|
void print(const std::string &filename);
|
||||||
|
|
||||||
/** Check correctness of a solutino to this problem. */
|
/** Check correctness of a solutino to this problem. */
|
||||||
void check_interp(const std::vector<ast> &itps, std::vector<ast> &theory);
|
void check_interp(const std::vector<ast> &itps, std::vector<ast> &theory);
|
||||||
|
|
||||||
/** For convenience -- is this formula SAT? */
|
/** For convenience -- is this formula SAT? */
|
||||||
bool is_sat(const std::vector<ast> &consts, ast &_proof);
|
bool is_sat(const std::vector<ast> &consts, ast &_proof);
|
||||||
|
|
||||||
/** Interpolator for clauses, to be implemented */
|
/** Interpolator for clauses, to be implemented */
|
||||||
virtual void interpolate_clause(std::vector<ast> &lits, std::vector<ast> &itps){
|
virtual void interpolate_clause(std::vector<ast> &lits, std::vector<ast> &itps){
|
||||||
throw "no interpolator";
|
throw "no interpolator";
|
||||||
}
|
}
|
||||||
|
|
||||||
ast get_proof_check_assump(range &rng){
|
ast get_proof_check_assump(range &rng){
|
||||||
std::vector<ast> cs(theory);
|
std::vector<ast> cs(theory);
|
||||||
cs.push_back(cnsts[rng.hi]);
|
cs.push_back(cnsts[rng.hi]);
|
||||||
return make(And,cs);
|
return make(And,cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame_of_assertion(const ast &ass){
|
int frame_of_assertion(const ast &ass){
|
||||||
stl_ext::hash_map<ast,int>::iterator it = frame_map.find(ass);
|
stl_ext::hash_map<ast,int>::iterator it = frame_map.find(ass);
|
||||||
if(it == frame_map.end())
|
if(it == frame_map.end())
|
||||||
throw "unknown assertion";
|
throw "unknown assertion";
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void to_parents_vec_representation(const std::vector<ast> &_cnsts,
|
void to_parents_vec_representation(const std::vector<ast> &_cnsts,
|
||||||
const ast &tree,
|
const ast &tree,
|
||||||
std::vector<ast> &cnsts,
|
std::vector<ast> &cnsts,
|
||||||
std::vector<int> &parents,
|
std::vector<int> &parents,
|
||||||
std::vector<ast> &theory,
|
std::vector<ast> &theory,
|
||||||
std::vector<int> &pos_map,
|
std::vector<int> &pos_map,
|
||||||
bool merge = false
|
bool merge = false
|
||||||
);
|
);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<ast> cnsts;
|
std::vector<ast> cnsts;
|
||||||
std::vector<ast> theory;
|
std::vector<ast> theory;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct ranges {
|
struct ranges {
|
||||||
range rng;
|
range rng;
|
||||||
range scp;
|
range scp;
|
||||||
bool scope_computed;
|
bool scope_computed;
|
||||||
ranges(){scope_computed = false;}
|
ranges(){scope_computed = false;}
|
||||||
};
|
};
|
||||||
|
|
||||||
stl_ext::hash_map<symb,range> sym_range_hash;
|
stl_ext::hash_map<symb,range> sym_range_hash;
|
||||||
stl_ext::hash_map<ast,ranges> ast_ranges_hash;
|
stl_ext::hash_map<ast,ranges> ast_ranges_hash;
|
||||||
stl_ext::hash_map<ast,ast> simplify_memo;
|
stl_ext::hash_map<ast,ast> simplify_memo;
|
||||||
stl_ext::hash_map<ast,int> frame_map; // map assertions to frames
|
stl_ext::hash_map<ast,int> frame_map; // map assertions to frames
|
||||||
|
|
||||||
int frames; // number of frames
|
int frames; // number of frames
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void add_frame_range(int frame, ast t);
|
void add_frame_range(int frame, ast t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize(const std::vector<ast> &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory);
|
void initialize(const std::vector<ast> &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory);
|
||||||
|
|
||||||
void initialize(const std::vector<std::vector<ast> > &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory);
|
void initialize(const std::vector<std::vector<ast> > &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory);
|
||||||
|
|
||||||
bool is_literal(ast n);
|
bool is_literal(ast n);
|
||||||
void gather_conjuncts_rec(ast n, std::vector<ast> &conjuncts, stl_ext::hash_set<ast> &memo);
|
void gather_conjuncts_rec(ast n, std::vector<ast> &conjuncts, stl_ext::hash_set<ast> &memo);
|
||||||
void gather_conjuncts(ast n, std::vector<ast> &conjuncts);
|
void gather_conjuncts(ast n, std::vector<ast> &conjuncts);
|
||||||
ast simplify_and(std::vector<ast> &conjuncts);
|
ast simplify_and(std::vector<ast> &conjuncts);
|
||||||
ast simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map<ast,ast> &memo, int depth);
|
ast simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map<ast,ast> &memo, int depth);
|
||||||
ast simplify_with_lit(ast n, ast lit);
|
ast simplify_with_lit(ast n, ast lit);
|
||||||
void find_children(const stl_ext::hash_set<ast> &cnsts_set,
|
void find_children(const stl_ext::hash_set<ast> &cnsts_set,
|
||||||
const ast &tree,
|
const ast &tree,
|
||||||
std::vector<ast> &cnsts,
|
std::vector<ast> &cnsts,
|
||||||
std::vector<int> &parents,
|
std::vector<int> &parents,
|
||||||
std::vector<ast> &conjuncts,
|
std::vector<ast> &conjuncts,
|
||||||
std::vector<int> &children,
|
std::vector<int> &children,
|
||||||
std::vector<int> &pos_map,
|
std::vector<int> &pos_map,
|
||||||
bool merge
|
bool merge
|
||||||
);
|
);
|
||||||
bool weak;
|
bool weak;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -464,7 +464,9 @@ namespace hash_space {
|
||||||
|
|
||||||
Value &operator[](const Key& key) {
|
Value &operator[](const Key& key) {
|
||||||
std::pair<Key,Value> kvp(key,Value());
|
std::pair<Key,Value> kvp(key,Value());
|
||||||
return lookup(kvp,true)->val.second;
|
return
|
||||||
|
hashtable<std::pair<Key,Value>,Key,HashFun,proj1<Key,Value>,EqFun>::
|
||||||
|
lookup(kvp,true)->val.second;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -814,6 +814,10 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
ast equa = sep_cond(arg(pf,0),cond);
|
ast equa = sep_cond(arg(pf,0),cond);
|
||||||
if(is_equivrel_chain(equa)){
|
if(is_equivrel_chain(equa)){
|
||||||
ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove
|
ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove
|
||||||
|
if(!rewrites_from_to(equa,lhs,rhs)){
|
||||||
|
lhs = arg(arg(neg_equality,0),0); // the equality proved is ambiguous, sadly
|
||||||
|
rhs = arg(arg(neg_equality,0),1);
|
||||||
|
}
|
||||||
LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs);
|
LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs);
|
||||||
if(lhst != LitMixed && rhst != LitMixed)
|
if(lhst != LitMixed && rhst != LitMixed)
|
||||||
return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond);
|
return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond);
|
||||||
|
@ -1671,9 +1675,20 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
// split a rewrite chain into head and tail at last non-mixed term
|
bool has_mixed_summands(const ast &e){
|
||||||
|
if(op(e) == Plus){
|
||||||
|
int nargs = num_args(e);
|
||||||
|
for(int i = 0; i < nargs; i++)
|
||||||
|
if(has_mixed_summands(arg(e,i)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return get_term_type(e) == LitMixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// split a rewrite chain into head and tail at last sum with no mixed sumands
|
||||||
ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){
|
ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){
|
||||||
if(is_true(chain) || get_term_type(rhs) != LitMixed){
|
if(is_true(chain) || !has_mixed_summands(rhs)){
|
||||||
mid = rhs;
|
mid = rhs;
|
||||||
tail = mk_true();
|
tail = mk_true();
|
||||||
return chain;
|
return chain;
|
||||||
|
@ -1686,11 +1701,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// split a rewrite chain into head and tail at first non-mixed term
|
// split a rewrite chain into head and tail at first sum with no mixed sumands
|
||||||
ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){
|
ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){
|
||||||
if(is_true(chain)){
|
if(is_true(chain)){
|
||||||
mid = lhs;
|
mid = lhs;
|
||||||
if(get_term_type(lhs) != LitMixed){
|
if(!has_mixed_summands(lhs)){
|
||||||
tail = mk_true();
|
tail = mk_true();
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
@ -1790,10 +1805,21 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool rewrites_from_to(const ast &chain, const ast &lhs, const ast &rhs){
|
||||||
|
if(is_true(chain))
|
||||||
|
return lhs == rhs;
|
||||||
|
ast last = chain_last(chain);
|
||||||
|
ast rest = chain_rest(chain);
|
||||||
|
ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last));
|
||||||
|
return rewrites_from_to(rest,lhs,mid);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bad_ineq_inference {};
|
||||||
|
|
||||||
ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){
|
ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){
|
||||||
if(is_true(chain)){
|
if(is_true(chain)){
|
||||||
if(lhs != rhs)
|
if(lhs != rhs)
|
||||||
throw "bad ineq inference";
|
throw bad_ineq_inference();
|
||||||
return make(Leq,make_int(rational(0)),make_int(rational(0)));
|
return make(Leq,make_int(rational(0)),make_int(rational(0)));
|
||||||
}
|
}
|
||||||
ast last = chain_last(chain);
|
ast last = chain_last(chain);
|
||||||
|
@ -2656,9 +2682,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
pf = make_refl(e); // proof that e = e
|
pf = make_refl(e); // proof that e = e
|
||||||
|
|
||||||
prover::range erng = pv->ast_scope(e);
|
prover::range erng = pv->ast_scope(e);
|
||||||
|
#if 0
|
||||||
if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){
|
if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){
|
||||||
return e; // this term occurs in range, so it's O.K.
|
return e; // this term occurs in range, so it's O.K.
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
hash_map<ast,ast>::iterator it = localization_map.find(e);
|
hash_map<ast,ast>::iterator it = localization_map.find(e);
|
||||||
|
|
||||||
|
|
|
@ -1,321 +1,321 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2011 Microsoft Corporation
|
Copyright (c) 2011 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
iz3scopes.cpp
|
iz3scopes.cpp
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
Calculations with scopes, for both sequence and tree interpolation.
|
Calculations with scopes, for both sequence and tree interpolation.
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Ken McMillan (kenmcmil)
|
Ken McMillan (kenmcmil)
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "iz3scopes.h"
|
#include "iz3scopes.h"
|
||||||
|
|
||||||
|
|
||||||
/** computes the least common ancestor of two nodes in the tree, or SHRT_MAX if none */
|
/** computes the least common ancestor of two nodes in the tree, or SHRT_MAX if none */
|
||||||
int scopes::tree_lca(int n1, int n2){
|
int scopes::tree_lca(int n1, int n2){
|
||||||
if(!tree_mode())
|
if(!tree_mode())
|
||||||
return std::max(n1,n2);
|
return std::max(n1,n2);
|
||||||
if(n1 == SHRT_MIN) return n2;
|
if(n1 == SHRT_MIN) return n2;
|
||||||
if(n2 == SHRT_MIN) return n1;
|
if(n2 == SHRT_MIN) return n1;
|
||||||
if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX;
|
if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX;
|
||||||
while(n1 != n2){
|
while(n1 != n2){
|
||||||
if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX;
|
if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX;
|
||||||
assert(n1 >= 0 && n2 >= 0 && n1 < (int)parents.size() && n2 < (int)parents.size());
|
assert(n1 >= 0 && n2 >= 0 && n1 < (int)parents.size() && n2 < (int)parents.size());
|
||||||
if(n1 < n2) n1 = parents[n1];
|
if(n1 < n2) n1 = parents[n1];
|
||||||
else n2 = parents[n2];
|
else n2 = parents[n2];
|
||||||
}
|
}
|
||||||
return n1;
|
return n1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** computes the greatest common descendant two nodes in the tree, or SHRT_MIN if none */
|
/** computes the greatest common descendant two nodes in the tree, or SHRT_MIN if none */
|
||||||
int scopes::tree_gcd(int n1, int n2){
|
int scopes::tree_gcd(int n1, int n2){
|
||||||
if(!tree_mode())
|
if(!tree_mode())
|
||||||
return std::min(n1,n2);
|
return std::min(n1,n2);
|
||||||
int foo = tree_lca(n1,n2);
|
int foo = tree_lca(n1,n2);
|
||||||
if(foo == n1) return n2;
|
if(foo == n1) return n2;
|
||||||
if(foo == n2) return n1;
|
if(foo == n2) return n1;
|
||||||
return SHRT_MIN;
|
return SHRT_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FULL_TREE
|
#ifndef FULL_TREE
|
||||||
|
|
||||||
/** test whether a tree node is contained in a range */
|
/** test whether a tree node is contained in a range */
|
||||||
bool scopes::in_range(int n, const range &rng){
|
bool scopes::in_range(int n, const range &rng){
|
||||||
return tree_lca(rng.lo,n) == n && tree_gcd(rng.hi,n) == n;
|
return tree_lca(rng.lo,n) == n && tree_gcd(rng.hi,n) == n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** test whether two ranges of tree nodes intersect */
|
/** test whether two ranges of tree nodes intersect */
|
||||||
bool scopes::ranges_intersect(const range &rng1, const range &rng2){
|
bool scopes::ranges_intersect(const range &rng1, const range &rng2){
|
||||||
return tree_lca(rng1.lo,rng2.hi) == rng2.hi && tree_lca(rng1.hi,rng2.lo) == rng1.hi;
|
return tree_lca(rng1.lo,rng2.hi) == rng2.hi && tree_lca(rng1.hi,rng2.lo) == rng1.hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool scopes::range_contained(const range &rng1, const range &rng2){
|
bool scopes::range_contained(const range &rng1, const range &rng2){
|
||||||
return tree_lca(rng2.lo,rng1.lo) == rng1.lo
|
return tree_lca(rng2.lo,rng1.lo) == rng1.lo
|
||||||
&& tree_lca(rng1.hi,rng2.hi) == rng2.hi;
|
&& tree_lca(rng1.hi,rng2.hi) == rng2.hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes::range scopes::range_lub(const range &rng1, const range &rng2){
|
scopes::range scopes::range_lub(const range &rng1, const range &rng2){
|
||||||
range res;
|
range res;
|
||||||
res.lo = tree_gcd(rng1.lo,rng2.lo);
|
res.lo = tree_gcd(rng1.lo,rng2.lo);
|
||||||
res.hi = tree_lca(rng1.hi,rng2.hi);
|
res.hi = tree_lca(rng1.hi,rng2.hi);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes::range scopes::range_glb(const range &rng1, const range &rng2){
|
scopes::range scopes::range_glb(const range &rng1, const range &rng2){
|
||||||
range res;
|
range res;
|
||||||
res.lo = tree_lca(rng1.lo,rng2.lo);
|
res.lo = tree_lca(rng1.lo,rng2.lo);
|
||||||
res.hi = tree_gcd(rng1.hi,rng2.hi);
|
res.hi = tree_gcd(rng1.hi,rng2.hi);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
class hash<scopes::range_lo > {
|
class hash<scopes::range_lo > {
|
||||||
public:
|
public:
|
||||||
size_t operator()(const scopes::range_lo &p) const {
|
size_t operator()(const scopes::range_lo &p) const {
|
||||||
return p.lo + (size_t)p.next;
|
return p.lo + (size_t)p.next;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline
|
template <> inline
|
||||||
size_t stdext::hash_value<scopes::range_lo >(const scopes::range_lo& p)
|
size_t stdext::hash_value<scopes::range_lo >(const scopes::range_lo& p)
|
||||||
{
|
{
|
||||||
std::hash<scopes::range_lo> h;
|
std::hash<scopes::range_lo> h;
|
||||||
return h(p);
|
return h(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
class less<scopes::range_lo > {
|
class less<scopes::range_lo > {
|
||||||
public:
|
public:
|
||||||
bool operator()(const scopes::range_lo &x, const scopes::range_lo &y) const {
|
bool operator()(const scopes::range_lo &x, const scopes::range_lo &y) const {
|
||||||
return x.lo < y.lo || x.lo == y.lo && (size_t)x.next < (size_t)y.next;
|
return x.lo < y.lo || x.lo == y.lo && (size_t)x.next < (size_t)y.next;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct range_op {
|
struct range_op {
|
||||||
scopes::range_lo *x, *y;
|
scopes::range_lo *x, *y;
|
||||||
int hi;
|
int hi;
|
||||||
range_op(scopes::range_lo *_x, scopes::range_lo *_y, int _hi){
|
range_op(scopes::range_lo *_x, scopes::range_lo *_y, int _hi){
|
||||||
x = _x; y = _y; hi = _hi;
|
x = _x; y = _y; hi = _hi;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
class hash<range_op > {
|
class hash<range_op > {
|
||||||
public:
|
public:
|
||||||
size_t operator()(const range_op &p) const {
|
size_t operator()(const range_op &p) const {
|
||||||
return (size_t) p.x + (size_t)p.y + p.hi;
|
return (size_t) p.x + (size_t)p.y + p.hi;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline
|
template <> inline
|
||||||
size_t stdext::hash_value<range_op >(const range_op& p)
|
size_t stdext::hash_value<range_op >(const range_op& p)
|
||||||
{
|
{
|
||||||
std::hash<range_op> h;
|
std::hash<range_op> h;
|
||||||
return h(p);
|
return h(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
class less<range_op > {
|
class less<range_op > {
|
||||||
public:
|
public:
|
||||||
bool operator()(const range_op &x, const range_op &y) const {
|
bool operator()(const range_op &x, const range_op &y) const {
|
||||||
return (size_t)x.x < (size_t)y.x || x.x == y.x &&
|
return (size_t)x.x < (size_t)y.x || x.x == y.x &&
|
||||||
((size_t)x.y < (size_t)y.y || x.y == y.y && x.hi < y.hi);
|
((size_t)x.y < (size_t)y.y || x.y == y.y && x.hi < y.hi);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct range_tables {
|
struct range_tables {
|
||||||
hash_map<scopes::range_lo, scopes::range_lo *> unique;
|
hash_map<scopes::range_lo, scopes::range_lo *> unique;
|
||||||
hash_map<range_op,scopes::range_lo *> lub;
|
hash_map<range_op,scopes::range_lo *> lub;
|
||||||
hash_map<range_op,scopes::range_lo *> glb;
|
hash_map<range_op,scopes::range_lo *> glb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
scopes::range_lo *scopes::find_range_lo(int lo, range_lo *next){
|
scopes::range_lo *scopes::find_range_lo(int lo, range_lo *next){
|
||||||
range_lo foo(lo,next);
|
range_lo foo(lo,next);
|
||||||
std::pair<range_lo,range_lo *> baz(foo,(range_lo *)0);
|
std::pair<range_lo,range_lo *> baz(foo,(range_lo *)0);
|
||||||
std::pair<hash_map<range_lo,scopes::range_lo *>::iterator,bool> bar = rt->unique.insert(baz);
|
std::pair<hash_map<range_lo,scopes::range_lo *>::iterator,bool> bar = rt->unique.insert(baz);
|
||||||
if(bar.second)
|
if(bar.second)
|
||||||
bar.first->second = new range_lo(lo,next);
|
bar.first->second = new range_lo(lo,next);
|
||||||
return bar.first->second;
|
return bar.first->second;
|
||||||
//std::pair<hash_set<scopes::range_lo>::iterator,bool> bar = rt->unique.insert(foo);
|
//std::pair<hash_set<scopes::range_lo>::iterator,bool> bar = rt->unique.insert(foo);
|
||||||
// const range_lo *baz = &*(bar.first);
|
// const range_lo *baz = &*(bar.first);
|
||||||
// return (range_lo *)baz; // exit const hell
|
// return (range_lo *)baz; // exit const hell
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){
|
scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){
|
||||||
if(!rng1) return rng2;
|
if(!rng1) return rng2;
|
||||||
if(!rng2) return rng1;
|
if(!rng2) return rng1;
|
||||||
if(rng1->lo > rng2->lo)
|
if(rng1->lo > rng2->lo)
|
||||||
std::swap(rng1,rng2);
|
std::swap(rng1,rng2);
|
||||||
std::pair<range_op,range_lo *> foo(range_op(rng1,rng2,0),(range_lo *)0);
|
std::pair<range_op,range_lo *> foo(range_op(rng1,rng2,0),(range_lo *)0);
|
||||||
std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->lub.insert(foo);
|
std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->lub.insert(foo);
|
||||||
range_lo *&res = bar.first->second;
|
range_lo *&res = bar.first->second;
|
||||||
if(!bar.second) return res;
|
if(!bar.second) return res;
|
||||||
if(!(rng1->next && rng1->next->lo <= rng2->lo)){
|
if(!(rng1->next && rng1->next->lo <= rng2->lo)){
|
||||||
for(int lo = rng1->lo; lo <= rng2->lo; lo = parents[lo])
|
for(int lo = rng1->lo; lo <= rng2->lo; lo = parents[lo])
|
||||||
if(lo == rng2->lo)
|
if(lo == rng2->lo)
|
||||||
{rng2 = rng2->next; break;}
|
{rng2 = rng2->next; break;}
|
||||||
}
|
}
|
||||||
range_lo *baz = range_lub_lo(rng1->next,rng2);
|
range_lo *baz = range_lub_lo(rng1->next,rng2);
|
||||||
res = find_range_lo(rng1->lo,baz);
|
res = find_range_lo(rng1->lo,baz);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scopes::range_lo *scopes::range_glb_lo(range_lo *rng1, range_lo *rng2, int hi){
|
scopes::range_lo *scopes::range_glb_lo(range_lo *rng1, range_lo *rng2, int hi){
|
||||||
if(!rng1) return rng1;
|
if(!rng1) return rng1;
|
||||||
if(!rng2) return rng2;
|
if(!rng2) return rng2;
|
||||||
if(rng1->lo > rng2->lo)
|
if(rng1->lo > rng2->lo)
|
||||||
std::swap(rng1,rng2);
|
std::swap(rng1,rng2);
|
||||||
std::pair<range_op,range_lo *> cand(range_op(rng1,rng2,hi),(range_lo *)0);
|
std::pair<range_op,range_lo *> cand(range_op(rng1,rng2,hi),(range_lo *)0);
|
||||||
std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->glb.insert(cand);
|
std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->glb.insert(cand);
|
||||||
range_lo *&res = bar.first->second;
|
range_lo *&res = bar.first->second;
|
||||||
if(!bar.second) return res;
|
if(!bar.second) return res;
|
||||||
range_lo *foo;
|
range_lo *foo;
|
||||||
if(!(rng1->next && rng1->next->lo <= rng2->lo)){
|
if(!(rng1->next && rng1->next->lo <= rng2->lo)){
|
||||||
int lim = hi;
|
int lim = hi;
|
||||||
if(rng1->next) lim = std::min(lim,rng1->next->lo);
|
if(rng1->next) lim = std::min(lim,rng1->next->lo);
|
||||||
int a = rng1->lo, b = rng2->lo;
|
int a = rng1->lo, b = rng2->lo;
|
||||||
while(a != b && b <= lim){
|
while(a != b && b <= lim){
|
||||||
a = parents[a];
|
a = parents[a];
|
||||||
if(a > b)std::swap(a,b);
|
if(a > b)std::swap(a,b);
|
||||||
}
|
}
|
||||||
if(a == b && b <= lim){
|
if(a == b && b <= lim){
|
||||||
foo = range_glb_lo(rng1->next,rng2->next,hi);
|
foo = range_glb_lo(rng1->next,rng2->next,hi);
|
||||||
foo = find_range_lo(b,foo);
|
foo = find_range_lo(b,foo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
foo = range_glb_lo(rng2,rng1->next,hi);
|
foo = range_glb_lo(rng2,rng1->next,hi);
|
||||||
}
|
}
|
||||||
else foo = range_glb_lo(rng1->next,rng2,hi);
|
else foo = range_glb_lo(rng1->next,rng2,hi);
|
||||||
res = foo;
|
res = foo;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** computes the lub (smallest containing subtree) of two ranges */
|
/** computes the lub (smallest containing subtree) of two ranges */
|
||||||
scopes::range scopes::range_lub(const range &rng1, const range &rng2){
|
scopes::range scopes::range_lub(const range &rng1, const range &rng2){
|
||||||
int hi = tree_lca(rng1.hi,rng2.hi);
|
int hi = tree_lca(rng1.hi,rng2.hi);
|
||||||
if(hi == SHRT_MAX) return range_full();
|
if(hi == SHRT_MAX) return range_full();
|
||||||
range_lo *lo = range_lub_lo(rng1.lo,rng2.lo);
|
range_lo *lo = range_lub_lo(rng1.lo,rng2.lo);
|
||||||
return range(hi,lo);
|
return range(hi,lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** computes the glb (intersection) of two ranges */
|
/** computes the glb (intersection) of two ranges */
|
||||||
scopes::range scopes::range_glb(const range &rng1, const range &rng2){
|
scopes::range scopes::range_glb(const range &rng1, const range &rng2){
|
||||||
if(rng1.hi == SHRT_MAX) return rng2;
|
if(rng1.hi == SHRT_MAX) return rng2;
|
||||||
if(rng2.hi == SHRT_MAX) return rng1;
|
if(rng2.hi == SHRT_MAX) return rng1;
|
||||||
int hi = tree_gcd(rng1.hi,rng2.hi);
|
int hi = tree_gcd(rng1.hi,rng2.hi);
|
||||||
range_lo *lo = hi == SHRT_MIN ? 0 : range_glb_lo(rng1.lo,rng2.lo,hi);
|
range_lo *lo = hi == SHRT_MIN ? 0 : range_glb_lo(rng1.lo,rng2.lo,hi);
|
||||||
if(!lo) hi = SHRT_MIN;
|
if(!lo) hi = SHRT_MIN;
|
||||||
return range(hi,lo);
|
return range(hi,lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is this range empty? */
|
/** is this range empty? */
|
||||||
bool scopes::range_is_empty(const range &rng){
|
bool scopes::range_is_empty(const range &rng){
|
||||||
return rng.hi == SHRT_MIN;
|
return rng.hi == SHRT_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return an empty range */
|
/** return an empty range */
|
||||||
scopes::range scopes::range_empty(){
|
scopes::range scopes::range_empty(){
|
||||||
return range(SHRT_MIN,0);
|
return range(SHRT_MIN,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return a full range */
|
/** return a full range */
|
||||||
scopes::range scopes::range_full(){
|
scopes::range scopes::range_full(){
|
||||||
return range(SHRT_MAX,0);
|
return range(SHRT_MAX,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return the maximal element of a range */
|
/** return the maximal element of a range */
|
||||||
int scopes::range_max(const range &rng){
|
int scopes::range_max(const range &rng){
|
||||||
return rng.hi;
|
return rng.hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return a minimal (not necessarily unique) element of a range */
|
/** return a minimal (not necessarily unique) element of a range */
|
||||||
int scopes::range_min(const range &rng){
|
int scopes::range_min(const range &rng){
|
||||||
if(rng.hi == SHRT_MAX) return SHRT_MIN;
|
if(rng.hi == SHRT_MAX) return SHRT_MIN;
|
||||||
return rng.lo ? rng.lo->lo : SHRT_MAX;
|
return rng.lo ? rng.lo->lo : SHRT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** return range consisting of downward closure of a point */
|
/** return range consisting of downward closure of a point */
|
||||||
scopes::range scopes::range_downward(int _hi){
|
scopes::range scopes::range_downward(int _hi){
|
||||||
std::vector<bool> descendants(parents.size());
|
std::vector<bool> descendants(parents.size());
|
||||||
for(int i = descendants.size() - 1; i >= 0 ; i--)
|
for(int i = descendants.size() - 1; i >= 0 ; i--)
|
||||||
descendants[i] = i == _hi || parents[i] < parents.size() && descendants[parents[i]];
|
descendants[i] = i == _hi || parents[i] < parents.size() && descendants[parents[i]];
|
||||||
for(unsigned i = 0; i < descendants.size() - 1; i++)
|
for(unsigned i = 0; i < descendants.size() - 1; i++)
|
||||||
if(parents[i] < parents.size())
|
if(parents[i] < parents.size())
|
||||||
descendants[parents[i]] = false;
|
descendants[parents[i]] = false;
|
||||||
range_lo *foo = 0;
|
range_lo *foo = 0;
|
||||||
for(int i = descendants.size() - 1; i >= 0; --i)
|
for(int i = descendants.size() - 1; i >= 0; --i)
|
||||||
if(descendants[i]) foo = find_range_lo(i,foo);
|
if(descendants[i]) foo = find_range_lo(i,foo);
|
||||||
return range(_hi,foo);
|
return range(_hi,foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** add an element to a range */
|
/** add an element to a range */
|
||||||
void scopes::range_add(int i, range &n){
|
void scopes::range_add(int i, range &n){
|
||||||
range foo = range(i, find_range_lo(i,0));
|
range foo = range(i, find_range_lo(i,0));
|
||||||
n = range_lub(foo,n);
|
n = range_lub(foo,n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Choose an element of rng1 that is near to rng2 */
|
/** Choose an element of rng1 that is near to rng2 */
|
||||||
int scopes::range_near(const range &rng1, const range &rng2){
|
int scopes::range_near(const range &rng1, const range &rng2){
|
||||||
|
|
||||||
int frame;
|
int frame;
|
||||||
int thing = tree_lca(rng1.hi,rng2.hi);
|
int thing = tree_lca(rng1.hi,rng2.hi);
|
||||||
if(thing != rng1.hi) return rng1.hi;
|
if(thing != rng1.hi) return rng1.hi;
|
||||||
range line = range(rng1.hi,find_range_lo(rng2.hi,(range_lo *)0));
|
range line = range(rng1.hi,find_range_lo(rng2.hi,(range_lo *)0));
|
||||||
line = range_glb(line,rng1);
|
line = range_glb(line,rng1);
|
||||||
return range_min(line);
|
return range_min(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** test whether a tree node is contained in a range */
|
/** test whether a tree node is contained in a range */
|
||||||
bool scopes::in_range(int n, const range &rng){
|
bool scopes::in_range(int n, const range &rng){
|
||||||
range r = range_empty();
|
range r = range_empty();
|
||||||
range_add(n,r);
|
range_add(n,r);
|
||||||
r = range_glb(rng,r);
|
r = range_glb(rng,r);
|
||||||
return !range_is_empty(r);
|
return !range_is_empty(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** test whether two ranges of tree nodes intersect */
|
/** test whether two ranges of tree nodes intersect */
|
||||||
bool scopes::ranges_intersect(const range &rng1, const range &rng2){
|
bool scopes::ranges_intersect(const range &rng1, const range &rng2){
|
||||||
range r = range_glb(rng1,rng2);
|
range r = range_glb(rng1,rng2);
|
||||||
return !range_is_empty(r);
|
return !range_is_empty(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool scopes::range_contained(const range &rng1, const range &rng2){
|
bool scopes::range_contained(const range &rng1, const range &rng2){
|
||||||
range r = range_glb(rng1,rng2);
|
range r = range_glb(rng1,rng2);
|
||||||
return r.hi == rng1.hi && r.lo == rng1.lo;
|
return r.hi == rng1.hi && r.lo == rng1.lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,197 +1,197 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2011 Microsoft Corporation
|
Copyright (c) 2011 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
iz3scopes.h
|
iz3scopes.h
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
Calculations with scopes, for both sequence and tree interpolation.
|
Calculations with scopes, for both sequence and tree interpolation.
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Ken McMillan (kenmcmil)
|
Ken McMillan (kenmcmil)
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef IZ3SOPES_H
|
#ifndef IZ3SOPES_H
|
||||||
#define IZ3SOPES_H
|
#define IZ3SOPES_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
class scopes {
|
class scopes {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Construct from parents vector. */
|
/** Construct from parents vector. */
|
||||||
scopes(const std::vector<int> &_parents){
|
scopes(const std::vector<int> &_parents){
|
||||||
parents = _parents;
|
parents = _parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes(){
|
scopes(){
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(const std::vector<int> &_parents){
|
void initialize(const std::vector<int> &_parents){
|
||||||
parents = _parents;
|
parents = _parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The parents vector defining the tree structure */
|
/** The parents vector defining the tree structure */
|
||||||
std::vector<int> parents;
|
std::vector<int> parents;
|
||||||
|
|
||||||
// #define FULL_TREE
|
// #define FULL_TREE
|
||||||
#ifndef FULL_TREE
|
#ifndef FULL_TREE
|
||||||
struct range {
|
struct range {
|
||||||
range(){
|
range(){
|
||||||
lo = SHRT_MAX;
|
lo = SHRT_MAX;
|
||||||
hi = SHRT_MIN;
|
hi = SHRT_MIN;
|
||||||
}
|
}
|
||||||
short lo, hi;
|
short lo, hi;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** computes the lub (smallest containing subtree) of two ranges */
|
/** computes the lub (smallest containing subtree) of two ranges */
|
||||||
range range_lub(const range &rng1, const range &rng2);
|
range range_lub(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
/** computes the glb (intersection) of two ranges */
|
/** computes the glb (intersection) of two ranges */
|
||||||
range range_glb(const range &rng1, const range &rng2);
|
range range_glb(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
/** is this range empty? */
|
/** is this range empty? */
|
||||||
bool range_is_empty(const range &rng){
|
bool range_is_empty(const range &rng){
|
||||||
return rng.hi < rng.lo;
|
return rng.hi < rng.lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return an empty range */
|
/** return an empty range */
|
||||||
range range_empty(){
|
range range_empty(){
|
||||||
range res;
|
range res;
|
||||||
res.lo = SHRT_MAX;
|
res.lo = SHRT_MAX;
|
||||||
res.hi = SHRT_MIN;
|
res.hi = SHRT_MIN;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return an empty range */
|
/** return an empty range */
|
||||||
range range_full(){
|
range range_full(){
|
||||||
range res;
|
range res;
|
||||||
res.lo = SHRT_MIN;
|
res.lo = SHRT_MIN;
|
||||||
res.hi = SHRT_MAX;
|
res.hi = SHRT_MAX;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return the maximal element of a range */
|
/** return the maximal element of a range */
|
||||||
int range_max(const range &rng){
|
int range_max(const range &rng){
|
||||||
return rng.hi;
|
return rng.hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return a minimal (not necessarily unique) element of a range */
|
/** return a minimal (not necessarily unique) element of a range */
|
||||||
int range_min(const range &rng){
|
int range_min(const range &rng){
|
||||||
return rng.lo;
|
return rng.lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return range consisting of downward closure of a point */
|
/** return range consisting of downward closure of a point */
|
||||||
range range_downward(int _hi){
|
range range_downward(int _hi){
|
||||||
range foo;
|
range foo;
|
||||||
foo.lo = SHRT_MIN;
|
foo.lo = SHRT_MIN;
|
||||||
foo.hi = _hi;
|
foo.hi = _hi;
|
||||||
return foo;
|
return foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void range_add(int i, range &n){
|
void range_add(int i, range &n){
|
||||||
#if 0
|
#if 0
|
||||||
if(i < n.lo) n.lo = i;
|
if(i < n.lo) n.lo = i;
|
||||||
if(i > n.hi) n.hi = i;
|
if(i > n.hi) n.hi = i;
|
||||||
#else
|
#else
|
||||||
range rng; rng.lo = i; rng.hi = i;
|
range rng; rng.lo = i; rng.hi = i;
|
||||||
n = range_lub(rng,n);
|
n = range_lub(rng,n);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Choose an element of rng1 that is near to rng2 */
|
/** Choose an element of rng1 that is near to rng2 */
|
||||||
int range_near(const range &rng1, const range &rng2){
|
int range_near(const range &rng1, const range &rng2){
|
||||||
int frame;
|
int frame;
|
||||||
int thing = tree_lca(rng1.lo,rng2.hi);
|
int thing = tree_lca(rng1.lo,rng2.hi);
|
||||||
if(thing == rng1.lo) frame = rng1.lo;
|
if(thing == rng1.lo) frame = rng1.lo;
|
||||||
else frame = tree_gcd(thing,rng1.hi);
|
else frame = tree_gcd(thing,rng1.hi);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct range_lo {
|
struct range_lo {
|
||||||
int lo;
|
int lo;
|
||||||
range_lo *next;
|
range_lo *next;
|
||||||
range_lo(int _lo, range_lo *_next){
|
range_lo(int _lo, range_lo *_next){
|
||||||
lo = _lo;
|
lo = _lo;
|
||||||
next = _next;
|
next = _next;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct range {
|
struct range {
|
||||||
int hi;
|
int hi;
|
||||||
range_lo *lo;
|
range_lo *lo;
|
||||||
range(int _hi, range_lo *_lo){
|
range(int _hi, range_lo *_lo){
|
||||||
hi = _hi;
|
hi = _hi;
|
||||||
lo = _lo;
|
lo = _lo;
|
||||||
}
|
}
|
||||||
range(){
|
range(){
|
||||||
hi = SHRT_MIN;
|
hi = SHRT_MIN;
|
||||||
lo = 0;
|
lo = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
range_tables *rt;
|
range_tables *rt;
|
||||||
|
|
||||||
/** computes the lub (smallest containing subtree) of two ranges */
|
/** computes the lub (smallest containing subtree) of two ranges */
|
||||||
range range_lub(const range &rng1, const range &rng2);
|
range range_lub(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
/** computes the glb (intersection) of two ranges */
|
/** computes the glb (intersection) of two ranges */
|
||||||
range range_glb(const range &rng1, const range &rng2);
|
range range_glb(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
/** is this range empty? */
|
/** is this range empty? */
|
||||||
bool range_is_empty(const range &rng);
|
bool range_is_empty(const range &rng);
|
||||||
|
|
||||||
/** return an empty range */
|
/** return an empty range */
|
||||||
range range_empty();
|
range range_empty();
|
||||||
|
|
||||||
/** return a full range */
|
/** return a full range */
|
||||||
range range_full();
|
range range_full();
|
||||||
|
|
||||||
/** return the maximal element of a range */
|
/** return the maximal element of a range */
|
||||||
int range_max(const range &rng);
|
int range_max(const range &rng);
|
||||||
|
|
||||||
/** return a minimal (not necessarily unique) element of a range */
|
/** return a minimal (not necessarily unique) element of a range */
|
||||||
int range_min(const range &rng);
|
int range_min(const range &rng);
|
||||||
|
|
||||||
/** return range consisting of downward closure of a point */
|
/** return range consisting of downward closure of a point */
|
||||||
range range_downward(int _hi);
|
range range_downward(int _hi);
|
||||||
|
|
||||||
/** add an element to a range */
|
/** add an element to a range */
|
||||||
void range_add(int i, range &n);
|
void range_add(int i, range &n);
|
||||||
|
|
||||||
/** Choose an element of rng1 that is near to rng2 */
|
/** Choose an element of rng1 that is near to rng2 */
|
||||||
int range_near(const range &rng1, const range &rng2);
|
int range_near(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
range_lo *find_range_lo(int lo, range_lo *next);
|
range_lo *find_range_lo(int lo, range_lo *next);
|
||||||
range_lo *range_lub_lo(range_lo *rng1, range_lo *rng2);
|
range_lo *range_lub_lo(range_lo *rng1, range_lo *rng2);
|
||||||
range_lo *range_glb_lo(range_lo *rng1, range_lo *rng2, int lim);
|
range_lo *range_glb_lo(range_lo *rng1, range_lo *rng2, int lim);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** test whether a tree node is contained in a range */
|
/** test whether a tree node is contained in a range */
|
||||||
bool in_range(int n, const range &rng);
|
bool in_range(int n, const range &rng);
|
||||||
|
|
||||||
/** test whether two ranges of tree nodes intersect */
|
/** test whether two ranges of tree nodes intersect */
|
||||||
bool ranges_intersect(const range &rng1, const range &rng2);
|
bool ranges_intersect(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
/** test whether range rng1 contained in range rng2 */
|
/** test whether range rng1 contained in range rng2 */
|
||||||
bool range_contained(const range &rng1, const range &rng2);
|
bool range_contained(const range &rng1, const range &rng2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int tree_lca(int n1, int n2);
|
int tree_lca(int n1, int n2);
|
||||||
int tree_gcd(int n1, int n2);
|
int tree_gcd(int n1, int n2);
|
||||||
bool tree_mode(){return parents.size() != 0;}
|
bool tree_mode(){return parents.size() != 0;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -464,7 +464,7 @@ public:
|
||||||
for(int i = 0; i < 2; i++){ // try the second equality both ways
|
for(int i = 0; i < 2; i++){ // try the second equality both ways
|
||||||
if(match_op(eq_ops_r[0],Select,sel_ops,2))
|
if(match_op(eq_ops_r[0],Select,sel_ops,2))
|
||||||
if(match_op(sel_ops[0],Store,sto_ops,3))
|
if(match_op(sel_ops[0],Store,sto_ops,3))
|
||||||
if(match_op(eq_ops_r[1],Select,sel_ops2,2))
|
if(match_op(eq_ops_r[1],Select,sel_ops2,2))
|
||||||
for(int j = 0; j < 2; j++){ // try the first equality both ways
|
for(int j = 0; j < 2; j++){ // try the first equality both ways
|
||||||
if(eq_ops_l[0] == sto_ops[1]
|
if(eq_ops_l[0] == sto_ops[1]
|
||||||
&& eq_ops_l[1] == sel_ops[1]
|
&& eq_ops_l[1] == sel_ops[1]
|
||||||
|
@ -482,8 +482,8 @@ public:
|
||||||
// int frame = range_min(ast_scope(res)); TODO
|
// int frame = range_min(ast_scope(res)); TODO
|
||||||
// antes.push_back(std::pair<ast,int>(res,frame));
|
// antes.push_back(std::pair<ast,int>(res,frame));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::swap(eq_ops_l[0],eq_ops_l[1]);
|
std::swap(eq_ops_l[0],eq_ops_l[1]);
|
||||||
}
|
}
|
||||||
std::swap(eq_ops_r[0],eq_ops_r[1]);
|
std::swap(eq_ops_r[0],eq_ops_r[1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -484,7 +484,7 @@ public:
|
||||||
for(int i = 0; i < 2; i++){ // try the second equality both ways
|
for(int i = 0; i < 2; i++){ // try the second equality both ways
|
||||||
if(match_op(eq_ops_r[0],Select,sel_ops,2))
|
if(match_op(eq_ops_r[0],Select,sel_ops,2))
|
||||||
if(match_op(sel_ops[0],Store,sto_ops,3))
|
if(match_op(sel_ops[0],Store,sto_ops,3))
|
||||||
if(match_op(eq_ops_r[1],Select,sel_ops2,2))
|
if(match_op(eq_ops_r[1],Select,sel_ops2,2))
|
||||||
for(int j = 0; j < 2; j++){ // try the first equality both ways
|
for(int j = 0; j < 2; j++){ // try the first equality both ways
|
||||||
if(eq_ops_l[0] == sto_ops[1]
|
if(eq_ops_l[0] == sto_ops[1]
|
||||||
&& eq_ops_l[1] == sel_ops[1]
|
&& eq_ops_l[1] == sel_ops[1]
|
||||||
|
@ -502,8 +502,8 @@ public:
|
||||||
int frame = range_min(ast_scope(res));
|
int frame = range_min(ast_scope(res));
|
||||||
antes.push_back(std::pair<ast,int>(res,frame));
|
antes.push_back(std::pair<ast,int>(res,frame));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::swap(eq_ops_l[0],eq_ops_l[1]);
|
std::swap(eq_ops_l[0],eq_ops_l[1]);
|
||||||
}
|
}
|
||||||
std::swap(eq_ops_r[0],eq_ops_r[1]);
|
std::swap(eq_ops_r[0],eq_ops_r[1]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue