libqasm
library for handling cQASM files
cqasm-v1-resolver.cpp
Go to the documentation of this file.
1 
5 #include <unordered_set>
6 #include "cqasm-utils.hpp"
7 #include "cqasm-error.hpp"
8 #include "cqasm-v1-resolver.hpp"
9 
10 namespace cqasm {
11 namespace v1 {
12 namespace resolver {
13 
14 using Type = types::Type;
18 
19 
24  const std::string &name,
25  const values::Value &value,
26  const tree::Maybe<ast::Mapping> &node
27 ) {
28  auto lname = utils::lowercase(name);
29  auto it = table.find(lname);
30  if (it != table.end()) {
31  table.erase(it);
32  }
33  table.insert(
34  std::make_pair(
35  lname,
36  std::pair<const values::Value, tree::Maybe<ast::Mapping>>(value, node)
37  )
38  );
39 }
40 
45 Value MappingTable::resolve(const std::string &name) const {
46  auto entry = table.find(utils::lowercase(name));
47  if (entry == table.end()) {
48  throw NameResolutionFailure("failed to resolve " + name);
49  } else {
50  return Value(entry->second.first->clone());
51  }
52 }
53 
57 const std::unordered_map<std::string, std::pair<const values::Value, tree::Maybe<ast::Mapping>>> &MappingTable::get_table() const {
58  return table;
59 }
60 
65 template <class T>
66 class Overload {
67 private:
68  T tag;
69  Types param_types;
70 public:
74  template <class... Ts>
75  Overload(const T &tag, const Types &param_types)
76  : tag(tag), param_types(param_types)
77  {}
78 
82  const T &get_tag() const {
83  return tag;
84  }
85 
89  size_t num_params() const {
90  return param_types.size();
91  }
92 
97  const Type &param_type_at(size_t index) const {
98  return param_types.at(index);
99  }
100 };
101 
110 template <class T>
112 private:
113  std::vector<Overload<T>> overloads;
114 
115 public:
116 
122  void add_overload(const T &tag, const Types &param_types) {
123  overloads.emplace_back(tag, param_types);
124  }
125 
132  std::pair<T, Values> resolve(const Values &args) {
133  for (auto overload = overloads.rbegin(); overload != overloads.rend(); ++overload) {
134  if (overload->num_params() != args.size()) {
135  continue;
136  }
137  Values promoted_args;
138  bool ok = true;
139  for (size_t i = 0; i < args.size(); i++) {
140  auto promoted_arg = promote(args.at(i), overload->param_type_at(i));
141  if (promoted_arg.empty()) {
142  ok = false;
143  break;
144  }
145  promoted_args.add(promoted_arg);
146  }
147  if (ok) {
148  return std::pair<T, Values>(overload->get_tag(), promoted_args);
149  }
150  }
151  throw OverloadResolutionFailure("failed to resolve overload");
152  }
153 
154 };
155 
160 template <class T>
162 private:
163  std::unordered_map<std::string, OverloadResolver<T>> table;
164 public:
175  void add_overload(const std::string &name, const T &tag, const Types &param_types) {
176  std::string name_lower = utils::lowercase(name);
177  auto entry = table.find(name_lower);
178  if (entry == table.end()) {
179  auto resolver = OverloadResolver<T>();
180  resolver.add_overload(tag, param_types);
181  table.insert(std::pair<std::string, OverloadResolver<T>>(name_lower, std::move(resolver)));
182  } else {
183  entry->second.add_overload(tag, param_types);
184  }
185  }
186 
195  std::pair<T, Values> resolve(const std::string &name, const Values &args) {
196  std::string name_lower = utils::lowercase(name);
197  auto entry = table.find(name_lower);
198  if (entry == table.end()) {
199  throw NameResolutionFailure("failed to resolve " + name);
200  } else {
201  try {
202  return entry->second.resolve(args);
203  } catch (OverloadResolutionFailure &e) {
204  e.message.str("");
205  e.message << "failed to resolve overload for " << name;
206  e.message << " with argument pack " << values::types_of(args);
207  throw;
208  }
209  }
210  }
211 
212 };
213 
214 // The following things *are all default*. Unfortunately, the compiler
215 // can't infer them because OverloadedNameResolver is incomplete.
219 FunctionTable::FunctionTable(FunctionTable&& t) : resolver(std::move(t.resolver)) {}
221  resolver = std::unique_ptr<OverloadedNameResolver<FunctionImpl>>(new OverloadedNameResolver<FunctionImpl>(*t.resolver));
222  return *this;
223 }
225  resolver = std::move(t.resolver);
226  return *this;
227 }
228 
242 void FunctionTable::add(const std::string &name, const Types &param_types, const FunctionImpl &impl) {
243  resolver->add_overload(name, impl, param_types);
244 }
245 
252 Value FunctionTable::call(const std::string &name, const Values &args) const {
253 
254  // Resolve the function and typecheck/promote the argument list.
255  auto resolution = resolver->resolve(name, args);
256 
257  // Call the function with the typechecked/promoted argument list, and
258  // return its result.
259  return resolution.first(resolution.second);
260 
261 }
262 
263 // The following things *are all default*. Unfortunately, the compiler
264 // can't infer them because OverloadedNameResolver is incomplete.
265 ErrorModelTable::ErrorModelTable() : resolver(new OverloadedNameResolver<error_model::ErrorModel>()) {}
267 ErrorModelTable::ErrorModelTable(const ErrorModelTable& t) : resolver(new OverloadedNameResolver<error_model::ErrorModel>(*t.resolver)) {}
268 ErrorModelTable::ErrorModelTable(ErrorModelTable&& t) : resolver(std::move(t.resolver)) {}
270  resolver = std::unique_ptr<OverloadedNameResolver<error_model::ErrorModel>>(new OverloadedNameResolver<error_model::ErrorModel>(*t.resolver));
271  return *this;
272 }
274  resolver = std::move(t.resolver);
275  return *this;
276 }
277 
282  resolver->add_overload(type.name, type, type.param_types);
283 }
284 
292 tree::One<semantic::ErrorModel> ErrorModelTable::resolve(const std::string &name, const Values &args) const {
293  auto resolved = resolver->resolve(name, args);
294  return tree::make<semantic::ErrorModel>(
295  tree::make<error_model::ErrorModel>(resolved.first),
296  name,
297  resolved.second,
299 }
300 
301 // The following things *are all default*. Unfortunately, the compiler
302 // can't infer them because OverloadedNameResolver is incomplete.
303 InstructionTable::InstructionTable() : resolver(new OverloadedNameResolver<instruction::Instruction>()) {}
305 InstructionTable::InstructionTable(const InstructionTable& t) : resolver(new OverloadedNameResolver<instruction::Instruction>(*t.resolver)) {}
306 InstructionTable::InstructionTable(InstructionTable&& t) : resolver(std::move(t.resolver)) {}
308  resolver = std::unique_ptr<OverloadedNameResolver<instruction::Instruction>>(new OverloadedNameResolver<instruction::Instruction>(*t.resolver));
309  return *this;
310 }
312  resolver = std::move(t.resolver);
313  return *this;
314 }
315 
320  resolver->add_overload(type.name, type, type.param_types);
321 }
322 
331  const std::string &name,
332  const Values &args
333 ) const {
334  auto resolved = resolver->resolve(name, args);
335  return tree::make<semantic::Instruction>(
336  tree::make<instruction::Instruction>(resolved.first),
337  name, values::Value(), resolved.second,
339 }
340 
341 } // namespace resolver
342 } // namespace v1
343 } // namespace cqasm
void add(const error_model::ErrorModel &type)
Registers an error model.
void add(const std::string &name, const values::Value &value, const tree::Maybe< ast::Mapping > &node=tree::Maybe< ast::Mapping >())
Adds a mapping.
const std::unordered_map< std::string, std::pair< const values::Value, tree::Maybe< ast::Mapping > > > & get_table() const
Grants read access to the underlying map.
::tree::base::Maybe< T > Maybe
Definition: cqasm-tree.hpp:23
types::Types types_of(const Values &values)
Returns the types of the given values.
std::string name
The name of the error model.
types::Types param_types
The vector of parameter types that this error model expects.
Toplevel namespace with entry points for the new API.
Defines various utility functions.
STL namespace.
ErrorModelTable & operator=(const ErrorModelTable &t)
InstructionTable & operator=(const InstructionTable &t)
void add_overload(const T &tag, const Types &param_types)
Adds a possible overload to the resolver.
Table of the supported instructions and their overloads.
FunctionTable & operator=(const FunctionTable &t)
tree::Any< Node > Values
Zero or more cQASM values.
Representation of an error model.
Overload(const T &tag, const Types &param_types)
Construct a possible overload.
Representation of an available instruction (also known as gate) in the instruction set...
Value promote(const Value &value, const types::Type &type)
Type-checks and (if necessary) promotes the given value to the given type.
Table of all overloads of all constant propagation functions.
Table of the supported instructions and their overloads.
types::Types param_types
The vector of parameter types that this instruction expects.
tree::One< semantic::Instruction > resolve(const std::string &name, const values::Values &args) const
Resolves an instruction.
Namespace for the "new" cQASM 1.x API.
void add_overload(const std::string &name, const T &tag, const Types &param_types)
Registers a callable.
Contains custom exception objects used by libqasm.
tree::One< Node > Value
A cQASM value, either known at compile-time or an expression for something only known at runtime...
tree::One< TypeBase > Type
A cQASM type.
::tree::base::Any< T > Any
Definition: cqasm-tree.hpp:29
tree::Any< TypeBase > Types
Zero or more cQASM types.
std::pair< T, Values > resolve(const Values &args)
Tries to resolve which overload belongs to the given argument list, if any.
tree::One< semantic::ErrorModel > resolve(const std::string &name, const values::Values &args) const
Resolves an error model.
void add(const instruction::Instruction &type)
Registers an instruction type.
Contains MappingTable, FunctionTable, and ErrorModelTable, representing the various cQASM namespaces ...
std::pair< T, Values > resolve(const std::string &name, const Values &args)
Resolves the particular overload for the callable with the given case-insensitively matched name...
Represents a set of possible overloads for the parameter types of a function, gate, or error model.
std::string lowercase(const std::string &name)
Makes a string lowercase.
Definition: cqasm-utils.cpp:15
Table of overloaded callables with case-insensitive identifier matching.
values::Value resolve(const std::string &name) const
Resolves a mapping.
const T & get_tag() const
Returns the tag for this overload.
values::Value call(const std::string &name, const values::Values &args) const
Calls a function.
::tree::base::One< T > One
Definition: cqasm-tree.hpp:26
void add(const std::string &name, const types::Types &param_types, const FunctionImpl &impl)
Registers a function.
Represents a possible overload for the parameter types of a function, gate, or error model...
std::function< values::Value(const values::Values &)> FunctionImpl
C++ function representing (one of the overloads of) a function usable in cQASM constant expressions...
size_t num_params() const
Returns the number of parameters for this overload.
const Type & param_type_at(size_t index) const
Returns the parameter type object for the parameter at the specified index.
std::string name
The name of the instruction.