ilasmでstack machine その39

# 概要
ilasmでstack machineやってみた。
練習問題やってみた。

# 練習問題
日本語をilasmに変換するコンパイラを書け。
数9を4個つかって1から15までの数を表す式をコンパイルせよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f66d0af1-dc75-30bb-8a92-e229b0aa9867.png)


# 投入したソース

```
d1:
  数値 9 を積み
  数値 9 を積み
  引く
  数値 9 を積み
  数値 9 を積み
  割る
  足す
  数値印字し
d2:
  数値 9 を積み
  数値 9 を積み
  割る
  数値 9 を積み
  数値 9 を積み
  割る
  足す
  数値印字し
d3:
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  数値印字し
d4:
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  数値 9 を積み
  捨てる
  コピペし
  足す
  数値印字し
d5:
  数値 9 を積み
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  コピペし
  足す
  引く
  数値印字し
d6:
  数値 9 を積み
  コピペし
  数値 9 を積み
  足す
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  引く
  数値印字し
d7:
  数値 9 を積み
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  引く
  数値印字し
d8:
  数値 9 を積み
  数値 9 を積み
  数値 9 を積み
  割る
  引く
  数値 9 を積み
  捨てる
  数値印字し
d9:
  数値 9 を積み
  数値 9 を積み
  引く
  数値 9 を積み
  掛ける
  数値 9 を積み
  足す
  数値印字し
d10:
  数値 9 を積み
  数値 9 を積み
  割る
  数値 9 を積み
  足す
  数値 9 を積み
  捨てる
  数値印字し
d11:
  数値 9 を積み
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  足す
  数値印字し
d12:
  数値 9 を積み
  コピペし
  数値 9 を積み
  数値 9 を積み
  足す
  足す
  数値 9 を積み
  割る
  足す
  数値印字し
d13:
  数値 9 を積み
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  コピペし
  足す
  足す
  数値印字し
d14:
  数値 9 を積み
  コピペし
  数値 9 を積み
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  コピペし
  足す
  引く
  足す
  数値印字し
d15:
  数値 9 を積み
  コピペし
  コピペし
  数値 9 を積み
  足す
  数値 9 を積み
  足す
  数値 9 を積み
  割る
  引く
  足す
  数値印字し
  終わり。


```

# 実行結果

```
.assembly extern mscorlib {}
.assembly d94 {}
.method static void main() {
.maxstack 8
.entrypoint
d1:
  ldc.i4   9
  ldc.i4   9
  sub
  ldc.i4   9
  ldc.i4   9
  div
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d2:
  ldc.i4   9
  ldc.i4   9
  div
  ldc.i4   9
  ldc.i4   9
  div
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d3:
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  add
  ldc.i4   9
  div
  call void [mscorlib]System.Console::WriteLine(int32)
d4:
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  div
  ldc.i4   9
  pop
  dup
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d5:
  ldc.i4   9
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  div
  dup
  add
  sub
  call void [mscorlib]System.Console::WriteLine(int32)
d6:
  ldc.i4   9
  dup
  ldc.i4   9
  add
  ldc.i4   9
  add
  ldc.i4   9
  div
  sub
  call void [mscorlib]System.Console::WriteLine(int32)
d7:
  ldc.i4   9
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  div
  sub
  call void [mscorlib]System.Console::WriteLine(int32)
d8:
  ldc.i4   9
  ldc.i4   9
  ldc.i4   9
  div
  sub
  ldc.i4   9
  pop
  call void [mscorlib]System.Console::WriteLine(int32)
d9:
  ldc.i4   9
  ldc.i4   9
  sub
  ldc.i4   9
  mul
  ldc.i4   9
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d10:
  ldc.i4   9
  ldc.i4   9
  div
  ldc.i4   9
  add
  ldc.i4   9
  pop
  call void [mscorlib]System.Console::WriteLine(int32)
d11:
  ldc.i4   9
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  div
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d12:
  ldc.i4   9
  dup
  ldc.i4   9
  ldc.i4   9
  add
  add
  ldc.i4   9
  div
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d13:
  ldc.i4   9
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  div
  dup
  add
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d14:
  ldc.i4   9
  dup
  ldc.i4   9
  ldc.i4   9
  add
  ldc.i4   9
  div
  dup
  add
  sub
  add
  call void [mscorlib]System.Console::WriteLine(int32)
d15:
  ldc.i4   9
  dup
  dup
  ldc.i4   9
  add
  ldc.i4   9
  add
  ldc.i4   9
  div
  sub
  add
  call void [mscorlib]System.Console::WriteLine(int32)
  ret
}

```

