Oberon space

General Category => Общий раздел => Тема начата: vlad от Октябрь 11, 2013, 05:54:37 am

Название: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 05:54:37 am
Итак, pure Oberon-07 (без динамических массивов). Пытаемся написать модуль для работы со строками любого размера. Минимальный варинт:
- создать строку из ARRAY OF CHAR
- получить размер за O(1)
- получить CHAR по индексу (не знаю как сделать за O(1), но можно попытаться сделать меньше, чем за O(n))
Вот, что у меня получилось:
MODULE String;
CONST
    offs8 = 8;
    offs16 = 8 + 16;
    offs32 = offs16 + 32;
    offs64 = offs32 + 64;
    offs128 = offs64 + 128;
    offs256 = offs128 + 256;
    offs512 = offs256 + 512;
    offs1024 = offs512 + 1024;
    chunkSize = 4096;
TYPE
    Type* = POINTER TO RECORD
        size: INTEGER;
        data: ARRAY 8 OF CHAR;
        next: POINTER TO Data16
    END;
    Data16 = RECORD
        data: ARRAY 16 OF CHAR;
        next: POINTER TO Data32
    END;
    Data32 = RECORD
        data: ARRAY 32 OF CHAR;
        next: POINTER TO Data64
    END;
    Data64 = RECORD
        data: ARRAY 64 OF CHAR;
        next: POINTER TO Data128
    END;
    Data128 = RECORD
        data: ARRAY 128 OF CHAR;
        next: POINTER TO Data256
    END;
    Data256 = RECORD
        data: ARRAY 256 OF CHAR;
        next: POINTER TO Data512
    END;
    Data512 = RECORD
        data: ARRAY 512 OF CHAR;
        next: POINTER TO Data1024
    END;
    Data1024 = RECORD
        data: ARRAY 1024 OF CHAR;
        next: POINTER TO Chunk
    END;
    Chunk = RECORD
        data: ARRAY chunkSize OF CHAR;
        next: POINTER TO Chunk
    END;

PROCEDURE fromArray*(a: ARRAY OF CHAR): Type;
VAR
    result: Type;
   
    PROCEDURE copy(from: INTEGER; VAR dst: ARRAY OF CHAR): BOOLEAN;
    VAR
        i: INTEGER;
    BEGIN
        WHILE (i < LEN(dst)) & (i + from < LEN(a)) DO
            dst[i] := a[i + from];
            INC(i);
        END;
        RETURN i + from < LEN(a)
    END copy;

    PROCEDURE copyToChunks();
    VAR
        i: INTEGER;
        from: INTEGER;
        chunk: POINTER TO Chunk;
    BEGIN
        from := offs1024;
        NEW(chunk);
        result.next.next.next.next.next.next.next.next := chunk;
        WHILE from < LEN(a) DO
            IF i = LEN(chunk.data) THEN
                NEW(chunk.next);
                chunk := chunk.next;
                i := 0;
            END;
            chunk.data[i] := a[from];
            INC(i);
            INC(from);
        END;
    END copyToChunks;

BEGIN
    NEW(result);
    IF copy(0, result.data) THEN
        NEW(result.next);
        IF copy(offs8, result.next.data) THEN
            NEW(result.next.next);
            IF copy(offs16, result.next.next.data) THEN
                NEW(result.next.next.next);
                IF copy(offs32, result.next.next.next.data) THEN
                    NEW(result.next.next.next.next);
                    IF copy(offs64, result.next.next.next.next.data) THEN
                        NEW(result.next.next.next.next.next);
                        IF copy(offs128, result.next.next.next.next.next.data) THEN
                            NEW(result.next.next.next.next.next.next);
                            IF copy(offs256, result.next.next.next.next.next.next.data) THEN
                                NEW(result.next.next.next.next.next.next.next);
                                IF copy(offs512, result.next.next.next.next.next.next.next.data) THEN
                                    copyToChunks();
                                END;
                            END;
                        END;
                    END;
                END;
            END;
        END;
    END;

    result.size := LEN(a);
    RETURN result
END fromArray;   

PROCEDURE size*(s: Type): INTEGER;
    RETURN s.size
END size;

PROCEDURE at*(s: Type; index: INTEGER): CHAR;
VAR
    result: CHAR;

    PROCEDURE chunkAt(): CHAR;
    VAR
        i: INTEGER;
        chunk: POINTER TO Chunk;
    BEGIN
        chunk := s.next.next.next.next.next.next.next.next;
        FOR i := 0 TO ((index - offs1024) DIV chunkSize) - 1 DO
            chunk := chunk.next;
        END;
        RETURN chunk.data[(index - offs1024) MOD chunkSize]
    END chunkAt;

