LMCode bahasa Esoterik

Bagian I
Bagian II
Bagian III
Bagian iv
Bagian v

Artikel ini dikhususkan untuk membuat juru bahasa dari beberapa bahasa LMCode esoterik, yang didasarkan pada arsitektur Little Man Computer .
Sebenarnya, ini adalah emulator assembler untuk LMC , hanya di sini alih-alih perintah assembler INP, STA, ADD, SUB, OUT, yang khusus digunakan. karakter.
Untuk memuat nomor ke dalam memori perintah command_mem , transisi dari perintah ke perintah, dan juga untuk menghasilkan hasilnya, perintah brainfuck digunakan.

  • Biarkan perintah INP cocok
  • Perintah OUT sesuai .
  • Perintah ADD sesuai dengan +
  • perintah sub berhubungan dengan -
  • Perintah STA berhubungan dengan ~
  • Perintah LDA sesuai dengan ^

Kami menulis sebuah program yang memuat nomor dari perangkat input ke dalam baterai, menyimpan nomor dalam memori, menambahkan nomor dari memori ke baterai (menggandakan nomor), dan menampilkan nomor dua kali lipat ke perangkat output.

Dalam assembler LMC, program ini akan terlihat seperti ini (biarkan sel awal menjadi 20)

INP STA 20 ADD 20 OUT 


Dalam LMCode, program ini akan terlihat seperti , ~ +.
Di mesin LMCode kami, memori kode dan memori data dipisahkan (arsitektur Harvard), kami akan membuat baris command_mem untuk memuat kode LMCode. String command_mem akan merepresentasikan memori dari perintah. Kami juga membuat larik data data_mem yang akan mewakili memori data.

Kami memuat program ke command_mem , ~ +.

 #include <stdio.h> int main(void) { int i=0; //    int j=0; //    int acc = 0; // char command_mem[100] = ",~+."; //  int data_mem[10]={0}; //   while (command_mem[i] != '\0') { if (command_mem[i]==',') //     scanf("%d", &acc); if (command_mem[i]=='+') //    data_mem acc=acc+data_mem[j]; //   if (command_mem[i]=='~') //     data_mem[j]=acc; //    if (command_mem[i]=='.') //       printf("Output: %d",acc); i++; //    } //    printf("\n"); //    for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; } 

Saat memuat nomor 123 ke perangkat input, kami mendapatkan nomor 246 .
Anda dapat memeriksa di oline ide ideone.com

Tambahkan perintah untuk

  • buka sel selanjutnya >
  • buka sel sebelumnya <

Saat memproses simbol > kita akan meningkatkan indeks j dari array data data_mem

 if(command_mem[i]=='>') j++; 

Saat memproses simbol <, kita akan mengurangi indeks j dari data_mem array data

 if(command_mem[i]=='<') j--; 

Untuk melompat maju pada perintah ? Kami akan melakukan transisi ke label !
Untuk melakukan ini, kita akan melewati semua karakter di antara ? dan !

 if(command_mem[i]=='?') { while(command_mem[i] != '!' ) { i++; } } 

Sebagai perbandingan, kami menulis program di mana pengguna memasukkan angka, misalnya 5 , dengan perintah , menjadi lima sel berturut-turut dengan perintah
~> ~> ~> ~> ~
 #include <stdio.h> int main(void) { int i=0; //    int j=0; //    int acc = 0; // char command_mem[100] = ",~>~>~>~>~"; //  int data_mem[10]={0}; //   while (command_mem[i] != '\0') { if (command_mem[i]==',') //     scanf("%d", &acc); if (command_mem[i]=='+') //    data_mem acc=acc+data_mem[j]; //   if (command_mem[i]=='~') //     data_mem[j]=acc; //    if (command_mem[i]=='.') //       printf("Output: %d",acc); if(command_mem[i]=='>') //     j++; if(command_mem[i]=='<') //     j--; if(command_mem[i]=='?') { //    ! while(command_mem[i] != '!') i++; } i++; //    } //    printf("\n"); //    for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; } 

Hasilnya, kami mendapatkan array 5 5 5 5 5 0 0 0 0 0 0
ideone.com

dan program yang sama di mana beberapa langkah maju dilewati oleh perintah lompatan tanpa syarat , ~> ~?> ~> ~> ~!

Kami mendapatkan array 5 5 0 0 0 0 0 0 0 0 0
ideone.com

Tambahkan pzflag flag PositiveZero-flag

Bendera hanya akan dinaikkan jika angka dalam baterai lebih besar atau sama dengan nol.

  if(acc>=0){ pzflag=1;} else { pzflag=0;} 

Melangkah kedepan dengan syarat pzflag == 1 kita akan menjalankan perintah { dan }

 if(command_mem[i]=='{') && (pzflag==1){ while(command_mem[i] != '}' ) i++; } 


