* 「10日くらいでできる!プログラミング言語自作入門」の続編#2-1a (HL-30a)
-(by [[K]], 2022.06.22)

** (1) 今回の改造テーマ
-[[a22_txt03]]の続きで、今回は小数の計算をやりたいと思います。
-いきなりたくさんやると大変なので、とりあえず二項演算子の四則演算だけを考えます。

** (2-1) isInt(), isDbl() の追加
-before:
 enum { TypInt, TypDbl };
 AInt varTyp[MAX_TC + 1]; // そのトークンは、int型か、double型か?
 AInt var[MAX_TC + 1];	// int変数.
 double varDbl[MAX_TC + 1]; // double変数.
-after:
 enum { TypInt, TypDbl };
 AInt varTyp[MAX_TC + 1]; // そのトークンは、int型か、double型か?
 AInt var[MAX_TC + 1];	// int変数.
 double varDbl[MAX_TC + 1]; // double変数.
 
 int isInt(int i) { return i >= 0 && varTyp[i] == TypInt; }
 int isDbl(int i) { return i >= 0 && varTyp[i] == TypDbl; }

** (2-2) double用の一時変数を整備(1)
-before:
 enum { TcSemi = 0, TcDot, TcWiCard, Tc0, Tc1, Tc2, Tc3, Tc4, Tc5, Tc6, Tc7, Tc8, TcBrOpn, TcBrCls, TcSqBrOpn, TcSqBrCls, TcCrBrOpn, TcCrBrCls,
     TcEEq, TcNEq, TcLt, TcGe, TcLe, TcGt, TcPlus, TcMinus, TcAster, TcSlash, TcPerce, TcAnd, TcShr, TcPlPlus, TcEqu,
     TcComma, TcExpr, TcExpr0, TcTmp0, TcTmp1, TcTmp2, TcTmp3, TcTmp4, TcTmp5, TcTmp6, TcTmp7, TcTmp8, TcTmp9 };
 
 char tcInit[] = "; . !!* 0 1 2 3 4 5 6 7 8 ( ) [ ] { } == != < >= <= > + - * / % & >> ++ = , !!** !!*** _t0 _t1 _t2 _t3 _t4 _t5 _t6 _t7 _t8 _t9"

-after:
 enum { TcSemi = 0, TcDot, TcWiCard, Tc0, Tc1, Tc2, Tc3, Tc4, Tc5, Tc6, Tc7, Tc8, TcBrOpn, TcBrCls, TcSqBrOpn, TcSqBrCls, TcCrBrOpn, TcCrBrCls,
     TcEEq, TcNEq, TcLt, TcGe, TcLe, TcGt, TcPlus, TcMinus, TcAster, TcSlash, TcPerce, TcAnd, TcShr, TcPlPlus, TcEqu,
     TcComma, TcExpr, TcExpr0, TcTmp0, TcTmp1, TcTmp2, TcTmp3, TcTmp4, TcTmp5, TcTmp6, TcTmp7, TcTmp8, TcTmp9,
     TcTmpDbl0, TcTmpDbl1, TcTmpDbl2, TcTmpDbl3, TcTmpDbl4, TcTmpDbl5, TcTmpDbl6, TcTmpDbl7, TcTmpDbl8, TcTmpDbl9 };
 
 char tcInit[] = "; . !!* 0 1 2 3 4 5 6 7 8 ( ) [ ] { } == != < >= <= > + - * / % & >> ++ = , !!** !!*** _t0 _t1 _t2 _t3 _t4 _t5 _t6 _t7 _t8 _t9"
     " _td0 _td1 _td2 _td3 _td4 _td5 _td6 _td7 _td8 _td9";

** (2-3) double用の一時変数を整備(2)
-before:
 char tmp_flag[10];
 
 int tmpAlloc()
 {
     int i;
     for (i = 0; i < 10; i++) {
         if (tmp_flag[i] == 0) break;
     }
     if (i >= 10) {
         printf("tmpAlloc: error\n");
         return -1;
     }
     tmp_flag[i] = 1;
     return i + TcTmp0;
 }
 
 void tmpFree(int i)
 {
     if (TcTmp0 <= i && i <= TcTmp9) {
         tmp_flag[i - TcTmp0] = 0;
     }
 }
-after:
 char tmp_flag[10], tmpDbl_flag[10];
 
 int tmpAlloc()
 {
     int i;
     for (i = 0; i < 10; i++) {
         if (tmp_flag[i] == 0) break;
     }
     if (i >= 10) {
         printf("tmpAlloc: error\n");
         return -1;
     }
     tmp_flag[i] = 1;
     return i + TcTmp0;
 }
 
 int tmpAllocDbl()
 {
     int i;
     for (i = 0; i < 10; i++) {
         if (tmpDbl_flag[i] == 0) break;
     }
     if (i >= 10) {
         printf("tmpAllocDbl: error\n");
         return -1;
     }
     tmpDbl_flag[i] = 1;
     varTyp[i] = TypDbl;
     varTyp[i + TcTmpDbl0] = TypDbl;
     return i + TcTmpDbl0;
 }
 
 void tmpFree(int i)
 {
     if (TcTmp0 <= i && i <= TcTmp9) {
         tmp_flag[i - TcTmp0] = 0;
     }
     if (TcTmpDbl0 <= i && i <= TcTmpDbl9) {
         tmpDbl_flag[i - TcTmpDbl0] = 0;
     }
 }

