xacc.cpp 22.9 KB
Newer Older
1
2
3
4
5
6
/*******************************************************************************
 * Copyright (c) 2017 UT-Battelle, LLC.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompanies this
 * distribution. The Eclipse Public License is available at
7
8
 * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
 *License is available at https://eclipse.org/org/documents/edl-v10.php
9
10
 *
 * Contributors:
11
12
 *   Alexander J. McCaskey - initial API and implementation
 *******************************************************************************/
13
#include "xacc.hpp"
14
#include "InstructionIterator.hpp"
15
#include "IRProvider.hpp"
16
#include "CLIParser.hpp"
Mccaskey, Alex's avatar
Mccaskey, Alex committed
17
18
#include <signal.h>
#include <cstdlib>
19
20
21
#include <fstream>
#include "xacc_config.hpp"
#include "cxxopts.hpp"
22
#include "AcceleratorDecorator.hpp"
23

24
25
#include "xacc_service.hpp"

26
27
#include <sys/types.h>
#include <sys/stat.h>
28
#include "TearDown.hpp"
29

30
using namespace cxxopts;
31
32
33

namespace xacc {

34
bool verbose = false;
35
bool isPyApi = false;
36
bool xaccFrameworkInitialized = false;
37
std::shared_ptr<CLIParser> xaccCLParser;
38
int argc = 0;
39
char **argv = NULL;
40
41
std::map<std::string, std::shared_ptr<CompositeInstruction>>
    compilation_database{};
42
43
std::map<std::string, std::shared_ptr<AcceleratorBuffer>> allocated_buffers {};

44
std::string rootPathString = "";
45

46
47
void set_verbose(bool v) {verbose=v;}

48
49
int getArgc() { return argc; }
char **getArgv() { return argv; }
50
void Initialize(std::vector<std::string> argv) {
51
52
53
54
55
56
  std::vector<char *> cstrs;
  argv.insert(argv.begin(), "appExec");
  for (auto &s : argv) {
    cstrs.push_back(&s.front());
  }
  Initialize(argv.size(), cstrs.data());
57
58
}

59
void Initialize() { Initialize(std::vector<std::string>{}); }
60

61
bool isInitialized() { return xaccFrameworkInitialized; }
62

Mccaskey, Alex's avatar
Mccaskey, Alex committed
63
void ctrl_c_handler(int signal) {
64
65
66
67
68
  error("Caught CTRL-C, exiting the framework.");
  Finalize();
  exit(1);
}

69
std::vector<std::string> getIncludePaths() {
70
  return xaccCLParser->getIncludePaths();
71
72
}

73
74
75
76
77
void PyInitialize(const std::string rootPath) {
  std::vector<std::string> args{"--xacc-root-path", rootPath};
  Initialize(args);
}

78
79
80
void Initialize(int arc, char **arv) {

  if (!xaccFrameworkInitialized) {
81
    xaccCLParser = std::make_shared<CLIParser>();
82
83
84
    argc = arc;
    argv = arv;

85
    xacc::ServiceAPI_Initialize(argc, argv);
86
87

    // Parse any user-supplied command line options
88
    xaccCLParser->parse(argc, argv);
89
90
91
92
93
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler = ctrl_c_handler;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT, &sigIntHandler, NULL);
94
95

    rootPathString = xacc::getRootPathString();
96
97
98
99
100
101
102
103
104
  }

  // We're good if we make it here, so indicate that we've been
  // initialized
  xacc::xaccFrameworkInitialized = true;

  if (!optionExists("queue-preamble")) {
    XACCLogger::instance()->dumpQueue();
  }
105
106
}

107
108
void setIsPyApi() { isPyApi = true; }

Mccaskey, Alex's avatar
Mccaskey, Alex committed
109
void setGlobalLoggerPredicate(MessagePredicate predicate) {
110
111
  XACCLogger::instance()->setGlobalLoggerPredicate(predicate);
  XACCLogger::instance()->dumpQueue();
Mccaskey, Alex's avatar
Mccaskey, Alex committed
112
}
113

114
115
116
117
118
119
120
121
void logToFile(bool enable) {
  XACCLogger::instance()->logToFile(enable);
}

void setLoggingLevel(int level) {
  XACCLogger::instance()->setLoggingLevel(level);
}

122
123
124
125
int getLoggingLevel() {
  return XACCLogger::instance()->getLoggingLevel();
}

126
127
128
129
void subscribeLoggingLevel(LoggingLevelNotification callback) {
  XACCLogger::instance()->subscribeLoggingLevel(callback);
}

130
void info(const std::string &msg, MessagePredicate predicate) {
131
  if (verbose) XACCLogger::instance()->info(msg, predicate);
132
133
}

134
void warning(const std::string &msg, MessagePredicate predicate) {
135
  if (verbose) XACCLogger::instance()->warning(msg, predicate);
136
137
}

138
void debug(const std::string &msg, MessagePredicate predicate) {
139
140
141
  #ifdef _XACC_DEBUG
  if (verbose) XACCLogger::instance()->debug(msg, predicate);
  #endif
142
143
}

144
void error(const std::string &msg, MessagePredicate predicate) {
145
  print_backtrace();
146
147
148
149
150
151
152
153
  if (isPyApi) {
    throw std::runtime_error(msg);
  } else {
    XACCLogger::instance()->error(msg, predicate);
    XACCLogger::instance()->error("Framework Exiting", predicate);
    xacc::Finalize();
    exit(-1);
  }
154
155
}

156
qbit qalloc(const int n) {
157
  qbit q(n);
158
159
160
161
162
  std::stringstream ss;
  ss << q;
  q->setName(ss.str());
  allocated_buffers.insert({ss.str(), q});
  return q;
163
}
164
165
qbit qalloc() {
  qbit q;
166
167
168
169
  std::stringstream ss;
  ss << q;
  q->setName(ss.str());
  allocated_buffers.insert({ss.str(), q});
170
171
  return q;
}
172

173
174
175
void storeBuffer(std::shared_ptr<AcceleratorBuffer> buffer) {
    auto name = buffer->name();
    if (allocated_buffers.count(name)) {
176
177
178
        // error("Invalid buffer name to store: " + name);
        allocated_buffers[name] = buffer;
    } else {
179
    allocated_buffers.insert({name, buffer});
180
    }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
}

void storeBuffer(const std::string name, std::shared_ptr<AcceleratorBuffer> buffer) {
    if (allocated_buffers.count(name)) {
        error("Invalid buffer name to store: " + name);
    }
    buffer->setName(name);
    allocated_buffers.insert({name, buffer});
}

std::shared_ptr<AcceleratorBuffer> getBuffer(const std::string &name) {
    if (!allocated_buffers.count(name)) {
        error("Invalid buffer name: " + name);
    }
    return allocated_buffers[name];
}
197
bool hasBuffer(const std::string& name) {return allocated_buffers.count(name);}
198

199
200
201
void addCommandLineOption(const std::string &optionName,
                          const std::string &optionDescription) {
  xaccCLParser->addStringOption(optionName, optionDescription);
202
203
}

204
205
206
void addCommandLineOptions(const std::string &category,
                           const std::map<std::string, std::string> &options) {
  xaccCLParser->addStringOptions(category, options);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
207
208
}

209
210
void addCommandLineOptions(const std::map<std::string, std::string> &options) {
  xaccCLParser->addOptions(options);
211
212
}

213
214
bool optionExists(const std::string &optionKey) {
  return RuntimeOptions::instance()->exists(optionKey);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
215
216
}

217
218
219
220
221
const std::string getOption(const std::string &optionKey) {
  if (!optionExists(optionKey)) {
    error("Invalid runtime option - " + optionKey);
  }
  return (*RuntimeOptions::instance())[optionKey];
Mccaskey, Alex's avatar
Mccaskey, Alex committed
222
223
}

