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

Твердыня модульных языков
Текущее время: 28 мар 2024, 23:41

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




Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
 Заголовок сообщения: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 30 ноя 2014, 20:51 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Насколько я понял, SDCC до сих пор не понимает оператор присваивания для всей записи целиком (проблема Feature cannot assign values to aggregates). Пока пробирался в дебрях Ofront, вроде бы нашёл идею, как вместо присваивания генерировать макрос, который потом можно заменять на memcpy или что-то подобное.
Но тут вылезла другая ошибка, связанная с охраной типов.
Программа
Код: "OBERON"
  1. MODULE AsgnRec; (*$MAIN*)
  2. IMPORT SYSTEM, P := Platform, B := Basic;
  3.  
  4. TYPE
  5. Card = RECORD suit, rank: INTEGER END;
  6. VAR
  7. a, b: POINTER TO Card;
  8. BEGIN
  9. a^ := b^;
  10. END AsgnRec.
транслируется в
Код: "C"
/*  Ofront 1.2 -xtspkaem */
#include "SYSTEM.h"
#include "Basic.h"
#include "Platform.h"
 
typedef
struct AsgnRec_Card {
INTEGER suit, rank;
} AsgnRec_Card;
 
 
static AsgnRec_Card *AsgnRec_a, *AsgnRec_b;
 
export LONGINT *AsgnRec_Card__typ;
 
 
 
/*============================================================================*/
 
static void EnumPtrs(void (*P)(void*))
{
P(AsgnRec_a);
P(AsgnRec_b);
}
 
__TDESC(AsgnRec_Card__desc, 1, 0) = {__TDFLDS("Card", 4), {-4}};
 
export main(int argc, char **argv)
{
__INIT(argc, argv);
__IMPORT(Basic__init);
__IMPORT(Platform__init);
__REGMAIN("AsgnRec", EnumPtrs);
__INITYP(AsgnRec_Card, AsgnRec_Card, 0);
/* BEGIN */
_GUARDEQP(AsgnRec_a, AsgnRec_Card) = *AsgnRec_b; /* 37-я строка */
__FINI;
}
но выдаёт при компиляции ошибки

Код: "TEXT"
AsgnRec.c:37: error 101: too many parameters
AsgnRec.c:37: error 48: cannot assign values to aggregates
Ошибка 48 понятна, это как раз и есть проблема с присваиванием. А что такое "слишком много параметров"?
Удалось выяснить, что _GUARDEQP (и прочие "охранники") задаются в SYSTEM.H макросами вида
Код: "C"
#define __GUARDEQP(p, typ)	if(__TYPEOF(p)!=typ##__typ)__HALT(-6);*(p)

в которых __HALT сводится строчкой
Код: "C"
#define __HALT(x)	SYSTEM_HALT(x)
к процедуре SYSTEM_HALT, которая в этом же файле SYSTEM.H определена как процедура без параметров
Код: "C"
extern void SYSTEM_HALT(); 
Вот это несоответствие числа параметров, видимо и вызывает ошибку 101.
Что же это за процедура SYSTEM_HALT и сколько у ней должно быть параметров?


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 30 ноя 2014, 22:28 
Не в сети

Сообщения: 203
Saferoll писал(а):
Код: "C"
extern void SYSTEM_HALT(); 
Вот это несоответствие числа параметров, видимо и вызывает ошибку 101.
Что же это за процедура SYSTEM_HALT и сколько у ней должно быть параметров?

Насколько я помню, в сях такое объявление означает, что функция SYSTEM_HALT не возвращает результата и имеет неопределённое на данном этапе количество параметров...


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 30 ноя 2014, 22:41 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
geniepro писал(а):
Насколько я помню, в сях такое объявление означает, что функция SYSTEM_HALT не возвращает результата и имеет неопределённое на данном этапе количество параметров...
Мне тоже что-то такое вспоминается (А если extern void SYSTEM_HALT(void);, то это явно функция без параметров), но что тогда значит ошибка "too many parameters"? И где тогда, задаётся конкретная функция SYSTEM_HALT с конкретным числом параметров?
Кстати, в конце файла SYSTEM.H есть
/* ANSI prototypes; not used so far
...
void SYSTEM_HALT(int n);
*/
Может быть раскомментировать? Если эта функция объявлена, она где-то должна быть "в натуре" - в той среде, в которой скомпилированная программа должна выполняться.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 01 дек 2014, 09:11 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Эта же проблема возникает, если использовать в транслируемой программе ASSERT. Вывод - Ofront не просто транслирует синтаксис Оберона в синтаксис Си, как это делает Oberon Script для javascript. Ofront старается перенести и положительные runtime-свойства. Но для этого в среде выполнения должны быть процедуры system_halt и прочие, а макросы в файлах конфигурации должны на них указывать.
И мы должны с этим разобраться и либо всё это верно настроить, чтобы действовало, либо отключить, чтобы не выдавало непонятных ошибок.
Либо описать в документации, что такое-то средство Оберона применять нельзя, потому что оно еще не реализовано и выдаёт ошибки при компиляции Си-программы.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 01 дек 2014, 10:34 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Saferoll писал(а):
Насколько я понял, SDCC до сих пор не понимает оператор присваивания для всей записи целиком (проблема Feature cannot assign values to aggregates).
Да, пока не спешат исправить. У них там специализация. Филипп Краузе, с которым налажен контакт, по бэку Z80, во фронт-энд не лезет. А Эрик Петрич, или кто у них там по фронту, задвинул это дело в долгий ящик.

