- PVSM.RU - https://www.pvsm.ru -
Дорогой %username%, если ты решишь сделать свой ЯП(язык программирования), с преферансом и балеринами, или понять некоторые основы работы препроцессора, компилятора и выполнения программы, тебе сюда!
Если уж задаться целью сделать ЯП, то необходимо первоначально выбрать, парадигму. Подробнее о парадигмах [1].
Если читатель собирается проектировать современный язык, то на сегодняшний день, наиболее распространенной будет обьектрно-ориентированая парадигма [2].
Моя жизненная ситуация сложилась так, что я программировал на С++ и Objective-C, и когда я погуглил тесты производительности Objective-C и чистого С, то нашел только топик на StackOverflow [3]. Я понял, что что-то в этом мире пора менять и по этому нужно написать свой обьектно-ориентированный язык.
Впринципе, эту статью можно было бы разбить на несколько более мелких статей, но я постараюсь уместить все в одну.
Какие же требования можно привести к обьектно-ориентированому ЯП? Ответ знаю все — это три кита (+-четвертый).
Также я выбрал пару важных штук для себя:
По своей неопытности думал, что можно взять пару препроцессорных макросов, которые сделали бы новый синтаксис С и сишные структуры — и вот готов новенький ЯП. Каков был мой шок, когда я вспомнил про полиморфизм (Наследование и Инкапсуляцию еще, с горем-пополам, можно реализовать на сишных структурах, а вот для полиморфизма нужно что-то еще). Так я стал разделять два ключевых времени для написанной на высокоуровневом языке программы. Это время компиляции( и процессинга, т.е. выполнения препроцессором [9] своих команд) и время выполнения(runtime).
Что нам может дать С во время компиляции
Для полиморфизма:
Дополнительные вкусности для себя:
Таким образом, я пришел к выводу, что обьектно-ориентированному языку нужен runtime, в котором он будет определять что это за обьект, и какую функцию вызывать. И у класса должны хранится указатели на методы.
Почти все современные языки программирования дополнительно к данным обьекта, хранят еще огромную тучу(по сравнению с самим обьектом) метаинформации(информацию о способах и методах обработки обьекта или о том, где найти эту информацию). Что можно хранить в качестве метаинформации:
Все это можно хранить вместе с обьектом. «О боже, да это же сколько дублировать-то прийдется: к простому классу прийдется добавлять еще дополнительно N-килобайт метаинфы», да, но при определении метода(свой, родительский), это будет очень быстро работать, т.к. мы просто смотрим на элемент обьекта.
Я решил, что это непозволительная роскошь, и поэтому с каждым обьектом я буду хранить идентификатор его класса, которому будет присваиваться уникальный номер. Это будет 64(можно взять и 16-разрядное, я, например, не видел программу, у которой будет больше 65536 классов) разрядное число. Согласно этому числу, в специльных таблицах и можно будет найти метаинформацию об обьекте.
Таблицу можно разбить на несколько подклассов — она будет наследником класса словаря(map, NSDictionary), который будет наследником динамического массива(vector, NSArray) и будет содержать обьекты пары обьект1 — обьект2, или ключ — значение(идентификатор — имя). Так, как компилятор представляет возможность представления куска кода в виде сишной строки, то и имена обьектов и будут сишными строками. При регистрации имени класса, будет создаваться пара из имени и идентификатора, и добавляться в массив.
Все то что я придумал как временное решение.
Из интересных моментов:
#define _TOSTRING(x) #x
#define TOSTRING(x) _TOSTRING(x) // gets c-string from define or some code
#define _splitUp(one, two) one##two
#define splitUp(one, two) _splitUp(one, two) // splits up two words: splitUp(Hello,World) -> HelloWorld
splitUp сделал для «пространств имен», например когда я обьявляю метод
#define $method(returnValue, methodName, className) returnValue splitUp(methodName, className)(className *object
$method(uint64_t , getNumberOfClasses, RClassTable));
То препроцессором генерируеться сишная функция
uint64_t getNumberOfClassesRClassTable(RClassTable *object);
Как вы уже поняли — object это аналог this в C++ и self в Obj-C.
А вот так выглядид реализация этого метода:
$method(uint64_t , getNumberOfClasses, RClassTable)){
return $master(object, RDynamicArray)->count;
}
И не надо писать никаких
:: и @implimentation @end
Вызов метода:
#define m(methodName, className) splitUp(methodName,className) // some method function name
#define $(object, methodName) methodName(object
$(classTable, m(registerClassWithName, RClassTable)),"Luke");
Язык я назвал Ray — Луч.
Синтаксис еще сырой и не обьектно-ориентированный, потому что рантайм не готов(будет готов — прийдется немного поменять синтаксис),
и все мои попытки open-source и absolute free, никаких лицензий, подписей и т.д.
Ознакомится с проектом на GitHub можно тут [11]
Hello world:
#include "RayFoundation.h"
#include <stdio.h>
$class(HelloWorlder)
char *word;
$endOfClass(HelloWorlder)
$constructor(HelloWorlder)){
HelloWorlder object2;
object2.word = "Hello world";
return &object2;
}
$printer(HelloWorlder){
printf(object->word,"n");
}
int main(int argc, const char *argv[]) {
HelloWorlder helloWorlder = *$(NULL, c(HelloWorlder)) );
$( &helloWorlder, p(HelloWorlder)) );
return 0;
}
Синтаксис так-себе, но к нему быстро привыкаешь и показывает больше детерминизма, какого класса метод ты вызываешь, и что это за метод(m — method, sm — static method, p — printer, d — destructor, c — constructor). Вот такой вот вышла моя попытка создать ЯП. Буду работать над ним дальше. Больше примеров можно увидеть на GitHub. Единственное что, там проект под Mac (AppCode, Xcode). Можете просто скопировать исходники себе и развлекатся как хотите. Хорошего дня. Буду очень благодарен за feedback если попробуете что-то написать.
Автор: Kojiba
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/68046
Ссылки в тексте:
[1] парадигмах: https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B0%D0%B4%D0%B8%D0%B3%D0%BC%D0%B0_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F
[2] обьектрно-ориентированая парадигма: https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
[3] топик на StackOverflow: http://stackoverflow.com/questions/9668709/objective-c-vs-c-speed
[4] Инкапсуляция: https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D0%BA%D0%B0%D0%BF%D1%81%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
[5] Наследование: https://ru.wikipedia.org/wiki/%D0%9D%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
[6] Полиморфизм: https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%BB%D0%B8%D0%BC%D0%BE%D1%80%D1%84%D0%B8%D0%B7%D0%BC_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
[7] Абстракция: https://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%86%D0%B8%D1%8F_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85
[8] стеком: https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BA
[9] препроцессором: https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80
[10] github.com/kojiba/RayLanguage/blob/master/RayLanguage/RayFoundation.h: https://github.com/kojiba/RayLanguage/blob/master/RayLanguage/RayFoundation.h
[11] тут: https://github.com/kojiba/RayLanguage
[12] Источник: http://habrahabr.ru/post/234157/
Нажмите здесь для печати.