224
225
226
227
228
229
void setOption(const std::string &optionKey, const std::string &value) {
  if (optionExists(optionKey)) {
    (*RuntimeOptions::instance())[optionKey] = value;
  } else {
    RuntimeOptions::instance()->insert(std::make_pair(optionKey, value));
  }
Mccaskey, Alex's avatar
Mccaskey, Alex committed
230
}
231
232
233
234
235
void unsetOption(const std::string &optionKey) {
  if (optionExists(optionKey)) {
    (*RuntimeOptions::instance()).erase(optionKey);
  }
  return;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
236
237
}

238
239
void setCompiler(const std::string &compilerName) {
  setOption("compiler", compilerName);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
240
}
241
242
void setAccelerator(const std::string &acceleratorName) {
  setOption("accelerator", acceleratorName);
Mccaskey, Alex's avatar
Mccaskey, Alex committed
243
244
}

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
std::shared_ptr<Accelerator> getAcceleratorDecorator(const std::string& decorator, std::shared_ptr<Accelerator> acc, const HeterogeneousMap& params) {
 std::shared_ptr<AcceleratorDecorator> accd;
  if (xacc::hasService<AcceleratorDecorator>(decorator)) {
    accd = xacc::getService<AcceleratorDecorator>(decorator, false);
  } else if (xacc::hasContributedService<AcceleratorDecorator>(decorator)) {
    accd = xacc::getContributedService<AcceleratorDecorator>(decorator, false);
  }

  if (!accd) {
      xacc::error("Cannot find AcceleratorDecorator with name " + decorator);
  }

  accd->setDecorated(acc);
  accd->initialize(params);
  return accd;
}

262
std::shared_ptr<Accelerator> getAccelerator() {
263
  if (!xacc::xaccFrameworkInitialized) {
264
    error("XACC not initialized before use.\nPlease execute "
265
266
267
          "xacc::Initialize() before using API.");
  }
  if (!optionExists("accelerator")) {
268
269
    error("Invalid use of XACC API.\nxacc::getAccelerator() with no string "
          "argument\n"
270
271
272
          "requires that you set --accelerator at the command line.");
  }

273
  auto name = getOption("accelerator");
Mccaskey, Alex's avatar
Mccaskey, Alex committed
274
  HeterogeneousMap m;
275
  auto name_backend = split(name, ':');
276
277
278
279
280
281
282
283

  std::shared_ptr<Accelerator> acc;
  if (xacc::hasService<Accelerator>(name_backend[0])) {
    acc = xacc::getService<Accelerator>(name_backend[0], false);
  } else if (xacc::hasContributedService<Accelerator>(name_backend[0])) {
    acc = xacc::getContributedService<Accelerator>(name_backend[0], false);
  }

284
  if (name_backend.size() > 1) {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
285
286
    std::string b = name_backend[1];
    m.insert("backend", b);
287
    setOption(name_backend[0] + "-backend", name_backend[1]);
288
289
  }

290
  if (acc) {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
291
    acc->initialize(m);
292
  } else {
293
    error("Invalid Accelerator.\nCould not find " + getOption("accelerator") +
294
295
296
297
          " in Accelerator Registry.");
  }
  return acc;
}
298
std::shared_ptr<Accelerator> getAccelerator(const std::string &name,
299
                                            std::shared_ptr<Client> client,
300
                                            const HeterogeneousMap &params) {
301
  if (!xacc::xaccFrameworkInitialized) {
302
    error("XACC not initialized before use.\nPlease execute "
303
304
          "xacc::Initialize() before using API.");
  }
305
306

  auto name_backend = split(name, ':');
307
308
309
310
311
312
313
314

  std::shared_ptr<Accelerator> acc;
  if (xacc::hasService<Accelerator>(name_backend[0])) {
    acc = xacc::getService<Accelerator>(name_backend[0], false);
  } else if (xacc::hasContributedService<Accelerator>(name_backend[0])) {
    acc = xacc::getContributedService<Accelerator>(name_backend[0], false);
  }

315
  if (name_backend.size() > 1) {
316
    setOption(name_backend[0] + "-backend", name_backend[1]);
317
318
  }

319
320
321
  if (acc) {
    auto remoteacc = std::dynamic_pointer_cast<RemoteAccelerator>(acc);
    if (remoteacc) {
322
      remoteacc->setClient(client);
323
    }
324
    acc->initialize(params);
325
326
327
328
329
330
  } else {
    error("Invalid Accelerator. Could not find " + name +
          " in Accelerator Registry.");
  }
  return acc;
}
331

332
std::shared_ptr<Accelerator> getAccelerator(const std::string &name,
333
                                            const HeterogeneousMap &params) {
334
335
336
337
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
338
  HeterogeneousMap m = params;
339
  auto name_backend = split(name, ':');
340
341
342
343
344
345
346
347

  std::shared_ptr<Accelerator> acc;
  if (xacc::hasService<Accelerator>(name_backend[0])) {
    acc = xacc::getService<Accelerator>(name_backend[0], false);
  } else if (xacc::hasContributedService<Accelerator>(name_backend[0])) {
    acc = xacc::getContributedService<Accelerator>(name_backend[0], false);
  }

348
  if (name_backend.size() > 1) {
349
    std::string b = name_backend[1];
350
    m.insert("backend", b);
351
    setOption(name_backend[0] + "-backend", name_backend[1]);
352
353
  }

354
  if (acc) {
355
    acc->initialize(m);
356
  } else {
357

358
    if (xacc::hasContributedService<Accelerator>(name_backend[0])) {
359

360
      acc = xacc::getContributedService<Accelerator>(name_backend[0]);
361
      if (acc)
362
        acc->initialize(m);
363
364

    } else {
365
      error("Invalid Accelerator. Could not find " + name_backend[0] +
366
367
            " in Accelerator Registry.");
    }
368
369
370
371
372
373
374
375
376
  }
  return acc;
}

bool hasAccelerator(const std::string &name) {
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
377
  return xacc::hasService<Accelerator>(name) || xacc::hasContributedService<Accelerator>(name);
378
379
380
381
382
383
384
}

std::shared_ptr<Compiler> getCompiler(const std::string &name) {
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
385
  auto c = xacc::getService<Compiler>(name, false);
386
  if (!c) {
387
388
    if (xacc::hasContributedService<Compiler>(name)) {
      c = xacc::getContributedService<Compiler>(name);
389
    } else {
390
391
      error("Invalid Compiler. Could not find " + name +
            " in Service Registry.");
392
    }
393
394
  }
  return c;
395
}
396
397

