1. C++ / Говнокод #22504

    −138

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    #include "HelloWorld.h"
    namespace HelloWorld { 
        CoreLib::System::RuntimeType pituh::__type = CoreLib::System::RuntimeType(&HelloWorld::pituh::__rt_info);
        
        // Method : pituh.pituh()
        void pituh::_ctor()
        {
            base::_ctor();
            return;
        }
        
        // Method : 
        CoreLib::System::Type* pituh::__get_type()
        {
            return &HelloWorld::pituh::__type;
        }
        
        // Method : 
        bool pituh::__is_type(CoreLib::System::Type* value)
        {
            return ((&HelloWorld::pituh::__type == value) || base::__is_type(value));
        }
        
        // Method : 
        void* pituh::__get_interface(CoreLib::System::Type* value)
        {
            return base::__get_interface(value);
        }
        
        // Method : pituh.Main(string[])
        int32_t pituh::Main(__array<string*>* args)
        {
            CoreLib::System::Console::WriteLine(u"Kokoko!"_s);
            return 0;
        }
    
        pituh::__type_methods_table pituh::_methods_table;
        __runtimetype_info pituh::__rt_info = { u"pituh", u"", 18, false, &object::__type, nullptr };
    }
    
    auto __main(int32_t argc, char* argv[]) -> int32_t
    {
        __startup();
        auto exit_code = HelloWorld::pituh::Main(__get_arguments(argc, argv));
        __shutdown();
        return exit_code;
    }
    
    auto main(int32_t argc, char* argv[]) -> int32_t
    {
        return __main(argc, argv);
    }

    Вот такой красивый говнокод получается после прогонки С# HelloWorld в С++

    using System;

    class pituh
    {
    public static int Main (string [] args)
    {
    Console.WriteLine ("Kokoko!");
    return 0;
    }
    }


    тулза тут https://github.com/ASDAlexander77/cs2cpp

    Запостил: ASD_77, 07 Марта 2017

    Комментарии (130) RSS

    • и хедор на закуску


      и хедор на закуску

      #include "CoreLib.h"
      namespace HelloWorld { 
          class pituh : public object
          {
          public:
              typedef CoreLib::System::Object base;
              static CoreLib::System::RuntimeType __type;
              void _ctor();
              void* operator new (size_t _size)
              {
                  return __new_set0(_size, GCAtomic::Default);
              }
              void* operator new (size_t _size, const char* _file, int _line)
              {
                  return __new_set0(_size, GCAtomic::Default, _file, _line);
              }
              void* operator new (size_t _size, int32_t _customSize)
              {
                  return __new_set0(_customSize, GCAtomic::Default);
              }
              void* operator new (size_t _size, int32_t _customSize, const char* _file, int _line)
              {
                  return __new_set0(_customSize, GCAtomic::Default, _file, _line);
              }
              virtual CoreLib::System::Type* __get_type() override;
              virtual bool __is_type(CoreLib::System::Type*) override;
              virtual void* __get_interface(CoreLib::System::Type*) override;
              virtual object* __clone() override
              {
                  return new (__FILE__, __LINE__) HelloWorld::pituh(*this);
              }
              virtual int32_t __hash() override
              {
                  return __hash_code(this, sizeof(HelloWorld::pituh));
              }
              virtual bool __equals(object* obj) override
              {
                  return __equals_helper(this, sizeof(HelloWorld::pituh), obj, sizeof(HelloWorld::pituh));
              }
              static int32_t Main(__array<CoreLib::System::String*>*);
              class __type_methods_table : public __methods_table
              {
              public:
                  virtual CoreLib::System::Type* __get_type() override
                  {
                      return _typeof<HelloWorld::pituh*>();
                  }
              };
              static pituh::__type_methods_table _methods_table;
              static __runtimetype_info __rt_info;
          };
      }
      Ответить
      • и хедор на закуску

        PS: было уже
        Ответить
        • угу. я просто подумал что в коменты уже никто не лазит. решил сделать топик
          Ответить
    • >https://github.com/ASDAlexander77/cs2cpp/blob/master/Il2Native/Program.cs#L48
      Зачем все эти отрицания, коль есть Except?
      Ответить
      • Можно и Except но кол-во операций которые сделает Except будет порядка N*И а Where сделает только N операций но не суть важно в данном коде :)
        Ответить
        • Не, это моя дырявая башка подумала, что Except принимает не коллекцию, а условие.
          Ответить
          • Твоя гостеприимная дырявая башка...
            Ответить
    • Вы бы еще скрипт питона собраный в бинарник на "феншуй" проверили - зачем жаловаться на Белаз что его трудно парковать?
      Ответить
      • а там разве не тупо архив с python(.exe), кодом программы и зависимостями?
        Ответить
        • А кстати, может быть, хотя может и "добросовестный" компилятор.
          Ответить
        • .dll там, а не exe

          а так всё таки
          Ответить
    • > #include "CoreLib.h"
      > object
      > __array
      > string

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

        вот. из CoreLib.h

        typedef CoreLib::System::String string;
        typedef CoreLib::System::Object object;


        а вот вижимка для __array

        template <typename T> class __array : public CoreLib::System::Array
        {
        public:
        	int32_t _length;
        	T _data[0];
        ...
        }
        Ответить
        • ага. я линк на cs2cpp слишком поздно заметил.

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

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

              Сомнительное утверждение. Для объектов без деструкторов с коротким временем жизни ГЦ с поколениями может быть в среднем ощутимо быстрее, особенно когда счётчики ссылок должны быть атомарными. Без конкретных замеров затрат на различных юзкейсах это всё голословно.

              > ничем не лучше референс каунтинга

              Дефрагментация кучи.
              Ответить
              • Да, согласен что надо мерить

                но ГЦ все же требует отдельного потока и (иногда) стоп зе ворлд

                Яблоко говорит что дескать они меньше едят батарею чем андроид потому что у них не гц а рефкаунтинг

                >>Дефрагментация кучи.
                да, тут я погорячился
                Ответить
              • Можно еще присобачить какой-нибудь SMT солвер, который бы мог доказывать, что вот в этом месте на такую-то аллоцированную память никакие указатели уже не могут ссылаться и эта память уже точно использоваться не будет, и тут можно втулить free(). А для тех выделений памяти, к которым не получилось подобрать free() в автоматическом режиме, надо писать какие-то варнинги, чтобы программисты все это сами разгребали
                Ответить
                • ну так это и будет почти гц

                  гц вроде ищет пути к объектам из стеков потоков и стат памяти, и если нет -- выпиливает
                  Ответить
                  • нет, я предлагаю на этапе компиляции все определять, а гц это рантаймовая по своей сути штука
                    Ответить
                    • ну вот автоматик референс каунтинг так работает

                      но там есть жесткие правила кто ссыль увеличивает, а кто нет

                      грубо говоря функция useFoo(*bar) увеличивает ссылку на bar, а abuseFoo -- нет
                      Ответить
                    • удачи это делать на этапе компиляции.

                      switch(msg = socket.read()) {
                      case SESSION_OPEN:
                         session = new UserSession();
                         break;
                      case COMM_TIMEOUT:
                      case SESSION_CLOSE:
                         if (session) { delete session; session = NULL; };
                         break;
                      }
                      Ответить
                  • Это хуевый гц так делает (boehm например), нормальный по стекам лазать не будет
                    Ответить
                    • а как?
                      Ответить
                      • У нормального гц своя управляемая куча, из которой он выделяет и ее потом мониторит
                        Ответить
                        • как мониторит?

                          на каждый выход ссылки из зоны видимости уменьшает счетчик?
                          Ответить
                          • Как вариант. В любом случае лучше, чем хуярить по стеку до посинения
                            Ответить
                            • не до посинения а пока не наткнешся на "свою" метку которая скажет что это конец(начало) стека :)
                              Ответить
                              • Ага, постоянно
                                Загружая при этом процессор под сотку
                                Ответить
                                • За все нужно платить :) в случае с ГЦ - цайклами CPU а если учесть что их сейчас вагон и маленькая тележка(корок на проце) то можно и не жалеть :)
                                  Ответить
                                  • Вообще-то за гц платят прежде всего памятью. А про цпу - в теории гц может быть перфоманснее традиционной кучи.
                                    Ответить
                    • Если ГЦ не будет лазить по стекам то она может удалить используемый обьект т.к. посчитает что на него нет референсов и отметит участок памяти как не используемый.

                      вот пример

                      Bla::Foo(new Boo());


                      единственная ссылка на память(обьект) Boo находиться только в стеке и если в этот момент вызвать GCCollect и не проверить стэк то обьект Boo будет удален а значить вызов Bla::Foo приведет к Memory Access ошибке
                      Ответить
            • а что бы не юзать смарт поинтеры да и проще для имплементации использовать C++ GC. https://www.hboehm.info/gc/ Это как раз кросплатформенная либа которая прекрасно работает
              Ответить
            • > а зачем там гц?

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

              > Вообще я всё меньше понимаю зачем нужен ГЦ.
              > кроме поддержки циклических ссылок

              именно. результат: проще семантика.

              > он ничем не лучше референс каунтинга,

              референс каунтинг - отстой. я его делал пару раз в ручную, и толку от него было мало. если дата модель позволяет использовать референс каунтинг без граблей, то там и до детерменистического life cycle объектов не далеко. а если у объектов детерменистический life cycle, то гц и не надо: если знаешь точно когда можно/нужно удалять объекты, то не велика работа их удалить.

              на самом деле, полноценный гц - это просто облегчение жизни. ну как коробка-автомат: профи ругаются что типа не эффективно, а всем кому просто из А в Б доехать надо это приятная (не)мелочь.
              Ответить
              • >>потому что шарп использует гц.
                Не знаю является-ли работа с памятью частью требования к ЯП. Хотя ключ слова delete в нем нет, и метода release у System.Object (а это стдлиба япа) тоже нет.

                >>референс каунтинг без граблей,
                каких граблей?

                Я создал объект и ссылка пошла гулять по куче. Как мне узнать когда его можно того?
                Ответить
                • > > референс каунтинг без граблей,
                  > каких граблей?

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

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

                    да, это не решается без гц
                    я про это сразу сказал
                    Ответить
              • а
                я понял про грабли

                типа такого
                https://developer.apple.com/reference/foundation/nsautoreleasepool
                Ответить
              • > если знаешь точно когда можно/нужно удалять объекты, то не велика работа их удалить
                Мне кажется, это отвлекает, рассеивает внимание программиста, уводит от цели, понижает понятность. Вместо того, чтобы работать над алгоритмом, программист работает над тем, чтобы разложить байты вручную.

                А потом само мышление начинает исключать случаи, где отсутствие гц - боль. Например, по условию из функции возвращаем либо переданный объект, либо объект по умолчанию; из функции возвращает либо элемент переданной коллекции, либо новый созданный элемент. Без гц и подсчёта ссылок повезёт, если такие "либо-либо" возвращают объекты с разными классами владельцев (как в первом случае), а то вообще могут возвратить какую-то странную питушню (как во втором случае). Программисту приходится городить подсчёт ссылок/копирование или претворяться, что вообще таких способов передачи ссылок не существует.
                Ответить
                • > > если знаешь точно когда можно/нужно удалять объекты, то не велика работа их удалить

                  > Мне кажется, это отвлекает, рассеивает внимание программиста, уводит от цели, понижает понятность

                  ты выдрал из контекста. речь шла о реф-каунтинге. редкий язык его нативно поддерживает - что значит что в общем случае надо самому ручками прикручивать. явное удаление - против явного реф-каунтинга, я не уверен что хуже.
                  Ответить
                  • Ну вот шланг умеет рефкаунтинг для свифта и objc, причем делает это автоматически.
                    Получается относительно не плохо: не надо руками писать retain (+) и release (-) но нужно учитывать что:

                    1) циклические ссылки это мемори лик. Так что ВЕЗДЕ есть четкие правила в какую сторону нужно иметь weak reference. Это нужно помнить и соблюдать.
                    2) если функция создает объект и возвращает его, она вынуждена увеличить ссылку (потому что без ссылки он сразу коллектница), но кто должен уменьшить эту ссылку потом? Вызывающая сторона не знает отдали-ли ей новый объект или старый (это то, о чем говорит 1024). Для этого есть тот самый pool в который кладутся такие объекты и потом он коллектится (обычно в конце евентлупа)
                    3) наконец рефкаунтинг не работает для плейнси. Там надо самому делать retain/release, причем надо помнить что функции с названием create делают reatin а get -- нет (говорю по памяти но правила именно такие -- по НЕЙМНИГУ)

                    Так что это конечно проще чем вручную делать free, но внимательность всё равно нужна
                    Ответить
                    • в теории, цикличность рефкаунтинга можно проверить на этапе компиляции. По кр мере worst case
                      Ответить
                      • В теории нельзя.
                        a.next = &b;
                        if (find_riemann_hypothesis_contradiction()) {
                          b.next = &a;    
                        }
                        Ответить
                        • так если true, то это и есть демонстрация worst case.
                          Ответить
                          • И получится раст, в котором двусвязный список без unsafe не написать. Такой статический анализ нам не нужен.
                            Ответить
                            • ты облысеешь что ли, если тебе компилятор даст ворнинг: "у вас потенциально циклическая ссылка"?
                              Ответить
                              • А ты из тех, кто кладет болт на простыню ворнингов от компилятора? Нерешенные ворнинги вредны, т.к. отвлекают на себя внимание и прячут настоящие ошибки. Их надо либо чинить, либо выключать нахуй.
                                Ответить
                                • я делаю чтоб ворнингов вообще не было. Поэтому и хочу какой-то переносимый способ их отключать для конкретной строки или блока, где они возникают.
                                  Ответить
                                  • Корочи ты сам не знаешь, чего хочешь. Закончим.
                                    Ответить
                                    • слышь чо, за базар ответь
                                      Ответить
                                      • На пенёк сел - косарь отдал ёпта!
                                        А как ви себе это представляете, переносимый способ убирать ворнинги? Насколько я знаю, стандарт си/плюсов вообще никак не затрагивае тему того, что есть какие-то там ворнинги. Нужно добавить это в стандарт? Под плюсы даже name mangling никто не стандартизировал(что кстати является проблемой куда серьезнее), какие к дьяволу стандартизации варнингов?
                                        Ответить
                                        • Даже в Plain C есть расхождения в name mangling в разных компиляторах, хотя Plain C не поддерживает перегрузку и по идее name mangling в Plain C вообще не нужен.
                                          Ответить
                                        • Вика пишет: "On Microsoft Windows, the Intel compiler and Clang uses the Visual C++ name mangling for compatibility". Странно, у меня шланг генерирует гэцэцэшные имена, а не микрософтовские. Никому верить нельзя...
                                          Ответить
                                        • > Насколько я знаю, стандарт си/плюсов вообще никак не затрагивае тему того, что есть какие-то там ворнинги

                                          Плохо знаешь:
                                          "— If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message."
                                          diagnostic message и есть warning. Еще, из с++17:
                                          http://en.cppreference.com/w/cpp/language/attributes
                                          Вообще не вижу проблемы ввести аттрибут аля [[nowarn]] или [[nowarn=sign-compare]]

                                          > Под плюсы даже name mangling никто не стандартизировал(что кстати является проблемой куда серьезнее)

                                          Потому что для этого надо стандартизировать calling conventions и сделать один из них стандартным по умолчанию. Можешь представить, сколько программ это сломает? Какого члена они не стандартизировали эти вещи с самого начала? Наверно, производители компиляторов сыграли в "лебедь, рак и щука"
                                          Ответить
                                          • просто кал конвешнеш был разный на разных платформах и часто вообще был продиктован ЦПУ

                                            И конечно же копеляторы должны были генерить код под свою платформу чтобы интероптица с уже существующим кодом
                                            Ответить
                                          • >Плохо знаешь:

                                            Да, действительно. Не думал, что они ПРО ЭТО напишут в стандарте.

                                            >Вообще не вижу проблемы ввести аттрибут аля [[nowarn]] или [[nowarn=sign-compare]]

                                            И написать еще в стандарте подробнейший список того, на что должен и на что не должен выдавать варнинг компилятор (с примерами кода), и что вот этому варнингу соответствует "sign-compare", вот этому "NULL-dereference-possible", а этому "undefined-behaviour-div0"? Не, я не говорю что это невозможно сделать, просто есть задачи поприоритетней.

                                            В идеале я считаю из компилятора вообще надо выкинуть все варнинги(кроме тех, из-за которых код тупо не компилируется, но это уже не варнинги, это ошибки компиляции). Потому что анализаторы, встроенные в разные компиляторы могут с разным успехом диагностировать разные ошибки, и например может иметь смысл прогонять некий код и через анализатор gcc и анализатор clang, потому что множество варнингов, которые может выдать gcc но не clang и выдать clang но не gcc, т.е. симметрическая разность двух множеств варнингов для разных компиляторов будет не пустой, так не лучше ли отцепить анализатор от компилятора, чтобы применять его отдельно? Ну как PVS-studio какую-то. На кой черт это надо обязательно заставлять делать при компиляции?
                                            Ответить
                                            • дело говоришь
                                              Ответить
                                            • > Не, я не говорю что это невозможно сделать, просто есть задачи поприоритетней.

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

                                              > На кой черт это надо обязательно заставлять делать при компиляции?

                                              Статический анализ многократно дольше компиляции, а диагностики компилятора не налагают существенных затрат. Вот и выходит, что проще ловить простые ошибки (типа опечаток) на лету, а на сложные пусть сервер проверяет анализатором перед коммитом.
                                              Ответить
                                              • > Статический анализ многократно дольше компиляции

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

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

                                                Ну так можно запускать статический анализатор в облегченном режиме, чтобы он анализировал это так же, как это делает компилятор, не вижу в этом никаких проблем. Например, перед коммитами мне вот действительно приходится компилировать, но конечным результатом (скомпилированным бинарем) я не пользуюсь, и компилирую я именно чтобы отловить всякие тупые ошибки. Т.е. фактически компилировать мне не надо, мне нужны только варнинги, и всякие там юнит-тесты запускаются не у меня на компе.
                                                Ответить
                                                • признаться, не видел сложных constexpr-функций, кроме как в синтетических примерах
                                                  Ответить
                                      • ответил тебе за щеку, проверь
                                        Ответить
                            • а низя просто одну ссылку сделать типа слабой?
                              Ответить
                              • Можно даже сильной. Но использовать референс каунтинг для реализации списка - это так себе тема.
                                Ответить
                                • Не знаю парни. Я поюзал GC на крестах и больше чем доволен. Моменты когда происходит коллект мусора почти незаметны
                                  Ответить
                                  • Это какой-то сетевой маркетинг? Этот боэм никому не нужен, особенно в крестах.
                                    Ответить
                                    • да уж, гц без поколений в 2к17 разве что для лаб или недоязыков типа го применим.
                                      Ответить
                                    • если бы это было так так жаба и хшарп бы никогда не родились бы в этом мире
                                      Ответить
                                  • > Я поюзал GC на крестах и больше чем доволен
                                    Спасибо, ты мне напомнил про С++/CLI, и где теперь мой обед.
                                    Ответить
                                    • ты не можешь сравнивать чистый С++ с жутким гибридом между MSIL и ASM :)
                                      Ответить
                                • а как бы вы реализовывали референс каунтинг для XOR-связного списка?
                                  Ответить
                                  • Это точно не та задача, где правильный ответ - уебать автору?
                                    Ответить
                                    • Ты про xor список? Задачи бывают разные, и я допускаю, что может возникнуть необходимость сделать список (или даже несколько) на очень большом количестве маленьких структур. Экономия 30-50% памяти может стоить ебли с ксорами.
                                      Ответить
                                  • очевидно нужно иметь явное понятие референс

                                    если ты хранишь int и ксоришь его чтобы получать адрес то никто (кроме тебя) не знает что это ссыль или указатель

                                    тут не раьботает ни гц ни рефкаунт
                                    Ответить
                  • > ты выдрал из контекста
                    > явное удаление - против явного реф-каунтинга
                    Я писал про пользу неявного с гц. Действительно, написал комментарий не по теме.
                    Ответить
          • по поводу ГЦ

            вот что использованно для ГЦ

            https://www.hboehm.info/gc/

            Кросплатформенная либа работает везде
            Ответить
    • Идея: получившийся .cpp-файл скомпилировать с ключом /clr:pure, чтобы получить байткод вместо нативного, и снова прогнать.
      Ответить
      • Ха-ха. Поидее это должно скопилять ужасного зверя (но думаю тупо не скомпилиться по какой-нить ошибке)
        Ответить
    • попробовал код с async

      C# async
      public async void AsyncTest()
      	{
      		await Task.Delay(10);
      	}


      Развернуло в 1 метод + 1 класс

      // Method : pituh.AsyncTest()
          void pituh::AsyncTest()
          {
              HelloWorld::pituh_GAsyncTestCd__1 LoweringTemp_1;
              {
                  CoreLib::System::Runtime::CompilerServices::AsyncVoidMethodBuilder LoweringTemp_2;
                  LoweringTemp_1.GCt__builder = CoreLib::System::Runtime::CompilerServices::AsyncVoidMethodBuilder::Create();
                  LoweringTemp_1.GC1__state = -1;
                  LoweringTemp_2 = LoweringTemp_1.GCt__builder;
                  LoweringTemp_2.template Start_Ref<HelloWorld::pituh_GAsyncTestCd__1>(LoweringTemp_1);
                  return;
              }
          }


      и дохрена кода ...

      ....
      Ответить
    • Вот вам еще подобного бреда https://github.com/frranck/asm2c
      Swift tool to transform DOS/PMODEW 386 TASM Assembly code to C code
      Только там надо какой-то свифт ставить, чтобы это собрать
      Ответить
      • Собственно, эта хрень была написана для портирования какой-то досовской игрушки:
        https://github.com/libretro/mrboom-libretro

        Конвертированный код выглядит довольно мерзко:
        https://raw.githubusercontent.com/libretro/mrboom-libretro/master/mrboom.c
        Ответить
        • Посоны, не открывайте, я прочитал буквально чуть-чуть и чуть не стал Настенькой.
          Ответить
        • Мне кажется аффтор поленилься и не захотел собрать это в нормальный "С" код. ASM не плохо транслейтится в С а если есть проблемы то некоторые учатски можно было заменить макросами как это было сделанно. :)
          Ответить
      • > Только там надо какой-то свифт ставить, чтобы это собрать

        > .xcodeproj

        Там ещё какой-то мак нужно ставить, чтобы это собрать.
        Ответить
        • Думаю что можно и под линуксами. Код я не читал, но скорее всего это что-то консольное, и всяких там Cocoa и прочих мак-специфичных вещей оно требовать не будет, а компилятор свифта есть и под линуксы
          Ответить
      • Существует ли конвертор из Свифта в Objective-C? В обратную сторону нашёл, а в эту пока не получается.
        Ответить
        • Думаю, вряд ли. Зато существует конвертор C в Rust, C в Go, C++ to C#, C в Java и еще какие-то кривые компиляторы C в брейнфак
          Ответить
    • а я баг в коде нашел, но править не буду :)
      Ответить
      • показать все, что скрытоЯ тоже баг нашел. Ты кончаешь с перебоями.
        Непорядок. Засор.
        Ответить
        • Vanished
          Ответить
          • умей проигрывать голубчик
            сказал проктолог так нельзя
            и стал вытаскивать из глеба
            ферзя
            Ответить
            • Умей проигрывать, голубчик,
              Сказал проктолог. Так нельзя!..
              И стал вытаскивать из Глеба
              Большого черного ферзя.
              Ответить
    • Офтопик. Случайно обнаружил, что у LLVM версии до 3.1 был бекенд C (да, язык программирования Си). При указании параметра компилятора -march=c генерировался сишный код вместо нативного. Можно было даже из программы на C++ генерировать программу на C (как cfront).

      Пример (копировать сюда не буду из-за размера):
      http://web.archive.org/web/20100615232803/paste.lisp.org/display/73134

      А теперь представим, что получится, если сначала прогнать C# → C++, а потом C++ → С.
      Ответить
    • # auto main(int32_t argc, char* argv[]) -> int32_t

      Красота-то какая! Комитет решил добавить синтаксис для того, что бы пользователь помогал компилятору выводить типы?
      Ответить
      • > пользователь помогал компилятору выводить типы
        А что зелёным? Именно для этого и прикрутили эту хрень...
        template <typename T1, typename T2>
        auto foo(T1 a, T2 b) -> decltype(a + b) {
            // ...
        }
        Ответить
        • # auto foo(T1 a, T2 b) -> decltype(a + b) {

          decltype(a + b) foo(T1 a, T2 b) {

          PS. Да, я знаю, что a и b ещё не объявлены. Но неужели нельзя было как во всяких там Сишарпиках делать? Не нужны были бы эти "предварительные объявления" (или как они там, в крестах?)
          Ответить
          • Подозреваю, что создатели крестов мечтают об однопроходном компиляторе, а хранить лишние данные в стеке компилятора не хотят. Пирфоманс!
            Ответить
            • # об однопроходном компиляторе

              И даже без AST, сразу строчат машинный код?
              Ответить
            • > однопроходном компиляторе
              И при этом оптимайзер всё равно делает 100500 заходов, чтобы упростить всю высранную однопроходным фронтендом метушню...
              Ответить
              • Кстати, в Турбо Паскале и в Дельфи есть как минимум два типа предварительных объявлений:

                1. Директива forward у функции, чтобы можно было создавать косвенную рекурсию. Аналог в няшной — голый прототип.

                2. Можно объявить указатель на ещё не полностью определённый тип. Используется, например, для создания связных списков.
                type
                  PFoo = ^TFoo;
                  TFoo = record
                    field1, field2: Integer;
                    next, prev: PFoo;
                  end;

                Сишный аналог кода:
                typedef struct Foo_tag {
                  int field1, field2;
                  struct Foo_tag *next, *prev;
                } Foo;


                Извращенцы могут определить в Object Pascal указатель на функцию, принимающую указатель на такую же функцию и/или возвращающую указатель на такую же функцию:
                type
                  PMyFunc = ^TMyFunc;
                  TMyFunc = function(x: PMyFunc): PMyFunc;

                А как с этим в няшной и в крестах?
                Ответить
                • Ну частично работает для структур: typedef struct Foo* LPFOO.
                  Ответить
                • В няшной был какой-прикол из серии: "можно декларнуть указатель на незавершенный тип" и потому собственно приведенный твобой пример с рекурсивной структурой работает.
                  А если бы там был не указатель то фиг.

                  Вероятно потому что для подсчета размера указателя не нужно знать весь тип, а для размера типа нужно.
                  Ответить
            • # об однопроходном компиляторе

              Об заднепроходном компиляторе
              Ответить
            • > Подозреваю, что создатели крестов мечтают об однопроходном компиляторе

              Сомневаюсь. Скорее всего, проблема в потенциальном сокрытии имён.
              class Rational { /* ... */ };
              
              extern const Rational a, b;
              
              template <class T1, class T2>
              /* which a and b ? */ decltype(a + b) foo(T1 a, T2 b) {
                return a + b;
              }
              Ответить
              • > проблема в потенциальном сокрытии имён
                Но ведь имена - это не проблема для компилятора. Можно сразу после парсинга поменять местами список аргументов и возвращаемый тип, после чего на это AST отдать на вход алгоритмам (а таковые реализованы, т.к. компиляторы C++11 существуют).

                Остаются только людские сомнения, которым в C++ уже противостоят работающие исключения из простых правил:

                Преждевременное использование неинициализированной питушни (аргументов) - тоже не проблема как для компилятора, так и для человека, т.к. вещи вида struct X { X():x(0){} int x; }; работают.

                И область видимости, не покрытая фигурными скобками - тоже не проблема как для компилятора, так и для человека, т.к. аргументы функции объявляются где-то вне фигурных скобок, опоясывающих тело, а видны только внутри них.
                Ответить
                • остаётся только радоваться, что ты не глава комитета
                  Ответить
                  • Есть ли чему радоваться? Может если бы 1024-- был главой комитета, в плюсах бы не появилось два разных синтаксиса для объявления функций.
                    Ответить
                  • То есть вводить инородное с точки зрения C++ ololouto fname(fargs) -> typexpr - вполне себе нормально, а понять, что typexpr fname(fargs) вполне встраивается в существующую логику - грешновато?

                    Как по мне, если и вносить инородную питушню, то хотя бы что-то реальное полезное и более удобное. Например, сделать наконец работающие typedefы для функций и обновить описания типов.
                    typedef array_of_pointers = [int*]; // no brain spiralling while reading typeshnya
                    int* a, b; // a, b are pointers
                    // const int c; // ERROR
                    int const c; // OK
                    int* const d; // constant pointer
                    int const* pd; // pointer to a constant
                    typedef cleaner_t = (array_or_pointers, size_t lenght) -> int;
                    typedef binary_getter_t = void -> (int, int) -> int;
                    cleaner_t free_pointers(pointers, length) {
                      for(int i=0; i<length; i++) free(pointers[i]);
                      return 42;
                    }
                    Ответить
                    • Я не говорю, что добавление второго синтаксиса f(...) -> decltype(...) не выглядит как говно. Это необходимое зло, т.к. сишка —изначально говно, тип возвращаемого значения функции должен идти после типов аргументов, это любому вменяемому человеку очевидно (см синтаксис Паскаля и любого современного статически-типизированного языка: scala, rust, ocaml, etc.). Т.е. проблема в том, что примерно такой синтаксис должен быть введён изначально.

                      Я говорю, что decltype(a+b) f — это говно, потому-то возникает проблема с именами. Тебе кажется логичным, что имена должны привязываться к параметрам, а мне — наоборот.

                      Что то говно, что это говно.
                      Ответить
                      • >>etc
                        swift, kotlin.

                        А откуда вообще в сишке такой говносинтаксис?
                        Ответить
                        • > А откуда вообще в сишке такой говносинтаксис?

                          Ritchie's idea was to declare identifiers in contexts resembling their use: "declaration reflects use".

                          Видимо, хотели, чтобы было "интуитивненько", по заветам 1024--, типа
                          int f(float)
                          x = f(y)
                          ------------------------
                          значит, x : int, y:float
                          Получилось как всегда.
                          Ответить
                          • > resembling their use: "d
                            ага, отсюда же и char *foo, c
                            потому что c = *foo

                            фу таким быть!
                            Ответить
                            • Всё предельно логично.
                              > "declaration reflects use"
                              Нельзя с первого раза поработать с памятью без утечек и UB.
                              Нельзя с первого раза объявить несколько указателей.
                              Ответить
                              • Цинизм в том, что можно написать "char* foo, bar, buz" и тут наверняка нуб споткнется
                                Ответить
                                • хорошо что есть особый gnu extension, можно писать "typeof(char *) foo, bar, buz" и никаких проблем
                                  Ответить
                                  • Почему-то в няшной и в крестах почти всё, что по стандарту, сделано плохо, а то, что сделано хорошо, оказывается вендорным расширением.

                                    Например, #pragma link, #pragma library, #pragma comment (lib), призванные хоть как-то компенсировать отсутствие модульности, так и не стали стандартом. Да даже диапазоны в switch-case есть только у gcc.
                                    Ответить
                                  • Удобно. Пусть в каждом компиляторе будет что-то свое, пусть расцветают сто цветов!

                                    Вы не подумайте: я люблю няшную, код люблю писать, а вот читать -- нет.
                                    Ответить
                                    • Да просто у других языков всего один компилятор, поэтому все эти "нестандартные" расширения воспринимаются не так нестандартно.
                                      Ответить
                                  • А в плюсах можно наметушить
                                    template<class T> using typeof = T;
                                    typeof<char *> h, p, j;

                                    Вот она, метушиная сила - любую хуйню можно сделать.
                                    Ответить
                • Твой никнейм натолкнул меня на мысль, что люди нерационально используют дары природы - считают на пальцах до десяти, используя единичную систему счисления, когда могли бы считать аж до 1023. Хотя человеческих возможностей все равно не хватит, чтобы представить результат выражения, записанного в твоем нике.
                  Ответить
                  • > могли бы считать аж до 1023
                    Мне кажется, было бы не так надёжно. Если случайно разогнётся один палец, то результат изменится на какое-то число от 2^0 до 2^9 вместо единицы.
                    Ну и число "3" (или "20") показывать сложно (невозможно?).
                    Если взять только все доступные среднему человеку кобенации с пальцами и фалангами, уже сложно будет запомнить, не пытаться корячиться и восстановить число по положению пальцев.

                    Кстати да, какая бы система счисления была бы у нас, если бы был выбран вариант счёта с использованием всех физически доступных кобенаций пальцев и фаланг? Наверно какая-нибудь странная питушня вроде дюймов, футов, миль или дней в месяцах. Во всяком случае, во французском языке, если не ошибаюсь, 80..89 уже сейчас именуют как семьдесят десять, семьдесят одиннадцать, ..., семьдесят девятнадцать, а где-то ещё в цивилизованной Европе не гнушаются названий вида "пару раз сорок плюс треть пятнадцати". И это только с загибанием пальцев согласно количеству!
                    Ответить
                    • В муриканских фильмах считают дюжинами. Даже такое нетрудное число как 50 они называют «четыре раза по двенадцать и ещё два».
                      Ответить

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