LINUX.ORG.RU

Мои проги на PureBasic

 


4

5

Если у кого есть желание ознакомится можете скачать архив прог (53Мб), в комплекте общая справка по прогам в CHM со скриншотами. Можно посмотреть её в онлайн

В комплекте исходники и можно их скомпилировать. Для Linux собраны 3 варианта пакетов deb (Mint-x64 и MX-x86), rpm (Fedora), zst (Arch), и исполняемые для Raspberry-x32, и есть отдельно архив для Андроида Можете посмотреть видео о PureBasic на моём ютуб канале


Ответ на: комментарий от AZJIO

Я же говорил о пути в дереве из стороннего окна, а не о контролс. Там всего то EnumChildWindows

Не знаю, что это означает.

Для данной задачи однозначно использовал бы API Linux или Windows для
работы с процессами, а оно предоствляет различного рода enumeration.
Ниже приведу названия модулей, которые использую для enumeration:

  • EnumLangsProc.cpp;
  • EnumNamesProc.cpp;
  • EnumResourcesModule.cpp;
  • EnumTypesProc.cpp;
  • ExtractResource.cpp;
  • LoadResourceMemory.cpp

Этого функционала вполне достаточно для получения информации о любом процессе.

anonymous
()
Ответ на: комментарий от wandrien

Псс, парень, Modula-2 надо?

MODULE LoopDemo;

FROM Terminal2 IMPORT WriteString, WriteInt, WriteLn, WriteChar;

CONST Where = 11;

VAR  Index   : INTEGER;
     What    : INTEGER;
     Letter  : CHAR;

BEGIN

   WriteString("REPEAT loop     = ");
   Index := 0;
   REPEAT
     Index := Index + 1;
     WriteInt(Index,5);
   UNTIL Index = 5;          (* This can be any BOOLEAN expression *)
   WriteLn;

   WriteString("WHILE loop      = ");
   Index := 0;
   WHILE Index < 5 DO        (* This can be any BOOLEAN expression *)
      Index := Index + 1;
      WriteInt(Index,5);
   END;
   WriteLn;

   WriteString("First FOR loop  = ");
   FOR Index := 1 TO 5 DO
      WriteInt(Index,5);
   END;
   WriteLn;

   WriteString("Second FOR loop = ");
   FOR Index := 5 TO 25 BY 4 DO
      WriteInt(Index,5);
   END;
   WriteLn;

(* Note - The four loops above could use a CARDINAL type variable
          in place of the INTEGER type variable Index.  The next 2
          examples must use an INTEGER type variable because it
          must be capable of storing a negative value.            *)

   WriteString("Third FOR loop  = ");
   FOR Index := 5 TO -35 BY -7 DO
      WriteInt(Index,5);
   END;
   WriteLn;

   What := 16;
   FOR Index := (What - 21) TO (What * 2) BY Where DO
      WriteString("Fourth FOR loop = ");
      WriteInt(Index,5);
      WriteLn;
   END;

(* Note - The next two loops are demonstrations of using a CHAR
          type variable to index a FOR loop.                      *)

   FOR Letter := "A" TO 'Z' DO
      WriteChar(Letter);
   END;
   WriteLn;

   FOR Letter := 'z' TO 'a' BY -1 DO
      WriteChar(Letter);
   END;
   WriteLn;

(* Note - The following loop contains an EXIT which is a way to get
          out of the loop in the middle.                           *)

   Index := 1;
   LOOP
      WriteString("In the EXIT loop ");
      WriteInt(Index,5);
      IF Index = 5 THEN
         WriteLn;
         EXIT;
      END;
      WriteString("  We are still in the loop.");
      WriteLn;
      Index := Index + 1;
   END;

END LoopDemo.
LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

Плохо, что Turbo Modula не взлетела, там с синтаксисом получше, да и в качестве промышленного языка можно сразу использовать, без допилки.

ТурбоПаскаль - вполне промышленный язык был, причем многое заимствовал из Модулы. А вот почему сама Модула не взлетела не очень понятно. Правда, чтобы он взлетел надо было ООП добавить, как это сделали с TP5.5. Может все же паскаль оказался популярнее

praseodim ★★★★★
()
Ответ на: комментарий от praseodim

Правда, чтобы он взлетел надо было ООП добавить, как это сделали с TP5.5.

И популярен он ныне?
Есть хайп, а есть технологии.
Нужно использовать хорошие технологии, а хайп «был и прошёл».
В основном ныне хайп, которые всегда рекламируют как САМОЕ СОВРЕМЕННОЕ.

anonymous
()
Ответ на: комментарий от anonymous

И популярен он ныне?

Delphi и FreePascal нынче не мейнстрим, но и не забыты, даже новые программы на них появляются.

Нужно использовать хорошие технологии, а хайп «был и прошёл».

Не совсем понял, что ты счел хайпом? В принципе, сейчас у паскаля нет каких-то серьезных преимуществ, хотя язык по-моему лучше C и С++ в том, что сохраняет возможность низкоуровневых операций, но менее склонен способствовать выстрелу себе в ногу.

praseodim ★★★★★
()
Последнее исправление: praseodim (всего исправлений: 1)
Ответ на: комментарий от praseodim

Не совсем понял, что ты счел хайпом? В принципе, сейчас у паскаля нет каких-то серьезных преимуществ, хотя язык по-моему лучше C и С++ в том, что сохраняет возможность низкоуровневых операций, но менее склонен способствовать выстрелу себе в ногу.

Пост был не о том, что Pascal плох.
Это хороший ЯП.
Хайп в основном от монополистов IT.
Любой свой проект они акцентируют как «сам современный», а всё остальное для них «так себе».
Разве может Microsoft признать, что Pascal хороший ЯП?
НИКОГДА.

anonymous
()
Ответ на: комментарий от anonymous

Что касаемо Basic, то годами ранее было большое сообщество VB.
Конечно это не C++, так как C++ всё же в первую очередь ЯП для системного программирования (ИМХО в первую очередь всякого рода libraries).
Но для прикладного программирования вполне пригодны: Pascal, …
У меня этих проблем вовсе нет, так как 100% веду разработку лишь libraries, которые можно использовать в любом прикладном ЯП.
Пока лучшего пути в разработке просто нет.

anonymous
()
Ответ на: комментарий от anonymous

Нужно использовать хорошие технологии, а хайп «был и прошёл».

Есть хайп, а есть прогресс, и попытки найти действительно лучшие подходы к разработке, потому что люди и компании накапливают опыт и со временем начинают понимать, что работает плохо, а что работает хорошо.

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

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

Вот бейсик - это язык, который создавался, когда таких вещей ещё не понимали. Не было накоплено опыта. И многое, что появилось после него, это не хайп, а реально языки, которые лучше.

Конечно.
Но несложный tools можно писать на разных ЯП.
Для хорошего tools правда лучше использовать C++, так как у него хорошо поддерживается разработка для архитектуры проекта.
В прикладных ЯП такой возможности нет.

anonymous
()
Ответ на: комментарий от anonymous

Для хорошего tools правда лучше использовать C++, так как у него хорошо поддерживается разработка для архитектуры проекта. В прикладных ЯП такой возможности нет.

«Что ты, черт побери, такое несешь…» (с)

anonymous
()
Ответ на: комментарий от praseodim

ТурбоПаскаль - вполне промышленный язык был, причем многое заимствовал из Модулы. А вот почему сама Модула не взлетела не очень понятно.

Jensen & Partners вышли из Borland и основали сначала JPI, Inc. затем TopSpeed. Вот их модула-2 это турбо-модула-2 с батарейками была вполне себе неплохой.

в общем, борланд был не очень заинтересован продвигать модулу и топспид заодно.

Правда, чтобы он взлетел надо было ООП добавить, как это сделали с TP5.5.

модула-2 с ООП – это модула-3. вот реально, был такой CM Modula-3 by Dec Research center, затем Olivetti Research. оно и сейчас более-менее живое, Critical Mass Modula-3. есть библиотеки, подключается сишные FFI, есть свои.

ещё есть модула-2 в GCC 15, есть итальянская модула-2 с батарейками которая напрямую в сишку конпелируется.

XDS Modula-2/Oberon-2 есть с исходниками (См. также диссер Недори про Excelsior, Xerion и т.п.)

ещё есть австралийская модула-2 (примерно там же где и оберон-2 под .NET) и Stony Brook Modula-2, вполне неплохая.

в каком-то смысле почти как пурбасик – можно писать коротенькие win32 программки размером в 8-20 кб на win32 API. C FFI подключается элементарно, есть куча примеров и книжка Петцольда.

А вот почему сама Модула не взлетела не очень понятно.

ну если сравнивать по фичам. то например, исключения, сопрограммы были сделаны в модула-2 отдельными модулями, расширениями – в разных конпеляторах сильно по разному.

ООП в модула-2 опять же не было (было в модула-3 и в обероне-2, в Active Oberon-2, Zonnon двумя-тремя разными способами)

вообще, правильный системный паскаль это на мой взгляд не столько модула-2 сколько Ада – GNAT компилятор в GCC довольно неплох.

runtime там довольно просто переписывается при необходимости, почти как в турбо модуле-2 и турбо и виртуал паскале.

при этом в языке есть задачи и рандеву; задачный тип (например, для воркеров и планировщика); нормальные пакеты и шаблоны (а не как в С++); нормальная модульность и линковка с #pragma C(import), нормальный С FFI который может сам gcc сгенерировать.

В общем, Ада в реализации GNAT под gcc (сейчас ещё новая на LLVM начинает появляться) – тот системный паскаль, которым он и должен был быть.

обероны немного слишком более просты, чем нужно. ада пошла по пути усложнения паскаля, а не минимализма и упрощения как в оберонах. но при всём при этом ада всё ещё легко человекочитаема и всё ещё проще С++.

опять же, есть SPARK и Design by contract. есть многозадачность, встроенная в язык.

нормальная модульность и «проектирование по-большому».

в общем, нормальный язык, продуманный инженерами (а не полутеоретиком/практиком, как в С++).

в GCC 15 вообще есть куча ретро: кобол, алгол, модула-2, ада.

надо как-то собрать и кроссконпелировать в мингв под венду, с батарейками.

откопать ещё gpc к fpc и собрать им классический tex из weave/tangle.web изначальный.

и начать его переписывать сначала на Active Oberon под ЯОС, затем на аду, ога.

или до кучи, ещё и на алгол-68 с модулой.

понастольгировать, что ли.

парсер CocoR например есть с книжкой. изначально он был как раз под модулу написан, есть порт под аду.

можно weave/tangle изначальный под него портировать.

anonymous
()
Ответ на: комментарий от AZJIO

Вот заходят такие новички представляющие из себя полный ноль и пишут, что у вас нет ООП. По факту, когда ему дадут ООП, то он просто не дорастёт до него. А обслуживать сложный синтаксис ему придётся.

и получается обычно очередной С++ со сложным синтаксисом, где помимо ООП ещё и шаблоны, и template и constexpr и ещё и новая семантика в каждой версии стандарта, гораздо дальше от C++97 изначального

ООП бывает разное. в некоторых языках ООП можно добавить разными способами. есть например, объектно-ориентированный ассемблер. или Objective C = C + SmallTalk. или CLOS из Common Lisp и попытка его реализовать в plain C: Dynace, и прочие минималистичные «ООП в несколько тыщ строчек».

что характерно, при этом получается обычно ООП более гибкое чем в С++. если понимать как его делать, например.

Также я помню вбросы «у вас нет многопоточности», но вот когда я перешёл на язык поддерживающий многопоточность, то понял (хотя частично и знал), что писать потоками надо ещё их изучать контроль над ними и создавать прогу на порядок сложнее, учитывающую работу потоков.

вот поэтому мне и нравится АДА, например – там всё довольно просто.

вот пример многопоточного кода про ужинающих философов (палочки для еды у них одни на всех, так что они их передают по кругу и синхронизируются между собою):

file E:\GNAT.2019\2021\share\examples\gnat\simple_project (в новых версиях GNAT пример куда-то пропал, да не суть)

examples/gnat/simple_project/{simple_project.xml,simple.gpr,Makefile, gnat.adc, README.testing}

скрипты для сборки проекта – simple.gpr консольный для gprbuild (собирает проект целиком), обычный makefile для make, xml для IDE, README и ненужный gnat.adc с pragma Restrictions ...

здесь из simple.gpr видно, что основной модуль находится в diners.adb

examples/gnat/simple_project/include/{chop.ads,phil.ads,random_generic.ads,room.ads,screen.ads,random_generic.ads,room.ads,windows.ads}

это интерфейсы используемых модулей составляющие программу – definition часть, не implementation

examples/gnat/simple_project/src/{chop.adb,phil.adb,random_generic.adb, room.adb, screen.adb, random_generic.adb, room.adb, windows.adb,diners.adb}

это основные модули, реализация этих интерфейсов.

  • самый главный модуль лежит в diners.adb

все исходники гуглятся (хотя не сразу, в новых GnatStudio их зачем-то удаляли из примеров, в 2019 точно есть; в 2021 вроде бы тоже ещё были; так что находятся не сразу):

11.1 PORTABLE DINING PHILOSOPHERS EXAMPLE

что здесь можно сказать о многопоточности.

начинаем изучать с diners.adb, главного модуля. видим функцию main (из сишки) которая тут называется diners. в ней видим Room.Maitre_D.Start_Serving;

anonymous
()
Ответ на: комментарий от anonymous

идём смотреть в модуль комнат, rooms.ads интерфейс и room.adb реализацию. что видим?

package body Room is
 
  -- Dining Philosophers, Ada 95 edition
  -- A line-oriented version of the Room package
  -- Michael B. Feldman, The George Washington University, 
  -- July, 1995.
  -- Revisions
  -- July, 1995. Bjorn Kallberg, CelsiusTech Systems, Sweden.
  --             Pictorial display of stick in use 

  -- philosophers sign into dining room, giving Maitre_D their DNA code
 
  Dijkstra   : aliased Phil.Philosopher (My_ID => 1);
  Stroustrup : aliased Phil.Philosopher (My_ID => 2);
  Anderson   : aliased Phil.Philosopher (My_ID => 3);
  Taft       : aliased Phil.Philosopher (My_ID => 4);
  Ichbiah    : aliased Phil.Philosopher (My_ID => 5);
 
  type Philosopher_Ptr is access all Phil.Philosopher;

  Phils      : array (Table_Type) of Philosopher_Ptr;
  Phil_Pics  : array (Table_Type) of Picture.Root_Ptr;
  Phil_Seats : array (Society.Unique_DNA_Codes) of Table_Type;

  task body Maitre_D is
 
    T          : Natural;
    Start_Time : Calendar.Time;
    Blanks     : constant String := "     ";


  begin
 
    accept Start_Serving;

    Start_Time := Calendar.Clock;
 
    -- now Maitre_D assigns phils to seats at the table

    Phils :=
      (Dijkstra'Access,
       Anderson'Access,
       Ichbiah'Access,
       Taft'Access,
       Stroustrup'Access);
  
    -- Which seat each phil occupies.
    for I in Table_Type loop
       Phil_Seats (Phils(I).My_Id) := I;
    end loop;

    Phil_Pics :=
       (new Picture.North, 
        new Picture.East, 
        new Picture.South,
        new Picture.South,
        new Picture.West);
  

    Picture.Open (Phil_Pics(1).all,( 1, 24), 7, 30);
    Picture.Open (Phil_Pics(2).all,( 9, 46), 7, 30);
    Picture.Open (Phil_Pics(3).all,(17, 41), 7, 30);
    Picture.Open (Phil_Pics(4).all,(17,  7), 7, 30);
    Picture.Open (Phil_Pics(5).all,( 9,  2), 7, 30);


    -- and assigns them their chopsticks.

    Phils (1).Start_Eating (1, 2);
    Phils (3).Start_Eating (3, 4);
    Phils (2).Start_Eating (2, 3);
    Phils (5).Start_Eating (1, 5);
    Phils (4).Start_Eating (4, 5);
 
anonymous
()
Ответ на: комментарий от anonymous
    loop
      select
        accept Report_State (Which_Phil : in Society.Unique_DNA_Codes;
                             State      : in Phil.States;
                             How_Long   : in Natural := 0;
                             Which_Meal : in Natural := 0) do

          T := Natural (Calendar."-" (Calendar.Clock, Start_Time));
 
          case State is
 
            when Phil.Breathing =>
              Picture.Title (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     Society.Name_Register (Which_Phil));
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "Breathing...");

            when Phil.Thinking =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "Thinking" 
                      & Integer'Image (How_Long) & " seconds.");

            when Phil.Eating =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "Meal"  
                      & Integer'Image (Which_Meal)
                      & ","  
                      & Integer'Image (How_Long) & " seconds.");

            when Phil.Done_Eating =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "Yum-yum (burp)");
              Picture.Left_Fork (Phil_Pics (Phil_Seats (Which_Phil)).all, False);
              Picture.Right_Fork (Phil_Pics (Phil_Seats (Which_Phil)).all, False);

            when Phil.Got_Left_Stick =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "First chopstick" 
                      & Integer'Image (How_Long));
              Picture.Left_Fork (Phil_Pics (Phil_Seats (Which_Phil)).all, True);

            when Phil.Got_Right_Stick =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "First chopstick" 
                      & Integer'Image (How_Long));
              Picture.Right_Fork (Phil_Pics (Phil_Seats (Which_Phil)).all, True);

            when Phil.Got_Other_Stick =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "Second chopstick" 
                      & Integer'Image (How_Long));
              Picture.Left_Fork (Phil_Pics (Phil_Seats (Which_Phil)).all, True);
              Picture.Right_Fork (Phil_Pics (Phil_Seats (Which_Phil)).all, True);

            when Phil.Dying =>
              Picture.Put_line (Phil_Pics (Phil_Seats (Which_Phil)).all,
                     "T =" & Integer'Image (T) & " " 
                      & "Croak");

          end case; -- State
          
        end Report_State;
 
      or
        terminate;
      end select;
 
    end loop;
 
  end Maitre_D;
 
end Room;

_(простыня не влезла в один пост, немного нагляднее будет если смотреть сначала даже не реализацию diners.adb – _

anonymous
()
Ответ на: комментарий от anonymous

…, а интерфейс diners.ads:)

--::::::::::
--room.ads
--::::::::::
with Chop;
with Phil;
with Society;
package Room is
 
  -- Dining Philosophers - Ada 95 edition

  -- Room.Maitre_D is responsible for assigning seats at the
  --   table, "left" and "right" chopsticks, and for reporting
  --   interesting events to the outside world.

  -- Michael B. Feldman, The George Washington University,
  -- July, 1995.

  Table_Size : constant := 5;
  subtype Table_Type is Positive range 1 .. Table_Size;
 
  Sticks : array (Table_Type) of Chop.Stick;
 
  task Maitre_D is
    entry Start_Serving;
    entry Report_State (Which_Phil : in Society.Unique_DNA_Codes;
                        State      : in Phil.States;
                        How_Long   : in Natural := 0;
                        Which_Meal : in Natural := 0);
  end Maitre_D;
 
end Room;
anonymous
()
Ответ на: комментарий от anonymous

по-моему, всё наглядно и логично: есть задача Maitre_D которая всё запускает:

  1. есть массив философов, точнее доступов (указателей) на них – в аде есть как сишные указатели foo'address так и нормальные, типизированные ссылки foo'access которые проверяются во время компиляции.

  2. рассаживаем философов за стулья в комнате, настраиваем комнату. философы начинают жрать.

  3. запускается в теле основной задачи Maitre_D обработчик в цикле.

в обработчике, accept Report_State принимает состояния задачи task entry: Start_Serving, Report_State

и делает что?

switch по состояниям, конечный автомат case State is который обновляет картинку, в окошках на экране Picture.Title,Picture.Put_line.

что такое Picture? это текстовые окошки наподобие Curses (по крайней мере и под виндой и под xterm-ом отрисовывается через ncurses):

Picture.adb – тело модуля (реализация), Picture.ads – его интерфейс

здесь уже из интерфейса и особенно из реализации видно, что это просто обёртка над модулем Windows, который и отрисовывает окошки с бордюрами в текстовой консоли (через Esc-последовательности).

далее видно, что Phil.ads модуль тоже реализует задачу:

