caseとlet*

case syntaxとlet* syntaxに対応した。
パーサにparseLetstarとparseCaseを追加した。
対話環境でテストしてみる。

# let e1 = parse "(case (* 2 3)
     ((2 3 5 7) 'prime)
     ((1 4 6 8 9) 'composit))";;
val e1 : Parser.exp =
  IfExp
   (ApplyExp (VarExp "memv",
     [ApplyExp (VarExp "*", [SelfEvalExp (Int 2); SelfEvalExp (Int 3)]);
      QuoteExp (List [Int 2; Int 3; Int 5; Int 7])]),
   QuoteExp (Id "prime"),
   IfExp
    (ApplyExp (VarExp "memv",
      [ApplyExp (VarExp "*", [SelfEvalExp (Int 2); SelfEvalExp (Int 3)]);
       QuoteExp (List [Int 1; Int 4; Int 6; Int 8; Int 9])]),
    QuoteExp (Id "composit"), UnspecifiedExp))
# evalExp env e1;;
- : Parser.exp Valtype.valtype = SymbolV "composit"

# let e2 = parse "(let* ((x 7) (z (+ x 3)))
    (* z x))";;
val e2 : Parser.exp =
  ApplyExp
   (LambdaExp (["x"], Fixed,
     ApplyExp
      (LambdaExp (["z"], Fixed,
        ApplyExp
         (LambdaExp ([], Fixed,
           ApplyExp (VarExp "*", [VarExp "z"; VarExp "x"])),
         [])),
      [ApplyExp (VarExp "+", [VarExp "x"; SelfEvalExp (Int 3)])])),
   [SelfEvalExp (Int 7)])
# evalExp env e2;;
- : Parser.exp Valtype.valtype = IntV 70

展開していて結果もそれなりであるが、caseでは (* 2 3) が何回も評価されている。r7rsの else => にも未対応。
伝統的なマクロが動くのでschemeで書いてもいいのだが、外部ファイルを読み込むデザインは保留しているので、当面はパーサにOCamlでハードコードする。