Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 26 мар 2019, 08:46

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 26 ]  На страницу 1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: 09 янв 2016, 19:30 
Не в сети
Администратор
Аватара пользователя

Сообщения: 237
Откуда: Россия
SDCC до сих пор не понимает оператор присваивания для всей записи целиком (проблема Feature cannot assign values to aggregates). Один из возможных способов исправления - заставить Ofront генерировать для записей не оператор присваивания "a=b;" , а вызов макроса __COPYREC(a,b,size).
Для этого в модуле OPV нужно исправить в процедуре stat обработку узла assign:
Код: "OBERON"
  1. PROCEDURE stat(n: OPT.Node; outerProc: OPT.Object);
  2. ...
  3. assign:
  4. l := n^.left; r := n^.right;
  5. IF l^.typ^.comp = Array THEN (* includes string assignment but not COPY *)
  6. OPM.WriteString(MoveFunc);
  7. expr(r, MinPrec); OPM.WriteString(Comma); expr(l, MinPrec); OPM.WriteString(Comma);
  8. IF r^.typ = OPT.stringtyp THEN OPM.WriteInt(r^.conval^.intval2)
  9. ELSE OPM.WriteInt(r^.typ^.size)
  10. END ;
  11. OPM.Write(CloseParen)
  12. ELSE
  13. (* присваивание записей *)
  14. IF l^.typ^.comp = Record THEN
  15. OPM.WriteString(" __COPYREC( ");
  16. END;
  17. IF (l^.typ^.form = Pointer) & (l^.obj # NIL) & (l^.obj^.adr = 1) & (l^.obj^.mode = Var) THEN
  18. l^.obj^.adr := 0; design(l, MinPrec); l^.obj^.adr := 1; (* avoid cast of WITH-variable *)
  19. IF r^.typ^.form # NilTyp THEN OPM.WriteString(" = (void*)")
  20. ELSE OPM.WriteString(" = ")
  21. END
  22. ELSE
  23. design(l, MinPrec);
  24. (* присваивание записей *)
  25. IF l^.typ^.comp = Record THEN
  26. OPM.WriteString(Comma)
  27. ELSE
  28. OPM.WriteString(" = ")
  29. END
  30. END ;
  31. IF l^.typ = r^.typ THEN expr(r, MinPrec)
  32. ELSIF (l^.typ^.form = Pointer) & (r^.typ^.form # NilTyp) & (l^.typ^.strobj # NIL) THEN
  33. OPM.Write("("); OPC.Ident(l^.typ^.strobj); OPM.Write(")"); expr(r, MinPrec)
  34. ELSIF l^.typ^.comp = Record THEN
  35. OPM.WriteString("*("); OPC.Andent(l^.typ); OPM.WriteString("*)&"); expr(r, 9)
  36. ELSE expr(r, MinPrec)
  37. END;
  38. (* присваивание записей *)
  39. IF l^.typ^.comp = Record THEN
  40. OPM.WriteString(Comma);
  41. OPM.WriteString("sizeof(");
  42. OPC.Andent(l^.typ);
  43. OPM.WriteString("))");
  44. END
  45. END
Присваивание в модуле
Код: "OBERON"
  1. MODULE AsgnRec; (*$MAIN*)
  2. IMPORT SYSTEM, P := Platform, B := Basic;
  3. TYPE
  4. Card = RECORD
  5. suit, rank: INTEGER
  6. END;
  7. VAR
  8. p: POINTER TO Card;
  9. a, b: Card;
  10. BEGIN
  11. a := b
  12. END AsgnRec.

транслируется в
Код: "C"
	 __COPYREC( AsgnRec_a, AsgnRec_b, sizeof(AsgnRec_Card));

Необходимо добавить в файл ZXDev\Lib\C\SYSTEM.h макроопределение:
Код: "C"
#define __COPYREC(d, s, n) memcpy((char*)(d),(char*)(s),n)
например, после аналогичного __MOVE(d,s,n)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 09 янв 2016, 19:47 
Не в сети
Администратор
Аватара пользователя

Сообщения: 237
Откуда: Россия
Просто переменных-записей всё работает, но возникает проблема для указателей на записи:
Код: "OBERON"
  1. MODULE AsgnRec; (*$MAIN*)
  2. IMPORT SYSTEM, P := Platform, B := Basic;
  3. TYPE
  4. Card = RECORD
  5. suit, rank: INTEGER
  6. END;
  7. VAR
  8. p,q: POINTER TO Card;
  9. a, b: Card;
  10. BEGIN
  11. a := b;
  12. p^ := a;
  13. q^ := p^;
  14. END AsgnRec.

При операциях с указателями генерируется охрана типов через макросы ZXDev\Lib\C\SYSTEM.h:
Код: "C"
#define __GUARDEQR(p, dyntyp, typ)	if(dyntyp!=typ##__typ) __HALT(-6);*(p)
#define __GUARDEQP(p, typ) if(__TYPEOF(p)!=typ##__typ)__HALT(-6);*(p)
Но условный оператор if не может быть частью выражения, поэтому не может быть аргументом memcpy.

Выход состоит в замене макросов на выражения с тернарным "? :" :
Код: "C"
#define __GUARDEQR(p, dyntyp, typ)	*((dyntyp!=typ##__typ)?__HALT(-6):p)
#define __GUARDEQP(p, typ) *((__TYPEOF(p)!=typ##__typ)?__HALT(-6):p)
 

Вместе с исправлением __HALT это решает проблему. Правда замена конструкции if на тернарный оператор в данном случае немного снижает эффективность.
Возможно, для Спектрума вообще следует отключить подобные проверки указателей (особенно для динамической типизации).


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 10 янв 2016, 00:24 
Не в сети
Аватара пользователя

Сообщения: 933
Откуда: Днепропетровская обл.
Saferoll писал(а):
SDCC до сих пор не понимает оператор присваивания для всей записи целиком.
Олежек, а я с этим боролся вот как:
Код: "OBERON"
  1. IF Cfg.AssignValsToAggregs THEN
  2. desk[deskN] := hand[player, cardn];
  3. ELSE
  4. desk[deskN].suit := hand[player, cardn].suit;
  5. desk[deskN].rank := hand[player, cardn].rank;
  6. END;
При этом для SDCC константа Cfg.AssignValsToAggregs = FALSE, для других TRUE.

Согласен, это не слишком удобно. Так что твоё предложение одобряю.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 13 янв 2016, 03:55 
Не в сети
Аватара пользователя

Сообщения: 933
Откуда: Днепропетровская обл.
Предлагаю вместо sizeof(type) подставлять сразу числовое значение. Это несложно. В OPV.stat вместо:
Код: "OBERON"
  1. OPM.WriteString("sizeof("); OPC.Andent(l^.typ); OPM.WriteString("))")
Код: "OBERON"
  1. OPM.WriteInt(l^.typ^.size); OPM.Write(")")
Подставлять для размера типа число — вполне в духе Ofront'а.

Saferoll писал(а):
Возможно, для Спектрума вообще следует отключить подобные проверки указателей (особенно для динамической типизации).
Безусловно. Это регулируется опцией OPM.typchk, могу сделать директиву (*$TYPCHK-*) для вставки в исходник.

Поразмыслил над тем, не генерировать ли вместо:
Код: "C"
__COPYREC(__GUARDEQP(AsgnRec2_p, AsgnRec2_Card), AsgnRec2_a, 4);
код:
Код: "C"
__GUARDEQP(AsgnRec2_p, AsgnRec2_Card); __COPYREC(AsgnRec2_p, AsgnRec2_a, 4);
, отделив проверку типа от копирования. Но как-то сомневаюсь. Хотя это даёт свои преимущества. Например, можно было бы сделать спектрумную реализацию макроса __COPYREC не через memcpy (вызов подпрограммы), а прямо LD DE,AsgnRec2_p : LD HL,AsgnRec2_a : LD BC,4 : LDIR.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 янв 2016, 09:01 
Не в сети
Администратор
Аватара пользователя

Сообщения: 237
Откуда: Россия
Zorko писал(а):
Предлагаю вместо sizeof(type) подставлять сразу числовое значение. Это несложно. В OPV.stat вместо:
Код: "OBERON"
  1. OPM.WriteString("sizeof("); OPC.Andent(l^.typ); OPM.WriteString("))")
Код: "OBERON"
  1. OPM.WriteInt(l^.typ^.size); OPM.Write(")")
Подставлять для размера типа число — вполне в духе Ofront'а.
Да, лучше подставлять сразу число.
Кстати, а что будет при динамической типизации, будет ли там указываться верный размер? И возможна ли, вообще, динамическая типизация для данной версии?
Zorko писал(а):
Поразмыслил над тем, не генерировать ли вместо:
Код: "C"
__COPYREC(__GUARDEQP(AsgnRec2_p, AsgnRec2_Card), AsgnRec2_a, 4);
код:
Код: "C"
__GUARDEQP(AsgnRec2_p, AsgnRec2_Card); __COPYREC(AsgnRec2_p, AsgnRec2_a, 4);
, отделив проверку типа от копирования. Но как-то сомневаюсь. Хотя это даёт свои преимущества. Например, можно было бы сделать спектрумную реализацию макроса __COPYREC не через memcpy (вызов подпрограммы), а прямо LD DE,AsgnRec2_p : LD HL,AsgnRec2_a : LD BC,4 : LDIR.
Отделение проверки даст несколько более эффективный код, но... 1)указатели могут быть не только на записи 2)при прямом присваивании записей не делается проверка. И я не знаю точно, делается ли проверка __GUARDEQP только для присваивания, или используется для аргументов других операций.
Так что вынести проверку отдельно не так-то просто.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 янв 2016, 18:03 
Не в сети
Аватара пользователя

