LINUX.ORG.RU

Metaprog: универсальная графическая среда программирования [в разработке] часть 4

 , , ,


4

3

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

FAQ

1. Где скачать?

Релиза еще не было. Идет разработка, темы посвящены ей. Есть сделанный на LabVIEW прототип (его работа показана в примерах).

2. Почему не открыт код LabVIEW-прототипа Метапрога?

Он весьма глючный, прожорливый по памяти, а самое главное - зависит от пропиетарного LabVIEW, то есть в него вряд ли кто-либо из здешней публики будет контрибутить. Но если кто докажет намерение контрибутить - могу открыть.

3. Почему не Дракон, MIT App Inventor, Unreal Blueprints?

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

4. Чем плохи LabVIEW или MyOpenLab?

LabVIEW пропиетарный, а MyOpenLab - хоть и опенсорсный, но какой-то недоделанный (пытался у себя запустить - выдало джава эксепшоны). Да-да, опенсорсный «клон» LabVIEW написанный на джаве! LabVIEW хотя бы на C++, а это все же меньшее зло. Обе эти системы даже не сделаны «сами на себе» в графике. Они даже не пытаются претендовать на универсальную замену всем текстовым языкам, хотя LabVIEW могло бы, если бы не тупость копирастов. Эти системы написаны на текстовых языках, их код (даже если б LabVIEW был опенсорсным) невозможно редактировать, ни разу не обращаясь к текстовым языкам. Метапрог изначально предполагает полный отрыв от текста и текстовых языков, за исключением Си как бэкенда. И то пользователям никогда не придется иметь дело с текстовым Си за исключением блоков сишных вставок (для особых случаев типа арифметических операций, ассемблерных вставок итп).

5. Почему как бэкенд выбран именно Си?

Си - это по сути мощный «кроссплатформенный ассемблер». На нем сделано огромное количество кода, готовых библиотек, в Линуксе (и вообще UNIX) Си - общепринятый стандарт для системного программирования. Кроме того, на Си делаются прошивки микроконтроллеров. Си работает быстро, не требует тяжелых и глючных рантаймов, и в то же время дает наиболее полный контроль над поведением программы (из кроссплатформенных языков).

6. В Си указатели и ручное управление памятью. Это же так сложно!

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

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

Пункт 6 касается разработки программ, то есть исполняемых файлов и библиотек. Для задач типа браузерных/игровых скриптов, разумеется, будут свои подмножества Метапрога без указателей.

8. Почему в Метапроге будут предпочитаться бинарные форматы и чем это лучше?

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

http://zone.ni.com/reference/en-XX/help/371361R-01/glang/flatten_to_string/

http://zone.ni.com/reference/en-XX/help/371361R-01/glang/unflatten_from_string/

Что-то подобное будет и в Метапроге. При открытом коде никаких сложностей с чтением бинарных файлов не будет.

9. А как будет обеспечиваться совместимость со старыми файлами, сетевыми протоколами итп, если будет изменен тип?

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

Примеры

Metaprog: универсальная графическая среда программирования [в разработке]

Metaprog: универсальная графическая среда программирования [в разработке] часть 2

Metaprog: универсальная графическая среда программирования [в разработке] часть 3

Прокручиваемая и выделяемая строка с автопереносом

https://i.postimg.cc/Gm6KMJBs/image.png

https://pastebin.com/SWJJwvvC

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

Скрины подфункций в следующем примере.

Тот же пример, но покрасивее

Что можно сделать для большего удобства? Убрать инициализацию, подвязку коллбэка на закрытие окна и главную петлю гтк в подддиаграму «главное окно»:

https://i.postimg.cc/vm5DYjsw/image.png

На сей раз не поленюсь сделать скрины и объяснить их суть.

В подфункциях есть три вида контейнеров с данными: константа (стала, constant), контроль и индикатор (сверху вниз):

https://i.postimg.cc/gJkfRVBd/image.png

Значение константы задается прямо в диаграмме. В Си константа превращается в объявление переменной с инициализатором. Контроли и индикаторы в теле подфункции превращаются в терминалы, к которым можно подключаться в «вызывающей» функции.

Сама подфункция «главное окно»:

https://i.postimg.cc/fbsDKR61/image.png

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

Все это уходит под капот, а жесткие последовательности (зеленые линии) все контролируют. Зеленая стрелка стоит на том что обязательно должно быть выполнено до того, как будет выполнен блок под красной стрелкой.

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

