Oberon space
General Category => Общий раздел => Тема начата: ilovb от Май 28, 2013, 08:13:08 pm
-
Для тех кто плохо понимает зачем нужен псевдо-модуль SYSTEM в Оберонах и каким он должен быть на конкретной платформе вот интересная ссылочка из ETH: The Module SYSTEM (http://www.ethoberon.ethz.ch/SYSTEM.html)
-
Насчет байта в Обероне...
Работа с байтами через "стандартный" систем может быть примерно такой:
MODULE MyTest;
IMPORT SYSTEM, Log;
CONST WORDSIZE = SIZE(INTEGER);
PROCEDURE Do*;
VAR
bytes: POINTER TO ARRAY OF INTEGER;
PROCEDURE Get8(pos: INTEGER): INTEGER;
VAR adr, val: INTEGER;
BEGIN
adr := SYSTEM.ADR(bytes^);
ASSERT(pos < LEN(bytes) * WORDSIZE);
SYSTEM.GET(adr + pos, val);
RETURN val MOD 256;
END Get8;
PROCEDURE Put8(pos, val: INTEGER);
VAR adr: INTEGER;
BEGIN
adr := SYSTEM.ADR(bytes^);
ASSERT(pos < LEN(bytes) * WORDSIZE);
ASSERT((val >= 0) & (val <= 255));
SYSTEM.PUT(adr + pos, val);
END Put8;
BEGIN
NEW(bytes, (640 DIV WORDSIZE) * (480 DIV WORDSIZE));
Put8(0, 0);
Put8(1, 1);
Put8(2, 255);
Put8(3, 200);
Log.Int(Get8(0));
Log.Int(Get8(1));
Log.Int(Get8(2));
Log.Int(Get8(3));
END Do;
BEGIN
END MyTest.Do
Ну и не стоит забывать что в последней неофициальной редакции репорта от 01.07.2012 байт таки появился.
6.1. Basic types
The following basic types are denoted by predeclared identifiers. The associated operators are defined in 8.2, and the predeclared function procedures in 10.2. The values of a given basic type are the following:
BOOLEAN the truth values TRUE and FALSE
CHAR the characters of a standard character set
INTEGER the integers
REAL real numbers
BYTE the integers between 0 and 255
SET the sets of integers between 0 and 31
The type BYTE is compatible with the type INTEGER, and vice-versa.
Однако, имхо, это спорное решение.
Также спорным является SET, который прибит гвоздями к 32 битам. Что будет если делать ORD() при 16 бит INTEGER неизвестно....
-
И еще...
Имхо, по задумке Вирта, SYSTEM должен позволять делать все что угодно на целевой платформе, но минимальным набором средств. Такой набор он описал в репорте.
Т.е. вполне можно обойтись и "стандартным" SYSTEM. Просто в своем приложении нужно предусмотреть набор платформозависимых модулей под каждую целевую платформу: Platform_x86, Platform_x64, Platform_ARM etc
В каждом модуле соответственно один и тот же набор процедур, но реализация специфичная для каждой платформы. Имхо, это вполне нормально для кроссплатформенного ПО. Профит в том, что нет зависимости от особенностей компилятора и вы полностью контролируете поведение программы.
Если нужно выжать все соки, то можно и в маш. кодах реализовать некоторые процедуры.
Все это, возможно, немного сложновато на первый взгляд. Но, имхо, это гораздо лучше всяких ад и сишек. Т.к. есть полный контроль над кодом вплоть до поведения платформозависимых вещей. (при условии что компилятор отвечает требованиям репорта)
ps Репорт требует уточнения, да. Думаю что Вирт сейчас этим и занимается.
-
ps Репорт требует уточнения, да. Думаю что Вирт сейчас этим и занимается.
Не думаю. Неинтересно это...
-
Ну можно спросить у него... ;)
По поводу этого http://oberspace.dyndns.org/index.php/topic,484.0.html
лично я бы не использовал Get8/Put8. Мне кажется что гораздо проще все вычисления делать на INTEGER и просто сделать одну процедуру PackToBytes(src: ARRAY OF INTEGER, adr: INTEGER), которая просто пересылает данные в видеобуфер, попутно упаковывая INTEGER'ы в байты.
-
Ну можно спросить у него... ;)
По поводу этого http://oberspace.dyndns.org/index.php/topic,484.0.html
лично я бы не использовал Get8/Put8. Мне кажется что гораздо проще все вычисления делать на INTEGER и просто сделать одну процедуру PackToBytes(src: ARRAY OF INTEGER, adr: INTEGER), которая просто пересылает данные в видеобуфер, попутно упаковывая INTEGER'ы в байты.
Дорого.
-
Ну дешевле наверно только специальные команды пересылки....
ps Или ты про память?
-
Блин, с арихметикой не дружу... :)
так должно быть там (640 * 480 DIV WORDSIZE)
-
Ну дешевле наверно только специальные команды пересылки....
ps Или ты про память?
Я про всё. И про лишние копирования, и про то что в результате у нас объем данных увеличивается в 4 раза, что вполне вероятно приведет к тому, что оно не влезет в кеш процессора (и начнет в результате дико тормозить), и про то что это будет да, лишняя память.
-
Тогда маш. код :) Ведь тебя не пугает написание двух маленьких процедур в маш. кодах? ;)
Кстати, поправил Put8:
PROCEDURE Put8(pos, val: INTEGER);
VAR adr, int: INTEGER;
BEGIN
adr := SYSTEM.ADR(bytes^);
ASSERT(pos < LEN(bytes) * WORDSIZE);
ASSERT((val >= 0) & (val <= 255));
SYSTEM.GET(adr + pos, int);
SYSTEM.PUT(adr + pos, SYSTEM.VAL(SET, int) - {0..7} + SYSTEM.VAL(SET, val));
END Put8;
ps Наверно есть более элегантные и производительные способы, но нужно иметь опыт чтобы быстро сообразить...
-
valexey, вот такой код отрабатывает у меня за 2 секунды
MODULE MyTest;
IMPORT SYSTEM, Log;
CONST WORDSIZE = SIZE(INTEGER);
PROCEDURE Do*;
VAR
ints: POINTER TO ARRAY OF INTEGER;
bytes: POINTER TO ARRAY OF INTEGER;
i: INTEGER;
PROCEDURE Get8(pos: INTEGER): INTEGER;
VAR adr, val: INTEGER;
BEGIN
adr := SYSTEM.ADR(bytes^);
ASSERT(pos < LEN(bytes) * WORDSIZE);
SYSTEM.GET(adr + pos, val);
RETURN val MOD 256;
END Get8;
PROCEDURE Put8(pos, val: INTEGER);
VAR adr, int: INTEGER;
BEGIN
adr := SYSTEM.ADR(bytes^);
ASSERT(pos < LEN(bytes) * WORDSIZE);
ASSERT((val >= 0) & (val <= 255));
SYSTEM.GET(adr + pos, int);
SYSTEM.PUT(adr + pos, SYSTEM.VAL(SET, int) - {0..7} + SYSTEM.VAL(SET, val));
END Put8;
PROCEDURE PackToBytes(VAR src: ARRAY OF INTEGER; adr: INTEGER);
VAR i: INTEGER;
BEGIN
FOR i := 0 TO LEN(src) - 1 BY 4 DO
SYSTEM.PUT(adr + i, src[i] +
SYSTEM.LSH(src[i+1], 8) +
SYSTEM.LSH(src[i+2], 16) +
SYSTEM.LSH(src[i+3], 24));
END;
END PackToBytes;
BEGIN
NEW(ints, (640 * 480 * 3));
NEW(bytes, (640 * 480 * 3 DIV WORDSIZE));
(*
Put8(0, 0);
Put8(1, 1);
Put8(2, 255);
Put8(3, 200);
*)
ints[0] := 0;
ints[1] := 1;
ints[2] := 255;
ints[3] := 200;
FOR i := 0 TO 1000 DO
PackToBytes(ints, SYSTEM.ADR(bytes^));
END;
Log.Int(Get8(0)); Log.Ln;
Log.Int(Get8(1)); Log.Ln;
Log.Int(Get8(2)); Log.Ln;
Log.Int(Get8(3)); Log.Ln;
END Do;
BEGIN
END MyTest.Do
-
Ну и такой вариант совсем немного медленнее:
PROCEDURE PackToBytes2(VAR src, dst: ARRAY OF INTEGER);
VAR i, j: INTEGER;
BEGIN
j := 0;
FOR i := 0 TO LEN(src) - 1 BY 4 DO
dst[j] := src[i] +
SYSTEM.LSH(src[i+1], 8)+
SYSTEM.LSH(src[i+2], 16)+
SYSTEM.LSH(src[i+3], 24);
INC(j);
END;
END PackToBytes2;
А в Обероне это даже без SYSTEM будет