Selanjutnya, biarkan dua angka disimpan dalam memori kita
data_mem [0] = 3 dan data_mem [1] = 5
Kami akan menulis sebuah program yang menampilkan angka maksimum.

 #include <stdio.h> int main(void) { int i=0; //    int j=0; //    int acc = 0; int pzflag = 1; //  acc>=0 char command_mem[100] = "^>-{^?}<^!."; //  int data_mem[10]={0}; data_mem[0]=3; //   data_mem[1]=5; while ( command_mem[i] != '\0') { if(command_mem[i]==',') //     scanf("%d", &acc); if(command_mem[i]=='+') //    data_mem acc=acc+data_mem[j]; //   if(command_mem[i]=='-') //   data_mem acc=acc-data_mem[j]; //   if(command_mem[i]=='>') //      j++; if(command_mem[i]=='<') //     j--; if(command_mem[i]=='~') //     data_mem[j]=acc; //    if(command_mem[i]=='^') //    data_mem acc=data_mem[j]; //   if(command_mem[i]=='.') { //       printf("Output: %d",acc); printf(" "); }; if(command_mem[i]=='?') { //    ! while(command_mem[i] != '!') i++; } if (command_mem[i]=='{' && pzflag==1) { //    acc>=0 while(command_mem[i] != '}') i++; } if(acc>=0){ //  ,  acc>=0 pzflag=1; } else { pzflag=0; } i++; //    } //    printf("\n"); //    for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; } 

ideone.com

Untuk melompat kembali, tambahkan pz_prev variabel.

Jika karakter saat ini adalah { , maka "menaikkan bendera" pz_prev

 if (command_mem[i]=='}') pz_prev=1; 

Jika label } mendahului perintah { , maka Anda perlu melompat kembali

 if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; } 

Kami akan menulis sebuah program yang menampilkan angka genap dari 10 hingga 0 .

Kami memuat angka 10 dan 2 ke dalam array data_mem , kemudian, sementara angka dalam acc lebih besar atau sama dengan nol, kami akan mengurangi 2 dari 10 dan menampilkan hasilnya

 #include <stdio.h> int main(void) { int i=0; //    int j=0; //    int acc = 0; int pzflag = 1; //  acc>=0 int pz_prev=0; //     acc>=0 char command_mem[100] = "}^.>-<~{"; //     10  0 int data_mem[10]={0}; data_mem[0]=10; //   data_mem[1]=2; while ( command_mem[i] != '\0') { if(command_mem[i]==',') //     scanf("%d", &acc); if(command_mem[i]=='+') //    data_mem acc=acc+data_mem[j]; //   if(command_mem[i]=='-') //   data_mem acc=acc-data_mem[j]; //   if(command_mem[i]=='>') //      j++; if(command_mem[i]=='<') //      j--; if(command_mem[i]=='~') //     data_mem[j]=acc; //    if(command_mem[i]=='^') //    data_mem acc=data_mem[j]; //   if(command_mem[i]=='.') { //       printf("Output: %d",acc); printf(" "); }; if (command_mem[i]=='}') //  ? pz_prev=1; if(command_mem[i]=='?') { //    ! while(command_mem[i] != '!') i++; } if (command_mem[i]=='{' && pzflag==1 && pz_prev==0) { //   while(command_mem[i] != '}') //   acc>=0 i++; } if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { //   while(command_mem[i] != '}') //   acc>=0 i--; } if(acc>=0){ //  ,  acc>=0 pzflag=1;} else { pzflag=0;} //printf("i=%d",i);printf(" "); i++; //    } //    printf("\n"); //    for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; } 

ideone.com

Untuk mengalikan dua angka A dan B , Anda harus menambahkan B kali A ke B.

Dalam loop, pada setiap iterasi, kita akan mengurangi satu dari A , dan, sementara A tidak nol, tambahkan B ke B.