Я пока что делаю так:
Код: "OBERON"
  1. TYPE
  2. Rank* = SHORTINT; Suit* = SHORTINT;
  3. Card* = RECORD suit*: Suit; rank*: Rank END;
  4. Cards = ARRAY Amount OF Card;
  5. VAR
  6. desk*: ARRAY 12 OF Card;
  7. hand*: ARRAY Players OF Cards;
Код: "OBERON"
  1. IF Sets.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;
Код получается оптимальный; Ofront вообще выкидывает неиспользуемую ветку.

Saferoll писал(а):
Но тут вылезла другая ошибка, связанная с охраной типов.
Код: "TEXT"
AsgnRec.c:37: error 101: too many parameters
AsgnRec.c:37: error 48: cannot assign values to aggregates
Ошибка 48 понятна, это как раз и есть проблема с присваиванием. А что такое "слишком много параметров"?
Это ошибка отсутствия реализации процедуры SYSTEM_HALT в ZXDev. Я собрал твой код (убрав импорт) в WinDev, всё скомпилиорвалось.

Saferoll писал(а):
SYSTEM_HALT, которая в этом же файле SYSTEM.H определена как процедура без параметров
Код: "C"
extern void SYSTEM_HALT(); 
Вот это несоответствие числа параметров, видимо и вызывает ошибку 101.
Всё не так просто. Это объявление в "старом стиле", где сначала объявляется процедура с пустыми скобочками, а потом дальше набор параметров. Ведь void внутри скобок нет. Не знаю есть ли смысл поддерживать этот старый стиль, я не встречал компиляторов, которые не понимают нового.

Saferoll писал(а):
Что же это за процедура SYSTEM_HALT и сколько у ней должно быть параметров?
Макрос __HALT, он же процедура SYSTEM_HALT имеет один параметр (код возврата) и превращается (должна превращаться) в сишный exit(n); для WinDev так и есть; а вот в ZXDev я так и не придумал как правильно выйти в бейсик (особенно с учётом режима прерываний и необходимого для этого вызова Basic.Quit).

Пока не реализована SYSTEM_HALT можно реализовать __GUARDEQR и __GUARDEQP (охрана типов) как "пустышки", просто игнорирующие проверку типа (и не вызывающие __HALT). Опция "игнорировать охрану типа" может быть добавлена в XDevCfg.h. Впрочем, в данном конкретном случае это мало что даст, потому что раздельное присваивание полей работает и так.
Код: "OBERON"
  1. a^.suit := b^.suit;
  2. a^.rank := b^.rank;


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 01 дек 2014, 14:33 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Есть решение проблемы SYSTEM_HALT. Пожалуй, не следует мудрить с Basic.Quit. Останется работать обработчик прерываний IM 2 или режим DI (можно разрешить). Но выход по HALT(не 0) всё равно аварийный. Здесь максимум что нужно — чтобы пользователь увидел код ошибки. А вызвать Basic.Quit перед HALT(0) можно и ручками. Я вспомнил про RST 8, потестировал. Такой вариант нам вполне сгодится:
Код: "C"
#define SYSTEM_HALT(n) __asm RST 8 \
.DB n-1 \
__endasm
HALT(0) даёт сообщение "0 OK", HALT(1) — "1 NEXT without FOR"; и прочие сообщения Спектрум-бейсика. Можно даже попробовать подобрать код по смыслу. Добавил в репозиторий.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 01 дек 2014, 16:59 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Тестирование показывает, что вариант нужно усовершенствовать. При возврате по HALT() регистры IY и HL' не всегда содержат значения, нужные для корректной работы бейсика. Ну и режим прерываний не должен быть DI, иначе всё просто зависнет. Так что предлагаю такую реализацию SYSTEM_HALT:
Код: "C"
void SYSTEM_HALT_A (void /* Register A */) __naked {
__asm
LD (HALTCODE$),A
LD HL,#0x2758
EXX
LD IY,#0x5C3A
IM 0
EI
RST 8
HALTCODE$:
.DB 0xFF
__endasm;
} //SYSTEM_HALT_A
Код: "C"
#define __SYSTEM_hash__ #
#define __SYSTEM_id__(x) x
#define __SYSTEM_ld_a__(x) if(x==0) {__asm xor a __endasm;}else{__asm ld a,__id__(__SYSTEM_hash__)x __endasm;}
#define SYSTEM_HALT(n) __SYSTEM_ld_a__(n-1); SYSTEM_HALT_A()


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 01 дек 2014, 19:48 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Оптимизировал на пару байт.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 08 янв 2016, 20:20 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Итак, HALT(n) вызывает SYSTEM_HALT(n) в силу макроса ZXDev\Lib\C\SYSTEM.h:
Код: "C"
#define __HALT(x)	SYSTEM_HALT(x)

