Синтаксис
type Vector3
def with_y self (y : f32) = Vector3 self.x y self.z
Параметр self предотвращает затенение поля y одноимённым параметром.
let enabled_extension_names = ["VK_EXT_debug_report"
"VK_EXT_debug_utils"
"VK_KHR_surface"
"VK_KHR_xcb_surface"
"VK_KHR_xlib_surface"]
Запятые между элементами массива не нужны, если каждый находится на отдельной строке или строках.
let thickness = (left = border.left
right = border.right
up = border.up
down = border.down)
let size = Atom<(u32, u32) width height> (0, 0)
Имена полей кортежа не влияют на совместимость типов.
val identity = Matrix3 1
m22 = 1
m33 = 1
f@ struct@zero
Задавать значения полей можно позиционно, по имени и с помощью заполнителя. Применимо для создания объектов, инициализации структур, наследования типов и вызова функций. Тип заполнителя должен либо совпадать с типом создаваемой сущности, либо быть кортежем с именованными полями.
let vector = Vector3@ref 1 3 8
Структура инициализируется в куче из-за суффикса @ref. Привязка vector имеет тип mut ref Vector3, что также можно записать как MutRef<Vector3>. Ссылки такого рода по сути являются указателями, которые вместо традиционных для указателей операций дают доступ к полям и методам типа.
text
|> lines
|> filter { line -> line.starts_with "layout" }
|> map { remove_comment _ }
Замыкания создаются с помощью фигурных скобок. Каждое использование подчёркивания возвращает следующий параметр.
filter и map это методы типа List.
object Obs =
def map<T, U> (list : List<T>) (f : T -> U) : List<U> = ...
let squares = numbers |> Obs.map { x -> x * x }
Значение numbers передаётся в функцию Obs.map в качестве первого аргумента.
type Array<T> @byval =
val size : u32
let ptr @param = kedr/alloc<T> size
Атрибут @param делает привязку необязательным именованным параметром конструктора, может также использоваться в функциях.
let up_right = Vector3 left.as<f32> 0 border_z
let adjusted_size = size as f32 * 1.5 |> as<u32>
Преобразование типа можно записать без скобок.
let list @owner = List@mrc.new
Модификатор @mrc, расшифровывается как manual reference counting, даёт доступ к версии типа без автоматического подсчета ссылок. Атрибут @owner гарантирует освобождение памяти перед выходом из содержащей привязку функции, также доступен для полей объектов.
Ключевое слово new используется для типов без параметров конструктора.
import num/vector_f32/Vector3
Vector4
vector_i32/Vector2i
control.set_width width
set_height control.measure_height
arrange
Методы set_width, set_height и arrange вызываются на одной и той же привязке control.
type Entry =
path : String
created : DateTime
| File size : u32
| Directory entries : Slice<Entry>
| Local
| Remote url : String
Entry и Directory это типы-суммы. Структуры File, Local и Remote наследуют поля path и created. Local и Remote также содержат entries.
type CString ptr
fun get (i : u32) = ptr[i]
Значение единственного элемента кортежа привязывается к ptr.
Особые функции определяются через ключевое слово fun, fun get это индексатор.
type Slice<T> @byval =
val ptr : Ptr<T>
val size : u32
type MutSlice<T> @byval @[mut_of Slice] =
val ptr : MutPtr<T> @impl
inherit Slice<T>
Поле ptr имеет разные типы для Slice и mut Slice.
type Object =
var room : Room @late
Привязка room не является параметром конструктора, вернёт ошибку при попытке чтения до присвоения значения.
# Однострочный комментарий
/* Многострочный комментарий */
Закрывающая часть многострочной лексемы не обязательна.
Видимость и изменяемость
val определяет привязку, var — изменяемую привязку, def — функцию, let — привязку или функцию, доступную только в текущем файле.
var align_h @mut = AlignH/Stretch
val items @mut = List<Control>.new
У типа List есть изменяемая версия mut List. Тип только для чтения нельзя снова преобразовать в изменяемый.
Без атрибута @mut по окончании файла привязка align_h превратится в только для чтения, а items получит тип List<Control> вместо mut List<Control>.
var size : u32 @[mut internal] = 0
Аргумент атрибута @mut уточняет область изменяемости привязки.
type Grid @mut =
var count : u32 = 0
var distance : u32 = 0
Поля становятся изменяемыми повсеместно по-умолчанию благодаря атрибуту @mut на уровне типа.
begin@ editor
type Editor =
var count : u64 = 0
local mut should_separate = false
let rectangle = Rectangle.new
end@ editor
editor это логический файл. За пределами editor привязка count становится только для чтения, а should_separate не видна. rectangle становится недоступной, когда заканчивается либо editor, либо физический файл.
internal@
var array = Array<T> 0
Помимо ключевых слов let и local, видимость элементов также ограничивается с помощью директив: private@ — внутри файла, local@ — внутри логического файла, internal@ — внутри ящика, protected@ — внутри иерархии.
Примесь
type Control @abstract =
def measure (w : u32) (h : u32)
def arrange
type SingleChildLayout @mixin =
require Control
def Control.measure w h =
measure_single_child self w h
def Control.arrange =
arrange_single_child self
type Button =
inherit Control
include SingleChildLayout
Control объявляет абстрактные методы measure и arrange.
Примесь SingleChildLayout может быть включена только в тип, наследующий Control.
Button получает содержимое SingleChildLayout, но связь наследования между типами не создаётся.
Обобщённое объявление
object Kd =
def hash<T> @decl (x : T) (state : HashState)
def Kd.hash @impl (x : bool) state =
let i = if x then 1 else 0
Kd.hash<i32> i state
Специализации функции Kd.hash задаются отдельно для каждой комбинации типов аргументов.
Прикреплённые функции
type Control =
var width : u32 = 0
var min_width : u32 = 0
var max_width = u32.max
coerce@ width { _.clamp min_width max_width }
Значение поля width всегда будет находиться в диапазоне между min_width и max_width.
observe@ width { _ w ->
let event = SizeEvent/Width w
push event }
Замыкание вызывается после каждой записи в поле.
Внедрение зависимостей
type Selector =
let overlay : Overlay @auto
let overlay @publish = display.overlay
let selector = Selector.new
Привязки с атрибутом @auto получают значения из опубликованных привязок при соответствии имён и типов.
Дерево объектов
let stack = Stack
align_h = AlignH/Left
items <- margin, text_block
run@ set_fixed_width 200
Выражение создаёт новый объект Stack, присваивает AlignH/Left его полю align_h, добавляет margin и text_block в список items, вызывает метод set_fixed_width.
stack
align_v = AlignV/Center
is_horizontal = true
Мы заменили имя типа именем привязки, поэтому вместо нового объекта возвращается stack.
let border = Border.new
let stack = Stack.new
border
stack
Button
text = "save"
on_press <- { save_current_file }
Button
text = "load"
on_press <- { show_load_dialog }
Объект stack присваивается полю border.content, кнопки добавляются в список stack.items. Поля content и items обозначены атрибутом @dst.