ackage Phil is
 
  -- Dining Philosophers - Ada 95 edition
  -- Philosopher is an Ada 95 task type with discriminant
  -- Michael B. Feldman, The George Washington University,
  -- July 1995
  --
  -- Revisions:
  -- July 1995. Bjorn Kallberg, CelsiusTech
  --            Reporting left or right instead of first stick

  task type Philosopher (My_ID : Society.Unique_DNA_Codes) is
 
    entry Start_Eating (Chopstick1 : in Positive;
                        Chopstick2 : in Positive);
 
  end Philosopher;
 
  type States is (Breathing, Thinking, Eating, Done_Eating, 
                  Got_Left_Stick, Got_Right_Stick, Got_Other_Stick, Dying);

end Phil;

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

реализуя нечто наподобие планировщика.

anonymous
()
Ответ на: комментарий от anonymous

то есть, здесь у нас есть одна главная задача которая запускает другие задачи из пула воркеров (реализованных через массив доступов к статически определённым объектам-задачам).

и обёртки, реализующий текстовый оконный TUI интерфейс.

так что – вот в Аде с многопроцессностью и многозадачностью всё нормально

я даже не знаю где ещё подобное можно написать более наглядным способом.

уж явно не в С++ (хотя и там вроде корутины в std начали появляться)

но, task type, task entry – принципиально другое. они формулируются в терминах задачи, как удобнее об ней рассуждать. и точки синхронизации через task entry состояния или через рандеву – с другими syncronized контролируемыми, управляемыми состояниями.

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

а вот например, корутины были реализованы в модуле-2 в отдельных модулях (как и исключения).

или вот например, в С++ в std в новых стандартах.

компилятор не имеет информации о том, что этот код многопоточный.

и поэтому эффективно соптимизировать не может.

к тому же например, в С++ нет транзитивности константности, а в D2 например есть – immutable вдобавок к const.

то есть, многопоточный код в D будет правильно immutable, а в const С++ коде – неправильно организован.

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

anonymous
()
Ответ на: комментарий от praseodim

итальянская модула-2 транспилятором в сишечку — это, ЕМНИП, вот эта: www.icosaedro.it/m2

вот ещё список транспиляторов в сишечку: github.com/GunterMueller/Modula-2_to_C_Transpilers

кстати, Excelsior JET XDS Modula-2 конпелятор А. Недори – в принципе, он тоже транспилятор в сишечку, общий фронтенд и бекенд для Модулы-2 и Оберона-2 (конпелятор оберона написан на модуле); используется SSA представление как в LLVM (ещё до того, как это стало модным); используется пара бекендов – нативный кодогенератор в EXE файлы и через сишечку из SSA представления.

А. Недоря сейчас делает язык Вирт с го-шным синтаксисом. в 80х-90х он участвовал в проекте Кронос и делал компилятор и среду наподобие BlackBox Component Pascal – на модуле-2 и обероне-2 под ДОС.

Кронос – это реализация юникс ядра на модуле-2. работала под железо соответствующей архитектуры , которое

  1. сделали студенты в ходе лабораторных и курсовых, дипломов в НГУ
  2. сделали процессор с микрокодом М-кодом (если в паскале был P-код, в модуле был М-код, и он был описан например в книге Н.Вирта про конструирование конпеляторов, одна редакция была на паскале, другая на модуле-2)
  3. под который + остальное железо написали свою операционную систему – Кронос
  4. операционка Кронос – была юникс ядром на модуле-2, POSIX совместима, ЕМНИП.

потом её недавно на FPGA переимплементировали в римейках.

ещё ссылки есть например здесь.

австралийский комплиятор это Gardens Point GPM (был также и оберон-2 под .NET). ADW Modula-2 как и StonyBrook была довольно неплохая под винду; там в качестве примеров была целая книжка Чарльза Петцольда с портированными примерами.

ещё ссылок: redstar/m2lang и доклад на FOSDEM.2019 – конпелятор модулы-2 на ЛЛВМ, с примерами как выкатить свой кодогенератор.

sblendorio/gorilla-cpm – GORILLA.BAS CP/M Version

Gorilla.BAS - CP/M version
This is a Modula-2 (despite the name) implementation for CP/M of the classic "GORILLA.BAS" BASIC game included in MS-DOS 5.0.

Why Turbo Modula-2?
The choice was mainly due to a historic interest: this compiler (never distributed by Borland) was written by Martin Odersky (the inventor of Scala language) and had never been used by a critical mass of users. So it was both a challenging choice and a historic research.

вот, ты знал, к примеру что турбо модулу-2 написал Мартин Одёрски? я вот не знал. думал что это Jensen и прочий которые в JPI и TopSpeed отпочковались.

или они с собой и Одёрского заодно в JPI/TopSpeed прихватили? ….скандалы, интриги, расследования….

anonymous
()
Ответ на: комментарий от anonymous

www.icosaedro.it/m2/tutorial и в браузере, экзамплы и приложеньица, либы

здесь видно что есть и не сильно тривиальные.

например, привязки к OpenGL,Xlib,GTK,Tcl/tk,сокетам,PgSQL

в общем, неудивительно – потому что из модулы-2 в сишку транспилируется.

так что привязки там тривиальные.

