2007年 10月 21日

Io における演算子拡張

Io は演算子の Map を内部に持っていて、パース時にそれを参照する。

例えば =~ は定義されていないので

Message fromString("\"abc\" =~ \"a.\"") code print
#=> "abc" =~ "a."

となり、これだと =~ というメッセージを定義しても、後ろの文字列 (Sequence) は =~ メッセージの引数とは解釈されない。"abc" =~ と "a." は別の文になるわけです。

しかしながらこれは拡張することができて

OperatorTable addOperator("=~", 7)
Message fromString("\"abc\" =~ \"a.\"") code print
#=> "abc" =~("a.")

ということができる。7 は演算子の優先順で、OperatorTable print すれば登録済みの演算子とその優先順位がわかる。

Operators
  0   ' ( ) . ? @ @@
  1   **
  2   ++ --
  3   % * /
  4   + -
  5   << >>
  6   < <= > >=
  7   != ==
  8   &
  9   ^
  10  |
  11  && and
  12  or ||
  13  ..
  14  %= &= *= += -= -> /= <- <-> <<= >>= ^= |=
  15  return
  16  ,

Assign Operators
  ::= newSlot
  :=  setSlot
  =   updateSlot

To add a new operator: OperatorTable addOperator("+", 4) and implement the + message.
To add a new assign operator: OperatorTable addAssignOperator("=", "updateSlot") and implement the updateSlot message.

ところで若干のハマりどころなのは、

Object =~ := method(s,
	call message print
)
OperatorTable addOperator("=~", 7)

"abc" =~ "a."

とやっても、"abc" =~ "a." をパースする時点では addOperator はまだ評価されていないので、演算子にはならない。doString とかでこのあとにパースされるようにしないといけない。実際つかうとするとファイルをわけて doFile みたいになると思う。

Io かっけー