Хабрахабр

Loli — новый высокопроизводительный язык

В этой статье мы поговорим о новом интерпретируемом языке Loli, рассмотрим синтаксис и сравним с языками C и Python.

Введение

Но по производительности в разы быстрее.
Loli строго типизированный язык. Язык loli по синтаксису больше всего похож на Python. То есть Loli одновременно и функциональный и объектный язык. В нём так же присутствуют объекты. Расширение файлов у языка это .li.
Loli имеет возможность написания расширений на C. И это несомненно плюс.

Тесты производительности

Тесты на github Итак, я не наврал про его производительность, ведь она действительно высокая.
Я написал одинаковые тесты производительности на C, Python и Loli.

Результат вы видите сами:



Небольшой пример

Пример вычисления факториала:

#[ Loli строго типизирован, поэтому нужно описать каждую переменную своим типом или классом
]# fn fact(num: Integer): Integer if (num == 1): {` return 1 # Если 1 то возвращаем 1 } return num * fact(num - 1) # Ну а тут умножаем num на рекурсивный вызов fact с num - 1 } sayln(fact(5)) # Вызываем нашу функцию и даём ей на вход число 5, ответ 120

Синтаксис

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

Переменные:

var x = 5 # Авто-определение типа переменной
var y: Double = 5.32 # Определение типа в ручную
var z = [1, 2, 3], hi = "Hello, world!" # Создание множества переменных через запятую

Массивы:

# List
var a_list = [1, 2, 3]
var a_range = range(1, 3)
var empty_list: List[Double] = [] # Hash
var a_hash = ["a" => 1, "b" => 2, "c" => 3]
var empty_hash: Hash[String, Integer] = []
# Hash от List отличается только тем что можно создавать ключи определённого типа #[ Tuple это как List только Tuple. Tuple имеет фиксированный размер и может содержать типы, которые не имеют никакого сходства друг с другом ]#
var a_tuple: Tuple[String, Double] = <["hi", 34.93]>

Как видим массивы очень интересны, но так же интересны и строки:

# Всё это один тип String
var hi = "Hello, world!"
var multi_line = """Hello, \ world!""" #[ А это уже ByteString, единственное их отличие в том что они хранят в себе массив байтов. Так же обычные строки можно переводить в ByteString методом to_bs Конструкция типа var a = "Hello".to_bs() тоже будет иметь свой смысл. ]#
var a = b"123456"
var b = b"\0\1\2"
var c = b"\255\254\t"
var d = b"""A \ multi-line \ ByteString"""

Со строками разобрались, теперь числа.
Под капотам в C у типа Integer стоит uint64_t, то есть 64-битные числа.
У Byte это uint8_t, то есть 8-битные числа.
Ну а у Double соответственно double.

Теперь поговорим о функциях:

# Функции
fn empty_fn { sayln("Hello, World!") # Функция без аргументов и возвращаемого значения } fn fn_with_arg(num: Integer) { # Функция с обязательным аргументом sayln("Num: " ++ num) # ++ в Loli это не инкремент, а соединение типов
} fn fn_with_arg_and_return(num: Integer): Integer { return num # Возвращаем num } fn fn_without_arg_but_with_return: Integer { return 2 + 2
} # Функция с Keyarg
fn sample(:first x: Integer, :second y: Integer, :third z: Integer): Integer { return x + y + z
} sample(1, 2, 3) # 6
sample(1, :second 2, :third 3) # 6
sample(:third 30, :first 10, :second 5) # 45 # Не обязательные значения функций
# В данном случаи можно просто вызвать sample() и a будет равна 10
fn sample(a: *Integer = 10): Integer { return a + 10 } # Varargs
fn sum(n: Integer...): Integer { # В данном случаи n будет типом List[Integer] var result = 0 n.each(|x| result += x) # Лямбда функция return result
} # Лямбда функции
fn apply(a: Integer, fn: Function(Integer => Integer)): Integer { return fn(a)
} sayln(apply(10, (|a| a * a))) # 100 # Future функции
future fn add(Integer, Integer): Integer { ... } # *a lot of code* fn add(x: Integer, y: Integer): Integer { return x + y
}

Такс, с функциями мы разобрались, ну а теперь классы.

# Класс Point с двумя аргументами в конструкторе
class Point(x: Integer, y: Integer) { pub var @x = x # pub означает что это поле публичное, так же есть pri (private), pro (protected) pub var @y = y
} # Можно также сократить предыдущий пример
class Point(pub var @x: Integer, pub var @y: Integer) { } # Наследование
class Point2D(pub var @x: Integer, pub var @y: Integer) {}
class Point3D(x: Integer, y: Integer, pub var @z: Integer) < Point2D(x, y) {} #[ По умолчанию методы класса получают неявный параметр self в качестве первого аргумента. Спецификатор sta при применении к методу класса отключает это поведение
]# # Дженерики
class Stack[A](element: A) { pub var @contents = [element] pub fn push(value: A): self { @contents.push(value) }
} Stack(1).push(2).push(3) # [1, 2, 3]

Исключение это обыкновенный класс который унаследован от класса Exception. Классы прошли, теперь рассмотрим исключения. В loli по умолчанию уже есть 7 исключений которые можно использовать.

  • Exception — базовый класс всех исключений
  • DivisionByZero — ошибка деления на 0
  • IndexError — Доступ за пределы контейнера (например, List), String или ByteString
  • IOError — Некорректная работа с файлами
  • KeyError — Попытка прочитать значение из Hash, которое не существует
  • RuntimeError — Неправильное действие во время выполнения, например изменение хеша во время итерации или превышение предела рекурсии
  • ValueError — Указано неверное или необоснованное значение

Все исключения можно вызвать через ключевое слово raise

raise IndexError("Index out of range") # Тут мы создаём экземпляр класса унаследованного от Exception

Для отлова исключений существует блок try\except

try: { raise IndexError("Index out of range")
except Exception as e: sayln("Exception: {0}".format(e.message))
}

Импорты

Система импорта похожа на ту что в Python:

import sys sys.exit() import package import package as pkg import (somefn, somevar) package import "folder/package"

Пути импортов в loli выглядят таким образом:

./<name>.li
./<name>.(dll/so) ./pkg/<name>/<name>.li
./pkg/<name>/<name>.(dll/so) <original root>/pkg/<name>/<name>.li
<original root>/pkg/<name>/<name>.(dll/so)

Enums

Небольшой пример enum:

enum Rgb { Red, Green, Blue fn is_blue: Boolean { match self: { case Blue: return true else: return false } }
}

Заключение

На Loli уже есть биндинги OpenGL и FreeGLUT и обёртка над cURL. Как мы видим Loli это очень хороший и быстрый скриптовой язык который можно бесконечно расширять расширениями на C. Так же планируется написать HTTP сервер для loli. А так же в разработке порт GTK+. Я надеюсь вам понравился этот язык и вы уделите ему немного времени. Из этого следует что язык можно применять в разных сферах.

Ссылки

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть