Skip to content

Commit 95ea29a

Browse files
Merge pull request #2115 from peterschrammel/language-mode-utils
Language mode utils
2 parents bacfa27 + baa15f5 commit 95ea29a

File tree

5 files changed

+90
-30
lines changed

5 files changed

+90
-30
lines changed

src/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ languages: util.dir langapi.dir \
2525
cpp.dir ansi-c.dir xmllang.dir assembler.dir java_bytecode.dir \
2626
jsil.dir
2727

28+
solvers.dir: util.dir langapi.dir
29+
2830
goto-instrument.dir: languages goto-programs.dir pointer-analysis.dir \
2931
goto-symex.dir linking.dir analyses.dir solvers.dir \
3032
json.dir

src/langapi/language.h

+21
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,42 @@ class languaget:public messaget
114114

115115
// conversion of expressions
116116

117+
/// Formats the given expression in a language-specific way
118+
/// \param expr: the expression to format
119+
/// \param code: the formatted expression
120+
/// \param ns: a namespace
121+
/// \return false if conversion succeeds
117122
virtual bool from_expr(
118123
const exprt &expr,
119124
std::string &code,
120125
const namespacet &ns);
121126

127+
/// Formats the given type in a language-specific way
128+
/// \param type: the type to format
129+
/// \param code: the formatted type
130+
/// \param ns: a namespace
131+
/// \return false if conversion succeeds
122132
virtual bool from_type(
123133
const typet &type,
124134
std::string &code,
125135
const namespacet &ns);
126136

137+
/// Encodes the given type in a language-specific way
138+
/// \param type: the type to encode
139+
/// \param name: the encoded type
140+
/// \param ns: a namespace
141+
/// \return false if the conversion succeeds
127142
virtual bool type_to_name(
128143
const typet &type,
129144
std::string &name,
130145
const namespacet &ns);
131146

147+
/// Parses the given string into an expression
148+
/// \param code: the string to parse
149+
/// \param module: prefix to be used for identifiers
150+
/// \param expr: the parsed expression
151+
/// \param ns: a namespace
152+
/// \return false if the conversion succeeds
132153
virtual bool to_expr(
133154
const std::string &code,
134155
const std::string &module,

src/langapi/language_util.cpp

+4-24
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,12 @@ Author: Daniel Kroening, [email protected]
1717
#include "language.h"
1818
#include "mode.h"
1919

20-
static std::unique_ptr<languaget> get_language(
21-
const namespacet &ns,
22-
const irep_idt &identifier)
23-
{
24-
const symbolt *symbol;
25-
26-
if(identifier=="" ||
27-
ns.lookup(identifier, symbol) ||
28-
symbol->mode=="")
29-
return get_default_language();
30-
31-
std::unique_ptr<languaget> ptr=get_language_from_mode(symbol->mode);
32-
33-
if(ptr==nullptr)
34-
throw "symbol `"+id2string(symbol->name)+
35-
"' has unknown mode '"+id2string(symbol->mode)+"'";
36-
37-
return ptr;
38-
}
39-
4020
std::string from_expr(
4121
const namespacet &ns,
4222
const irep_idt &identifier,
4323
const exprt &expr)
4424
{
45-
std::unique_ptr<languaget> p(get_language(ns, identifier));
25+
std::unique_ptr<languaget> p(get_language_from_identifier(ns, identifier));
4626

4727
std::string result;
4828
p->from_expr(expr, result, ns);
@@ -55,7 +35,7 @@ std::string from_type(
5535
const irep_idt &identifier,
5636
const typet &type)
5737
{
58-
std::unique_ptr<languaget> p(get_language(ns, identifier));
38+
std::unique_ptr<languaget> p(get_language_from_identifier(ns, identifier));
5939

6040
std::string result;
6141
p->from_type(type, result, ns);
@@ -68,7 +48,7 @@ std::string type_to_name(
6848
const irep_idt &identifier,
6949
const typet &type)
7050
{
71-
std::unique_ptr<languaget> p(get_language(ns, identifier));
51+
std::unique_ptr<languaget> p(get_language_from_identifier(ns, identifier));
7252

7353
std::string result;
7454
p->type_to_name(type, result, ns);
@@ -93,7 +73,7 @@ exprt to_expr(
9373
const irep_idt &identifier,
9474
const std::string &src)
9575
{
96-
std::unique_ptr<languaget> p(get_language(ns, identifier));
76+
std::unique_ptr<languaget> p(get_language_from_identifier(ns, identifier));
9777

9878
null_message_handlert null_message_handler;
9979
p->set_message_handler(null_message_handler);

src/langapi/mode.cpp

+58-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Author: Daniel Kroening, [email protected]
1818

1919
#include "language.h"
2020

21+
#include <util/invariant.h>
22+
#include <util/namespace.h>
23+
2124
struct language_entryt
2225
{
2326
language_factoryt factory;
@@ -28,6 +31,10 @@ struct language_entryt
2831
typedef std::list<language_entryt> languagest;
2932
languagest languages;
3033

34+
/// Register a language
35+
/// Note: registering a language is required for using the functions
36+
/// in language_util.h
37+
/// \param factory: a language factory, e.g. `new_ansi_c_language`
3138
void register_language(language_factoryt factory)
3239
{
3340
languages.push_back(language_entryt());
@@ -37,17 +44,60 @@ void register_language(language_factoryt factory)
3744
languages.back().mode=l->id();
3845
}
3946

47+
/// Get the language corresponding to the given mode
48+
/// \param mode: the mode, e.g. `ID_C`
49+
/// \return the language or `nullptr` if the language has not been registered
4050
std::unique_ptr<languaget> get_language_from_mode(const irep_idt &mode)
4151
{
42-
for(languagest::const_iterator it=languages.begin();
43-
it!=languages.end();
44-
it++)
45-
if(mode==it->mode)
46-
return it->factory();
52+
for(const auto &language : languages)
53+
if(mode == language.mode)
54+
return language.factory();
4755

4856
return nullptr;
4957
}
5058

59+
/// Get the mode of the given identifier's symbol
60+
/// \param ns: a namespace
61+
/// \param identifier: an identifier
62+
/// \return the mode, e.g. `ID_C`, if the identifier is in the given
63+
/// symbol table, or `ID_unknown` otherwise
64+
const irep_idt &
65+
get_mode_from_identifier(const namespacet &ns, const irep_idt &identifier)
66+
{
67+
if(identifier.empty())
68+
return ID_unknown;
69+
const symbolt *symbol;
70+
if(ns.lookup(identifier, symbol))
71+
return ID_unknown;
72+
return symbol->mode;
73+
}
74+
75+
/// Get the language corresponding to the mode of the given identifier's symbol
76+
/// \param ns: a namespace
77+
/// \param identifier: an identifier
78+
/// \return the corresponding language if the mode is not `ID_unknown`, or
79+
/// the default language otherwise;
80+
/// Note: It is assumed as an invariant that languages of symbols in the symbol
81+
/// table have been registered.
82+
std::unique_ptr<languaget>
83+
get_language_from_identifier(const namespacet &ns, const irep_idt &identifier)
84+
{
85+
const irep_idt &mode = get_mode_from_identifier(ns, identifier);
86+
if(mode == ID_unknown)
87+
return get_default_language();
88+
89+
std::unique_ptr<languaget> language = get_language_from_mode(mode);
90+
INVARIANT(
91+
language,
92+
"symbol `" + id2string(identifier) + "' has unknown mode '" +
93+
id2string(mode) + "'");
94+
return language;
95+
}
96+
97+
/// Get the language corresponding to the registered file name extensions
98+
/// \param filename: a filename
99+
/// \return the corresponding language or `nullptr` if the extension cannot
100+
/// be resolved to any registered language
51101
std::unique_ptr<languaget> get_language_from_filename(
52102
const std::string &filename)
53103
{
@@ -83,8 +133,10 @@ std::unique_ptr<languaget> get_language_from_filename(
83133
return nullptr;
84134
}
85135

136+
/// Returns the default language
137+
/// \return the first registered language
86138
std::unique_ptr<languaget> get_default_language()
87139
{
88-
assert(!languages.empty());
140+
PRECONDITION(!languages.empty());
89141
return languages.front().factory();
90142
}

src/langapi/mode.h

+5
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@ Author: Daniel Kroening, [email protected]
1515
#include <memory> // unique_ptr
1616

1717
class languaget;
18+
class namespacet;
1819

1920
std::unique_ptr<languaget> get_language_from_mode(const irep_idt &mode);
21+
const irep_idt &
22+
get_mode_from_identifier(const namespacet &ns, const irep_idt &identifier);
23+
std::unique_ptr<languaget>
24+
get_language_from_identifier(const namespacet &ns, const irep_idt &identifier);
2025
std::unique_ptr<languaget> get_language_from_filename(
2126
const std::string &filename);
2227
std::unique_ptr<languaget> get_default_language();

0 commit comments

Comments
 (0)