Skip to content

Commit 3e77dd6

Browse files
author
Daniel Kroening
authored
Merge pull request #1496 from smowton/smowton/feature/symbol_table_writer
SEC-79 Add symbol table writer
2 parents 728dbb5 + c3c24e2 commit 3e77dd6

File tree

3 files changed

+414
-0
lines changed

3 files changed

+414
-0
lines changed

src/util/symbol_table_writer.h

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
2+
// Copyright 2016-2017 DiffBlue Limited. All Rights Reserved.
3+
4+
/// \file
5+
/// A symbol table writer that records which entries have been updated
6+
7+
#ifndef CPROVER_UTIL_SYMBOL_TABLE_WRITER_H
8+
#define CPROVER_UTIL_SYMBOL_TABLE_WRITER_H
9+
10+
#include <utility>
11+
#include <unordered_set>
12+
#include "irep.h"
13+
#include "symbol_table.h"
14+
15+
/// \brief A symbol table wrapper that records which entries have been
16+
/// updated/removed
17+
/// \ingroup gr_symbol_table
18+
/// A caller can pass a `journalling_symbol_table_writert` into a callee that is
19+
/// expected to mutate it somehow, then after it has run inspect the recording
20+
/// table's journal to determine what has changed more cheaply than examining
21+
/// every symbol.
22+
///
23+
/// Example of usage:
24+
/// ```
25+
/// symbol_tablet real_table;
26+
/// init_table(real_table);
27+
///
28+
/// journalling_symbol_table_writert journal(actual_table); // Wraps real_table
29+
/// alter_table(journal);
30+
31+
/// for(const auto &added : journal.added())
32+
/// {
33+
/// printf("%s was added\n", added.name);
34+
/// }
35+
class journalling_symbol_table_writert
36+
{
37+
public:
38+
typedef std::unordered_set<irep_idt, irep_id_hash> changesett;
39+
private:
40+
symbol_tablet &base_symbol_table;
41+
// Symbols originally in the table will never be marked inserted
42+
changesett inserted;
43+
// get_writeable marks an existing symbol updated
44+
// Inserted symbols are marked updated, removed ones aren't
45+
changesett updated;
46+
// Symbols not originally in the table will never be marked removed
47+
changesett removed;
48+
49+
private:
50+
explicit journalling_symbol_table_writert(symbol_tablet &base_symbol_table):
51+
base_symbol_table(base_symbol_table)
52+
{
53+
}
54+
55+
public:
56+
journalling_symbol_table_writert(
57+
const journalling_symbol_table_writert &other):
58+
base_symbol_table(other.base_symbol_table)
59+
{
60+
}
61+
62+
/// Permits implicit cast to const symbol_tablet &
63+
operator const symbol_tablet &() const
64+
{
65+
return base_symbol_table;
66+
}
67+
68+
static journalling_symbol_table_writert wrap(
69+
symbol_tablet &base_symbol_table)
70+
{
71+
return journalling_symbol_table_writert(base_symbol_table);
72+
}
73+
74+
bool add(const symbolt &symbol)
75+
{
76+
bool ret=base_symbol_table.add(symbol);
77+
if(!ret)
78+
on_insert(symbol.name);
79+
return ret;
80+
}
81+
82+
bool move(symbolt &symbol, symbolt *&new_symbol)
83+
{
84+
bool ret=base_symbol_table.move(symbol, new_symbol);
85+
if(!ret)
86+
on_insert(symbol.name);
87+
else
88+
on_update(symbol.name);
89+
return ret;
90+
}
91+
92+
symbolt *get_writeable(const irep_idt &identifier)
93+
{
94+
symbolt *result=base_symbol_table.get_writeable(identifier);
95+
if(result)
96+
on_update(identifier);
97+
return result;
98+
}
99+
100+
symbolt &get_writeable_ref(const irep_idt &identifier)
101+
{
102+
// Run on_update *after* the get-ref operation in case it throws
103+
symbolt &result=base_symbol_table.get_writeable_ref(identifier);
104+
on_update(identifier);
105+
return result;
106+
}
107+
108+
std::pair<symbolt &, bool> insert(symbolt symbol)
109+
{
110+
std::pair<symbolt &, bool> result=
111+
base_symbol_table.insert(std::move(symbol));
112+
if(result.second)
113+
on_insert(result.first.name);
114+
return result;
115+
}
116+
117+
bool remove(const irep_idt &id)
118+
{
119+
bool ret=base_symbol_table.remove(id);
120+
if(!ret)
121+
on_remove(id);
122+
return ret;
123+
}
124+
125+
void erase(const symbol_tablet::symbolst::const_iterator &entry)
126+
{
127+
base_symbol_table.erase(entry);
128+
on_remove(entry->first);
129+
}
130+
131+
void clear()
132+
{
133+
for(const auto &named_symbol : base_symbol_table.symbols)
134+
on_remove(named_symbol.first);
135+
base_symbol_table.clear();
136+
}
137+
138+
const changesett &get_inserted() const { return inserted; }
139+
const changesett &get_updated() const { return updated; }
140+
const changesett &get_removed() const { return removed; }
141+
142+
private:
143+
void on_insert(const irep_idt &id)
144+
{
145+
if(removed.erase(id)==0)
146+
inserted.insert(id);
147+
updated.insert(id);
148+
}
149+
150+
void on_update(const irep_idt &id)
151+
{
152+
updated.insert(id);
153+
}
154+
155+
void on_remove(const irep_idt &id)
156+
{
157+
if(inserted.erase(id)==0)
158+
removed.insert(id);
159+
updated.erase(id);
160+
}
161+
};
162+
163+
#endif // CPROVER_UTIL_SYMBOL_TABLE_WRITER_H

unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ SRC += unit_tests.cpp \
3131
util/expr_iterator.cpp \
3232
util/message.cpp \
3333
util/simplify_expr.cpp \
34+
util/symbol_table.cpp \
3435
catch_example.cpp \
3536
# Empty last line
3637

0 commit comments

Comments
 (0)