BEGIN
    IF index < offs8 THEN
        result := s.data[index];
    ELSIF index < offs16 THEN
        result := s.next.data[index - offs8];
    ELSIF index < offs32 THEN
        result := s.next.next.data[index - offs16];
    ELSIF index < offs64 THEN
        result := s.next.next.next.data[index - offs32];
    ELSIF index < offs128 THEN
        result := s.next.next.next.next.data[index - offs64];
    ELSIF index < offs256 THEN
        result := s.next.next.next.next.next.data[index - offs128];
    ELSIF index < offs512 THEN
        result := s.next.next.next.next.next.next.data[index - offs256];
    ELSIF index < offs1024 THEN
        result := s.next.next.next.next.next.next.next.data[index - offs512];
    ELSE
        result := chunkAt();
    END
    RETURN result
END at;

END String.

Тестируем это безобразие:
MODULE TestString;
IMPORT String;
CONST
    longStringSize = 1024 * 100 + 1;
VAR
    s: String.Type;
    testArray: ARRAY longStringSize OF CHAR;
    i: INTEGER;
BEGIN
    s := String.fromArray("abc");
    ASSERT(String.size(s) = 3);
    ASSERT(String.at(s, 0) = "a");
    ASSERT(String.at(s, 1) = "b");
    ASSERT(String.at(s, 2) = "c");

    FOR i := 0 TO LEN(testArray) - 1 DO
        testArray[i] := CHR(i);
    END;
    s := String.fromArray(testArray);
    ASSERT(String.size(s) = LEN(testArray));
    FOR i := 0 TO LEN(testArray) - 1 DO
        ASSERT(testArray[i] = String.at(s, i));
    END;

END TestString.
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 06:15:33 am
Что не нравится в этом решении (помио отсутствия динамических массивов, которые сделали бы решение тривиальным):
- Жуткий копипаст (привет джерекам).
- Огроменная лестница IF'ов (из-за единственности RETURN). Можно завести булевую переменную и проверять ее каждый раз... но зачем?
- Запись String.at(s, index) для доступа к элементу строки осилят только религиозно обработанные писатели (привет перегрузке операторов).
- Строка всегда будет в хипе (давайте представим, что транслируем не в JS). И с этим ничего нельзя сделать, если потребовать иммутабельности строки (мутабельные строки не нужны). Привет конструкторам.
- Доступ к элементу за O(n), хотя n и поделено на довольно большую константу. Более быстрый доступ требует более сложной реализации.

 
Название: Re: Делаем строку на O7
Отправлено: adva от Октябрь 11, 2013, 07:09:08 am
Извиняюсь, что не в тему:

Не могу сообразить, какие типы использовать, чтобы получить следующее:
Нужна таблица, в которой одна из колонок была бы ссылка на объект составного типа (в терминах 1С).

Таблица, как понимаю МАССИВ. Колоноки обеспечиваются ЗАПИСЬю

Но вот не соображу, как задать СВОЙСТВО данной ЗАПИСИ составного типа (чтобы можно было присвоить, например и ТИП1 и ТИП2)
Название: Re: Делаем строку на O7
Отправлено: adva от Октябрь 11, 2013, 07:16:38 am
И вдогонку, в итоге нужна будет одна функция, возвращающая объекты разных типов. Это реализуется с помощью ПРОЦЕДУРНОГО типа?
Название: Re: Делаем строку на O7
Отправлено: Илья Ермаков от Октябрь 11, 2013, 07:43:37 am
Таки это попытки использовать язык для встроенки на прикладном уровне, имхо.
Вирт порезал его для того, чтобы это всюду влезало, а не чтобы так строки на нём реализовывать :)
Название: Re: Делаем строку на O7
Отправлено: DddIzer от Октябрь 11, 2013, 07:54:55 am
Таки это попытки использовать язык для встроенки на прикладном уровне, имхо.
Вирт порезал его для того, чтобы это всюду влезало, а не чтобы так строки на нём реализовывать :)
только сам Вирт про это ничего не говорил.. видать не влезло в 16 страниц... хотя вроде место для  general purpose language - у него нашлось.. ;)
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Октябрь 11, 2013, 08:53:53 am
Таки это попытки использовать язык для встроенки на прикладном уровне, имхо.
Вирт порезал его для того, чтобы это всюду влезало, а не чтобы так строки на нём реализовывать :)
Стоп. А как отсутствие массивов с размером неизвестным на этапе компиляции облегчает влезабельность в микроконтроллер?

PS. а чтобы оно везде влезало нужно было отвязываться от 32 бит. А то в msp430 оно, в отличие от С++, до сих пор не влазит.
Название: Re: Делаем строку на O7
Отправлено: Илья Ермаков от Октябрь 11, 2013, 09:53:12 am
Ну, я так понимаю рантайм упрощается - это раз;
во-вторых, чтобы любой компонент, написанный на языке X, мог быть использован в любом окружении, можно пойти как раз путём сделать невозможным программировать так, что потом конкретный компонент не влезет в конкретное системное окружение (типа, писали на КП библиотеку - внутри понаюзали дин. массивов, потом микроконтроллерщики, допустим, на том же КП захотели использовать эту библиотеку - а оп-па, этот компонент требует кучи не слабого размера и т.п. А запретим дин. массивы - так все будут осмотрительнее по использованию памяти). Возможна такая логика.
Кроме того, Вирт давно смотрел в сторону компиляции с ЯП прямо в схемную топологию, может, из-за этого тоже такие эксперименты с урезанием языка...
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Октябрь 11, 2013, 10:27:25 am
Ну, я так понимаю рантайм упрощается - это раз;
Если подумать, то нет, не упрощается - менеджер памяти на практике остается тем же самым - размещающим блоки произвольного размера в куче.

Либо нужно сурово усложнить рантайм, сделать его сборку зависящим от сборки основного приложения - усложнить компилятор, чтобы он проводил глубокий анализ кодов приложения и на основе этого генерировал код рантайма. В этом случае да, теоретически возможно скажем уменьшить вероятность фрагментации кучи во время работы.

во-вторых, чтобы любой компонент, написанный на языке X, мог быть использован в любом окружении, можно пойти как раз путём сделать невозможным программировать так, что потом конкретный компонент не влезет в конкретное системное окружение (типа, писали на КП библиотеку - внутри понаюзали дин. массивов, потом микроконтроллерщики, допустим, на том же КП захотели использовать эту библиотеку - а оп-па, этот компонент требует кучи не слабого размера и т.п. А запретим дин. массивы - так все будут осмотрительнее по использованию памяти).
Запрет динамических массивов скорее приведет либо к написанию собственного менеджера памяти и собственных Opaque-массивов, либо к ПЕРЕРАСХОДУ памяти в куче и на стеке. Ибо брать будут с запасом, чтобы гарантированно поместилось.

Возможна такая логика.
Кроме того, Вирт давно смотрел в сторону компиляции с ЯП прямо в схемную топологию, может, из-за этого тоже такие эксперименты с урезанием языка...
А вот на попытку скрестить ежа с ужом действительно немного похоже. Но еще более похоже на еще большее упрощение языка, на подтягивание его еще ближе к Си (С89) - там тоже нет динамических массивов. Правда там и NEW нет, так что следующим логическим шагом для Вирта было бы выпиливание NEW вообще.

Нужно что-то разместить в куче? Делайте через SYSTEM!

PS. А есть еще более странные изменения в Обероне-07/11 относительно Оберона изначального: http://oberspace.dyndns.org/index.php/topic,544.0.html Мы так и не смогли придумать нафига это может быть нужно.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 10:58:43 am
Из всего, что сказано, 07 это универсальный язык или нет? Сам Вирт, что пишет по этому поводу? Это дальнейшее развитие языка оберон или узконацеленная ветка языка, для конкретных задач?
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 11:02:42 am
И такой вопрос, имеет ли смысл запрет дин массивов для программирования микроконтроллёров?
И ещё вопрос, обосновывает ли Вирт, удаление возможностей из языка? Исключил потому, что мол так и так.
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Октябрь 11, 2013, 11:04:31 am
Из всего, что сказано, 07 это универсальный язык или нет? Сам Вирт, что пишет по этому поводу? Это дальнейшее развитие языка оберон или узконацеленная ветка языка, для конкретных задач?
Судя по репорту - это дальнейшее развитие Оберона. Там нет ни слова про "Oberon-07" - это чисто наше изобретение. Это просто Oberon, новая, уточненная и дополненная ревизия репорта.
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Октябрь 11, 2013, 11:08:25 am
И такой вопрос, имеет ли смысл запрет дин массивов для программирования микроконтроллёров?
Для программирования микроконтроллеров (и не только) имеет смысл запрет NEW (кучи) вообще. Точнее, по хорошему, NEW вынести бы в либы (тогда был бы один набор либ для скажем микроконтроллеров, другой для десктопа). Но семантика NEW такова, что языковыми методами библиотечно NEW сделать не возможно. Видимо поэтому NEW Вирт до сих пор из языка не выпилил - чтобы NEW стала обычной процедурой пришлось бы существенно усложнить язык.

И ещё вопрос, обосновывает ли Вирт, удаление возможностей из языка? Исключил потому, что мол так и так.
По поднятым тут вопросам обоснований я не видел. Ну и Вирт на письма не отвечает, увы.
Название: Re: Делаем строку на O7
Отправлено: Geniepro от Октябрь 11, 2013, 01:09:43 pm
И вдогонку, в итоге нужна будет одна функция, возвращающая объекты разных типов. Это реализуется с помощью ПРОЦЕДУРНОГО типа?

А на каком языке? Если на обероне, то это делается с помощью наследования записей.
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 02:44:25 pm
Но вот не соображу, как задать СВОЙСТВО данной ЗАПИСИ составного типа (чтобы можно было присвоить, например и ТИП1 и ТИП2)

Классический ООП подход - завести базовый "безтиповый" тип и наследовать от него "типизированные". Везде, где нужна "безтиповость" такскать базовый, а там где нужен тип - кастить к "типизированному". На O7:
TYPE
    AnyType = RECORD END;
    Type1 = RECORD(AnyType) field: INTEGER END;
    Type2 = RECORD(AnyType) field: CHAR END;
    PAnyType: POINTER TO AnyType;

PROCEDURE getObject(): PAnyType; (* возвращает любой объект*)
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 02:51:21 pm
Таки это попытки использовать язык для встроенки на прикладном уровне, имхо.
Вирт порезал его для того, чтобы это всюду влезало, а не чтобы так строки на нём реализовывать :)

Да, если бы Вирт объяснил для чего он порезал язык, то разборок было бы сильно меньше... А по поводу применимости в контроллерах я согласен с valexey_u. Добавлю только, что в астробовской версии динамические массивы есть, но только на стеке (неплохой компромисс, по-моему).
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 02:56:40 pm
(типа, писали на КП библиотеку - внутри понаюзали дин. массивов, потом микроконтроллерщики, допустим, на том же КП захотели использовать эту библиотеку - а оп-па, этот компонент требует кучи не слабого размера и т.п. А запретим дин. массивы - так все будут осмотрительнее по использованию памяти). Возможна такая логика.

Ну вот даже на примере из топика видно, что это не так - получившаяся у меня строка неэффективна по памяти и в любой микроконтроллер не засунется...
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 04:43:08 pm
А запретим дин. массивы - так все будут осмотрительнее по использованию памяти).

Хочу отметить еще вот какой момент. В данном примере я приложил определенные усилия (выразившиеся в не совсем тривиальном коде и потраченном времени), чтобы реализация вообще не была полным гавном. В общем случае будет большой соблазн зафигачить связный список CHAR'ов и все (боролись за осмотрительность использования хипа - а получили жуткий оверхед по этому самом хипу). Потому что так проще. И если десктоп такое "простое, но гавно" еще потянет, то для микроконтроллера все равно придется переписывать.

Это я все к идее о том, что простота языка в какой-то момент начинает бить по простоте решений на этом языке. Вплоть до брэйнфака. И есть какой-то оптимум, который может двигаться в одну и другую сторону в зависимости от характера задач. Так вот, по моим текущим ощущениям в случае O7 есть сильное смещение от оптимума (для заявленного general purpose language) в сторону простоты языка. Т.е., решения general purpose задач оказываются неоправданно сложными или неэффективными.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 05:53:25 pm
vlad

Цитировать
Хочу отметить еще вот какой момент. В данном примере я приложил определенные усилия (выразившиеся в не совсем тривиальном коде и потраченном времени), чтобы реализация вообще не была полным гавном. В общем случае будет большой соблазн зафигачить связный список CHAR'ов и все (боролись за осмотрительность использования хипа - а получили жуткий оверхед по этому самом хипу). Потому что так проще. И если десктоп такое "простое, но гавно" еще потянет, то для микроконтроллера все равно придется переписывать.

Я бы реализовал так. STRING: ARRAY 1024 OF CHAR;
Если вдруг станет мало, увеличу. Уверен для большинства задач, со строками подойдёт.

И останется обычное обращение к массиву s[i].

Или сделать через запись.

STRING = RECORD
  DATA: ARRAY 1024 OF CHAR;
  SIZE: INTEGER; длина строки символов, что бы не проходить весь массив.
END

Но в таком варианте обращение через функцию. Вроде StrIdx(S, 5); Или S.Data[5]

Цитировать
Это я все к идее о том, что простота языка в какой-то момент начинает бить по простоте решений на этом языке. Вплоть до брэйнфака. И есть какой-то оптимум, который может двигаться в одну и другую сторону в зависимости от характера задач. Так вот, по моим текущим ощущениям в случае O7 есть сильное смещение от оптимума (для заявленного general purpose language) в сторону простоты языка. Т.е., решения general purpose задач оказываются неоправданно сложными или неэффективными.

07 переступил эту черту, и гордо шагает. :)
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 05:58:51 pm
В такой реализации перерасход памяти. В исходниках А2, используются строки разных размеров
STRING16
STRING32

Нужно посмотреть реализацию.
Название: Re: Делаем строку на O7
Отправлено: Илья Ермаков от Октябрь 11, 2013, 06:13:46 pm
И такой вопрос, имеет ли смысл запрет дин массивов для программирования микроконтроллёров?

Вообще, для любых приложений 24*365 лучше использовать выделение только фиксированных размеров блоков. Дабы не нарваться на полную фрагментацию памяти. В целом, когда у вас нет кусков непредсказуемого размера, дин. память эффективнее используется.
Название: Re: Делаем строку на O7
Отправлено: Илья Ермаков от Октябрь 11, 2013, 06:16:53 pm
Это я все к идее о том, что простота языка в какой-то момент начинает бить по простоте решений на этом языке. Вплоть до брэйнфака. И есть какой-то оптимум, который может двигаться в одну и другую сторону в зависимости от характера задач. Так вот, по моим текущим ощущениям в случае O7 есть сильное смещение от оптимума (для заявленного general purpose language) в сторону простоты языка. Т.е., решения general purpose задач оказываются неоправданно сложными или неэффективными.

Согласен.
О7 - это культурный, строго типизированный аналог С.

Название: Re: Делаем строку на O7
Отправлено: valexey_u от Октябрь 11, 2013, 06:49:43 pm
Это я все к идее о том, что простота языка в какой-то момент начинает бить по простоте решений на этом языке. Вплоть до брэйнфака. И есть какой-то оптимум, который может двигаться в одну и другую сторону в зависимости от характера задач. Так вот, по моим текущим ощущениям в случае O7 есть сильное смещение от оптимума (для заявленного general purpose language) в сторону простоты языка. Т.е., решения general purpose задач оказываются неоправданно сложными или неэффективными.

Согласен.
О7 - это культурный, строго типизированный аналог С.
Не выйдет сделать аналог Си строго типизированным. Отсюда, собственно, все беды Оберона-07. Банально malloc не сделать. Си вот отлично обходится без массивов переменной длины.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 08:48:31 pm
Можно сделать так.

Работа со строками происходит, только в статике. Для этого можно сделать массивы разных размеров.

Пример.
TinyString = 16 символов
SmallString = 64 символа
SizeString = 256 символов
HugeString = 1024 символа

В модуле объявляем string := HugeString; И понеслась.

Удобства, одни и те же процедуры для всех типов, плюс умеренный расход памяти.

Дополнительно реализовать тип Text для работы с многомегобайтными строками. Здесь уже идёт деления на чанки, как предлагал Влад.

Разделяем обязанности. Если нужны простые строки выбираем один из стрингов, если, что побольше уже работа с текстом.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 09:10:59 pm
А вообще если отвлечься. Становится даже грустно. То, что на с++, питоны, джавы, руби делается двумя строками, да те самые контейнеры. На оберон языках нужно, рвать и метать... ???
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 11, 2013, 09:13:58 pm
С каждым новым оберон языком под рапортом Вирта, лопата становится меньше, а яму копать глубже. ИМХО.
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 11, 2013, 11:29:58 pm
TinyString = 16 символов
SmallString = 64 символа
SizeString = 256 символов
HugeString = 1024 символа

Не, это тупиковый путь. Вот смотри - я пишу компилятор на обероне :) И у меня естественным образом возникает некая сруктурка, в которой я буду держать, например, распарсенный идентификатор переменной. Вот мне какую строку под это дело взять? 16? Не, маловато. 32? Должно хватить. А вдруг тексты на обероне начнут генерить и компилить моим компилятором - фиг знает чего там нагенерят и упрутся в эти 32. Ладно, возьму 1024 - хватит всем (гхм, ну с вероятностью близкой к 1). Но с другой стороны для большинства случаев получаем оверхед в расходе памяти на 2 порядка. Плюс еще пишем в документации (вроде у arkon'а как раз было) - "нельзя использовать идентификаторы больше 1024". Пользователь читает такую доку и недоумевает - а почему, собственно? Че за херня? А! Это потому что в обероне (на котором писался компилятор) нет нормальных строк.

P.S. Кстати реальный случай. В 6-й студии (вроде) было ограничение 255 на длину идентификатора в отладочной информации. Хорошо еще, что это был warning, а не error. Соответственно линковщик мусорил этими варнингами. Ну и понятно, что у них там тоже не было строк, а был где-то char buffer[256];.

P.S.S. Конечно Вирт в своей книжке про компиляторы не гнушается использовать ARRAY 16 OF CHAR для этих самых идентификаторов. Ну так то в учебной книжке - почему бы и нет. Но в промышленном коде - это уже попахивает...
Название: Re: Делаем строку на O7
Отправлено: Илья Ермаков от Октябрь 12, 2013, 05:34:26 am
Ну, можно ещё задавать размер массива константой.
И для системного уровня не привыкать вводить такие ограничения, типа максимальной длины имени...
Даже твой пример несколько надуманный - если кто-то упрётся в эти 32, переделает генерацию имён. Зачем имена длиннее 64, допустим? "Шоб была возможность"? :)

Вообще, строки - штука хитрая... Очень от задачи зависит.
Можно и вообще делать спец. кучу для строк, где хранить их по ID. Кстати, Губанов, кажется, на такое переходил, когда избавлялся от managed memory в своём софте...
Название: Re: Делаем строку на O7
Отправлено: Илья Ермаков от Октябрь 12, 2013, 05:36:52 am
А вообще если отвлечься. Становится даже грустно. То, что на с++, питоны, джавы, руби делается двумя строками, да те самые контейнеры. На оберон языках нужно, рвать и метать... ???

В плане того, что О7 - пониженного уровня язык, я говорил, поэтому я не доказываю, что с ним в типовых задачах всё замечательно.
Но хочу заметить, что часто проблемы надумываются, пока не решается конкретная задача. Если сидеть и думать "А как же я буду делать вот это, если оно мне понадобится", то голову сломаешь. А когда есть конкретный контекст, конкретные требования - то и вырабатываются решения. Которые потом иногда обобщаются.
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 12, 2013, 06:54:08 am
Ну, можно ещё задавать размер массива константой.
И для системного уровня не привыкать вводить такие ограничения, типа максимальной длины имени...

Никто не говорит, что константный размер не нужен. Особенно в плане оптимизаций. Пусть будет. Просто действительно много случаев, когда и диапазон большой и оптимизировать нечего.
Посмотри на те же классические БД. Уж насколько тщательно там высчитывают размер колонки CHAR - и все равно расширяют потом. В то же время всегда есть тип TEXT - не такой эффективный как CHAR, но не менее востребованный.

Кстати, Губанов, кажется, на такое переходил, когда избавлялся от managed memory в своём софте...

Да, он боролся с GC. И согласись, у него довольно специфический случай, когда от универсальных строк действительно имеет смысл отказаться.
Название: Re: Делаем строку на O7
Отправлено: vlad от Октябрь 12, 2013, 06:59:46 am
А когда есть конкретный контекст, конкретные требования - то и вырабатываются решения. Которые потом иногда обобщаются.

Ну я и пошел от конкретного контекста - что в компиляторе уже сейчас можно переписать на O7. И сразу уперся в строки, потому что они везде :)
Название: Re: Делаем строку на O7
Отправлено: Губанов Сергей Юрьевич от Октябрь 14, 2013, 10:43:57 am
Итак, pure Oberon-07 (без динамических массивов). Пытаемся написать модуль для работы со строками любого размера.
Я на оберонах разучился писать, вот идея на псевдоязыке:

struct MemoryBlock
{
virtual size_t size () = 0;
virtual void put (size_t position, char value) = 0;
virtual char get (size_t position) = 0;
};

struct MemoryBlock8b: public MemoryBlock
{
char buffer[8];

size_t size ()
{
return 8;
}

void put (size_t position, char value)
{
this->buffer[position] = value;
}

char get (size_t position)
{
return this->buffer[position];
}
};

struct MemoryBlock16b: public MemoryBlock
{
char buffer[16];

size_t size ()
{
return 16;
}

void put (size_t position, char value)
{
this->buffer[position] = value;
}

char get (size_t position)
{
return this->buffer[position];
}
};

struct MemoryBlock24b: public MemoryBlock
{
char buffer[24];

size_t size ()
{
return 24;
}

void put (size_t position, char value)
{
this->buffer[position] = value;
}

char get (size_t position)
{
return this->buffer[position];
}
};

...и так далее...

MemoryBlock* allocate_memory_block (size_t size)
{
if (size <= 8)
{
return new MemoryBlock8b();
}
if (size <= 16)
{
return new MemoryBlock16b();
}
if (size <= 24)
{
return new MemoryBlock24b();
}
...и так далее...
return 0;
}
Название: Re: Делаем строку на O7
Отправлено: Губанов Сергей Юрьевич от Октябрь 14, 2013, 11:10:18 am
Вообще, для любых приложений 24*365 лучше использовать выделение только фиксированных размеров блоков. Дабы не нарваться на полную фрагментацию памяти. В целом, когда у вас нет кусков непредсказуемого размера, дин. память эффективнее используется.
Фиксированного размера нехорошо: будет перерасход памяти как на очень мелких так и на очень крупных объектах.  Надо выравнивание блока делать прогрессирующим: маленький блок - маленькое выравнивание; а крупнее блок - грубее выравнивание.

