Иерархия типов и обобщения

NewLang имеет закрытую систему типов. т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником одного из уже существующих, т.е. расширять один из них. Такой поход напоминает создание классов в языке Java, в котором каждый новый класс имеет в своих родителях класс Object.

С помощью обобщений (generics) можно писать код, который может работать с любым совместимым типом данных.

Фрагмент иерархии типов данных (строки и числа, а в скобках указаны синонимы типов):

:Any -+-> :Arithmetic -+-> :Tensor -+-> :Integer --> :Int64   ...  --> :Int8 --> :Bool
      |                |            |               (:DWord64)        (:Char)
      |                |            |                                 (:Byte)
      |                |            |
      |                |            +-> :Number --> :Float64 --> :Float32 --> :Float16 --> ...
      |                |            |              (:Double)    (:Single)
      |                |            |
      |                |            +-> :Complex ...
      |                | 
      |                +-> :Rational
      | 
      +-> :String -+-> :StrChar
      |            |  (:FmtChar)
      |            |
      |            +-> :StrWide
      |               (:FmtWide)
      |            
      |
     ...


:Any -+-> :Collection -+-> :Tensor ---> Array
      |                | 
      |                +-> :Dictionary ---> Array

:Template<T:Obj>(Arg:type) ::= <T:Obj>(Arg:type){

};

Обобщенные типы

  • :Any - обобщенный тип для всех остальных типов данных
  • :Arithmetic - обобщенный тип для всех числовых типов
  • :Collection - обобщенный тип для всех видов коллекций
  • :Tensor - обобщенный тип для всех коллекций машинных типов
  • :Array - обобщенный тип для всех одномерным коллекций машинных типов
  • :Tensor - обобщенный тип для чисел, которые можно представить в машинном формате
  • :Integer - обощенный тип для всех целочисленных типов данных
  • :Number - обощенный тип для всех чисел с плавающей точкой
  • :Complex - обощенный тип для всех комплексных чисел
  • :String - обощенный тип для текстовых строк

BaseType

ExtraType (для упрощения и оптимизации) Scalar -> Tensor[0] Array -> Tensor[1] String (general) -> (StrChar-> Array:Char, StrWide -> Array:Int32) Format (general) -> (FmtChar-> StrChar, FmtWide -> StrWide)

Any -> Arithmetic -> Integer = :Int64 … –> :Int8 –> :Bool -> Number -> Complex -> Rational

-> Container    -> Dict
                -> Set
                -> Tensor   -> Array (Tensor[1])    ->   Scalar (Tensor[0])
                -> String (StrChar, StrWide) 

Any -> Arithmetic -> (Integer, Number, Complex, Rational) Container -> (Dictionary, Array, Tensor, String)

Any -> Tensor -> Array -> String (StrChar, StrWide) -> Dictionary -> Set -> Plain -> (Enum, Struct, Union, Optional)

Чистые функции или pure functions — это функции, которые при вызове не влияют на состояние программы и не имеют побочных эффектов. Они возвращают значения только на основе входных аргументов и не изменяют их. Признаки чистых функций:

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

Чистота функции контролируется компилятором, но во время выполнения чистая функция ничем не отличается от обычной функции.

Execution Function Corutine

pure() :- { } # Чистая функция (обычная функция во время выполнения) func() := { } # Обычная функция без сохранения состояние между вызовами coro() := { }; # Сохраняет состояние между вызовами

Thread( func: Function ) # функция выполняется в отдельном потоке Async( coro: Corutine ) # Поток выполнения переключается в одном потоке между всеми корутинами ThreadPool( thread: Thread ) # Балансирует нагрузку между потоками

Пул потоков с асинхронными обработчиками (асинхронная матрешка) ThreadPool( Thread( Async( { } ) ) )

:Any -+-> :Arithmetic -+-> :Tensor -+-> :Integer --> :Int64   ...  --> :Int8 --> :Bool
      |                |            |               (:DWord64)        (:Char)
      |                |            |                                 (:Byte)
      |                |            |
      |                |            +-> :Number --> :Float64 --> :Float32 --> :Float16 --> ...
      |                |            |              (:Double)    (:Single)
      |                |            |
      |                |            +-> :Complex ...
      |                | 
      |                +-> :Rational
      | 
      +-> :String -+-> :StrChar
      |            |  (:FmtChar)
      |            |
      |            +-> :StrWide
      |               (:FmtWide)
      |            
      |
     ...

Примеры определения функций с обобщенными типами

    only_int8(arg:Int8):Int8 :=  ... ;   # Функиця принимает и возвращает только :Int8

    any_int(arg:Integer):Integer :=  ... ;  # Функиця принимает и возвращает только целые числа

    any_tensor(arg:Tensor):Tensor :=  ... ;# Функиця принимает и возвращает любые машинные типы чисел
    
    any_any1(arg:Any):None :=  ... ; # Функиця принимает любой тип аргумента и ничего не возвращает 

    any_any_not(arg:<:Arithmetic-:Rational-:Complex>):None :=  ... ; # Функиця принимает любые числа, кроме рациональьных и комплексных и ничего не возвращает 
    any_any_or(arg:<:Integer+:Number>):None :=  ... ; # Функиця принимает только целые числа и числа с плавающей точкой и ничего не возвращает 

    any_any2(arg) :=  ... ;     # Тип не указан - функиця можен принимать и возвращать любой тип