Pull to refresh

Comments 201

Если честно, то на первый взгляд Паскаль и получился, дополненный, правда, полиморфизмом, сборщиком мусора и посыпанный синтаксическим сахаром. Может, правда, Вы так и задумывали, но тогда задача сформулирована не очень убедительно.
Мне кажется, что язык похож на Pascal очень отдаленно.
оператор break позволяет выйти из процедуры/функции (если он стоит вне циклов)
А что при этом вернет функция?

Ничего. Но можно в стек закинуть что-нибудь если уж нужно сильно. Просто: push

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

В языке, претендующем на звание простого, никаких undefined behaviour быть не должно.

Тут их и нет. Если палки в колеса себе не пихать)

break, в зависимости от контекста, либо выход из цикла, либо из функции, это заготовка для граблей.

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

Ну да, немного интриги не повредит ;)

Единственный язык со специальным оператором для неопределнного поведения))

Что есть, то есть :)

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


Если ожидается значение от функции, а в функции оно в стек не ложится, то да. Либо значение с вершины стека, либо access violation.

А чем вы руководствовались, когда давали оператору break такой функционал? Ни в одном известном мне языке break такого не делает.
Это Вы мало самодельных языков знаете. В моём тоже делает.

Если использовать exit внутри циклов, то это черевато мусором в стеке.

У вас еще и exit есть, помимо return и break?
Нет, но могу добавить :)
Лучше поясните, о чем был предыдущий комментарий :)
Добавил в язык оператор exit для выхода из процедур или функций.
Теперь break позволяет выйти только из циклов, case и try/catch блоков.
Так, а exit возвращает значение или нет? И чем он от return'a отличается?
Отличается тем, что ничего не возвращает.
Погодите, то есть у вас был break из функций, который ничего не возвращал, а теперь у вас есть exit из функций, который ничего не возвращает? :D

И точно так же можно словить мусорное значение со стека? Чем это лучше тогда?
Зачем вообще из функций возвращаться, не возвращая значение?
Зачем ожидать из функции значение, которое не собираетесь в функции возвращать?
Если в вашем языке некий бессмысленный код является валидным, и количество пользователей языка больше нуля, значит рано или поздно кто-то такой код обязательно напишет.
В этом же смысла нету. Тем более, стек открыт и доступен для работы с ним.

Получить значение с вершины стека можно и вот так:
peek a
А вот и ассемблером повеяло… ;)
Можно даже из процедуры вернуть значение, если сильно нужно.

Пример:
proc test():
  push 123
end

...

x ?= test()
А как вызывающий должен догадаться, что функция не возвращает значения, если это функция, а не процедура (раз уж у вас есть разделение на функции и процедуры)?

К тому же, внутри функции может быть ветвление и по одной ветке значение возвращается, а по другой — нет.

Извините, но по-моему вы как будто специально footgun в язык вносите такими фишками :)
Только у нас самые лучшие револьверы на Диком западе? :-)

У вас Форт какой-то получается.

Какую задачу решает ваш язык программирования лучше чем любой другой?

Я думаю, задачу изучения компиляторов и VM RoPi0n. Ведь если бы цель была в создании «языка решения X задач», то выбран был бы какой нибудь LLVM, а лексинг/парсинг отдан сторонней либе. Ведь это затратные по времени пункты, которые не релевантны цели. А автор решил сам всё писать.

Это пожалуй самый верный ответ который только можно дать на этот вопрос. Как много можно найти мануалов по построению современных ЯП на русском языке? В рунете не особо много людей, кто озадачивал себя написанием языка.

ИМХО, потому что это никому не нужно. Делать ещё одного "Неуловимого Джо", если ты не MS или Oracle и даже не JetBrains — такая себе идея. Разве что только поиграться. Но как мне кажется, гораздо больше опыта можно получить в попытках написать каких-нибудь расширений для уже существующих языков.

Каждому своё. Многие ЯП писались не крупными компаниями, а инициативными людьми.

Если вы не говорите о PHP, то во многих случаях эти самые инициативные люди работали в тех самых крупных компаниях :)
Я к тому что попрактиковаться — это дело хорошее конечно, но я всё же призываю вас быть реалистом и понимать что для широкой поддержки вашего языка вам нужны ресурсы заинтересованной крупной компании. И чтобы что-либо, что вы делаете гордо смотрелось в резюме, гораздо прагматичнее будет, скажем, запилить спорную языковую фичу в TypeScript, о которой в сообществе будет срач на 10 экранов, чем сделать с нуля свой язык :) Ну и заодно вместо того, чтобы делать руками лексер/парсер — вы познакомитесь с промышленными инструментами для создания/обслуживания языков.

Но на Гитхабе вы пишете следующее:
Основные цели и идеи проекта:

1) Создать максимально простую для разработчиков (и главное — для конечных пользователей!) среду разработки и выполнения кода.
2) Создать максимально простой, удобный, гибкий, функционально полный, кроссплатформенный и быстрый язык.


На Гитхабе пишете:
Нетипизированный кроссплатформенный язык программирования, поддерживающий базовые парадигмы ООП.

а здесь в статье:
В языке Mash поддерживаются все парадигмы объектно-ориентированного программирования.


Так где правда, в статье или на Гитхабе? :)
На момент написания статьи поддерживаются уже все вроде как.
Лексер — весьма тривиальная вещь. Не особо сложнее, чем описать набор правил для того же flex. Парсер контекстно-свободной грамматики тоже не является rocket science. Другое дело, что при разработке парсера, придется в любом случае как-то описывать грамматику, что по сути эквивалентно созданию входных данных для bison. Тем не менее, при использовании готовых библиотек-построителей персеров, вы становитесь зависимы от них при весьма сомнительном уменьшении времени на разработку. Насколько оправдана такая зависимость — решать только вам.
Тем не менее, при использовании готовых библиотек-построителей персеров, вы становитесь зависимы от них при весьма сомнительном уменьшении времени на разработку.

Сможете доказать этот тезис? Глядя на грамматики SQL (T-SQL, PL/SQL, MySQL) с кучей ключевых слов в такое что-то не верится...

В случае реализации парсера самостоятельно, придется написать больше текста и потратить больше времени — это правда. Но время, необходимое на написание самого парсера, сильно меньше времени, необходимого на реализацию остальных компонентов компилятора/интерпретатора/VM. Тем более, что многие элементы парсера похожи, копипаст хорошо ускоряет процесс. Доказать я вам ничего не могу, мои высказывания основаны на небольшом личном опыте. Ученых степеней по теме не имею, в разработке серьезных компиляторов участия не принимал.
UFO just landed and posted this here
При реализации парсера вручную, хорошие сообщения об ошибках получатся без проблем сами собой.
Тут весь вопрос в том, какая именно у вас задача. Если требуется каждый день писать парсер для чего-то нового, конечно вариант готовой либы заруливает все остальное.
UFO just landed and posted this here
Для некоторых ошибок реализованы уведомления.
Я не работал над серьезными компиляторами (честно говоря никогда не слышал о коммерческой разработке компиляторов в РФ), поэтому не претендую на объективную истину. В моих велосипедах контекст ошибки был всегда понятен и проблемы сформировать хорошее сообщение с указанием точной позиции в тексте не возникало.
Есть Jet Brains, Excelsior — уже как минимум 2 ру компании, которые занимаются разработкой компиляторов.
Да, вы правы, о JetBrains я забыл. Можно сказать, что они вообще специализируются на парсерах.

LLVM медленный в компиляции, даже с джитом так что это отнюдь не 100% решения для бэкенда нового языка

Мне хотелось создать на мой взгляд максимально простой, функциональный и удобный язык

Когда видишь в описании языка слово «функциональный», ожидаешь увидеть нечто другое.
Некоторые уже настолько упоролись, что и на «функциональные обязанности» в должностной инструкции будут триггерить.

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

Ну, под функциональностью я подразумевал гибкость и потенциал языка
Подошло бы слово «гибкий»)
Исправил это слово в статье. Спасибо.
Лет 10 программирование моё основное «хобби».
И что я понял за это время — ещё один способ интерпретирования текстового файла (plain text) не нужен.
Нужен качественный переход, например как переход от текста к гипертексту.
И самое главное это ориентированность на средства разработки, а не на то какой последовательностью символов заканчивается блок кода\функции\etc.
В общем, если уж решили потратить свое время и силы, могли бы запилить дополнительный уровень абстракции между бэкендом llvm\gcc и ide.
Доступны десятки потоков, гигабайтый памяти, а мы всё мусолим эти текстовые файлы, ну бред же.
Сколько лет уже с++, а до сих пор я не видел ide с его полной поддержкой.
Ну вот вы сделали язык, а где ide, которая будет разматывать ваш синтаксис в абстрактное дерево? Как рефакторить код на вашем языке?

ide тоже реализована. Если бы вы чекнули сайт или репозиторий, то увидели бы её. Вы ожидаете от меня супер новую и мощную технологию с комплексом инструментария, так может поможете мне?) Репозиторий открыт, код доступен всем для ознакомления. Если у вас ести идеи по проекту и руки дотянутся до их реализации, то жду ваши пулы на github.


Проект изначально не был нацелен на обход современных языков по производительности или в чем-либо. Хотелось попробовать самому реализовать свой ЯП с полностью моими архитектурными решениями и концептами. Получился простой и гибкий язык, как по мне. В ВМ отсутствуют лишние абстракции. Поддержка всех парадигм ООП реализована.


Написал же, что хочу на GraalVM либо на LLVM направить транслятор. Тут как бы вопрос времени и того, как скоро я наковыряю достаточно информации для реализации транслятора под целевую ВМ. Если буду копать в сторону LLVM, то поддержка GraalVM уже и так будет, т.к. она может и биткод LLVM выполнять. Да и плюсом WebAssembly подтянется.


Стоит понимать, что архитектуры всех этих вм, в т.ч. и моей реализации по сути схожи. Разница лишь в том, что LLVM и GraalVM заточены под работу со строгой типизацией, а моя ВМ наделена функционалом для автоматического приведения типов и выделения/перевыделения памяти, т.к. нетипизированный язык же писал изначально.


Идея переноса проекта на новые ВМ у меня появилась не так уж и давно, когда я в серьез задумался над оптимизацией. (К слову, мб месяц назад ВМ выполняла код примерно в 8-10 раз медленней чем сейчас).

