Язык программирования Dark

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

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

Для удобной разработки на языке Dark рекомендуется использовать официальное расширение для Visual Studio Code, которое предоставляет подсветку синтаксиса, автодополнение и другие полезные функции.

Скачать установщик Dark-0.3.5

Исходный код

Основы синтаксиса

Переменные

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

my_variable = 10
another_var = "Hello, Dark!"
is_active = true

Типы данных

Операторы

Dark поддерживает стандартные арифметические (+, -, *, /), сравнительные (==, !=, <, >, <=, >=) и логические операторы.

Логические операторы (and / or / not)

Для создания сложных условий используются логические операторы and (логическое И), or (логическое ИЛИ) и not (логическое НЕ).

# Пример с 'and'
if age > 18 and has_license == true then
    println("Можно водить машину")
end

# Пример с 'or'
if is_weekend or is_holiday then
    println("Время отдыхать!")
end

# Пример с 'not'
is_ready = false
if not is_ready then
    println("Ещё не готово.")
end

# Пример not с операторами сравнения
if not (a > b) then
    println("a не больше b")
end

Операторы поддерживают "короткое замыкание" (short-circuiting). Например, в выражении A and B, если A ложно, то B не будет вычисляться.

Управляющие конструкции

If-Then-Else

Условный оператор. Блок else не является обязательным.

if x > 10 then
    println("x is greater than 10")
else
    println("x is not greater than 10")
end

While

Цикл, который выполняется, пока условие истинно.

i = 0
while i < 5 do
    println(i)
    i = i + 1
end

For

Цикл для итерации по элементам списка, строки или ключам словаря.

my_list = [1, 2, 3]
for item in my_list do
    println(item)
end

Обработка ошибок (try...except)

Конструкция try...except позволяет перехватывать ошибки времени выполнения, предотвращая аварийное завершение программы.

try do
    # Код, который может вызвать ошибку
except e do
    # Код, который выполнится в случае ошибки.
    # 'e' - это словарь с информацией об ошибке.
end

С версии 0.3.1 сообщения об ошибках стали более понятными и информативными. При возникновении ошибки времени выполнения, Dark не только выведет ее описание, но и покажет строку кода, где она произошла, с указателем на проблемное место.

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

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

function inner_function() do
    c = 10 / 0 # Ошибка здесь
end

function middle_function() do
    inner_function() # Вызов, ведущий к ошибке
end

middle_function()

Вывод в консоли будет выглядеть так:

Трассировка вызовов (от последнего к первому):
  Файл "D:\...\script.dark", строка 8, в функция 'middle_function'
  Файл "D:\...\script.dark", строка 2, в функция 'inner_function'

Ошибка выполнения: деление на ноль
  [Файл: "D:\...\script.dark", строка 2, позиция 12]

  2 |     c = 10 / 0 # Ошибка здесь
    |            ^
--------------------------------------------------------------------

Пример:

try do
    result = 10 / 0
except e do
    println("Произошла ошибка: " + e["message"])
end

Импорт модулей

Для использования кода из других файлов (модулей) используется ключевое слово import. Путь к модулю указывается в двойных кавычках. Расширение .dark или .py указывать не нужно.

В качестве синонима import можно использовать use.

# Импортируем стандартный модуль os
import "os"
# или так:
use "os"

# Импортируем пользовательский модуль из файла my_module.dark
import "my_module"

# Используем функцию из импортированного модуля
os.system("cls")
my_module.my_function()

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

# В файле my_math.dark есть PI = 3.14 и функция square(x)
from "my_math" use PI, square

println(PI)       # Выведет 3.14
println(square(5)) # Выведет 25

Функции

Определение пользовательских функций.

function add(a, b) do
    return a + b
end

result = add(5, 3)
println(result) # Выведет 8

Функция может не возвращать значение. В этом случае можно использовать return для досрочного выхода из функции.

function check_age(age) do
    if age < 18 then
        println("Доступ запрещен.")
        return # Досрочный выход из функции
    end
    println("Доступ разрешен.")
end

Комментарии

Однострочные комментарии начинаются с символа #.

# Это комментарий. Он будет проигнорирован.
variable = 1 # Это тоже комментарий.

Директивы

Если в начале фаила будет строка начинающаяся с символа #! - это даст информацию о объявлении директивы.

#!nocache
# Это директива, которая отключает кеширование для этого файла.
# Полезно при разработке, чтобы изменения в файле сразу применялись.
#!USE_WITH_PYTHON
# Эта директива включает интеграцию с Python, позволяя использовать модуль `python`.
# Требуется для выполнения Python-кода внутри Dark-скрипта.
python.exec('print("Hello from Python!")')

# или версия с созданием переменных:
python_code = """
a = input("Enter something: ")
print(f"You entered: {a}")
def greet(name):
    return f"Hello, {name}!"
b = greet("World")
"""
vars = python.exec(python_code)
println(vars['a'])
println(vars['b'])

ООП: Классы и Объекты

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

Определение классов

Класс определяется с помощью ключевого слова class, за которым следует имя класса и блок do...end.

class Animal do
    # ... методы и атрибуты ...
end

Конструктор (__main__)

Метод с именем __main__ является конструктором. Он вызывается автоматически при создании нового объекта и используется для инициализации его начального состояния. Первый параметр конструктора (и любого другого метода) — это ссылка на сам создаваемый объект, по соглашению его часто называют object.

class Animal do
    function __main__(object, name) do
        object.name = name # Создание и инициализация атрибута 'name'
    end
end

Создание объектов (экземпляров)

Новый объект (экземпляр класса) создается вызовом имени класса как функции. Аргументы, переданные при вызове, передаются в конструктор __main__ (за исключением первого аргумента object, который передается автоматически).

my_dog = Animal("Рекс")
println(my_dog.name) # Выведет "Рекс"

Атрибуты и методы

Атрибуты — это переменные, принадлежащие объекту. Методы — это функции, принадлежащие классу, которые могут работать с данными объекта.

class Dog do
    function __main__(object, name) do
        object.name = name
    end

    # Это метод
    function speak(object) do
        return "Гав-гав"
    end
end

my_dog = Dog("Рекс")
println(my_dog.name, " говорит: ", my_dog.speak()) # Выведет: Рекс говорит: Гав-гав

Наследование

Класс может наследовать атрибуты и методы другого класса (родительского). Это позволяет избежать дублирования кода и строить иерархии типов. Родительский класс указывается в скобках после имени дочернего класса.

class Animal do
    function __main__(object, name) do
        object.name = name
    end

    function speak(object) do
        return "Животное издает звук"
    end
end

# Cat наследует от Animal
class Cat(Animal) do
    # Переопределяем метод родителя
    function speak(object) do
        return "Мяу"
    end
end

my_cat = Cat("Мурка")
# Атрибут 'name' унаследован от Animal
println(my_cat.name) # Выведет "Мурка"
# Метод 'speak' был переопределен
println(my_cat.speak()) # Выведет "Мяу"

Специальные методы (Перегрузка операторов)

Классы в Dark могут определять специальные методы, чтобы имитировать поведение встроенных типов. Это позволяет, например, складывать объекты вашего класса с помощью оператора + или определять их строковое представление.

Строковое представление: __str__

Если в классе определен метод __str__, он будет автоматически вызываться, когда объект нужно преобразовать в строку (например, при использовании println или to_str). Этот метод должен возвращать строку.

class User do
    function __main__(object, name, id) do
        object.name = name
        object.id = id
    end

    function __str__(object) do
        return "Пользователь(id=" + to_str(object.id) + ", name='" + object.name + "')"
    end
end

user = User("Alice", 101)
println(user) # Выведет: Пользователь(id=101, name='Alice')

Перегрузка операторов

Вы можете определить, как стандартные операторы (+, *, == и т.д.) будут работать с экземплярами вашего класса, определив соответствующие специальные методы.

Вот список поддерживаемых операторов и их методов:

ОператорИмя методаОписание
+__add__Сложение
-__sub__Вычитание
*__mul__Умножение
/__div__Деление
==__eq__Равенство
!=__ne__Неравенство
<__lt__Меньше чем
>__gt__Больше чем
<=__le__Меньше или равно
>=__ge__Больше или равно

class Vector do
    function __main__(object, x, y) do
        object.x = x
        object.y = y
    end

    function __add__(object, other) do
        return Vector(object.x + other.x, object.y + other.y)
    end
end

v1 = Vector(2, 3)
v2 = Vector(10, 5)
v3 = v1 + v2 # Здесь вызывается __add__
# v3 будет объектом Vector с x=12, y=8

Приватные члены (Инкапсуляция)

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

class BankAccount do
    function __main__(object, owner, initial_balance) do
        object.owner = owner
        object.__balance = initial_balance # Приватный атрибут
    end

    # Публичный метод для получения баланса
    function get_balance(object) do
        return object.__balance # Доступ внутри класса разрешен
    end
end

my_account = BankAccount("VSP", 1000)

# Это сработает
println(my_account.get_balance()) # Выведет 1000

# А это вызовет ошибку, так как __balance - приватный
# println(my_account.__balance)

Встроенные функции

print(value) / print()

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

println(value) / println()

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

input()

Читает строку текста от пользователя.

to_int(value)

Преобразует значение в целое число. (Рекомендуется использовать конструкцию try...except)

to_str(value)

Преобразует значение в строку.

to_float(value)

Преобразует значение в число с плавающей точкой. (Рекомендуется использовать конструкцию try...except)

type(value)

Возвращает тип значения (например, "string", "number").

Встроенные методы

Некоторые типы данных имеют встроенные методы, которые можно вызывать через точку. Методы — это функции, связанные с конкретным объектом.

Методы строк (String)

"my string".len()

Возвращает количество символов в строке.

"my string".upper()

Возвращает новую строку в верхнем регистре.

"my string".lower()

Возвращает новую строку в нижнем регистре.

" str ".strip()

Удаляет пробельные символы в начале и в конце строки.

"string".startswith(prefix)

Возвращает true, если строка начинается с prefix.

"string".endswith(suffix)

Возвращает true, если строка заканчивается на suffix.

"string".find(substring)

Ищет подстроку и возвращает индекс первого вхождения или -1, если не найдено.

Методы списков (List)

my_list.len()

Возвращает количество элементов в списке.

my_list.append(item)

Добавляет элемент в конец списка.

my_list.pop()

Удаляет и возвращает последний элемент списка.

Методы словарей (Dictionary)

my_dict.len()

Возвращает количество пар ключ-значение в словаре.

my_dict.keys()

Возвращает список всех ключей в словаре.

Стандартная библиотека

Язык Dark поставляется с набором встроенных модулей для выполнения общих задач. Для использования функций модуля, импортируйте его: import "os", а затем вызывайте функции через точку: os.getcwd().

Модуль vsp210

vsp210.history()

Возвращает исторю создателя языка Dark.

vsp210.philosophy()

Возвращает философию языка Dark.(Секретная функция)

vsp210.calculator()

Запускает калькулятор написаный для примера.

vsp210.version()

Возвращает версию языка Dark.

vsp210.docs()

Отправляет пользователя на страницу документации языка Dark.

vsp210.telegram()

Отправляет пользователя в телеграм канал создателя языка Dark.

Модуль http

http.get(url)

Выполняет HTTP GET-запрос и возвращает словарь с `status_code`, `headers` и `body`.

http.post(url, data)

Выполняет HTTP POST-запрос с телом `data` (словарь) и возвращает ответ.

Модуль os

os.getcwd()

Возвращает текущую рабочую директорию.

os.path_exists(path)

Проверяет, существует ли путь. Возвращает True или False.

os.mkdir(path)

Создает директорию.

os.rmdir(path)

Удаляет директорию.

os.remove(path)

Удаляет файл.

os.rename(old, new)

Переименовывает файл или директорию.

os.listdir(path)

Возвращает список содержимого директории.

os.getsize(path)

Возвращает размер файла.

os.isdir(path)

Проверяет, является ли путь директорией.

