butterfly dream

FX自動取引のための時系列分析・信号処理・戦略ブログ

科学技術計算用プログラミング言語:Sci-Lispの自作(9日目):C++によるクラスと出力の定義(基本型)

chaploud-blog.hatenablog.com

Sci-Lisp自作の9日目です。C++を勉強しつつSci-Lispの基本型の実装をしました。以下にコード例を載せます。

#include <cmath>
#include <iostream>
#include <limits>
#include <regex>
#include <string>
#include <iomanip>

#define STR "str"
#define REGEX "regex"
#define BOOL "bool"
#define NIL "nil"
#define I64 "i64"
#define F64 "f64"
#define SYM "sym"

// base class
template <typename T>
class Object {
 public:
  friend std::ostream& operator<<(std::ostream& os, const Object& v) { return os << v.display(); }
  friend std::string type(const Object& v) { return v.m_type; }

 protected:
  T m_value;
  std::string m_type;
  virtual std::string display() const { return "object"; }
  std::string type() const { return m_type; }
};

// str
class str : public Object<std::string> {
 public:
  str(const char* value) {
    m_value = std::string(value);
    m_type = STR;
  }
  str& operator=(const str& x) {
    m_value = x.m_value;
    return *this;
  }
  str& operator=(const std::string& x) {
    m_value = x;
    return *this;
  }
 private:
   std::string display() const override {
    return "\"" + m_value + "\"";
   }
};

// regex
class regex : public Object<std::regex> {
 public:
  regex(const char* value) {
    m_string = std::string(value);
    m_value = std::regex(m_string);
    m_type = REGEX;
  }
 private:
  std::string m_string;
  std::string display() const override {
    return "regex(\"" + m_string + "\")";
  }
};

// bool
// needs call function init() to display bool

// nil
struct nil_t {}; // TODO: compare

class nil : public Object<nil_t> {
 public:
  nil() {
    m_value = {};
    m_type = NIL;
  }
 private:
  std::string display() const override {
    return "nil";
  }
};

// i64
using i64 = long long;

// f64
using f64 = double;

// symbol
struct sym_t {};

// sym
class sym : public Object<sym_t> {
 public:
  sym(const char* value) {
    m_string = std::string(value);
    m_value = {}; // TODO: compare
    m_type = SYM;
  }
 private:
  std::string m_string;
  std::string display() const override {
    return m_string;
  }
};

template <class T>
std::string type(const Object<T>& obj) {
  return obj.type();
}

// for bool
std::string type(bool obj) {
  return BOOL;
}
// for i64
std::string type(i64 obj) {
  return I64;
}
// for f64
std::string type(f64 obj) {
  return F64;
}

// nan
const f64 NaN = std::numeric_limits<f64>::quiet_NaN();
// inf
const f64 inf = std::numeric_limits<f64>::infinity();
// -inf
const f64 ninf = -inf;

void init(void) {
  std::cout << std::boolalpha;
  std::cout << std::scientific << std::setprecision(5);
}

int main(void) {
  init();

  str s = "hoge";
  std::cout << s << " " << type(s) << std::endl;

  regex re = R"([0-9]+\.\d*)";
  std::cout << re << " " << type(re) << std::endl;

  bool tr = true;
  bool fa = false;
  std::cout << tr << " " << fa << " " << type(tr) << std::endl;

  nil ni;
  std::cout << ni << " " << type(ni) << std::endl;

  i64 i = -999;
  std::cout << i << " " << type(i) << std::endl;

  f64 f = -3.141592;
  std::cout << f << " " << type(f) << std::endl;

  f64 fe = -3.14e15;
  std::cout << fe << " " << type(fe) << std::endl;

  f64 na = NaN;
  f64 posinf = inf;
  f64 neginf = ninf;
  std::cout << na << " ";
  std::cout << posinf << " ";
  std::cout << neginf << std::endl;

  sym sy = sym(":hoge");
  std::cout << sy << " " << type(sy) << std::endl;

  return 0;
}

この出力は以下のようになりました。

"hoge" str
regex("[0-9]+\.\d*") regex
true false bool
nil nil
-999 i64
-3.14159e+00 f64
-3.14000e+15 f64
nan inf -inf
:hoge sym

終わりに

次回はコレクションクラスの実装に進めればと思います。