LINUX.ORG.RU

\[палёный мёд\] фантазии на тему своего ЯП

 , , ,


0

4

Привет, котаны!

Я решился на отчаянный шаг — поэкспериментировать с компиляторами. После долгого сидения я понял что питон это не то — надо шагнуть дальше. Ну, хотя бы в с т.з. функционального программирования. Сразу скажу что концепции я пока не вижу и ответов на фундаментальные вопросы типа степень ленивости языка, всякие там монады, в каком виде делать ООП (и делать ли?) у меня нет. Но всё же забавно поиграться просто с синтаксисом.

Основные приоритеты: компактность, наглядность, удобное представление рутинных действий. Цели: высокоуровневое системное программирование. Т.е. целей писать на нём ядро нет, вопросы скорости пока не интересует. Скажем, хотелось бы ЯП чтобы можно было легко писать как скрипты аля-шелл, так и полноценные программы. Но внутренние детали я бы хотел обсудить позже, и так вопросов куча. Вот что родилось в моём больном воображении:

/* DATA TYPES */
//ints and floats, types are infered from the value
i = 1; f = 1.0
// list
l = [1,2,3]
//tuple (arguments of functions are passed in tuples)
t = 1, 2, 3
//tuple with named fields
tuple X: a, b, c
x = X a=1, b=2, c=3
// the same but with optional parens
x = X(a=1, b=2, c=3)
// access tuple attrs
print x.a, x.b, x.c
//hashes
{}  // empty hash
h = {b=>2,a=>1}
print h.keys // -> "pb, a]" because hashes preserve insert order

//regular expressions
pattern = /[A-z][a-z]{1-2}/


/* BASICS */
// define variable
x = 1

// define function "z" of two args
z x:int, y:int = 2*x + y

// function invocation
z 1, 2
// or
z x=1, y=2

// composition, equivalent of print(z(1,2))
print z 1, 2

// conditions:
if a > 2:
  pass
//if-else in one line
if x == 2: {x = 3} else: {x = 4}
//regexp
if x ~= //


switch x:
  x == 1: pass
  x < 10: print("x is really less than 10")
          continue  # go down
  x < 5 : print("x ")
  _     : print("what a strange X")


/* SUGAR */

# shell invocation
x = `ps ax | wc -l`


# equivalent of vm = VM(); ...; vm.stop()
vm1 = VM(), vm2 = VM():
  on cleanup:
    vm1.stop and vm2.stop():
  ...


/* HIGHER ORDER FUNCTIONS */
# a(b(c))
c | b | a
a . b . c

/* GROUPING */
// block may appear at any place where expression is acceptable.
// the return value is the last statement
// statements are separated by semicolon.
x = true
if x: {print "it turned out that x is true"; x=false}
else: {print "x is false, sad but true"; }


/* HELLO, WORLD */
main argv =
  print "hello, hell"
  print "my args:", argv

/* STRING SUBSTITUTION */
x = 666
print "x is equal to ${x+1}" // equivalent of { tmp = x+1; printf("x is equal to %d\n", tmp) }

/* EXCEPTIONS */
// catch exception and get its value in _err
fd = open "filename" || die "exception ${_err}"

try:
  fd = open "filename"
except NotFound:

fd = try {open "filename"} except NotFound: -1


/* LANGUAGE MODES */
//shell invocation in backticks
files = `ls -la /tmp`
`for f in ${files}; do scp $f remote:/tmp; done` \
  || die "scp failed with ${_err}"


/* COMMENTS */
// this is a comment
# and this is a comment
/* and this as well */
; have fun with many comment styles


/* SMALL THINGS */
for elem in some_list:
  ...
print elem  //will raise error because loop variables are not seen outside the loop by default

// for this reason file will be automaticaly closed once the control reach the end of the loop
for l in os.open("some_file"):
  ...

PS кодовое название — velosipedix. PPS case ymn, archimag, baverman, tailgunner, qnikst, mv и всех других кого забыл :)

PPPS похоже что инета у меня не будет до воскресенья...

★★★★★

Последнее исправление: CYB3R (всего исправлений: 2)

Основные приоритеты: компактность, наглядность, удобное представление рутинных действий.

Welcome to OpenEuphoria.

quickquest ★★★★★
()
Ответ на: комментарий от yyk

то нужны макросы или что-то подобное, следовательно, либо интерпретатор, либо jit

Ты тупой, да?

Какое отношение макросы имеют к интерпретации? Макросистему можно прикрутить к любому компилятору, даже к Си.

anonymous
()
Ответ на: комментарий от www_linux_org_ru

а по какому образцу/идее/... сделаны векторные операции?

Честно говоря, не помню. Вероятно, это попытка скретить идеи array languages и обычную статическую систему типов в стиле Джавы/Ады/крестов.

geekless ★★
()
Ответ на: комментарий от anonymous

Какое отношение макросы имеют к интерпретации? Макросистему можно прикрутить к любому компилятору, даже к Си.

С интерпретацией макросы делаются «в один щелчёк пальцев». Полноценная макросистема без гомоиконного синтаксиса - ешьте вы сами такие кактусы.

yyk ★★★★★
()

руби изобретено успешно

punya ★★
()
Ответ на: комментарий от yyk

ешьте вы сами такие кактусы

а в чем проблема?

ymn ★★★★★
()
Ответ на: комментарий от baverman

Бгг. Постоянный оверхед?

скажем так, OrderedDict востребован. Можно итерацию в порядке вставке сделать опциональной, но вот вместе со значением сохранить порядковый номер не помешает.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

цель

питон почти устраивает, но хочу для него другой синтаксис

Я хочу избавиться от родовых косяков питона. Мне идея его нравится, но он, по-моему, скоро достигнет дна своего развития как ЯП.

Как минимум две вещи хотелось бы решить - сделать всё выражением и больше функциональных фишек. Ну и статическую типизацию, не буду записывать это в недостатки питона.

В идеале ещё бы рантайм маленький сделать и скорости побольше, но это больше личные загоны, чем необходимость.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от geekless

Нечитабельно

Можешь привести кусок кода который не парсится?

не понятно, зачем это нужно.

just for fun же

Система типов какая?

Первое присвоение определяет тип переменной. Либо опциональная явная аннотация. Преобразование типов планируется явное.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от gh0stwizard

Спасибо, всё это уже видел. И даже частично сделал peg-парсер для разбора синтаксических конструкций предыдущей версии ЯП. И даже понял как работает pratt-парсер для разбора выражений с приоритетом оператора и левой/правой ассоциативностью.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin
/* HIGHER ORDER FUNCTIONS */
# a(b(c))
c | b | a
a . b . c

a(b(c)) - это похоже на цепочку вызовов (метод чейнинг в ооп или просто вложенные вызовы в императивщине), не очень подходит для HOF.

так ты планируешь его писать или это так?

cdshines ★★★★★
()
Ответ на: комментарий от anonymous

В корне неправильный совет!

Угу, с учетом того, что хороший ЯП прежде всего должен решать определенные задачи, которые другие ЯП почему-то (это надо четко описать и доказать еще) делают не очень хорошо.

Я просто навел на те источники, с которых можно запросто начать писать свой недо-ЯП. Просто для just for fun, а также самому почувствовать сколько проблем может возникнуть при составлении синтаксиса :) Но теоретикам и этого не нужно.

Начинать надо с заполнения вот этой формы: http://colinm.org/language_checklist.html

Неплохо, но не дает понимания того, что всетаки надо начинать с решения _своей_ задачи текущими ЯП, а потом уж браться за свой потому что _________. А тупо обосрать другого человека взявшегося за это можно кого-угодно, даже во времена создания питона, go и т.д. :)

gh0stwizard ★★★★★
()
Ответ на: комментарий от true_admin

Я может чего-то не так понял, поэтому сначала спрошу: функции обязательно чистые, или могут иметь size effects?

geekless ★★
()
Ответ на: комментарий от eugeno

В каких местах твой velosipedix лучше?

статическая типизация, pattern matching (тут не показано), встроенная поддержка регулярок и шелла, более котороткие некоторые конструкции, в частности по ловле эксепшенов, expression-oriented (можно присваивать в if, но результирующее выражение должно быть bool чтобы избежать ошибок типа i = 1 vs i == 1). Планируется пользовательские операторы с заданным приоритетом и ассоциативостью и, возможно, расширяемый синтаксис (щас прообраз парсера на питоне написан, поэтому с этим не должно быть проблем). Итд итп по мелочи. Это по синтаксису. А по рантайму у меня просто наполеоновские планы, но я пока делиться ими не хочу, надо всё обдумать.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Первое присвоение определяет тип переменной. Либо опциональная явная аннотация. Преобразование типов планируется явное.

Это не ответ. :}

То есть тут два варианта. Либо ты и сам понимаешь, что это не ответ. Либо не понимаешь, и тогда тебе рано думать о создании ЯП.

geekless ★★
()

питон-питончик...

x0r ★★★★★
()
Ответ на: комментарий от true_admin

сделать всё выражением

а в питоне без этого где-то возникают проблемы?

больше функциональных фишек

это про что? иммутабельные структуры данных?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от true_admin

