Важная информация

User Tag List

Страница 1 из 5 12345 ПоследняяПоследняя
Показано с 1 по 10 из 48

Тема: Паскаль о котором не знали...

  1. #1
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Паскаль о котором не знали...

    Сага о CLSN Pascal.
    Часть1.

    Снова мне хотелось бы представить Вам новый древний язык программирования для Атари.

    Прежде всего - это Паскаль.
    Затем, Паскаль ВПОЛНЕ совершенный!
    И, наконец, он - Атарьский. (* Я имею ввиду, что системные вещи Атари в нём весьма заметно реализованы *).

    (* Вот так в CLSN пишутся комментарии (,в отсутствии фигурных скобок...) *)

    Как Вы понимаете, и CC8 и PL65 и CLSN являются ПРЯМЫМИ наследниками ПЕРВОГО языка программирования - ALGOL. Для нас значимо, что синтаксис у наследников заимствует большинство принцыпов синтаксиса родителя.
    Уточню, НЕ САМОГО СИНТАКСИСА, А ПРИНЦЫПОВ!

    Что же внесено нового после ALGOL'а?
    IMHO:
    PL65 - Эклектичность = бессистемная всеядность. (всё новое, что тогда было...)
    CC8 - Приверженность к C = (максимальная безошибочность чтения C текстов, как источника логично-короткого, но полноценного синтаксиса для переносимости.)
    CLSN - Приверженность к Pascal = (максимальная предобработка текстов для беспроблемной их компиляции при условии точного соблюдения правил языка.)

    Откровенно, мне до лампочки на каком языке писать. Хочется найти СВОЙ!
    И CLSN близок к этому. Причин необычайно много! О них я расскажу позднее.

    Давайте, будучи знакомыми с моими ранее опубликованными постами об ассемблере, напишем программку для инверсии строки символов со скоростью ассемблера.
    (* Кстати, в CLSN есть встроенная функция инверсии символов с клавиатуры!
    Но это не то, что нам надо... *).
    Мы хотим - просто взять строку (либо ATASCII, либо INTERNAL) и преобразовать её в инверсную. Здесь строка = короткая (0-255) символов.

    Вот код:

    Код:
    (* Global *)
    var
      _s_temp: string;    (* Temporary global *)
    
    function invStr(s: string): string;
    begin
      _s_temp := s; (* Copy the local to an absolute memory location *)
    
      inline($ac/_s_temp/ (*     LDY _S_TEMP   *)
             $f0/$0c/     (*     BEQ XIT       *)
             $b9/_s_temp/ (* NXT LDA _S_TEMP,Y *)
             $49/$80/     (*     EOR #$80      *)
             $99/_s_temp/ (*     STA _S_TEMP,Y *)
             $88/         (*     DEY           *)
             $d0/$f3);    (*     BNE NXT       *)
                          (* XIT               *)
      invstr := _s_temp;  (* Return the value  *)
    end;
    
    (* Main Procedure *)
    procedure main;
    (* Local *)
    var
      s: string;
    
    begin
      repeat (*repeat this ...*)
        writeln('Enter some string:'); write('>'); (*prompt symbol*)
        readln(s); (*reads line*) writeln; (*place it on screen as input*)
        writeln(invstr(s)); (*place on screen the result*) writeln; (*skip line*)
      until (s=''); (*... to the end of line, looking at chars *)
    end;
    
    (* Calling *)
    begin main; end.

    Как Вы видете, CLSN не различает Прописных и Строчных символов.
    Последний раз редактировалось ezswift; 22.06.2018 в 22:26.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #2
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Часть 2.

    Сага о CLSN Pascal.
    Часть 2.

    В первой части я обещал рассказать о CLSN поподробнее...

    Уверяю, ЕСТЬ о чём.
    Во первых, это среда быстрого программирования со своим Редактором, Компилятором, но без Линкера, так как язык компилирует коды из памяти на диск в машкоды, сразу же получая исполняемую программу ДОСа. Отсутствие же линкера позволяет запускать куски кода прямо из CLSN, что удобно при отладке.

    Насколько я понимаю, CLSN является вторым, после BasicXE языком, полностью использующим расширенную память XL/XE. Причём, переключение банков памяти полностью автоматическое и память можно рассматривать как динамическую. В Паскале полноценно реализована работа с Кучей, и кучей является почти вся расширенная память - 57kb. Кроме этого хорошо реализована работа с записями, что в атарьских языках большая редкость. Если что ещё вспомню, скажу.
    А, да, из предыдущего примера видно, что общение CLSN с Ассемблером похоже на общение с Ассемблером Action! Не удивлюсь, если можно подставлять коды для Action!!!

    Ну, в общем, в процессе изучения CLSN, мне в голову пришла идея IMHO элегантного простого текстового меню, управляемого стрелками, которого так не хватает для Атари.

    Идеи за этим стояли следующие:
    1. Пусть текст меню задаётся строкой. Это - экономно и может раздаваться различными способами.
    2. Строка автоматически разделяется пробелами на слова, являющиеся пунктами меню, кроме этого, открыто или скрыто каждому пункту присваивается индекс, по которому он может быть однозначно определен.
    3. Я совершенно не хочу заботиться ни о длине пункта, ни о выделении памяти.
    То есть программировать буду динамически то есть на Куче.
    4. в качестве носителя меню хочу использовать динамический двусвязный список, так как он позволяет простейшим способом траверсировать цепочку как вперёд, так и назад вдоль списка.
    5. Скорость вычислений при движении по меню совершенно не имеет значения, так как движения пальцев всё равно медленнее.

    В общем, сначала начнём с ДДС - Динамического Двусвязного Списка - Doubly Linked List. Заодно вспомним и Паскаль.

    - Идеологически список является единым мультиконтейнером, все элементы которого связаны между собой по Вашему выбору: - передней, задней или двойной сцепкой. Это - прямой намёк на некий тип самоадресации звеньеа списка.
    - Соответственно, можно различить контейнерную (информационную) часть элемента списка и одну или несколько связных частей.
    - Доступ к списку как к целому осуществляется указателями.

    Если Вы помните, указатели в PL65 являются нетипизированными (void).
    Код:
    POINTER myPtr
    Типизированными их делуют используемые совместно простые переменные типа BASED.
    Код:
    BYTE bVar BASED myPtr INT iVar BASED myPtr
    Однако Паскаль имеет возможнолсть работы с большим количеством сложных программных элементов и вполне достоин простого и эффективного их описания и простых и эффективных методов работы с ними.

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

    В Паскале указатели тоже содержат метаданные об адресации, однако задаётся это всё описанием типов пользователя и они могут быть весьма сложными, хотя описываются они просто. Заодно, данная ситуация намекает насколько пользовательские типы данных необходимы и популярны в Паскале. Строгая типизация языка делает возможность взаимодействовать со сложными типами данных как с простыми - прозрачно. Иными словами, делай правильную работу правильными инструментами!

    Если две переменных описаны одним и тем же типом, то присваивание
    Код:
    complicated1 := complicated2;
    здесь означает полное копирование, со всеми метаданными, независимое от сложности. Также, полностью копируются сложные указательные типы.

    Это в частности значит, что указатели имеют особое значение для списков. Они и обеспечивают ту самую самоадресацию узлов. Соответственно, плохо типизированные указатели не в состоянии справиться с этой функцией.


    Итак, название -
    Код:
    program dll;
    Пользовательские типы -
    Код:
    type
    (* Информационный тип, являющийся записью, в которой хранится поле счетчика типа целое. Эта запись
    будет помещена в каждый узел списка. *)
      infoT = record (* большая T = Type *)
                cnt: integer;
              end;
    
    (* Тип связь, являющийся каким-то указателем на узел, пока ещё не описанный типом. Это - единственное
    исключение в Паскале. Всё остальное требует строгой типизации. *)
      linkT = ^nodeT;
    
    (* Сложный тип узла, являющийся записью, в которой хранится вышеописанный информационный тип и две
    вышеописанных связи, указывающие на узлы (полностью со всеми метаданными) следующий и предыдущий *)
      nodeT = record
                info: infoT;
                next: linkT;
                prev: linkT;
              end;
    Здесь следует отметить, что после полного описания связи - linkT и её подсистемы - узла nodeT, мы уже не нуждаемся в nodeT, так как он сам используется старшим описанием. Нужно пользоваться только описанием связи - linkT.

    Код:
    (* Тип список, описывающий dll как целое и являющийся записью, содержащей связи как с первым,
    так и с последним элементом списка *)
      listT = record
                first: linkT;
                last: linkT;
              end;
    Кроме обычных задач списка нам существенно также отделить работу со списком от работ с самими программными данными, то есть написать несколько подпрограмм, являющихся фактически универсальными библиотеками взаимодействия со списками. Именно поэтому захотелось максимально абстрагировать списки от данных. Именно поэтому был введён тип listT. Реально нам никто не мешал пользоваться только Указателем старта списка, или Указателем его финиша, или обоими. Однако обобщение сокращает нам запоминание лишних слов.

    Тип listT, содержащий необходимые связи, является определяющим для самого смысла двусвязного списка. Если мы теряем связь со списком, - фактически его у нас нет.

    Существует ситуация в которой мы НЕ ТЕРЯЛИ связи со списком, однако элементов в списке нет. То есть теряется смысл списка, как самоуказателя. Выходит и в такой ситуации списка нет? Вовсе неверно.
    - Начиная с Лиспа для этого был придуман вырожденный список NULL, а для Паскаля nil, грубо говоря, признак того, что эта СИСТЕМНАЯ фикция и есть - список. То есть, приравнивая значения связных полей к вырожденным спискам, мы говорим компилятору, что несмотря на некоторые недоразумения, он имеет дело, всё же, со списком. Чтобы создать список нам достаточно прировнять связные поля вырожденным спискам. Void не говорит ни слова из метаданных, nil уже говорит, что наш объект - список и может иметь ВСЕ надлежащие типу поля!

    Первой программной процедурой у нас будет создание списка, но с проверкой на то, не забыли ли мы удалить список с подобным названием. Это - облегчает жизнь. Мы не хотим получить НЕ ТЕ данные и хотим вообще абстрагироваться от данных списка!
    L - параметрическая переменная, передаваемая со всеми пирогами по ссылке (так как указатель)!

    Вот процедура:
    Код:
    (* Переменная, в качестве параметра, нужна, так как список ТАК ИЛИ ИНАЧЕ изменяется
    (Здесь - создаётся) *)
    procedure initList(var L: listT); (*название процедуры*)
    var
    (* Роль nxtP - всегда в цикле переходить своей связью next на следующий узел. Роль delP сначала
    перенять связь с узла nextP, а затем пропустив его вперёд, стереть на Куче память узла, на который
    указывает, т.е. самоуничтожившись. Стирание идёт с первого узла. В цикле.*)
      nxtP, delP: linkT;
    begin
    (* Да, это список, но он пустой. От nil данных не добыть. Складываем ручки. *)
      if L.first = nil then Exit;
    (* если не пустой *)
      nxtP := L.first; (*Нашли следующий. Он - наш первый!*)
    (* Будем занудно искать все следующие, пока какой-нибудь из них не покажет нам nil *)
      while nxtP <> nil do begin (* не последний, определённо... *)
        delP := nxtP; (* delP становиться на nextP (текущий) *)
        nxtP := nxtP^.next; (* передвинем next на next+1 *)
        Dispose(delP); (* а вот с delP разберёмся... *)
      end; (*кружимся в цикле while!!!*)
    (* Стерев память предыдущего списка, возрождаем/создаём список! *)
      L.first := nil;
      L.last := nil;
    end;
    Не забывайте, что Список = большее, чем Узел!
    zen
    Последний раз редактировалось ezswift; 27.06.2018 в 06:27.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  4. #3
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Чтобы работать со списком нам всегда необходимо помнить о двух вещах:
    - Связи узла(тип связь) должны указывать либо на узел, либо на nil. Больше ни на что!
    - Связи списка(тип список) должны указывать либо на узлы, либо на nil. Больше ни на что!
    Иначе крах!

    Чтобы добавить узел к нашему списку, мы в качестве параметров сначала передадим подпрограмме
    сам список, с которым мы работаем(списковый тип), затем временный узел(связной тип), созданный
    в главной программе на Куче.

    Алгоритм:
    Предстоит разобрать несколько вариантов...
    1. Не создан временный узел.
    - Выходим из бесполезной подпрограммы.
    2. Временный узел задан, но не инициализирован как связь.
    - Инициализируем в nil и работаем дальше...
    3. Если переданный в подпрограмму список задан, но пуст
    - Делаем временный узел первым и его же последним элементом списка, работаем дальше...
    4. Если задан, но не пуст...
    а) реинициализация последнего узла
    - Продлеваем связь next последнего в списке узла, ныне указывающую на nil, на наш временный узел
    - Устанавливаем связь prev временного узла на бывший последний узел
    (Здесь узел добавлен, но список об этом нифига не знает)
    б) реинициализация всего списка
    - Переносим связь last списка на временный узел
    Готово!

    Код:
    (* Процедура добавления узла к пустому, или не пустому списку. Параметры передаются по ссылке, а не
    по значению, так как список изменяется! добавлением. *)
    procedure addNode(var L: listT; tmpP: linkT);
    begin
      if tmpP = nil then Exit;
    
      tmpP^.next := nil;
      tmpP^.prev := nil;
    
      if L.first = nil then begin
        L.first := tmpP; L.last := tmpP;
    
      end else begin
        L.last^.next := tmpP;
        tmpP^.prev := L.last;
        L.last := tmpP;
      end;
    end;
    Вот тестовая программа:

    Код:
    program dll;
    (* User types *)
    type
      infoT = record
                cnt: integer;
              end;
    
      linkT = ^nodeT;
    
      nodeT = record
                info: infoT;
                next: linkT;
                prev: linkT;
              end;
    
      listT = record
                first: linkT;
                last: linkT;
              end;
    
    (* Procedures to work with list *)
    procedure initList(var L: listT);
    var
      nxtP, delP: linkT;
    begin
      if L.first = nil then Exit;
    
      nxtP := L.first;
      while nxtP <> nil do begin
        delP := nxtP;
        nxtP := nxtP^.next;
        Dispose(delP);
      end;
    
      L.first := nil;
      L.last := nil;
    end;
    
    procedure addNode(var L: listT; tmpP: linkT);
    begin
      if tmpP = nil then Exit;
    
      tmpP^.next := nil;
      tmpP^.prev := nil;
      if L.first = nil then begin
        L.first := tmpP;
        L.last := tmpP;
      end else begin
        L.last^.next := tmpP;
        tmpP^.prev := L.last;
        L.last := tmpP;
      end;
    end;
    
    (* Main program *)
    var
      list: listT;
      A: linkT;
      i: Integer;
    begin
      list.first := nil;
      list.last := nil;
    
      for i := 1 to 5 do begin
        New(A);
        A^.info.cnt := i;
        AddNode(list, A);
      end;
    
      Writeln('List created:');
      A := list.first;
      i := 0;
      while A <> nil do begin
        Inc(i);
        Writeln(A^.info.cnt);
        A := A^.next;
      end;
      Writeln;
    end.
    Вот паскаль и результат...
    Pascal.zip

    Вот результат
    Нажмите на изображение для увеличения. 

Название:	dll.png 
Просмотров:	201 
Размер:	9.6 Кб 
ID:	65629

    Удачи, zen
    Последний раз редактировалось ezswift; 27.06.2018 в 09:15.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  5. #4
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Сначала хотелось бы сказать пару слов о синтаксисе Паскаля.

    Как следует понимать следующую запись? nxtP^.info.cnt?

    Вспомним из чего состоит узел списка. Прежде всего из информационного поля, являющегося записью.
    Доступ к полям записи ведётся через оператор . - точка.
    То есть info.cnt - это нахождение значения счётчика внутри информационного контейнера.
    Также в узле есть два связных поля prev и next.

    Однако, прежде чем доступаться к значениям, мы должны сначала доступиться к самому узлу.
    Вот как раз адрес самого узла и задаётся следующим образом nxtP^ - сам узел.
    Так как узел сам является записью, то доступ к его информационному полю будет таким nxtP^.info
    И соответственно погружаясь далее в поле счётчика в info записи получаем nxtP^.info.cnt

    В программе нам может понадобиться подпрограмма поиска по числу в счётчике пунктов.

    Вот она:

    Код:
    (*Поиск элемента в списке по данным. Если элемент не найден, то возвращается nil.*)
    function findNode(var A: listT; c: integer): linkT;
    var
      nxtP,resP: linkT;
    begin
    (* Инициализируем результат в nil *)
      resP := nil;
    (* Устанавливаем временный указатель на первый узел *)
      nxtP := A.first;
    (* Траверсируем вперёд, пока не закончился список *)
      while nxtP <> nil do begin
    (* Если данные счётчика достигли заданного знычения *)
        if nxtP^.info.cnt = c then begin
    (* Берём этот узел как результат и выходим из подпрограммы *)
          resP := nxtP; exit;
        end;
    (* Если пока не достигли траверсируем вперёд к концу списка *)
        nxtP := nxtP^.next;
      end;
    (* возвращаем связь узла результата *)
      findNode := resP;
    end;
    А вот набросок программы меню:

    Код:
    program menu;
    (* User types *)
    type
      infoT = record
                cnt: integer;
                dat: string;
              end;
    
      linkT = ^nodeT;
    
      nodeT = record
                info: infoT;
                next: linkT;
                prev: linkT;
              end;
    
      listT = record
                first: linkT;
                last: linkT;
              end;
    
    var
    (* Строка меню и временная строка пункты *)
      mStr,items: string;
    
    (* Procedures to work with list *)
    procedure initList(var L: listT);
    var
      nxtP, delP: linkT;
    begin
      if L.first = nil then Exit;
      nxtP := L.first;
      while nxtP <> nil do begin
        delP := nxtP;
        nxtP := nxtP^.next;
        Dispose(delP);
      end;
      L.first := nil;
      L.last := nil;
    end;
    
    procedure addNode(var L: listT; tmpP: linkT);
    begin
      if tmpP = nil then Exit;
      tmpP^.next := nil;
      tmpP^.prev := nil;
      if L.first = nil then begin
        L.first := tmpP;
        L.last := tmpP;
      end else begin
        L.last^.next := tmpP;
        tmpP^.prev := L.last;
        L.last := tmpP;
      end;
    end;
    
    (* Main program *)
    var
      list: listT;
      A: linkT;
      i: Integer;
    begin
      initList(list);
      clrscr;
      mStr := 'First Second Third Fourth Fifth';
    
      i := 0; items := mStr+' ';
      while pos(' ', items) <> 0 do begin
        New(A); Inc(i);
        A^.info.cnt := i;
        A^.info.dat := copy(items,1,pos(' ', items)-1);
        items := delete(items,1,pos(' ', items));
        AddNode(list, A);
      end;
    
      WriteLn;
      A := list.first;
      while A <> nil do begin
        Write(A^.info.cnt); Writeln('. '+A^.info.dat);
        A := A^.next;
      end;
      Writeln;
    end.
    Здесь оператор pos ищет первый пробел во временной строке items.
    Позиция пробела без единицы и будет длиной первого пункта меню.
    Именно это количество символов и заносится в поле dat созданного оператором New узла.
    После чего первый пункт стирается из строки items вместе с пробелом.
    Так как эти действия зациклены просматривается вся строка items до последнего пробела, который мы программно пришили к строке items. Также в цикле мы наращиваем поле счётчика, автоматически нумеруя пункты меню.

    Вот результат:
    Нажмите на изображение для увеличения. 

Название:	menu.png 
Просмотров:	167 
Размер:	10.0 Кб 
ID:	65636

    Мне кажется, что алгоритм просто очарователен.
    zen
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  6. #5
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Здравствуйте, здравствуйте, здравствуйте!

    Размышляя о том, что мы(знаю, знаю!..) наляпали в программировании на Паскале, я ощущал непрерывный дискомфорт.

    Связан он был с тем, что мы постоянно распылялись по неструктурированному программированию.

    То есть пользуясь тем, что CLSN позволяет компильнуть-запустить, или проверить код, мы далеко уходили от структуры как СИСТЕМЫ, в зону Бейсика := набрал-исполнил.

    Ну, например, если мы зададим _infoT глобальным, мы можем уже начать создавать библиотеку Doubly-Linked Lists. Мы же честно отделили функции списков от функций данных!!!

    ДА!!! У нас очень мало списковых функций, но ведь мы не этим озабочены, правда?

    Я думаю, что автосоздание пунктов меню из строки требует только одной дополнительной функции - Отключения_Пункта, при показе в меню, то есть 'Серый пункт' (Я даже не знаю как его реально делают, но видел!!!) В смысле списка, нужно его сохранить, как связь (и память) в дополнительной глобальной переменной, но удалить из списка, переустановив связи.

    Затем, как со всем этим работать?
    Ясно, что меню нужно читать из файла на диске. (В Противном случае нужно раздавать все коды пользователю, а как он ими распорядится? - XZ)

    Радует то, что изучение Паскаля, пока идёт гладко. Но индикации НАСКОЛЬКО - вовсе нет.

    То есть, Я думаю, что так как текстовое меню должно быть квадратным, то всё равно мы должны отслеживать максимальную длину пункта.
    Системная функция Len'ка вернёт число копируемых или инвертируемых символов, но я ненавижу ёрзанье по ширине курсора в Вертикальном меню!

    Отследить - просто. Коли текущая длина меньше или равна - не заботься, а коли увеличилась - измени свою переменную... ДА! в Горизонтальном меню наш алгоритм ИСКЛЮЧИТЕЛЬНО рулит!

    Это всё размышления о пост-программировании. Об облизывании сущностей...

    А нужно думать о сущностях!
    Например, как мне узнать, насколько двумерный массив экрана в CLSN обсчитывается быстрее, чем то, что я задавал в PL65.

    То есть, стоит ли создавать библиотеку прямого вывода на экран CLSN?, когда существуют системные двумерные массивы?

    Это для меня - загадка есть! Я просто не знаю Паскаля! I BEG YOUR PARDON PLEASE,SIRS!

    Вот первые приближения к файловым операциям...

    Код:
    function fexist(s: string): boolean;
    var
      f: file of char;
    begin
      assign(f,s); (*Look up FileName*)
      [I-]; (* chkoff *)
        reset(f); (* Open *)
      [I+]; (* chkon *)
      fexist := (ioresult < 128); (* Less than 128 is success *)
      c1ose(f);
    end;
    
    function freadln(f: text; s: string): string;
    (* Reads a text file *)
    var
      s: string;
      f: text;
    begin
      assign(f,'D:MENU.DAT'); reset(f);
      while not eof(f) begin
        readln(f,s); (* Get a line *)
        _mStr01 := s; (* Save it *)
      end;
      close(f);
    end.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  7. #6
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Ещё немного...

    Здравствуйте, Дорогие Атаристы - ВосьмиБитники!
    Пришло время ещё одного маленького прорыва. (Он - не маленький!)

    Ситуация следующая: Я никогда в жизни не программировал на Паскале. И поэтому в принцыпе - не ведаю, что творю! Кроме этого, Мануал CLSN - не является ВООБЩЕ учебником Паскаля.

    То есть брать данные приходится из чужих кодов для чужих компиляторов.
    Поэтому, всё идёт не туда и не так.

    Ну, в общем, разобрался я ещё с одной проблемкой...

    Как Вы знаете, чтобы что-то системное нарисовать, надо данные-то под этим сохранить сперва...
    Так вот, средствами Паскаля мне удалось доступиться к экрану, как к видеобуферу. DMA, короче.

    Честно, для меня, не знающего Паскаль было туго и непросто.

    Однако я и с ЛИСПом справлялся и с Паскалем справлюсь!

    Во Первых, Что нам ЭТО даст? Да, не печать через терминал CIO вывода, а занесение подготовленного (нашими предыдущими процедурками) тега байтов напрямую в меню. Или, инверсию символов, со скоростью машкодов.

    А храниться сохранённое будет на Куче! То есть количество меню ограничено лишь ВСЕЙ памятью.
    Пиши, не напишешь! Идём прямяком к Светлому Будущему!

    Итак, Паскалевский DMA...

    Код:
    program scr;
    type
      SAVMSC = ^scrT;
      scrT = array[1..24] of array[1..40] of byte;
    
    var
      screen: SAVMSC absolute $58;
    
    begin
      x := 10; y := 10;
      screen^[y][x] := 128;
    end.
    Идея была проста.
    Честно определяем SAVMSC как (не удивляйтесь!) указатель.
    Затем определяем экран, как массив массивов байтов (не литер!, так как screen-bytes!).
    Определяем абсолютную переменную screen ярлыком SAVMSC и...

    И вот здесь я увяз. Понадобилась неделя, чтобы я понял, что мне нужно screen[y][x], заменить на screen^[y][x]. То есть, screen^ - это получение из указателя данных, являющихся адресом - разыменование!

    В общем поделился с Вами большой радостью!!!
    Ваш zen.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  8. #7
    Guru Аватар для Shiny
    Регистрация
    19.01.2017
    Адрес
    г. Арзамас
    Сообщений
    2,125
    Записей в дневнике
    36
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    22
    Поблагодарили
    11 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Интересно array объявляется.

    а array [0..39,0..23] of byte не прокатит?

  9. #8
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Здравствуйте, Шынни!

    В CLSN для массивов только - array[1..24] of array[1..40] of byte;
    Старый синтаксис.

    Откровенно говоря, из за того, что блоки меню - прямоугольные структуры, следовало бы в блочных процедурах работать с массивами, в то время как при работе с траверсированием списков отлично подходят двусвязные списки.
    Я покумекую над этим...

    Да, кстати, заметил некий загадочный баг в отображении экрана выполнения прогрвммы, наверное это CLSN шалит.

    Вот скрин первого запуска предыдущей программы:
    Нажмите на изображение для увеличения. 

Название:	scr1.png 
Просмотров:	156 
Размер:	9.2 Кб 
ID:	65664

    А вот второго:
    Нажмите на изображение для увеличения. 

Название:	scr2.png 
Просмотров:	181 
Размер:	12.9 Кб 
ID:	65663
    Последний раз редактировалось ezswift; 04.07.2018 в 08:27.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

  10. #9
    Guru Аватар для Shiny
    Регистрация
    19.01.2017
    Адрес
    г. Арзамас
    Сообщений
    2,125
    Записей в дневнике
    36
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    22
    Поблагодарили
    11 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Кстати, а тип данных Record есть?

  11. #10
    Activist Аватар для ezswift
    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Дык, я двусвязные списки на Record делал. Немного раньше в теме.

    Вот изображение двусвязного списка:

    Нажмите на изображение для увеличения. 

Название:	DLL.png 
Просмотров:	170 
Размер:	17.9 Кб 
ID:	65749
    Последний раз редактировалось ezswift; 16.07.2018 в 11:44.
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

Страница 1 из 5 12345 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Компилятор языка Паскаль - планы на будущее
    от Bolt в разделе Программирование
    Ответов: 212
    Последнее: 13.10.2019, 17:12

Ваши права

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