Сообщения: 933
Откуда: Днепропетровская обл.
Saferoll писал(а):
Кстати, а что будет при динамической типизации, будет ли там указываться верный размер?
Да, ведь размер динамических типов точно известен в момент компиляции.

Saferoll писал(а):
И возможна ли, вообще, динамическая типизация для данной версии?
Конечно же, Олежек. И даже динамическая модульность каким-то образом возможна. Я, правда, не тестировал, но в спеке на Ofront всё это заявлено. Если мы ещё не успели сломать. ;)

Saferoll писал(а):
Так что вынести проверку отдельно не так-то просто.
Абсолютно согласен. А как ты смотришь на то, чтобы добавить опцию "SDCC support"?


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 18 янв 2016, 20:20 
Не в сети
Администратор
Аватара пользователя

Сообщения: 237
Откуда: Россия
Zorko писал(а):
А как ты смотришь на то, чтобы добавить опцию "SDCC support"?
А что именно будет делать эта опция?


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 19 янв 2016, 02:18 
Не в сети
Аватара пользователя

Сообщения: 933
Откуда: Днепропетровская обл.
Включать __COPYREC вместо rec1=rec2 :)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 21 янв 2016, 18:01 
Не в сети
Администратор
Аватара пользователя

Сообщения: 237
Откуда: Россия
Zorko писал(а):
Включать __COPYREC вместо rec1=rec2 :)

