liin_lang 0.1.0 copy "liin_lang: ^0.1.0" to clipboard
liin_lang: ^0.1.0 copied to clipboard

discontinued
outdated

A simple programing language for creating instructions

Linear Instructions Language (liin) #

Логотип

Dart Version License: MIT

Что это? #

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

У языка философия следующая: всё состоит из инструкций и пустых строк. Инструкции это то, что выполняется, а всё остальное - пустые строки (несмотря на то, что сейчас есть уже и комментарии). На данный момент инструкции разделяются на объявления и команды. Объявление - операции с переменными (или объявление блока), команды - выполнение каких-либо действий

Пример кода:

. Комментарий
! inp << input
! a = inp * 2
> if a > 10
    . Тоже комментарий
    > print a
> if a <= 10
    > print -a

Эта программа получает на вход число, умножает его на 2, если оно больше 10, выводится без изменений, иначе меняется знак числа

И сделано всё это чудо на 100% на замечательном языке Dart :)

Как на этом писать? #

А теперь поговорим о синтаксисе. Здесь он довольно простой. Каждое действие с новой строчки, и тут главные начала строчек:

  • ! - начало для любых объявлений и разделяется на:
    • просто ! - объявление переменной. Далее должно идти имя переменной, операнд (присвоение =/плюс +=/минус -=/умножение *=/деление /=/остаток от деления %= либо операция получение значения команды <<). В случае с обычными операциями, то после операнда указывается выражение, в случае с командной операцией << после операнда указывается команда (все параметры также можно указывать, как и при обычном вызове функции)
    • !x или !X - удаление переменной. Далее идёт имя переменной
    • !> - объявление блока. Далее указывается имя блока. После строчки с объявлением блока, код пишется с отступом, для обозначения границ блока. Вызывается блок командой run <имя блока в кавычках>
  • > - начало для любой команды. После этого символа пишется имя команды и аргументы (через запятые)
  • . - обозначение комментария. Строчка, которая начинается с такого символа (отступы можно игнорировать), не будет выполняться

Теперь, полагаю, стоит поговорить и о самих выражениях и тиках данных. Здесь тип данных определяется сам по себе в зависимости от того, что писать в выражении. Выражение это в принципе всё, что указывается в значении переменной, в аргументе и в вводе. 1 + 1, true || false, "lmao", 5.25 - это всё выражения. bool, int и string между собой не скрестить в рамках одного выражения и в рамках одной переменной, разные типы чисел могут использоваться в одном контексте, тип преобразуется в наиболее подходящий. Всё это - магия модуля expressions, магия, работающая отлично.

Про все команды можно узнать здесь

Также примеры кода есть здесь

Как с этим работать? #

Ну вот синтаксис, наверное, стал понятен, а что с этим делать-то?

// TODO здесь будет информация о пакете из pub.dev, если залью

Можно работать с этим всем, как с модулем, то есть импортировать, запускать код и получать из него какие-то результаты:

import 'package:liin_lang/liin_lang.dart';

void main() async {
    final r = await runLiin(
        fileName: 'instructions/lines.liin',
        runInput: ['96', '"Hello World!"'],
    );
    print('Executed in ${r.executionTime.inMilliseconds}ms');
}

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

pub run 'liin_lang:interpreter.dart'

Можно указать файл и тогда просто выполнится файл. Если не указать, то можно построчно выполнить файл. Для ввода блоков надо разделять на строки, это делается через \ (надо учесть, что этот символ делит строки, даже если этот символ внутри выражения). Например можно вот так:

❯ dart pub run 'liin_lang:interpreter.dart'
.! version = "0.1.0 alpha"
.! author = "u/vlad"
>> > print "Hello World!"
Hello World!

Что будет дальше? #

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

Как это появилось? #

Началось всё это с идеи автоматизировать скриншоты ежедневные одного сайта, поэтому я на NodeJS сделал простенький скрипт, который делал скрин сайта, писал на нём кое-какие данные и отправлял этот скрин в ВК. Однако тут мне пришла идея создать что-то вроде отдельно интерпретатора для команд по рисованию на картинке, чтобы, например, делать скрин, потом запускать отдельный скрипт, который бы написал и нарисовал на скрине всё, что мне надо. Выглядело это как-то так:

Этот код рисовал чёрную линию из верхнего левого угла в центр картинки
> line 0; 0; x / 2; y / 2; 0xff000000

Далее я игрался с рисованием линий и подумал, что было бы неплохо сделать ещё переменные и циклы, чтобы рисовать по несколько линий по определённом алгоритму. Тут я переписал код ещё пару раз, сделал блоки кода, сделал переменные, всё работало по философии какого-то супер функционального языка (даже более функционального, чем он есть сейчас), вставляя, например, переменную i в while, ты вставлял только значение i в конкретный вызова while. Аргументы разделялись через ";", отступы обозначались через "-". Всё это я сделал где-то за 2 вечера и половину выходного. На этом моменте развития это выглядело как-то так:

! a = 1
! b = 2 + 3
> count 5
-> print 1

Тут тоже было много перемен. В какой-то промежуток времени были константы, обозначающиеся через "!!", до констант были "настройки", по факту константные переменные, которые получают сразу все значения на уровне первичного анализа, где бы в коде они не находились. Сначала был только цикл count, который просто выполнял свой блок кода указанные N раз, позже реализовал while как строковое выражение, которое потом уже парсилось. На этом этапе парсинг и построчное выполнение были одним целым, программа сразу читала код, определяла, что есть что, выполняла. При этом комментариев как таковых не было: всё, что не было инструкциями, было "пустыми строками", а значит удалялись перед выполнением

После некоторых размышлений, некоторых идеи и 2 университетских лекций по программированию, через ~полторы недели я вернулся к проекты, я переписал весь интерпретатор с нуля. Теперь сначала проходит парсинг с анализом, а только потом уже выполнение по проанализированным строкам. Были в большей мере задействованы регулярные выражения, были добавлены блоки (слабый аналог функций), переменные в команды терерь переходят в виде выражений, и только потом парсятся, команды теперь могут возвращать значения. Также появились комментарии, так как с усложнением кода, стало иногда трудно находить ошибки, так как ошибочные строки пропускались на уровне первичного анализа

И вот сейчас я на этом этапе развития проекта, этапе версии 0.1.0. Думаю, что если буду развивать идею, то ещё много чего поменяю, но по-крайней мере какой-то живучий скелет кода создан, осталось только создать функционал и доделать до полноценного вида

Помочь идее? #

Нет помощи лучше, чем помощь кодом. Поэтому буду рад вкладам в виде кода больше всего. Особенно в области парсера, так как там я довольно слаб. По каким-либо вопросам, просьбам, пожеланиям и прочем можно писать на мою странички в ВКонтакте, мне в лс в Телеграме, ну и в худшем случае на почту-помойку: idroidservv@gmail.com или на почту DT: debils.technologies@gmail.com

4
likes
0
pub points
0%
popularity

Publisher

unverified uploader

A simple programing language for creating instructions

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

ansicolor, expressions

More

Packages that depend on liin_lang