Можно и вообще делать спец. кучу для строк, где хранить их по ID. Кстати, Губанов, кажется, на такое переходил, когда избавлялся от managed memory в своём софте...
У меня было два сорта строк: постоянные и временные. Постоянную строку нельзя удалить, зато они внутре суть указатели указывающие на уникальное и неповторимое содержимое (при попытке создать ещё одну строку с уже существующим содержимым возвращается указатель на старое содержимое). Но это не имеет отношения к теме, здесь речь про временную строку: создал, поработал, удалил.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Октябрь 15, 2013, 02:49:22 pm
А вообще если отвлечься. Становится даже грустно. То, что на с++, питоны, джавы, руби делается двумя строками, да те самые контейнеры. На оберон языках нужно, рвать и метать... ???

В плане того, что О7 - пониженного уровня язык, я говорил, поэтому я не доказываю, что с ним в типовых задачах всё замечательно.
Но хочу заметить, что часто проблемы надумываются, пока не решается конкретная задача. Если сидеть и думать "А как же я буду делать вот это, если оно мне понадобится", то голову сломаешь. А когда есть конкретный контекст, конкретные требования - то и вырабатываются решения. Которые потом иногда обобщаются.

Можно обобщить, но только в динамике. Как сейчас делают в си и паскале, через union или record case(Данные алгоритмы могут быть использованы только в реализуемом проекте). И только потому, что бы не копипастить. Мне кажется это высокоуровневый хак.
Название: Re: Делаем строку на O7
Отправлено: kkkk от Ноябрь 08, 2013, 08:09:47 am
Стоп. А как отсутствие массивов с размером неизвестным на этапе компиляции облегчает влезабельность в микроконтроллер?
Если почитать всякие рекомендации по написанию программ для встраиваемых устройств, например, промышленный стандарт MISRA C, то там Вы можете обнаружить (обязательное/рекомендационное) требование - не использовать динамическое выделение памяти, а значит прощай и динамические массивы. Оберон не настолько суров, но очевидно сделал шаг в этом направлении.
Название: Re: Делаем строку на O7
Отправлено: kkkk от Ноябрь 08, 2013, 08:18:18 am
Ну я и пошел от конкретного контекста - что в компиляторе уже сейчас можно переписать на O7. И сразу уперся в строки, потому что они везде :)
Для компилятора, особенно Оберона, не нужны строки с произвольным доступом. Да и учитывая контекст задачи, её можно реализовать с такими накладными расходами по памяти, которые  недостижимы при использовании отдельных динамических строк. Просто не нужно пытаться делать обобщённое решение, в данном случае Оберон 07 к этому не располагает.
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Ноябрь 08, 2013, 08:36:46 am
Стоп. А как отсутствие массивов с размером неизвестным на этапе компиляции облегчает влезабельность в микроконтроллер?
Если почитать всякие рекомендации по написанию программ для встраиваемых устройств, например, промышленный стандарт MISRA C, то там Вы можете обнаружить (обязательное/рекомендационное) требование - не использовать динамическое выделение памяти, а значит прощай и динамические массивы. Оберон не настолько суров, но очевидно сделал шаг в этом направлении.
Я это и сам практикую когда под микроконтроллеры пишу - динамическое выделение памяти там вовсе ни к чему. Тем более что в Си прям таки в языке нет средств для этого :-) (есть в стандартной либе).

Но если бы это был шаг в ту сторону, то прежде всего нужно было бы запретить в Обероне NEW вообще (перетащить его в SYSTEM или в другой псевдомодуль). Убирание лишь одной разновидности NEW никак не избавляет от кучи. И не упрощает работу менеджера памяти.

Кроме того, чтобы при этом жилось таки легче, нужно было сделать возможность создания массивов на стеке длиной неизвестной на этапе компиляции. Как это сделано в С99, и как это сделано расширизмом в Astrobe.

То есть этот момент в Обероне сейчас явно как-то не доработан. Повсему выходит, что Оберон (если не менять основы языка) нужно расширять несколькими опциональными стандартными псевдомодулями, вынося туда тот же NEW например. Будет Oberon report и у нему несколько Annex'ов для разных применений.
Название: Re: Делаем строку на O7
Отправлено: kkkk от Ноябрь 08, 2013, 08:56:31 am
Цитировать
Убирание лишь одной разновидности NEW никак не избавляет от кучи. И не упрощает работу менеджера памяти.
Не могу судить однозначно, зависит от реализации, но по-моему упрощает, ибо все динамически выделенные штуки имеют постоянный размер, их можно проще складировать/замещать друг другом.
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Ноябрь 08, 2013, 09:40:53 am
Цитировать
Убирание лишь одной разновидности NEW никак не избавляет от кучи. И не упрощает работу менеджера памяти.
Не могу судить однозначно, зависит от реализации, но по-моему упрощает, ибо все динамически выделенные штуки имеют постоянный размер, их можно проще складировать/замещать друг другом.

