川合のプログラミング言語自作のためのテキスト第三版#9

(1) HL-9

#include <acl.c>

typedef unsigned char *String;	// こう書くと String は unsigned char * の代用になる.

int loadText(String path, String t, int siz) → HL-4と同じなので省略

///////////////////////////////////////////////////////////////////////////////

#define MAX_TC  1000 // トークンコードの最大値.
String ts[MAX_TC + 1]; // トークンの内容(文字列)を記憶.
int tl[MAX_TC + 1]; // トークンの長さ.
unsigned char tcBuf[(MAX_TC + 1) * 10]; // トークン1つ当たり平均10バイトを想定.
int tcs = 0, tcb = 0;

AInt var[MAX_TC + 1];	// 変数. (!)

int getTc(String s, int len) → HL-8aと同じなので省略

///////////////////////////////////////////////////////////////////////////////

int isAlphabetOrNumber(unsigned char c) → HL-2と同じなので省略

int lexer(String s, int tc[]) → HL-8aと同じなので省略

int tc[10000];	// トークンコード.

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";

///////////////////////////////////////////////////////////////////////////////

int phrCmp_tc[32 * 100], ppc1, wpc[9], wpc1[9]; // ppc1:一致したフレーズの次のトークンをさす, wpc[]:ワイルドカードのトークンの場所をさす.

int phrCmp(int pid, String phr, int pc) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

typedef AInt *IntP; // こう書くと IntP は AInt * の代わりに使えるようになる. (!)

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 };

IntP ic[10000], *icq; // ic[]:内部コード、icq:ic[]への書き込み用ポインタ.

void putIc(int op, IntP p0, IntP p1, IntP p2, IntP p3) → HL-6と同じなので省略

///////////////////////////////////////////////////////////////////////////////

char tmp_flag[10]; // 一時変数の利用状況を管理.

int tmpAlloc() → HL-7と同じなので省略

void tmpFree(int i) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

int epc, epc1;	// exprのためのpcとpc1.

int exprSub(int priority);	// exprSub1()が参照するので、プロトタイプ宣言.
int expr(int j);
int phrCmpPutIc(int pid, String phr, int pc, int *pi, int lenExpr, int op, int *err);

int exprSub1(int i, int priority, int op) → HL-7と同じなので省略

int exprSub(int priority)
{
    int i = -1, e0 = 0, e1 = 0;
    ppc1 = 0;
    (中略)
    } else if (tc[epc] == TcMinus) {	// 単項マイナス.
        epc++;
        e0 = exprSub(2);
        i = tmpAlloc();
        putIc(OpNeg, &var[i], &var[e0], 0, 0);
+   } else if (phrCmpPutIc(72, "mul64shr(!!**1, !!**2, !!**3)",          epc, &i, 4, OpM64s,     &e0)) {
+   } else if (phrCmpPutIc(73, "aRgb8(!!**1, !!**2, !!**3)",             epc, &i, 4, OpRgb8,     &e0)) {
+   } else if (phrCmpPutIc(74, "aOpenWin(!!**0, !!**1, !!***2, !!***8)", epc, 0,  3, OpOpnWin,   &e0)) {
+       i = Tc0;
+   } else if (phrCmpPutIc(75, "aXorShift32()",                          epc, &i, 1, OpXorShift, &e0)) {
+   } else if (phrCmpPutIc(76, "aGetPix(!!**8, !!**1, !!**2)",           epc, &i, 3, OpGetPix,   &e0)) {
+   } else if (phrCmpPutIc(77, "ff16sin(!!**1)",                         epc, &i, 2, OpF16Sin,   &e0)) {
+   } else if (phrCmpPutIc(78, "ff16cos(!!**1)",                         epc, &i, 2, OpF16Cos,   &e0)) {
+   } else if (phrCmpPutIc(79, "aInkey(!!***8 , !!**1)",                 epc, &i, 2, OpInkey,    &e0)) {
    } else {		// 変数もしくは定数.
        i = tc[epc];
        epc++;
    }
    (中略)
}

int expr(int j) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

enum { IfTrue = 0, IfFalse = 1 };

void ifgoto(int i, int not, int label) → HL-8と同じなので省略

int tmpLabelNo;

int tmpLabelAlloc() → HL-8と同じなので省略

#define BInfSiz		10

int binf[BInfSiz * 100], bd, lbd; // binf:block-info, bd:block-depth, lbd:loop-block-depth

enum { BlkIf = 1, BlkFor };
enum { IfLabel0 = 1, IfLabel1 };
enum { ForLopBgn = 1, ForCont, ForBrk, ForLbd0, ForWpc01, ForWpc11, ForWpc02, ForWpc12 };

