Числа

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

Арифметические типы

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

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

Проблемы без знаковых чисел (из интернета):
Во-первых, вычитание двух без знаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как без знаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.

Имена встроенных арифметических типов: :Int8, :Int16, :Int32, :Int64, :Float16, :Float32, :Float64, :Complex16, :Complex32, :Complex64 говорят сами за себя. И хотя среди них присуствуют названия, присущие беззнаковым числам (:Byte, :Word, :DWord и т.д.), они являются синонимами и применяются для взаимодействия с нативным C++ кодом.

Логический тип

Отдельным типом идет логический тип :Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции тоже может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).

// Treat bool as a distinct "category," to be consistent with type promotion
// rules (e.g. `bool_tensor + 5 -> int64_tensor`). If `5` was in the same
// category as `bool_tensor`, we would not promote. Differing categories
// implies `bool_tensor += 5` is disallowed.
//
// NB: numpy distinguishes "unsigned" as a category to get the desired
// `bool_tensor + 5 -> int64_tensor` behavior. We don't, because:
// * We don't want the performance hit of checking the runtime sign of Scalars.
// * `uint8_tensor + 5 -> int64_tensor` would be undesirable.

Индексация тензоров

Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).

В качесте индекса тензора могут быть использованы диапазоны которые обработываются точно так же как и в Python, а так же значение :None и многоточие .... Значение :None, т.е. отсуствие индекса, означает произвольный размер тензора в одном конкретном измерении, тогда как многоточие ... обозначет произвольную размерность в любом количестве измерений (поэтому может встречаться в индексе тензора только однократно).

Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.

Примеры создания тензоров и преобразования их размерности можно посмотреть тут.

Рациональные числа

Для вычислений с неограниченной точностью в NewLang используются отдельный тип - рациональные числа. Они записываются в форме обыкновенной дроби, в которой числитель должен быть целым числом, а знаменатель натуральным (целым без нуля). В качестве разделителя дроби используется обратная косая черта, т.е. 1\1 - рациональное число 1, -5\1 - рациональное числа -5 и т.д.