Ну, про это я уже писал: http://oberspace.dyndns.org/index.php/topic,552.msg18360.html#msg18360

Менеджер памяти ничего не знает о множестве типов (и их размеров соответственно) которыми будет оперировать данный конкретный модуль или совокупность модулей. Так что он в любом случае должен быть готов ко всему. Упрощения тут нет.
Название: Re: Делаем строку на O7
Отправлено: kkkk от Ноябрь 08, 2013, 10:00:12 am
Это всё на уровне кажется. Я и писал, что не могу судить однозначно, но очевидно дополнительное свойство, а насколько оно полезно, можно будет сказать, помахав кувалдой да посозерцав за полученным.
Название: Re: Делаем строку на O7
Отправлено: adva от Ноябрь 10, 2013, 02:41:58 am
Подскажите, пожалуйста, а LEN(v, ind) для массивов, чего возвращает, константную длину массива, или количество заполненных значений? Если второе, то можно наверное было бы использовать для создания строки ARRAY 10, 10, 10 ... OF CHAR? Хотя не знаю, был бы выигрыш тут, или нет
Название: Re: Делаем строку на O7
Отправлено: adva от Ноябрь 10, 2013, 02:58:59 am
Хотя вижу, что возвращает 10, а если как нибудь нулевыми символами забить, или в массивах другой принцип?
Название: Re: Делаем строку на O7
Отправлено: kkkk от Ноябрь 10, 2013, 10:13:49 am
Для любых массивов, хоть литерных, хоть каких-либо других LEN должна вернуть длину массива, а не строки.
Название: Re: Делаем строку на O7
Отправлено: vlad от Март 15, 2014, 05:19:34 am
Вот что получилось в oberonjs:
https://github.com/vladfolts/oberonjs/wiki/eberon-strings
Критикуйте :)
Название: Re: Делаем строку на O7
Отправлено: Jordan от Март 15, 2014, 02:47:43 pm
Вот что получилось в oberonjs:
https://github.com/vladfolts/oberonjs/wiki/eberon-strings
Критикуйте :)

Что критиковать? Отличная работа, теперь в языке нормальные строки, которые должны быть.
Как дела обстоят с юникодом? Будет отдельный тип вроде WSTRING, или при компиляции можно выбрать, считать STRING unicod'ом?

Во free pascal'е 2 вариант, есть ключ компиляции, который string заменяет на wstring. Исходники переделывать не нужно. По умолчанию utf8. Как мне кажется, лучше сделать по умолчанию utf32, а уже в зависимости от системы, внутренние функции будут конвертировать в системную кодировку. К примеру в windows utf16, в linux utf8.
Название: Re: Делаем строку на O7
Отправлено: vlad от Март 15, 2014, 03:31:48 pm
Как дела обстоят с юникодом?

Ну конкретно в JS реализации деваться особо некуда - строки напрямую отображаются на JS строки. Соответственно юникод поддерживается ровно настолько, насколько он поддерживается исполняющим JS движком.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Март 15, 2014, 03:33:50 pm
Что, то я сглючил. Код же в js компилируется. Спишем, на недосып.
Название: Re: Делаем строку на O7
Отправлено: Jordan от Март 15, 2014, 03:42:53 pm
vlad

MODULE test;
IMPORT JS;
 
VAR
  S1: STRING;
  S2: STRING;
BEGIN
  S1 := "Hello ";
  S2 := "World!";
    JS.alert(S1 + S2);
END test.

Eberon на STRING ругается.
Цитировать
line 5: undeclared identifier: 'STRING'

Изменения ещё не внесены в язык? Компилю в режиме Eberon.
Название: Re: Делаем строку на O7
Отправлено: valexey_u от Март 15, 2014, 07:26:50 pm
vlad

MODULE test;
IMPORT JS;
 
VAR
  S1: STRING;
  S2: STRING;
BEGIN
  S1 := "Hello ";
  S2 := "World!";
    JS.alert(S1 + S2);
END test.

Eberon на STRING ругается.
Цитировать
line 5: undeclared identifier: 'STRING'

Изменения ещё не внесены в язык? Компилю в режиме Eberon.
Онлайн компилятор еще не обновлен, там старая версия. Обновлю завтра.