int phrCmpPutIc(int pid, String phr, int pc, int *pi, int lenExpr, int op, int *err) // この関数はHL-9で追加したもの.
{
    int e[9], i, i0 = 0;
    if (phrCmp(pid, phr, pc)) {
        e[0] = e[1] = e[2] = e[3] = e[4] = e[5] = e[6] = e[7] = e[8] = 0;
        if (pi != 0) {
            e[0] = *pi = tmpAlloc();
            i0 = 1;
        }
        for (i = i0; i < lenExpr; i++) {
            e[i] = expr(i);
        }
        putIc(op, &var[e[0]], &var[e[1]], &var[e[2]], &var[e[3]]);
        if (lenExpr >= 5) {
            putIc(OpPrm, &var[e[4]], &var[e[5]], &var[e[6]], &var[e[7]]);
        }
        for (i = i0; i < lenExpr; i++) {
            if (e[i] < 0) {
                *err = -1;
            }
            tmpFree(e[i]);
        }
        return 1;
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////////

int compile(String s)
{
    (中略)
        } else if (phrCmp(22, "int !!*0[!!**2] = {", pc)) {
            (中略)
+       } else if (phrCmpPutIc(23, "aSetPix0(!!***8, !!**0, !!**1, !!**2);",                       pc, 0, 3, OpSetPix0, &e0)) {
+       } else if (phrCmpPutIc(24, "aWait(!!**0);",                                                pc, 0, 1, OpWait,    &e0)) {
+       } else if (phrCmpPutIc(25, "aFillRect0(!!***8, !!**0, !!**1, !!**2, !!**3, !!**4);",       pc, 0, 5, OpFilRct0, &e0)) {
+       } else if (phrCmpPutIc(26, "aDrawStr0(!!***8, !!**0, !!**1, !!**2, !!**3, !!**4);",        pc, 0, 5, OpDrwStr0, &e0)) {
+       } else if (phrCmpPutIc(27, "gprintDec(!!***8, !!**0, !!**1, !!**2, !!**3, !!**4, !!**5);", pc, 0, 6, OpGprDec,  &e0)) {
+       } else if (phrCmpPutIc(28, "bitblt(!!***8, !!**0, !!**1, !!**2, !!**3, !!**4);",           pc, 0, 5, OpBitBlt,  &e0)) {
        } else if (phrCmp( 8, "!!***0;", pc)) {	// これはかなりマッチしやすいので最後にする.
            e0 = expr(0);
    (中略)
}

void exec()
{
    clock_t t0 = clock();
    IntP *icp = ic;
!   AInt i, j, *a, sx, sy;
+   AInt32 *p32;
+   char s[100];
    for (;;) {
        switch ((int) icp[0]) {
         (中略)
+       case OpOpnWin:
+           if (win != 0) {
+               if (win->xsiz < *icp[1] || win->ysiz < *icp[2]) {
+                   printf("openWin error\n");
+                   return;
+               }
+           } else
+               win = aOpenWin(*icp[1], *icp[2], (char *) *icp[3], 0);
+           icp += 5;
+           continue;
+       case OpSetPix0:
+           aSetPix0(win, *icp[1], *icp[2], *icp[3]);
+           icp += 5;
+           continue;
+       case OpM64s:
+           *icp[1] = (((AInt64) *icp[2]) * ((AInt64) *icp[3])) >> *icp[4];
+           icp += 5;
+           continue;
+       case OpRgb8:
+           *icp[1] = aRgb8(*icp[2], *icp[3], *icp[4]);
+           icp += 5;
+           continue;
+       case OpWait:
+           if (*icp[1] == -1) {
+               if (win != 0)
+                   aFlushAll(win);
+               return;
+           }
+           aWait(*icp[1]);
+           icp += 5;
+           continue;
+       case OpXorShift:
+           *icp[1] = aXorShift32();
+           icp += 5;
+           continue;
+       case OpGetPix:
+           *icp[1] = aGetPix(win, *icp[2], *icp[3]);
+           icp += 5;
+           continue;
+       case OpFilRct0:
+           aFillRect0(win, *icp[1], *icp[2], *icp[3], *icp[4], *icp[6]);
+           icp += 10;
+           continue;
+       case OpF16Sin:
+           *icp[1] = (AInt) (sin(*icp[2] * (2 * 3.14159265358979323 / 65536)) * 65536);
+           icp += 5;
+           continue;
+       case OpF16Cos:
+           *icp[1] = (AInt) (cos(*icp[2] * (2 * 3.14159265358979323 / 65536)) * 65536);
+           icp += 5;
+           continue;
+       case OpInkey:
+           *icp[1] = aInkey(win, *icp[2]);
+           icp += 5;
+           continue;
+       case OpDrwStr0:
+           aDrawStr0(win, *icp[1], *icp[2], *icp[3], *icp[4], (char *) *icp[6]);
+           icp += 10;
+           continue;
+       case OpGprDec:
+           sprintf(s, "%*d", *icp[3], *icp[7]);
+           aDrawStr0(win, *icp[1], *icp[2], *icp[4], *icp[6], s);
+           icp += 10;
+           continue;
+       case OpBitBlt:
+           a = (AInt *) *icp[6];
+           p32 = &win->buf[*icp[3] + *icp[4] * win->xsiz];
+           sx = *icp[1];
+           sy = *icp[2];
+           for (j = 0; j < sy; j++) {
+               for (i = 0; i < sx; i++) {
+                   p32[i] = a[i];
+               }
+               a += sx;
+               p32 += win->xsiz;
+           }
+           icp += 10;
+           continue;
       }
   }
}

int run(String s) → HL-6と同じなので省略

///////////////////////////////////////////////////////////////////////////////

void aMain() // 関数名を変更.
{
    unsigned char txt[10000];
    int i;
    lexer(tcInit, tc);
!   if (aArgc >= 2) {
!       if (loadText((String) aArgv[1], txt, 10000) == 0) {
            run(txt);
        }
        exit(0);
    }
    for (;;) { // Read-Eval-Print Loop.
        (中略)
    }
}

(2) phrCmpPutIc()について

(3) aclライブラリについて

(3) HL-8aにおける配列アクセスの実現方法

次回に続く

こめんと欄


コメントお名前NameLink

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS