Brein strom

``` func void testFn(var a) : a == null => {print("Null check failed")} {

}

Маска:

let const y = 0x2a; let mut x = mask::hex! 0xff(y : 1 byte); // x == 0xff2a

let const z = 523; let mut k = mask::dec! 1(z : 000..999)000; // k == 1523000

let const b = 0b111; let mut s = mask::bin! 0b10(b : ); // s == 0b10111

Перегрузки && и const в одной мета-функции.

Переопределение оператора выделения памяти для использования 
вместо стандартных вещей кустомных алокаторов.
Кустомные аллокаторы в стандарте.

isCastableTo

Итерируемый энум+
Тип хранилища обектов с ссылками на хранимые объекты.

Возможность создания абстрактных классов. Выделяется память и частично инициализируется. Потом когда присваиваем объект выполняется всё остальное.
Для этого нужно знать есть ли у класса наследники.

Знание о иерархии наследования. Плюс неизвестные на момент компиляции
наследники, но известные в рантайме.

Шаблоны имплементации базовых вещей в стандартной библиотеке. 
Например шаблон массива или списка.

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

Список исключений в объявлении функции.

Запрет присвоения лвалью и рвалью.

`ptr to int`
Выделение в статической памяти.

Упрощённый формат перебора в циклах.
`for i in range(arr) // где arr - массив (без размера) i - число`
`for curr in arr // где arr - масмсив, curr - элемент`

Модификатор `const::strict` который говорит что значение нельзя менять.

несколько наборов аргументов в функции разделенные знаком ;
func(;;) несколько групп возврата/вызова

Что-то типа списка инициализации но круче.
Разделение больших чисел `var a = 1_000_000;`

Замыкания как в раст.

Тип объекта который включает в себя несколько других, например
строка и строка самописная (такой объект константен)

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

Тип `smart_string` - накапливает конкатенации и
прочие операции и выдаёт результат по запросу.
Требует поддержки компилятора.

Выбор модели безопасной памяти. Время жизни/сборщик мусора/умные указатели/сырое выделение.

`var<ptr to int>

По умолчанию функции не должны выкидывать исключений,
исключения надо включать.

Универсальный механизм исключений/возврата кода операции.

Все функции по умолчанию explicit но можно это отключать.

Виртуальный деструктор по умолчанию для абстрактных классов.

Сделать что-то с вызовом виртуальных функций в конструкторах/деструкторах.

Операторы скоупа - они могут пересекаться частично и нужны для описания
границ действия к примеру локов мьютекса.

Дополнительные функции-операторы. Например `if (a ==::precise b)`

Спецификатор размера переменной. `123i32`, `0x23i8`

Тип if-а `if::strict(func1() and func2())`  `if::loose(func1() and func2())`
`strict` - Выполнять все функции даже если в этом нет смысла
`loose` - Оптимизировать

Строгое и нестрогое правило типизации 
можно варьировать`variable :` 
строго `variable !:`

Nodiscard.

Несколько групп аргументов в функции.


**same type** в шаблонах.

Возможность адекватно вызывать виртуальную функцию в 
конструкторе/деструкторе.

Возможность использовать умные указатели в конструкторе (передавать куда-то).

Перегрузка функции по имени. `shutdown::reboot();`

параметры по умолчанию для виртуальных функций.

Битовые маски и структуры двойного назначения - когда
под капотом 1 переменная в которой хранится значение 
разных переменных из одной структуры. Можно например
делать указатель для CAS (compare and exchange) мульти
поточных программах.

опциональные и обязательные подвиды параметров.
например `__forceinline` и `inline`

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

обращение к членам класса через `this.` а  к глобальным данным через 
`global.`

atomic register

битовые флаги в if и switch. Битовые флаги в enum

assert

Тип энумов, итерация по ним.

переобъявления переменных - задание другого типа

`volitile` переменная - доступная из разных потоков и единиц трансляции.
`memonly` переменная - не оптимизировать переменную для хранения 
в регистрах (как vilitile в c++)

Слово final запрещающее перегрузку и наследование.

Переменные с ограниченным диапазоном значений и ограничителями.

`.` и `->` при обращении к объектам имеют разный смысл

`new() delete()` и `new_raw() raw_delete()`

`sort( arr, {>} )` `map({>= 10})

при определении в определении метода дефолтного аргумента
иметь возможность определить в реализации если они полностью совпадают

область видимости при подключении библиотек

слова in out

несколько типов исключений - warning и error

слово final

local global переменные

объявление членов классов в конструкторе как в питоне

