一般」カテゴリーアーカイブ

CodeTyphon 6.70 がリリースされました。

CodeTyphon 6.70 が出ました。
http://www.pilotlogic.com/sitejoom/
Free Pascal 3.3.1 ベースです。

ダウンロードはこちらです。
http://www.pilotlogic.com/sitejoom/index.php/downloads/category/14-codetyphon

インストール手順などは CodeTyphon 6.50 と同じです。[CodeTyphon Studioの設定]

旧 CodeTyphon がインストールされている場合、新しいインストールのメニューで「1) Update CodeTyphon Studio」ではなく「0) Install CodeTyphon Studio (remove old first」を選択するのが無難です。

XDS Modula-2 2.51 インストール時の注意事項

ADW Mudula-2 がしばらく待たされそうなので、XDS Modula-2 をインストールする場合、以下の点に注意して下さい。Windows版の話です。
Version 2.51 のインストールの途中で以下の画面が現れます。「Personal」がログインユーザのみで「Common」が全ユーザというお決まりの選択です。ここで「Common」を選択すると、システムのPATHの設定が「C:\XDS\BIN」で上書きされ、「C:\XDS\BIN」だけになってしまいます。ユーザのPATH設定は変りませんが、これまでのシステムのPATHが丸ごと消えることになるので、ここでは「Personal」を選んで下さい。その場合は、ユーザの環境変数の末尾に「C:\XDS\BIN」が追加され、既存の設定は消えません。
「Common」にしたい場合は、事前にシステムの環境変数の設定値をテキストファイルなどに保存しておいて事後にそれから設定を復元して下さい。

万が一、システムの環境変数を書き換えられて事前の保存もしていなかった場合は、[システムのプロパティ]-[システムの保護]の[システムの復元]で、直近の復元ポイントに戻すとPATHもその時点に復元されます。ただし、復元ポイント以降のインストールや設定は無効になります。

また、XDS Modula-2 2.6 Beta の場合は上記の画面は出ません。インストールすると「C:\XDS\bin;」がシステムの環境変数の先頭に挿入されます。既存の設定が消されることはありません。

でも、環境変数の状態は何かインストールする場合の前後で保存しておくのが賢明です。

 

問い1(続々々)

【なぜ「Pascal 日和」でC言語の話か?】

実はC言語がどうこうというのはどうでも良い話で、Modula-2 R10 の仕様が気になったからです。
C言語は、副作用の問題を抱えながら長年使用され続け、定着しているのでどうこう言うつもりはありません。

現在進んでいる Modula-2 R10 の「Modula-2 R10 Language Report」を見ると、これまでのModula-2に無かった‘++’‘–‘が追加されていました。
もし「問い1(続々)」の話の様なことが突然Modula-2にも起こったら皆さん困ると思います。

しかし、「Modula-2 R10 Language Report」の記載を見ると
‘++’は Increment Statement Suffix
‘–‘は Decrement Statement Suffix
となっています。

Operator(演算子)ではなくStatement(文)となっているので、C言語とは違う扱いで実装されるようです。
X++;INC(X, 1); と同じ。
X–;DEC(X, 1); し同じ。

これらは文なので値として評価できないので、Y := X++;A[X++] := Y;IF X++ = Y THEH… などはできません。

つまり、Modula-2 R10 では、「問い1(続々)」の様なことは起こらないということになります。
まずまず一安心というところです。

ちなみに

Free Pascal(Lazarus)ではどうかというと、代入文(Assignment Statement)として、‘+=’‘-=’‘*=’‘/=’が実装されていますが、Pascalではこれらは代入式ではなく代入文なので、これについても問題ありません。
X += Y;X := X + Y; と同じ。
X -= Y;X := X – Y; と同じ。
X += Y;X := X * Y; と同じ。
X /= Y;X := X / Y; と同じ。’div’ではなく’/’なので、実数演算に限定されます。
Inc()Dec()手続きがあるので、‘++’‘–‘は実装していないようです。‘+=’‘-=’もいらないと思いますが。

ということで、Free Pascalも大丈夫そうです。

.NETのObject Pascalである、RemObject社のOxygeneはイベントの割当てと解除のための‘+=’‘-=’はありますが、数値の演算に‘++’、’–‘‘+=’‘-=’‘*=’‘/=’はありません。
こちらも大丈夫そうです。

Modula-2やPascal系のコンパイラは、C言語ライクな表現を取り入れる場合も、副作用の問題などは取り込まない様になっているようですね。

以上

 

問い1(続々)

【解説】(少しだけ)

間違っている部分もあると思いますので、参考程度に見て下さい。

回答例で「不定」とした部分は、実際には「未定義」という扱いとなり、極端な解釈をすれば全く想定外の結果となり、【C】【F】【G】【I】も含め全て未定義となり全体が木っ端みじんみたいなこともあり得るのかもしれません。
現実的には未定義に対してそこまで暴れまくる実装をしているコンパイラは無いと思うので、それぞれのコンパイラがそれぞれのルールを決めて実装していると考えます。

今回の問題点は、式内で、副作用がある変数に複数回参照している点です。
副作用とは、式の中で演算をしたときに、演算とは別に変数に対して作用を及ぼすことです。
たとえば、次の式があったとき、(これは副作用がある変数(x)に複数回参照していないケース)

 /* x は 0 で初期化済 */
 y = x++;

普通は「yにxの今の値を代入し、xをインクリメントする」という説明になります。

これを演算と副作用に分解します。
使用されている演算子は代入演算の’=’と後置インクリメントの演算’++’の2つです。各演算子の優先度は ‘++’ > ‘=’ です。
演算は優先順位と結合性(左から/右から)に従って評価されます。
【演算】評価順序は①→②→③
①: ‘x++’ を評価して演算前の x の値を返す。つまり 0。
②: ‘y = 0’ を評価して、第1演算項 y に代入されるべき値(つまり第2演算項の値)を返す。つまり 0。
③: ‘0’ という評価値になったが、誰も拾わないので結果は捨てられる。もし、z = y = x++ ならばさらに z = 0 が評価される。
【副作用】A,Bの適用順は未定義
A: x の値を1つ増やす。
B: y の値を 0 にする。

ここで、演算には優先度と結合性がありますが、副作用については式の評価の始まりから、副作用完了点まで間に行えばよいというだけです。
この場合の副作用完了点は終端記号(;)のところになります。
つまり、「*①*②*③*」の任意の場所(*)でAとBは実行されます。この副作用の実行場所がコンパイラによって違う可能性があるわけです。
この式の場合は、xに対して副作用が1回のみしかし要されていないので、どのコンパイラでも結果は同じ(x == 1, y == 0)ということになりそうですが?
しかし、もし、「AB①②③」というように最初に副作用を実行したら y は 1 になるのではないかとふと思いました。単純にそのままの実装なら本当にそうなるかもしれません(???)。

演算項の評価に先立ち全ての副作用を最初に適用するという実装はちょっと除外して話を進めます(複雑になりすぎるので)。

次は、副作用がある変数(x)に複数回参照しているケース。

 /* x は 0 で初期化済、a[]は{9,9}で初期化済 */
 a[x] = x++;

演算子は、配列添え字の'[]’と代入演算の’=’と後置インクリメント演算の’++’。各演算子の優先度は ‘[]’ > ‘++’ > ‘=’ です。
【演算】評価順序は①→②→③→④
①: a[x]を評価して配列 a の場所を特定します。場所は x の値で特定されます。x の値は副作用の実行場所により 0 または 1 となる。評価結果が2つに分かれてしまう。
②: ‘x++’ を評価して演算前の x の値を返す。つまり 0
③: ‘a[0または1] = 0’ を評価して第1演算項 y に代入されるべき値(つまり第2演算項の値)を返す。
④: ‘0’ という評価値になったが、誰も拾わないので結果は捨てられる。もし、z = a[x] = x++ ならばさらに z = 0 が評価される。
【副作用】A,Bの適用順は未定義
A: x の値を1つ増やす。
B: a[0または1] の値を 0 にする。

ということになります。

その他の式も「演算」(値の評価)と「副作用」(変数・オブジェクトの変更)と分けて考え、各幅作用がどこで適用されるかでどう変るかを検証してみて下さい。

一番安全なのは、++, — は単独の式(x++;や–y;など)で使用するのが良いと思います。

「C言語 副作用」や「C言語 副作用完了点」で検索するといろいろ説明しているページが出てきます。

【式と手続き】

プログラムの実行部分は、「式」、「手続き」、「制御文」などありますが、C言語とPascalでは違いがありますね。

C言語の、y = x; は式(代入演算)で、この式自体が値を持ちます。z = y = x; は可。
Pascal言語の Y := X; は代入文で、この文自体は値を持ちません。z := y := x; は不可。

また、変数のインクリメントやデクリメントもC言語では演算子でPascal言語では手続きです。

C言語の x++; はxをインクリメントするだけではなく、これ自体が演算項になり得る。y = x++; は可。
Pascal言語の Inc(X); はXをインクリメントするだけの手続きで、これ自体が演算項にはなり得ない。Y := Inc(X); は不可。

Pascal言語の代入やインクリメントは、「演算と副作用」が発生するのではなく、単純に「作用」を及ぼすものと言えます。

続きは改めて...