toge's diary

コンピュータ関連の趣味をつらつらと。

ExprEvalの導入 -定数・変数の値を取得する-

書くための検証コード書いたり、ベンチマークとったりして、貴重な平日の時間をどんどん無駄にしてるな。
まあ自分が使う情報だしいいか。

前回は定数・変数の値を変更しましたが、次は定数・変数の値を取得します。
もちろん、式を評価してもいいのですが、それ以外の方法もありますんで。
やり方はとても簡単。exprValListGet()関数を呼び出すだけです。

EXPRTYPE testVar;
exprValListGet(v, "testVar", &testVar); 

いつもどおり、今回のコードを置いておきます。
http://toge.skr.jp/program/expreval/sample05.c

もちろん定数の値も同じように取得出来ますが、多分そんな意味のないことはしないと思うのでここでは書きません。
これで式を評価した後に、式の値以外にも、変数の値を取得出来るようになります。

// 式のパーズ
exprParse(e, "angle = 30; radius = 50; x = radius * sin(angle); y = radius * cos(angle);");

// パーズした式の評価
EXPRTYPE val;
exprEval(e, &val);

EXPRTYPE x, y;
exprValListGet(v, "x", &x);
exprValListGet(v, "y", &y); 

こんな風にすれば、x, y座標の値を取り出すことが出来るというわけです。
それなら式の値なんていらないのでexprEval()の第2引数をNULLにしたいと思うのですが、exprEval()の実装は以下のようにそれを許してくれません。ちょっと不親切ですね。

int exprEval(exprObj *o, EXPRTYPE *val)
{
  if(o == NULL)
    return EXPR_ERROR_NULLPOINTER;

  if(val ==  NULL)
    return EXPR_ERROR_NULLPOINTER; 

もし今までに生成されていない変数の値を取得しようとした場合には、第3引数で示したEXPRTYPE型の変数は操作されず、exprValListGet()関数はEXPR_ERROR_NOTFOUNDを返します。

式評価とのベンチマークをとってみました。コンパイルしたコードは以下の通り。
http://toge.skr.jp/program/expreval/sample06.c

> gcc-4.0.2 -I.. -lm -O3 -march=athlon-xp sample06.c ../*.c
> ./a.out
exprValListGet span 2.710000
exprEval       span 4.410000 

値の取得は専用関数を使った方が速いですね。良かった。