概要
ilasmでstack machineやってみた。
練習問題やってみた。
練習問題
俺言語を、ilasmに変換するコンパイラを書け。
zundokoをコンパイルせよ。
写真
投入したソース
10 a=0
30 b=$
50 #=b<1*100
60 ?="zun "
70 a=a+1
80 #=a>3*130
90 #=30
100 ?="doko "
110 a=0
120 #=30
130 ?="doko "
140 ?="kiyosi!"
実行結果
.assembly extern mscorlib {}
.assembly zundoko {}
.method static void main() {
.entrypoint
.locals init (class [mscorlib]System.Random r, int32 a, int32 b)
newobj instance void [mscorlib]System.Random::.ctor()
stloc r
ldc.i4 0
stloc a
label_30:
ldloc r
ldc.i4 2
callvirt instance int32 [mscorlib]System.Random::Next(int32)
brfalse label_100
ldstr "zun "
call void [mscorlib] System.Console::WriteLine(string)
ldloc a
ldc.i4 1
add
stloc a
ldloc a
ldc.i4 3
bgt label_130
br label_30
label_100:
ldstr "doko "
call void [mscorlib] System.Console::WriteLine(string)
ldc.i4 0
stloc a
br label_30
label_130:
ldstr "doko "
call void [mscorlib] System.Console::WriteLine(string)
ldstr "kiyosi!"
call void [mscorlib] System.Console::WriteLine(string)
label_255:
ret
}
検証
>ilasm zundoko4.il
Microsoft (R) .NET Framework IL Assembler. Version 4.8.9105.0
Copyright (c) Microsoft Corporation. All rights reserved.
Assembling 'zundoko4.il' to EXE --> 'zundoko4.exe'
Source file is ANSI
Assembled global method main
Creating PE file
Emitting classes:
Emitting fields and methods:
Global Methods: 1;
Emitting events and properties:
Global
Writing PE file
Operation completed successfully
>zundoko4
doko
zun
zun
doko
zun
zun
doko
doko
doko
zun
zun
doko
zun
doko
zun
doko
zun
doko
zun
doko
zun
zun
doko
doko
doko
doko
doko
doko
doko
zun
doko
zun
zun
zun
zun
doko
kiyosi!
成果物
サンプルコード
コンパイラ
function putlp(d) {
val = "";
var n = 0;
while (buf[ptr] != d)
{
val += buf[ptr++];
}
val = '"' + val + '"';
}
function term() {
f = buf[ptr++];
factr2();
return;
}
function term2() {
ff = buf[ptr++];
factr3();
return;
}
function factr3() {
if (buf[ptr] == '\0')
{
return;
}
t = 3;
if (getnm4())
{
return;
}
getvr4();
ptr++;
return;
}
function factr2() {
if (buf[ptr] == '\0')
{
return;
}
t = 2;
if (getnm3())
{
return;
}
getvr3();
ptr++;
return;
}
function factr() {
if (buf[ptr] == '\0')
{
val = 0;
return;
}
if (getnm2())
{
return;
}
t = 1;
getvr2();
ptr++;
return;
}
function expr() {
factr();
if (buf[ptr] != '\0')
{
term();
if (buf[ptr] != '\0')
{
term2();
}
}
ptr++;
return;
}
function getvr4() {
cccc = buf[ptr];
}
function getvr3() {
ccc = buf[ptr];
}
function getvr2() {
cc = buf[ptr];
}
function getvr() {
c = buf[ptr];
}
function ordr() {
getvr();
ptr++;
ptr++;
if (buf[ptr] == '"')
{
t = 2;
ptr++;
putlp('"');
}
else
{
expr();
}
return;
}
function num() {
if (48 <= (buf[ptr]).charCodeAt(0) && (buf[ptr]).charCodeAt(0) <= 57)
return true;
else
return false;
}
function getnm4() {
var ch;
if (!num())
return false;
var n = 0;
do
{
n *= 10;
ch = buf[ptr++];
n += ch.charCodeAt(0) - 48;
} while (num());
val3 = n;
return true;
}
function getnm3() {
var ch;
if (!num())
return false;
var n = 0;
do
{
n *= 10;
ch = buf[ptr++];
n += ch.charCodeAt(0) - 48;
} while (num());
val2 = n;
return true;
}
function getnm2() {
var ch;
if (!num())
return false;
var n = 0;
do
{
n *= 10;
ch = buf[ptr++];
n += ch.charCodeAt(0) - 48;
} while (num());
val = n;
return true;
}
function getnm() {
var ch;
if (!num())
return false;
var n = 0;
do
{
n *= 10;
ch = buf[ptr++];
n += ch.charCodeAt(0) - 48;
} while (num());
lin = n;
return true;
}
var koko = document.getElementById('koko');
var out = document.getElementById('out');
var ptr;
var c;
var cc;
var ccc;
var f;
var val;
var val2;
var buf;
var t;
var lin;
function run() {
var i;
var str = koko.value;
var label = {};
var res = ".assembly extern mscorlib {}\n.assembly zundoko {}\n.method static void main() {\n.entrypoint\n.locals init (class [mscorlib]System.Random r, int32 a, int32 b)\n\tnewobj instance void [mscorlib]System.Random::.ctor()\n\tstloc r\n";
var lines = str.split("\n");
for (i = 0; i < lines.length; i++)
{
var k = lines[i].indexOf(" #=");
if (k > -1)
{
var lin0 = lines[i].substr(k + 3);
k = lin0.indexOf("*");
if (k > -1)
{
label[parseInt(lin0.substr(k + 1))] = 1;
}
else
{
label[parseInt(lin0)] = 1;
}
}
}
for (i = 0; i < lines.length; i++)
{
ptr = 0;
c = null;
cc = null;
val = null;
val2 = null;
t = 0;
lin = 0;
buf = lines[i] + '\0';
getnm();
ptr++;
ordr();
if (label[parseInt(lin)] > 0)
{
res += "label_" + lin + ":\n";
}
if (c == '?')
{
if (t == 1)
{
res += "\tldloc " + cc + "\n\tcall void [mscorlib] System.Console::WriteLine(int32)\n";
}
if (t == 2)
{
res += "\tldstr " + val + "\n\tcall void [mscorlib] System.Console::WriteLine(string)\n";
}
}
else if (c == '#')
{
if (t == 0)
{
res += "\tbr\tlabel_" + val + "\n";
}
if (t == 3)
{
if (cc== 'b')
{
res += "\tbrfalse\tlabel_" + val3 + "\n";
}
if (cc== 'a')
{
res += "\tldloc\ta\n\tldc.i4\t" + val2 + "\n\tbgt\tlabel_" + val3 + "\n";
}
}
}
else if (c == 'a')
{
if (t == 0)
{
res += "\tldc.i4\t" + val + "\n\tstloc\ta\n";
}
if (t == 2)
{
if (f == "+")
f = "add";
res += "\tldloc\t" + cc + "\n\tldc.i4\t" + val2 + "\n\t" + f + "\n\tstloc\ta\n";
}
}
else if (c == 'b')
{
if (cc == "$")
{
res += "\tldloc r\n\tldc.i4 2\n\tcallvirt instance int32 [mscorlib]System.Random::Next(int32)\n";
}
if (t == 2)
{
if (f == "%")
f = "rem";
res += "\tldloc\t" + cc + "\n\tldc.i4\t" + val2 + "\n\t" + f + "\n";
}
}
}
res += "label_255:\n\tret\n}";
out.value = res;
}
以上