вот взял бы кто-нибудь и написал на этом хтмл парсере нормальный браузер без всей этой С++-ной хромой фигни, например.

на нормальных виджетах и гаджетах.

на няшной и наглядной, зело понятной и доступной модуле-2.

если что, можно взять тот же CocoR и допилить нормальный парсер до ума.

anonymous
()
Ответ на: комментарий от anonymous

экзешник хелловорда на 600 килобайт довольно жирноват, но может можно обрезать рантайм…

хотя там, ЕМНИП, фича в другом: что он транспилирует в сишечку. то есть со всякими tiny c runtime и егойным упрощённым m2 рантаймом тоже можно повозиться. если это случайно не DWARF символы нестрипнутые в mingw-gcc -g остались.

вот что ADW Modula-2, что StonyBrook Modula-2 делал компактные EXE бинарники на 8-10 кб, почти что пурбасиковые по компактности.

XDS кажется около 60-100кб рантайм генерировал, хелловорд что-то на 20..40 кб ЕМНИП.

а насчёт gcc-шной и LLVM-овской фигни сильно не уверен.

anonymous
()
Ответ на: комментарий от anonymous

нормальный веб-браузер на EBNF парсере

в примерах bnf_chk/bnf_chk-on-line там есть грамматика e-mail в EBNF.

144 правила, Карл!!

я не шучу, это полный ЛОЛъ. пример грамматики паскаля – всего 133, похапе – всего 102, самой модулы-2 отсюдова, мама мия мона белла – всего 70 правила, карлито бомбино.

Stupidità o tradimento? Provo vergogna spagnola quando vedo tutto questo.

anonymous
()
Ответ на: комментарий от wandrien

А тут вообщее что-то другое, с наследием от Амиги. Я на таком не писал.

вот где-то под атари был аналогичный cowgol-у какой-то алгол даже, а не бейсик, ещё на картрижде. и бейсик там кстати тоже был довольно приличный – но не встроенный который READY с квадратным курсором пишет, а вот этот какой-то недоалгольный бейсик. он конпелировал в фоне в токены (примерно как в спектрумовском) и к концу ввода строки уже запускал откомпилированный машкод. не помню какой это был бейсик точно, какой-то недоалголыш типа cowgol-а, помню что был на картрижде специальном, как бы даже не с IDE (редкая вещь – IDE на Atari 800XL)

а на амиге были интересные языки, да. например, Амига Е. что-то среднее между бейсиком, алголом и cowgol-ом. Или тот же пурбасик. или REBOL.

впрочем, там был родной AREXX – Аmiga Rexx был всю дорогу, операционка в смысле командной строки – это BCPL-ная TRIPOS (оттуда странный синтаксис утилит командной строки).

С там был довольно простой, – BOOPSI – ООП на Си, загружаемые библиотеки типа dll. немного интереснее были Intuition и далее MUI (в AROS есть его форк ZUNE)

в MUI все виджеты и гаджеты были дефолтно скриптуемы через REXX, и на них заведены стандартные порты и сообщения.

то есть, в написанном гуёвом хелловорде под MUI можно было программно нажать любую кнопку, запустить любую команду что есть в меню, или если что-то специально написали и экспортировали – хоть на С, хоть на самом REXX.

то есть, по умолчанию любой GUI софт, написанный с этой библиотекой был легко программно скриптуемым черех AREXX.

в полуоси тоже была похожая фича с WPS, даже видел в вики статью как SOM WPS десктоп объекты писали на ассемблере и скриптовали Object REXX-ом.

но в целом не совсем то. не настолько просто.

вот под амигу было дофига самобытного софта и языков (Hollywood ещё, например) – которые были и просты и наглядны, и достаточно мощны и фичасты.

и пользоваться всем этим было просто.

блин, да тут в пурбасиковых архивах tajmone/purebasic-archives например, 2D игрушку пишут: tajmone/purebasic-archives/blob/master/books/2d-games/Programming_2D_Scrolling_Games.pdf

я угораю от того, насколько это всё там сделано просто.

просто сделано – и просто и удобно всем этим пользоваться. потому что сделано для людей.

anonymous
()
Ответ на: комментарий от wandrien

даже странно весьма, отчего же не пишут вот всякие там метапроги на пурбасике или вот например на итальянской M2 реализации, элементарно транспилируемой через сишечку…

может и написали бы уже давно, кабы взяли не сишечку с имгуями – а более другие tools архитектурно спроектированные для метапрожества???

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

отчего же не летают метапроги, не летают словно птицы? от того, что отрастили большие ягодицы. больше не отчего, думаю истинно так

anonymous
()
Ответ на: комментарий от praseodim

итальянская модула-2 M2 транспилятором через сишечку.

это просто прекрасно, Карл. зацени в библиотеке модуль m2-1.5-20110205.tar/m2-1.5-20110205/lib/pg.{def,imp}, как там делают постгрю.

Карл – это просто отлично, ящитаю:
файл pg.imp:

IMPLEMENTATION MODULE pg

$$ linker options: -I /usr/local/pgsql/include -L /usr/local/pgsql/lib -l pq

$#include <libpq-fe.h>

