s7

debug c++

Cフラフラの詳しい入門を一読したんだけど、お腹いっぱいと言う感じがしたので、別の入門書にもあたってみる。色々な角度からの切込みって大事と思うよ。

C++ 入門

C++入門 基礎知識は仮定しません

前回のスキームもどきを題材に実地で追跡。 sol-prog / schm

old-version

最初にググルして、これを見付けたのよ。 Implementing Scheme in C++ - Introduction

ob$ ls old_version/
Environment.h   Procedures.h    schm.cpp
PList.h         README          utils.h

こんな構成。ここに全てが凝縮されている。中でも一番高密度な部分は、Environment.h

class   Object {
    string          (*pp) (vector < string > &);
    string          (*rr) ();
    string          value;
    string          kind;

    public:
    Object    () { };
    Object(string ss) {
        value = ss;
        kind = "variable";
        pp = NULL;
    };
    Object(string(*p_) (vector < string > &)) {
        pp = p_;
        kind = "procedure";
        value = "";
    };
    string          get_kind() {
        return kind;
    }
    :
};
typedef         map <   string, Object > Environment;

構成確認

こんな構成になってる(見やすいように、一部を整理してる)。

ob$ ls
Cell.cpp        Object.h        Procedure.h     schm*
Cell.h          PList.cpp       Procedures.cpp  schm.cpp
Makefile        PList.h         Procedures.h    utils.cpp
Object.cpp      Procedure.cpp   README          utils.h

xxx.h と xxx.cpp が、ペアになってる。これって、 C++言語によるプログラミング入門6 クラスを作ろう(補足)で、説明されてる奴の実践だな。 この事を理解出来たのは、大きな収穫だな。

PList.h, PList.cpp に PList::PList() が定義されてる。不要? コメントにしてコンパイルすると、

PList.cpp: In member function ‘PList PList::get(size_t)’:
PList.cpp:81:11: error: no matching function for call to ‘PList::PList()’
   81 |     PList pp;
      |           ^~

こういう所でエラーになった。他にも関連が盛大にエラー。変数宣言で、空のコンストラクターが使われているのね。既定のコンストラクターは必ず定義しておけとな。

この近辺にthisなんて言う英単語が出て来る。

*thisはメンバー関数を呼んだクラスのオブジェクトへのリファレンスだ
メンバー関数の中で、メンバー関数が呼ばれているクラスのオブジェクトを参照する方法が*thisだ

との事だ。

gdb or lldb

余りCフラフラ語をデバッガーにかけている所を見た事が無いので、やってみる。特にC++に特化した所ね。Cフラフラを扱かう人って、デバッガーのお世話になんてならない人ばかりなのかな。

[sakae@fb /tmp/schm]$ lldb schm
(lldb) target create "schm"
Current executable set to '/tmp/schm/schm' (i386).
(lldb) b Object::Object
Breakpoint 1: 5 locations.
(lldb) break list
Current breakpoints:
1: name = 'Object::Object', locations = 5
  1.1: where = schm`Object::Object(Procedure&) + 17 at Object.cpp:34:9, address = schm[0x00413bd1], unresolved, hit count = 0
  1.2: where = schm`Object::Object(Object const&) + 18 at Object.h:3:7, address = schm[0x0041bfc2], unresolved, hit count = 0
  1.3: where = schm`Object::Object(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > (*)(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)) + 17 at Object.cpp:26:9, address = schm[0x00413b01], unresolved, hit count = 0
  1.4: where = schm`Object::Object() + 12 at Object.cpp:14:9, address = schm[0x004139ec], unresolved, hit count = 0
  1.5: where = schm`Object::Object(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 17 at Object.cpp:18:9, address = schm[0x00413a31], unresolved, hit count = 0

メソッドにBPを置く時は、言うまでもなく、クラス名も指定する事。同名な奴があると、複数のBPが設定される。

(lldb) r
Process 10273 launching
Process 10273 launched: '/tmp/schm/schm' (i386)
Process 10273 stopped
 * thread #1, name = 'schm', stop reason = breakpoint 1.3
    frame #0: 0x00413b01 schm`Object::Object(this=0xffbfebc4, p_=(schm`add(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&) at Procedures.cpp:24))(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)) at Object.cpp:26:9
   23   }
   24
   25   //Store a pointer to a C++ function (this can be accessed from Scheme)
-> 26   Object::Object(string(*p_)(vector<string>&)) {
   27       pp = p_;
   28       kind = "procedure";
   29       value = "";
(lldb) bt
 * thread #1, name = 'schm', stop reason = breakpoint 1.3
  * frame #0: 0x00413b01 schm`Object::Object(this=0xffbfebc4, p_=(schm`add(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&) at Procedures.cpp:24))(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)) at Object.cpp:26:9
    frame #1: 0x00417a7f schm`main at schm.cpp:239:16
    frame #2: 0x0040aa66 schm`_start1(cleanup=0x2042eb80, argc=1, argv=0xffbfec64) at crt1_c.c:72:7
    frame #3: 0x0040abc0 schm`_start at crt1_s.S:46

ウーーン マンダム じゃなくて、lldb 醜いな。何とかならんかと gdb.

[sakae@fb /tmp/schm]$ gdb -q schm
Reading symbols from schm...
(gdb) b Object::Object
Breakpoint 1 at 0x4139ec: Object::Object. (5 locations)
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   <MULTIPLE>
1.1                         y   0x004139ec in Object::Object() at Object.cpp:14
1.2                         y   0x00413a31 in Object::Object(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
                                           at Object.cpp:18
1.3                         y   0x00413b01 in Object::Object(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > (*)(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)) at Object.cpp:26
1.4                         y   0x00413bd1 in Object::Object(Procedure&)
                                           at Object.cpp:34
1.5                         y   0x0041bfc2 in Object::Object(Object const&)
                                           at ./Object.h:3

横長のモニターで、首を左右に振れってか。

(gdb) r
Starting program: /tmp/schm/schm

Breakpoint 1, Object::Object (this=0xffbfeba4, p_=0x40f780 <add(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)>) at Object.cpp:26
26      Object::Object(string(*p_)(vector<string>&)) {
(gdb) bt
#0  Object::Object (this=0xffbfeba4,
    p_=0x40f780 <add(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)>)
    at Object.cpp:26
#1  0x00417a7f in main () at schm.cpp:239

こちらは、まあまあか。美人は3日で飽きるけどブスは3日で慣れるって言うなあ。美醜は気にするな。

lldbな奴はpythonでお化粧してGUI環境に載せる事を考えているんだろうね。だから、そのまま使うのは、ルール違反な気がする。

お気楽C++プログラミング超入門

others scheme in c++

他にも無かと思って、GitHub へ行って探してみる。検索語は、 Implementing Scheme in C++ ぐらいでいいかな。

arichel / PicoScheme

loong / scheme-interpreter

Br1an6 / Scheme-Interpreter

davedoesdev / mce (many lang)

cwbriones / bootstrap-scheme

この他にも多数見付かった。例題に事かかないなあ。有り難い事です。

s7

たまたま検索してて見付けたもの。

C++にScheme処理系を楽して組み込みたい

こういう先人がおられた。単独では、みつからなかっただろう。

sakae@pen:/tmp/s7$ time gcc s7.c -o repl -DWITH_MAIN -I. -O2 -g -ldl -lm -Wl,-export-dynamic

real    1m9.511s
user    1m7.988s
sys     0m1.499s

随分時間がかかるな。まあ、巨大ですからね(10万行ぐらい)。

sakae@pen:/tmp/s7$ ./repl
s7: 27-Dec-2021
load /tmp/s7/libc_s7.so failed: /tmp/s7/libc_s7.so: cannot open shared object file: No such file or directory
writing libc_s7.c
loading libc_s7.so
<1>
sakae@pen:/tmp/s7$ ./repl
s7: 27-Dec-2021
<1>

遅いOpenBSDでも、やってみる。

vbox$ time cc s7.c -o repl -DWITH_MAIN -I. -O2 -g -lm -Wl,-export-dynamic
    3m14.01s real     2m55.93s user     0m16.70s system

起動するとエラーが出て来た。取り敢えず、 WITH_GCC 0 にして再コンパイルしたよ。

#if (defined(__GNUC__) || defined(__clang__)) /* s7 uses PRId64 so (for example) g++ 4.4 is too old */
  #define WITH_GCC 1
#else
  #define WITH_GCC 0
#endif

やっぱり、リナの方向しか向いていないのかな。組み込みを歌っているなら、それはまずいだろう。 ちゃんとconfigの機構が用意されているのだろうね。オイラーが見落しているだけ? 付属のs7.htmlに説明があるのだろうか。

go module

rust