Подфункция для подцепки асинхронных функций:

https://i.postimg.cc/3r0rYVCS/image.png

Добавить объект в контейнер:

https://i.postimg.cc/SNGBhf51/image.png

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

https://i.postimg.cc/xjv7vP0j/image.png

Делаем лейбл (и любой другой нужный виджет) прокручиваемым:

https://i.postimg.cc/R0PtCmkd/image.png

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

https://pastebin.com/16bq1Jbs

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

Каст типов и тактическая победа над нуль-терминированными строками

Оказывается в текстовых буферах гтк можно задавать текст не нуль-терминированной строкой. Этим грех не воспользоваться. Изменяю подфункцию, создающую текствью:

https://i.postimg.cc/s2hrDj6b/image.png

Беззнаковое 32-битное, означающее размер массива (темно-синий провод) кастуется в знаковое 32-битное (светло-синие провода и пустая константа, задающая тип). Функция gtk_text_buffer_set_text в качестве размера строки берет беззнаковое, а не знаковое, как принято - видимо, чтобы через "-1" говорить, что строка нуль-терминированная. Но из-за этого вместо 4 гб строки туда можно подать лишь 2 гб - аж в 2 раза меншье! Что за люди?

Тем не менее, с нуль-терминированными функциями в текстовых полях покончено - и это победа!

https://pastebin.com/hQRMSZ1s

Также там был изменен текст. В остальном пример соответствует скринам выше.



Последнее исправление: CYB3R (всего исправлений: 7)
Ответ на: комментарий от metaprog

Haskell:

не надо декларировать переменные всякие

check, Type inference

ставить «;»

check

скобки (){}[]

check, pointfree

париться с оформлением текстового кода

check, hindent

могу называть все на своем языке

check, utf support

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

Лмао, да ему и жабаскрипт подойдёт:

не надо декларировать переменные всякие

check, Type inference + замыкания, ололо

ставить «;»

check, пускай и с нюансами

скобки (){}[]

увы

париться с оформлением текстового кода

check, prettier

могу называть все на своем языке

check, utf support

Deleted
()
Ответ на: комментарий от metaprog
  1. Хаскель сам выводит нужные типы для каждого выражения (а переменных в Хаскеле по сути вообще нет)
  2. Точки с запятой ставить не надо
  3. На хаскеле можно писать без скобок
  4. hindent делает твой код красивым сам
  5. Ну если utf – это заклинание, то я уж не знаю.

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

Очень рекомендую его и Эрланг к тщательному изучению, после этого возможно осознаете, почему вам все говорят про то, что нужно метапрог делать на ФП-языке.

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

Что такое utf-8 знаю, если что. С остальным проблема такая, что текстовый код мне дается тяжело в принципе. Один питон показывает, ты - хаскелл... кстати, покажешь пример кода на хаскелле? У тебя есть что в опенсорсе своего?

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

почему вам все говорят про то, что нужно метапрог делать на ФП-языке

Ну разве что сами схемы такими сделать...

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

Покажу ка я сам код на Haskell:

sptCreateStaticBinds :: HscEnv -> Module -> CoreProgram
                     -> IO ([SptEntry], CoreProgram)