interface в классах

авто генерация хэдера. специфиатор public/private для включения
выключения в хэдер символов

extends и implements в классах

пояснение сохранения - перемещение, копирование, клонирование
копирование - полностью копировать, клонирование - копировать умно

Каждый метод получает на вход в подблок аргументов такие вещи как ссылку на окружение с помощью которого функция может захватывать глобальную область видимости func( environment, this ; )
Тое

явный this как self в питоне чтобы видеть члены без венгерской нотации

дефрагментация кучи

конец жизни переменной после её последнего использования а не в конце скоупа как в раст или в с++ сейф поинтеров

аналог make встроенный

вложенные энумы

формат ip адреса

тип процентов

Оператор `#` тега который позволяет писать строки но без `" "` в виде просто имён типов.


мультикоманда - как когда в sh пишешь `rm *` и это преобразуется в несколько удалений, т.е. одна и та же строка делается с несколькими аргументами. Что-то похожее будет прикольно.

print( #for<0,5>.value ) // 01234

Данный код эквивалентен 5ти вызовам функции print с числами от 0 до 4х включительно

Решить - лучше foreach или for для работы с генератором

стримы символов как в c++ (iostream etc)

стандартная либа для безопасной работы с SQL запросами

отладчик - не заходить куда-то

вместо using как в c++ @names.extend(#nameOfNamespace)

Доступ к закрытым членам при тестах (возможно плохое решение)

Передавать this явно как в питоне и если не передавать считать функцию статичной

битовые маски и доступ к отдельным битам

проверка типов статика/рантайм. Например диапазон значений. при выходе за пределы - эксепшон.

int<@max = 256> a;

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

сдвиги бит - стандартный и циклический

проверка функционала рантайм/статика (какие возможности поддерживаются)

авто алиасы к именам типов ("aVal" == "aval" == "a_val")

отладчик: супер юнит тесты - отладчик джелает копию памяти приложения, делает шаг, записывает, возвращает в исходное положение

отладчик: подробный визуальный разбор того как вычислилась строка.

Доступ к члену-функции как к переменной (как в c#). Различные режимы для этого доступа. Например readonly или full.

Оператор возврата error

Бесшовный переход от исключений к возврату ошибки значением

Циклы как функции.

for([{int i = 0}, {i < 10}, {i++}],{print(i);}); for([pre : {int i = 0}, cond : {i < 10}, op : {i++}],{print(i);});


for(var i = 0, var j = 0 | i < 3, j < 5 | iter(i,j)) print(str(i) + str(j)) // 00 // 10 // 20 // 01 // 11 // 21 // ...


var arr = ["a","b","c"]; for(var i = key(), var val = value() | none | in arr) print(str(i) + " " + val + "\n"); // 0 a // 1 b // 2 c

for(var (i, val) = (key, value) in arr) print(str(i) + " " + val + "\n");

Матрица наследования. Что-то типа паттерна абстрактная фабрика.

парные итераторы, объединённые в один объект. тип одного из них - end

var f = "%%dd.%%mm.%%yyyy".format.char(["d" = 10, "m" = 8, "y" = 2024]) print(f) // напечатает 10.08.2014

Цепочка операций.

var v = input() >> parse() >> set();

Спецификаторы доступа для импорта модулей. Возможность ограничить область видимости местом кода, в которую непосредственно импортируется модуль. (в c++ можно импортировать хэдеры в cpp файле, так, что они не попадут в хэдер)

isolate функции. функции которые игнорируют глобальные переменные. В переменную передаётся только то, что поступает в качестве аргументов.

default тип присваивания при инициализации. если переменной присваивается дефолт - она не инициализируется

Операция yield как в питоне - пауза в вызываемой функции и возврат значения.

Должно быть легко переходить от "исключения c++ стиль" к "ошибки С стиль". Отдельный оператор возврата из функции.

null - тип данных. Любая переменная может быть помечена как null-able. Тогда к ней может быть добавлена bool переменная под капотом, которая говорит о том, что значение null. В некоторых случаях для этого может быть использовано одно из значений переменной, например для указателя (нулевой указатель). Разные переменные могут зависить от одной переменной к которой применяются битовые операции.

В коде сделать функцию-друг для выставления параметров класса (включая закрытые)

Ключевые слова

$ptr == $variable

@ - символ захвата окружения, распаковки. пример:

// Выделение памяти со сборкой мусора var a = new::@gc(num); // Импорт кода в пространство модуля @import("console")

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

:: - символ добавленного имени. Этот символ позволяет объединять в одну логику работы разных функций, при этом мы можем пользоваться такой функцией точно также, как если бы мы написали её имя слитно, без этого символа.

var shType = [reboot, shutdown, sleep];

func shutdown::{var op}() { if (op == "reboot" or shType::reboot) reboot(); else if (op == "shutdown" or shType::shutdown) shutdown(); else sleepMode();
}

func main() { shutdown::reboot(); shutdown::"reboot"(); // Функции делают одно и то же shutdown::{"reboot"}();

    var<string> reb = "reboot";
    shutdow::{reb}();

}

~ - символ повторения имени или классификатора. Повторяет последнее имя ещё раз.

func f(var a, var b) { // ... }

func main() { var a,b; f(::a = ~, ::b = ~); // Эквивалентно f(::a = a, ::b = b); }

var - объявление переменной

var a = 10; var b = 10;

let - ссылка на переменную

var a = 10; let b = a;

ptr - указатель

var p; ptr p2 = p; var a = 10; p = a; print(p2) // 10

ref - тоже что-то такое

auto слово. Авто выводит 1 уровень в иерархии типизации.

var> a = [1,2,3,4,5]; var> a2 = a;

### Треугольные скобки. <>

Типы пишутся в треугольных скобочках если в его имени есть пробелы. Треугольные скобочки отведены под типы.

var t = ; // В переменной t хранится тип знаковое целое var t2 = 10; // В переменной t2 хранится значение 10 типа sign int var t3 = 10; // В перменной t3 хранится значение 10 типа t (sign int)

### Квадратные скобки []

Квадратные скобочки отданы под энумерацию, массивы и словари

// Массивы var> a = [0,10,20,30,40,50]; print(a[3]) // Напечатает 20

// Пример словаря var> m; m.append("first", 10); var n = m["first"] print(n) // Напечатает 10

// Пример простого словаря var> d = ["key1" : 10, "key2" : 20, "key3" : 30] print(d["key3"]) // напечатает 30

// Пример мультитипового словаря let dictType = [(,),(,)] // Возможные комбинации // ключ-значение var> d = ["key1" = 10, "key2" = 20, 3 = 30] print(d[3]) // напечатает 30

**TODO**: добавить способ безопасного обращения к элементу

### Фигурные скобки {}
Фигурные скобки отданы под блоки кода.

func f() { // блок кода функции }

### Круглые скобки ()

Круглые скобки выделены под передачу параметров функции.

functionCall() { return ("Hello", "world"); }

var a = functionCall(); // вызов функции print(a) // выведет hello world

exist()

Проверяет существует ли объект

obj.exist() // true false

# Типы данных

### Неделимые типы

Базовые типы более не делимы.

num - любое число

cptr - указатель в C стиле. (void*)

carr - массив в C стиле (без указания размера)

cchar - символ в C стиле (без указания кодировки)

cstring - строка в C стиле. Массив cchar (без указания кодировки)

### Общие типы кроме неделимых

bool - булев тип. Подтип int

string - строка. Строка имеет указание на кодировку. Можно глобально задать какую-то одну кодировку для строки в пределах проекта, модуля или функции. Или информацию о кодировке хранить в самом объекте строки.

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

arr<t, n> - массив t типа, n размера

ptr<t> - указатель на t тип

### Подтипы num

int - целочисленное

real - дробь

### Подтипы cchar

basicChar - аналог char в c++

wideChar - аналог wchar_t в c++

вместо этого можно использовать подтип int

### Подтипы real

floating - подтип real дробь, плавающая точка

decimal - подтип real, фиксированная точка

### Подтипы int

sign - cо знаком

unsign - беззнаковое

### Подтипы размера int:

Основные:

byte - 8 бит

word - 16 бит

dword - 32 бит

qword - 64 бит

dqword - 128 бит

Дополнительные:

bit - 1 бит. Используется в битовых масках

bits<n> - n бит. Например bits<128>

bytes<n> - n байт. например bytes<4>

### Подтипы размера real

single - 32 бит

double - 64 бит

ldouble - 80 бит

### Алиасы

i8, i16, i32, i64, i128 - int

u8, u16, u32, u64, u128 - unsigned

r32, r64, r80 - real

### Масштабирование числом

byte<2> - word

word<4> - qword

etc.

### Проверка наличия типа и размеры

dqword.isExist()

qword.max()

<sign dqword>.min()

### Хранимые и исполняемые

Фундаментальные типы данных могут быть определенны как хранимые в памяти и как исполняемые процессором непосредственно, например может быть тип в памяти 32 бита, а исполнятся операция будет как 64 битное, т.к. лежать это будет в большем по размеру регистре, чем то, что лежит в памяти. То же самое справедливо и для значений с плавающей точкой. Это используется исключительно компилятором и почти никем больше.

### Переопределение базовых типов

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

Сделать это можно вот так:

class newDword { ... } let dword = newDword;

Если нам нужно обратиться к “настоящему” типу следует писать имя типа с подчёркиванием спереди. Например: _dword

### Особые символы

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

Например:

var a = "\endl"; // Символ/символы конца строки var b = "\\endl"; // строка \endl var c = "\n" // Символ конца строки, unix стиль var d = "\{0x2012}"; // Символ юникода var e = "\\" // обратный слеш

### Enum

var eSimpleEnum = enum[a,b,c];

var t = eSimpleEnum::a;

### Агрегатные типы

Агрегатные типы: Слева тип, справа пример объекта

- enum - enum[a,b,c]

- dict<string,int> - dict<string,int>[”a” : 10,“b” : 20,“c” : 30 ]

- dict - dict[1:”asd”, ]


## Выводимые и динамические типы auto и any

В языке есть 2 сущности с похожим поведением.

Это auto и any

auto соответствует auto в c++, то есть тип выводится, но при этом существуют ограничения. В случае auto код будет работать так, словно на этапе компиляции мы бы уже знали тип и просто вписали бы его место auto.

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

# Функции

### Передача по значению / ссылке

func noChange(var a) // передача по значению { a += 20; }

func change(let a) // передача по ссылке { a += 10; }

func main() { var a = 10; change(a); out << a << endl; // Выведет 20 noChange(a); out << a << endl; // Выведет 20 }

### Пропуск параметра функции

В некоторых ситуациях нам надо объявить несколько аргументов. В таком случае на помощь придёт пропуск параметра. Следующий параметр при не указании параметра явно имеет параметр параметр предыдущего. При указании предыдущего параметра как var или var<auto> оба параметра имеют свой уникальный тип при необходимости.

func skip(var a, b) // a и b оба типа int {

} func main() { skip(1,5); }

### Дефолтные параметры

Мы можем определить умолчательные параметры. В отличие от c++ мы не обязаны указывать умолчательные параметры последними параметрами. Вместо этого мы можем применить символ _ или default слово для передачи вместо значения пустоты с сохранением порядка следования аргументов функции.

func SayBalance(var name = "John", var balance = 10) { cout << "Hello " << name << " balance " << balance << endl; }

func main() { // Все функции вывдут "Hello John balance 10" SayBalance("John", 10); SayBalance("John"); SayBalance("John", ); // скип 2го параметра SayBalance(, 10); // скип 1го параметра SayBalance(,); // скип 1го и 2го параметров SayBalance(); // скип обоих параметров SayBalance(_); // скип обоих параметров // То же самое но с default
SayBalance(default, default);
SayBalance("John", default);
SayBalance(default, 10); }

### Именованные параметры

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

func SayHello(var name, var last) { cout << "Hello " << name << " " << last << endl; }

func main() { SayHello("James", "Bond"); // ok SayHello(::name = "James", ::last = "Bond"); // ok SayHello(::last = "Bond", ::name = "James"); // ok SayHello("James", ::last = "Bond"); // ok SayHello(::name = "James", "Bond"); // ok SayHello(::last = "Bond", "James"); // error - позиционирование нарушено }

### Передача типа в функцию

func function(var a) { var t = a.type(); }

// Количество параметров типа должно быть // равно числу параметров func function2(var a) { var t = type; }

func main() { var a = 10; function(a); function2(a); }

### Захват окружения

func @load(var moduleName) { var loadedModuleName = moduleName; // Написаное здесь исполняется в вызывающей // функции }

func main() { @load("TestModule"); print(loadedModuleName); // Напечатает "TestModule", т.к. функция @load объявляет // эту переменную в текущем контексте }

Это прямой аналог препроцессорных директив в C/C++.

Некоторые функции требуют вызова именно таким способом, например функция new::@gc(num) выделяет память, управляемую сборщиком мусора. Соответственно сборщик мусора должен знать где находятся вхождения переменных для сборки мусора.

### Распаковка параметров в функции

func unpack(var a, var b) { print(a + b); } func test_1() { var arrToUnpack= [5,10]; unpack(@arrToUnpack); // Выведет 15

    var<dict> dicToUnpack = ["a" = 5, "b" = 10];
    unpack(@dicToUnpack); // Выведет 15

    var<enum> e = enum [a, b];
    var<dict<enum, int>> arrToUnpack = [e::a = 5, e::b = 10];
    unpack(@arrToUnpack); // Выведет 15

    var<type> params = struct
    {
        var<int> a,
        var<int> b
    }
    var<params> structToUnpack = [5,10];
    unpack(@structToUnpack); // Выведет 15

}

# Операции и циклы

### Инициализация

Инициализация нескольких переменных

var a,b,c = "Test"; // a,b,c будут равны "Test"

Инициализация нескольких переменных каждая в отдельности

var {a,b,c} = 1,5,10; // a == 1 b == 5 c == 10

Хранение кортежа

var multiple = @{1,5,10}; var {a,b,c} = @multiple; // a == 1 b == 5 c == 10

## Циклы

TODO: выбрать формат циклов

### while c++ style

var iterate = true; while(iterate) {

iterate = false;

}

### for c++ style

for(var i = 0; i < 5; i++) { print(i * 10); // 0, 10, 20, 30, 40 }

### foreach c++ style

foreach(var i : a) {

}

### meta

### foreach

Наиболее удобный и предпочтительный формат итерации. В первой половине круглых скобочек мы указываем переменные, в которые мы будем получать текущее значение, вторая половина, отделённая знаком : это генератор значений итерации.

foreach (var i : range(0,5,1)) { print(i) // 0, 1, 2, 3, 4 }


var arr = ["a", "b", "c"]; foreach (var i : arr) { print(i) // a b c }


var arr = ["a", "b", "c"]; foreach (var i : index(arr)) { print(i) // 0, 1, 2 }


var arr = ["a", "b", "c"]; foreach (var i, var val : enumerate(arr)) { print(i, " ", val) // 1 a, 2 b, 3 c }

### for

for (var = 0; var < 5; var++) { print(var); // 0, 1, 2, 3, 4 }

### while

var it = true; while(it) { it = false; }

### switch

Оператор switch аналогичен такому же в C. С той разницей что по дефолту мы выходим из блока case и если мы хотим продолжить двигаться вниз нам нужно ключевое слово continue_switch

switch (a) { case 0: { // блок кода операнда свитч } case 1: { continue_switch; // Если мы попали в 1 кейс то после этой // операции мы продолжим двигаться вниз
} case 2: {

}

}

# Классы

### Доступ

### Спецификаторы доступа в классах и структурах

1. public - члены доступные извне и изнутри, в дочерних классах

2. private - члены доступные только изнутри, в дочерних классах (protected c++)

3. own - члены доступны только изнутри. (private c++)

class Test { public: function Test() { a = 10; b = 15; }

private:
var a;

var b; public var c; }

func main() { var test; // ok конструктор test.c = 20; // ok test.a = 30; // error }

Классы по умолчанию имеют private поля, структуры public. Это не единственное различие, см. дальше

### Наследование по спецификаторам доступа

class Base // Родительский класс { // ... } class Child(Base) // Public наследование - члены базы доступны извне {

} class Child2(private Base) // Private наследование - члены базы доступны { // только самому классу

}

### Структуры

### Структуры

В отличие от классов в meta структуры почти всегда POD (Plain old data) - не содержит служебных таблиц, служебных переменных и проч. Структуры обычно передаются по значению по умолчанию.

struct Point3d { var x,y,z; // num гарантирует что тип будет числовым }

@import mem func main() { let> vec = [0,12,-2]; // используем // ... // mem.erase(vec) // обнуляем структуру (не очень хорошо но быстро) }

### Шаблонные классы.

class ArrayT { // Здесь используем type и size как хотим };

## Перегрузка операций

struct Vector { // тут данные operation+(var a,b); operation-(var a,b) { operation+(a, -b) }; operation(var a, var b); // скалярное произведение operationcross(var a,b); // векторное произведение }

void test() { var a(1,0,0); var b(0,1,0); var c; c = a + b; // 1, 1, 0 c = a * 10; // 10, 0, 0 c = a *cross b; // 0, 0, 1 }


struct ArrTest { own var> data;

// конструктор здесь

operation[]get(var i) { return data[i]; } operation[]set(var i, var dataToSet) { data[i] = dataToSet; } }

void test() { var a = [1,3,5]; print(a[1]); // print 3 a[1] = 10; print(a[1]); // print 10 } ```

Редактор

Пакетное переименования

Прочее

Можно сделать венгерскую нотацию обязательной с проверкой компилятором.