Rust\MangoLanguage

Mango

Язык для веб разработки.


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

Каждый проект - это структурированная категория с классами + конфигурационные файлы

root/
.mango-conf - конфигурационные файл проекта (содержит различные директивы)
.router - маршрутизатор - рулит запросом
project/ - содержит в себе сам проект (пользовательские классы, т.д)
vendor/ - содержит в себе зависимости подгруженные через менеджер зависимостей
runtime/ - отладочная информация, логи и проч
web/ - содержит статику (js, css, ...)
... пользователь может добавить неограниченое количество дополнительных папок и файлов - они не будут учтены сборщиком
.mango-conf:

// максимально допустимый размер загружаемого файла:
post.max_filesize=90mb

// здесь хранится набор конфигурационных директив

include ".mango-conf.local" // подключает локальный конфиг который дает возможность переопределить директивы

.router


// позволяет выполнять любой код в скриптовой форме.
// Обязательно должен возвращать наследника интерфейса Mango.Response.IResponse

use Mango.Response.Raw;

request().path.match({
    /^path\/to\/([\d]+)$/ => fun(id) { // [\d] будет передано в аргумент "id"
        return new Raw().content('Hello, World!' + (string)id);
    }
});

return new Raw().content('Sample page');

Шаблонизаторы

use Mango.Response.TemplateBuilder;

// пример прямого рендера из роутера:
// TemplateBuilder содержит экспортированную функцию (инициализатор) которая возвращает TemplateBuilder.
// compile собирает представление и возвращает наследника IResponse
// при желании вы можете использовать любой другой не стандартный шаблонизатор

return template('views/main.tpl').setData([
    'users' => [
        'Andrew Sikorsky', 'Maxim Ambroskin', 'Artem Mickehin',
    ]
]).compile();


views/main.tpl:
@foreach (users as user)
    <b>{{ user }}</b><br>
@endforeach

Встроенный отладочный веб-сервер

mango-server ./ - запустит веб сервер для разработчика в текущей директории. Заметим что для полноценной работы Вам понадобится связка с nginx

Ошибки выполнения и интерпретации

Каждая ошибка логируется в удобный для просмотра лог-файл в папке runtime/. Лог файл содержит в себе стек вызовов и дамп памяти, так-же дополнительную информацию о запросе. При желании можно переопределить обработчик ошибок на свой и присоединять доп. информацию. Для этого необходимо переопределить соответвующую директиву в .mango-config

Например, вы можете использовать свой логирующий класс который будет реализовывать интерфейс Log и отправлять логи на почту

Типизация

Используется строгая не статическая типизация. Никаких ===

Для приведения типов используется префиксный оператор (type).

1 == '1' // false
0 == false // false
1 == (int)'1' // true
'' == null // false
'' == (string)null // Ошибка: неприводимые типы

(int)'10' + 10 // 20
(string)10 + 'qwe' // 10qwe

// При этом в объявлении метода можно указывать требуемый тип аргумента:
public fun someName(int a, b) { ... }

Каждый тип данных - объект псевдо-класса

var some = "test";
some.toUpper(); // TEST
"test".toUpper(); // TEST

Инициализатор

Для каждого класса можно написать функции-иницилизаторы Она имеет доступ ко всем приватным свойствам класса.
Как вариант на ее основе сделать синглтон или фабрику.

class A {
	export fun a(string arg1, arg2)
	{
		return new A(arg1, arg2);
	}

    // конструктор класса
    constructor(arg1, arg2) {
        //
    }

	public fun some() : bool
	{
		return true;
	}
}

a("arg", "arg")->some();

Никаких __autoload

При запуске веб сервера происходит предварительная сборка классов в "пакеты". Например класс имеющий следующий путь: project/Folder1/Folder2/Classname.mango будет помещен в пакет Folder1.Folder2.Classname;
При этом есть некоторые пакеты, которые поставляются самим языком, например Mango. Это дает возможность импортировать сразу все классы пакета просто указав *.


use Mango.Request;
use SomeVendor.SomeClass;
use Mango.FilySystem.*;

...

Request.get('attr');

Порядок парсинга файла

В файле недопустим код вне класса или функции. Единственное что допустимо - объявление переменных. В таком случае эти переменные будут приватными константами в области видимости файла

SomeVendor/SomeClass.mango:

var SOME_CONSTANT;

class SomeClass
{
	public fun meth()
	{
		return SOME_COSTANT;
	}
}

Отладка

Встроенная конструкция debug позволяет детализированно просмотреть стек вызовов внутри указанного кода. При запуске отладки, стек выводится на экран или пишется в отладочный .html файл в папке проекта

debug {
	for (var i = 0; i <= 10; i++) {
		dump(i);
	}
}

Набор стандартных пакетов

package Mango {
    package FileSystem {} // работа с файловой системой
    package Network {} // позволяет отправлять http-запросы
    package Database {} // для работы с бд
    package Encryption {} // все для генерации хешей
    package Json {} // для работы с json
    package Xml {}
    package Soap {}
    package Encoding {} // для кодирования файлов, например base64
    package Request {} // для работы с request'ом (get, post, cookies, files, etc)
    package Response {} // для настройки http ответа
    package Cli {} // для работы с консолью
    package Mail {} // работа с почтой
    package Session {} // работа с сессией
    package Date {} // работа с датами
    package Archive {} // работа с архивами
    package Charset {} // работа с кодировками
    package Graphics {} // работа с графикой
}

Удобнейшие инструменты

// Regex:

var some = [];
someTestStringVar.matches('/\d+.\d+.\d+/').each(fun(Mango.Regex.Match item) {
    // пройдет по каждому найденому результату и запишет найденые совпадения
    some[] = item.toString();
});

if ('somestring'.matches('%some regex%')) {
    // любая строка может быть проверена regexp без создания экземпляров
}

--------------------------------------------------------------------------

Гораздо более удобный аналог switch:

int a = 3;
var some = a.match({
    5 => fun () {
        return 'пять';
    },
    a > 10 => fun() {
        return 'много';
    }
});
Интересно Не интересно

+187, -106