FUNCTION open(db: STRING): CONNECTION
RAISE ERROR
VAR
	errmsg: STRING
	conn: CONNECTION
$	char *s;
$	PGconn *conn;
BEGIN
$	MK_ZSTRING(s, pg_db);
$	conn = PQconnectdb(s);
$	if( PQstatus(conn) == CONNECTION_BAD ){
$		s = PQerrorMessage(conn);
$		pg_errmsg = new_STRING(s, strlen(s));
		RAISE ERROR 1 db + ": " + errmsg
		RETURN NIL
$	}
$	pg_conn = (RECORD *) conn;
	RETURN conn
END

FUNCTION close(conn: CONNECTION)
BEGIN
	mark(conn)
$	PQfinish( (PGconn *) pg_conn );
END

FUNCTION exec(conn: CONNECTION, query: STRING): RESULT
RAISE ERROR
VAR
	res: RESULT
	errmsg: STRING
$	PGresult *res;
$	char *s;
BEGIN
	mark(conn)
$	MK_ZSTRING(s, pg_query);
$	res = PQexec( (PGconn *) pg_conn, s);
$	if( PQresultStatus(res) != PGRES_TUPLES_OK ){
$		s = PQresultErrorMessage(res);
$		pg_errmsg = new_STRING(s, strlen(s));
		RAISE ERROR 1 query + ": " + errmsg
$		PQclear(res);
		RETURN NIL
$	}
$	pg_res = (RECORD *) res;
	RETURN res
END

FUNCTION clear(res: RESULT)
BEGIN
	mark(res)
$	PQclear( (PGresult *) pg_res );
END

FUNCTION nrows(res: RESULT): INTEGER
BEGIN
	mark(res)
$	return PQntuples( (PGresult *) pg_res );
END

FUNCTION ncols(res: RESULT): INTEGER
BEGIN
	mark(res)
$	return PQnfields( (PGresult *) pg_res );
END

FUNCTION fname(res: RESULT, col: INTEGER): STRING
VAR
	f: STRING
$	int cols;
$	char *fz;
BEGIN
	mark(res)
	mark(col)
$	cols = PQnfields( (PGresult *) pg_res );
$	if( pg_col < 0 || pg_col >= cols )
$		die("pg.fname(): col=%d out of the range", pg_col);
$	fz = PQfname((PGresult *)pg_res, pg_col);
$	pg_f = new_STRING(fz, strlen(fz));
	RETURN f
END

FUNCTION get_value(res: RESULT, row: INTEGER, col: INTEGER): STRING
VAR
	v: STRING
$	char *vz;
$	int rows, cols;
BEGIN
	mark(res)
	mark(row)
	mark(col)
$	rows = PQntuples( (PGresult *) pg_res );
$	cols = PQnfields( (PGresult *) pg_res );
$	if( pg_row < 0 || pg_row >= rows )
$		die("pg.get_value(): row=%d out of the range", pg_row);
$   if( pg_col < 0 || pg_col >= cols )
$		die("pg.get_value(): col=%d out of the range", pg_col);
$	if( PQgetisnull((PGresult *)pg_res, pg_row, pg_col) )
$		return 0;
$	vz = PQgetvalue((PGresult *)pg_res, pg_row, pg_col);
$	pg_v = new_STRING(vz, strlen(vz));
	RETURN v
END

FUNCTION get_value_byname(res: RESULT, row: INTEGER, fn: STRING): STRING
VAR
	col: INTEGER
$	char *fnz;
$	int rows;
BEGIN
	mark(fn)
$	rows = PQntuples( (PGresult *) pg_res );
$	if( pg_row < 0 || pg_row >= rows )
$		die("pg_get_value_byname(): row=%d out of the range", pg_row);
$	MK_ZSTRING(fnz, pg_fn);
$	pg_col = PQfnumber( (PGresult *)pg_res, fnz);
$	if( pg_col == -1 )
$		die("pg.get_value_byname(..., ..., \"%s\"): field don't exists in table",
$			fnz);
	RETURN get_value(res, row, col)
END