# 検証

```
>ilasm d9.il

Microsoft (R) .NET Framework IL Assembler.  Version 4.8.9105.0
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'd9.il'  to EXE --> 'd9.exe'
Source file is UTF-8

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

>d9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

```

# 成果物

https://embed.plnkr.co/plunk/S1CIJBc5ewIpUdxw

# サンプルコード
コンパイラ

```

var out = document.getElementById("out");
var src = document.getElementById("src"); 

function run() {
  var str = src.value;
  str = str.replace(/\t/g, " ");
  str = str.replace(/  /g, " ");
  str = str.replace(/  /g, " ");
  str = str.replace(/  /g, " ");
  var codes = str.split("\n");  
  var pc = 0;  
  var i = 1;
  var res = ".assembly extern mscorlib {}\n.assembly d94 {}\n.method static void main() {\n.maxstack 8\n.entrypoint\n";
  while (i > 0)
  {
    var code = codes[pc].split(" ");
    switch (code[1])
    {
    case "入力し":  
      res += "  call string [mscorlib]System.Console::ReadLine()\n";
      pc++;
    break;
    case "乱数召喚し":  
      res += "  newobj instance void [mscorlib]System.Random::.ctor()\n";
      pc++;
    break;
    case "文字列":
      res += "  ldstr    " + code[2] + "\n";
      pc++;
    break;
    case "数値":
      res += "  ldc.i4   " + code[2] + "\n";
      pc++;
    break;
    case "変数":   
      if (code[3] == "を積み")
        res += "  ldloc    " + code[2] + "\n";
      if (code[3] == "に移動し")
        res += "  stloc    " + code[2] + "\n";
      pc++;
    break; 
    case "数値印字し":
      res += "  call void [mscorlib]System.Console::WriteLine(int32)\n";
      pc++;
    break;
    case "文字印字し":
      res += "  call void [mscorlib]System.Console::Write(string)\n";
      pc++;
    break;
    case "文字列印字し":
      res += "  call void [mscorlib]System.Console::WriteLine(string)\n";
      pc++;
    break;
    case "真なら": 
      res += "  brtrue   "+ code[2] + "\n";
      pc++;
    break;
    case "偽なら": 
      res += "  brfalse  "+ code[2] + "\n";
      pc++;
    break;      
    case "比べて大なら":  
      res += "  bgt      "+ code[2] + "\n";
      pc++;
    break;
    case "捨てる":  
      res += "  pop\n";
      pc++;
    break;
    case "コピペし":  
      res += "  dup\n";
      pc++;
    break;
    case "足す":  
      res += "  add\n";
      pc++;
    break;
    case "掛ける":  
      res += "  mul\n";
      pc++;
    break;
    case "引く":  
      res += "  sub\n";
      pc++;
    break;
    case "割る":  
      res += "  div\n";
      pc++;
    break;
    case "剰余し":  
      res += "  rem\n";
      pc++;    
    break;
    case "乱数し":  
      res += "  callvirt instance int32 [mscorlib]System.Random::Next(int32)\n";
      pc++;    
    break;
    case "長さし":  
      res += "  callvirt instance int32 [mscorlib]System.String::get_Length()\n";
      pc++;    
    break;
    case "切り出し":  
      res += "  callvirt instance string [mscorlib]System.String::Substring(int32, int32)\n";
      pc++;    
    break;
    case "無条件で": 
      res += "  br       "+ code[2] + "\n";
      pc++;
    break;
    case "終わり。":  
      res += "  ret\n}\n";
      i = 0;
    break;
    case undefined:
      res += code[0] + "\n";
      pc++;
    break;
    default:
      alert(code[1]);
      pc++;
    break;
    }
  }
  out.value = res;
}




```


以上