std::shared_ptr<Algorithm> getAlgorithm(const std::string name) {
398
  if (!xacc::xaccFrameworkInitialized) {
399
400
401
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
402
403
404
405
406
407
408
409
410
411
412
413
414

  auto a = xacc::getService<Algorithm>(name, false);

  if (!a) {
    if (xacc::hasContributedService<Algorithm>(name)) {
      a = xacc::getContributedService<Algorithm>(name);

    } else {
      error("Invalid Compiler. Could not find " + name +
            " in Service Registry.");
    }
  }
  return a;
415
416
}

417
std::shared_ptr<Algorithm> getAlgorithm(const std::string name,
418
                                        const xacc::HeterogeneousMap &params) {
419
420
  auto algo = xacc::getAlgorithm(name);
  if (!algo->initialize(params)) {
421
    error("Error initializing " + name + " algorithm.");
422
423
424
  }
  return algo;
}
425
std::shared_ptr<Algorithm> getAlgorithm(const std::string name,
426
                                        const xacc::HeterogeneousMap &&params) {
427
428
  return getAlgorithm(name, params);
}
429

430
431
432
433
434
std::shared_ptr<Optimizer> getOptimizer(const std::string name) {
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
435
436
437
438
439
440
441
442
443
444
445
   std::shared_ptr<Optimizer> t;
  if (xacc::hasService<Optimizer>(name)) {
    t = xacc::getService<Optimizer>(name, false);
  } else if (xacc::hasContributedService<Optimizer>(name)) {
    t = xacc::getContributedService<Optimizer>(name, false);
  }

  if (!t) {
      xacc::error("Invalid Optimizer name, not in service registry - " + name);
  }
  return t;
446
447
}

448
449
std::shared_ptr<Optimizer> getOptimizer(const std::string name,
                                        const HeterogeneousMap &opts) {
450
451
452
453
454
  auto opt = getOptimizer(name);
  opt->setOptions(opts);
  return opt;
}

455
456
std::shared_ptr<Optimizer> getOptimizer(const std::string name,
                                        const HeterogeneousMap &&opts) {
457
458
459
  return getOptimizer(name, opts);
}

460
461
std::shared_ptr<IRProvider> getIRProvider(const std::string &name) {
  if (!xacc::xaccFrameworkInitialized) {
462
463
464
465
466
467
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }

  auto irp = xacc::getService<IRProvider>(name);
  if (!irp) {
468
469
470
471
472
473
    error("Invalid IRProvider. Could not find " + name +
          " in Service Registry.");
  }
  return irp;
}

474
std::shared_ptr<Compiler> getCompiler() {
475
476
477
478
479
480
481
482
483
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
  auto options = RuntimeOptions::instance();
  if (!optionExists("compiler")) {
    error("Invalid use of XACC API. getCompiler() with no string argument "
          "requires that you set --compiler at the command line.");
  }
484
  auto compiler = xacc::getService<Compiler>(getOption("compiler"));
485
486
487
488
489
490
491
492
493
494
495
496
497
  if (!compiler) {
    error("Invalid Compiler. Could not find " + (*options)["compiler"] +
          " in Compiler Registry.");
  }
  return compiler;
}

bool hasCompiler(const std::string &name) {
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }

498
  return xacc::hasService<Compiler>(name);
499
500
501
}

std::shared_ptr<IRTransformation>
502
getIRTransformation(const std::string &name) {
503
504
505
506
  if (!xacc::xaccFrameworkInitialized) {
    error("XACC not initialized before use. Please execute "
          "xacc::Initialize() before using API.");
  }
507

508
  std::shared_ptr<IRTransformation> t;
509
510
511
512
513
  if (xacc::hasService<IRTransformation>(name)) {
    t = xacc::getService<IRTransformation>(name, false);
  } else if (xacc::hasContributedService<IRTransformation>(name)) {
    t = xacc::getContributedService<IRTransformation>(name, false);
  }
514

515
516
517
518
519
520
521
  if (!t) {
    error("Invalid IRTransformation. Could not find " + name +
          " in Service Registry.");
  }

  return t;
}
522

523
524
const std::string translate(std::shared_ptr<CompositeInstruction> ci,
                            const std::string toLanguage) {
525
  auto toLanguageCompiler = getCompiler(toLanguage);
526
  return toLanguageCompiler->translate(ci);
527
528
}

529
void clearOptions() { RuntimeOptions::instance()->clear(); }
530

531
bool hasCache(const std::string fileName, const std::string subdirectory) {
532
  auto rootPathStr = xacc::getRootPathString();
533
  if (!subdirectory.empty()) {
534
535
536
537
    rootPathStr += "/" + subdirectory;
    if (!xacc::directoryExists(rootPathStr)) {
      return false;
    }
538
  }
539
  return xacc::fileExists(rootPathStr + "/" + fileName);
540
}
541