sptCreateStaticBinds hsc_env this_mod binds
    | not (xopt LangExt.StaticPointers dflags) =
      return ([], binds)
    | otherwise = do
      -- Make sure the required interface files are loaded.
      _ <- lookupGlobal hsc_env unpackCStringName
      (fps, binds') <- evalStateT (go [] [] binds) 0
      return (fps, binds')
  where
    go fps bs xs = case xs of
      []        -> return (reverse fps, reverse bs)
      bnd : xs' -> do
        (fps', bnd') <- replaceStaticBind bnd
        go (reverse fps' ++ fps) (bnd' : bs) xs'

    dflags = hsc_dflags hsc_env

    -- Generates keys and replaces 'makeStatic' with 'StaticPtr'.
    --
    -- The 'Int' state is used to produce a different key for each binding.
    replaceStaticBind :: CoreBind
                      -> StateT Int IO ([SptEntry], CoreBind)
    replaceStaticBind (NonRec b e) = do (mfp, (b', e')) <- replaceStatic b e
                                        return (maybeToList mfp, NonRec b' e')
    replaceStaticBind (Rec rbs) = do
      (mfps, rbs') <- unzip <$> mapM (uncurry replaceStatic) rbs
      return (catMaybes mfps, Rec rbs')

    replaceStatic :: Id -> CoreExpr
                  -> StateT Int IO (Maybe SptEntry, (Id, CoreExpr))
    replaceStatic b e@(collectTyBinders -> (tvs, e0)) =
      case collectMakeStaticArgs e0 of
        Nothing      -> return (Nothing, (b, e))
        Just (_, t, info, arg) -> do
          (fp, e') <- mkStaticBind t info arg
          return (Just (SptEntry b fp), (b, foldr Lam e' tvs))

    mkStaticBind :: Type -> CoreExpr -> CoreExpr
                 -> StateT Int IO (Fingerprint, CoreExpr)
    mkStaticBind t srcLoc e = do
      i <- get
      put (i + 1)
      staticPtrInfoDataCon <-
        lift $ lookupDataConHscEnv staticPtrInfoDataConName
      let fp@(Fingerprint w0 w1) = mkStaticPtrFingerprint i
      info <- mkConApp staticPtrInfoDataCon <$>
            (++[srcLoc]) <$>
            mapM (mkStringExprFSWith (lift . lookupIdHscEnv))
                 [ unitIdFS $ moduleUnitId this_mod
                 , moduleNameFS $ moduleName this_mod
                 ]

      -- The module interface of GHC.StaticPtr should be loaded at least
      -- when looking up 'fromStatic' during type-checking.
      staticPtrDataCon <- lift $ lookupDataConHscEnv staticPtrDataConName
      return (fp, mkConApp staticPtrDataCon
                               [ Type t
                               , mkWord64LitWordRep dflags w0
                               , mkWord64LitWordRep dflags w1
                               , info
                               , e ])

    mkStaticPtrFingerprint :: Int -> Fingerprint
    mkStaticPtrFingerprint n = fingerprintString $ intercalate ":"
        [ unitIdString $ moduleUnitId this_mod
        , moduleNameString $ moduleName this_mod
        , show n
        ]

    -- Choose either 'Word64#' or 'Word#' to represent the arguments of the
    -- 'Fingerprint' data constructor.
    mkWord64LitWordRep dflags
      | platformWordSize (targetPlatform dflags) < 8 = mkWord64LitWord64
      | otherwise = mkWordLit dflags . toInteger

    lookupIdHscEnv :: Name -> IO Id
    lookupIdHscEnv n = lookupTypeHscEnv hsc_env n >>=
                         maybe (getError n) (return . tyThingId)

    lookupDataConHscEnv :: Name -> IO DataCon
    lookupDataConHscEnv n = lookupTypeHscEnv hsc_env n >>=
                              maybe (getError n) (return . tyThingDataCon)

    getError n = pprPanic "sptCreateStaticBinds.get: not found" $
      text "Couldn't find" <+> ppr n

-- | @sptModuleInitCode module fps@ is a C stub to insert the static entries
-- of @module@ into the static pointer table.
--
-- @fps@ is a list associating each binding corresponding to a static entry with
-- its fingerprint.
sptModuleInitCode :: Module -> [SptEntry] -> SDoc
sptModuleInitCode _ [] = Outputable.empty
sptModuleInitCode this_mod entries = vcat
    [ text "static void hs_spt_init_" <> ppr this_mod
           <> text "(void) __attribute__((constructor));"
    , text "static void hs_spt_init_" <> ppr this_mod <> text "(void)"
    , braces $ vcat $
        [  text "static StgWord64 k" <> int i <> text "[2] = "
           <> pprFingerprint fp <> semi
        $$ text "extern StgPtr "
           <> (ppr $ mkClosureLabel (idName n) (idCafInfo n)) <> semi
        $$ text "hs_spt_insert" <> parens
             (hcat $ punctuate comma
                [ char 'k' <> int i
                , char '&' <> ppr (mkClosureLabel (idName n) (idCafInfo n))
                ]
             )
        <> semi
        |  (i, SptEntry n fp) <- zip [0..] entries
        ]
    , text "static void hs_spt_fini_" <> ppr this_mod
           <> text "(void) __attribute__((destructor));"
    , text "static void hs_spt_fini_" <> ppr this_mod <> text "(void)"
    , braces $ vcat $
        [  text "StgWord64 k" <> int i <> text "[2] = "
           <> pprFingerprint fp <> semi
        $$ text "hs_spt_remove" <> parens (char 'k' <> int i) <> semi
        | (i, (SptEntry _ fp)) <- zip [0..] entries
        ]
    ]
  where
    pprFingerprint :: Fingerprint -> SDoc
    pprFingerprint (Fingerprint w1 w2) =
      braces $ hcat $ punctuate comma
                 [ integer (fromIntegral w1) <> text "ULL"
                 , integer (fromIntegral w2) <> text "ULL"
]

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

По моему вообще нечитаемо, вот код на С, тоже из компилятора. По моему все предельно ясно!

/* store vtop a register belonging to class 'rc'. lvalues are
   converted to values. Cannot be used if cannot be converted to
   register value (such as structures). */
int gv(int rc)
{
    int r, rc2, bit_pos, bit_size, size, align, i;

    /* NOTE: get_reg can modify vstack[] */
    if (vtop->type.t & VT_BITFIELD) {
        CType type;
        int bits = 32;
        bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
        bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
        /* remove bit field info to avoid loops */
        vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
        /* cast to int to propagate signedness in following ops */
        if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
            type.t = VT_LLONG;
            bits = 64;
        } else
            type.t = VT_INT;
        if((vtop->type.t & VT_UNSIGNED) ||
           (vtop->type.t & VT_BTYPE) == VT_BOOL)
            type.t |= VT_UNSIGNED;
        gen_cast(&type);
        /* generate shifts */
        vpushi(bits - (bit_pos + bit_size));
        gen_op(TOK_SHL);
        vpushi(bits - bit_size);
        /* NOTE: transformed to SHR if unsigned */
        gen_op(TOK_SAR);
        r = gv(rc);
    } else {
        if (is_float(vtop->type.t) && 
            (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
            Sym *sym;
            int *ptr;
            unsigned long offset;
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
            CValue check;
#endif
            
            /* XXX: unify with initializers handling ? */
            /* CPUs usually cannot use float constants, so we store them
               generically in data segment */
            size = type_size(&vtop->type, &align);
            offset = (data_section->data_offset + align - 1) & -align;
            data_section->data_offset = offset;
            /* XXX: not portable yet */
#if defined(__i386__) || defined(__x86_64__)
            /* Zero pad x87 tenbyte long doubles */
            if (size == LDOUBLE_SIZE)
                vtop->c.tab[2] &= 0xffff;
#endif
            ptr = section_ptr_add(data_section, size);
            size = size >> 2;
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
            check.d = 1;
            if(check.tab[0])
                for(i=0;i<size;i++)
                    ptr[i] = vtop->c.tab[size-1-i];
            else
#endif
            for(i=0;i<size;i++)
                ptr[i] = vtop->c.tab[i];
            sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
            vtop->r |= VT_LVAL | VT_SYM;
            vtop->sym = sym;
            vtop->c.ul = 0;
        }
#ifdef CONFIG_TCC_BCHECK
        if (vtop->r & VT_MUSTBOUND) 
            gbound();
#endif

        r = vtop->r & VT_VALMASK;
        rc2 = RC_INT;
        if (rc == RC_IRET)
            rc2 = RC_LRET;
        /* need to reload if:
           - constant
           - lvalue (need to dereference pointer)
           - already a register, but not in the right class */
        if (r >= VT_CONST || 
            (vtop->r & VT_LVAL) ||
            !(reg_classes[r] & rc) ||
            ((vtop->type.t & VT_BTYPE) == VT_LLONG && 
             !(reg_classes[vtop->r2] & rc2))) {
            r = get_reg(rc);
#ifndef TCC_TARGET_X86_64
            if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
                int r2;
                unsigned long long ll;
                /* two register type load : expand to two words
                   temporarily */
                if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
                    /* load constant */
                    ll = vtop->c.ull;
                    vtop->c.ui = ll; /* first word */
                    load(r, vtop);
                    vtop->r = r; /* save register value */
                    vpushi(ll >> 32); /* second word */
                } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
                           (vtop->r & VT_LVAL)) {
                    /* We do not want to modifier the long long
                       pointer here, so the safest (and less
                       efficient) is to save all the other registers
                       in the stack. XXX: totally inefficient. */
                    save_regs(1);
                    /* load from memory */
                    load(r, vtop);
                    vdup();
                    vtop[-1].r = r; /* save register value */
                    /* increment pointer to get second word */
                    vtop->type.t = VT_INT;
                    gaddrof();
                    vpushi(4);
                    gen_op('+');
                    vtop->r |= VT_LVAL;
                } else {
                    /* move registers */
                    load(r, vtop);
                    vdup();
                    vtop[-1].r = r; /* save register value */
                    vtop->r = vtop[-1].r2;
                }
                /* allocate second register */
                r2 = get_reg(rc2);
                load(r2, vtop);
                vpop();
                /* write second register */
                vtop->r2 = r2;
            } else
#endif
            if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
                int t1, t;
                /* lvalue of scalar type : need to use lvalue type
                   because of possible cast */
                t = vtop->type.t;
                t1 = t;
                /* compute memory access type */
                if (vtop->r & VT_LVAL_BYTE)
                    t = VT_BYTE;
                else if (vtop->r & VT_LVAL_SHORT)
                    t = VT_SHORT;
                if (vtop->r & VT_LVAL_UNSIGNED)
                    t |= VT_UNSIGNED;
                vtop->type.t = t;
                load(r, vtop);
                /* restore wanted type */
                vtop->type.t = t1;
            } else {
                /* one register type load */
                load(r, vtop);
            }
        }
        vtop->r = r;
#ifdef TCC_TARGET_C67
        /* uses register pairs for doubles */
        if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) 
            vtop->r2 = r+1;
#endif
    }
    return r;
}

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

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

Например: https://github.com/balsoft/lambda-launcher/

Но пользоваться этим вполне можно, хотя и делалось просто для отдыха.

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

Позволю себе предположить, что вытаскивание поля из именованной структуры. Без контекста в любом ЯП неочевидно, что происходит.

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

В Лабвью каждое действие очевидно на уровне блоков. Увидел блок по-отдельности - сразу понятно что делает.

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

Без контекста в любом ЯП неочевидно, что происходит.

Нет. Открой например код gtk, это конечно не компилятор... Но там все очевидно. Код Tiny C Compiler тоже прост, я как то его скачал и за вечер добавил туда классы, код очень прост и понятен.

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

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

А так-то я себе pandoc и xmonad патчил за вечер, там тоже всё очевидно. Даже более очевидно, чем в императивщине, потому что чистая функция не может натворить бед, и значение не может оказаться null, etc.

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

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

Я скинул выше кусочек, все довольно таки понятно.

А так-то я себе pandoc и xmonad патчил за вечер, там тоже всё очевидно.

Ну там же DSL уже есть вроде.

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

И что же такое gen_op(TOK_SAR); ?

Ну там же DSL уже есть вроде.

В этом и суть – на хаскеле легко писать DSL, который после этого легко читать. По сути любое ПО содержит свой DSL, просто в императивщине (типа сишечки) он менее понятен из-за слабеньких типов и возможности накосячить где угодно. Раст это несколько правит, но там тоже работы ещё много.

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

Ты видимо меня не так понял, я просто показал строчку, и попросил назвать ее смысл в большом куске что я дал. Ну а что такое р=гв(рс) подписанно строкой выше %) В Haskell коде выше почему то комментариев очень мало, да и названия выбранны неинформативные... Ужос.

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

В этом и суть – на хаскеле легко писать DSL, который после этого легко читать.

Ну код читать на нем не очень просто %)