А это через макроопределения
Код: "C"
extern void SYSTEM_HALT_N (void);
#define SYSTEM_HALT(n) SYSTEM_HALT_N(); __asm .DB n-1 __endasm

превращается в вызов функций
Код: "C"
SYSTEM_HALT_N (void);
__asm .DB n-1 __endasm

И вот здесь возможна проблема! Дело в том, что __HALT(x) вызывается из runtime-проверок, например из охранников типа. Причем в некоторых местах это происходит из середины выражения. Например,
Код: "C"
#define __SHORT(x, y)	((int)((unsigned long)(x)+(y)<(y)+(y)?(x):(__HALT(-8),0))) 
#define __GUARDP(p, typ, level) ((typ*)(__ISP(p,typ,level)?p:(__HALT(-5),p)))

Но "SYSTEM_HALT_N();" является отдельным оператором, а не выражением, поэтому нельзя вычислить (__HALT(-5),p) - возникает ошибка из-за символа ";".
Попробуем задать
Код: "C"
extern void SYSTEM_HALT_N (void);
#define SYSTEM_HALT(n) SYSTEM_HALT_N()

При этом будет выходить не сообщение с заданным кодом n, а какое-то неопределенное сообщение, зависящее от того, какой байт компилятор поместит в код после вызова функции. Но зато теперь можно задать макрос вида
Код: "C"
#define __GUARDEQP(p, typ)	*((__TYPEOF(p)!=typ##__typ)?__HALT(-6):p)

К сожалению, так просто создать сообщение с нужным кодом не получается. Если задать
Код: "C"
#define SYSTEM_HALT(n) 	__asm    call _SYSTEM_HALT_N 	\
.DB n-1 \
__endasm
то компилятор ругается на __endasm.

Похоже вызов функции является выражением, а асм-вставка – нет.
Наверно, единственный выход – написать ассемблерную процедуру, которая поместит в какое-то место байт (номер сообщения), запишет в стек адрес этого места, а затем выполнит все действия SYSTEM_HALT_N.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Что за SYSTEM_HALT() в макросах SYSTEM.H?
СообщениеДобавлено: 09 янв 2016, 13:39 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Да, ты совершенно прав. Нужно возвратиться к предыдущему варианту. Потестил и закоммитил такой код:
Код: "C"
// Оптимизация: пусть n-1 вычисляется во время компиляции, ведь n всегда константа
extern void SYSTEM_HALT_m1 (unsigned char n);
#define SYSTEM_HALT(n) SYSTEM_HALT_m1(n-1)
 
// ...
 
void SYSTEM_HALT_m1 (unsigned char n) __naked {
__asm
LD IY,#0x5C3A
IM 1
EI
POP HL ; Адрес возврата больше не нужен (не возвращаемся)
DEC SP ; Выравним стек чтобы достать аргумент в рег. A
POP AF
LD (HALTCODE$),A
RST 8
HALTCODE$:
.DB 0xFF
__endasm;
} //SYSTEM_HALT_m1

Другое дело, что такие проверки в рантайме для ZX, видимо, следует опционально отключать для эффективности. Кое-что уже в этом плане реализовано, например, см. опции SYSTEM_NoASSERT, SYSTEM_NoCheck_X, SYSTEM_NoCheck_CASE.


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

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


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

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


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

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club