- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};
type LockedAccount = {
readonly id: string;
readonly name: string;
};
type UnlockedAccount = CreateMutable<LockedAccount>;
function main() {
let a: LockedAccount;
let b: UnlockedAccount;
print("done.");
}
Доказать это утверждение будет домашним заданием.
https://govnokod.ru/23275#comment389295
Это классика! Это знать надо!
Вообще-то да.
> Ведь вся хуйня с перестройкой AST может отработать на этапе компиляции
Не может, а это единственный вариант.
> и уже потом всё четко откомпилируется без всяких интерпретаторов, и отлично в контроллеры встраивается.
А это правда.
Так как компиляция и выполнение программы – два раздельных этапа, невозможно создать гомиконный компилируемый язык. Придётся либо как-то разделять файлы на АСД-питушню, либо для питуления АСД разрабатывать отдельные синтаксические штучки.
Нет. Неинтерпретируемость языка никак не мешает на этапе компиляции работать с его AST. Можешь представить себе программу на Си, которая на вход принимает свой собственный исходник и в нем что-то переписывает, и потом высирает окончательный исходник? Так вот, никакого интерпретатора тут не нужно.
> Не может, а это единственный вариант.
Нет. Не вижу проблемы в том, чтобы программа динамически перестраивала свой AST в процессе выполнения. Можно сделать даже интерпретатор и JiT над этим AST.
В скомпилированной программе нет АСД, там машинные коды. Преобразование исходного кода в АСД – это этап компиляции, чтобы потом это АСД преобразовать в какой-ниюудь другой вид, например в машинные коды или исходные коды на другом языке программирования.
> Неинтерпретируемость языка никак не мешает на этапе компиляции работать с его AST.
Это правда. Зато неинтерпретируемость мешает работать с АСД на этапе выполнения программы, да и на этапе компиляции добавляет сложностей: приходится вводить новый синтаксис для компайл-тайм вычислений.
Могут и быть. Т.е. в бинарник вполне можно напихать кроме скомпилированных инструкций процессора еще и AST от его исходника, и этот бинарник может в процессе своего выполнения частично себя перекомпилировать, и переписывать себе машинный код таким образом.
HotSpot VM этим постоянно занимается. В рантайме всякое говно профилирует и перекомпилирует. См. https://ru.wikipedia.org/wiki/Адаптивная_оптимизация
Вот именно, что VM. Это инструкции для виртуальной машины, а не какой-нибудь там бинарник. Плюс такие адаптивные оптимизации очень ограничены: в основном либо инлайнят вызовы функций, либо джитят.
> Рассмотрим гипотетическое банковское приложение, которое обрабатывает транзакции друг за другом. Эти транзакции могут быть списаниями, взносами и множеством других непонятных операций. Когда программа выполняется, фактические данные могут состоять из очистки десятков тысяч списаний без единой обработки взноса и без единой обработки списания с мошеннического счёта. Адаптивный оптимизатор будет компилировать в машинный код, оптимизируя его для общего случая. Если система затем начинает вместо этого обрабатывать десятки тысяч взносов, адаптивный оптимизатор перекомпилирует в машинный код, чтобы оптимизировать для новых общих условий. Эти оптимизации могут включать встраивание функций или перемещение кода обработки ошибок во вторичный кэш.
Таким образом такие оптимизации всегда будут в языках вроде «Jawa», а скомпилированные такими языками программы будут байткодом для виртуальной машины, которая будет по каким-то мутным эвристикам дополнительно компилировать кусочки байткода в машинный код.
Инструкции виртуальной машины вполне могут быть в бинарнике. Кроме того, можно уже предварительно скомпилированную в машинные коды хуйню в бинарнике хранить, вместе с жабовым байткодом, чтобы потом перекомпилировать, если условия изменились.
Зато я точно уверен, что прослойка в виде виртуальной машины скажется на перфомансе в худшую сторону.
Т.е. это вполне работает и юзается в местах, где критичен пирфоманс, но заранее какие-то параметры неизвестны (софтварная прыщеграфика, емнип).
Не всегда есть смысл использовать такую жирную хуйню, как LLVM IR. Если пилить инженерный калькулятор под контроллеры, и например там считается некоторая сложная хуйня, скажем численно интегрируется какое-то говно, то можно запилить какой-нибудь недокомпилятор, который в память набросает опкодов и выполнит их, и это будет быстрее интерпретации какой-то хуйни. А LLVM в контроллер со всеми своими говнооптимизациями тупо не влезет.
Не факт. В крестопарашных constexpr новый синтаксис не вводили. Но там не работают такие замечательные сишные функции, как memcpy(), memset(), malloc() - так что это неполноценная убогая херня, ведь я не могу переиспользовать свой код, в котором эти функции присутствуют.
Это и есть новый синтаксис, чтобы разделить компайл-тайм и обычные функции.
В крестах добавили ключевое слово, в «Nim» добавили много ключевых слов. От этого суть не сильно поменялся, но «Nim» мне кажется более выразительным.
В "Nim" нет гомоиконности, так что хуита это. Надо чтоб гомоиконность!
> This is due to the fact that D is not as “regular” a language as Lisp. Some of the people helming the evolution of D are working on changing this, and it is my hope that an improved D will emerge in the not-too-distant future.
Нет конечно. https://en.wikipedia.org/wiki/Homoiconicity#Implementation_methods - там вот перечислены некоторые языки
https://stackoverflow.com/questions/1238858/can-a-compiled-language-be-homoiconic
In the most literal form, C is homoiconic. You can get access to the representation of a function using &functionName and execute data using somePtrCastToFnPtr(SomeArgs). However this is at the machine code level and without some kind of library support you will find it very hard to work with. Some kind of embeddable compiler (I seem to remember that LLVM can do this) would make it more practical.
Сишка гомоиконная, получается?
Сомнительно. Функции вообще могут в другом адресном пространстве находиться, и это адресное пространство может быть даже недоступно для модификации.
The problem is that a lot of processors separate instruction and data areas, and actively prevent programs from modifying their own code. This kind of code used to be called "degenerate code", and considered a very Bad Thing.
Interpreters (and VMs) don't have that problem, as they can treat the whole program as data, with the only "code" being the interpreter.
Что ж, видимо, скоро тебе в контроллеры завезут VM, и тебе придётся пересесть на интерпретируемый язык типа йажаскрипта или пэйсона.
У меня на контроллерах нет задач, где надо самомодифицировать что-то в логике.
Итак, во второй строке у нас цикл по всем свойствам, объявленным в базовом типе?
Если подключить Reflection TS (или сделать что-нибудь работающее на основе p0707), то можно.
Если бы можно было такое делать в рантайме, то он был бы медленный.