542
HeterogeneousMap getCache(const std::string fileName,
543
                          const std::string subdirectory) {
544
  std::string rootPathStr = xacc::getRootPathString();
545
  if (!subdirectory.empty()) {
546
547
548
549
550
    rootPathStr += "/" + subdirectory;
    if (!xacc::directoryExists(rootPathStr)) {
      error("Tried to get Cache at " + rootPathStr + "/" + fileName +
            ", and it does not exist.");
    }
551
  }
552

553
554
555
556
557
  std::ifstream t(rootPathStr + "/" + fileName);
  std::string json(std::istreambuf_iterator<char>{t}, {});
  std::istringstream s(json);
  auto buffer = std::make_shared<AcceleratorBuffer>();
  buffer->useAsCache();
558

559
560
561
  buffer->load(s);

  auto info = buffer->getInformation();
562
  HeterogeneousMap c;
563
  for (auto &kv : info) {
564
    std::string key = kv.first;
565
    ExtraInfoValue2HeterogeneousMap e2h(c, key);
566
    mpark::visit(e2h, kv.second);
567
  }
568
  std::stringstream ss;
569
570
571
  return c;
}

572
void appendCache(const std::string fileName, HeterogeneousMap &params,
573
                 const std::string subdirectory) {
574
575
576

  // This will over write the ip cache file

577
  auto rootPathStr = xacc::getRootPathString();
578
579

  if (!subdirectory.empty()) {
580
581
582
583
584
    rootPathStr += "/" + subdirectory;
    if (!xacc::directoryExists(rootPathStr)) {
      auto status =
          mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    }
585
  }
586
587
588
589
  std::map<std::string, ExtraInfo> einfo;
  HeterogenousMap2ExtraInfo h2ei(einfo);
  params.visit(h2ei);
  //   InstructionParameter2ExtraInfo ip2e;
590
591
592
  AcceleratorBuffer b;
  b.useAsCache();

593
594
595
  for (auto &kv : einfo) {
    // auto extrainfo = mpark::visit(ip2e, kv.second);
    b.addExtraInfo(kv.first, kv.second);
596
597
598
599
600
601
602
  }

  std::ofstream out(rootPathStr + "/" + fileName);
  std::stringstream s;
  b.print(s);
  out << s.str();
  out.close();
603
}
604
const std::string getRootDirectory() { return xacc::getRootPathString(); }
605

606
607
608
609
610
611
612
613
void appendCompiled(std::shared_ptr<CompositeInstruction> composite,
                    bool _override) {
  if (!_override) {
    if (compilation_database.count(composite->name())) {
      xacc::error("Invalid CompositeInstruction name, already in compilation "
                  "database: " +
                  composite->name() + ".");
    }
614
  }
615
616

  compilation_database[composite->name()] = composite;
617
}
618
bool hasCompiled(const std::string name) {
619
  return compilation_database.count(name);
620
621
}

622
std::shared_ptr<CompositeInstruction> getCompiled(const std::string name) {
623
  if (!compilation_database.count(name)) {
624
625
626
    xacc::error(
        "Invalid CompositeInstruction requested. Not in compilation database " +
        name);
627
628
629
630
631
  }
  return compilation_database[name];
}