LLVM (Low Level Virtual Machine) — это ВМ с JIT компилятором на борту.
Исполняет она абстрактный упакованный биткод. Над LLVM существует куча надстроек и окружений (возможно вы думали именно о них, когда писали этот комментарий). Ничего у меня не путается.
Но это не отменяет того факта, что LLVM — не ВМ.
ru.wikipedia.org/wiki/LLVM
Универсальная система анализа, трансформации и оптимизации программ, реализующая виртуальную машину с RISC-подобными инструкциями.
А давайте пройдём на официальный сайт LLVM: llvm.org

Почитаем. А потом на главной странице поищем слово «virtual». Их там два — одно это сразу "…. Despite its name, LLVM has little to do with traditional virtual machines. ...".

Второе — это klee, действительно ВМ. Только вот это проект на базе LLVM, а не сам LLVM.
Слов «virtual» там не так уж и много, потому что их роль выполняют другие формулировки.
LLVM может использоваться, как компилятор абстрактного биткода в нативный. Так что это по-сути сложная ВМ.
Нет, даже «по-сути» это не ВМ.
Я не буду продолжать это. Надоело.
Достаточно уметь читать и гуглить, чтобы разобраться с тем, что такое LLVM. Можно даже скачать проект и покопаться в нем, если у вас есть на это время.
К сожалению, ваше мнение не обоснованно и не является весомым. Оно скорее показывает, что один из двух требуемых навыков у вас отсутствует.
Для вашего блага могу посоветовать вам для ознакомления азбуку и/или поисковую строку google.com
The name LLVM was originally an initialism for Low Level Virtual Machine. This initialism has officially been removed to avoid confusion, as the LLVM has evolved into an umbrella project that has little relationship to what most current developers think of as virtual machines
llvm.org
The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Despite its name, LLVM has little to do with traditional virtual machines. The name «LLVM» itself is not an acronym; it is the full name of the project.

In addition to official subprojects of LLVM, there are a broad variety of other projects that use components of LLVM for various tasks. Through these external projects you can use LLVM to compile Ruby, Python, Haskell, Java, D, PHP, Pure, Lua, and a number of other languages. A major strength of LLVM is its versatility, flexibility, and reusability, which is why it is being used for such a wide variety of different tasks: everything from doing light-weight JIT compiles of embedded languages like Lua to compiling Fortran code for massive super computers.

LLVM — это JIT компилятор с абстрактного биткода в машинный, для его дальнейшего выполнения. Т.е. этот проект можно рассматривать как ВМ. Также он может компилировать абстрактный биткод в натив. Но это уже немного другое.
Не пойму, от чего так вы зацепились за это.
LLVM — это JIT компилятор

Вот именно. А не виртуальная машина


А то так можно сказать, что "GCC — это компилятор C в машинный код, для его дальнейшего выполнения. Т.е. этот проект можно рассматривать как ВМ". Чувствуете нелогичность?

Отличие GCC от LLVM в том, что GCC компилирует C/C++ в нативный код, а LLVM может выполнять абстрактный биткод и во время выполнения компилировать его в машинный для оптимизации. Так что я считаю, что LLVM — это ВМ, подобно JVM, Parrot и прочим.

Почитал, действительно в составе LLVM есть тулза с помощью которой можно запустить биткод. Думаю все придрались именно к определению


LLVM — это ВМ

LLVM — это всё таки "a collection of modular and reusable compiler and toolchain technologies". И одной из технологий (не самой популярной, кмк) является запускалка биткода.

Использует для этого промежуточное представление подобно многим современным трансляторам и компиляторам. У меня тоже так реализовано.

LLVM — это набор инструментов, я бы сказал что это специальный платформонезависимый язык с набором компиляторов (в том числе статической компиляции сразу в машинный код/асм без всяких джитов). Называть это ВМ у меня бы не поднялась рука

Объём проделанной вами работы, поражает.
Просто жаль что такие усилия не оставят инфраструктуры для будущего.
Самое главное, что эти усилия оставят для будущего — это мои приобретенный скилл и опыт (и возможно что-то большее, если дойдут руки до более детального изучения LLVM или GraalVM). Проект само собой не с первой попытки был реализован. К самой оптимальной на мой взгляд архитектуре ВМ я пришел далеко не сразу. Но все решения и реализации мне пришлось проектировать и кодить самому. Этот процесс был весьма сложным и интересным.
UFO just landed and posted this here
А какие вам нужны файлы? Двоичные чтоли?
На самом деле правильный подход — оставить текстовые файлы, но предусмотреть синтаксис настолько простой и эффективный, чтобы анализ и построение синтаксического дерева выполнялись буквально «на лету» в любой IDE начиная от профессиональных систем и заканчивая сверхлегкими блокнотоподобными. В С++ этого нет, потому что С++ создавался тогда когда об этом не задумывались.
Я думаю лучше текстовый формат файлов, будет проще использовать системы контроля версий.
А что если просто сохранять дерево в json\xml?
Стоит понимать, что дерево кода можно строить не полное, дабы сэкономить время анализа кода (и сохранять не обязательно никуда его). Да и многопоточность никто не мешает использовать, чтобы анализировать все «на лету».
А что если просто сохранять дерево в json\xml?

Это называется придумывать решение, сначала придумав инструмент. Надо наоборот
Чем json с xml полезнее?
На самом деле правильный подход — оставить текстовые файлы, но предусмотреть синтаксис настолько простой и эффективный, чтобы анализ и построение синтаксического дерева выполнялись буквально «на лету» в любой IDE начиная от профессиональных систем и заканчивая сверхлегкими

И получается Lisp!
UFO just landed and posted this here
Отож! Вот Sinclair Basic токенизировал все ключевые слова — опечатку было сделать невозможно! Встроенный Autocomplete с IntelliSense в 1982 году!
но предусмотреть синтаксис настолько простой и эффективный, чтобы анализ и построение синтаксического дерева выполнялись буквально «на лету» в любой IDE
Синтаксис должен быть максимально простой и эффективный для чтения, написания и понимания ПРОГРАММИСТОМ, а не IDE.
IDE может быть очень сложной «под капотом» — это не помешает разрабатывать на языке, в конце концов, таких IDE много не надо, достаточно одной хорошей кросс-платформенной.
ИМХО, не стоит чрезмерно упрощать ЯП, лучше когда IDE будут поддерживать и развивать LSP, а ЯП пуст сам реализует LSP сервер.
Э… Язык в 2019 году без алгебраических типов, pattern matching'а и исчерпывающих перечислений?
Первое и второе возможно будет реализовано позже. У меня не так уж и много времени, чтобы круглосуточно кодить.
Перечисления в языке есть:
enum MyEnum [meA, meB, meC, meD]


Также поддерживается объявление массивов, содержащих перечень типов данных. Пример:
a ?= [10, 20, 3.14, "Test", new MyClass(1, 2, "Test"), func1(10, 20, 3.14)]


Из не упомянутого — также в языке поддерживается реализация методов с неограниченным числом аргументов.
func SummAll(...):
  ...
end

...

r ?= SummAll(10, 20, 3.14, "337", 0xFF)

Для получения аргументов есть переменная argcount — хранящая число переданных аргументов и стек — аргументы ложатся в обратном порядке, соответственно принять в методе их весьма просто.
Отлично, а как бы теперь обработать ситуацию, что MyEnum игнорируется? Основная польза от алгебраических типов не в том, что кто-то может положить перечисления, а в том, что попытка использовать перечисления требует полного исчерпания этого перечисления при match.
У вас есть идеи для реализации? Или может у вас имеется готовое решение, которое идеально встанет в код проекта? Пожалуйста — github.com/RoPi0n/mash-lang, жду pull
Чем вам FPC не угодил?)
Посмотрю на этот код, но ничего не обещаю к реализации. Как пойдет.
А чем он должен угодить? Я даже скажу, зачем вам свой язык, если вам паскаль хорош?
UFO just landed and posted this here
В расте прекрасно без GADT приносит массу пользы.
UFO just landed and posted this here

В Rust есть (для наиболее распространённого типа Result) синтаксический сахар — знак вопроса, он говорит "передать ошибку дальше по стеку, т.е. вернуть Result(Err(_)), или .unwrap(), который паникует, если не Ok (т.е. Err).


Вообще, если у вас по типу не пологается какого-то значения, зачем оно в типе присутствует?

UFO just landed and posted this here
Ну, GADT в раст пытаются притащить, но, кажется, не в rust 2019. :(
Э… Язык в 2019 году без алгебраических типов, pattern matching'а и исчерпывающих перечислений?
Кстати, что мешает добавить алгебраические типы данных в более старые языки? Вроде того же c#? Я вот недавно решал одну задачу и очень жалел, что таких нету.
Необходимость компилятору знать все элементы перечисления на момент парсинга.
UFO just landed and posted this here

Немного критики синтаксиса:
1) Двоеточия для управляющих структур излишни. Можно и без них. Особенно это заметно в try, но и в других конструкциях тоже не нужны.


  try:
    ...
  catch:
    ...
  finally:
    ...
  end

Без двоеточий это выглядело бы чуть проще.
2) Не вижу цикла с постусловием, аналог do..while или repeat..until.
3) Разделение proc-func, наверно, излишне.
4) Знак $ в переменных и методах лишний.
5) Синтаксис a ?= 10 непонятен для неподготовленного человека.
6) Скобки в uses <bf> лишние.
7) Можно придраться к ->, точка всё же короче.
8) Оператор @= (разыменование с присваиванием) нелогичен. В паскале для этого используются variable ^ := value, у вас почему-то @ означает то взятие указателя, то разыменование.
9) Чем отличаются jump и goto? Если ничем, достаточно одного.
10) Самое главное. Отдельные объявления и определения классов совершенно не нужны.


И ещё немного замечаний. Типизация, я так понимаю, динамическая? Генераторы (yield), как в питоне — хорошая штука, рекомендую добавить. "Полуавтоматический" сборщик мусора будут постоянно забывать вызывать, это странная идея.


В языке Mash поддерживаются все парадигмы объектно-ориентированного программирования. Т.е. классы, наследования, полиморфизм (в т.ч. динамический), динамические автоматические рефлексия и интроспекция (полная).

Это не парадигмы. ООП и есть парадигма. И если уж говорить о всех идеях из ООП, не вижу поддержки мультиметодов.

1) Мне наоборот кажется, что немного строгости языку не помешает, а то будет совсем уж аморфный синтаксис :)
2) Вместо do..while в Mash реализован until <условие>:… end
Пример:
until a > 0:
  a--
end

Получается как в паскале цикл.
3) Возможно. Но так же код представляется более строго и однозначно. Если разработчик бегло осматривает код, то ему будет удобнее сразу видеть, процедура перед ним или функция.
4) Знак $ заменяет «this->» — он нужен только для обращения к классовым методам и переменным.
5) Возможно. Но обычно люди в нашей сфере готовы к многому.
6) В uses можно добавлять файл через "<имя файла>" или же через <>. В первом случае, транслятор будет искать файл с исходниками возле собираемого файла. Во втором — в папке inc возле транслятора.
7) Ну, тут уж кому как.
8) Ну, как сделал…
9) goto нету, есть jump.
10) Мне наоборот больше привлекателен код, когда объявление классов и определения раздельны. Если разработчик будет знакомиться с незнакомыми ему либами, то думаю, ему будет удобнее смотреть на объявление классов без их реализации.

Да, типизация динамическая. Полуавтоматический сборщик мусора — наоборот как по мне забавная штука. Всегда знаешь когда мусор очищен. Сам контролируешь это. Генераторы конечно попробую реализовать в будущем, вещь несомненно полезная.

Я рассматривал ООП как набор основных парадигм. Мультиметоды и шаблоны считаю немного лишними в языке с динамической типизацией и интроспекцией.
Можно typeof() или x->type использовать.
until a > 0:
  a--
end

Какова семантика? Условие проверяется до выполнения тела цикла или после? Тело цикла выполняется в случае, если условие истинно или ложно?

Условие проверяется после выполнения итерации. Цикл выполняется пока условие ложно. Как в pascal сделал это. Только until вверх объявления цикла перенес.
Большой WTF для любого, читающего код. Написано в одном месте, проверяется в другом.

Это фейл. Синтаксис until(cond){… } читается как while (! cond) {… }, то есть цикл с предусловием. Рекомендую как-то переставить условие в конец.
Ещё к паскалевскому repeat… until можно придраться в том ключе, что while выполняется пока условие истинно, а repeat..until — пока условие ложно. С-подобное do… while в этом плане логичнее.
Кажется, в visual basic я видел все варианты: while(){}, do{}while(), until(){}, do{}until() (но синтаксис там чуть другой).

Ну, кому как. Возможно в будущем изменю эту конструкцию.
Цикл выполняется пока условие ложно.

Тогда не стоит в качестве примера такой конструкции приводить бесконечный цикл.
JFYI в J парой к while идёт whilst. Получается очень красиво: во-первых, это тоже английское слово, тоже while; во-вторых, оно в J расшифровывается как while-s-t = while + skip test, т.е. тест в первый раз не выполняется.

Могу слегка одобрить только $ в качестве замены this->. 2,8,10 категорически не одобряю, они не логичны (ну, ничего страшного, учебный язык). Остальные пункты вызывают меньше WTF.


Я рассматривал ООП как набор основных парадигм.

"Парадигма" — это и есть набор. "Совокупность идей и понятий" (см.вики). ООП как набор идей — парадигма, отдельные идеи до "парадигмы" не дотягивают. Высказывание в вашем варианте режет глаз.

Если разработчик бегло осматривает код, то ему будет удобнее сразу видеть, процедура перед ним или функция.

Зачем?

Доводилось ли вам работать с неизвестным вам кодом? Мб с объемными библиотеками? Несмотря на гибкость языка, строгость должна присутствовать. proc & func реализованы исключительно для этого. Можно было и обойтись без них оставив например только func.

Вы не ответили на вопрос. Какая практическая польза от того, что программист будет знать, функция это или процедура? Что случится, если он будет рассматривать все куски кода как функции?


Я много работал с неизвестным кодом, и мне ни разу не надо было знать, процедура это или функция.

Я решил сделать разделение на функции и процедуры, ведь это все же мой язык. Раз вам нет пользы до того, функция перед вами или процедура, то это ваше дело :)
Тут вопрос в том, как кому больше нравится.

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

Так а что за новая архитектура-то? Неужели нету виртуальных стековых машин? Или все новаторство — в использовании разных кусков памяти под разные нужды?

Да особо ничего новаторского нету. Но архитектура спроектирована в ходе моей работы над проектом, так что можно считать, что она новая. Из новаторского можно разве что сборщик мусора отметить. Он реализован отлично от реализаций в других языках.

Почему синтаксис языка не на русском основан?

Until не ужас, а "пока не" почему-то ужас. Или парсеру не все равно?

Считаю, что ЯП на английском языке будет выглядеть лучше.

Пока видно pascal (end в конце блока кода, разделение на процедуры-функции), python (: в начале), php ( $ как префикс переменной), ?= — know-how автора; всё это заботливо перемешано. Не иначе, чтобы всех запутать :). Вот где ужас, а не в способе кодирования ключевых слов.

$ — сокращение this->
Они стоят только в классовых методах, как вы можете посмотреть.
Разве pascal & python плохие языки?)
Мне кажется, что Mash больше смахивает на Ruby.

У всех языков своя изюминка. C — лаконичный, с его {} и ?:. Pascal — строгий. Python — навороченный из коробки. Ruby — продукт сумрачного японского гения одно слово в:) Mash… даже не знаю… адский микс.

Python — навороченный из коробки

Python хорош тем, что он позволяет писать как очень просто, так и навороченно.
То есть можно ничего не знать о функциональщине, ООП и даже работе с функциями, но уже начать писать простые скрипты, например для автоматизации каких-то действий в консоли.
А потом войти во вкус, изучить тонкости и начать писать компактный и эффективный код, со всякими генераторами, итераторами и т.п.
Именно по этому он хорош как язык для обучения программированию — можно не меняя язык показать разные подходы и парадигмы.

И ещё в нем, как правило, нельзя просто взять и скопировать кусок кода; надо ещё и выровнять отступы ;) один из базовых паттернов говнокода нельзя просто использовать.
Хороший язык, и синтаксис интересный.

?= разве не из go позаимствовано вместе с var? Только там :=
Сделайте уж совсем эпично-патриотично, на дореволюционном русском. И капсом все ключевые слова:
ФУНКЦIЯ
...
КОНЕЦЪ


К сожалению, из статьи не видна киллер фича (она есть?), зато виден убийственный недостаток — автор одинок.
Чтож, что есть — то есть)
Если бы вы в качестве выходного формата взяли Java class file, у вас больше времени осталось бы на вылизывание собственно языка и компилятора, и результат был бы более востребован.

Если статью назвать по-другому, значительная часть комментариев была бы гораздо менее токсичной.
Я бы назвал статью "Еще одна попытка создать ЯП на основе транслятора и ВМ" или "Попытка разобраться с тем, как создаются языки программирования и ВМ". Тогда бы все поняли, что проект в большей степени учебный, и что реализация больше велосипедная, нежели академическая/профессиональная/промышленная. Я уверен, автор получил классный опыт, разрабатывая всё это. И пусть это велосипед, многие комментаторы-критики и такой бы не создали, причем возможно даже не от нехватки опыта, а чисто из лени. А автор не поленился, разобрался и сделал, еще и выложить не постеснялся. Плюс статье, плюс в карму автору. Давайте уважать старания, а не хаять их.

Спасибо. Это мой первый пост на Хабре.

Про звезду репозиторию забыли упомянуть :)

Звезда на гитхабе — это немного про другое. Звёзды на Хабре выражают отношение к вашей активности тут (на Хабре), а звезды в гитхабе — это скорее отметки юзеров гитхаба, кому интересен проект, наподобие закладок. Я бы не стал ставить звезды всем подряд проектам на гитхабе, про которые просто "только что" услышал.

Картофельное пюре (mash) — любый гарнир автора? :)

Аудитория вас интересует только русскоязычная или по какой причине на сайте из международночитаемого лишь «write, compile and run anywhere»?

Ну и мелочи…
Заглушки «Company Name, Company Name, Company Name, Company Name» и «Чтож… Эта страница тоже в скором времени будет заполнена.» как и ваш ник на Patreon (RoPi0n) и выпрашивание «звёзд» на официальном форуме не добавляют серьёзности (а следовательно и доверия) сайту проекта, над которым вы трудитесь на протяжении нескольких лет.

Сайт не слишком давно поднят.
Ему приоритет особо не выделял, т.к. времени небыло. Пока ещё не заполнен как следует. Хочется все по красоте сделать.

За использоване $var для переменных людей надо пожизненно отправлять в goto лапшу.
Вывод типа передачи данных в переменную будет довольно неудобным. Сложил так две переменных, а они по указателю передавались и в итоге попадаем в непонятный раздел памяти.

Чтож, пишу в который раз для внимательного талантливого кодера domix32. Оператор $ используется лишь для сокращения записи "this->". В языке нет "$var" переменных. Ваш комментарий вообще не связан с проектом и не несет никакой смысловой нагрузки. Не следует отправлять в непонятный раздел памяти информацию сразу после её прочтения. На хабре предпочтительна конструктивная критика.

омментарий вообще не связан с проектом и не несет никакой смысловой нагрузки
Автор, вам следует поумерить свой пыл, серьёзно. Тут вы неправы.

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

Ошибаются, но такой уж я человек. Иногда отвечаю колко))

За это могу лишь свои извинения принести заранее людям.

Не имеет принципиальной разницы для чего используется такой синтаксис, это сразу выкидывает из определения языка слово «простой». Перл уже использует аналогичное различие переменных, мало кто в восторге от его синтаксиса. Тут та же ситуация — вместо синтаксического сахара выходит перец. Набор символов !@#$%^ далеко не самый быстрый для набора, а при частом использовании мизинчик начинает страдать. Едва ли гуманно пересаживать людей за спецраскладки только ради языка.
Вторая часть относилась к присвоению переменных вообще. Вывод типа хорошо, но открыть блокнот и написать программу без ошибок из-за особенностей присвоения становится на порядок сложнее. То есть по хорошему нужен линтер или что-то подобное. Тоже далеко не аргумент в пользу простоты языка.
А так — успехов в своем начинании.
Вероятно это нужно чтобы однозначно определять, что это поле экземпляра класса, а не локальная или глобальная переменная
Тогда $->var, пожалуй, более наглядно и логично. И немного на perl похоже ;)
$ — синоним this
-> — признак указателя
var — имя.

Тут же целых 2 символа можно сократить.


  • При передаче $ как аргумента, допустим так:
    MyMethod($) — передается просто this без ->
Я не о том.

Внутри класса к его методам вы обращаетесь так:
  $rem()

снаружу — так:
  x->rem()


Зачем 2 разные формы записи одного и того же действия?

Изнутри можно использовать обращение:
this->rem()
Которое можно сократить так:
$rem()


Также и с любыми другими переменными и методами класса.
Ну ведь удобнее же так :\

Указатель this есть, ок.
Нотация для записи указателя есть, вот она ->
Синоним для this есть, вот он $

Почему вместо $->name использовать дополнительный вариант написания $name, годный только внутри класса? Так короче, да. Но удобнее ли… это дополнительное правило в синтаксисе простого языка.
Респект Вашему труду, но не ясна концепция языка. Вот в Python всё ясно — это современный крутой аналог бейсика, типизации нет, переменные объявлять не надо, даже поля классов объявлять не обязательно, пиши функционал, никакого занудства. В Си тоже ясно — строгая типизация, переменные объявлять обязательно, ну Вы понимаете. У Вас получилось нечто среднее, причём не ясно, а в чем изюминка? Т.е. для Вас это крутой учебный проект? Тогда ок… На первый взгляд, он ничего не даёт. Никакой крутой концепции, кроме того, что Вы написали свой язык, а я не написал.
И да, у Вас ведь нет компилятора под некоторую ОС? Ни байт-кода… Т.е. есть синтаксический анализатор, который разбирает строку на команды и тут же исполняет инструкции? Ну мне почти всё ясно тогда, кроме того, как Вы реализовали динамическое построение классов в трансляторе. На чём транслятор написан?
Т.е. на мой взгляд самое ценное здесь — реализация транслятора, но эта тема в статье не раскрыта. А так — Вашему уровню респект, конечно…

Транслятор преобразует код в промежуточное представление (ассемблер-подобный листинг) и затем собирает уже его в абстрактный байткод для написанной ВМ. Исходя из вашего текста, делаю вывод о том, что вам не почти все ясно, а почти ничего не ясно. Рекомендую пост к прочтению повторно.
Динамическое построение классов реализовано через структурные таблицы и генератор конструктора и деструктора структуры классов.


На чем написано? Серьезно? Вам сложно клацнуть по ссылке на репозиторий?

Ну ок, мне было почти ничего не ясно, теперь немного яснее, спасибо :)

Спасибо, что уделили внимание моей работе)

UFO just landed and posted this here
Пардон, имелась в виду явная и неявная типизация, а не «строгая» и «типизации нет».
И это типа хорошо?

В этом есть своё очарование. Иногда это очень удобно. Возможно, мне так кажется лишь потому, что Бейсик был одним из первых языков, который я освоил.
UFO just landed and posted this here
Да, это так. В Питоне лично мне понравилось то, что в нем не нужно объявлять переменные, а также поля классов. Этим он мне и напомнил Бейсик. А «очарование» здесь в том, что это снижает бюрократическую составляющую при написании кода. В этом есть определенное удовольствие, просто садиться и «фристайлить». Необходимость объявлять переменные это удовольствие резко снижает. ИМХО.
Строгость типизации — это да, это тоже немного мешает, т.к. усложняет текст программы явными преобразованиями.
Это не значит, что я говорю, что Python лучше чем Си. Скорее, мне кажется наоборот. Как перфекционист я бы вообще кодил на Асме, но увы, это коммерчески нежизнеспособная идея. А в Python как и в Бейсике есть своё очарование. Я знал классных кодеров, которые начинали с Бейсика. Именно потому, что неявная типизация позволяет сосредоточиться на задаче, а не на бюрократии… Это как кафе открыть — одно дело классно готовить и людей кормить, а другое — соблюдать положенный документооборот. Немного разные задачи. Хотя конечным итогом должно стать именно классное обслуживание клиента.
UFO just landed and posted this here
максимально простой, полнофункциональный и удобный язык

Взаимоисключающие понятия, имхо. Шарп и ява тоже задумывались такими, а в итоге получилось, то что получилось. Простыми языки может и являются (весьма условно, без хорошего опыта в «строгих» языках, с ходу в них не войдешь), но обвешаны таким количеством библиотек являющимися отраслевыми стандартами, что изучение «обвеса», занимает на порядок больше времени чем изучение непосредственно языка.

При разработке языка есть смысл ориентироваться либо на функциональность, либо на простоту, имхо совмесетить это невозможно.

Ну, тут уже как пойдет. Посмотрим что получится)

Раз уж Вы любите паскаль, посмотрите на Оберон, особенно на книгу «Проект Оберон» Вирта.
Она свободна доступна для чтения здесь: pdf.

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

Ну, тут комментатор ниже постарался и ответит по случаю на этот вопрос)

UFO just landed and posted this here
Исключения, сборка мусора — не самые актуальные сейчас элементы в новых ЯП (Rust и т. д.). Не рассматривается ли отказ от них?

Как же без них? Мне кажется, что от этого нельзя уходить.

UFO just landed and posted this here
От исключений можно и нужно уходить