os.system(command)

Выполняет системную команду (например, "cls" или "clear").

os.exit(code)

Завершает выполнение программы с указанным кодом выхода.

Модуль math

math.sqrt(number)

Вычисляет квадратный корень числа.

math.pow(base, exp)

Вычисляет `base` в степени `exp`.

math.floor(number)

Возвращает наибольшее целое число, меньшее или равное `number`.

math.ceil(number)

Возвращает наименьшее целое число, большее или равное `number`.

math.pi()

Возвращает значение числа PI.

math.random()

Возвращает случайное число с плавающей точкой от 0.0 до 1.0.

math.random_int(min, max)

Возвращает случайное целое число в диапазоне от `min` до `max` включительно.

Модуль stdlib

stdlib.range(start, stop)

Возвращает список чисел в диапазоне от `start` (включительно) до `stop` (не включительно).

stdlib.list_contains(list, item)

Проверяет, содержится ли `item` в `list`.

stdlib.list_join(list, separator)

Объединяет элементы списка в строку с указанным разделителем.

stdlib.dict_get(dict, key, default)

Получает значение из словаря по ключу, с возможностью указать значение по умолчанию.

stdlib.clamp(value, min, max)

Ограничивает значение `value` между `min` и `max`.

stdlib.json_decode(json_string)

Преобразует строку в формате JSON в словарь или список.

stdlib.read_file(path)

Читает содержимое файла и возвращает его в виде строки.

stdlib.write_file(path, content)

Записывает строку content в файл по указанному пути path.

stdlib.str_split(string, separator)

Разделяет строку по указанному разделителю и возвращает список.

stdlib.str_upper(string)

Преобразует строку в верхний регистр.

stdlib.str_lower(string)

Преобразует строку в нижний регистр.

stdlib.str_replace(string, old, new)

Заменяет все вхождения подстроки `old` на `new`.

Модуль time

time.time()

Возвращает текущее время в виде Unix timestamp (число секунд с 1 января 1970 года).

time.sleep(seconds)

Приостанавливает выполнение программы на указанное количество секунд.

Модуль file

Модуль для работы с файлами. Работает с одним файлом за раз. Сначала откройте файл с помощью file.open(), затем используйте функции чтения/записи и не забудьте закрыть его с помощью file.close().

file.open(path, mode)

Открывает файл. mode - это строка, например: "r" (чтение), "w" (запись), "a" (дозапись), "r+" (чтение и запись).

file.read()

Читает все содержимое открытого файла и возвращает его как строку.

file.readline()

Читает одну строку из файла.

file.readlines()

Читает все строки из файла и возвращает их в виде списка.

file.write(content)

Записывает строку content в открытый файл.

file.close()

Закрывает ранее открытый файл.

Модуль gui

Простой модуль для создания графических интерфейсов на основе Tkinter.

gui.create_window(title, width, height)

Создает главное окно приложения с указанным заголовком и размерами.

gui.create_label(text)

Создает и размещает текстовую метку в окне.

gui.create_button(text, command)

Создает кнопку. command - это имя функции (в виде строки), которая будет вызвана при нажатии.

gui.create_entry()

Создает поле для ввода текста.

gui.get_entry_value()

Возвращает текст, введенный в поле ввода (созданное через create_entry).

gui.set_label_text(text)

Изменяет текст метки (созданной через create_label).

gui.run_app()

Запускает главный цикл обработки событий GUI. Эта функция должна вызываться в конце скрипта.

gui.stop()

Завершает главный цикл обработки событий GUI.

Модуль color

Модуль для вывода цветного текста в консоль. Поддерживает именованные цвета, а также форматы RGB, HEX и HSL.

color.red(text)

Возвращает текст, окрашенный в красный цвет.

color.green(text)

Возвращает текст, окрашенный в зеленый цвет.

color.blue(text)

Возвращает текст, окрашенный в синий цвет.

color.yellow(text)

Возвращает текст, окрашенный в желтый цвет.

color.cyan(text)

Возвращает текст, окрашенный в голубой цвет.

color.magenta(text)