просто в императивщине (типа сишечки) он менее понятен

Ну по моему flex, bison вполне понятен.

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

Не ту строчку сначала скопировал, обнови страничку.

В Haskell коде выше почему то комментариев очень мало, да и названия выбранны неинформативные… Ужос.

Зависит не от языка, как ты понимаешь.

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

Не ту строчку сначала скопировал, обнови страничку.

gen_op == generate opcode, TOK_SAR тут как генерируемое действие.

Зависит не от языка, как ты понимаешь.

Немного зависит, да и у хескеля всякие трюки в стиле '<$>%+W@+.

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

спроси у другого человека, который кодит и на сишечке, и на хаскеле

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

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

на хескеле пишут по фану и любознательности

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

Да хоть на pandoc глянь, если хочешь настоящего кода на хаскеле.

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

И вполне себе кровавый ынтерпрайз

Ты слышал о Red? Я когда то читал о нем новость где то, одну, на этом все. Чел выше rebforcer или как то так, говорит что и на нем интерпризе делает серьезные программы. Может и делает, но сколько библиотек на С/C++?

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

сколько библиотек на С/C++

И все можно использовать из хаскеля просто переписав заголовки.

Ты слышал о Red

Да

Чел выше rebforcer или как то так, говорит что и на нем интерпризе делает серьезные программы

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

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