(* Queste funzioni sfruttano le proprieta' del linguaggio: *)
FUNCTION get_field_names(res: RESULT): ARRAY OF STRING
VAR
	cols, col: INTEGER
	fn: ARRAY OF STRING
BEGIN
	cols = ncols(res)
	FOR col = 0 TO cols-1 DO
		fn[col] = fname(res, col)
	END
	RETURN fn
END

FUNCTION get_fields(res: RESULT, row: INTEGER): ARRAY OF STRING
VAR
	col, cols: INTEGER
	fv: ARRAY OF STRING
$	int rows;
BEGIN
$	rows = PQntuples( (PGresult *) pg_res );
$	if( pg_row < 0 || pg_row >= rows )
$		die("pg.get_fields(): row=%d out of the range", pg_row);
	cols = ncols(res)
	FOR col = 0 TO cols-1 DO
		fv[col] = get_value(res, row, col)
	END
	RETURN fv
END

END

вот такая отличнейшая модула-2 произрастает порою в итальянских деревнях. это прекрасное пурбасиковое с асм-вставками, то есть в этом вот случае – с Си вставками.

anonymous
()
Ответ на: комментарий от anonymous

элементарно транспилируемой через сишечку…

это 5% от основной работы, транслировать то можно, но его ещё написать надо. А пурик то транслирует сразу в 3-6 систем, а попробоуй сишечку написанную для GTK потранслируй в WinAPI или Cocoa и что мы получим? Получим неработающий код и доводок там будет проще с нуля написать.

AZJIO
() автор топика
Ответ на: комментарий от AZJIO

поэтому писать это надо не руками – писать должен сам конпелятор.

как например, в GNAT аде из gcc есть ключик -fdump-ada-spec:

gem-59

g++ -c -fdump-ada-spec -C /usr/include/time.h
gcc -c -gnat05 *.ads

просто есть в языке Ада нормальный C FFI самим компилятором: pragma import(C, ada_name, "c_name"); , вот пример:

gcc.gnu.org/onlinedocs//gnat_ugn/Interfacing-to-C.html

вот книжка на русском про адское_программирование – и вообще, на ada-ru.org много полезной информации.

ещё есть примеры например программирования под линукс на GNAT аде в книжке BOBLAP – там в конце есть пример как с ассемблером сопрягать.

в целом, вот ада – язык с нормальной FFI интеграцией посредством компилятора:

gcc (и g++) собраный с c,c++,ada это драйвер, который поддерживает например ключик -fdump-ada-spec и запускает нужный компилятор в зависомости от расширения файла.

-fdump-ada-spec просто заставляет генерировать сам компилятор, бекенд g++ (C++ компилятора) при компиляции С++ исходников привязки на ада – те же самые pragma Import(C,Ada_func_name,"C_func_name"); что ты и написал бы вручную.

С С++ немного сложнее чем с С из-за того что есть стандартный C ABI (calling convention: cdecl), но нет стандартного C++ ABI, зато есть все нестандартные.

пример в конце книжки BOBLAP показывает как справляться с С++ привязками с манглингом и прочее

но в целом, проще C API из C++ врапперы написать.

шаблоны, понятное дело С++ таким образом перевести не получится.

но в целом, весь адский рантайм – это то, что находится между вызовами adainit() и adafinal(), и элементарно пишутся привязки между С и адой в обе стороны, в том числе через волшебный ключик – и притом, полностью автомагически

anonymous
()
Ответ на: комментарий от anonymous

BOBLAP-chapter19:

ассемблер, впрочем, там из ады дёргается чуть более громоздко, чем в пурбасике:

with Ada.Text_IO, Interfaces, System.Machine_Code;
use  Ada.Text_IO, Interfaces, System.Machine_Code;

procedure asm4 is
-- A demonstration of Pentium assembly language programming.
--
-- We'll use the Interface package's unsigned_32 integers for the 32-bit
-- values stored in registers.  Of course, we could have made our own types
-- to do the same thing...

function do_math( value1, value2 : unsigned_32 ) return unsigned_32 is
  -- Do some arbitrary math in assembly language.  We'll use
  -- ( value + 1 ) * 2 - value2 in this example.
  result : unsigned_32;
begin

  asm(

       "incl %%eax" & ASCII.LF & ASCII.HT &      -- increment by 1
       "sall %%eax" & ASCII.LF & ASCII.HT &      -- shift left ( * 2 )
       "subl %%ebx, %%eax",                      -- subtract value2 (ebx)

       -- EAX register := value1;
       -- EBX register := value2;

       inputs => (
           unsigned_32'asm_input( "a", value1 ),  -- value1 in EAX
           unsigned_32'asm_input( "b", value2 )   -- value2 in EBX
       ),

       -- result := EAX register;

       outputs => unsigned_32'asm_output( "=a", result ),

       -- The carry flag will be altered in EFLAGS by subl

       clobber => "cc"

  );
  return result;
end do_math;
pragma inline( do_math );

value1 : unsigned_32;
value2 : unsigned_32;
result : unsigned_32;

begin
  value1 := 5;
  value2 := 8;
  result := do_math( value1, value2 );
  put_line( "do_math will do ( value1 + 1 ) * 2 - value2" );
  put( "do_math(" & value1'img & "," & value2'img & ") = " );
  put_line( result'img );
end asm4;

do_math will do ( value1 + 1 ) * 2 - value2

do_math( 5, 8) = 4

anonymous
()
Ответ на: комментарий от anonymous

asm(

если что, в пурик есть возможность писать на asm в asm-backend и на Си в C-backend.

Найти не могу пост, где кто то писал что я должен был сначала найти аналоги оболочек для консольных утилит прежде чем писать свою. Но аналогов конечно не был опредложено, а потому что аналог слабоватый и я его видел. Аргумент нулевой.

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

AZJIO
() автор топика
Последнее исправление: AZJIO (всего исправлений: 1)
Ответ на: комментарий от Shushundr

А как это эула не на софт, а на формат данных? Ерунда какая-то, с каких пор форматы данных стали объектом авторского права? Их иногда пытаются патентовать с переменным успехом, но это не эула.

anonymous
()
Ответ на: комментарий от anonymous

с каких пор форматы данных стали объектом авторского права?

А ты разве где-то видишь формальную спецификацию этого формата? Надо реверсинженерить? И как это соотносится с законодательством РФ?

Shushundr ★★★★
()