статическая типизация

тут надо написать какая именно

более котороткие некоторые конструкции, в частности по ловле эксепшенов

пример

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от geekless

функции обязательно чистые, или могут иметь size effects?

это был мой следующий вопрос на форуме...

Одним из вариантов был такой: функция не может менять переданные ей аргументы (в том числе содержимое содержимого контейнеров), если только в её сигнатуре явно не прописано это. По дефолту все функции pure.

Второй вариант такой: функция может делать всё что хочет, но эти изменения не будут видны за её пределами.

Это что касается данных программы. По поводу IO: я пока не уверен что надо io-функции считать автоматически нечистыми и как-то их разделять/отделять. У меня нет опыта программирования по этой части.

Короче, я пока сам не разобрался.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от geekless

То есть тут два варианта.

статическая и динамическая? Статическая.

тебе рано думать о создании ЯП.

меня это не остановит :). Мне всю жизнь окружающие говорят что у меня ничего не получится. Например, на одном из ранних линуксфестов меня серьёзно убеждали что работы для unix-специалистов никогда не будет.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

пример

Ловля всех эксепшенов:

raise Exception || die «Whoops...»

специфичных

raise Exception || (on Exception1 do_smth | die «Default action»)

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Это на самом деле ключевой пункт, тут не получится так, что вот тут мы играем, там рыбу заворачивали:

Это что касается данных программы. По поводу IO: я пока не уверен что надо io-функции считать автоматически нечистыми и как-то их разделять/отделять. У меня нет опыта программирования по этой части.

Вот смотри.

x = y
x — это функция? Какой тип у выражения?

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от geekless

x — это функция?

переменная. Функции через ":" обявляются. Вот так x: y

Какой тип у выражения?

y должен быть объявлен выше чтобы к этому момент компилер знал тип. Хотя, всё равно парсинг итп будут многопроходным, поэтому можно отрезолвить тип даже если y объявлен ниже x. Это если в этом действительно есть необходимость.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

а какие бывают? strong и weak? тогда strong.

Не бывает «каких бывает». Бывает система. Сначала у тебя появляется идея, какие задачи должна решать система типов в твоём ЯП, потом формулируются свойства, которыми должна обладать система типов для этого, потом проектируется сама система.

А потом мы смотрим: «опа-опа, эта система типов по своим свойствам попадает в категорию статических». Это просто ярлык для каталогизации.

geekless ★★
()
Ответ на: комментарий от www_linux_org_ru

это про что?

операторы и функции высшего порядка. Вопросы иммутабельности я пока не созрел обсуждать. Как будет время подумаю и мы обсудим.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от geekless

какие задачи должна решать система типов в твоём ЯП

непротиворечивость типов — если собралось значит ошибок типов быть не может. Неявных преобразований не планируется. Я не очень понимаю что ещё ты хочешь услышать.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

переменная. Функции через ":" обявляются. Вот так x: y

Вот твой пример:

z x:int, y:int = 2*x + y
Функция объявлена через =

Поехали дальше:

a x
Если у тебя язык не pure, тебе придётся знать ответ на вопрос: в какой момент будет вызвана x. И сколько раз.

y должен быть объявлен выше чтобы к этому момент компилер знал тип. Хотя, всё равно парсинг итп будут многопроходным, поэтому можно отрезолвить тип даже если y объявлен ниже x. Это если в этом действительно есть необходимость.

Если тебе нужно знать тип y, чтобы сформулировать выражение типа для x, то это «плохие новости», ну. :} Даю подсказку: typeof(x) == typeof(y). Наверное. А может и нет, я ж не знаю твоего ЯП.

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от cdshines

У тебя указано main, в котором последний принт. Каков тип main?

Получается что void :). Тут компилер должен возбухать т.к. main должен вернуть int32.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от geekless

Если тебе нужно знать тип y, чтобы сформулировать выражение типа для x, то это «плохие новости»

А почему нет? Это же всё упрощает.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от geekless

Функция объявлена через =

Опечатка.

Но я согласен, внутри модели есть противоречия. Например, как передавать функции внутрь других функций если вызов идёт по имени без всяких (). Собственно, для этого и пишу, вы мне задаёте вопросы, а сижу и думаю что делать дальше.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от ymn

Types and Programming Languages

Это точно так необходимо? Даже для простого ЯП?

Я вот кучу времени убил на изучение различных парсеров, как они работают, какие выражения они не могут распарсить итп. И, знаешь, три-четыре статьи дали ответы на мои вопросы, а остальные 20-30 просто потратили моё время. Я к тому что для решения задачи не всегда нужно знать абсолютно весь state of the art, достаточно знать что эффективно работает.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Опечатка.