И все можно использовать из хаскеля просто переписав заголовки.

С шаблонами, макросами, std::function каллбеками и наследованием?

Мысль была в том, что читаемость хаскеля очень видна в этом самом ынтерпрайзе.

Ну тут видимо как и со схемами, некоторые жалуются что они нечитаемые, другие говорят что класс! Для меня так же и хаскел нечитаем.

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

С шаблонами, макросами, std::function каллбеками и наследованием?

Это оставляется на совесть компилятору C/C++. std::function колбэки работают нормально.

Ну тут видимо как и со схемами, некоторые жалуются что они нечитаемые, другие говорят что класс! Для меня так же и хаскел нечитаем.

А вы пробовали? Понятно, что чтобы читать язык, нужно изучить синтаксис и стандартную библиотеку. Для хаскеля это делается за пару-тройку дней. (Справедливости ради, я тоже в течение года откладывал нормальное изучение хаскеля, считая его нечитаемым, но потом поменял мнение)

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

Это оставляется на совесть компилятору C/C++.

А покажи код, я чего то не понял. Отнаследуйся от sf::Sprite из <SFML/Graphics/Sprite.hpp>. Типа такого на плюсах:

class sprite : public sf::Sprite { };

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

А вы пробовали?

Читать?) Код на С/C++ мне казался вполне понятным еще когда я совершенно ничего не знал о программировании.