Возвращает текст, окрашенный в пурпурный цвет.

color.white(text)

Возвращает текст, окрашенный в белый цвет.

color.black(text)

Возвращает текст, окрашенный в черный цвет.

color.orange(text)

Возвращает текст, окрашенный в оранжевый цвет.

color.purple(text)

Возвращает текст, окрашенный в фиолетовый цвет.

color.pink(text)

Возвращает текст, окрашенный в розовый цвет.

color.brown(text)

Возвращает текст, окрашенный в коричневый цвет.

color.gray(text)

Возвращает текст, окрашенный в серый цвет.

color.light_gray(text)

Возвращает текст, окрашенный в светло-серый цвет.

color.dark_gray(text)

Возвращает текст, окрашенный в темно-серый цвет.

color.light_blue(text)

Возвращает текст, окрашенный в светло-синий цвет.

color.light_green(text)

Возвращает текст, окрашенный в светло-зеленый цвет.

color.light_cyan(text)

Возвращает текст, окрашенный в светло-голубой цвет.

color.light_red(text)

Возвращает текст, окрашенный в светло-красный цвет.

color.light_magenta(text)

Возвращает текст, окрашенный в светло-пурпурный цвет.

color.dark_red(text)

Возвращает текст, окрашенный в темно-красный цвет.

color.dark_green(text)

Возвращает текст, окрашенный в темно-зеленый цвет.

color.dark_blue(text)

Возвращает текст, окрашенный в темно-синий цвет.

color.dark_yellow(text)

Возвращает текст, окрашенный в темно-желтый цвет.

color.dark_cyan(text)

Возвращает текст, окрашенный в темно-голубой цвет.

color.dark_magenta(text)

Возвращает текст, окрашенный в темно-пурпурный цвет.


color.rgb(r, g, b, text)

Возвращает текст, окрашенный в указанный RGB цвет (компоненты от 0 до 255).

color.rgba(r, g, b, a, text)

Возвращает текст, окрашенный в указанный RGBA цвет. Альфа-канал `a` в большинстве терминалов не поддерживается и игнорируется.

color.hex(hex_string, text)

Возвращает текст, окрашенный в указанный HEX цвет (например, "#ff6496").

color.hsl(h, s, l, text)

Возвращает текст, окрашенный в указанный HSL цвет (h: 0-360, s: 0-100, l: 0-100).

Модуль python

Модуль для прямой интеграции с Python. Требует директиву #!USE_WITH_PYTHON в начале файла.

python.exec(code_string)

Выполняет код Python (переданный в виде строки) в текущем окружении Dark. Это позволяет обмениваться переменными между Dark и Python.

Python-расширения

Одной из самых мощных возможностей Dark является способность подключать модули, написанные на Python. Это открывает доступ ко всей экосистеме библиотек Python.

Структура проекта

Для использования расширений создайте папку dark_extensions в корне вашего проекта. В эту папку помещайте ваши .py файлы-модули.

my_project/
├── dark_extensions/
│   └── math_ext.py
├── my_script.dark
└── ...

Создание модуля-расширения

Каждый Python-файл расширения должен содержать функцию get_module(). Эта функция должна возвращать словарь, где ключи — это имена, которые будут доступны в Dark, а значения — это соответствующие функции или переменные из Python.

Все функции, предназначенные для вызова из Dark, должны принимать один аргумент — список (list) переданных параметров.

Пример: dark_extensions/math_ext.py

import math

# Функция принимает список аргументов от Dark
def power(args):
    if len(args) != 2:
        raise TypeError("pow() expects 2 arguments")
    return math.pow(args[0], args[1])

# Эта функция будет вызвана интерпретатором Dark
def get_module():
    return {
        "pi": math.pi,      # Экспорт переменной
        "pow": power        # Экспорт функции
    }

Использование в Dark

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

import "math_ext"

println("Число PI из Python: " + math_ext.pi)

# Вызываем функцию из Python, передавая аргументы
# В Python они придут как список [2, 8]
result = math_ext.pow(2, 8) 
println("2 в степени 8 = " + result) # Выведет 256.0