FSML In His Grace
FSML - это постфиксный конкатенативный гомоиконный язык программирования, призванный дать мне и всем желающим привычную, комфортную постфиксную среду программирования и быть конкурентоспособным в современных реалиях, эффективным во всех отношениях.
Разработка находится в зачаточном состоянии, поэтому большая часть документа будет посвящена концепции языка и планам его развития, а не тому, что уже сделано. Хотя для затравки я сначала покажу несколько небольших примеров того, что уже сделано. Затем опишу концепцию. И в конце приведу технические подробности. Надеюсь, что читатель в общих чертах знаком с постфиксными языками прогаммирования, как Форт, Фактор или 8th.
В первую очередь заметьте, что объекты, дублируемые с помощью классических Форт-слов как dup, over, и т.д. доступны по ссылке, а не по значению. В частности это означает следующее.
1 dup
[2] 1 -> 1
25 +
[2] 1 + 25 -> 1 + 25
Упс! Это не то, чего бы вы ожидали от Форта или Фактора. В этих языках результат был бы таким:
1 dup
\ 1 -> 1
25 +
\ 26 -> 1
Это объясняется тем, что в FSML продублировав элемент стека используя DUP мы на самом деле продублировали ссылку на объект, так как абстрактный стек в действительности может содержать только ссылки. Таким образом оба получившихся элемента стека - это ссылки на один объект. И прибавив к нему 25, мы сделали этот объект выражением 25 + 1. Поэтому два верхних элемента стека ссылаются на это выражение.
Нужен "ind" после "dup", чтобы разделить их. "ind" означает независимый или индивидуальный, на ваш выбор. Он создаёт новый объект и переставляет ссылку на него. Этот новый объект всё ещё ссылается на то же подвыражение, что и раньше. Но все последующие операции над ним будут создавать другой семантический граф. С этого момента они будут иметь разную историю операций над ними, запечатлённую в вершинах абстрактных семантических графов (asg). Но то, что было сделано до "ind" останется общей частью истории операций над элементом.
1 dup ind
[2] 1 -> 1
25 +
[2] 1 + 25 -> 1
Существует также операция "dc", что означает deep copy. dc производит глубокое копирование asg, соответствующего элементу стека. С этого момента появляется полностью новый граф, который не имеет общих вершин с исходным. Новый граф не является точной копией исходного. Например вершины графа могут содержать uid, которые по определению не могут быть такими же, как в прототипе.
.js
:
12 34 + 56 78 -
[2] 56 - 78 -> 12 + 34
.js
\ var subex_2 = 12 + 34;
\ var subex_3 = 56 - 78;
.eval
:
as df + 56 78 -
[2] 56 - 78 -> "as" + "df"
.eval
\ evaluated stack: [ -22, asdf ]
123 some_name !
some_name @ 456 +
.eval dp
[ 579 ]
ol
:
+ * ol
[1] (var_2, var_3, var_4) => var_4 * (var_3 + var_2);
mul
с !
:
* ol mul ! .js
\ var mul = (var_0, var_1) => var_1 * var_0;
if
, 1range
и 1fold
:
12 dup [ 1 1range mul @ 1fold ] [ 0 ] if .eval
* ol mul !
[479001600]
if
и while
:
12 dup [ 1 [ over * over 1 - ] while swap dp ] [ 0 ] if .eval
[479001600]
'Кладём на стек строку с пробелами и сразу же её сбрасываем при помощи dp' dp
'dp - это короткий псевдоним для классического drop' dp
'Без отступа между левой кавычкой и началом строки, здесь это не нужно' dp
"Или с двойными кавычками" dp
Или_вообще_без_кавычек_если_строка_не_содержит_пробелов dp
'\ Полноценные комментарии ещё не реализованы, поэтому пока это и для комментариев, хотя начать строку можно с обратного слэша Форт-комментария, чтобы было понятно, но всё же это только строка' dp
list 12 push 34 push
.js
var subex_2 = [];
var subex_1 = (subex_2 .push (12), subex_2);
var subex_0 = (subex_1 .push (34), subex_1);