Для хаскеля это делается за пару-тройку дней.

Ну хескель не подходит для моих задач совсем, с чего начать? Пару тройку дней ради интереса я могу выделить!

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

Ну хескель не подходит для моих задач совсем, с чего начать?

Начать можно с прочтения https://learnyouahaskell.com , по крайней мере первых глав. Одновременно можно начинать писать свои хеловорды, ну и скриптецы можно пописывать вместо башей и перлов на хаскеле (понятно, что смысла не особо много, но всё же). Даже если сам хаскель не пригодится, мышление в функциональном стиле и умение думать типами можно использовать в любом языке.

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

Это соединение является недоверенным

Wtf?

А знаешь какие библиотеки есть для 3d графики? Только не лямбдакубе, это движок уже.

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

IDE? Emacs + haskell-mode + flycheck + ghc-mode + company работают на ура – типы показывает, ошибки подсвечивает на ходу, все значения с подходящими типами подсказывает, отладка в ghci встроенном. Вроде в vim тоже есть что-то подобное.

Ну и есть ещё какой-то yi, но там на любителя.

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

Я там уже смотрел, нету ж ничего. Разве что Visual Code ставить, пробовать, но столлман не оценит.

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

Ну за Red оно не совсем так. Ынтырпрайз (преимущественно французский и швейцарский) таки юзает Rebol 2.7, да. Штабильно, глобально, надёжно, древне, шо тот дебиан, и проприетарно, шо тот лабвью. Зато полную лицуху на SDK купил и ваяй что угодно. Syllable Desktop не даст соврать.

Red же, равно как и Rebol 3, ынтырпрайз ещё не юзает, ибо без network I/O как-то тяжко, да и сами разрабы что одного, что другого говорят, что анстейбл. Зато у Red в итоге по идее получится куда более кроссплатформенный и компактный рантайм, чем у всего того SDK от 2.7.8. Не говоря уж о прозрачной поддержке юникода и прочих фичах, без которых в 2019 году ЯП — не ЯП, а мечта мазохиста.

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

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

Гляну как-нибудь поподробнее. Я ж не ТС, кругозор расширять всегда полезно.

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

Отличная причина не заморачиваться с изучением хаскелла и переделкой уже работающего транслятора с Си на него.

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

Ого, Red даже без network I/O? А ты хотел, чтобы я променял 47-летний Си с огромным багажом исходников, библиотек, кодом ядра Линукс, системных служб и кучи прикладных программ и прочими плюшками на недоделку даже без сетевого функционала? Которую мне еще и учить, в отличие от Си? И транслятор тоже переделывать... И кто из нас выглядит глупее?

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

Тебе просто надо расширять кругозор, в современном мире бизнесу главное 50 базовых типов, а не какой то там устаревший TCP/IP!!!

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

Ого, Red даже без network I/O?

А в C (как языке) он с каких пор появился?

Сторонние биллиотечки-то я и в Реде подключить могу. А вот ты открыть HTTP URL как файловый дескриптор без потусторонних библиотек не можешь. А я в Реде могу. Чего нет - так это внутриязыковых конструкций для сокетов (появятся в 0.7.0), но сторонние костыли, как и у тебя, ничто для этого использовать не мешает. Так что обломись.

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