** (2-4) 内部コードに命令を追加
-before:
 enum { OpCpy = 0, OpCeq, OpCne, OpClt, OpCge, OpCle, OpCgt, OpAdd, OpSub, OpMul, OpDiv, OpMod, OpAnd, OpShr, 
     OpAdd1, OpNeg, OpGoto, OpJeq, OpJne, OpJlt, OpJge, OpJle, OpJgt, OpLop, OpPrint, OpTime, OpEnd,
     OpPrints, OpAryNew, OpAryInit, OpArySet, OpAryGet, OpOpnWin, OpSetPix0, OpM64s, OpRgb8, OpWait,
     OpXorShift, OpGetPix, OpFilRct0, OpPrm, OpF16Sin, OpF16Cos, OpInkey, OpDrwStr0, OpGprDec, OpBitBlt,
     OpPrintd };
-after:
 enum { OpCpy = 0, OpCeq, OpCne, OpClt, OpCge, OpCle, OpCgt, OpAdd, OpSub, OpMul, OpDiv, OpMod, OpAnd, OpShr, 
     OpAdd1, OpNeg, OpGoto, OpJeq, OpJne, OpJlt, OpJge, OpJle, OpJgt, OpLop, OpPrint, OpTime, OpEnd,
     OpPrints, OpAryNew, OpAryInit, OpArySet, OpAryGet, OpOpnWin, OpSetPix0, OpM64s, OpRgb8, OpWait,
     OpXorShift, OpGetPix, OpFilRct0, OpPrm, OpF16Sin, OpF16Cos, OpInkey, OpDrwStr0, OpGprDec, OpBitBlt,
     OpPrintd, OpAddDbl, OpSubDbl, OpMulDbl, OpDivDbl, OpIntToDbl };



** (2-5) exprSub1()関数を改造
-before:
 int exprSub1(int i, int priority, int op)	// 二項演算子の処理の標準形.
 {
     int j, k;
     epc++;
     j = exprSub(priority);
     k = tmpAlloc();
     putIc(op, &var[k], &var[i], &var[j], 0);
     tmpFree(i);
     tmpFree(j);
     if (i < 0 || j < 0) return -1;
     return k;
 }
-after:
 int intToDbl(int i)
 {
     if (isDbl(i) || i < 0) return i; // 最初からdoubleなら何もしない、エラーなら何もしない。
     int k = tmpAllocDbl();
     putIc(OpIntToDbl, varP(k), varP(i), 0, 0);
     tmpFree(i);
     return k;
 }
 
 int exprSub1(int i, int priority, int op)	// 二項演算子の処理の標準形.
 {
     int j, k;
     epc++;
     int opDbl = 0;
     if (op == OpAdd) opDbl = OpAddDbl;
     if (op == OpSub) opDbl = OpSubDbl;
     if (op == OpMul) opDbl = OpMulDbl;
     if (op == OpDiv) opDbl = OpDivDbl;
     j = exprSub(priority);
     if (opDbl > 0 && (isDbl(i) || isDbl(j))) { // もしどちらかがdoubleならdoubleで計算.
         i = intToDbl(i);
         j = intToDbl(j);
         k = tmpAllocDbl();
         op = opDbl;
     } else {
         k = tmpAlloc();
     }
     putIc(op, varP(k), varP(i), varP(j), 0);
     tmpFree(i);
     tmpFree(j);
     if (i < 0 || j < 0) return -1;
     return k;
 }

** (2-6) exec()関数に追加
-以下を適当な位置に追加します。
         case OpAddDbl:  *icpd[1] = *icpd[2] +  *icpd[3]; icp += 5; continue;
         case OpSubDbl:  *icpd[1] = *icpd[2] -  *icpd[3]; icp += 5; continue;
         case OpMulDbl:  *icpd[1] = *icpd[2] *  *icpd[3]; icp += 5; continue;
         case OpDivDbl:  *icpd[1] = *icpd[2] /  *icpd[3]; icp += 5; continue;
         case OpIntToDbl: *icpd[1] = *icp[2];             icp += 5; continue;

** (3) 計算のテスト
 >printd 10.0 / 3.0
 3.333333
 
 >printd 11.111111 / 9
 1.234568

** 次回に続く
次回: [[a22_txt03_1b]]

*こめんと欄
#comment

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS