اللغة الباطنية LMCode

الجزء الأول
الجزء الثاني
الجزء الثالث
الجزء الرابع
الجزء الخامس

تم تخصيص هذه المقالة لإنشاء مترجم للغة مقصورة معينة على LMCode ، والتي تعتمد على بنية كمبيوتر الرجل الصغير .
في الواقع ، هذا هو محاكي المجمع لـ LMC ، فقط هنا بدلاً من أوامر التجميع INP ، STA ، ADD ، SUB ، OUT ، يتم استخدام أوامر خاصة. الشخصيات.
لتحميل الرقم في ذاكرة أوامر command_mem ، والانتقال من أمر إلى أمر ، وكذلك لإخراج النتيجة ، يتم استخدام أوامر mindfuck .

  • دع الأمر INP يطابق
  • يتوافق الأمر OUT .
  • يتوافق الأمر ADD مع +
  • يتوافق الأمر الفرعي مع -
  • أمر STA يتوافق مع ~
  • أمر LDA يتوافق مع ^

نكتب برنامجًا يقوم بتحميل رقم من جهاز الإدخال في البطارية ، ويحفظ الرقم في الذاكرة ، ويضيف الرقم من الذاكرة إلى البطارية (يضاعف الرقم) ، ويخرج الرقم المضاعف إلى جهاز الإخراج.

في أداة التجميع LMC ، سيبدو هذا البرنامج بهذا الشكل (دع الخلية الأولى تكون 20)

INP STA 20 ADD 20 OUT 


في LMCode ، سيبدو هذا البرنامج ، ~ +.
في جهاز LMCode الخاص بنا ، يتم فصل ذاكرة الكود وذاكرة البيانات (بنية هارفارد) ، وسوف نقوم بإنشاء سطر command_mem لتحميل رمز LMCode. تمثل السلسلة command_mem ذاكرة الأوامر. نقوم أيضًا بإنشاء مجموعة بيانات data_mem تمثل ذاكرة البيانات.

نقوم بتحميل البرنامج في 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; } 

عند تحميل الرقم 123 في جهاز الإدخال ، نحصل على الرقم 246 .
يمكنك التحقق في oline ide ideone.com

إضافة أوامر لـ

  • انتقل إلى الخلية التالية >
  • انتقل إلى الخلية السابقة <

عند معالجة الرمز > سنزيد الفهرس j لصفيف البيانات data_mem

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

عند معالجة الرمز سنقوم بتقليل الفهرس j لصفيف البيانات data_mem

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

للقفز إلى الأمام في الأمر ؟ سنقوم بالانتقال إلى الملصق !
للقيام بذلك ، سوف نتخطى جميع الشخصيات بينهما ؟ و !

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

للمقارنة ، نكتب برنامجًا يدخل فيه المستخدم رقمًا ، على سبيل المثال 5 ، بأمر ، إلى خمس خلايا متتالية مع أوامر
~> ~> ~> ~> ~
 #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; } 

نتيجة لذلك ، نحصل على صفيف 5 5 5 5 5 0 0 0 0 0 0
ideone.com

ونفس البرنامج الذي يتم فيه تخطي عدة خطوات للأمام بواسطة أمر القفز غير المشروط ، ~> ~؟> ~> ~> ~!

نحصل على صفيف 5 5 0 0 0 0 0 0 0 0 0
ideone.com

قم بإضافة علامة pzflag لعلامة إيجابية

سيتم رفع العلم فقط إذا كان الرقم في البطارية أكبر من أو يساوي الصفر.

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

بالمضي قدمًا بالحالة pzflag == 1 ، سننفذ الأوامر { و }

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


بعد ذلك ، اسمح بتخزين رقمين في ذاكرتنا
data_mem [0] = 3 و data_mem [1] = 5
سنكتب برنامجًا يعرض العدد الأقصى.

 #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

للقفز مرة أخرى ، أضف المتغير pz_prev .

إذا كان الحرف الحالي { ، ثم "رفع العلم" pz_prev

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

إذا كانت التسمية } تسبق الأمر { ، فأنت بحاجة إلى القفز مرة أخرى

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

سنكتب برنامجًا يعرض الأرقام الزوجية من 10 إلى 0 .

نحمل الرقمين 10 و 2 في مصفوفة data_mem ، ثم ، بينما الرقم في acc أكبر من أو يساوي الصفر ، سنطرح 2 من 10 ونعرض النتيجة

 #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

لضرب رقمين A و B ، تحتاج إلى إضافة B مضروبة من A إلى B.

في الحلقة ، في كل تكرار ، سنطرح واحدًا من A ، وبينما لا تكون A صفرًا ، أضف B إلى B.

برنامج LMCode } >>> ^ <+> ~ <<< ^> - <~ {>>> ^. ضرب الأرقام A + 1 و B ، أي يجب تخفيض عامل واحد عن عمد بواحد.

هذا لأن الحلقة ستنتهي فقط عندما تكون -1 في acc .

على سبيل المثال ، اضرب 5 في 5 .

للقيام بذلك ، قم أولاً بوضع القيم الضرورية في data_mem

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

ideone.com

أضف قفزات غير مشروطة مرة أخرى .

للقيام بذلك ، أضف المتغير prev .

نضيف أيضًا انتقالات إلى الأمام / الخلف تحت شرط acc = 0 . لمثل هذه الانتقالات ، قم بإنشاء علامة zflag (ZeroFlag) ومتغير z_prev .

سيتم تنفيذ التحويلات بواسطة الشرط zflag == 1 بواسطة الأوامر ( و )
نضرب 5 و 5 باستخدام الانتقال غير المشروط والانتقال وفقًا للشرط zflag == 1 .

أولاً ضع القيم الضرورية في data_arr
  data_arr[0]=5; data_arr[1]=1; data_arr[2]=5; 

برنامج LMCode ! >>> ^ <+> ~ <<< ^> - <~ (؟) >>> ^. يتوافق مع برنامج المجمع
  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
 #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

بشكل عام ، تعذر إنشاء الأعلام ، ولكن بدلاً من ذلك تحقق على الفور من الرقم الذي يساوي البطارية.

دعونا نتحقق من كيفية حساب أرقام فيبوناتشي.
 #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

لقد نشرت ملاحظة حول لغة LMCode على esolang.org هنا

ملاحظة مقال حول محاكي المجمع لـ Intel-4004 للترفيه هنا

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


All Articles