ЙажаСценарий / Говнокод #27855 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
function main() {
    let a: number | string;

    a = "Hello";

    if (typeof(a) == "string")
    {
	print("str val:", a);
    }

    a = 10.0;

    if (typeof(a) == "number")
    {
	print("num val:", a);
    }

    print("done")
}

Аллилуйя братья... я вам принес "union"-s . Возрадуйтесь новой фиче. (А ты можешь так в с/c++?)

дампик https://pastebin.com/QNmKFfT7

C:\temp>C:\dev\TypeScriptCompiler\__build\tsc\bin\tsc.exe --emit=jit --opt --shared-libs=C:\dev\TypeScriptCompiler\__build\tsc\bin\TypeScriptRuntime.dll C:\temp\1.ts 
str val: Hello
num val: 10
done

Запостил: ASD_77 ASD_77, (Updated )

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

  • std::variant<double, std::string> x;

    if (std::string* p = std::get_if<std::string*>(&x)) { ... }
    Ответить
            • > для 98

              Скопипастим-ка эту портянку ещё 20 раз... Или у них boost preprocessor уже тогда работал?
              Ответить
        • можно и в борланд C++ 3.1: работай только через указатель и RTTI. В примере с TS ведь сделано на самом деле именно так
          Ответить
          • у меня RTTI минимальный ... если его можно так назвать. скорее это TaggedUnion
            Ответить
  • Было бы еще хорошо добавить нормальную реализацию tagged union-ов (как в Расте например). А не: type MySumType = { kind: 'a'; fieldA: string } | { kind: 'b'; fieldB: boolean } .
    Ответить
    • Ну это будет уже не TS...

      Они же пытались очень тонкую прокладку для проверки типов сделать, а не новый язык. Видимо поэтому и не могут добавить какие-то скрытые магические поля в структуры.
      Ответить
            • и где здесь "т добавить какие-то скрытые магические поля в структуры."?

              Это касается только проверки типов. В результирующем JS ничего этого нет
              Ответить
              • в этом и прикол... что первое поле это и есть твое любимое магическое поле. которое имеет один и тот же тип для разных вариантов
                Ответить
                • Но оно ведь есть в js'е и называется точно так же? Т.е. не такое уж оно и магическое.
                  Ответить
  • Кстати, конпелятор все переменные обозначает magic tagged union-ами? Упадет ли на стадии компиляции код типа?

    let a: number = 4;
    typeof(a);
    Ответить
      • На уровне юзера - да. На уровне kernel-а ЖС - в общем случае tagged union (а вы как думали засчет чего динамическая типизация?). Но ведь ОП пилит конпелятор диалекта TypeScript в машинный код, там обычно принято не включать инфу о типе для встроенных типов.
        Ответить
        • В крестах тоже не принято, тем не менее typeof() там вполне работает для встроенных типов.

          З.Ы. Если их тип статически известен, конечно. Из void* он тип уже не вытрясет.
          Ответить
          • Так в крестах typeof() для встроенных типов — чисто компайл-тайп. В рантайме он работает только для вротуальных классов.
            Ответить
            • Что мешает в данной реализации TS поступить точно так же? Раз тип нам уже известен статически, то его и вернём.
              Ответить
              • Шаблонов не завезли.
                function foo(a: int | float) {
                    console.log(typeof(a));  // Не получается статически, насяльника.
                }
                foo(42);
                foo(16.16);
                Ответить
                • Дык в данном случае тип есть в рантайме и будет работать нормальный рантайм typeof().

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

                  Конкретной реализации ASD конечняо ничего не мешает
                  Ответить
                • тут получается т.к. за крышкой TaggedUnion

                  function foo(a: int | float) {
                  console.log(a); // Не получается статически, насяльника.
                  // а теперь получается начальника
                  if (typeof(a) == "number") console.log(a); // мы знаем, что в коде после typeof(a) 100% number
                  }
                  foo(42);
                  foo(16.16);
                  Ответить
          • typeof поди макрос/конструкт шаблона. В ЖС typeof именно оператор, выполняющийся в рантайме.
            Ответить
            • Но мы же конпелятор пишем. И он может раскрыть этот оператор и заранее подставить его результат. Тогда в рантайме можно такую переменную ничем не обмазывать.

              Тут главное в рантайме не дать string засунуть в этот number потом... Но я думаю это учтено.
              Ответить
        • >На уровне kernel-а ЖС - в общем случае tagged union (а вы как думали засчет чего динамическая типизация?).

          мы думали, что там говно в куче лежит, и динамически диспатчится по указателю
          Ответить
          • Зависит от реализации, наверное. Tagged union выглядит логичнее т.к. типов конечное число. Классов то нету.
            Ответить
            • сейчас нету, а завтра есть.
              Этоже только в TS ты можешь скзаать
              let a: number | string;

              а в JS этого знания нет.

              алсо, как там хранится строка?
              Ответить
            • А объекты уже сами хранят, какой функцией они были созданы. Переменная хранит только тег "указатель на кучу" и адрес объекта в куче.
              Ответить
          • Это уже лет 10 как минимум неактуально для ЖС-а. По-простому любая переменная в ЖС (без всяких JIT-компиляций) имеет тип:

            enum Variable {
            Number(uint64),
            String{ length: int64; begin: *char },
            Object(*void),
            Boolean(bool),
            // ...
            }

            На самом деле встроенных "типов" (различающихся по memory layout в т.ч.) больше

            https://v8.dev/blog/elements-kinds
            Ответить
            • переменная имеет вид перечисляемого типа?

              Или всмысле там юнион из uint64в котором может быть number, указатель на объект, bool, и указатель на строку с длиной на перевес?

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

              Документацию и пейперы лучше распостранять текстом. Если там очередное тикток видео на полтора часа, то оно не нужно
              Ответить
              • Ну да, буду щас копипастить простыню, вместо того чтобы сослаться на нее...

                > Или всмысле там юнион из uint64в котором может быть number, указатель на объект, bool, и указатель на строку с длиной на перевес?

                Скорее структура, которая хранит char-тег и юнион из uint64 (= number), указателя на объект, булеана, view для строки (сама строка лежит в куче) и пр.

                " говно в куче лежит, и динамически диспатчится по указателю" - это когда сами данные относящиеся к переменной, всегда хранятся в куче, а переменнная хранит лишь указатель на них не?
                Ответить
                • >Ну да, буду щас копипастить простыню, вместо того чтобы сослаться на не...


                  если бы она была текстом, то проблем бы не было. Видео на полтора часа неприлично предлагать:)

                  >Скорее структура

                  Ну да, я понял: у нас есть 64 бита, в них мы храним булен, намбр, указатель итд, смотря что за сущность у нас.

                  Так что typeof можно получить довольно быстро, действительно. А вот за instanceof придется ходить в объект вероятно по указателю
                  Ответить
                  • > Так что typeof можно получить довольно быстро, действительно. А вот за instanceof придется ходить в объект вероятно по указателю

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

                    > если бы она была текстом, то проблем бы не было. Видео на полтора часа неприлично предлагать:)

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

                      Угу. В JS есть типы boolean/string/итд/object, а уже object может быть инстансом класса. Информация о типе хранится прямо в юнионе, а о классе уже по ссылке


                      > Так впрочем ведет себя и Джава с Шарпом (иначе невозможна была бы рефлексия).

                      В C# есть value types структуры, их тип можно понять статически, но смысла в этом обычно нет.
                      Ответить
      • И если переменная a и на уровне kernel-а number, то вызов typeof вообще не валидный с точки зрения компилятора (упадет компиляция либо вызов функции вернет черт знает что).
        Ответить
        • валидный просто его значение известно зарание. typeof это не функция это конструкция языка
          Ответить
    • нет не упадет .. тк. компилятор тупо заменит typeof(a) на константу "number"
      Ответить
      • А при передаче в функцию, которая примает number | string, компилятор завернёт "a" в tagged union?
        Ответить
          • А я чет сначала подумала про то, что компилятор генерит портянку для каждого набора generic аргументов. Типа

            function f(x: number | string, y: Date | number) { ... }
            function main() {
              f(4, new Date());
              f("xabc", 10000000000000000);
            }


            Превращается перед компиляцией в байт-код во что-то типа:

            function f$x_number$y_Date(x: number, y: Date){ ... }
            function f$x_string$y_number(x: string, y: number){ ... }
            
            function main() {
              f$x_number$y_Date(4, new Date());
              f$x_string$y_number("xabc", 10000000000000000);
            }


            (как с плюсовыми шаблонами примерно)
            Ответить
              • Судя по тому, что typeof - компайл-тайм конструкт, такое предположение возникло. Иначе что должно быть сгенерированно вместо typeof(a) внутри функции, если какого конкретно субтипа будет a в общем случае известно только в рантайме.
                Ответить
                • Ну собственно рантайм проверка, которая смотрит какой из вариантов там реально лежит...
                  Ответить
              • Или typeof от аргумента функции внезапно не компайл-тайм конструкт а оператор вычисляющий по магическому полю аргумента строковый литерал? Интересная механика...
                Ответить
                • Компайлтайм конструкт, который раскрывается в рантайм проверку.
                  Ответить
                  • Компайл-тайм - это значит результат typeof(a) вычисляется во время компиляции. В рантайме if-ы с typeof будут просто болванками.
                    Ответить
                    • Или оптимизатор их вообще выбросит, если очевидно что они не вызовутся.
                      Ответить
                • Или даже так: если компилятор видит что функция вызывается только с небольшим числом вариантов аргумента, typeof вычисляется в компайл-тайме. И генерятся портянки функций. Иначе generic аргумент имеет тип tagged union-а и typeof - обычная функция, мапящая магическое поле на строку. Комбинаторного взрыва удается избежать.
                  Ответить
                  • Единственно надо учесть, что переменную могут посреди функции присвоить и она сменит тип. Такие функции видимо не стоит оптимизировать.

                    Т.е. например функция принимает int|string, мы в неё передаём int, но она внутри в эту переменную ложит string.
                    Ответить

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

Переведи на "PHP", guest!

    А не использовать ли нам bbcode?


    8