Skip to content
Snippets Groups Projects
  • Sam Yates's avatar
    Add linear kinetic schemes to modcc. (#145) · 5846f90b
    Sam Yates authored
    Incorporate symbolic GE code from prototype (with some simplifications) in msparse.hpp, symge.hpp and symge.cpp, together with unit tests.
    
    Add two kinetic scheme test cases for validation: test_kin1 (simple exponential scheme) and test_kinlva (combination of exponential gate and a three-species kinetic scheme, modelling a low voltage-activated Calcium channel from Wang, X. J. et al., J. Neurophys. 1991).
    
    Adapt numeric HH validation data generation to LVA Ca channel, with explicit stopping at stimulus discontinuities.
    
    Add two new validation tests based on above: kinetic.kin1_numeric_ref and kinetic.kinlva_numeric_ref (multicore backend only).
    
    Introduce a BlockRewriterBase visitor base class, as an aid for visitors that transform/rewrite procedure bodies; refactor KineticRewriter over this class.
    
    Introduce common error_stack mixin class for common functionality across Module and the various procedure rewriters.
    
    Implement visitors and public-facin...
    5846f90b
error.hpp 1.91 KiB
#pragma once

#include <deque>
#include <iterator>
#include <stdexcept>
#include <string>

#include "location.hpp"

struct error_entry {
    std::string message;
    Location location;

    error_entry(std::string m): message(std::move(m)) {}
    error_entry(std::string m, Location l): message(std::move(m)), location(l) {}
};

// Mixin class for managing a stack of error info.

class error_stack {
private:
    std::deque<error_entry> errors_;
    std::deque<error_entry> warnings_;

public:
    bool has_error() const { return !errors_.empty(); }
    void error(error_entry info) { errors_.push_back(std::move(info)); }
    void clear_errors() { errors_.clear(); }

    std::deque<error_entry>& errors() { return errors_; }
    const std::deque<error_entry>& errors() const { return errors_; }

    template <typename Seq>
    void append_errors(const Seq& seq) {
        errors_.insert(errors_.end(), std::begin(seq), std::end(seq));
    }

    bool has_warning() const { return !warnings_.empty(); }
    void warning(error_entry info) { warnings_.push_back(std::move(info)); }
    void clear_warnings() { warnings_.clear(); }

    std::deque<error_entry>& warnings() { return warnings_; }
    const std::deque<error_entry>& warnings() const { return warnings_; }

    template <typename Seq>
    void append_warnings(const Seq& seq) {
        warnings_.insert(warnings_.end(), std::begin(seq), std::end(seq));
    }
};

// Wrap error entry in exception.

class compiler_exception : public std::exception {
public:
    explicit compiler_exception(error_entry info)
    :   error_info_(std::move(info))
    {}

    compiler_exception(std::string m, Location location)
    :   error_info_({std::move(m), location})
    {}

    virtual const char* what() const throw() {
        return error_info_.message.c_str();
    }

    Location const& location() const {
        return error_info_.location;
    }
private:
    error_entry error_info_;
};