Program LMCode } >>> ^ <+> ~ <<< ^> - <~ {>>> ^. mengalikan angka A +1 dan B , yaitu satu faktor harus sengaja dikurangi satu.

Ini karena loop hanya akan berakhir ketika -1 dalam acc .

Misalnya, kalikan 5 dengan 5 .

Untuk melakukan ini, pertama tempatkan nilai yang diperlukan dalam data_mem

  data_mem[0]=4; data_mem[1]=1; data_mem[2]=5; 

ideone.com

Tambahkan lompatan tanpa syarat kembali .

Untuk melakukan ini, tambahkan variabel prev .

Kami juga menambahkan transisi maju / mundur dalam kondisi acc = 0 . Untuk transisi seperti itu, buat bendera zflag (ZeroFlag) dan variabel z_prev .

Transisi dengan syarat zflag == 1 akan dilakukan oleh perintah ( dan )
Kami mengalikan 5 dan 5 menggunakan transisi tanpa syarat dan transisi sesuai dengan kondisi zflag == 1 .

Pertama tempatkan nilai yang diperlukan dalam data_arr
  data_arr[0]=5; data_arr[1]=1; data_arr[2]=5; 

Program LMCode ! >>> ^ <+> ~ <<< ^> - <~ (?) >>> ^. sesuai dengan program assembler
  INP STA 20 INP STA 21 INP STA 22 LDA 23 ADD 22 STA 23 LDA 20 SUB 21 STA 20 BRZ 14 BRA 06 LDA 23 OUT HLT 

Kode C
 #include <stdio.h> int main(void) { int i=0; //    int j=0; //    int acc = 0; int pzflag = 1; //  acc>=0 int zflag =1; //  acc==0 int pz_prev=0; //     acc>=0 int z_prev=0; //     acc==0 int prev=0; //    char command_mem[100] ="!>>>^<+>~<<<^>-<~(?)>>>^."; int data_mem[10]={0}; data_mem[0]=5; //   data_mem[1]=1; data_mem[2]=5; while ( command_mem[i] != '\0') { if(command_mem[i]==',') //     scanf("%d", &acc); if(command_mem[i]=='+') //    data_mem acc=acc+data_mem[j]; //   if(command_mem[i]=='-') //   data_mem acc=acc-data_mem[j]; //   if(command_mem[i]=='>') //      j++; if(command_mem[i]=='<') //      j--; if(command_mem[i]=='~') //     data_mem[j]=acc; //    if(command_mem[i]=='^') //    data_mem acc=data_mem[j]; //   if(command_mem[i]=='.') { //       printf("Output: %d",acc); printf(" "); }; if (command_mem[i]=='}') //  ? pz_prev=1; if (command_mem[i]==')') //  ? z_prev=1; if (command_mem[i]=='!') //  ? prev=1; //    if (command_mem[i]=='?' && prev==0) { while(command_mem[i] != '!') i++; } //    if (command_mem[i]=='?' && prev==1) { while(command_mem[i] != '!') i--; } //     acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==0) { while(command_mem[i] != ')') i++; } //     acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==1) { while(command_mem[i] != ')') i--; } //     acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==0) { while(command_mem[i] != '}') i++; } //     acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; } //  if(acc>=0){ pzflag=1;} else { pzflag=0;} if(acc==0){ zflag=1;} else { zflag=0;} //printf("i=%d",i);printf(" "); i++; //    } //    printf("\n"); //    for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; } 

ideone.com

Secara umum, bendera tidak dapat dibuat, tetapi sebagai ganti mereka segera memeriksa apa nomor dalam baterai sama dengan.

Mari kita periksa bagaimana angka Fibonacci dihitung.
 #include <stdio.h> int main(void) { int i=0; //    int j=0; //    int acc = 0; int pzflag = 1; //  acc>=0 int zflag =1; //  acc==0 int pz_prev=0; //     acc>=0 int z_prev=0; //     acc==0 int prev=0; //    char command_mem[100] ="}>>^>+.~<+.~<<^>-<~{"; int data_mem[10]={0}; data_mem[0]=5; //   data_mem[1]=1; data_mem[2]=1; while ( command_mem[i] != '\0') { if(command_mem[i]==',') //     scanf("%d", &acc); if(command_mem[i]=='+') //    data_mem acc=acc+data_mem[j]; //   if(command_mem[i]=='-') //   data_mem acc=acc-data_mem[j]; //   if(command_mem[i]=='>') //      j++; if(command_mem[i]=='<') //      j--; if(command_mem[i]=='~') //     data_mem[j]=acc; //    if(command_mem[i]=='^') //    data_mem acc=data_mem[j]; //   if(command_mem[i]=='.') { //       printf("Output: %d",acc); printf(" "); }; if (command_mem[i]=='}') //  ? pz_prev=1; if (command_mem[i]==')') //  ? z_prev=1; if (command_mem[i]=='!') //  ? prev=1; //    if (command_mem[i]=='?' && prev==0) { while(command_mem[i] != '!') i++; } //    if (command_mem[i]=='?' && prev==1) { while(command_mem[i] != '!') i--; } //     acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==0) { while(command_mem[i] != ')') i++; } //     acc=0 if (command_mem[i]=='(' && zflag==1 && z_prev==1) { while(command_mem[i] != ')') i--; } //     acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==0) { while(command_mem[i] != '}') i++; } //     acc>=0 if (command_mem[i]=='{' && pzflag==1 && pz_prev==1) { while(command_mem[i] != '}') i--; } //  if(acc>=0){ pzflag=1;} else { pzflag=0;} if(acc==0){ zflag=1;} else { zflag=0;} //printf("i=%d",i);printf(" "); i++; //    } //    printf("\n"); //    for (int k = 0; k<10; k++) printf("%d ", data_mem[k]); return 0; } 

ideone.com

Saya memposting catatan tentang bahasa LMCode di esolang.org di sini

PS Artikel tentang emulator assembler untuk Intel-4004 untuk hiburan di sini

Source: https://habr.com/ru/post/id427629/


All Articles