Langage ésotérique LMCode

Partie I
Partie II
Partie III
Partie IV
Partie V

Cet article est consacré à la création d'un interprète d'un certain langage ésotérique LMCode , basé sur l'architecture de Little Man Computer .
En fait, il s'agit d'un émulateur assembleur pour LMC , uniquement ici au lieu des commandes assembleur INP, STA, ADD, SUB, OUT, des commandes spéciales sont utilisées. caractères.
Pour charger le nombre dans la mémoire des commandes command_mem , des transitions de commande en commande, et également pour sortir le résultat, des commandes brainfuck sont utilisées.

  • Laissez la commande INP correspondre
  • La commande OUT correspond .
  • La commande ADD correspond à +
  • la sous- commande correspond à -
  • La commande STA correspond à ~
  • La commande LDA correspond à ^

Nous écrivons un programme qui charge un nombre du périphérique d'entrée dans la batterie, enregistre le nombre dans la mémoire, ajoute le nombre de la mémoire à la batterie (double le nombre) et sort le nombre doublé vers le périphérique de sortie.

Dans l'assembleur LMC, ce programme ressemblera à ceci (que la cellule initiale soit 20)

INP STA 20 ADD 20 OUT 


Dans LMCode, ce programme ressemblera à ~ +.
Dans notre machine LMCode, la mémoire de code et la mémoire de données sont séparées (architecture Harvard), nous allons créer la ligne command_mem pour charger le code LMCode. La chaîne command_mem représentera la mémoire des commandes. Nous créons également un tableau de données data_mem qui représentera la mémoire de données.

Nous chargeons le programme dans 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; } 

Lors du chargement du nombre 123 dans le périphérique d'entrée, nous obtenons le nombre 246 .
Vous pouvez vérifier dans oline ide ideone.com

Ajouter des commandes pour

  • aller à la cellule suivante >
  • aller à la cellule précédente <

Lors du traitement du symbole > nous augmenterons l'indice j du tableau de données data_mem

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

Lors du traitement du symbole <, nous diminuerons l'indice j du tableau de données data_mem

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

Pour sauter sur commande ? Nous allons effectuer la transition vers le label !
Pour ce faire, nous allons sauter tous les caractères entre ? et !

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

À titre de comparaison, nous écrivons un programme dans lequel l'utilisateur entre un nombre, par exemple 5 , avec une commande , dans cinq cellules d'affilée avec des commandes
~> ~> ~> ~> ~
 #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; } 

En conséquence, nous obtenons un tableau 5 5 5 5 5 0 0 0 0 0 0
ideone.com

et le même programme dans lequel plusieurs pas en avant sont sautés par la commande de saut inconditionnel , ~> ~?> ~> ~> ~!

On obtient un tableau 5 5 0 0 0 0 0 0 0 0 0 0
ideone.com

Ajouter le drapeau pzflag PositiveZero-flag

Le drapeau ne sera levé que si le nombre dans la batterie est supérieur ou égal à zéro.

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

En poursuivant par la condition pzflag == 1 nous exécuterons les commandes { et }

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


Ensuite, laissez deux nombres être stockés dans notre mémoire
data_mem [0] = 3 et data_mem [1] = 5
Nous allons écrire un programme qui affiche le nombre maximum.

 #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

Pour revenir en arrière, ajoutez la variable pz_prev .

Si le caractère actuel est { , alors "lever le drapeau" pz_prev

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

Si l'étiquette } précède la commande { , alors vous devez revenir en arrière

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

Nous allons écrire un programme qui affiche des nombres pairs de 10 à 0 .

Nous chargeons les nombres 10 et 2 dans le tableau data_mem , puis, tandis que le nombre dans acc est supérieur ou égal à zéro, nous soustraireons 2 de 10 et afficherons le résultat

 #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

Afin de multiplier deux nombres A et B , vous devez ajouter B fois A à B.

Dans la boucle, à chaque itération, nous soustraireons un à A et, alors que A n'est pas nul, ajouter B à B.

Programme LMCode } >>> ^ <+> ~ <<< ^> - <~ {>>> ^. multiplie les nombres A + 1 et B , c'est-à-dire un facteur doit être délibérément réduit d'un.

En effet, la boucle ne se terminera que lorsque -1 est en acc .

Par exemple, multipliez 5 par 5 .

Pour ce faire, placez d'abord les valeurs nécessaires dans data_mem

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

ideone.com

Ajoutez des sauts inconditionnels en arrière .

Pour ce faire, ajoutez la variable prev .

Nous ajoutons également des transitions avant / arrière sous la condition acc = 0 . Pour de telles transitions, créez l'indicateur zflag (ZeroFlag) et la variable z_prev .

Les transitions par la condition zflag == 1 seront effectuées par des commandes ( et )
On multiplie 5 et 5 en utilisant la transition inconditionnelle et la transition selon la condition zflag == 1 .

Placez d'abord les valeurs nécessaires dans data_arr
  data_arr[0]=5; data_arr[1]=1; data_arr[2]=5; 

Programme LMCode ! >>> ^ <+> ~ <<< ^> - <~ (?) >>> ^. correspond au programme assembleur
  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 

Code 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

En général, les drapeaux n'ont pas pu être créés, mais au lieu de cela, vérifiez immédiatement à quoi correspond le nombre dans la batterie.

Vérifions comment les nombres de Fibonacci sont calculés.
 #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

J'ai posté une note sur le langage LMCode sur esolang.org ici

PS Un article sur l'émulateur assembleur pour Intel-4004 pour le divertissement ici

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


All Articles