void qasm(const std::string &qasmString) {
632
633
634
635
  std::regex rgx(".compiler \\w+"), rgxx(".circuit \\w+"),
      buffrgx(".qbit \\w+");
  std::smatch match, match2, match3;
  std::map<std::string, std::string> function2code;
636
637
638
639
640

  if (!std::regex_search(qasmString.begin(), qasmString.end(), match, rgx)) {
    error("Cannot parse which compiler this qasm corresponds to.");
  }

641
642
  std::vector<std::string> variables;
  std::string bufferName = "b";
643
644
  auto compiler = split(match[0], ' ')[1];
  auto lines = split(qasmString, '\n');
645
  std::string currentFunctionName = "";
646
  for (auto &l : lines) {
647
    xacc::trim(l);
648
    if (l.find(".compiler") == std::string::npos &&
649
650
651
652
653
654
655
656
        l.find(".circuit") == std::string::npos &&
        l.find(".parameters") == std::string::npos &&
        l.find(".qbit") == std::string::npos && !l.empty()) {
      function2code[currentFunctionName] += l + "\n";
    }

    if (l.find(".circuit") != std::string::npos) {
      currentFunctionName = split(l, ' ')[1];
657
    }
658

659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
    if (l.find(".parameters") != std::string::npos) {
      auto tmp = split(l, ' ');
      std::string varLine = tmp[1];
      for (auto i = 2; i < tmp.size(); i++) {
        varLine += tmp[i];
      }

      tmp = split(varLine, ',');
      if (tmp.size() > 1) {
        // we had t0,t1,t2,...
        for (auto &p : tmp) {
          variables.push_back(p);
        }
      } else {
        variables.push_back(tmp[0]);
      }
    }
    if (l.find(".qbit") != std::string::npos) {
      bufferName = split(l, ' ')[1];
    }
  }

  std::string variablesString = "";
  if (!variables.empty()) {
    for (auto &v : variables) {
      variablesString += ", double " + v;
685
    }
686
687
  }

688
  std::vector<std::string> newQasms;
689
  for (auto &kv : function2code) {
690
691
    newQasms.push_back("__qpu__ void " + kv.first + "(qbit " + bufferName +
                       variablesString + ") {\n" + kv.second + "\n}\n");
692
693
694
  }

  std::shared_ptr<IR> ir;
695
696
697
698
699
700
701
702
703
  for (auto &newQasm : newQasms) {
    if (optionExists("accelerator")) {
      ir = getCompiler(compiler)->compile(newQasm, getAccelerator());
    } else {
      ir = getCompiler(compiler)->compile(newQasm);
    }

    auto k = ir->getComposites()[0];
    appendCompiled(k, true);
704
705
  }

706
  for (auto &k : ir->getComposites())
707
    appendCompiled(k, true);
708
}
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
namespace ir {
    std::shared_ptr<CompositeInstruction> asComposite(std::shared_ptr<Instruction> inst) {
        auto comp = std::dynamic_pointer_cast<CompositeInstruction>(inst);
        if(!comp) {
            error("Invalid conversion of Instruction to CompositeInstruction.");
        }
        return comp;
    }
    std::shared_ptr<Instruction> asInstruction(std::shared_ptr<CompositeInstruction> comp) {
        auto inst = std::dynamic_pointer_cast<Instruction>(comp);
        if(!inst) {
            error("Invalid conversion of CompositeInstruction to Instruction.");
        }
        return inst;
    }
}
725

726
727
728
729
730
namespace external {
  void load_external_language_plugins() {
      auto loaders = xacc::getServices<ExternalLanguagePluginLoader>();
      for (auto& loader : loaders) {
          if (!loader->load()) {
731
              xacc::warning("[xacc::external] Warning, could not load " + loader->name() + " external language plugin.");
732
733
734
735
736
737
738
          }
      }
  }
void unload_external_language_plugins() {
      auto loaders = xacc::getServices<ExternalLanguagePluginLoader>();
      for (auto& loader : loaders) {
          if(!loader->unload()) {
739
              xacc::warning("[xacc::external] Warning (maybe an error), could not unload " + loader->name() + " external language plugin.");
740
741
742
743
744
          }
      }
  }
}

745
void Finalize() {
746
  XACCLogger::instance()->dumpQueue();
747
  if (xaccFrameworkInitialized) {
748
749
    // Execute tearDown() for all registered TearDown services.
    auto tearDowns = xacc::getServices<TearDown>();
750
    debug("Tearing down " + std::to_string(tearDowns.size()) + " registered TearDown services..");
751
752
753
754
755
756
757
758
    for (auto& td : tearDowns) {
      try {
        td->tearDown();
      }
      catch (int exception) {
        xacc::error("Error while tearing down a service. Code: " + std::to_string(exception));
      }
    }
759

760
    xacc::xaccFrameworkInitialized = false;
761
762
    compilation_database.clear();
    allocated_buffers.clear();
763
764
    xacc::ServiceAPI_Finalize();
  }
765
}
766

767
} // namespace xacc