Делаю свой домашний проект - виртуальную машину наподобие jvm. Есть текстовый файл с опкодами по типу: store 200 0 i //кладет в ячейку памяти 0 значение 200 и помечает ячейку как integer store string 1 s //кладет в ячейку памяти 1 значение string и помечает ячейку как string store a 2 c //кладет в ячейку памяти 2 значение c и помечает ячейку как char store 300 3 i //кладет в ячейку памяти 3 значение 300 и помечает ячейку как integer load 0 //загружает из ячейки памяти 0 значение в стек, тип стека задается типом первого загружаемого значение, в данном случае int load 3 //загружает из ячейки памяти 3 значение в стек add //складывает значения в стеке store 4 //результат который остался от сложения берет из стека и кладет в ячейку 4 Code store 200 0 i //кладет в ячейку памяти 0 значение 200 и помечает ячейку как integer store string 1 s //кладет в ячейку памяти 1 значение string и помечает ячейку как string store a 2 c //кладет в ячейку памяти 2 значение c и помечает ячейку как char store 300 3 i //кладет в ячейку памяти 3 значение 300 и помечает ячейку как integer load 0 //загружает из ячейки памяти 0 значение в стек, тип стека задается типом первого загружаемого значение, в данном случае int load 3 //загружает из ячейки памяти 3 значение в стек add //складывает значения в стеке store 4 //результат который остался от сложения берет из стека и кладет в ячейку 4 И я столкнулся с проблемой как хранить эти ячейки памяти. Если создавать ячейки через дженерики < T >, то такие ячейки будут разными и хранить их в одном массиве не получится. Если бы так работало, то можно было бы получать доступ к ячейке просто по индексу и вызывать в ней метод get который возвращал тот тип данных который хранит ячейка. Потом я подумал хранить ячейки в массиве object, но это плохая идея так как все равно придется приводить к типу ячейки, приведение типов не безопасно. Да и конвертация в object и обратно занимает время просто так, неэффективно. Далее я подумал сделать ячейку универсальной и дать ей поля всех нужных типов данных: int float char string bool, но тогда получается когда в ячейку помещается значение оно хранится в одном из 5 полей, остальные 4 поля пустые и неинициализированные, что не есть хорошо. Еще была идея создать 5 массивов, каждый для своего типа ячеек, например массив MemArrInt[] хранит ячейки MemCellInt которые имеют поле int для хранения данных, но мне эта идея показалась неправильной и костыльной и что будто есть нормальный путь сделать задуманное. Если тут есть хорошо разбирающиеся в C# и в целом архитектуре языков программирования, подскажите пожалуйста идею как это все можно было бы реализовать по вашему. Или если вы знаете источники где это хорошо описано прошу поделиться. Заранее спасибо. Если есть какие либо идеи или предложения и вам удобнее показать/рассказать это в тг, то пожалуйста, буду ждать вас там.
Host1, Всё зависит на каком уровне абстракции ты хочешь реализовать свлю виртуалку - если на уровне байтов, то только так - ты всегда оперируешь байтами, если же ты хочешь реализовывать на уровне объектов то надо забыть про байты и всё (включая память) делать по типу класса MemoryCell который мы обсуждали раньше.
Host1, удачи. меня еще зацепила эта фраза Как бы если делать "по-настоящему" то переносить из байтов в нужный тип - это оксюморон - эти байты это уже нужный тип, и операции надо проводить прямо над этими байтами, но боюсь что без кода мне будет трудно объяснить тебе разницу. Условно говоря, ты не должен пользоваться соответсвующими типами виртуальной машины .NET для того чтобы производить действия над объектами этих типов, а должен писать свои методы которые совершают эти действия над байтами. Но повторюсь - всё это сильно зависит от твоей цели - хочешь ли ты реализовать рабочую машину для своего языка (и акцент при этом на языке, то есть не важно как работает машина, но главное что она правильно отрабатывет все команды языка) или ты хочешь реализовать свою виртуальную машину (а язык вторичен и просто нужен чтобы показать что идея заложенная в виртуальную машину работает и ее можно расширить вместе с языком)