a21_txt01_6
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 川合のプログラミング言語自作のためのテキスト第三版#6
-(by [[K]], 2021.03.02)
** (1) HL-6
-HL-5は多少速くなったものの、C言語と比べれば圧倒的に負け...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす|
|[[a21_txt01]]|HL-1|RIGHT:49行|RIGHT:6.0KB|初めの一歩、た...
|[[a21_txt01_2]]|HL-2|128行|RIGHT:6.5KB|変数名は1文字じゃ...
|[[a21_txt01_3]]|HL-3|148行|RIGHT:7.0KB|条件分岐などをサ...
|[[a21_txt01_4]]|HL-4|186行|RIGHT:7.5KB|REPLの導入(これ...
|[[a21_txt01_5]]|HL-5|214行|RIGHT:7.5KB|少し高速化|RIGHT:...
-ということで本気を出してどこまで速くなるか挑戦します。JI...
-基本方針としては、tc[]をphrCmp()で一致しているかどうか調...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef unsigned char *String; // こう書くと String は u...
int loadText(String path, String t, int siz) → HL-4と同...
////////////////////////////////////////////////////////...
#define MAX_TC 255 // トークンコードの最大値.
String ts[MAX_TC + 1]; // トークンの内容(文字列)を記憶.
int tl[MAX_TC + 1]; // トークンの長さ.
unsigned char tcBuf[(MAX_TC + 1) * 10]; // トークン1つ当...
int tcs = 0, tcb = 0;
int var[MAX_TC + 1]; // 変数.
int getTc(String s, int len) → HL-4と同じなので省略
////////////////////////////////////////////////////////...
int isAlphabet(unsigned char c) → HL-2と同じなので省略
int lexer(String s, int tc[]) → HL-2と同じなので省略
int tc[10000]; // トークンコード.
enum { TcSemi = 0, TcDot, TcWiCard, Tc0, Tc1, Tc2, Tc3, ...
char tcInit[] = "; . !!* 0 1 2 3 4 5 6 7 8 == != < >= <=...
////////////////////////////////////////////////////////...
int phrCmp_tc[32 * 100], ppc1, wpc[9]; // ppc1:一致した...
int phrCmp(int pid, String phr, int pc) → HL-5と同じなの...
////////////////////////////////////////////////////////...
typedef int *IntP; // こう書くと IntP は int * の代わり...
enum { OpCpy = 0, OpAdd, OpSub, OpPrint, OpGoto, OpJeq, ...
IntP ic[10000], *icq; // ic[]:内部コード、icq:ic[]への書...
void putIc(int op, IntP p1, IntP p2, IntP p3, IntP p4) ...
{
icq[0] = (IntP) op;
icq[1] = p1;
icq[2] = p2;
icq[3] = p3;
icq[4] = p4;
icq += 5;
}
////////////////////////////////////////////////////////...
int compile(String s)
{
int pc, pc1, i;
IntP *icq1;
pc1 = lexer(s, tc);
tc[pc1++] = TcSemi; // 末尾に「;」を付け忘れることが...
tc[pc1] = tc[pc1 + 1] = tc[pc1 + 2] = tc[pc1 + 3] = ...
icq = ic; // これで、icqはic[0]を指すようになる. こ...
for (pc = 0; pc < pc1; ) { // コンパイル開始.
if (phrCmp( 1, "!!*0 = !!*1;", pc)) { // 単純代入.
putIc(OpCpy, &var[tc[wpc[0]]], &var[tc[wpc[...
} else if (phrCmp( 9, "!!*0 = !!*1 + 1;", pc) &&...
putIc(OpAdd1, &var[tc[wpc[0]]], 0, 0, 0);
} else if (phrCmp( 2, "!!*0 = !!*1 + !!*2;", pc)...
putIc(OpAdd, &var[tc[wpc[0]]], &var[tc[wpc[...
} else if (phrCmp( 3, "!!*0 = !!*1 - !!*2;", pc)...
putIc(OpSub, &var[tc[wpc[0]]], &var[tc[wpc[...
} else if (phrCmp( 4, "print !!*0;", pc)) { // p...
putIc(OpPrint, &var[tc[wpc[0]]], 0, 0, 0);
} else if (phrCmp( 0, "!!*0:", pc)) { // ラベル...
var[tc[wpc[0]]] = icq - ic; // ラベルに対応...
} else if (phrCmp( 5, "goto !!*0;", pc)) { // go...
putIc(OpGoto, &var[tc[wpc[0]]], 0, 0, 0);
} else if (phrCmp( 6, "if (!!*0 !!*1 !!*2) goto ...
putIc(OpJeq + (tc[wpc[1]] - TcEEq), &var[tc[...
} else if (phrCmp( 7, "time;", pc)) {
putIc(OpTime, 0, 0, 0, 0);
} else if (phrCmp( 8, ";", pc)) {
// 何もしない.
} else
goto err;
pc = ppc1;
}
putIc(OpEnd, 0, 0, 0, 0);
icq1 = icq;
for (icq = ic; icq < icq1; icq += 5) { // goto先の...
i = (int) icq[0];
if (OpGoto <= i && i <= OpJgt) {
icq[1] = (IntP) (*icq[1] + ic);
}
}
return icq1 - ic;
err:
printf("syntax error : %s %s %s %s\n", ts[tc[pc]], t...
return -1;
}
void exec()
{
clock_t t0 = clock();
IntP *icp = ic; // これによりicpはic[0]を指すように...
for (;;) {
switch ((int) icp[0]) {
case OpCpy:
*icp[1] = *icp[2];
icp += 5;
continue;
case OpAdd:
*icp[1] = *icp[2] + *icp[3];
icp += 5;
continue;
case OpSub:
*icp[1] = *icp[2] - *icp[3];
icp += 5;
continue;
case OpPrint:
printf("%d\n", *icp[1]);
icp += 5;
continue;
case OpGoto:
icp = (IntP *) icp[1];
continue;
case OpJeq: if (*icp[2] == *icp[3]) { icp = (In...
case OpJne: if (*icp[2] != *icp[3]) { icp = (In...
case OpJlt: if (*icp[2] < *icp[3]) { icp = (In...
case OpTime:
printf("time: %.3f[sec]\n", (clock() - t0) /...
icp += 5;
continue;
case OpEnd:
return;
case OpAdd1:
(*icp[1])++;
icp += 5;
continue;
}
}
}
int run(String s)
{
if (compile(s) < 0)
return 1;
exec();
return 0;
}
////////////////////////////////////////////////////////...
int main(int argc, const char **argv) → HL-5と同じなので...
-トータルの行数は285行まで一気に増えてしまいました。でも...
** (2) HL-6の簡単な説明
-関数:
--void loadText(String path, String t, int siz)
---ファイルパスpathで指定されたソースファイルをtに読み込...
--int getTc(String s, int len)
---トークン(単語)をsに渡すと、それに対応するトークンコ...
--int isAlphabetOrNumber(unsigned char c)
---引数で渡された文字コードが、英数字であれば1を返す。そ...
---アンダースコアもHL-6の中ではアルファベットということに...
---この関数は以下のlexer()の下請け。
--int lexer(String s, int tc[])
---sにプログラムのソースコードを渡す。すると、tc[]にトー...
---より詳しい動作は、[[a21_txt01_2a]]を参照のこと。
--int phrCmp(int pid, String phr, int pc)
---tc[pc]からのトークンコード列がphrで指定されたトークン...
---pidはフレーズIDで、この番号を使ってphrCmp_tc[]のどこに...
---なお、処理できるフレーズの最大長はこのプログラムの場合...
--void putIc(int op, IntP p1, IntP p2, IntP p3, IntP p4)
---引数で渡された内容を内部コードのic[]に書き込む関数。関...
--int compile(String s)
---与えられた文字列をプログラムだと解釈して、内部コードを...
---関数run()の下請け関数。
--void exec()
---ic[]に格納された内部コードを高速に実行する。
---関数run()の下請け関数。
--int run(String s)
---言語処理の本体。HL-3までのmain()に相当。
---内部的にはcompile()してrun()しているだけ。
--int main(int argc, const char **argv)
---REPLの処理をしている。
-変数:
--String ts[]
---getTc()が管理している配列変数で、トークンコードからト...
--int tl[]
---getTc()が管理している配列変数で、トークンコードからト...
--unsigned char tcBuf[]
---getTc()が管理している変数で、トークン文字列の実体を保...
--int tcs, tcb
---どちらもgetTc()が管理している変数で、tcsは今までに発行...
---tcbはtcBuf[]の未使用領域を指している。
---もしtcBuf[]やtcbの役割がピンとこない場合は、[[a21_txt0...
--int var[]
---変数の値を記憶しておくための変数。トークンコードをその...
--int tc[]
---プログラムをトークンコード列に変換したものがここに入る。
--int phrCmp_tc[]
---phrCmp()が管理している変数で、phrCmp_tc[]にはフレーズ...
--int ppc1, wpc[]
---フレーズが一致した場合、ppc1に一致したフレーズの次のト...
---wpc[]にはワイルドカードで一致した位置が入る。
--IntP ic[], *icq
---ic[]は内部コード(internal-code)を格納しておくための...
----
-まず、高速かつ簡潔に書くためにどうしたらいいかを検討しま...
** (3) 内部コードに関する詳しい説明(compile(), exec()な...
-まず最初に、exec()から説明したいと思います。exec()の基本...
-内部コードは、以下のような仕様にしています。
|icp[0]|icp[1]|icp[2]|icp[3]|icp[4]|動作|説明|
|OpCpy |p1|p2| | |*p1 = *p2;|単純代入|
|OpAdd |p1|p2|p3| |*p1 = *p2 + *p3;|加算|
|OpSub |p1|p2|p3| |*p1 = *p2 - *p3;|減算|
|OpPrint|p1| | | |print *p1;|値の表示|
|OpGoto |p1| | | |goto p1;|無条件分岐(icp = p1;してい...
|OpJeq |p1|p2|p3| |if (*p2 == *p3) goto p1;|条件分岐(ju...
|OpJne |p1|p2|p3| |if (*p2 != *p3) goto p1;|条件分岐(ju...
|OpJlt |p1|p2|p3| |if (*p2 < *p3) goto p1;|条件分岐(ju...
|OpTime | | | | |時間表示|exec()を開始してからの経過...
|OpEnd | | | | |exec()を終了|内部的にはreturnするだけ|
|OpAdd1 |p1| | | |(*p1)++;|変数に1を加算。OpAddで1を加...
--表の中のp1~p3は、ポインタです。しかもgotoや条件分岐のp...
--もしポインタを扱うのが嫌なら、p1~p3ではなくて、i1~i3...
--これがやむなくポインタを多用することになった理由です。
--この表と見比べると、exec()で不可解なところはほぼないの...
--あ、そうだ。OpGotoのところで、「icp = (IntP *) icp[1];...
-次はcompile()です。
--HL-5と比較すれば、より分かりやすいだろうと思うので、比...
[HL-5]
} else if (phrCmp( 2, "!!*0 = !!*1 + !!*2;", pc)) { ...
var[tc[wpc[0]]] = var[tc[wpc[1]]] + var[tc[wpc[2...
[HL-6]
} else if (phrCmp( 2, "!!*0 = !!*1 + !!*2;", pc)) { ...
putIc(OpAdd, &var[tc[wpc[0]]], &var[tc[wpc[1]]]...
--HL-5のときは、実際に変数の値を2つ読み取って加算して、結...
--C言語では、変数名を書けば変数の値を意味しますが、その前...
--これでexec()でうまく実行できるようになります。
--compile()でちょっとわかりにくいかもしれないのは、gotoの...
--まずラベル定義命令が来たら、内部コードは何も出力しない...
--(C言語では、2つのポインタの差は整数値になります。)
--この整数値は、icqがic[]の何番目になっているかを表す整数...
--そしてgoto命令を見つけたら、OpGoto命令を生成して第一引...
--HL-5までだったら、ここでpc値を更新してgoto先に移動する...
--そうして、最後まで内部コードへの変換が終わると、OpEnd命...
icq1 = icq;
for (icq = ic; icq < icq1; icq += 5) { // goto先の...
i = (int) icq[0];
if (OpGoto <= i && i <= OpJgt) {
icq[1] = (IntP) (*icq[1] + ic);
}
}
--ここでやっているのは、もしOpGotoやOpJeqのように、p1がジ...
--ここでもやはり型が合わないので、(IntP)でキャストしてエ...
----
-あとは、こまごましたことをQ&A形式で説明します。
-[Q]なぜジャンプ先の計算を後になってやっているんですか?g...
putIc(OpGoto, (IntP) (var[tc[wpc[0]]] + ic), 0, 0, 0);
--ってやっちゃえばいいじゃないですか。
--[A]それは良い質問です。実は私もそうしたいのですが、この...
-[Q]なぜ内部コードは全部長さが5なのか?単純代入なんて3つ...
--[A]実は私も最初はそのように思っていたのですが、キャッシ...
** (4) 発展的な改造
-HL-6では、少しでも高速化するために、+1するための専用の命...
--[[a21_txt01_6a]]
** 次回に続く
-次回: [[a21_txt01_7]]
*こめんと欄
#comment
終了行:
* 川合のプログラミング言語自作のためのテキスト第三版#6
-(by [[K]], 2021.03.02)
** (1) HL-6
-HL-5は多少速くなったものの、C言語と比べれば圧倒的に負け...
|ページ名|名前|行数|.exeの大きさ|説明|速度のめやす|
|[[a21_txt01]]|HL-1|RIGHT:49行|RIGHT:6.0KB|初めの一歩、た...
|[[a21_txt01_2]]|HL-2|128行|RIGHT:6.5KB|変数名は1文字じゃ...
|[[a21_txt01_3]]|HL-3|148行|RIGHT:7.0KB|条件分岐などをサ...
|[[a21_txt01_4]]|HL-4|186行|RIGHT:7.5KB|REPLの導入(これ...
|[[a21_txt01_5]]|HL-5|214行|RIGHT:7.5KB|少し高速化|RIGHT:...
-ということで本気を出してどこまで速くなるか挑戦します。JI...
-基本方針としては、tc[]をphrCmp()で一致しているかどうか調...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef unsigned char *String; // こう書くと String は u...
int loadText(String path, String t, int siz) → HL-4と同...
////////////////////////////////////////////////////////...
#define MAX_TC 255 // トークンコードの最大値.
String ts[MAX_TC + 1]; // トークンの内容(文字列)を記憶.
int tl[MAX_TC + 1]; // トークンの長さ.
unsigned char tcBuf[(MAX_TC + 1) * 10]; // トークン1つ当...
int tcs = 0, tcb = 0;
int var[MAX_TC + 1]; // 変数.
int getTc(String s, int len) → HL-4と同じなので省略
////////////////////////////////////////////////////////...
int isAlphabet(unsigned char c) → HL-2と同じなので省略
int lexer(String s, int tc[]) → HL-2と同じなので省略
int tc[10000]; // トークンコード.
enum { TcSemi = 0, TcDot, TcWiCard, Tc0, Tc1, Tc2, Tc3, ...
char tcInit[] = "; . !!* 0 1 2 3 4 5 6 7 8 == != < >= <=...
////////////////////////////////////////////////////////...
int phrCmp_tc[32 * 100], ppc1, wpc[9]; // ppc1:一致した...
int phrCmp(int pid, String phr, int pc) → HL-5と同じなの...
////////////////////////////////////////////////////////...
typedef int *IntP; // こう書くと IntP は int * の代わり...
enum { OpCpy = 0, OpAdd, OpSub, OpPrint, OpGoto, OpJeq, ...
IntP ic[10000], *icq; // ic[]:内部コード、icq:ic[]への書...
void putIc(int op, IntP p1, IntP p2, IntP p3, IntP p4) ...
{
icq[0] = (IntP) op;
icq[1] = p1;
icq[2] = p2;
icq[3] = p3;
icq[4] = p4;
icq += 5;
}
////////////////////////////////////////////////////////...
int compile(String s)
{
int pc, pc1, i;
IntP *icq1;
pc1 = lexer(s, tc);
tc[pc1++] = TcSemi; // 末尾に「;」を付け忘れることが...
tc[pc1] = tc[pc1 + 1] = tc[pc1 + 2] = tc[pc1 + 3] = ...
icq = ic; // これで、icqはic[0]を指すようになる. こ...
for (pc = 0; pc < pc1; ) { // コンパイル開始.
if (phrCmp( 1, "!!*0 = !!*1;", pc)) { // 単純代入.
putIc(OpCpy, &var[tc[wpc[0]]], &var[tc[wpc[...
} else if (phrCmp( 9, "!!*0 = !!*1 + 1;", pc) &&...
putIc(OpAdd1, &var[tc[wpc[0]]], 0, 0, 0);
} else if (phrCmp( 2, "!!*0 = !!*1 + !!*2;", pc)...
putIc(OpAdd, &var[tc[wpc[0]]], &var[tc[wpc[...
} else if (phrCmp( 3, "!!*0 = !!*1 - !!*2;", pc)...
putIc(OpSub, &var[tc[wpc[0]]], &var[tc[wpc[...
} else if (phrCmp( 4, "print !!*0;", pc)) { // p...
putIc(OpPrint, &var[tc[wpc[0]]], 0, 0, 0);
} else if (phrCmp( 0, "!!*0:", pc)) { // ラベル...
var[tc[wpc[0]]] = icq - ic; // ラベルに対応...
} else if (phrCmp( 5, "goto !!*0;", pc)) { // go...
putIc(OpGoto, &var[tc[wpc[0]]], 0, 0, 0);
} else if (phrCmp( 6, "if (!!*0 !!*1 !!*2) goto ...
putIc(OpJeq + (tc[wpc[1]] - TcEEq), &var[tc[...
} else if (phrCmp( 7, "time;", pc)) {
putIc(OpTime, 0, 0, 0, 0);
} else if (phrCmp( 8, ";", pc)) {
// 何もしない.
} else
goto err;
pc = ppc1;
}
putIc(OpEnd, 0, 0, 0, 0);
icq1 = icq;
for (icq = ic; icq < icq1; icq += 5) { // goto先の...
i = (int) icq[0];
if (OpGoto <= i && i <= OpJgt) {
icq[1] = (IntP) (*icq[1] + ic);
}
}
return icq1 - ic;
err:
printf("syntax error : %s %s %s %s\n", ts[tc[pc]], t...
return -1;
}
void exec()
{
clock_t t0 = clock();
IntP *icp = ic; // これによりicpはic[0]を指すように...
for (;;) {
switch ((int) icp[0]) {
case OpCpy:
*icp[1] = *icp[2];
icp += 5;
continue;
case OpAdd:
*icp[1] = *icp[2] + *icp[3];
icp += 5;
continue;
case OpSub:
*icp[1] = *icp[2] - *icp[3];
icp += 5;
continue;
case OpPrint:
printf("%d\n", *icp[1]);
icp += 5;
continue;
case OpGoto:
icp = (IntP *) icp[1];
continue;
case OpJeq: if (*icp[2] == *icp[3]) { icp = (In...
case OpJne: if (*icp[2] != *icp[3]) { icp = (In...
case OpJlt: if (*icp[2] < *icp[3]) { icp = (In...
case OpTime:
printf("time: %.3f[sec]\n", (clock() - t0) /...
icp += 5;
continue;
case OpEnd:
return;
case OpAdd1:
(*icp[1])++;
icp += 5;
continue;
}
}
}
int run(String s)
{
if (compile(s) < 0)
return 1;
exec();
return 0;
}
////////////////////////////////////////////////////////...
int main(int argc, const char **argv) → HL-5と同じなので...
-トータルの行数は285行まで一気に増えてしまいました。でも...
** (2) HL-6の簡単な説明
-関数:
--void loadText(String path, String t, int siz)
---ファイルパスpathで指定されたソースファイルをtに読み込...
--int getTc(String s, int len)
---トークン(単語)をsに渡すと、それに対応するトークンコ...
--int isAlphabetOrNumber(unsigned char c)
---引数で渡された文字コードが、英数字であれば1を返す。そ...
---アンダースコアもHL-6の中ではアルファベットということに...
---この関数は以下のlexer()の下請け。
--int lexer(String s, int tc[])
---sにプログラムのソースコードを渡す。すると、tc[]にトー...
---より詳しい動作は、[[a21_txt01_2a]]を参照のこと。
--int phrCmp(int pid, String phr, int pc)
---tc[pc]からのトークンコード列がphrで指定されたトークン...
---pidはフレーズIDで、この番号を使ってphrCmp_tc[]のどこに...
---なお、処理できるフレーズの最大長はこのプログラムの場合...
--void putIc(int op, IntP p1, IntP p2, IntP p3, IntP p4)
---引数で渡された内容を内部コードのic[]に書き込む関数。関...
--int compile(String s)
---与えられた文字列をプログラムだと解釈して、内部コードを...
---関数run()の下請け関数。
--void exec()
---ic[]に格納された内部コードを高速に実行する。
---関数run()の下請け関数。
--int run(String s)
---言語処理の本体。HL-3までのmain()に相当。
---内部的にはcompile()してrun()しているだけ。
--int main(int argc, const char **argv)
---REPLの処理をしている。
-変数:
--String ts[]
---getTc()が管理している配列変数で、トークンコードからト...
--int tl[]
---getTc()が管理している配列変数で、トークンコードからト...
--unsigned char tcBuf[]
---getTc()が管理している変数で、トークン文字列の実体を保...
--int tcs, tcb
---どちらもgetTc()が管理している変数で、tcsは今までに発行...
---tcbはtcBuf[]の未使用領域を指している。
---もしtcBuf[]やtcbの役割がピンとこない場合は、[[a21_txt0...
--int var[]
---変数の値を記憶しておくための変数。トークンコードをその...
--int tc[]
---プログラムをトークンコード列に変換したものがここに入る。
--int phrCmp_tc[]
---phrCmp()が管理している変数で、phrCmp_tc[]にはフレーズ...
--int ppc1, wpc[]
---フレーズが一致した場合、ppc1に一致したフレーズの次のト...
---wpc[]にはワイルドカードで一致した位置が入る。
--IntP ic[], *icq
---ic[]は内部コード(internal-code)を格納しておくための...
----
-まず、高速かつ簡潔に書くためにどうしたらいいかを検討しま...
** (3) 内部コードに関する詳しい説明(compile(), exec()な...
-まず最初に、exec()から説明したいと思います。exec()の基本...
-内部コードは、以下のような仕様にしています。
|icp[0]|icp[1]|icp[2]|icp[3]|icp[4]|動作|説明|
|OpCpy |p1|p2| | |*p1 = *p2;|単純代入|
|OpAdd |p1|p2|p3| |*p1 = *p2 + *p3;|加算|
|OpSub |p1|p2|p3| |*p1 = *p2 - *p3;|減算|
|OpPrint|p1| | | |print *p1;|値の表示|
|OpGoto |p1| | | |goto p1;|無条件分岐(icp = p1;してい...
|OpJeq |p1|p2|p3| |if (*p2 == *p3) goto p1;|条件分岐(ju...
|OpJne |p1|p2|p3| |if (*p2 != *p3) goto p1;|条件分岐(ju...
|OpJlt |p1|p2|p3| |if (*p2 < *p3) goto p1;|条件分岐(ju...
|OpTime | | | | |時間表示|exec()を開始してからの経過...
|OpEnd | | | | |exec()を終了|内部的にはreturnするだけ|
|OpAdd1 |p1| | | |(*p1)++;|変数に1を加算。OpAddで1を加...
--表の中のp1~p3は、ポインタです。しかもgotoや条件分岐のp...
--もしポインタを扱うのが嫌なら、p1~p3ではなくて、i1~i3...
--これがやむなくポインタを多用することになった理由です。
--この表と見比べると、exec()で不可解なところはほぼないの...
--あ、そうだ。OpGotoのところで、「icp = (IntP *) icp[1];...
-次はcompile()です。
--HL-5と比較すれば、より分かりやすいだろうと思うので、比...
[HL-5]
} else if (phrCmp( 2, "!!*0 = !!*1 + !!*2;", pc)) { ...
var[tc[wpc[0]]] = var[tc[wpc[1]]] + var[tc[wpc[2...
[HL-6]
} else if (phrCmp( 2, "!!*0 = !!*1 + !!*2;", pc)) { ...
putIc(OpAdd, &var[tc[wpc[0]]], &var[tc[wpc[1]]]...
--HL-5のときは、実際に変数の値を2つ読み取って加算して、結...
--C言語では、変数名を書けば変数の値を意味しますが、その前...
--これでexec()でうまく実行できるようになります。
--compile()でちょっとわかりにくいかもしれないのは、gotoの...
--まずラベル定義命令が来たら、内部コードは何も出力しない...
--(C言語では、2つのポインタの差は整数値になります。)
--この整数値は、icqがic[]の何番目になっているかを表す整数...
--そしてgoto命令を見つけたら、OpGoto命令を生成して第一引...
--HL-5までだったら、ここでpc値を更新してgoto先に移動する...
--そうして、最後まで内部コードへの変換が終わると、OpEnd命...
icq1 = icq;
for (icq = ic; icq < icq1; icq += 5) { // goto先の...
i = (int) icq[0];
if (OpGoto <= i && i <= OpJgt) {
icq[1] = (IntP) (*icq[1] + ic);
}
}
--ここでやっているのは、もしOpGotoやOpJeqのように、p1がジ...
--ここでもやはり型が合わないので、(IntP)でキャストしてエ...
----
-あとは、こまごましたことをQ&A形式で説明します。
-[Q]なぜジャンプ先の計算を後になってやっているんですか?g...
putIc(OpGoto, (IntP) (var[tc[wpc[0]]] + ic), 0, 0, 0);
--ってやっちゃえばいいじゃないですか。
--[A]それは良い質問です。実は私もそうしたいのですが、この...
-[Q]なぜ内部コードは全部長さが5なのか?単純代入なんて3つ...
--[A]実は私も最初はそのように思っていたのですが、キャッシ...
** (4) 発展的な改造
-HL-6では、少しでも高速化するために、+1するための専用の命...
--[[a21_txt01_6a]]
** 次回に続く
-次回: [[a21_txt01_7]]
*こめんと欄
#comment
ページ名: