s7
debug 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環境に載せる事を考えているんだろうね。だから、そのまま使うのは、ルール違反な気がする。
others scheme in c++
他にも無かと思って、GitHub へ行って探してみる。検索語は、 Implementing Scheme in C++ ぐらいでいいかな。
この他にも多数見付かった。例題に事かかないなあ。有り難い事です。
s7
たまたま検索してて見付けたもの。
こういう先人がおられた。単独では、みつからなかっただろう。
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に説明があるのだろうか。