*библиотечки (биллиотечки - это от дяди Билли, лол)

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

А вот ты открыть HTTP URL как файловый дескриптор без потусторонних библиотек не можешь.

Могу открыть с помощью socks5 не напрягаясь, чего не может Red.

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

Не-а. Не сможешь ты сделать так, чтобы fopen вместо файлов открывал урлы, а fread делал GET по HTTP вместо чтения файла. Не говоря уж о том, что и OpenSSL в стандартную библиотеку не входит.

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

Не-а. Не сможешь ты сделать так, чтобы fopen вместо файлов открывал урлы

Стандарт С существует для переносимости кода между компиляторами. Вдумайся в эту фразу. Не обязательно себя ограничивать МИНИМАЛЬНЫМ наобором, он не для того нужен!

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

Кстати, можно сделать поддержку открытия файлов в сети через какой нибудь

fopen('http://...')
, почему нет? Это даже будет полностью соответствовать стандарту.

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

Тут смотри, какая загогулина получается:

  1. Си чисто как язык умеет чуть менее, чем ничего. Без инклудов от него толку ноль. Даже хей-лох-ворлд не вывести.
  2. Си + стандартная библиотека — толку уже гораздо больше. Академично и кроссплатформенно. Однако туда ни системные вызовы, ни расширения компилятора не входят, ни тем более сетевое взаимодействие. Те же сокеты — штука уже платформозависимая по факту. Для stdlib сети не существует, смирись.
  3. Си + прочие библиотеки — то, что используется IRL. Но загогулина-то в том, что эти библиотеки могут использоваться и из других языков, поддерживающих ту же конвенцию вызова, но при этом по пунктам 1 и 2 находящихся лет на 50 впереди Си.

Так что или крёстик сними, или трусы надень. Или сравнивай Ред со стандартным рантаймом и Си со стандартной библиотекой (которая в этом случае, разумеется, всосёт по полной), или не говори, что Ред что-то там не умеет, поскольку сторонние библиотеки там можно подключать ровно так же, как и в Си.

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

Си чисто как язык умеет чуть менее, чем ничего. Без инклудов от него толку ноль. Даже хей-лох-ворлд не вывести.

Да. Кстати, ассемблер тоже.

Си + стандартная библиотека — толку уже гораздо больше.

Я тебе уже рассказал какой от нее толк.

Однако туда ни системные вызовы, ни расширения компилятора не входят

Однако никто и не запрещает им туда входить.

Те же сокеты — штука уже платформозависимая по факту.

Да, но к примеру libcurl поддерживает платформ больше чем Red, так что где тут минус? Где? Наоборот у С плюс, он может юзать платформозависимые вещи, а это оптимизация, это возможности.

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

Бредятина. Только если это библиотеки с одной функцией void hello_world(void), иначе нужно вручную писать обвязки, плюс многие возможности будут ограниченны, попробуй использовать библиотеку для математики с inline, atomic где? Где int128? Нету ничего в этом отсталом язычке.

Или сравнивай Ред со стандартным рантаймом и Си со стандартной библиотекой

Нет, я сравниваю Red с библиотеками, и С с библиотеками, у С все готово, на Red нужно епстись.

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

уже работающего

Пока что не работающего по 2 причинам:

  1. Язык ещё по вашим словам «в разработке»
  2. Нет релиза

А вот изучение Хаскела я бы не советовал выбрасывать – когда надоест метапрог, будет очень интересно сменить парадигму. Но это на будущее.

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

Пока что не работающего

Кое-как, но работающего. По крайней мере, для меня.

когда надоест метапрог, будет очень интересно сменить парадигму

Ага, щас. Это ты лучше ребольщику посоветуй, он уже слился делать «антиметапрог».

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

Раз «антиметапрог» на основе red отложен в долгий ящик, я могу бросить вызов. На днях я провалил собеседование на C++/Qt разработчика, очень неприятно. Вот как раз хочу написать приличную программу на этом стеке.

Так что я могу попробовать сделать свой «антиметапрог». Только у меня совсем другое видение. Возложить на визуальное программирование простые задачи, где рулят скрипты. То есть, сфера bash, python. Есть идея парсить баш скрипты и генерировать простые схемы с пояснениями. Может даже генерировать простые скрипты, читаемые человеком, из схем.