Прошу прощения, а можно про это по-подробнее? Есть какая-то техника, или какие-то тренды в этом направлении?
UFO just landed and posted this here
А как же писать код совсем без ошибок?))

Для этого уже придумали хаскель)

Хочу заметить, что хоть количество поддерживаемых платформ у фрипаскаля велико, оно очень туго расширяется. Уже несколько лет идут разговоры о бэкенде llvm, но реализации до сих пор нет. У нас была попытка сделать браузеры одной из платформ для программы, пришлось реализовать самописным конвертатором из паскаля в си, дальше цепочка из llvm (вот и пригодился бы родной llvm-бэкенд!) и emscripten. Самое интересное, что программа после прямой конвертации в совершенно неидеоматичный си и компиляции с оптимизациями оказывалась быстрее любой сборки фрипаскалем. Кроме того, за 14 лет использования фрипаскаля я уже трижды натыкался на баги релизного компилятора, что тоже несколько удручает.

Поэтому и хочу на llvm перенести выполнение кода. Только различие в работе с памятью и пока что недостаток моих знаний по LLVM.

Не дают мне реализовать задуменное

Добро пожаловать в клуб любителей трансляторов и компиляторов.

Для целых чисел 32 бита фундаментальное ограничение? Чтобы поближе к машине?
Не смотрели в сторону длинной арифметики?

Максимальная разрядность целого числа — 64 бита.

ar i = 2147483647*2+1
PrintLn(i) // Выводит 4294967295
i = i + 1
PrintLn(i) // Выводит 0
Добро пожаловать в клуб! Теперь, однако, вам необходимо ответить на самый тяжелый вопрос — нужен ли данный язык кому-то, кроме вас? Дело в том, что синтаксис по большому счету никому не сдался, а действительно важно удобство решения задач. Если, как вы пишете в комментариях, основная задача была в том, чтобы получить опыт — считайте, что вы его уже получили. Поставьте данный проект на почетное место на полке и двигайтесь дальше, с опытом и новыми силами, исходя от какой-нибудь конкретной задачи, решение которой с помощью языка принесет кому-то конкретную пользу.

Извините, но… зачем? Чем вас существующие-то языки не устроили?

Разработка компиляторов очень важная сфера в которой Россия и СНГ сильно отстает от всего мира.

У остального СНГ нету с этим проблем, т.к. компиляторы — дело международное. Если не самоизолироваться, то ты можешь пользоваться достоянием всего мира

Коммиты не оформлены практически никак, это ужасно. Похоже, для вас Git — это какая-то обязанность (все делают, ну и мне придётся, эххх, а мог бы по-старинке projname-2018-12-20.zip делать и не мучаться), а не инструмент работы. Советую почитать, как оформлять коммит-сообщения, чтобы всем стало лучше.

Для того, чтоб язык был полезен хоть кому-то после выхода (кроме самого разработчика), он должен обладать некоторым количеством отличающих черт, каждая из которых хоть как-то упрощала б задачу реализации программного обеспечения.


Извините, конечно, но Вы представили еще один generic язык, который ничего особо нового и не дает людям. Однако, для всего нужен опыт, и, даже один законченный ЯП, я уверен, смог Вас очень многому об этой области CS научить, и, следовательно, следующая попытка будет уже лучше. Нужно просто сделать его уникальным и полезным.


А вообще, могу точно сказать, что 99% всех программистов никогда в своей жизни не реализуют ничего своего и не напишут об этом статью. К тому же Вы за эту статью (скорее всего) получили приглашение на Хабр. Так что поздравляю!

Присоединяюсь к поздравлениям, хотя статью можно и попроще забацать для такой цели, как приглашение, мою гляньте))
Вопрос стоит — зачем язык создавался? Единственно, что его хоть как-то отличает — синтаксис питоно-паскале-подобный.
Что критически важно — на сайте добавить синтаксис! Говорить про язык программирования без синтаксиса (даже с репозиторием компилятора) как-то не серьёзно. Я, например, даже не понял — есть ли в этом языке комментарии или нет.
Далее критически важно — версификация. Какую версию вы нам описали в этой статье? 0.4.12? Или всё же — хэ его зэ? Это уже ближе к правде.
Ну, а по мелочи — есть к чему придраться.
Зачем делать until (false)… end постусловием, если уже придуман repeat… until (false)?
Или зачем создавать процедуры, если есть функции?
Я решил написать ряд постов, в которых детально опишу процесс создания и работы ЯП.
Часть 1: habr.com/post/435202
UFO just landed and posted this here

Проект без проблем собирается под unix системы.

UFO just landed and posted this here

Ставите себе Lazarus с офф сайта, можно последний. Собираете все проекты из репозитория.
Нужно собрать:


  1. ВМ /runtime/svm/
  2. Транслятор /lang/
  3. Окружение ВМ /runtime/libs/.../
  4. IDE. Она тоже должна собираться.
    Все должно работать.

Что нового ваш язык привнёс по сравнению с уществующими?

Принесет он как минимум цикл статей на русском, посвященных его разработке.
Юникод в консоль не выводит так понимаю? (windows 7)

Для этого кодировку консоли менять нужно. Есть winapi для этого соответствующий, который я ещё в либу языковую не портировал.

Sign up to leave a comment.

Articles