GAME言語コンパイラ to C on python3 'miep2.py'

GAME言語からCへ変換するコンパイラをpythonで書いてみました。

GAME言語コンパイラ -  miep2.py

厳密に言うとトランスパイラですが、出力されたCのソースはccでコンパイルして実行ファイルにすることが可能なので、コンパイラとしておきます。

`./miep2.py file.gm >out.c`とすると、GAME言語で書かれたfile.gmをCのソースに変換し、out.cに出力します。

本当はMIEP2ではなく、MIEPにしたいのですが、MIEPという名前は、1982年に中学生の僕と師匠の浜田さんがMicro Integer Expression Processorとして、自作のゲーム言語互換インタプリタ・コンパイラシステムに既に名付けていたので、2が付きました。

out.cはccでコンパイル可能です。 `cc out.c -o a.out`、`./a.out`で実行することが出来ます。

一般に冗長さを許せば、低級なプログラム言語で書かれたソースは、より高級なプログラム言語に翻訳することが容易です。

C言語はチューリング完全です。GAME言語はチューリング完全かどうかですが、brainfuckがチューリング完全で、GAME言語でbrainfuckの全てのインストラクションが記述できるので、GAME言語もチューリング完全です。

最適化はできていません。エラーチェックが甘いです。
ccのインラインアセンブラを使用しているので、x86_64 linuxシステム用です。
!=n(gosub)と] (ret) が機械依存部で、それ以外は機械独立です。完全に機械独立にし、一般のCコンパイラに掛けることができるようにすることが今後の課題ですが、C言語の仕様上、サブルーチン呼び出しを記述するのは難しいかも知れません。

一応完成　version 1.0.0 2024/8/26
ちょっとヴァージョンアップ、改名。　version 1.0.1 2024/8/27
剰余結果取得のバグ修正 version 1.0.2 2025/04/11

# 今後の課題の問題点

・for-next,do-untl文の、for文またはdo文一つに対して複数のnext文、until文がある場合には対応していません。
・for-next文の制御変数に配列が使えない
・for文の終値に変数を使うと、カウントアップとして扱われる。
・next文に２重以上の括弧があるとバグる。

# 本体 'miep2.py'

https://gist.github.com/fygar256/02506c7078f54d17e0a3466390b502dc

# サンプルプログラム 素数発生

```sieve.gm
#!/usr/bin/gamec
1*** sieve.gm エラトステネスの篩により素数を求めるプログラム
2*** アルゴリズムは、「C言語による標準アルゴリズム事典」奥村晴彦著によります。
6*** 
10  "Primes up to " M=? N=(M-3)/2
20  F=0
100  C=1
110  "2 "
120  J=0,N F:J)=1 @=J+1
150  J=0,N
160     ;=#F:J) #=200
170         P=J*2+3
175         Z=P !=230
180         ;=J+P<=N K=J+P,N F:K)=0 @=K+P
190         C=C+1
200  @=J+1
210 / ?=C " PRIMES" /
220 #=-1
230 ?=Z " " ]

```
# コンパイル後のコード

```sieve.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static short A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z;
static unsigned char memory[65536]={0};
static int tmp,reminder;
static char buff[100]={0};
int ia(char *s,int v) {if (v){int i=0,r;for(r=v;r/=10;i++);ia(s,v/10);s[i++]=v%10+48;s[i]=0;}}
void pretprt(short c,short v) {
ia(buff,v); 
for(short j=0;j<c-strlen(buff);j++) printf(" "); 
printf(buff); 
}
void main() {
l10: printf("Primes up to "); M=(scanf("%d",&tmp),(short)tmp);N=((reminder=((M-3))%2),(((M-3))/2));
l20: F=0;
l100: C=1;
l110: Z=2;__asm__ goto("call %l[l230]" : : : :l230); 
l120: J=0;while(1) { if (!(J<=N)) break; memory[F+J]=1; J=(J+1); } 
l150: J=0;while(1) { if (!(J<=N)) break; 
l160: if (!(!(memory[F+J]))) goto l170; goto l200; 
l170: P=((J*2)+3);
l175: Z=P;__asm__ goto("call %l[l230]" : : : :l230); 
l180: if (!(((J+P)<=N))) goto l190; K=(J+P);while(1) { if (!(K<=N)) break; memory[F+K]=0; K=(K+P); } 
l190: C=(C+1);
l200: J=(J+1); } 
l210: printf("\n"); printf("%d",C); printf(" PRIMES"); printf("\n"); 
l220: return; 
l230: pretprt((short)4,(short)Z); printf(" "); __asm__ ("ret" : : :); 
}
```

# 実行結果

```
$ ./miep2.py sieve.gm >t.c
$ cc t.c
$ ./a.out
Primes up to 1000
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997 
168 PRIMES
$ 
```

# 一言

僕はもう、疲労困憊らです。

# 参考文献など

ゲーム言語ドキュメント
コンパイラ構成論　近代科学社