Описание других идей приветствуется.

Более того, если буду пилить, то максимально открыто: с первых дней открытый репозиторий на гитхабе, типа отчёты о проделанной работе. Также обязательно заложить возможность расширять редактор различными способами помимо правки исходного кода.

Если начну, то обещаю релиз чего-то хоть как-то полезного раньше, чем релиз метапрога с полезным функционалом.

Однако я не начну, пока не будет хоть несколько человек «нужно, начинай» + помочь конкретнее сформировать суть проекта «схемы для скриптов»

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

Хммм, может все же спира поставишь Лабвью и будем совместно работать над Метапрогом?:)

shell-скрипты, python и прочая скриптота появилась из-за сложности программирования непосредственно на Си. С Метапрогом я думаю эту проблему решить и убить нужду в таких вот сложных и медленных скриптах.

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

В сравнении с твоим лабвью весь рантайм того же хаскеля — пушинка. Да что хаскеля — даже элма. Так что не надо ля-ля.

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

Кто знает как оно там в сравнении, но в любом случае от Лабвью я хочу отказаться после раскрутки.

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

будем совместно работать над Метапрогом?

Я - нет.

  1. Я не вижу смысла в визуальном программировании вне простых задач.
  2. Я уже упоминал, что для меня схемы в Unreal Engine гораздо понятнее твоих.
  3. У меня на подсознательном уровне отторжение сишки. А вот более высокоуровневые языки заходят норм.
  4. Я искренне люблю текстовые языки для больших и серьёзных поектов. Имхо, всё портит не текст, а говнокод и засилье в отрасли людей, у которых нет искренней любви к программированию.
  5. У меня искренняя любовь к ООП, но без фанатизма. Иногда люблю написать немного функциональщины. Очень ценю декларативность. И я очень сильно люблю Qt и питон.

скриптота появилась из-за сложности программирования непосредственно на Си

А также С++, Java, C# и прочих «серьёзных» языках. Но это касается только средних и больших проектах на «скриптоте». Есть множество «одноразовых скриптов» - написал и выполнил. Никакой компиляции, возни с бибилотеками и прочим геморроем серьёзных проектов. Copy&Paste скрипта и выполнить в 100 раз проще, чем искать исполняемый файл для своей платформы.

Напоминяю, что

Однако я не начну, пока не будет хоть несколько человек, которые сказали «нужно, начинай»

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

Я не вижу смысла в визуальном программировании вне простых задач.

Так ты вряд ли сделаешь что-то серьезное.

Есть множество «одноразовых скриптов» - написал и выполнил. Никакой компиляции, возни с бибилотеками и прочим геморроем серьёзных проектов. Copy&Paste скрипта и выполнить в 100 раз проще, чем искать исполняемый файл для своей платформы.

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

Словом, Метарпог решит эту проблему.

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

В Лабвью это еще проще

Нет, не проще. Сделать диаграмму хоть на 10 элементов дольше, чем выделить текст на несколько строк, Ctrl+C, Ctrl+V, Enter.

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

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

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

ты школьник игроман

Твоя настолько эмоциональная реакция указывает на то, что «школьник игроман» — это ты.

Школьником игроманом быть настолько плохо? Мы с товарищем после школы играли в элиту на спектруме, а когда надоедало, пытались программировать на бейсике и спектрумовском ассемблере.

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

Просто он технофошыст, все что не развивает технологии для него это плохо, такая вот логика.

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

все что не развивает технологии для него это плохо

Такого термина раньше не встречал. Но вроде «технофашизм» — это совсем наоборот https://habr.com/ru/post/395495/ . А если лурк читать, то там вообще всех гуманитариев в биореактор.

ЗЫ: модераторы, почистите тему.

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

Если проанализировать весь его бред, то скорее ПТУшник железнодорожного училища.

P.S. Пью Dr. Pepper, находясь в 4 кварталах от штаб-квартиры оного. Ваше здоровье, господа!

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

скорее ПТУшник железнодорожного училища.

А мне кажется, студент, первокурсник.

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

P.S. Пью Dr. Pepper, находясь в 4 кварталах от штаб-квартиры оного. Ваше здоровье, господа!

Пью водку дома. Ваше здоровье!

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

Лол. Тот Пеппер, что у нас, тот, что в Голландии и тот, что в Штатах, отличаются примерно так же, как C, C++ и C#. Штатовский мягче и слизистую не дерёт.

rebforce
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.