Esoterische Sprache LMCode

Teil I.
Teil II
Teil III
Teil iv
Teil v

Dieser Artikel befasst sich mit der Erstellung eines Interpreters einer bestimmten esoterischen Sprache LMCode , die auf der Architektur von Little Man Computer basiert.
Tatsächlich ist dies ein Assembler-Emulator für LMC , nur hier werden anstelle der Assembler-Befehle INP, STA, ADD, SUB, OUT spezielle verwendet. Zeichen.
Um die Nummer in den Speicher der Befehle command_mem zu laden, von Befehl zu Befehl zu wechseln und das Ergebnis auszugeben, werden Brainfuck- Befehle verwendet.

  • Lassen Sie den INP- Befehl übereinstimmen
  • Der OUT- Befehl entspricht .
  • Der Befehl ADD entspricht +
  • Der Unterbefehl entspricht -
  • Der STA- Befehl entspricht ~
  • Der LDA- Befehl entspricht ^

Wir schreiben ein Programm, das eine Nummer vom Eingabegerät in die Batterie lädt, die Nummer im Speicher speichert, die Nummer aus dem Speicher zur Batterie hinzufügt (die Nummer verdoppelt) und die doppelte Nummer an das Ausgabegerät ausgibt.

In Assembler LMC sieht dieses Programm folgendermaßen aus (die anfängliche Zelle sei 20).

INP STA 20 ADD 20 OUT 


In LMCode sieht dieses Programm wie folgt aus : ~ +.
In unserer LMCode-Maschine sind der Codespeicher und der Datenspeicher getrennt (Harvard-Architektur). Wir erstellen die Zeile command_mem , um den LMCode-Code zu laden. Die Zeichenfolge command_mem repräsentiert den Speicher der Befehle. Wir erstellen auch ein data_mem-Datenarray , das den Datenspeicher darstellt.

Wir laden das Programm in 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; } 

Beim Laden der Nummer 123 in das Eingabegerät erhalten wir die Nummer 246 .
Sie können in oline ide ideone.com einchecken

Befehle hinzufügen für

  • gehe zur nächsten Zelle >
  • gehe zur vorherigen Zelle <

Bei der Verarbeitung des Symbols > erhöhen wir den Index j des Datenarrays data_mem

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

Bei der Verarbeitung des Symbols < verringern wir den Index j des Datenarrays data_mem

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

Auf Befehl vorwärts springen ? Wir werden den Übergang zum Label machen !
Dazu überspringen wir alle Zeichen zwischen ? und !

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

Zum Vergleich schreiben wir ein Programm, in dem der Benutzer eine Zahl, zum Beispiel 5 , mit einem Befehl in fünf Zellen hintereinander mit Befehlen eingibt
~> ~> ~> ~> ~
 #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; } 

Als Ergebnis erhalten wir ein Array 5 5 5 5 5 0 0 0 0 0 0
ideone.com

und dasselbe Programm, in dem mehrere Schritte vorwärts durch den bedingungslosen Sprungbefehl ~> ~?> ~> ~> ~ übersprungen werden !

Wir erhalten ein Array 5 5 0 0 0 0 0 0 0 0 0 0
ideone.com

Fügen Sie das pzflag- Flag PositiveZero-flag hinzu

Das Flag wird nur gehisst, wenn die Zahl in der Batterie größer oder gleich Null ist.

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

Unter der Bedingung pzflag == 1 werden wir die Befehle { und } ausführen.

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


Als nächstes sollen zwei Zahlen in unserem Speicher gespeichert werden
data_mem [0] = 3 und data_mem [1] = 5
Wir werden ein Programm schreiben, das die maximale Anzahl anzeigt.

 #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

Um zurückzuspringen, fügen Sie die Variable pz_prev hinzu .

Wenn das aktuelle Zeichen {ist , dann " hisse das Flag" pz_prev

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

Wenn die Bezeichnung } vor dem Befehl {steht , müssen Sie zurückspringen

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

Wir werden ein Programm schreiben, das gerade Zahlen von 10 bis 0 anzeigt.

Wir laden die Zahlen 10 und 2 in das Array data_mem . Während die Zahl in acc größer oder gleich Null ist, subtrahieren wir 2 von 10 und zeigen das Ergebnis an

 #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

Um zwei Zahlen A und B zu multiplizieren, müssen Sie B mal A zu B addieren .

In der Schleife subtrahieren wir bei jeder Iteration eins von A und addieren B zu B, während A nicht Null ist.

LMCode-Programm } >>> ^ <+> ~ <<< ^> - <~ {>>> ^. multipliziert die Zahlen A + 1 und B , d.h. Ein Faktor muss bewusst um eins reduziert werden.

Dies liegt daran, dass die Schleife nur endet, wenn -1 gem .

Multiplizieren Sie beispielsweise 5 mit 5 .

Platzieren Sie dazu zunächst die erforderlichen Werte in data_mem

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

ideone.com

Fügen Sie bedingungslose Sprünge zurück .

Fügen Sie dazu die Variable prev hinzu .

Wir fügen auch Vorwärts- / Rückwärtsübergänge unter der Bedingung acc = 0 hinzu . Erstellen Sie für solche Übergänge das zflag- Flag (ZeroFlag) und die Variable z_prev .

Übergänge durch die Bedingung zflag == 1 werden durch Befehle ( und ) ausgeführt.
Wir multiplizieren 5 und 5 mit dem unbedingten Übergang und dem Übergang gemäß der Bedingung zflag == 1 .

Platzieren Sie zuerst die erforderlichen Werte in data_arr
  data_arr[0]=5; data_arr[1]=1; data_arr[2]=5; 

LMCode-Programm ! >>> ^ <+> ~ <<< ^> - <~ (?) >>> ^. entspricht dem Assembler-Programm
  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 

C-Code
 #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

Im Allgemeinen konnten keine Flags erstellt werden, sondern überprüfen sofort, wie hoch die Nummer in der Batterie ist.

Lassen Sie uns überprüfen, wie die Fibonacci-Zahlen berechnet werden.
 #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

Ich habe hier auf esolang.org einen Hinweis zur LMCode- Sprache veröffentlicht

PS Ein Artikel über den Assembler-Emulator für Intel-4004 zur Unterhaltung hier

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


All Articles