|
nedoPC.orgCommunity for electronics hobbyists, established in 2002 |
|
Robby - расширение языка Robot Warfare 1 (RW1)
Author |
Message |
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
какого именно? их было поболее одного вроде как...
|
30 May 2018 13:59 |
|
|
Lavr
Supreme God
Joined: 21 Oct 2009 08:08 Posts: 7777 Location: Россия
|
Так и бейсики - есть компиляторы...
_________________ iLavr
|
30 May 2018 14:00 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
для 8080 компиляторы бейсика? ты видел хотя бы один? и бейсик для 8080 вроде как был один - микрософтовский
|
30 May 2018 14:04 |
|
|
Lavr
Supreme God
Joined: 21 Oct 2009 08:08 Posts: 7777 Location: Россия
|
Видел и не один даже. Компилятор бейсика для 8080 под СР/М даже у меня есть. А кросс-компиляторы, я даже здесь на форуме искал публично - так поболе одного! Ну если у меня есть СР/М-овский, то значит точно не один...
_________________ iLavr
|
30 May 2018 14:15 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
У микрософта даже свой CP/M-80 был - MSX-DOS назывался
|
30 May 2018 16:03 |
|
|
Lavr
Supreme God
Joined: 21 Oct 2009 08:08 Posts: 7777 Location: Россия
|
А вот у меня CP/M, похоже, от DR, только вот кем адаптирована - не знаю, поскольку версия не от Бриджиди. Его версия появилась позже. Версия CP/M от Бриджиди адаптированная под "Специалист" у меня появилась только с эмулятором от Шевцова, и я с ней так и не поигрался. Но тем не менее - ты сравнивал свой Рубби с каким-либо компилятором С ?
_________________ iLavr
|
30 May 2018 16:17 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
У меня при необходимости (путём добавления более детальных правил в __RULES) можно добиться скорости ассемблерного кода, работающего с 16-битными словами - по поводу более продвинутой математики (умножить/разделить), то она была взята из исходников SmallC для CP/M - от него же собственно произошли другие существующе сишные кросс-компили для 8080 - в частности SDCC и Z88DK (который сейчас только Z80) А вообще про 8080 компиляцию из Robby лучше говорить в соответствущем топике, например обсудить пример с двумя вложенными циклами: http://www.nedopc.org/forum/viewtopic.php?p=144529#p144529
|
30 May 2018 17:47 |
|
|
Lavr
Supreme God
Joined: 21 Oct 2009 08:08 Posts: 7777 Location: Россия
|
Ну ты сам как бы дал здесь повод про 8080...
_________________ iLavr
|
30 May 2018 18:00 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
Это был ответ на вопрос зачем я изобрёл свой собственный язык, если есть новая прекрасная ява Одна из причин, почему я не использую яву - её попросту нету для целевых платформ, для которых пригоден мой язык P.S. Причём напомню, что с RW1 всё началось на 16-битном x86 и MS-DOS...
|
30 May 2018 18:07 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
|
01 Jun 2018 09:19 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
Простой интерпретатор RW0 я писал на PocketC прямо на своём пальме в мае-июне 2001 года (каких-то 22 года назад кхе-кхе) - не могу нигде тут на форуме найти где я про это писал - видимо нигде (форума тогда ещё небыло) - скопипащу сырцы прямо сюда: rw0.c | | | | Code: // rw0.c // May 2001
include "rw0code.hpp"
mload(pointer mem) { int i,j,k,kk,sum; string s,ss; i=0; while(!mmeof()) { s=mmgetl(); // puts(s+"\n"); k=strlen(s); if(k>16) { ss=strleft(s,16); s=ss;k=16; } for(j=0;j<k;j=j+2) { ss=substr(s,j,2); kk=ss@[0]; if(kk<='9') kk=kk-'0'; else kk=kk-'A'+10; sum=kk*16; kk=ss@[1]; if(kk<='9') kk=kk-'0'; else kk=kk-'A'+10; sum=sum+kk; mem[i++]=sum; } } }
sload() { int i=0; while(!mmeof()) { spr[i++]=mmgetl(); if(i>=NSPR) break; } }
main() { int i,j,k,size=2000; pointer mem; string fr,fs; string str="M"; clear(); puts("PocketRW1P2\n"); puts("http://shaos.h1.ru\n"); //str=gets("RW0 Name"); fr=str+".RW0"; fs=str+".SPR"; k=mmfind(fs); if(k) { puts(mmgetl()+" Loading\n"); sload(); mmclose(); } k=k*mmfind(fr); if(k) { mem=malloc(size); puts(mmgetl()+" Loading\n"); mload(mem); mmclose(); rw0code(mem); graph_on(); title(name); while(true) { text(130,0,hex(PC)+" "); // puts(">"+hex(PC)); k=code[PC]; // puts(" "+hex(k)+"\n"); if(!( (*op[k])())) break; } free(mem); free(var); } else puts("Error\n"); //wait(); }
| | | | |
rw0code.c | | | | Code: // rw0code.hpp // May 2001
#define RX 0 #define RY 1 #define RD 2 #define RN 3 #define RK 4 #define RR 5 #define RT 6 #define RE 7 #define RM 8 #define RI 9 #define RA 10 #define RB 11 #define RC 12 #define RP 13 #define RL 14 #define RS 15 #define BASE 0xFFFF #define NSPR 32 #define SP reg[RS] #define PC reg[RP] #define SX reg[RX] #define SY reg[RY]
string name; int offset,codelen,varlen=1000; int reg[16],stack[32]; pointer code,var,op[256]; string spr[NSPR];
int rvar(int a) {int k; if(a>0xF000) k=reg[a-0xFF00]; else k=var[a]; return k; }
wvar(int a,int k) {if(a>0xF000) reg[a-0xFF00]=k; else {var[a]=k; bitmap((a%20)*8,a/20*8+16,spr[0]);} //puts("wvar "+hex(a)+" "+k+"\n"); }
int get1() {return code[PC++];} int get2() {int k; k=get1() + (get1()<<8); if(k&0x8000) k=-1-(~k); return k; }
int getv() {int k; switch(get1()) {case 0: k=get2();break; case 1: k=rvar(get2());break; case 2: k=var[get2() + rvar(get2())];break; } return k; }
int geta() {int k; switch(get1()) {case 0: k=0;break; case 1: k=get2();break; case 2: k=get2() + rvar(get2());break; } return k; }
include "rw0graf.hpp"
int op_err() { alert("Code Error! [" +hex(PC)+"] "+hex(code[PC])); return 0; }
int op_def() { int a,n,k=0,i,o; o=code[PC++]; a=get2();n=get2(); if(o==2) { k=get2(); for(i=0;i<k;i++) var[a+i]=get2(); } return 1; }
int op_var() { int a,k; PC++;a=geta();k=getv(); wvar(a,k);return 1; }
int op_if() // 41,42 { int k,u,l; k=code[PC++];u=getv();l=getv(); if(k==0x41&&u) PC=l; if(k==0x42&&(!u)) PC=l; return 1; }
int op_goto() // 43 { int l; PC++;l=getv();PC=l; return 1; }
int op_call() // 44 { int l;PC++;l=getv(); stack[SP++]=PC;PC=l; return 1; }
int op_ret() // 33 { int l; SP--;PC=stack[SP]; return 1; }
int op_expr() // 40 { int i,b,k,s,x1,x2,x3; s=SP;PC++;k=get1(); for(i=0;i<k;i++) { b=get1(); if(b>=0x80&&b<=0xD1) {s--;x2=stack[s];s--;x1=stack[s];} if(b>=0xE0&&b<=0xE2) {s--;x1=stack[s];} switch(b) { case 0x80: stack[s++]=(x1&&x2); break; case 0x81: stack[s++]=(x1||x2); break; case 0x90: stack[s++]=(x1==x2); break; case 0x91: stack[s++]=(x1!=x2); break; case 0x92: stack[s++]=(x1>x2); break; case 0x93: stack[s++]=(x1<x2); break; case 0x94: stack[s++]=(x1>=x2); break; case 0x95: stack[s++]=(x1<=x2); break; case 0xA0: stack[s++]=(x1+x2); break; case 0xA1: stack[s++]=(x1-x2); break; case 0xB0: stack[s++]=(x1*x2); break; case 0xB1: stack[s++]=(x1/x2); break; case 0xB2: stack[s++]=(x1%x2); break; case 0xC0: stack[s++]=(x1&x2); break; case 0xC1: stack[s++]=(x1|x2); break; case 0xC2: stack[s++]=(x1^x2); break; case 0xD0: stack[s++]=(x1>>x2); break; case 0xD1: stack[s++]=(x1<<x2); break; case 0xE0: stack[s++]=(-x1);break; case 0xE1: stack[s++]=(~x1);break; case 0xE2: stack[s++]=(!x1); break; case 0xF0: s--;x1=stack[s]; s--;x2=stack[s]; s--;x3=stack[s]; if(x3) stack[s++]=x2; else stack[s++]=x1; break; case 0xF1: s--;x1=stack[s]; stack[s++]=x1; stack[s++]=x1; break; case 0xF2: s--;x1=stack[s]; s--;x2=stack[s]; stack[s++]=x1; stack[s++]=x2; break; case 0xF3: s--;x1=stack[s]; stack[s++]=rvar(x1); break; case 0xF4: s--;x1=stack[s]; s--;x2=stack[s]; wvar(x2,x1); break; case 0xF5: i=i+2; stack[s++]=get2(); break; case 0xF6: s--;x1=stack[s]; s--;x2=stack[s]; stack[s++]=x2+x1; break; } } return 1; }
rw0code(pointer mem) { int i,k; name="test "; offset=mem[3]+(mem[4]<<8); code=&mem[offset]; puts("offset="+offset+"\n"); SP=0;PC=0; k=mem[5]; for(i=0;i<k;i++) name@[i]=mem[i+6]; name@[k]=0; puts("name="+name+"\n"); k=k+7; codelen=mem[k+2]+(mem[k+3]<<8); puts("codelen="+codelen+"\n"); varlen=mem[k]+(mem[k+1]<<8); puts("varlen="+varlen+"\n"); var=malloc(varlen); for(i=0;i<varlen;i++) var[i]=0; for(i=0;i<256;i++) op[i]=op_err; op[1]=op_def;op[2]=op_def; op[0x20]=op_var; op[0x33]=op_ret; op[0x40]=op_expr; op[0x41]=op_if; op[0x42]=op_if; op[0x43]=op_goto; op[0x44]=op_call; op[0x69]=op_graf; op[0x6A]=op_graf;
}
| | | | |
rw0graf.hpp Роботы загружались из хексов, хранящихся как странички блокнота пальма вот в таком виде: M.RW0
|
23 Apr 2023 20:17 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
Зарегал доменное имя robby.club - может там какую обучалку пошаговую размещу по языку Robby на подобие https://try.ruby-lang.org/
|
30 Apr 2023 00:07 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
Цикл for(A in 1..10) превращается в тоже самое как и for(A=1;A<=10;A++) - это просто, а вот с for(A in array) надо помудрить ибо A в данном случае не индекс, а значение соответствующего элемента из массива, т.е. придётся для хранения индекса заводить "скрытую" переменную _1 (и далее _2, _3 и т.д.), которая будет инкрементироваться для доступа ко всем элементам массива array и A в цикле "под водой" будет присваиваться значение array[_1]. Обязательность скобок можно отменить - тогда синтаксис циклов будет похож на Rust. Аналогичный подход со скрытыми переменными, которые генерит сам компилятор, я планировал использовать для реализации вызовов функций в составе арифметических выражений. А по регистрам кроме всех 26 букв (для того чтобы добить до 32) можно ещё добавить регистры ALPHA, BETA, GAMMA, DELTA, а также GPIO и GPIODIR (для так давно желаемой платформы микроконтроллеров RW1P4)...
|
21 May 2023 01:31 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
Примерно с 2007 по 2016 годы я хотел называть расширение языка RW1 аббревиатурой ROBERTA (Real Object Basic Environment Reflecting Ttransactional Architecture) - см. закрытый топик viewtopic.php?f=46&t=8635&hilit=roberta - и только потом передумал и назвал язык Robby. Сейчас можно снова немножко это вспомнить и начать позиционировать язык программирования Robby как "Robot Oriented Programming Language" (ROPL) Можно таки сделать объектную модель, где объекты описываются роботами, которые обмениваются сообщениями, включая возможность компилировать такие программы в бинарники ретроплатформ через nedoPC SDK для запуска в пределах одной системы либо в сети ретрокомпьютеров - вот ранний текст на эту тему, который я написал ещё в 2002 году и распространял как текстовый файл rw1_para.txt: | | | | Code: RW1 КАК ЯЗЫК ПРОГРАММИРОВАНИЯ ПАРАЛЛЕЛЬНЫХ ПРОЦЕССОВ ----------------------------------------------------
Александр Шабаршин (shaos@mail.ru) http://robots.shaos.ru
В статье затрагивается возможность использования языка программирования роботов RW1 в качестве языка параллельных процессов (агентов).
Язык RW1 к версии 2.1 прошел путь от ассемблероподобного языка к языку типа Си (http://shaos.ru/main_rus/rw1_r.htm). Чтобы представить специфику языка, приведем пример простой программы:
robot "Program 1" author "A.Shabarshin" +rw1_std.rwi main() { while(1) { // вечный цикл } }
Данная программа не делает ничего, но в ней можно увидеть то, что должно быть обязательно в любой RW1 программе. Это ключевое слово ROBOT, за которым следует имя программы в кавычках. Слово AUTHOR, за которым идет имя автора программы в кавычках. Основная функция программы main(), которая должна быть самой первой функцией программы. Кроме того, внутри программы организуется вечный цикл. В файле RW1_STD.RWI определены некоторые полезные макросы.
Будем подразумевать, что мы используем подход RW1P1 - Robot Warfare 1 Platform 1, что может быть перенесено и на RW1P2 (см. http://shaos.ru/main_rus/rw1_r.htm#RW1P1).
В среде исполнения может быть запущено несколько роботов (программ или агентов), которые могут взаимодействовать друг с другом посредством сообщений. Каждый робот в системе имеет свой уникальный идентификационный номер, который можно узнать, прочитав регистр I. Например, так:
id=I; say "ID=&id "
Идентификаторы присваиваются начиная с 1. Идентификатор 0 обозначает всех роботов в системе (для широковещательных сообщений).
Самым простым типом сообщений является передача одного числового значения с помощью команды SEND, которое может быть принято командой RECV. Пример:
send -13 10 // отправить роботу с номером 10 число -13 recv info // если буфер не пуст, принять число и // сохранить его в переменной info
Команда RECV является очень информативной - кроме сохранения принятого числа, она располагает некоторую информацию в регистрах робота: регистр N - порядковый номер робота-передатчика (если N равен 0, то буфер принятых сообщений пуст); в регистрах X и Y записываются относительные координаты робота-передатчика (в случае, если пространственная привязка имеет смысл); в регистр K помещается значение времени, в которое был отправлен код.
Такое почисловое взаимодействие не слишком информативно. Более мощным средством межпроцессного обмена языка RW1, появившемся в версии 2.1, является прием/передача "пакетов". Итак, что же такое "пакет" в языке RW1? Пакет - это массив чисел, первое из которых обозначает количество оставшихся. Например:
def pack1[5] = {4, 1,2,3,4}
В данном случае создается массив pack1, который является RW1-пакетом с длиной 4. Этот пакет можно передать в качестве сообщения другому роботу с помощью команды SENDP:
sendp pack1 10 // отправить пакет роботу 10, или sendp pack1[0] 10 // то же самое
Если вы смогли догадаться, можно отправить и часть массива, и даже не с нулевого элемента. Пример:
sendp pack1[2] 10 // отправляем пакет c ячейки 2 - в ней // мы имеем число 2, поэтому отправляется только 2 числа
Прием пакета осуществляется командой RECVP:
def pack0[10] recvp pack0 if(n) say "принят пакет размером &k ячеек" else say "ошибка приема"
Для копирования пакетов используется команда COPYP:
copyp target source // копирование пакета из source
Интересно отметить, что пара SEND и RECVP совместимы. Только при этом одно число будет превращаться в пакет (массив с двумя элементами), первое из которых будет 1. Вторая пара SENDP и RECV совместима лишь частично - при этом происходит потеря всех данных за исключением первого числа. Так что если вы решили использовать для межпроцессного взаимодействия пакеты, не пользуйтесь командой RECV. Командой SEND пользоваться можно, так как приходящие отдельные сообщения успешно принимаются пакетной командой RECVP (как было указано выше).
Итак, типовая программа-робот будет выглядеть так:
robot "Program 2" author "A.Shabarshin" +rw1_std.rwi main() { // определение и инициализация массивов def buff[256] time = 0 // определение момента активности while(1) { // вечный цикл if(time>=T) { // некие действия send 111 // послать широковещательное сообщение // возможно тут будет переназначение time } recvp buff // получение сообщения if(n) { // анализ полученного сообщения say "> &n &x &y &k received" } } }
Следует разъяснить что у нас будет храниться в переменной TIME. Здесь мы будет сохранять метку времени, по достижению которой наш робот должен проявить некую самостоятельную активность. Регистр T используется для контроля времени - в нем хранится количество тиков от момента старта системы. Если мы имеем привязку к реальному времени (+RW1P1.RWI), то в T хранится время в десятых долях секунды (другое значение делителя может быть установленно отдельно). Кроме того, активность будет проявляться при получении какого-либо сообщения извне.
Попробуем написать робота, который определяет количество своих собратьев (экземпляров данного процесса) в системе.
robot "Program 3 - count me" author "A.Shabarshin" +rw1_std.rwi +rw1p1.rwi main() { def buff[256] def robots[100] // надеюсь их будет не больше 100 ;) nrobot = 0 // начальное значение счетчика time = 10 // определение момента активности say "I'm &I " while(1) { // вечный цикл if(time>=T) { // некие действия // вывести список найденных роботов for(ii=0;ii<nrobot;ii++) { jj = ii+1 say "&jj id=&robots[ii] " } nrobot = 0 // обнуляем send 111 // послать широковещательное сообщение time = time + @TIME_SEC(5) // повторить через 5 секунд } recv buff[0] // получение сообщения if(n) { // анализ полученного сообщения if(buff[0]==111) // это кто-то наш :) { robots[nrobot] = n nrobot = nrobot+1 } } } }
Copyright (c) 2002, Alexander Shabarshin
| | | | |
Более того, реализация RobbyVM в браузере уже многое из вышеперечисленного делает - надо просто описать это всё единообразно с возможностью использования в разных применениях, в частности на базе программирования для Circuits.CCP.S. А может быть ещё и соревнования роботов вернуть? https://web.archive.org/web/20020114102449/http://robots.shaos.ru/cgi/stat.cgi?top10
|
05 Jul 2024 15:08 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 23387 Location: Silicon Valley
|
В апреле 2023 года я обнаружил косяк в своём компиляторе Robby - CONTINUE внутри FOR не меняет счётчик - первопричина кроется в том, как я изначально переводил сложные синтаксические конструкции языка в простые через препроцессор: на самом деле оно должно быть так (чтобы expr3 выполнялось по continue тоже): или если нумеровать метки по порядку: осталось вспомнить как я кодил такие преобразования 24 года назад - заодно можно и for(A in 1..10) поддержать... P.S. Ещё когда я в 2018 году кодил TERNARO то наткнулся на другой косяк компилятора, когда сложные условия в if() работали неправильно - то ли я с приоритетами операций напутал, толи ещё что связанное с моим JS-фреймворком, но мне пришлось наставить скобок либо вообще разбить сложный if на пачку простых...
|
20 Jul 2024 00:56 |
|
|
Who is online |
Users browsing this forum: No registered users and 3 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|