徒然なる日々を送るソフトウェアデベロッパーの記録(2)

技術上思ったことや感じたことを気ままに記録していくブログです。さくらから移設しました。

minosys script を作ろう (7)

左辺値と右辺値の違い

前回、左辺値は変数を指し、右辺値は値を指すと言いました。
左辺値は変数を代入するための情報なので、最終的には変数のアドレス
にブレイクダウンされます。

つまり、実行エンジンの観点で見ると(仮に変数のクラスを Var
として)右辺値は Var (あるいは Var &) であるのに対し、左辺値は
Var ** を提供する必要があります。

func()[0] = ...;

のような表現が(実行エンジンの実装上)許可されない理由は
関数の戻り値は右辺値であり、(値が同じだとしても)変数のアドレス
は異なってしまうことがあるためです。
(実際、関数の戻り値はパラメータスタックトップにコピーされます。)

配列の場合はどうでしょうか。
変数が配列の場合、その表現は

class Var {
 std::vector<Var *> array
 ...
};

のようになっていると考えられるので、

$a[2] = ...;

という式の場合、変数 &a->array[2] を左辺値として積めば
正しいアドレスにたどり着けそうです。

もう少し複雑な例

$i.$a[1] = ...;

の場合でも、最初に $i.$a を計算して Var * を求め(仮に r とします)、
次に変数 &r->array を左辺値として積めばいいことなります。

左辺値を要求する演算子

左辺値を要求する演算子は代入系の演算子です。
具体的には、

=, +=, -=, *=, /=, %=, <<=, >>=
++, --

となります。これらの実行エンジンの実装では第1引数は左辺値となり、
Var ** を返します。

次回からは実行エンジンの実装に入りますが、その前に実行エンジンで
使用するデータ表現とメモリ管理について説明します。