Comments 31
А как это всё запускать, собирать? Есть пример, инструкция?

Да, именно так, ранняя стадия разработки.
Проект пишу ~4 месяца с чистого листа. За этот срок проделан значительный объем работ. Планирую основные работы по компилятору закончить в конце сентября. После чего накидаю минимум для RTOS(AVR) и высокоуровневый runtime. Даже в конце года проект будет максимум на стадии MVP(пока с поддержкой только AVR). Это слишком большой объем работ для одного человека. Я это осознаю, буду двигаться постепенно.
:) Немного торопитесь, проект на ранней стадии разработки. Пока не закончен кодогенератор(он оказался немного сложнее, чем я ожидал, тем не менее я надеюсь уложиться в срок и к концу сентября закончить кодогенерацию и навести порядок в семантике.
К примеру сейчас реализую кодогенерацию(для AVR) логических операций и операций сравнения для AVR в конструкции условных операторов
Я обязательно займусь документацией, примерами и тестами производительности, но скорее всего к концу года.
Ждем расширения поддерживаемых архитектур на MSP430
Новые AVR тоже будут?
У всего семейсва AVR почти одинаковый набор интрукций, по периферии тоже различия не особо критические. Так что не сложно будет накидать поддержку новых после реализации, скажем Atmega328. Главный вопрос когда. Возможно это даже сделает сообщество, если проект зайдет. Пока что-либо планирвоать рано.
Статья/карма/подписка/Github: +/+/+/+.
Плюсы: + амбициозный проект; + это подлинное программирование.
Минусы: - маленькая аудитория (но в этом минусе плюс, что она хотя бы есть один пользователь проекта - сам автор); - нужно тянуть java, а это платформа с весьма "специфичным" "характером".
Автору — респект.
Вопрос — в чем преимущества применения восьмибитных архитектур при дешевизне 32 битных?
Я могу ошибаться в деталях, но в общем 8 бит мк, по моему личному мнению, имеют следующие преимущества:
дешевле, в больших партиях эта разница существенна.
меньше размерами
потребляют меньше тока
более устойчивы к ESD
Предиктивны (можно прогнозировать количество потраченных тактов/времени)
Менее сложные (меньше периферии, легче реализация функционала - например инициализация периферии или тактирования)
5 вольтовых входы выходы.
Больший ток входов выходов
Иногда это критично
Насчет "дешевле" могу не согласиться, 32-битки уже дешевле 8-биток, в особенности, AVR. AVR'в сейчас даже дороже.
А насчет надёжности да, надёжнее, за счет 5В и сильных портов, до 20 мА с пина
Стабильно есть в наличии и совместимость pin-to-pin даже переферии в пределах серии. Например в STM32 во времена кризиса чипов это было проблемой.
Господи, RTTI на 8-битках... где SRAM может доходить до нескольких десятков байт...
Очевидно, что высокоуровневый ООП язык на устройстве с десятками байт невозможен. Однако в проекте будет режим функций(без ООП). Проект также может быть полезен для реализации ASM программы. Так как включает в себя ассемблер-сборщик и наработанные библиотеки(в том числе и RTOS). Подключение кода будет только по необходимости.
Также прошу обратить внимание, что в моем решении минимальное потребление памяти для RTTI
*проект находится на ранней стадии разработки.
Не очень понятны две вещи:
Зачем проверка типов во время исполнения кода?
Зачем полиморфизм также во время исполнения кода?
Обычно такие вещи в runtime присутствуют либо в языках с виртуальной машиной и интерпретатором, либо:
информация о типах удаляется, так как код прошёл все проверки;
обобщённый код заменяется на специализированные варианты во время компиляции.
import Animal {
void makeSound();
}
class Dog implements Animal {
void makeSound() {...}
void toWag() {...}
}
class Cat implements Animal {
void makeSound() {...}
}
Animal myPet = getRandomAnimal(); // Может вернуть и Dog, и Cat
myPet.makeSound(); // Какая реализация метода должна быть вызвана?
if(myPet is Dog as dog) {
dog.toWag();
}
Проверка типов во время выполнения нужна для работы с полиморфными объектами, конкретный тип которых неизвестен на этапе компиляции и определяется динамически (по данным с датчиков, от пользователя, из сети и т.д.).
Runtime-полиморфизм нужен для единообразной работы с объектами через их общий интерфейс, без необходимости знать их конкретный тип.
Всё ещё не понятно: у вас статическая типизация? Значит все типы переменных известны заранее. А если что-то придёт из-вне неизвестное, то всё что вы можете сделать -- проигнорировать или упасть.
Пример с кошечками и собачками сомнительный: какой тип у getRandomAnimal()? Animal? Тогда будет вызываться Animal.makeSound(). Так?
Это не чисто статическая система. У интерфейса Animal нет реализации метода makeSound(). Конкретный метод(класса Dog или Cat) выбирается в runtime.
Это не интерпретация, а компиляция с сохранением метаинформации для динамической диспетчеризации.
Если я правильно понял, то это всё напоминает C++ с его абстрактными классами и виртуальными методами.
Я ориентируюсь на Java, но более упрощенную(без наследования классов, но с интерфейсами)
Мне, собственно, так же не хватает интерфейсов и их реализации в языках для встраиваемых систем. А название class сбивает с толку и направляет мышление в сторону ООП с классами...
Да, я использую синтаксис, похожий на Java, но с ключевым отличием: в моём языке нет наследования классов (нет extends для классов, кроме extends для интерфейсов). Наследование классов - слишком избыточно для 8 бит.
Поэтому слово class здесь означает ровно то же, что и final class в Java:
Это конечный (final) тип данных, который нельзя наследовать.
Это реализация состояния (поля) и поведения (методов).
Это единственный способ реализовать интерфейс (implements).
Вся полиморфная работа, ведётся только через интерфейсы. Класс же — это всего лишь «фабрика» для создания объектов, которые могут реализовывать эти интерфейсы.
Таким образом, это не «полноценное ООП с наследованием», а скорее «ООП в стиле композиции», где интерфейсы определяют контракты, а классы — их конкретные реализации. Название class я использую для привычности и краткости, понимая его именно в этом, более узком смысле.
И главное. Я практик, а Вы меня затягиваете на поле спора в теорию. Посмотрите на приведенный в статье код, он буквально объясняет как это работает и зачем это нужно.
i8051 добавить - т.к. на него тыщи кода.....
А ещё i4004, i8086, i8088? :)
зря смеётесь... для 8051 огромная кодовая база и вроде как ядра открыты? (не очень в теме)
к примеру - всеми любимые переходники usb->/uart/i2c/spi/gpio , там управляющий мк - оно
Да никто же не мешает! Компилятор имеет четкое разделение на фронтенд и бэкенд. Бэкенд — это просто отдельная библиотека на Java, которая реализует логику генерации кода для конкретного железа через абстрактный класс.
Основная работа по добавлению нового чипа — это создание новой библиотеки по образцу. Это не требует переписывания компилятора. В редких случаях — мелкие доработки в общей common-библиотеке.
К тому же, всегда можно отодвинуть глубокую оптимизацию итогового кода на потом. На первом этапе главное — работающая функциональность, что значительно упрощает начальную разработку под новую платформу.
Я очень хочу сделать поддержку Z80, но потом. Сначала основные семейства 8 бит микроконтроллеров.
Наработанный низкоуровневый код — платформозависим, и его сложно использовать повторно. В этом и есть суть моего решения: весь этот низкоуровень (драйверы, HAL) пишется один раз под каждую платформу.
А вот всё, что выше — прикладная логика, алгоритмы, работа с данными, в том числе и железо(например LCD экраны, SD карта и прочее) — будет писаться на нашем мультиплатформенном языке. Всё, что не требует максимальной производительности и прямого доступа к «железу», будет переносимым между разными МК без изменений.
Оффтоп. Почему под atmega для описания режима работы переферии не используется Device Tree? Идеальный был бы подход, нет?
vm5277, пример компиляции для AVR