# 例: 整数式の評価

```datatype IEXP =
| IEXPcst of int // constants
| IEXPneg of (IEXP) // negative
| IEXPsub of (IEXP, IEXP) // subtraction
| IEXPmul of (IEXP, IEXP) // multiplication
| IEXPdiv of (IEXP, IEXP) // division
// end of [IEXP]
```

IEXP に関連するコンストラクタの意味は明確です。 IEXP 型の値はしばしば抽象構文木と呼ばれます。 例えば、式 (~1+(2-3)*4) の抽象構文木は次のようになります:

```IEXPadd(IEXPneg(IEXPcst(1)), IEXPmul(IEXPsub(IEXPcst(2), IEXPcst(3)), IEXPcst(4)))
```

```fun
eval_iexp
(e0: IEXP): int =
(
case+ e0 of
| IEXPcst (n) => n
| IEXPneg (e) => ~eval_iexp (e)
| IEXPadd (e1, e2) => eval_iexp (e1) + eval_iexp (e2)
| IEXPsub (e1, e2) => eval_iexp (e1) - eval_iexp (e2)
| IEXPmul (e1, e2) => eval_iexp (e1) * eval_iexp (e2)
| IEXPdiv (e1, e2) => eval_iexp (e1) / eval_iexp (e1)
) (* end of [eval_iexp] *)
```

```datatype IEXP =
| IEXPcst of int // integer constants
| IEXPneg of (IEXP) // negative
| IEXPsub of (IEXP, IEXP) // subtraction
| IEXPmul of (IEXP, IEXP) // multiplication
| IEXPdiv of (IEXP, IEXP) // division
| IEXPif of (BEXP(*test*), IEXP(*then*), IEXP(*else*))
// end of [IEXP]

and BEXP = // [and] for combining datatype declarations
| BEXPcst of bool // boolean constants
| BEXPneg of BEXP // negation
| BEXPconj of (BEXP, BEXP) // conjunction
| BEXPdisj of (BEXP, BEXP) // disjunction
| BEXPeq of (IEXP, IEXP) // equal-to
| BEXPneq of (IEXP, IEXP) // not-equal-to
| BEXPlt of (IEXP, IEXP) // less-than
| BEXPlte of (IEXP, IEXP) // less-than-equal-to
| BEXPgt of (IEXP, IEXP) // greater-than
| BEXPgte of (IEXP, IEXP) // greater-than-equal-to
// end of [BEXP]
```

```fun
eval_iexp
(
e0: IEXP
) : int = (
//
case+ e0 of
| IEXPcst n => n
| IEXPneg (e) => ~eval_iexp (e)
| IEXPadd (e1, e2) => eval_iexp (e1) + eval_iexp (e2)
| IEXPsub (e1, e2) => eval_iexp (e1) - eval_iexp (e2)
| IEXPmul (e1, e2) => eval_iexp (e1) * eval_iexp (e2)
| IEXPdiv (e1, e2) => eval_iexp (e1) / eval_iexp (e1)
| IEXPif
(
e_test, e_then, e_else
) =>
(
eval_iexp (if eval_bexp (e_test) then e_then else e_else)
) // end of [IEXPif]
//
) (* end of [eval_iexp] *)

and
eval_bexp
(
e0: BEXP
) : bool = (
//
case+ e0 of
| BEXPcst b => b
| BEXPneg (e) => ~eval_bexp (e)
| BEXPconj (e1, e2) =>
if eval_bexp (e1) then eval_bexp (e2) else false
| BEXPdisj (e1, e2) =>
if eval_bexp (e1) then true else eval_bexp (e2)
| BEXPeq (e1, e2) => eval_iexp (e1) = eval_iexp (e2)
| BEXPneq (e1, e2) => eval_iexp (e1) != eval_iexp (e2)
| BEXPlt (e1, e2) => eval_iexp (e1) < eval_iexp (e2)
| BEXPlte (e1, e2) => eval_iexp (e1) <= eval_iexp (e2)
| BEXPgt (e1, e2) => eval_iexp (e1) > eval_iexp (e2)
| BEXPgte (e1, e2) => eval_iexp (e1) >= eval_iexp (e2)
//
) (* end of [eval_bexp] *)
```

この例における整数式とブール式は全て変数を含まない定数式です。 そのため、これらの式の評価に環境は必要ありませんでした。 ATS のコアのような簡単な値渡し (call-by-value) の関数型プログラミング言語の評価器をどのように実装するのか示すために、より進んだ例を別の章で紹介します。

この章のコード全体と追加のテストコードは オンライン から入手できます。 (訳注: このコードを atscc でコンパイルする際には -DATS_MEMALLOC_LIBC オプションが必要です。)