То есть надо:

z x:int, y:int : 2*x + y
?

Чисто синтаксически, это ужасно.

А почему нет? Это же всё упрощает.

Я говорю о том, что ты, кажется, не понимаешь, что такое «тип» и «выражение типа».

Но я согласен, внутри модели есть противоречия. Например, как передавать функции внутрь других функций если вызов идёт по имени без всяких (). Собственно, для этого и пишу, вы мне задаёте вопросы, а сижу и думаю что делать дальше.

Если язык pure, это не противоречие, а фича. В чистом языке нет ни переменных, ни констант. Есть только функции. a = 1 — объявлена функция a, не принимающая ни одного аргумента. avg a b = (a + b) / 2 — объявлена функция avg с двумя аргументами. avg1 = avg a — объявлена функция avg1, принимающая один аргумент.

Если язык с сайд-эффектами, то в нём в явном виде разделены получение/передача/хранения значения и «применение» значения к аргументам (вызов функции, то бишь). И тут на самом деле вопрос чисто синтаксический, как эти два понятия различать. Как удобно, так и различай.

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от geekless

Собственно, немного утрируя, в языке и нет ничего, кроме системы типов. Всё остальное — синтаксический сахар и библиотеки с кодом.

geekless ★★
()

Бозе мой, какой ужос. Я насчитал 4 разных синтаксиса в твоем примере: питоний, хаскельный, шелловый и еще какой-то неизвестный.

Сразу скажу что концепции я пока не вижу

Боюсь, без концепции у тебя даже синтаксиса не получится. И да, возьми хоть что-нибудь за прототип. То, что знаешь.

Я вот кучу времени убил на изучение различных парсеров, как они работают

ИМХО, для разработчика языка это напрасная трата времени. Всё равно берется готовый генератор парсеров или вручную пишется recursive descent.

А вот TAPL или подобное - реально нужная вещь.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

А ты чертовски прав. Я вот этот момент не проработал. Возможно, если бы я начал с примеров кода где питон буксует было бы гораздо лучше. В след. версии исправлюсь, теперь уже поздно.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Я насчитал 4 разных синтаксиса в твоем примере: питоний, хаскельный, шелловый и еще какой-то неизвестный.

так в этом и была задумка: взять самое лучшее и удобное из них. Похоже что идея с треском провалилась.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Ну что ж, по крайней мере я выяснил всё это до того как что-то начал писать.

true_admin ★★★★★
() автор топика

Опиши что в нем конкретно уникального и что лучше чем в других. Никого не интересует как ты там hash map декларирируешь

vertexua ★★★★★
()

Двадцать первый век на дворе, а круглые технари всё вымучивают языки, которые выглядят как шизофазия пьяного Терминатора.

Слабо создать язык программирования, не отличающийся от какого-нибудь естественного? Английского, например. Или боитесь, что вам на хлеб нечем зарабатывать будет?

fragmentor
()
Ответ на: комментарий от fragmentor

не отличающийся от какого-нибудь естественного? Английского, например

Какой забавный клоун, «отличающийся умом и сообразительностью». Ну возьми shakespeare и уписывайся..

anonymous
()
Ответ на: комментарий от true_admin

бывают удачные гибриды функциональщины и императивщины? Или это фантастика?

Ruby. :-D

Если серьёзно, то ответ зависит от того, что считать ФП и ИП. Если считать по тем фичам, которые ключевые, которые определяют всю глубинную семантику языка, то нет. Потому что ФП и ИП — это два подхода к описанию алгоритов, которые появляются, когда мы по-разному отвечаем для себя на вопросы, что вообще такое алгоритмы, и какие их свойства нам важны.

Если же рассматривать язык прежде всего как интерфейс (или интерфейс как язык :-D), то всё в конечном счёте завист от того, «насколько это удобно». Противоречия в системе типов конечно полезут, если мы попытаемся последовательно двигаться в сторону ФП, оставаясь при этом императивным языком по сути, но если не углубляться, и делать вид, что «у нас такой удобный для людей язык, который почти настоящий функциональный», то жить можно.

Но из статических я как-то затрудняюсь назвать. Ибо почти не пишу на них. (Си считать за высокоуровневый язык затруднительно.) А по одному только запаху из кухни об умениях повара судить трудно.

Хотя у меня давно есть на задворках сознания мысль запилить собственный велосипедный статически-типизированный язык с мощной системой вывода типов, который при этом не будет пародией на C++. Вот что-то типа такого, как это чувак пилит: https://github.com/nddrylliog/the-ooc-language (Сайт проекта что-то не открывается.)

geekless ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.