Да, нужно такое сделать. Возможно, это пригодится не только для присвоения записей.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 25 янв 2016, 07:05 
Не в сети

Сообщения: 20
>>> Например, можно было бы сделать спектрумную реализацию макроса __COPYREC не через memcpy (вызов подпрограммы), а прямо LD DE,AsgnRec2_p : LD HL,AsgnRec2_a : LD BC,4 : LDIR.


так SDCC так и делает, вместо memcpy вставляет

Код: "OBERON"
  1.  
  2. #include <stdint.h>
  3. #include <string.h>
  4.  
  5. typedef struct
  6. {
  7. uint8_t fld1;
  8. uint8_t fld2;
  9. uint16_t fld3;
  10. uint32_t fld4;
  11. } struct_t;
  12.  
  13.  
  14. static struct_t str1, str2;
  15.  
  16. void main()
  17. {
  18. str1.fld1 = 0;
  19. str1.fld2 = 100;
  20. str1.fld3 = 10000;
  21. str1.fld4 = 1000000;
  22.  
  23. memcpy(&str2, &str1, sizeof(struct_t));
  24. }
  25.  


Код: "OBERON"
  1.  
  2. ;test.c:16: void main()
  3. ; ---------------------------------
  4. ; Function main
  5. ; ---------------------------------
  6. _main::
  7. ;test.c:18: str1.fld1 = 0;
  8. ld hl,#_str1+0
  9. ld (hl),#0x00
  10. ;test.c:19: str1.fld2 = 100;
  11. ld hl,#_str1 + 1
  12. ld (hl),#0x64
  13. ;test.c:20: str1.fld3 = 10000;
  14. ld hl,#0x2710
  15. ld ((_str1 + 0x0002)), hl
  16. ;test.c:21: str1.fld4 = 1000000;
  17. ld hl,#0x4240
  18. ld ((_str1 + 0x0004)), hl
  19. ld hl,#0x000F
  20. ld ((_str1 + 0x0004)+2), hl
  21. ;test.c:23: memcpy(&str2, &str1, sizeof(struct_t));
  22. ld hl,#_str1
  23. ld de,#_str2
  24. ld bc,#0x0008
  25. ldir
  26. ret
  27.  


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 26 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Тех.поддержка phpBB