* ネスト可能なダブルクォーテーションからはじまる、プリプロセッサ拡張計画
-(by [[K]], 2025.10.06)

** (1)
-私はかつてプリプロセッサが嫌いで、C言語にプリプロセッサがあることはC言語の欠点だと思っていました。プリプロセッサを使わないで済むように、C言語は拡張されるべきだとさえ思っていました。
-でも今は違ってC言語がプリプロセッサとそれ以降の処理フェーズに分かれていることは、むしろうまい仕組みだと思っています。・・・この境地に至るまで10年くらいかかった気がします。

-さて私は以前から、数式のカッコはネスト(=入れ子)が簡単にできるのに、文字列はそうなっていないのは不便だと思ってきました。それで、 [" ~ "] という記法まで考えたのですが、実はまだしっくり来ていませんでした。・・・今回 /" ~ "/ という記法を考えました。これはうまいと思うので、当面はこれでやってみます。
-この「ネスト可能なダブルクォーテーション」があると、プリプロセッサをさらに便利に拡張できる気がするので、しばらくはそれをやってみます。

** (2)
-プリプロセッサの #define は互換性のために維持しますが、追加で #.def というのを作ります。
 #.def Abc(x, y, z), /"myfunc(x*y, x+y, z-x)"/
--このとき、右側にネスト可能なダブルクォーテーションが使われています。
--この #.def は、「ネスト可能なダブルクォーテーション」のおかげで、どこが #.def の終わりなのかが容易にわかります。だからみっともないバックスラッシュ(もしくは円マーク)を多用せずとも、複数行で書くことができます。
--この #.def は、ネスト可能なダブルクォーテーションのおかげで、どこが #.def の終わりなのかが容易にわかります。だからみっともないバックスラッシュ(もしくは円マーク)を多用せずとも、複数行で書くことができます。
 #.def MakeOp2Func(nam, op), /"
   int nam(int x, int y)
   {
       return x op y;
   }
 "/
--この「どこが #.def の終わりなのかわかる」を利用して、1行に複数の #.def を書くことも許します。
 #.def Const1, /"123"/  #.def Const2, /"456"/
-#if 類も拡張形式を追加して、 #.if や #.else などを用意します。
 #.if !defined(Const1), /"#.def Const1, /"123"/ "/
--#.if がどこで終わるのかはすぐにわかるので、 #.endif はありません。
-#.def の中に #.if などを含むことができます。かなり複雑な記述が可能になります。

** (3)
-上記説明を書いているときに、
 #.if !defined(Const1), /"#.def Const1, /"123"/ "/
-が読みやすくないと感じたので、以下の記法も許すことにします。
 #.if !defined(Const1), [/"#.def Const1, [/"123"/]"/]
 #.if !defined(Const1), {/"#.def Const1, [/"123"/]"/}
 #.if !defined(Const1), </"#.def Const1, (/"123"/)"/>
-また、ネストするつもりがない時は、 "..."で代用することも許します。
 #.if !defined(Const1), [/"#.def Const1, "123" "/]


** (4)
-["..."]という記法を思いついた時のメモ: [[a24_idea001]]

-なぜ ["..."] がしっくりこないと思ったのか?
--C言語では配列の添え字に文字列を書くことはないですが、ほかの言語で辞書型などをサポートすれば、これもないとは言えなくなるので、あまり応用が利かないなと思ったのです。
--Pythonでは list = [1, “hello”, 3.14] みたいな書き方も普通にあり得て、["..."]形式は紛らわしいと思いました。

-[[a24_longdef]] では #longdef という
-[[a24_longdef]] では #longdef というプリプロセッサ拡張を考えて実装しましたが、ネスト可能なダブルクォーテーションがあって、 #.def が使えるなら、 #longdef と同等のことはできてしまうので、 #longdef はいらなくなります。

** (5)
-以下はネスト可能なダブルクォーテーションとは無関係ですが、ついでなのでやります。

 #.adddef Abc, "+1" // Abcのdef内容に +1 を書き足します。
 
 #.def Abc, "0"
 #.def IncAbc, /"#.adddef Abc, "+1" "/
 printf("%d ", Abc); IncAbc;
 printf("%d ", Abc); IncAbc;
 printf("%d ", Abc);
 → 「0 1 2 」と表示されます。
--この機能は、 [[a21_txt01_5]] の中に出てきた phrCmp() の pid の管理が面倒だと思って考え出したものです。
--ほかにこんな使い方もできます。

 p0 = malloc(123); #.adddef FreBuf, "free(p0);"
 p1 = malloc(456); #.adddef FreBuf, "free(p1);"
 p2 = malloc(789); #.adddef FreBuf, "free(p2);"
 ...
 ...
 ...
 FreBuf; #.undef FreBuf; // 新しくmallocを追加しても、記述を分散させずに済む。

--#.adddef は #.add とも書けます。

-最後に説明するのは #.final です。これは #.adddef した最後の値を前方参照するときに使います。なお、この用途で使う場合、 #.adddef していく内容に、#系の記述やマクロは含められません。

 #.def Sz "0"
 int a[#.final(Sz)];
 ...
 a[Sz] = 123; #.add Sz, "+1"
 ...
 a[Sz] = 456; #.add Sz, "+1"
 ...
 #.undef Sz;

** (6)
-些末な機能として、#.!(...) があります。これは...の中をsprintfで評価してその結果を返します。

 puts(# #.!("Sz=%d", Sz)); → puts("Sz=2"); になる。

-(以下編集中)

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS