Хочу сделать, кхм, скриптовый язык, пригодный для использования. Интерпретатор писать я пока не начинал, пока выкладываю только мысли о предположительной структуре, и примеры кода, который я вижу.
Синтаксис:
1) Пробел - разделитель. Некоторые другие символы вроде перевода строки и табуляции - аналогично.
2) Строка текста - подобно паскалю ('abc'#13#10 + 'def')
3) Числа (12345.44 или $3A6D)
4) Круглые скобки и запятая - для передачи аргументов функции:
do(123,456,'abcdef')
Либо для расстановки приоритетов
5) Фигурные скобки для отделения блока инструкций
{
do(1,2,'a')
do(3,4,'b')
}
6) Точка для обращения к полям данных или элементам массива:
do.first(123,456,'def')
7) Комментарии: начинаются на // и завершаются переводом строки
8) @ - служебный символ для объявления функций и разметки модуля
9) Остальные символы рассматриваются как части идентификаторов
Структура модуля (проход осуществляется один раз при загрузке):
@do //объявление функции do - код сохраняется для последующего использования
{
......
}
@ //объявление функции без названия - этот код выполняется сразу при проходе
{
//функция регистрации константы
const('const1_name',const_type,const_value)
const('abc',int,333)
//функция регистрации типа
type('my_class','field1',type,value,'field2',type,value, ... ,'fieldN',type,value)
//функция регистрации аргументов для загруженной ранее функции
args('do',0,int,type1,type2, ... ,typeN)
//0 означает макс. количество необязательных аргументов
//следом идет тип необязательных аргументов
//вариант не окончательный
//тип и результат функции задается внутри функции
......
}
@do2 //еще одна функция
{
...
}
@ //еще код, выполняемый сразу
{
...
}
Типы данных:
В интерпретаторе все хранится в Int64.
Возможны синонимы.
none - тип данных отсутствует (любой).
type - тип для типа данных
int - целое число 64bit signed
float - вещественное число типа Double (8 байт)
bool - 1 бит (истина или ложь)
str - динамическая строка текста
func - функция
array - универсальный массив переменных (каждая имеет свое имя, тип и значение)
Здесь, кажется, не все.
Идентификаторы и выражения:
Для них не делается различия, функция это или переменная. При считывании выражения, если идентификатор не является функцией или переменной, то он рассматривается как оператор. При считывании выражения, либо ожидается какой-то конкретный тип аргументов, либо допускается произвольный, но тогда можно указать только переменную или результат функции. Если ожидается конкретный тип аргументов, то можно использовать операторы для этого типа. Предполагается возможность перегружать и добавлять неограниченное количество новых операторов для имеющихся и новых типов.
Открытие скобки означает ожидание аргумента такого же типа. Если аргумент другого типа передан насильно (как результат функции или значение переменной), будет либо ошибка, либо инородный аргумент будет интерпретирован соответствующим образом. Например, целое число в строку будет преобразовано.
Операторы:
Функции с иным способом передачи аргументов. Аргументов всегда 2, оператор располагается между ними.
Например: arg1 operator arg2
Унарных не будет - функциональный вызов их даже несколько удобнее. И, судя по всему, будет обязательным окаймление операторов пробелами или прочими разделителями. Если перед оператором ничего не следует, то туда подставляется аргумент по-умолчанию, например 0. Можно использовать только те операторы, которые соответствуют ожидаемому типу аргумента.
Не знаю как быть с приоритетами умножения и подобных.
Пример:
Вычисление факториала
@fac
{
result(fac(argument - 1))
}
@fac_loop
{
local_variable(int,'i',1)
set(i,1) //как один из предполагаемых вариантов присвоения
i(1) //еще вариант присвоения, функциональный (если получится)
result(i)
loop('i',1,argument,
{ //предполагаемый вариант записи циклов
result(get_result * i)
})
}
|