```
func void testFn(var
}
Маска:
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
for(var (i, val) = (key, value) in arr) print(str(i) + " " + val + "\n");
Матрица наследования. Что-то типа паттерна абстрактная фабрика.
парные итераторы, объединённые в один объект. тип одного из них - end
var
Цепочка операций.
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
func shutdown::{var
}
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
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
### Треугольные скобки. <>
Типы пишутся в треугольных скобочках если в его имени есть пробелы. Треугольные скобочки отведены под типы.
var t =
### Квадратные скобки []
Квадратные скобочки отданы под энумерацию, массивы и словари
// Массивы
var
// Пример словаря
var
// Пример простого словаря
var
// Пример мультитипового словаря
let dictType = [(
**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
### Enum
var
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
func change(let
func main()
{
var
### Пропуск параметра функции
В некоторых ситуациях нам надо объявить несколько аргументов. В таком случае на помощь придёт пропуск параметра. Следующий параметр при не указании параметра явно имеет параметр параметр предыдущего. При указании предыдущего параметра как var или var<auto> оба параметра имеют свой уникальный тип при необходимости.
func skip(var
} func main() { skip(1,5); }
### Дефолтные параметры
Мы можем определить умолчательные параметры. В отличие от c++ мы не обязаны указывать умолчательные параметры последними параметрами. Вместо этого мы можем применить символ _ или default слово для передачи вместо значения пустоты с сохранением порядка следования аргументов функции.
func SayBalance(var
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
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
### Захват окружения
func @load(var
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
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
## Циклы
TODO: выбрать формат циклов
### while c++ style
var
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
### 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
Классы по умолчанию имеют private поля, структуры public. Это не единственное различие, см. дальше
### Наследование по спецификаторам доступа
class Base // Родительский класс { // ... } class Child(Base) // Public наследование - члены базы доступны извне {
} class Child2(private Base) // Private наследование - члены базы доступны { // только самому классу
}
### Структуры
### Структуры
В отличие от классов в meta структуры почти всегда POD (Plain old data) - не содержит служебных таблиц, служебных переменных и проч. Структуры обычно передаются по значению по умолчанию.
struct Point3d
{
var
@import mem
func main()
{
let
### Шаблонные классы.
class ArrayT
## Перегрузка операций
struct Vector
{
// тут данные
operation+(var
void test()
{
var
struct ArrTest
{
own var
// конструктор здесь
operation[]get(var
void test()
{
var
Пакетное переименования
Можно сделать венгерскую нотацию обязательной с проверкой компилятором.