# Скриптовый язык программирования Gentee

Документация по языку программирования Gentee.

Gentee является строго-типизированным процедурным языком. В первую очередь, он предназначен для написания скриптов с целью автоматизации повторяющихся действий и процессов на компьютере. Язык имеет простой синтаксис, лёгок в изучении и сопровождении.

**GitHub репозитарий:** [**https://github.com/gentee/gentee**](https://github.com/gentee/gentee)\
**Скачать для Linux, macOS, Windows:** [**https://github.com/gentee/gentee/releases**](https://github.com/gentee/gentee/releases)\
GitHub репозитарий документации: [https://github.com/gentee/docs-gentee-ru](https://github.com/gentee/docs-gentee-ru/)\
Язык разработки: Go

```go
run : ||"Привет, мир!\r\n"
```

```go
run : $ echo "Привет, мир!"
```

```go
run {
    str name = ReadString(`Укажите ваше имя: `)
    Println(`Привет, %{ ?(*name>0, name, `мир`) }!` )
}
```

Хотите посмотреть пример приложения, которое успешно использует язык программирования Gentee? Взгляните на [**Eonza**](https://www.eonza.org/ru/) - бесплатная кроссплатформенная программа для легкого создания и управления скриптами.

## Документация

* [Gentee Programming language (English)](https://docs.gentee.org)
* [Язык программирования Gentee (Russian)](https://ru.gentee.org)


# Синтаксис языка

Описание синтаксиса и конструкций скриптового языка программирования Gentee.


# Лексические элементы

Исходный код должен быть в кодировке UTF-8. Синтаксис описан с использованием расширенной формы Бэкуса-Наура.

```go
newline        = 0x0A
unicode_char = /* Unicode code point */
unicode_linechar  = /* Unicode code point except newline */ 
unicode_letter = /* a Unicode code point classified as "Letter" */
letter        = unicode_letter | "_"
decimal_digit = "0" … "9" 
octal_digit   = "0" … "7" 
hex_digit     = "0" … "9" | "A" … "F" | "a" … "f" 
decimals  = decimal_digit { decimal_digit }
exponent  = ( "e" | "E" ) [ "+" | "-" ] decimals
```

## Комментарии и замена символов

Имеются следующие типы комментариев и автоматически заменяемых символов

`// Однострочный комментарий`\
Однострочный комментарий начинается с двойного слеша `//` и заканчивается символом перевода строки *newline*.

`/* Общий комментарий */`\
Общий комментарий начинается с комбинации / *и заканчивается* /. Такие комментарии могут вставляться где угодно.

`# Заголовок`\
В начале скрипта можно указать данные для использования в других программах. Такие комментарии должны идти подряд в каждой строке от начала скрипта. Можно не указывать '#' в начале каждой строки, а вставить **###** перед и после текста.

```go
#!/usr/local/bin/gentee
# первая строка может использоваться для запуска скрипта в Linux.
###
  desc = Description of the script
  result = ok
  var = value
###
```

**;**\
Символ перевода строки служит разделителем между выражениями и управляющими конструкциями. Точка с запятой заменяется на перевод строки. Таким образом, вы можете использовать точку с запятой, если вы хотите разместить несколько выражений на одной строке.

**:**\
Двоеточие заменяется на открывающую фигурную скобку и вставляется закрывающая фигурная скобка в конце текущей строки.

```go
// эти примеры эквивалентны
if a == 10 : a = b + c; c = d + e 

if a == 10 
{
   a = b + c
   c = d + e
}
```

## Идентификаторы

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

```go
identifier = letter { letter | unicode_digit }
IdentifierList = identifier { identifier }
```

Имеется несколько предопределённых идентификаторов и ключевых слов. Следующие слова зарезервированы и не могут быть использованы в качестве идентификаторов.

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

**catch const elif else false for func go if in local recover retry return run struct true try while**

## Литералы

Целочисленный литерал - это последовательность цифр представляющая целочисленное число (константу).

```go
decimal = ( "1" … "9" ) { decimal_digit } 
octal = "0" { octal_digit } .
hex = "0" ( "x" | "X" ) hex_digit { hex_digit } 
integer = decimal | octal | hex
float = decimals "." [ decimals ] [ exponent ] | decimals exponent
```

```go
0x34Fab
0722
19023862
0.123e+3
234.e-2
9.7732E-1
0.0177E+2
5e-2
```

Символьный *char* литерал служит для идентификации Unicode символа. Вы можете указать один конкретный символ или последовательность символов начинающуюся с обратного слеша заключенные в одинарные кавычки. Последовательность символов с обратным слешем может иметь несколько форматов:

```go
'\r',  '\n',  '\t', '\"', '\'', '\\' 
\xa5 \x2B  (\x + two hex_digit)
\u03B1  (\u + four hex_digit)
\0371  (\0 + three octal_digit)
```

```go
byteVal  = octalStr | hexStr .
octalStr = `\` "0" octal_digit octal_digit octal_digit .
hexStr   = `\` "x" hex_digit hex_digit .
uShort   = `\` "u" hex_digit hex_digit hex_digit hex_digit .
uLong    = `\` "U" hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit .
escapedChar     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | `"` ) 
charLit         = "'" ( unicode_char | uShort | uLong | escapedChar | byteVal | `\'`) "'" .
```

Имеется два типа строковых литералов. 1. Строка в обратных кавычках может содержать любые символы. Если нужно указать обратную кавычку, то нужно удвоить её. 2. Строка в двойных кавычках также может содержать любые символы (в том числе перенос строки), но у неё имеется управляющий символ в виде обратной косой черты. Вы можете указывать после обратной косой черты следующие символы

```go
\a   U+0007 alert or bell  
\b   U+0008 backspace  
\f   U+000C form feed  
\n   U+000A newline  
\r   U+000D carriage return  
\t   U+0009 horizontal tab  
\v   U+000b vertical tab  
\\   U+005c backslash  
\"   U+0022 double quote
```

```go
stringLit         = stringBackQuote | stringDoubleQuote
stringBackQuote   = "`" { unicode_char | "%{" Expression "}" | "${" identifier "}" } "`"
stringDoubleQuote = `"` { unicode_char | uShort | uLong | escapedChar | byteVal | "\{" Expression "}" } `"`
```

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

```go
`10+20 equals %{10 + 20}. User name is "%{USERNAME}"`
"This is the first line.\r\nThis is \{ `the` + `second`} line."
```


# Типы

## Определение типа

Тип описывает множество значений, которые имеют одинаковые операции и функции специально для этих значений. Тип определяется именем типа. Ассоциативный массив *map* - это группа элементов одного типа к которой можно обращаться по строковому индексу. Каждый элемент имеет соответствующий уникальный строковый ключ. По умолчанию, массивы *arr* и *map* состоят из строк, но вы можете указать любую вложенность типов, разделив их точкой. Следует заметить, что переменные типов **arr**, **map**, **buf**, **set**, **obj** и типов определенных с помощью **struct**, в отличии от прочих типов, передаются по ссылке, а не по значению. Это значит, что если внутри функции вы изменили значение такого параметра, то у вас изменится оригинальная переменная.

```go
TypeName  = identifier  { "." identifier }
```

Язык Gentee содержит следующие предопределенные типы.

**arr bool buf char error finfo float handle int map obj range set str time trace thread**

| Имя        | Описание                      | Значения                                        | Начальное значение                |
| ---------- | ----------------------------- | ----------------------------------------------- | --------------------------------- |
| **int**    | 64-bit целочисленный тип      | -9223372036854775808 .. 9223372036854775807     | 0                                 |
| **float**  | 64-bit тип с плавающей точкой | 2.22 E–308 ..    1.79 E+308                     | 0.0                               |
| **bool**   | логический тип                | *true* or *false*                               | false                             |
| **str**    | строка                        | последовательность байт                         | пустая строка                     |
| **char**   | Unicode символ                | Unicode символ int32                            | пробел                            |
| **arr**    | массив                        | массив элементов                                | пустой массив строк               |
| **map**    | ассоциативный массив          | ассоциативный массив элементов                  | пустой ассоциативный массив строк |
| **buf**    | массив байт                   | последовательность uint8                        | пустой массив                     |
| **set**    | массив bool                   | последовательность uint64 по 1 биту на значение | пустоe множество                  |
| **obj**    | объект                        | int, bool, float, str, arr.obj, map.obj         | nil                               |
| **handle** | скрытый тип                   | любые типы на Go                                | nil                               |

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

```go
arr.map.int a
map.arr.str b   // the same as map.arr b
map.bool c
arr.int  d
```

## Приведение типов

В языке Gentee отсутствует автоматическое приведение типов. Для основных типов имеются функции конвертирования из одного типа в другой, их имена совпадают с именем результирующего типа.

|       | int       | bool       | str             | char     | float      |
| ----- | --------- | ---------- | --------------- | -------- | ---------- |
| int   |           | int(false) | int("-23")      | int('A') | int(3.24)  |
| bool  | bool(1)   |            | bool("0")       |          | bool(1.1)  |
| str   | str(20)   | str(false) |                 | str('z') | str(5.662) |
| char  |           |            |                 |          |            |
| float | float(10) |            | float("-2E-34") |          |            |

```go
int(false) // = 0           
int(true) // = 1    
bool(0) // = false  
bool(0.) // = false
bool(integer except zero) // = true    
bool("")  bool("0") bool("false") //=false
bool("not empty, zero or false string")   //=true
```

## Структурные типы

Вы можете определить структурный тип с помощью ключевого слова **struct**. Укажите имя типа после ключевого слова и перечислите типы и имена полей внутри фигурных скобок. Все поля в переменной структурного типа инициализируются автоматически. Все переменные таких типов при передаче в функции передаются по ссылке, а не по значению. Для присваивания или получения значения поля, укажите его имя после точки.

```go
structDecl = "struct" identifier "{" FieldDecl { newline  FieldDecl } "}"
FieldDecl = TypeName identifier
FieldExpr = PrimaryExpr "." identifier
```

```go
struct my : int ID; str name
struct myStruct {
      int ID
      my myval
      arr st_arr
      map.int st_map
}
run int {
    myStruct ms
    ms.ID = 20
    return ms.ID * 2
}
```

## Тип функции

Язык Gentee позволяет работать с идентификаторами функций. Вы можете получить идентификатор функции, передать его в качестве параметра и вызвать соответствующую функцию. Для работы с идентификаторами функций вы должны определить тип функции с помощью ключевого слова **fn** и указать типы параметров и возвращаемого значения. Для получения идентификатора функции укажите **&имяфункции.fnтип**. Идентификатор функции может передаваться в параметрах или присваиваться переменной соответствующего типа. Для вызова функции по её идентификатору достаточно указать имя переменной и круглые скобки с параметрами, как при вызове функции по имени.

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

* Встроенные функции.
* Функции с переменным количеством параметров.
* Функции с опциональными переменными.

```go
fnDecl = "fn" FnName [FnParameters] [ TypeName ]
FnName = identifier
FnParameters     = "(" [ FnParameterList ] ")"
FnParameterList  = TypeName { [","] TypeName }
FnIdent = "&" FuncName "." FnName
```

```go
fn bin( int int ) int
func add( int i, int j ) int : return i + j
func sub( int i, int j ) int : return i - j
func mybin(int i j, bin f ) int : return j + f(i, j)

run int {
  bin isub = &sub.bin
  return mybin(1, 2, &add.bin) + mybin(3, 7, isub)
}
```


# Описания

## Описание констант

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

```
ConstDecl      = "const" ( ConstIota | ConstExp )
ConstIota = Expression "{" { IdentifierList newline } "}"
ConstExp = "{" { identifier "=" Expression newline } "}"
```

Константы можно определить двумя способами.

1. Указывая начальное значение или выражение для каждой константы.

   ```
   const {
    MY_ID = 1
    MY_VAL = myFunc( MY_ID + 23)
    CHECK= MY_VAL < 32
   }
   ```
2. Используя общее выражение с **IOTA**. Иногда возникает необходимость определить список констант со значениями, которые вычисляются по определенным правилам. В этом случае, после ключевого слова **const** необходимо указать одно общее выражение, которая будет вычисляться для каждой константы в данном определении. В этом выражении можно использовать специальную переменную *IOTA*, которая равна порядковому индексу константы в списке с нуля. Сами константы могут перечисляться через пробел или с новой строки.

   ```
   const 0x1 << IOTA {
      FIRST SECOND   // 0x1    0x2
      THIRD                   // 0x4
   }
   const (IOTA * 2) + 1 {
      MY1    // 1
      MY2   // 3
      MY3   // 5
   }
   ```

## Описание функции

Определение функции состоит из двух частей - описание параметров с возвращаемым типом и тела функции. При определении функции вы должны указать ключевое слово "func", имя функции, передаваемые параметры и тип возвращаемого значения. Только имя функции является обязательным элементом.

```
FunctionDecl   = "func" FunctionName [Parameters] [ Result ] Block
FunctionName   = identifier 
Result         = TypeName 
Parameters     = "(" [ ParameterList ] ["..."] ")"
ParameterList  = VarList { "," VarList }
```

```
func VariadicExample(int i, int s...) int {
    int sum = i*2
    for v in s {
       sum += v
    }
    return sum
}
func MyFunc(int par1 par2) int { 
    int par3 = VariadicExample(3, par1, par2, 4, 5, par1+par2)
    return (par1+par2 +par3)/3 
}
```

Заключительный параметр в описании функции может иметь суффикс *'...'*. Функция с таким параметром называется вариативной и может принимать ноль и более аргументов для этого параметра. Вы получаете этот параметр как массив переданных аргументов. Например, *int pars...* означает, что *pars* в действительности является *arr.int* и вы можете получить i-й аргумент с помощью *pars\[i]*.

## Описание функции запуска

Скрипт на языке Gentee должен содержать специальную функцию без параметров, которая определяется с помощью ключевого слова "run". Выполнение скрипта начинается с вызова этой функции. Скрипт должен иметь только одно определение "run".

```
RunDecl = "run" [FunctionName] [ Result ] Block
```

```
run int {
    int i ret
    while i < 10 {
       ret += myFunc(i++)
    }
    return ret
}
```


# Конструкции языка

Блок это последовательность определений и конструкций внутри фигурных скобок. Блоки могут вкладываться друг в друга.

```
Block = "{" StatementList "}" .
StatementList = { Statement newline } .
Statement = ReturnStmt | IfStmt | Expression | WhileStmt | VarDeclaration | ForStmt | 
            LocalDecl | BreakStmt | ContinueStmt | SwitchStmt | GoStmt | TryStmt | 
            RecoverStmt | RetryStmt
```

## Определение переменной

Любая переменная функции должна быть описана перед её использованием. Определение переменной создает одну или несколько переменных и присваивает каждой начальные значения. Переменная может быть определена в любом блоке. Область видимости переменной распространяется на блок, в котором она определена и на все вложенные блоки. Нельзя создавать переменные с именем существующих функций и видимых переменных. Также, имя переменной должно содержать как минимум одну букву в нижнем регистре, так как имена в верхнем регистре используются для констант. Определение переменой начинается с указания её типа. Существует два типа инициализации - можно определить одну переменную с присваиванием ей значения или несколько переменных одного типа с инициализацией по умолчанию.

```
VarDeclaration = VarAssign | VarList
VarList = TypeName ["?"] IdentifierList
VarAssign = TypeName ["?"] identifier "=" | "&=" VarInit
```

```
int x y myVal
int z = myFunc(x) + y + 10
arr a &= b
```

Вы можете определить **опциональные параметры-переменные** указав **?** после типа переменной. Если вы инициализируете опциональный параметр оператором присваивания **=** или **&=**, то это будет его значение по умолчанию в том случае, если параметр не будет определен при вызове функции.\
Для того чтобы передать опциональный параметр при вызове функции, необходимо указать имя переменной и её значение через двоеточие. Опциональные параметры указываются после обычных параметров.

```
func mul(int i) int {
      int ? j = 10
      return i*j
}

run int {
      return mul(7) + mul(5, j: 5)  // 70+25
}
```

## Конструкция if

Конструкции **if** начинаются с "if", они могут иметь один или несколько блоков "elif" и заканчиваться "else". Команда последовательно вычисляет условие для каждой ветки и, если условие возвращает истину, то тогда происходит выполнение соответствующего блока. В этом случае, остальные ветки пропускаются и управление передается следующей команде. Если условия во всех ветках ложны, то выполняется блок "else", если он существует.

```
IfStmt = "if" Expression Block [{ "elif" Expression Block }][ "else" Block ]
```

```
if a == 11 {
    b = 20
} else {
    c = a+b
}
if x > y && isOK { 
     x = 1 
} elif a > 1 {
   x++
} elif b < 10 {
    b = a
} else {x = 0}
```

## Конструкция while

Конструкция **while** является простым циклом. Данная конструкция выполняет блок до тех пор, пока логическое выражение равно истине. Если выражение ложно изначально (при первом обращении), то блок не будет выполнен ни разу.

```
WhileStmt = "while" Expression Block
```

```
a = 0
while a < 5 {
   с += a
   a++
}
```

## Конструкция for

Конструкция **for** служит для перебора всех элементов указанного объекта. Объект должен иметь тип, который поддерживает обращение по индексу, например, **arr**, **map**, **str**, **buf**, **set**, **range of integers**. Для каждого из его элементов выполняется код, который определен внутри конструкции. Вы должны указать имя переменной, которой будут присваиваться элементы и, опционально, имя переменной, которая будет равна текущему индексу.\
Если вы хотите перебрать целочисленные значения в указанном диапазоне, то используйте в качестве объекта запись **from..to**, где *from* и *to* значения типа *int*. Такой цикл будет перебирать все числа от *from* до *to*, включая крайние значения. Начальное значение может быть больше конечного значения, в этом случае, значение на каждом цикле будет уменьшаться.

```
ForStmt = "for" identifier [, identifier] "in" Expression Block
```

```
str dest
for ch, i in `strΔ` {
   dest += "\{i}\{ch}"
}
int sum
for i in 0..100 : sum += i
```

## Конструкция switch

Конструкция **"switch"** позволяет производить разные действия в зависимости от значения выражения. После ключевого слова **switch** необходимо указать начальное выражение, значение которого будет сравниваться с различными вариантами в блоках **case**. Значение может иметь тип **int, float, char, str**. Затем вам нужно перечислить блоки **case** со всеми возможными значениями и соответствующим кодом в фигурных скобках, который необходимо будет выполнить в случае соответствия. Для одного **case** может быть указано несколько значений, разделённых запятыми. После выполнения **case** блока с найденными соответствием, программа заканчивает работу **switch** конструкции. Оставшиеся **case** блоки не проверяются.

Если вы хотите выполнить какие-то действия в случае, если подходящий вариант не найден, то укажите в конце блок **default**. Конструкция *default* может быть только одна и идти после всех *case* конструкций.

```
SwitchStmt = "switch" Expression newline CaseStmt { CaseStmt } [ "default" Block ]
CaseStmt = "case" Expression {, Expression } Block
```

```
int i = 67
int j
switch i+3 
case 20,10,5 {
  i +=10
}
case j,20+50,80 {
  i -=10
}
default: i *= 2
```

## Локальные функции local

Вы можете определять локальные функции **local** внутри функций **func**. Локальные функции могут принимать параметры и возвращать значения. Локальные функции не поддерживают переменное число аргументов. Для возврата из локальной функции необходимо использовать конструкцию **return**. В локальных функциях можно обращаться к внешним переменным и параметрам, которые были определены выше.

```
LocalDecl   = "local" FunctionName [Parameters] [ Result ] Block
```

```
run int {
    int i
    local loc(int step) int {
          return (i += 2)+step
    }
    return loc(1) + loc(2)*loc(3)
} 
// result: 57
```

## Конструкция return

Конструкция "return" прекращает выполнение текущей функции и может возвращать результирующее значение. Если у функции не указан результирующий тип, то конструкция "return" не должна возвращать значение. Вы можете использовать *return* в любом вложенном блоке.

```
ReturnStmt = "return" [ Expression ]
```

```
func mul2(int i) int { return i*2}
```

## Конструкция break

Конструкция **break** используется для выхода из конструкции **switch/case** и циклов (**for** и **while**). **break** может быть внутри вложенных блоков. Если есть несколько вложенных циклов, то произойдёт выход из текущего цикла.

```
BreakStmt = "break"
```

```
while b > c {
   if !myfunc( b ) {
      break   
   }
   b++
}
```

## Конструкция continue

Конструкция "continue" действует внутри циклов (**for** и **while**) и позволяет перейти к выражению изменения счетчика для циклов *for* или к выражению условию для *while* не выполняя до конца тело цикла. В случае вложенных циклов инструкция действует на текущий цикл .

```
ContinueStmt = "continue"
```

```
for i in 0..100 {
   if i > 10 && i < 20 {
      continue 
   }
   a += i // Это выражение не вычисляется если i>10 и i<20
}
```


# Обработка ошибок

## Конструкция try catch

По умолчанию, если в момент выполнения скрипта была получена ошибка, то скрипт сразу заканчивает свою работу. Если вы хотите избежать прекращения работы скрипта, то вы должны использовать конструкцию **try**. Если во время выполнения кода внутри блока *try* произошла ошибка, то управление перейдет в конструкцию **catch**, которая должна быть после **try**. После ключевого слова *catch* необходимо указать имя переменной типа *error*, которая будет содержать информацию об ошибке. Вы можете использовать [специальные функции](https://gentee.github.io/docs-gentee-ru/stdlib/runtime#erriderror-err-int) для получения идентификатора и текста ошибки. Если вы не удалите ошибку внутри *catch* с помощью **recover** или **retry**, то она будет передана дальше и скрипт закончит свою работу.

```
TryStmt ="try" Block CatchStmt
CatchStmt = "catch" identifier Block
```

```
run  {
   try {
      myfunc()
      error(101, "Custom error")
   }
   catch err {
      if ErrID(err) != 101:  error( 102, 
         "Error \{ErrText(err)} has occurred in myfunc()")
   } 
}
```

## Конструкция recover

Конструкция **recover** используется внутри блока **catch** для удаления ошибки. По этой команде информация об ошибке удаляется, скрипт выходит из текущего блока *catch* и продолжает выполнение дальше.

```
RecoverStmt = "recover"
```

```
run str {
   try : 10/0
   catch err :  recover
   return "ok"
} 
// ok
```

## Конструкция retry

Конструкция **retry** используется внутри блока **catch** для повторного запуска **try**. По этой команде информация об ошибке удаляется и скрипт заново выполняет соответствующий блок *try*.

```
RetryStmt = "retry"
```

```
run {
   str fname
   try {
       fname = ReadString("Specify filename: ")
       Println("Beginning of the file: ", str(ReadFile(fname, 0, 50)))
    } catch err {
       Println("ERROR #\{ErrID(err)}: \{ErrText(err)}")
       retry
    }
}
```


# Выражения

Выражение возвращает значение путем применения операторов и функций к операндам. Операндом может быть литерал, идентификатор определяющий константу, переменную, функцию или выражение в скобках. Для вызова функции необходимо указать её имя и в круглых скобках перечислить параметры через запятую. Параметры тоже могут быть выражениями. Кроме этого, можно выносить первый параметр впереди функции и отделять его точкой. Это помогает более наглядно указать последовательность вызовов функций.

```go
(b*c).func3(d).func2(a).func1(10)
"my string".Upper().TrimRight("g")
// эквивалентно
func1(func2(func3( b*c, d ), a), 10)
TrimRight(Upper("my string"), "g")
```

```
Operand     = Literal | OperandName | "(" Expression ")" | GoStmt
Literal     = BasicLiteral
constLit    = "true" | "false"
BasicLiteral    = float | integer | stringLit | constLit | charLit
OperandName = identifier | EnvVariable | FnIdent
PrimaryExpr = Operand | FuncName Arguments | Expression "." FuncName Arguments | IfOp | 
              IndexExp | FieldExpr
OptionalArgs = identifier ":" Expression { "," identifier ":" Expression }
Arguments    = "(" [ ExpressionList ] [ OptionalArgs ] ")" 
ExpressionList = Expression { "," Expression } 
Expression = UnaryExpr | Expression binaryOp Expression | 
             OperandName assignOp Expression
UnaryExpr  = PrimaryExpr | unaryOp UnaryExpr | incOp OperandName | OperandName incOp | 
             UnaryExpr postunaryOp
binaryOp  = "||" | "&&" | relOp | mathOp | assignOp | rangeOp
relOp     = "==" | "!=" | "<" | "<=" | ">" | ">=" 
mathOp   = "+" | "-" | "|" | "^" | "*" | "/" | "%" | "<<" | ">>" | "&" | 
unaryOp  = "-" | "!" | "^" | "*" | "#" | "##"
postunaryOp = "?"
incOp    = "++" | "--" 
rangeOp  = ".."
assignOp = "=" | "+=" | "-=" | "|=" | "^=" | "*=" | "/=" | "%=" | "<<=" | 
           ">>=" | "&=" | "#=" 
IfOp = "?" "(" Expression "," Expression "," Expression ")"
```

При вычислении логических операторов "&&" (И) и "||" (ИЛИ), правый операнд вычисляется опционально. Например, в случаях `false && myFunc()` и `true || myFunc()` функция myFunc не будет вызываться.

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

```go
int i j k
i = j = 5+(k=60/5)*2
return (k+j)*2 + i   // 111
```

## Приоритеты операторов

Как правило все операторы выполняются слева направо, но имеется такое понятие как приоритет операторов. Если следующий оператор имеет более высокий приоритет, то вначале выполнится оператор с более высоким приоритетом. Например, умножение имеет более высокий приоритет и 4 + 5 *2 равно 14, но если мы поставим круглые скобки то ( 4 + 5 )* 2 равно 18.

| Оператор                                                | Тип              | Ассоциативность |
| ------------------------------------------------------- | ---------------- | --------------- |
| Высший приоритет                                        |                  |                 |
| (   )  \[   ]                                           |                  | Слева направо   |
| -   ^   #   ##   \*   ++   --                           | Унарный префикс  | Справа налево   |
| ?                                                       | Унарный постфикс | Справа налево   |
| !                                                       | Унарный префикс  | Справа налево   |
| ++   --                                                 | Унарный постфикс | Слева направо   |
| /   %   \*                                              | Бинарный         | Слева направо   |
| +   -                                                   | Бинарный         | Слева направо   |
| <<   >>                                                 | Бинарный         | Слева направо   |
| &                                                       | Бинарный         | Слева направо   |
| ^                                                       | Бинарный         | Слева направо   |
| \|                                                      | Бинарный         | Слева направо   |
| ==   !=   <   <=   >   >=                               | Бинарный         | Слева направо   |
| \|\|                                                    | Бинарный         | Слева направо   |
| &&                                                      | Бинарный         | Слева направо   |
| #=                                                      | Бинарный         | Слева направо   |
| =   +=   -=   \*=   /=   %=   <<=   >>=   &=   ^=   \|= | Бинарный         | Справа налево   |
| ..                                                      | Бинарный         | Слева направо   |
| Низший приоритет                                        |                  |                 |

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

## Условный оператор "?"

Условный оператор "?" аналогичен по своей работе конструкции "if", но может использоваться внутри выражения. Он содержит три операнда-выражения. Операнды заключены в скобки и разделены запятыми, вначале вычисляется значение первого логического (целочисленного) выражения. Если значение истинно, то вычисляется второе выражение и полученное значение становится результатом работы условного оператора. В противном случае вычисляется третий операнд и возвращается его значение.

```go
if a >= ?( x, 0xFFF, ?( y < 5 && y > 2, y, 2*b )) + 2345
{
     r = ?( a == 10, a, a + b ) 
}
```

## Инициализация массивов и структур

При определении переменных с типом *arr*, *set*, *buf* или *map* можно сразу присвоить элементы массива. Также можно указывать значения полей переменных структурных типов. Значения перечисляются через запятую или перенос строки. В качестве значения можно указывать выражения. При инициализации ассоциативного массива *map* необходимо указать ключ в виде строки и через двоеточие значение. Если элементами массива являются другие массивы, то они тоже инициализируются с помощью фигурных скобок. При инициализации полей структур необходимо указать ключ в виде идентификатора и через двоеточие значение. Переменная типа **buf** может инициализироваться комбинацией значений типов **int**, **str**, **char**, **buf**.

```
DelimInit = "," | newline
ArrInit = "{" VarInit {DelimInit VarInit} "}"
BufInit = "{" Expression {DelimInit Expression} "}"
MapInit = "{" Expression ":" VarInit { DelimInit Expression ":" VarInit  }  "}"
SetInit = "{" Expression {DelimInit Expression} "}"
StructInit = "{" identifier ":" VarInit { DelimInit identifier ":" VarInit  }  "}"
VarInit = ArrInit | BufInit | MapInit | StructInit | SetInit | Expression
```

```go
mystruct my = {ID: 20, name: "some text"}
buf a = {250+5, '1', 'A', "test", 0}
map.arr.int ret = {"key1": {0, 1 }, `key2`:{ 2, 3 } }
arr.map ret = { {"test": "value 1"}
                {`next`:"value 2"} }
arr.bool mb = : true, false, true
map  my = {"key1": GetVal(1), "key2": GetVal(2)}
set s &= {1, 0, 45, myintval, MYCONST}
```

## Индексное выражение

Индексы позволяют вам получать или устанавливать определенный элемент переменной по его индексу. Индекс - это позиция определенного элемента внутри указанной переменной. Индексы в Gentee начинаются с нуля (для **map** индексы имеют строковый тип), первый элемент имеет индекс 0, второй индекс один и т.д. Следующие типы поддерживают индексы:

* **str**. Индекс должен иметь тип **int** и быть меньше длины строки. Если индекс выходит за этот диапазон, то возникает ошибка выполнения. Результат имеет тип **char**.
* **buf**. Индекс должен иметь тип **int** и быть меньше длины массива. Если индекс выходит за этот диапазон, то возникает ошибка выполнения. Результат имеет тип **int**, но 0 <= значение <= 255.
* **arr**. Индекс должен иметь тип **int** и быть меньше длины массива. Если индекс выходит за этот диапазон, то возникает ошибка выполнения. Результат имеет такой же тип, как тип элементов массива.
* **map**. Индекс должен иметь тип **str**. В случае получения значения, элемент с таким индексом должен существовать в ассоциативном массиве. Если такой ключ отсутствует, то возникает ошибка выполнения. Результат имеет такой же тип, как тип элементов ассоциативного массива.
* **set**. Индекс должен иметь тип **int** и быть меньше 64000000. Если индекс выходит за этот диапазон, то возникает ошибка выполнения. Результат имеет логический тип.

Если массив *array* или *map* состоит из массивов, то вы можете последовательно применить индексные выражения.

```
IndexExp = PrimaryExpr "[" Expression "]" { "[" Expression "]" }
```

```go
str temp = `0123`
temp[1] = temp[3]  // result `0323`
arr ain
ain += `test`
temp = ain[0]
map mymap
mymap["mykey"] = "myvalue"
arr.map amap
amap += mymap
amap[0]["mykey"] = "new value"
```

## Выражения присваивания

Для всех типов в языке Gentee существует оператор присваивания **=**. При использовании присваивания для типов **buf, arr, map, set** и всех структурных типов вы будете получать копии данных. Рассмотрим пример

```go
arr a1 = {`A`, `B`, `C`}
arr a2 = a1
a2 += `D`
a1[0] = `Z`
//  a1 = `Z`, `B`, `C`
//  a2 = `A`, `B`, `C`, `D`
```

При присваивании *a2 = a1* мы получили копию массива *a1*. Действия над массивами никак не будут влиять друг на друга. Иногда создание копий больших объектов может замедлять выполнение программы. Например, если функция возвращает какую-то структуру, с которой нужно работать дальше, то нет смысла создавать её копию. Для разрешения таких ситуаций, для типов **buf, arr, map, set** и всех структурных типов имеется еще один оператор присваивания **&=**. Этот оператор не копирует данные в переменную, а создает клон этих данных. В этом случае, данные остаются в единственном экземпляре.

```go
arr a1 = {`A`, `B`, `C`}
arr a2 &= a1
a2 += `D`
a1[0] = `Z`
//  a1 = `Z`, `B`, `C`, `D`
//  a2 = `Z`, `B`, `C`, `D`
```

```go
time t
t &= Now()  // так лучше, чем  t = Now()
```

## Контекст

В языке Gentee отсутствуют глобальные переменные. Вместо них имеется ассоциативный массив *map.str*, который доступен на чтение и запись из любых функций и потоков. Кроме хранения данных в виде ключ-значение, контекст может ещё производить рекурсивную замену ключей в строках вида *"#key\_name# #another\_key\_name#"*. Все [функции для работы с контекстом](https://gentee.github.io/docs-gentee-ru/stdlib/context) описаны в стандартной библиотеке. Здесь рассмотрим только операторы.

* Унарный оператор **## str** рекурсивно заменяет ключи на их значения  в переданной строке и возвращает полученный результат.&#x20;
* Унарный оператор **# key** работает аналогично оператору **##**, но ему нужно передать имя-идентификатор ключа контекста.
* Оператор **key #= value** записывает в контекст  ключ *key* с указанным  значением. Если вместо типа *str* значение имеет тип *int, bool, float*, то оно будет сконвертировано в строку.

```go
func ooops() {
    AB #= `oops`
}
run str {
    AB #= `test`
    CD #= `#AB# - `    // don't replace #AB#.  CD = #AB# - 
    E #= #AB           // get #AB#. E = test
    ooops()            // change AB
    val #= 10
    return #CD + #E + ##` #val# == 10`
}
// Result:  oops - test 10 == 10
```


# Запуск программ

В языке Gentee существует специальная команда **$** для запуска приложений и команд операционной системы с указанными параметрами. Данная команда запускает весь следующий за ней текст до конца строки. Между символом **$** и командной строкой должен присутствовать пробел. Если данная команда используется в выражении, то она перехватывает стандартный вывод и возвращает его в виде строки. В противном случае, стандартный вывод будет виден в консоли. Можно использовать подстановку выражений с помощью **%{Expression}** как в строке с обратными кавычками. Если какой-то параметр содержит пробел, то его нужно заключить в любые кавычки - *"a b", 'c d', \`e f\`*. Если запускаемое приложение или команда завершилось с кодом ошибки, отличным от нуля, то скрипт также прекратит работу и возвратит ошибку.

```
Command = "$ " { unicode_linechar | "%{" Expression "}" | "${" identifier "}" }
```

```
run str {
   $ dir
   str name = $ echo "John Smith"
   return $ echo My name is %{name}
}
```

## Переменные окружения

Язык Gentee позволяет вам легко получать и присваивать значения переменных окружения. Для этого укажите знак **$** перед именем переменной. Кроме этого, вы можете подставлять переменные окружения с помощью конструкции **${ENV\_NAME}** в командах запуска **$** и строках с обратными кавычками. Эта запись короче, чем *%{ $ENV\_NAME }*. Переменные окружения всегда имеют строковый тип, но вы можете присваивать им значения типа **str**, **int** и **bool**.

```
EnvVariable = "$" identifier
```

```
run str {
    $MYVAR = `Go path: ${GOPATH}` + $GOROOT
    return $ echo ${MYVAR}
}
```


# Многопоточность

Язык Gentee позволяет создавать многопоточные скрипты. В этом случае, часть скрипа может выполняться параллельно, что уменьшает время его работы. Чтобы выполнить какой-то код в отдельном потоке, необходимо указать его в конструкции **go**. Скрипт продолжит выполнять следующие конструкции не дожидаясь окончания работы кода внутри *go*, а сразу после того как новый поток будет запущен. Конструкция **go** возвращает идентификатор созданного потока, который можно присвоить переменной типа **thread** и использовать затем в функциях управления потоками. Если скрипт закончил свою работу раньше чем созданные потоки, то он будет ожидать окончания работы всех потоков. Если при выполнении многопоточного скрипта произошла ошибка в любом из потоков, то в этом случае, все потоки закрываются и скрипт возвращает эту ошибку.

```
GoStmt = "go" [ "(" GoArgs ")" ] Block
GoArgs = identifier ":" Expression { "," identifier ":" Expression }
```

```
func myThread {
  for i in 0..50 {
    Print(`x` )
    if i % 3 == 0 : sleep(5)
  }
}

run {
  thread th = go {
    for i in 0..100 {
      Print(` `, i )
      if i % 7 == 0 : sleep(5)
    }
  }
  suspend( th )
  go : myThread()
  resume(th)
  Print( `OK`)
  wait(th)
  Print( `END`)
}
```

Вы можете передавать любые параметры в команде **go**. Для этого необходимо указать имя параметра и, через двоеточие, его значение. Тип параметра определяется автоматически по переданному значению. Если вы передаете структуры или массивы, то параметру будет присвоена копия значения.

```
run str {
  str s = "ok"
  thread th1 = go (a: s + " test") : ctxPar #= a
  thread th2 = go (a: Max(1,23), b: Min(100,87)) {
     ctxSum #= a + b
  }
  wait(th2)
  wait(th1)
  return #ctxPar + #ctxSum
}
```


# Включение и импорт файлов

## Включение и импорт файлов

Описание **include** импортирует все типы, функции и константы из указанных файлов и их дочерних файлов включенных с помощью **include**.

Описание **import** импортирует только публичные типы, функции и константы из указанных файлов и их дочерних файлов включенных с помощью **include**. Публичные объекты определяются с помощью ключевого слова **pub**.

```
stringConst         = "`" { unicode_char } "`" | stringDoubleConst
stringDoubleConst = `"` { unicode_char | uShort | uLong | escapedChar | byteVal } `"`
importDecl = "import" "{" {stringConst newline} "}"
includeDecl = "include" "{" {stringConst newline} "}"
```

Рассмотрим видимость объектов в виде таблицы. Пусть имеется два файла.

```
// a.g can include or import b.g
func afunc(i int) : return i*2
pub func apubfunc(i int) : return i*3

// b.g 
func bfunc(i int) : return i*4
pub func bpubfunc(i int) : return i*5
```

Пусть файл *c.g* может импортировать или включать файл *a.g*. Вы можете видеть какие функции будут видимы в файле *c.g* в зависимости от различных ситуаций.

|          | include a   a includes b | include a   a imports b | import a   a includes b | import a   a imports b |
| -------- | ------------------------ | ----------------------- | ----------------------- | ---------------------- |
| afunc    | visible                  | visible                 |                         |                        |
| apubfunc | visible                  | visible                 | visible                 | visible                |
| bfunc    | visible                  |                         |                         |                        |
| bpubfunc | visible                  |                         | visible                 |                        |

## Описание pub

Команда **pub** определяет следующую функцию, тип или константы как публичные. Вы можете импортировать их с помощью команды **import**.

```
pubDecl = "pub" [newline]
objects = [pubDecl] (structDecl | FnDecl | ConstDecl | FunctionDecl)
```

Ключевое слово **pub** указывает, что следующая функция, константы или тип будут передаваться в случае импорта файла.

```
pub const IOTA {  // public constants. Visible when include or import
    MY1
    MY2
}

const IOTA*2 {  // private constants. Visible only when include
    MY3
    MY4
}
```


# Стандартная библиотека


# Архивация

Здесь описаны функции для работы с архивами **zip** и **tar.gz**.

* [ArchiveName( finfo fi, str root ) str](/stdlib/archive#archivename-finfo-fi-str-root-str)
* [CloseTarGz( handle h )](/stdlib/archive#closetargz-handle-h)
* [CloseZip( handle h )](/stdlib/archive#closezip-handle-h)
* [CreateTarGz( str name ) handle](/stdlib/archive#createtargz-str-name-handle)
* [CreateZip( str name ) handle](/stdlib/archive#createzip-str-name-handle)
* [CompressFile( handle h, str fname, str packname )](/stdlib/archive#compressfile-handle-h-str-fname-str-packname)
* [ReadTarGz( str name ) arr.finfo](/stdlib/archive#readtargz-str-name-arr-finfo)
* [ReadZip( str name ) arr.finfo](/stdlib/archive#readzip-str-name-arr-finfo)
* [TarGz( str name, str path )](/stdlib/archive#targz-str-name-str-path)
* [UnpackTarGz( str name, str path )](/stdlib/archive#unpacktargz-str-name-str-path)
* [UnpackTarGz( str name, str path, arr pattern, arr ignore )](/stdlib/archive#unpacktargz-str-name-str-path-arr-pattern-arr-ignore)
* [UnpackZip( str name, str path )](/stdlib/archive#unpackzip-str-name-str-path)
* [UnpackZip( str name, str path, arr pattern, arr ignore )](/stdlib/archive#unpackzip-str-name-str-path-arr-pattern-arr-ignore)
* [Zip( str name, str path )](/stdlib/archive#zip-str-name-str-path)

## Функции

### ArchiveName(finfo fi, str root) str

Функция *ArchiveName* объединяет поля *Name* и *Dir* в переменной типа *finfo* и возвращает путь файла для архива относительно корневого пути *root*.

### CloseTarGz(handle h)

Функция *CloseTarGz* заканчивает создание *.tar.gz* архива. Параметр *h* - это идентификатор, который был возвращен функцией **CreateTarGz**.

### CloseZip(handle h)

Функция *CloseZip* заканчивает создание *.zip* архива. Параметр *h* - это идентификатор, который был возвращен функцией **CreateZip**.

### CreateTarGz(str name) handle

Функция *CreateTarGz* начинает создание **.tar.gz** архива с указанным именем. Вы можете добавлять файлы в этот архив с помощью функции **CompressFile**. Функция возвращает идентификатор, который нужно будет закрыть с помощью функции *CloseTarGz*.

### CreateZip(str name) handle

Функция *CreateZip* начинает создание **.zip** архива с указанным именем. Вы можете добавлять файлы в этот архив с помощью функции **CompressFile**. Функция возвращает идентификатор, который нужно будет закрыть с помощью функции *CloseZip*.

### CompressFile(handle h, str fname, str packname)

Функция *CompressFile* добавляет указанный файл *fname* в создаваемый архив. Параметр *packname* содержит относительный путь и имя файла с которым он будет сохранен в архиве. В качестве разделителя нужно использовать символ **/**. Архив предварительно должен быть создан с помощью функций **CreateZip** или **CreateTarGz**.

```go
    handle zip = CreateZip(`my.zip`)
    CompressFile(zip, `../data/my.txt`, `my.txt`)
    CompressFile(zip, `/home/user/folder/copy.txt`, `folder/copy.txt`)
    CloseZip(zip)
```

### ReadTarGz(str name) arr.finfo

Функция *ReadTarGz* возвращает список файлов в указанном **tar.gz** архиве. Поле *Name* содержит имя файла вместе с относительным путем.

```go
   arr.finfo list = ReadTarGz(`my.tar.gz`)
   for fi in list : Println( "\{fi.Name} \{fi.Size}")
```

### ReadZip(str name) arr.finfo

Функция *ReadZip* возвращает список файлов в указанном **zip** архиве. Поле *Name* содержит имя файла вместе с относительным путем.

### TarGz(str name, str path)

Функция *TarGz* упаковывает файл или содержимое директории *path* в **.tar.gz** архив с именем *name*.

```go
   TarGz("/home/user/out/my.tar.gz", `/home/user/docs`)
```

### UnpackTarGz(str name, str path)

Функция *UnpackTarGz* распаковывает **.tar.gz** архив с именем *name* в директорию *path*.

```go
   UnpackTarGz("/home/user/out/my.tar.gz", `/home/user/olddocs`)
```

### UnpackTarGz(str name, str path, arr pattern, arr ignore)

Функция *UnpackTarGz* выборочно распаковывает **.tar.gz** архив с именем *name* в директорию *path*. Массив *pattern* содержит шаблоны файлов, которые необходимо распаковать. Массив *ignore* содержит шаблоны файлов, которые необходимо пропустить. Параметры *pattern* и *ignore* могу быть пустыми массивами. Если шаблон начинается и заканчивается символом **/**, то он обрабатывается как регулярное выражение.

```go
   arr empty
   arr doc = {`*.docx`, `/.txt$/`}
   UnpackTarGz("/home/user/out/my.tar.gz", `/home/user/tmp`, doc, empty )
```

### UnpackZip(str name, str path)

Функция *UnpackZip* распаковывает **.zip** архив с именем *name* в директорию *path*.

```go
   UnpackZip("/home/user/out/my.zip", `/home/user/olddocs`)
```

### UnpackZip(str name, str path, arr pattern, arr ignore)

Функция *UnpackZip* выборочно распаковывает **.zip** архив с именем *name* в директорию *path*. Массив *pattern* содержит шаблоны файлов, которые необходимо распаковать. Массив *ignore* содержит шаблоны файлов, которые необходимо пропустить. Параметры *pattern* и *ignore* могу быть пустыми массивами. Если шаблон начинается и заканчивается символом **/**, то он обрабатывается как регулярное выражение.

```go
   arr empty
   arr skip = {`/temp.pdf/`, `/.txt$/`}
   UnpackZip("/home/user/out/my.tar.gz", `/home/user/tmp`, empty, skip )
```

### Zip(str name, str path)

Функция *Zip* упаковывает файл или содержимое директории *path* в **.zip** архив с именем *name*.

```go
   Zip("/home/user/out/mydoc.zip", `/home/user/docs/important.docx`)
```


# Ассоциативные массивы

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

* [bool( map.typename m ) bool](/stdlib/map#bool-map-typename-m-bool)
* [Del( map.typename m, str key ) map.typename](/stdlib/map#del-map-typename-m-str-key-map-typename)
* [IsKey( map.typename m, str key ) bool](/stdlib/map#iskey-map-typename-m-str-key-bool)
* [Key( map.typename m, int index ) str](/stdlib/map#key-map-typename-m-int-index-str)

## Операторы

| Оператор                         | Результат    | Описание                                                                                      |
| -------------------------------- | ------------ | --------------------------------------------------------------------------------------------- |
| **\*** map.typename              | int          | Возвращает количество элементов в массиве.                                                    |
| map.typename **?**               | bool         | Вызов *bool(map.typename)*.                                                                   |
| map.typename **=** map.typename  | map.typename | Присваивание.                                                                                 |
| map.typename **&=** map.typename | map.typename | Создать клон ассоциативного массива. Новая переменная будет работать с тем же набором данных. |
| map.typename **\[** str **]**    | typename     | Присвоить/получить значение ассоциативного массива по ключу.                                  |

## Функции

### bool(map.typename m) bool

Функция *bool* возвращает *false*, если ассоциативный массив пустой. В противном случае, возвращается *true*.

### Del( map.typename m, str key ) map.typename

Функция *Del* удалять указанный ключ и его значение из массива *map*. Возвращается параметр *m*.

### IsKey( map.typename m, str key ) bool

Функция *IsKey* возвращает *true*, если в ассоциативном массиве *m* существует значение с указанным ключом и *false*, в противном случае.

### Key( map.typename m, int index ) str

Функция *Key* возвращает ключ элемента по его индексу. Например, эта функция может быть использована в цикле *for* для получения ключа элемента.

```go
for val,i in mymap {
    Println("\(Key(mymap, i)):\(val)")
}
```


# Буфер

Здесь описаны операторы и функции для работы со двоичными данными в виде массива байт (тип **buf**).

* [bool( buf b ) bool](/stdlib/buffer#bool-buf-b-bool)
* [buf( str s ) buf](/stdlib/buffer#buf-str-s-buf)
* [str( buf b ) str](/stdlib/buffer#str-buf-b-str)
* [Base64( buf b ) str](/stdlib/buffer#base-64-buf-b-str)
* [DecodeInt( buf b, int offset ) int](/stdlib/buffer#decodeint-buf-b-int-offset-int)
* [Del( buf b, int off, int length ) buf](/stdlib/buffer#del-buf-b-int-off-int-length-buf)
* [EncodeInt( buf b, int i ) buf](/stdlib/buffer#encodeint-buf-b-int-i-buf)
* [Hex( buf b ) str](/stdlib/buffer#hex-buf-b-str)
* [Insert( buf b, int off, buf src) buf](/stdlib/buffer#insert-buf-b-int-off-buf-src-buf)
* [SetLen( buf b, int size ) buf](/stdlib/buffer#setlen-buf-b-int-size-buf)
* [Subbuf( buf b, int off, int length ) buf](/stdlib/buffer#subbuf-buf-b-int-off-int-length-buf)
* [UnBase64( str s ) buf](/stdlib/buffer#unbase-64-str-s-buf)
* [UnHex( str s ) buf](/stdlib/buffer#unhex-str-s-buf)
* [Write( buf b, int off, buf src ) buf](/stdlib/buffer#write-buf-b-int-off-buf-src-buf)

## Операторы

| Оператор             | Результат | Описание                                                                      |
| -------------------- | --------- | ----------------------------------------------------------------------------- |
| **\*** buf           | int       | Получить размер буфера в байтах.                                              |
| buf **?**            | bool      | Вызов *bool(buf)*.                                                            |
| buf **+** buf        | buf       | Объединить два буфера.                                                        |
| buf **=** buf        | buf       | Присваивание двоичных данных.                                                 |
| buf **&=** buf       | buf       | Создать клон буфера. Новая переменная будет работать с тем же набором данных. |
| buf **+=** buf       | buf       | Добавить один буфер к другому.                                                |
| buf **+=** int       | buf       | Добавить один байт к буферу. Число должно быть меньше 256.                    |
| buf **+=** str       | buf       | Добавить строку к буферу.                                                     |
| buf **+=** char      | buf       | Добавить символ к буферу.                                                     |
| buf **\[** int **]** | int       | Присвоить/получить байт по индексу.                                           |

## Функции

### bool(buf b) bool

Функция *bool* возвращает *false*, если буфер пустой. В противном случае, возвращается *true*.

### buf(str s) buf

Функция *buf* конвертирует строку в значение типа *buf* и возвращает его.

### str(buf b) str

Функция *str* конвертирует значение типа *buf* в строку и возвращает её.

### Base64(buf b) str

Функция *Base64* преобразует значение типа *buf* в строку в кодировке **base64** и возвращает её.

### DecodeInt(buf b, int offset) int

Функция *DecodeInt* получает целое число из параметра типа *buf*. *offset* - смещение в буфере, по которому необходимо прочитать число. Функция читает 8 байт и возвращает их как целое число.

### Del(buf b, int off, int length) buf

Функция *Del* удалять часть данных из массива байт. *off* - смещение удаляемых данных, *length* - количество удаляемых байт. Если *length* меньше нуля, то данные будут удаляться слева от указанного смещения. Функция возвращает переменную *b*, в которой произошло удаление.

### EncodeInt(buf b, int i) buf

Функция *EncodeInt* добавляет целое число к указанной переменной типа *buf*. Так как значение *int* занимает 8 байт, то к буферу добавляется 8 байт независимо от значения параметра *i*. Функция возвращает параметр *b*.

### Hex(buf b) str

Функция *Hex* преобразует значение типа *buf* в шестнадцатеричную строку и возвращает её.

### Insert(buf b, int off, buf src) buf

Функция *Insert* вставляет массив байт *src* в массив *b*. *off* - смещение, куда будет вставлен указанный массив байт. Функция возвращает переменную *b*.

### SetLen(buf b, int size) buf

Функция *SetLen* устанавливает размер буфера. Если *size* меньше размера буфера, то он будет обрезан. В противном случае, буфер будет дополнен нулями до указанного размера.

### Subbuf(buf b, int off, int length) buf

Функция *Subbuf* возвращает возвращает новый буфер, который содержит фрагмент буфера *b* с указанным смещением и длиной.

### UnBase64(str s) buf

Функция *UnBase64* преобразует строку в кодировке **base64** в значение типа *buf* и возвращает его.

### UnHex(str s) buf

Функция *UnHex* преобразует шестнадцатеричную строку в значение типа *buf* и возвращает его. Входящая строка должна содержать только шестнадцатеричные символы.

### Write(buf b, int off, buf src) buf

Функция *Write* записывает массив байт переменной *src* в переменную *b* начиная с указанного смещения. Данные записываются поверх существующих значений. Функция возвращает переменную *b*.


# Время

Здесь описаны операторы и функции для работы с датами и временем (тип **time**).

* [int( time t ) int](/stdlib/time#int-time-t-int)
* [time( int unixtime ) time](/stdlib/time#time-int-unixtime-time)
* [AddHours( time t, int hours ) time](/stdlib/time#addhours-time-t-int-hours-time)
* [Date( int year month day ) time](/stdlib/time#date-int-year-month-day-time)
* [DateTime( int year month day hour minute second ) time](/stdlib/time#datetime-int-year-month-day-hour-minute-second-time)
* [Days( time t ) int](/stdlib/time#days-time-t-int)
* [Format( str layout, time t ) str](/stdlib/time#format-str-layout-time-t-str)
* [Now( ) time](/stdlib/time#now-time)
* [ParseTime( str layout, str value ) time](/stdlib/time#parsetime-str-layout-str-value-time)
* [str( time t ) str](/stdlib/time#str-time-t-str)
* [UTC( time t ) time](/stdlib/time#utc-time-t-time)
* [Weekday( time t ) int](/stdlib/time#weekday-time-t-int)
* [YearDay( time t ) int](/stdlib/time#yearday-time-t-int)

## Типы

### time

Тип *time* имеет следующие поля:

* **int Year** - год
* **int Month** - месяц
* **int Day** - день месяца
* **int Hour** - часы
* **int Minute** - минуты
* **int Second** - секунды
* **bool UTC** - если равно *true*, то это UTC время, в противном случае, считается локальное время.

## Операторы

| Оператор         | Результат | Описание                                                                                       |
| ---------------- | --------- | ---------------------------------------------------------------------------------------------- |
| time **==** time | bool      | Возвращается *true*, если два времени равны и *false*, в противном случае.                     |
| time **>** time  | bool      | Возвращается *true*, если первое время больше чем второе и *false*, в противном случае.        |
| time **<** time  | bool      | Возвращается *true*, если первое время меньше чем второе и *false*, в противном случае.        |
| time **!=** time | bool      | Возвращается *true*, если два времени не равны и *false*, в противном случае.                  |
| time **>=** time | bool      | Возвращается *true*, если первое время больше или равно второму и *false*, в противном случае. |
| time **<=** time | bool      | Возвращается *true*, если первое время меньше или равно второму и *false*, в противном случае. |
| time **=** time  | time      | Оператор присваивания.                                                                         |

## Функции

### int(time t) int

Функция *int* конвертирует значение *time* в Unix время, количество секунд с 1 января 1970 UTC и возвращает его.

### time(int unixtime) time

Функция *time* конвертирует данное Unix время *unixtime*, количество секунд с 1 января 1970 UTC в структуру *time* и возвращает её.

### AddHours(time t, int hours) time

Функция *AddHours* возвращает новое время, соответствующее указанному, с добавлением *hours* часов. Параметр *hours* может быть отрицательным.

### Date(int year month day) time

Функция *Date* возвращает структуру типа *time* c указанной датой.

### DateTime(int year month day hour minute second) time

Функция *DateTime* возвращает структуру типа *time* c указанным локальным временем. Также, вы можете инициализировать переменную времени подобным образом

```
time t = {Year: 2018, Month: 12, Day: 12}
```

### Days(time t) int

Функция *Days* возвращает количество дней в месяце, в котором находится указанное время.

### Format(str layout, time t) str

Функция *Format* возвращает текстовое представление времени в соответствии со строкой *layout*. Функция берет строку токенов и заменяет их соответствующими значениями.

|                    | Токен | Вывод             |
| ------------------ | ----- | ----------------- |
| **Год**            | YYYY  | 2019              |
|                    | YY    | 19                |
| **Месяц**          | MMMM  | January           |
|                    | MMM   | Jan               |
|                    | MM    | 01..12            |
|                    | M     | 1..12             |
| **День**           | DD    | 01..31            |
|                    | D     | 1..31             |
| **День недели**    | dddd  | Monday            |
|                    | ddd   | Mon               |
| **AM/PM**          | PM    | AM PM             |
|                    | pm    | am pm             |
| **Час**            | HH    | 00..23            |
|                    | hh    | 01..12            |
|                    | h     | 1..12             |
| **Минута**         | mm    | 00..59            |
|                    | m     | 1..59             |
| **Секунда**        | ss    | 00..59            |
|                    | s     | 1..59             |
| **Временная зона** | tz    | MST               |
|                    | zz    | -0700 ... +0700   |
|                    | z     | -07:00 ... +07:00 |

### Now() time

Функция *Now* возвращает текущее локальное время.

### ParseTime(str layout, str value) time

Функция *ParseTime* разбирает отформатированную строку и возвращает соответствующее время. Список токенов такой же как в функции **Format**.

```
run str {
  time t &= ParseTime(`MMM D, YYYY at h:mmpm (zz)`, `Jun 7, 2019 at 6:05am (+0300)`)
  time t1 &= ParseTime(`YY/MM/DD HH:mm:s`, `19/05/29 03:21:3`)
  return Format(`YY/MM/DD HH:mm:ss zz`, UTC(t)) + Format(` YY/MM/DD HH:mm:ss`, UTC(t1))
}
// 19/06/07 03:05:00 +0000 19/05/29 03:21:03
```

### str(time t) str

Функция *str* конвертирует указанное время в строку формата **YYYY-MM-DD HH:mm:ss**.

### UTC(time t) time

Функция *UTC* конвертирует локальное время в UTC и возвращает новую структуру. Если время *t* уже было UTC, то возвращается его копия.

### Weekday(time t) int

Функция *Weekday* возвращает номер дня недели. 0 - воскресенье, 1 - понедельник и т.д.

### YearDay(time t) int

Функция *YearDay* возвращает номер дня в году у указанного времени.


# Конвертация

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

* [Json( obj o ) str](/stdlib/encoding#json-obj-o-str)
* [JsonToObj( str s ) obj](/stdlib/encoding#jsontoobj-str-s-obj)
* [StructDecode( b buf, struct s )](/stdlib/encoding#structdecode-buf-b-struct-s)
* [StructEncode( struct s ) buf](/stdlib/encoding#structencode-struct-s-buf)

## Функции

### Json( obj o ) str

Функция *Json* преобразует переменную типа *obj* в **json** строку.

### JsonToObj( str s ) obj

Функция *JsonToObj* преобразует **json** строку в переменную типа *obj*.

```go
run str {
  return Json(JsonToObj(`{
         "int": 1234,
         "str": "value",
         "float": -45.67,
          "list":[{"on": true},
            "sub 2",
            "sub 3",
            {
                "q": "OK"
            }]
    }`))
}
// Result {"float":-45.67,"int":1234,"list":[{"on":true},"sub 2","sub 3",{"q":"OK"}],"str":"value"}
```

### StructDecode( buf b, struct s )

Функция *StructDecode* преобразует двоичные данные переменной типа *buf* в значения полей указанной структурной переменной. Двоичные данные должны быть созданы функцией *StructEncode*.

```go
  time t
  StructDecode(StructEncode(Now()), t)
```

### StructEncode( struct s ) buf

Функция *StructEncode* преобразует переменную структурного типа в двоичный вид и сохраняет результат в переменную типа *buf*. Сохраняются только поля типа: **int,bool,char,float,buf,str**. Поля остальных типов пропускаются.

```go
struct tmp {
    str head
    int i
}

run str {
  tmp t1 = {head: `HEADER`, i: -356}
  buf bout = StructEncode(t1)
  ...
}
```


# Консоль

Здесь описаны функции для работы с консолью.

* [ClearCarriage( str input ) str](/stdlib/console#clearcarriage-str-input-str)
* [Print( anytype par... ) int](/stdlib/console#print-anytype-par-int)
* [Println( anytype par... ) int](/stdlib/console#println-anytype-par-int)
* [ReadString( str text ) str](/stdlib/console#readstring-str-text-str)

## Операторы

| Оператор     | Результат | Описание                                                                                                                                                                |
| ------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **\|\|** str | int       | Этот унарный оператор выводит строку в стандартный вывод, но перед этим он удаляет крайние пробельные символы в каждой строке. Возвращает количество записанных байтов. |

```
run {
   ||`One
      Two
      Three
      `
}
/* It prints
One
Two
Three
*/
```

## Функции

### ClearCarriage(str input) str

Функция *ClearCarriage* очищает строку от всех сиволов возврата каретки **\r** назад до предыдущего символа перевода строки **\n**. Рекомендуется использовать *ClearCarriage*, если вы получаете вывод консоли при вызове функции **Run**. Функция вызывается автоматически при вызове *str s = $ command line*.

```go
buf dirout
Run("myapp", stdout: dirout)
// dirout == Start\nPercent: 0%\rPercent: 50%\rPercent: 100%\nFinish
ret = ClearCarriage(str(dirout))
// ret == Start\nPercent: 100%\nFinish
```

### Print(anytype par...) int

Функция *Print* форматирует по умолчанию все переданные операнды любых типов и выводит их в стандартный вывод. Пробелы являются разделителями при выводе параметров, если ни один из соседних параметров не является строкой. Функция *Print* возвращает количество записанных байтов.

### Println(anytype par...) int

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

### ReadString(str text) str

Функция *ReadString* читает данные из стандартного ввода до получения символа '\n' (нажатие Enter). Она возвращает строку содержащую введенные данные. Если параметр *text* не пустой, то функция выведет этот текст перед чтением данных.


# Константы

## Предопределенные константы

### CYCLE

Максимальное количество итераций в цикле. По умолчанию, равно 16000000.

### DEPTH

Максимальная вложенность исполняемых блоков. Ограничивает глубину рекурсии. По умолчанию, равно 1000.

### IOTA

Конcтанта *IOTA* используется для автоматического вычисления последовательности конcтант.

```go
const IOTA * 2 {
    ZERO  // 0
    TWO   // 2
    FOUR  // 4
}
```

### SCRIPT

Константа *SCRIPT* возвращает путь текущего скрипта. Если он не был указан, то возвращается имя *run*.

```go
// compile from file: /home/ak/gentee/scripts/myscript.g
run {
    Println(SCRIPT) // /home/ak/gentee/scripts/myscript.g
}

// compile from memory
run my_best_script {
    Println(SCRIPT) // my_best_script
}
```

### VERSION

Константа *VERSION* возвращает текущую версию компилятора Gentee.


# Контекст

В языке Gentee отсутствуют глобальные переменные. Одним из способов обмена данными является специальный ассоциативный массив строк. Любая функция может безопасно добавлять туда пары ключ-значение или получать значение по ключу. Кроме этого, в контекст встроена возможность подстановки других существующих значений из контекста. Например, если определены пары *"a": "String A"* и *"b": "String B"*, то *"#a# and #b#"* возвратит *"String A and String B"*. Ниже описаны функции и операторы для работы с контекстом.

* [Ctx( str input ) str](/stdlib/context#ctx-str-input-str)
* [CtxGet( str key ) str](/stdlib/context#ctxget-str-key-str)
* [CtxIs( str key ) bool](/stdlib/context#ctxis-str-key-bool)
* [CtxSet( str key, str val ) str](/stdlib/context#ctxset-str-key-str-val-str)
* [CtxSet( str key, bool b ) str](/stdlib/context#ctxset-str-key-bool-b-str)
* [CtxSet( str key, float f ) str](/stdlib/context#ctxset-str-key-float-f-str)
* [CtxSet( str key, int i ) str](/stdlib/context#ctxset-str-key-int-i-str)
* [CtxValue( str key ) str](/stdlib/context#ctxvalue-str-key-str)

## Операторы

| Оператор           | Результат | Описание                                                                            |
| ------------------ | --------- | ----------------------------------------------------------------------------------- |
| **#** ident        | str       | Тоже самое, что *CtxGet(key)*, где *ident* является ключом контекста.               |
| **##** str         | str       | Тоже самое, что *Ctx(str)*. Указывается любое выражение, которое возвращает строку. |
| ident **#=** str   | str       | Тоже самое, что *CtxSet(str key, str s)*, где *ident* - это ключ контекста.         |
| ident **#=** bool  | str       | Тоже самое, что *CtxSet(str key, bool b)*, где *ident* - это ключ контекста.        |
| ident **#=** float | str       | Тоже самое, что *CtxSet(str key, float f)*, где *ident* - это ключ контекста.       |
| ident **#=** int   | str       | Тоже самое, что *CtxSet(str key, int i)*, где *ident* - это ключ контекста.         |

```
run str {
  str s = ` #AºB#`
  AºB #= `ººº`
  b #= 71
  CD #= `#AºB# #b# == ` 
  return #CD + #b + ##s
}
// ººº 71 == 71 ººº
```

## Функции

### Ctx(str input) str

Функция *Ctx* заменяет в строке *input* подстроки **#keyname#** на значение соответствующего ключа, если он существует.

```
run str {
    CtxSetBool(`qq`, true)
    CtxSetFloat(`ff`, 3.1415)
    CtxSet(`out`, "it is #qq# that PI equals #ff#")
    return Ctx("#out#. #notexist#")
}
// it is true that PI equals 3.1415. #notexist#
```

### CtxGet(str key) str

Функция *CtxGet* получает значение ключа *key*, заменяет в нём все вхождения других ключей и возвращает полученную строку. Если указанный ключ отсутствует, то возвратится пустая строка.

```
func init {
   CtxSet(`a1`, `end`)
   CtxSet(`a2`, `=#a1#=`)
   CtxSet(`a3`, `+#a2#+#a1#`)
}

run str {
    init()
    return CtxGet(`a3`)
}
// +=end=+end
```

### CtxIs(str key) bool

Функция *CtxIs* возвращает *true*, если в контексте существует значение с указанным ключом. В противном случае, возвращается *false*.

### CtxSet(str key, str val) str

Функция *CtxSet* добавляет ключ и значение в контекст. Если ключ уже существует, то ему будет присвоено новое значение. Функция возвращает присвоенное значение ключа.

### CtxSet(str key, bool b) str

Функция *CtxSet* добавляет ключ и логическое значение *b* в контекст. Логическое значение будет преобразовано к строке *true* или *false*. Функция возвращает присвоенное значение ключа.

### CtxSet(str key, float f) str

Функция *CtxSet* добавляет ключ и число с плавающей точкой *f* в контекст. Число будет преобразовано в строку. Функция возвращает присвоенное значение ключа.

### CtxSet(str key, int i) str

Функция *CtxSet* добавляет ключ и целое число *i* в контекст. Число будет преобразовано в строку. Функция возвращает присвоенное значение ключа.

### CtxValue(str key) str

Функция *CtxValue* возвращает значение ключа *key* как есть. В отличие от функции **CtxGet**, она не заменяет вхождения других ключей. Если указанный ключ отсутствует, то возвратится пустая строка.

```
run str {
    CtxSet(`test`, `?value`)
    CtxSet(`param`, `#test# ==`)
    return CtxValue(`param`) + CtxValue(`nop`) + CtxGet(`param`)
}
// #test# ==?value ==
```


# Криптография

Ниже описаны криптографические функции.

* [AESDecrypt( str key, buf data ) buf](/stdlib/crypto#aesdecrypt-str-key-buf-data-buf)
* [AESEncrypt( str key, buf data ) buf](/stdlib/crypto#aesencrypt-str-key-buf-data-buf)
* [Md5( buf | str data ) buf](/stdlib/crypto#md-5-buf-or-str-data-buf)
* [RandomBuf( int size ) buf](/stdlib/crypto#randombuf-int-size-buf)
* [Sha256( buf | str data ) buf](/stdlib/crypto#sha-256-buf-or-str-data-buf)

## Функции

### AESDecrypt( str key, buf data ) buf

Функция *AESDecrypt* расшифровывает содержимое переменной типа *buf* с использованием ключа шифрования *key*. Зашифрованные данные должны быть получены с помощью функции *AESEncrypt*. Функция возвращает переменную типа *buf* с расшифрованными данными.

```go
buf encrypted = AESDecrypt(`my password`, encrypted)
```

### AESEncrypt( str key, buf data ) buf

Функция *AESEncrypt* шифрует содержимое переменной типа *buf* используя алгоритм AES-256. Параметр *key* является ключом шифрования. Функция возвращает переменную типа *buf* с зашифрованными данными. Используйте функцию *AESDecrypt* для расшифровки данных.

```go
buf crypted = AESEncrypt(`my password`, buf(`Test message`))
```

### Md5(buf|str data) buf

Функция *Md5* возвращает MD5 хэш переменной типа *buf* или *str*.

### RandomBuf(int size) buf

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

### Sha256(buf|str data) buf

Функция *Sha256* возвращает SHA256 хэш переменной типа *buf* или *str*.


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

Здесь описаны операторы и функции для работы с логическим типом **bool**.

* [int( bool b ) int](/stdlib/bool#int-bool-b-int)
* [str( bool b ) str](/stdlib/bool#str-bool-b-str)

## Операторы

| Оператор           | Результат | Описание                                                                |
| ------------------ | --------- | ----------------------------------------------------------------------- |
| bool **&&** bool   | bool      | Логическое И. Условие истинно, если истинны оба операнда.               |
| bool **\|\|** bool | bool      | Логическое ИЛИ. Условие истинно, если истинен хотябы один из операндов. |
| **!** bool         | bool      | Логическое НЕ.                                                          |
| bool **=** bool    | bool      | Присваивание.                                                           |

## Функции

### int(bool b) int

Функция *int* возвращает 1, если параметр имеет значение *true* и возвращает 0 в противном случае.

### str(bool b) str

Функция *str* возвращает строку "true", если параметр имеет значение *true* и возвращает строку "false" в противном случае.


# Массивы

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

* [bool( arr.typename a ) bool](/stdlib/array#bool-arr-typename-a-bool)
* [Join( arr.str a, str sep ) str](/stdlib/array#join-arr-str-a-str-sep-str)
* [Reverse( arr.typename a ) arr.typename](/stdlib/array#reverse-arr-typename-a-arr-typename)
* [Slice( arr.typename a, int start, int end ) arr.typename](/stdlib/array#slice-arr-typename-a-int-start-int-end-arr-typename)
* [Sort( arr.str a ) arr.str](/stdlib/array#sort-arr-str-a-arr-str)

## Операторы

| Оператор                             | Результат        | Описание                                                                       |
| ------------------------------------ | ---------------- | ------------------------------------------------------------------------------ |
| **\*** arr.typename                  | int              | Возвращает количество элементов в массиве.                                     |
| arr.typename **?**                   | bool             | Вызов *bool(arr.typename)*.                                                    |
| arr.typename **=** arr.typename      | arr.typename     | Присваивание.                                                                  |
| arr.typename **&=** arr.typename     | arr.typename     | Создать клон массива. Новая переменная будет работать с тем же набором данных. |
| arr.typename **+=** arr.typename     | arr.typename     | Добавляет элементы из одного массива к другому.                                |
| arr.str **+=** str                   | arr.str          | Добавление строки к массиву строк.                                             |
| arr.int **+=** int                   | arr.int          | Добавление целого числа к массиву чисел.                                       |
| arr.bool **+=** bool                 | arr.bool         | Добавление логического значения к массиву логических значений.                 |
| arr.arr.typename **+=** arr.typename | arr.arr.typename | Добавление массива к массиву массивов.                                         |
| arr.map.typename **+=** map.typename | arr.map.typename | Добавление ассоциативного массива к массиву ассоциативных массивов.            |
| arr.typename **\[** int **]**        | typename         | Присвоить/получить значение массива по индексу.                                |

## Функции

### bool(arr.typename a) bool

Функция *bool* возвращает *false*, если массив пустой. В противном случае, возвращается *true*.

### Join(arr.str a, str sep) str

Функция *Join* объединяет строки массива в одну строку. Разделительная строка *sep* вставляется между строками массива.

### Reverse( arr.typename a ) arr.typename

Функция *Reverse* меняет порядок элементов в массиве на противоположный и возвращает этот массив.

### Slice( arr.typename a, int start, int end ) arr.typename

Функция *Slice* создает новый массив с элементами от *start* (включая) до *end* (не включая). Функция возвращает созданный массив.

### Sort( arr.str a ) arr.str

Функция *Sort* сортирует переданный массив строк в порядке возрастания и возвращает его.


# Многопоточность

Здесь описаны операторы и функции для работы с потоками (тип **thread**).

* [Lock()](#lock)
* [resume( thread th )](#resume-thread-th)
* [SetThreadData(obj o)](#setthreaddata-obj-o)
* [sleep( int duration )](#sleep-int-duration)
* [suspend( thread th )](#suspend-thread-th)
* [terminate( thread th )](#terminate-thread-th)
* [ThreadData() obj](#threaddata-obj)
* [Unlock()](#unlock)
* [wait( thread th )](#wait-thread-th)
* [WaitAll()](#waitall)
* [WaitDone()](#waitdone)
* [WaitGroup( int count )](#waitgroup-int-count)

## Операторы

| Оператор            | Результат | Описание               |
| ------------------- | --------- | ---------------------- |
| thread **=** thread |           | Оператор присваивания. |

## Функции

### Lock()

Функция *Lock* блокирует доступ к глобальному ресурсу (мьютексу). Если он уже занят другим потоком, то текущий поток ждет его освобождения. Мьютекс должен быть освобожден с помощью функции *Unlock*.

### resume(thread th)

Функция *resume* продолжает работу потока, который был остановлен функцией *suspend*.

### SetThreadData(obj o)

Функция *SetThreadData* присваивает текущему потоку переменную типа *obj*. Значение переменной может быть получено функцией *ThreadData*.

### sleep(int duration)

Функция *sleep* останавливает выполнение текущего потока на как минимум *duration* миллисекунд.

### suspend(thread th)

Функция *suspend* приостанавливает поток *th*. Используйте функцию *resume* для продолжения работы потока.

### terminate(thread th)

Функция *terminate* прекращает работу потока. Если поток уже завершен, то функция ничего не делает.

### ThreadData() obj

Функция *ThreadData* возвращает объект, который был присвоен текущему потоку. Переменная типа *obj* присваивается потоку функцией *SetThreadData*.

### Unlock()

Функция *Unlock* освобождает доступ к глобальному ресурсу (мьютексу).

### wait(thread th)

Функция *wait* ожидает окончания работы потока *th*. Если поток уже завершен, то функция ничего не делает.

### WaitAll()

Функция *WaitAll* ожидает когда счётчик *WaitGroup* станет равен нулю.

```go
run {
  int count = 3
  WaitGroup(count)
  for i in 1..count {
    go {
      // ...
      WaitDone()
    }
  }
  WaitAll()
}
```

### WaitDone()

Функция *WaitDone* уменьшает счётчик *WaitGroup* на единицу.

### WaitGroup(int count)

Функция *WaitGroup* создает *WaitGroup* счётчик потоков, которые должны завершится вызовом функции *WaitDone*. *count* - начальное значение счётчика.


# Множества

Здесь описаны операторы и функции для работы с массивом логических значений (тип **set**).

* [arr( set s ) arr.int](/stdlib/sets#arr-set-s-arr-int)
* [set( arr.int a ) set](/stdlib/sets#set-arr-int-a-set)
* [set( str s ) set](/stdlib/sets#set-str-s-set)
* [str( set s ) str](/stdlib/sets#str-set-s-str)
* [Set( set s, int index ) set](/stdlib/sets#set-set-s-int-index-set)
* [Toggle( set s, int index ) bool](/stdlib/sets#toggle-set-s-int-index-bool)
* [UnSet( set s, int index ) set](/stdlib/sets#unset-set-s-int-index-set)

## Операторы

| Оператор             | Результат | Описание                                                                                                           |
| -------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
| **\*** set           | int       | Возвращает размер массива.                                                                                         |
| **^** set            | set       | Возвращает новое множество, которое обратно указанному. *!s\[i]* для каждого элемента.                             |
| set **=** set        | set       | Оператор присваивания.                                                                                             |
| set **&=** set       | set       | Создает клон множества. Новая переменная будет работать с тем же набором данных.                                   |
| set **+=** set       | set       | Добавить значение одного множества к другому.                                                                      |
| set **&** set        | set       | Возвращает множество, которое является пересечением двух множеств. *left\[i] && right\[i]* для каждого элемента.   |
| set **\|** set       | set       | Возвращает множество, которое является объединением двух множеств. *left\[i] \|\| right\[i]* для каждого элемента. |
| set **\[** int **]** | bool      | Установить/получить элемент множества.                                                                             |

## Функции

### arr(set s) arr.int

Функция *arr* конвертирует множество *set* в массив целых чисел, который содержит индексы элементов множества.

### set(str s) set

Функция *set* конвертирует строку в множество *set* и возвращает его. Строка должна содержать только символы 1 и 0.

### set(arr.int a) set

Функция *set* конвертирует массив целых чисел в множество *set* и возвращает его. Результирующее множество будет иметь элементы с соответствующими индексами.

```
run arr.int {
  set s &= {780, 99, 128, 105, 136}
  arr.int as = arr(s)
  as += 330
  s &= set(as)
  return arr(s) // [99 105 128 136 330 780]
}
```

### str(set s) str

Функция *str* конвертирует множество в строку и возвращает её. Результирующая строка содержит только символы 1 и 0.

### Set(set s, int index) set

Функция *Set* добавляет элемент к множеству. Эквивалентно *s\[index] = true*. Функция возвращает *s*.

### Toggle(set s, int index) bool

Функция *Toggle* добавляет элемент множеству, если его не существует, в противном случае, элемент удаляется. Эквивалентно *s\[index] = !s\[index]*. Функция возвращает предыдущее состояние - *true*, если элемент существовал и *false* в противном случае.

### UnSet(set s, int index) set

Функция *UnSet* удаляет элемент из множества. Эквивалентно *s\[index] = false*. Функция возвращает *s*.


# Объекты

Тип **obj** служит для хранения значений следующих типов - **int, bool, float, str, arr.obj, map.obj**. Если объекту не присвоено никакое значение, то он равен **nil**. Объекту можно присваивать значения типа, который отличается от текущего.\
Здесь описаны операторы и функции для работы с объектами.

* [arr( obj o ) arr.obj](/stdlib/obj#arr-obj-o-arr-obj)
* [arrstr( obj o ) arr.str](/stdlib/obj#arrstr-obj-o-arr-str)
* [bool( obj o ) bool](/stdlib/obj#bool-obj-o-bool)
* [bool( obj o, bool def ) bool](/stdlib/obj#bool-obj-o-bool-def-bool)
* [float( obj o ) float](/stdlib/obj#float-obj-o-float)
* [float( obj o, float def ) float](/stdlib/obj#float-obj-o-float-def-float)
* [int( obj o ) int](/stdlib/obj#int-obj-o-int)
* [int( obj o, int def ) int](/stdlib/obj#int-obj-o-int-def-int)
* [IsArray( obj o ) bool](/stdlib/obj#isarray-obj-o-bool)
* [IsMap( obj o ) bool](/stdlib/obj#ismap-obj-o-bool)
* [IsNil( obj o ) bool](/stdlib/obj#isnil-obj-o-bool)
* [item( obj o, int i ) obj](/stdlib/obj#item-obj-o-int-i-obj)
* [item( obj o, str s ) obj](/stdlib/obj#item-obj-o-str-s-obj)
* [map( obj o ) map.obj](/stdlib/obj#map-obj-o-map-obj)
* [obj( arr.typename a ) obj](/stdlib/obj#obj-arr-typename-a-obj)
* [obj( bool b ) obj](/stdlib/obj#obj-bool-b-obj)
* [obj( float f ) obj](/stdlib/obj#obj-float-f-obj)
* [obj( int i ) obj](/stdlib/obj#obj-int-i-obj)
* [obj( map.typename m ) obj](/stdlib/obj#obj-map-typename-m-obj)
* [obj( str s ) obj](/stdlib/obj#obj-str-s-obj)
* [Sort( arr.obj o, cmpobjfunc cmpfunc ) arr.obj](/stdlib/obj#sort-arr-obj-o-cmpobjfunc-cmpfunc-arr-obj)
* [str( obj o ) str](/stdlib/obj#str-obj-o-str)
* [str( obj o, str def ) str](/stdlib/obj#str-obj-o-str-def-str)
* [Type( obj o ) str](/stdlib/obj#type-obj-o-str)

## Типы

### fn cmpobjfunc(obj, obj) int

Тип функций **cmpobjtype** служит для сравнения двух объектов. Функции этого типа используются для сортировки объектов в массиве.

## Операторы

| Оператор                 | Результат | Описание                                                                                                                          |
| ------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------- |
| \*obj                    | int       | Если объект является *arr.obj* или *map.obj*, то возвращается количество элементов в массиве. В противном случае, возвращается 0. |
| obj **?**                | bool      | Вызов *bool(obj)*.                                                                                                                |
| obj **=** arr.typename   | obj       | Присваивание массива объекту.                                                                                                     |
| obj **=** bool           | obj       | Присваивание логического значения объекту.                                                                                        |
| obj **=** float          | obj       | Присваивание десятичного числа объекту.                                                                                           |
| obj **=** int            | obj       | Присваивание числа объекту.                                                                                                       |
| obj **=** map.typename   | obj       | Присваивание ассоциативного массива объекту.                                                                                      |
| obj **=** obj            | obj       | Присваивание объектов.                                                                                                            |
| obj **=** str            | obj       | Присваивание строки объекту.                                                                                                      |
| obj **+=** obj           | obj       | Добавление объекта к массиву объектов.                                                                                            |
| obj **&=** obj           | obj       | Создать клон объекта. Новая переменная будет работать с тем же набором данных.                                                    |
| obj **\[** int/str **]** | obj       | Присвоить/получить значение массива по индексу. Если объект не является *arr.obj* или *map.obj*, то возвращается ошибка.          |

## Функции

### arr(obj o) arr.obj

Функция *arr* возвращает массив объектов. Объект *o* должен быть массивом, в противном случае возвращается ошибка. При вызове функции не создается нового массива, а возвращается текущий массив, который содержит объект *o*.

### arrstr(obj o) arr.str

Функция *arrstr* конвертирует массив объектов в массив строк. Объект *o* должен быть массивом, в противном случае возвращается ошибка. Функция возвращает полученный массив строк.

### bool(obj o) bool

Функция *bool* возвращает логическое значение текущего типа. Например, если объект содержит строку, то возвращается результат вызова *bool(str)*. Если объект не определен, то возвращается ошибка.

### bool(obj o, bool def) bool

Функция *bool* возвращает логическое значение текущего типа. Если объект не определен, то возвращается второй параметр.

### float(obj o) float

Функция *float* конвертирует объект в действительное число. Объект должен содержать значение типа **str, int, float**, в противном случае, возвращается ошибка.

### float(obj o, float def) float

Функция *float* конвертирует объект в действительное число. Если объект не определен, то возвращается второй параметр.

### int(obj o) int

Функция *int* конвертирует объект в целое число. Объект должен содержать значение типа **str, int, float, bool**, в противном случае, возвращается ошибка.

### int(obj o, int def) int

Функция *int* конвертирует объект в целое число. Если объект не определен, то возвращается второй параметр.

### IsArray(obj o) bool

Функция *IsArray* возвращает *true*, если объект является массивом. В противном случае, функция возвращает *false*.

### IsMap(obj o) bool

Функция *IsMap* возвращает *true*, если объект является ассоциативным массивом (map). В противном случае, функция возвращает *false*.

### IsNil(obj o) bool

Функция *IsNil* возвращает *true*, если объект не определен (равен **nil**). В противном случае, функция возвращает *false*.

### item(obj o, int i) obj

Функция *item* возвращает i-й элемент объекта. Объект должен иметь тип **arr.obj**. Если элемент отсутствует, то возвращается пустой объект.

### item(obj o, str s) obj

Функция *item* возвращает значение ключа **s**. Объект должен иметь тип **map.obj**. Если элемент отсутствует, то возвращается пустой объект.

### map(obj o) map.obj

Функция *map* возвращает ассоциативный массив объектов. Объект *o* должен быть ассоциативным массивом (map), в противном случае возвращается ошибка. При вызове функции не создается нового массива, а возвращается текущий *map*, который содержит объект *o*.

### obj(arr.typename a) obj

Функция *obj* конвертирует массив типа *arr* в объект.

### obj(bool b) obj

Функция *obj* создает объект с указанными логическим значением.

### obj(float f) obj

Функция *obj* создает объект с указанными **float** значением.

### obj(int i) obj

Функция *obj* создает объект с указанными **int** значением.

### obj(map.typename m) obj

Функция *obj* конвертирует ассоциативный массив типа *map* в объект.

### obj(str s) obj

Функция *obj* создает объект с указанными **str** значением.

### Sort(arr.obj o, cmpobjfunc cmpfunc) arr.obj

Функция *Sort* сортирует массив объектов и возвращает его. Сортировка происходит с помощью функции типа **cmpobjfunc**.

```go
func mySort(obj left, obj right) int {
  if str(left) < str(right) : return -1
  if str(left) > str(right) : return 1
  return 0
}

run str {
  arr a = {"qwr","7","10","ab","тест","абв", "ka"}
  obj o = a
  Sort( arr(o), &mySort.cmpobjfunc )
  ...
}
```

### str(obj o) str

Функция *str* преобразует объект в строку и возвращает её.

### str(obj o, str def) str

Функция *str* преобразует объект в строку и возвращает её. Если объект не определен, то возвращается второй параметр.

### Type(obj o) str

Функция *Type* возвращает тип значения указанного объекта. Могут возвращаться следующие типы: **int, bool, float, str, arr.obj, map.obj**. Если объект не определен, то возвращается **nil**.


# Процесс

Здесь описаны операторы и функции для работы с процессами и приложениями. Функции *Args* и *ArgCount* работают с командной строкой любого формата. Для корректной работы остальных *Arg..* функций необходимо, чтобы командная строка имела следующий формат.

```go
CmdLine = [ CmdOptions ] ["-"] [ CmdParameters ]
CmdParameters = { CmdParameter }
CmdParameter = ParamWithoutSpace | "Param With Spaces" | 'Param With Spaces'
CmdOptions = {CmdOption}
CmdOption = "-" | "--" {letter} [ CmdOptionValue | CmdOptionValues ]
CmdOptionValue = "=" | ":" CmdParameter
CmdOptionValues = " " CmdParameters
```

```
-p="my value" --flag - one two three
-i:10 -n:Bob "one par" two three
--ext "*.txt" .js .html -o=/home/ak/dest /home/ak/in1 /home/ak/in2
```

* [Arg( str name ) str](/stdlib/process#arg-str-name-str)
* [Arg( str name, str def ) str](/stdlib/process#arg-str-name-str-def-str)
* [Arg( str name, int def ) int](/stdlib/process#arg-str-name-int-def-int)
* [ArgCount() int](/stdlib/process#argcount-int)
* [Args() arr.str](/stdlib/process#args-arr-str)
* [Args( str name ) arr.str](/stdlib/process#args-str-name-arr-str)
* [ArgsTail() arr.str](/stdlib/process#argstail-arr-str)
* [IsArg( str name ) bool](/stdlib/process#isarg-str-name-bool)
* [Open( str path )](/stdlib/process#open-str-path)
* [OpenWith( str app, str path )](/stdlib/process#openwith-str-app-str-path)
* [Run( str cmd, str params... )](/stdlib/process#run-str-cmd-str-params)
* [SplitCmdLine( str cmdline ) arr.str](/stdlib/process#splitcmdline-str-cmdline-arr-str)
* [Start( str cmd, str params... )](/stdlib/process#start-str-cmd-str-params)

## Операторы

| Operator                 | Result | Description                                       |
| ------------------------ | ------ | ------------------------------------------------- |
| **$** command line       |        | Запустить командную строку.                       |
| str = **$** command line |        | Запустить командную строку и возвратить её вывод. |

## Функции

### Arg(str name) str

Функция *Arg* возвращает значение параметра с указанным именем. Если параметр не был указан при запуске скрипта, то возвратится пустая строка. В имени параметра можно не указывать начальный символ **-**.

### Arg(str name, str def) str

Функция *Arg* возвращает значение параметра с указанным именем **name**. Если параметр не был указан при запуске скрипта, то возвратится значение **def**. В имени параметра можно не указывать начальный символ **-**.

### Arg(str name, int def) int

Функция *Arg* возвращает числовое значение параметра с указанным именем **name**. Если параметр не был указан при запуске скрипта, то возвратится число **def**. В имени параметра можно не указывать начальный символ **-**.

### ArgCount() int

Функция *ArgCount* возвращает количество параметров командной строки с которыми был запущен скрипт.

### Args() arr.str

Функция *Args* возвращает список всех параметров и опций командной строки с которыми был запущен скрипт.

### Args(str name) arr.str

Функция *Args* возвращает список значений параметра с именем **name**. В имени параметра можно не указывать начальный символ **-**.

```
// --ext .txt .js .html -o=/home/ak/dest /home/ak/in1 /home/ak/in2
list = Args(`--ext`) 
// list == [.txt, .js, .html]
```

### ArgsTail() arr.str

Функция *ArgsTail* возвращает список параметров командной строки после опций. Можно явно указать начало таких параметров с помощью **-**.

```
// --ext .txt .js .html -o=/home/ak/dest /home/ak/in1 /home/ak/in2
list = ArgsTail() // list == [/home/ak/in1, /home/ak/in2]

// -i=false - val0 -value1 "value 2" 
list = ArgsTail() // list == [val0, -value1, value 2]
```

### IsArg(str name) bool

Функция *IsArg* возвращает *true*, если в командной строке имеется опция с указанным именем. В противном случае, возвращается *false*. В имени параметра можно не указывать начальный символ **-**.

### Open(str path)

Функция *Open* открывает файл, директорию или URI адрес приложением по умолчанию для объектов данного типа. Скрипт не ожидает завершения работы.

### OpenWith(str app, str path)

Функция *OpenWith* открывает файл, директорию или URI адрес в указанном приложении. Скрипт не ожидает завершения работы.

### Run(str cmd, str params...)

**Опциональные параметры**

* **buf stdin** - буфер, который будет передан приложению как стандартный ввод.
* **buf stdout** - буфер, в который будет записан стандартный вывод приложения.
* **buf stderr** - буфер, в который будет записан стандартный вывод ошибок приложения.

Функция *Run* запуcкает указанную программу *cmd* c параметрами и ожидает её окончание. Дополнительно, вы можете переопределить стандартный ввод и вывод.

```go
    buf dirout
    Run("dir", stdout: dirout)
    Run("bash", stdin: buf(
      |`echo "dirs"
        #comment    
        echo "%{str(dirout)}"`
    ))
```

### SplitCmdLine(str cmdline) arr.str

Функция *SplitCmdLine* разбирает входящую строку с параметрами командной строки и возвращает массив параметров.

```go
run str {
    return SplitCmdLine(`param1 "second par" "qwert\"y" 100 'oo ps'
-lastparam`).Join(`=`)
}
// returns param1=second par=qwert"y=100=oo ps=-lastparam
```

### Start(str cmd, str params...)

**Опциональные параметры**

* **buf stdin** - буфер, который будет передан приложению как стандартный ввод.

Функция *Start* запуcкает указанную программу *cmd* c параметрами и выполняет скрипт дальше. Дополнительно, вы можете передать буфер в качестве стандартного ввода.

```go
    Start("echo", "hello, world!")
    Start("bash", stdin: buf(
      |`./myscript1.sh
        ./myscript2.sh`
    ))
```


# Путь

Здесь описаны функции для работы с путями разделяемых слешами.

* [AbsPath( str path ) str](/stdlib/path#abspath-str-path-str)
* [BaseName( str path ) str](/stdlib/path#basename-str-path-str)
* [Dir( str path ) str](/stdlib/path#dir-str-path-str)
* [Ext( str path ) str](/stdlib/path#ext-str-path-str)
* [JoinPath( str path... ) str](/stdlib/path#joinpath-str-path-str)
* [MatchPath( str pattern, str path ) bool](/stdlib/path#matchpath-str-pattern-str-path-bool)
* [Path( finfo fi ) str](/stdlib/path#path-finfo-fi-str)

## Функции

### AbsPath(str path) str

Функция *AbsPath* возвращает абсолютное представление пути.

### BaseName(str path) str

Функция *BaseName* возвращает последний элемент пути. Если есть последний слеш, то он удаляется. Если путь пустой, то возвращается ".".

### Dir(str path) str

Функция *Dir* возвращает путь, исключая последний элемент. Как правило, это путь директории.

### Ext(str path) str

Функция *Ext* возвращает расширение файла. Расширение возвращается без точки.

### JoinPath(str path...) str

Функция *JoinPath* объединяет все указанные пути в один путь, вставляя соответствующий разделитель, где он необходим.

### MatchPath(str pattern, str path) bool

Функция *MatchPath* проверяет, подходит ли данное имя к указанному шаблону. Функция проверяет шаблон полностью для указанного пути, а не для подстроки. Вы можете в качестве шаблона использовать регулярное выражение. Для этого, добавьте в начало и конец символ */*.

* '\*' - любая последовательность, кроме символа разделителя
* '?' - любой одиночный символ, кроме символа разделителя

```
MatchPath(`*.txt`, `myfile.txt`)       // true
MatchPath(`?a?.pdf`, `1ab.pdf`)        // true
MatchPath(`/home/ak/my.pdf`, `*.pdf`)         // false
MatchPath(`/home/ak/my.pdf`, `/home/*/my.*`)  // true
MatchPath(`/user/`, `/home/user/myfile`) // true
```

### Path(finfo fi) str

Функция *Path* объединяет поля *Name* и *Dir* в переменной типа *finfo* и возвращает полученный путь.


# Рантайм

Здесь описаны функции для работы с виртуальной машиной во время выполнения скрипта.

* [error( int id, str text, anytype pars... )](/stdlib/runtime#error-int-id-str-text-anytype-pars)
* [ErrID( error err ) int](/stdlib/runtime#errid-error-err-int)
* [ErrText( error err ) str](/stdlib/runtime#errtext-error-err-str)
* [ErrTrace( error err ) arr.trace](/stdlib/runtime#errtrace-error-err-arr-trace)
* [exit( int code )](/stdlib/runtime#exit-int-code)
* [Progress( int id inc )](/stdlib/runtime#progress-int-id-inc)
* [ProgressEnd( int id )](/stdlib/runtime#progressend-int-id)
* [ProgressStart( int total ptype, str src dest ) int](/stdlib/runtime#progressstart-int-total-ptype-str-src-dest-int)
* [Trace() arr.trace](/stdlib/runtime#trace-arr-trace)

## Типы

### trace

Тип *trace* служит для хранения информации о вызове функции и имеет следующие поля:

* **str Path** - имя файла
* **str Entry** - текущая функция
* **str Func** - вызываемая функция
* **int Line** - строка в исходном коде
* **int Pos** - позиция в строке, где произошёл вызов

## Функции

### error(int id, str text, anytype pars...)

Функция *error* генерирует ошибку времени выполнения скрипта.

* *id* - код ошибки,
* *text* - текст ошибки,
* *pars* - необязательные параметры. Если они указаны, то *text* должен содержать соответствующий шаблон

  как в функции [Format](https://gentee.github.io/docs-gentee-ru/stdlib/string#formatstr-s-anytype-args-str).

```go
    error(10, `Error message %{ 10 }`)
    error(10, `Error message %d`, 10)
```

### ErrID(error err) int

Функция *ErrID* возвращает идентификатор ошибки *err*. Эта функция может использоваться внутри конструкции **try-catch** для обработки ошибок.

```go
run {
  try {
    .....
    error(101, `oooops`)
  }
  catch err {
    if ErrID(err) == 101 {
      recover
    } elif ErrID(err) < 100 {
      retry
    }
  }
}
```

### ErrText(error err) str

Функция *ErrText* возвращает текст ошибки *err*. Эта функция может использоваться внутри конструкции **try-catch** для обработки ошибок.

### ErrTrace(error err) arr.trace

Функция *ErrTrace* возвращает стек вызовов функций на момент возникновения ошибки *err*. Эта функция может использоваться внутри конструкции **try-catch** для обработки ошибок.

### exit(int code)

Функция *exit* прекращает работу скрипта. Функция может быть вызвана в любом потоке. Скрипт возвращает значение *code*.

```go
func ok(int par) int {
  if par == 0 : exit(0)
  return 3 * par
}
run int {
  int sum
  for i in 10..-10 {
    sum += ok(i)
  }
  return sum
}
```

### Progress( int id inc )

Функция *Progress* увеличивает величину счётчика процесса на значение параметра *inc*. *id* - идентификатор прогресс-бара возвращённый функцией *ProgressStart*. Функция *Progress* вызывает Go функцию *ProgressFunc*, которая должна быть определена в настройках при запуске скрипта.

```go
  int total = 200
  int prog = ProgressStart(total, 100, `counter`, ``)
  for i in 1..5 {
    Progress(prog, 40)
  }
  ProgressEnd(prog)
```

### ProgressEnd( int id )

Функция *ProgressEnd* удаляет счётчик процесса с идентификатором *id*.

### ProgressStart( int total ptype, str src dest ) int

Функция *ProgressStart* создаёт счётчик процесса и возвращает его идентификатор. *total* - максимальная величина счётчика. *ptype* - тип счётчика, может быть любое число. *src* - имя источника. *dest* - имя целевого объекта. Функции для работы с прогрессом-баром ничего не отображают, они вызывают функцию *ProgressFunc*, которая должна быть определена в [настройках](/golang/reference) при запуске скрипта. В функции *ProgressFunc* вы можете отображать состояние процесса удобным для вас способом. После окончания работы с данным счётчиком необходимо вызвать функцию *ProgressEnd* для его удаления.

### Trace() arr.trace

Функция *Trace* возвращает стек вызовов функций.


# Регулярные выражения

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

* [FindFirstRegExp( str src, str re ) arr.str](/stdlib/regexp#findfirstregexp-str-src-str-re-arr-str)
* [FindRegExp( str src, str re ) arr.arr.str](/stdlib/regexp#findregexp-str-src-str-re-arr-arr-str)
* [Match( str s, str re ) bool](/stdlib/regexp#match-str-s-str-re-bool)
* [RegExp( str src, str re ) str](/stdlib/regexp#regexp-str-src-str-re-str)
* [ReplaceRegExp( str src, str re, str repl ) str](/stdlib/regexp#replaceregexp-str-src-str-re-str-repl-str)

## Функции

### FindFirstRegExp(str src, str re) arr.str

Функция *FindFirstRegExp* находит первое вхождение регулярного выражения *re* в указанной строке *src*. Функция возвращает массив строк. Первый элемент содержит подстроку совпадающую с регулярным выражением, остальные элементы содержат значения групп **(...)**, если они определены в регулярном выражении.

```go
arr.str a &= FindFirstRegExp(`This45i33s a isi777s inis1i2sg`, `is(\d*)i(\d+)s`)
// a = {`is45i33s`, `45`, `33`}
```

### FindRegExp(str src, str re) arr.arr.str

Функция *FindRegExp* находит все вхождения регулярного выражения *re* в указанной строке *src*. Функция возвращает массив массивов. Первый элемент в каждом из массивов содержит подстроку совпадающую с регулярным выражением.

```go
arr.arr.str a &= FindRegExp(`My email is xyz@example.com`, `(\w+)@(\w+)\.(\w+)`)
// a = { { `xyz@example.com`, `xyz`, `example`, `com`} }
a &= FindRegExp(`This is a test string`, `i.`)
// a = { { `is` }, {`is`}, {`in`} }
```

### Match(str s, str re) bool

Функция *Match* определяет содержит ли данная строка вхождение указанного регулярного выражения.

```go
bool a = Match(`somethiabng striabnbg`, `a.b`)  // false
a = Match(`somethianbg string`, `a.b`) // true
```

### RegExp(str src, str re) str

Функция *RegExp* возвращает первое вхождение регулярного выражения *re* в указанной строке *src*. Если соответствия не найдено, то возвращается пустая строка.

```go
  str input = "This is a string тестовое значение"
  ret = RegExp(input, `is (.{2})`) + RegExp(input, `е(.+?)е`)
  // isстово
```

### ReplaceRegExp(str src, str re, str repl) str

Функция *ReplaceRegExp* находит все вхождения регулярного выражения *re* в указанной строке *src* и заменяет их на строку *repl*. В параметре *repl* можно указывать *$i* или *${i}* для i-го подсовпадения.

```go
str s = ReplaceRegExp("This is a string", `i(.{2})`, "xyz") 
// Thxyzxyza strxyz
s = ReplaceRegExp(" email is xyz@example.com", `(\w+)@(\w+)\.(\w+)`, "${3}.${2}@zzz")
// email is com.example@zzz
```


# Сеть

Здесь описаны функции для работы с сетью/интернетом.

* [Download( str url, str filename ) int](/stdlib/network#download-str-url-str-filename-int)
* [HeadInfo( str url ) hinfo](/stdlib/network#headinfo-str-url-hinfo)
* [HTTPGet( str url ) buf](/stdlib/network#httpget-str-url-buf)
* [HTTPPage( str url ) str](/stdlib/network#httppage-str-url-str)
* [HTTPRequest( str url, str method, map.str params, map.str headers ) str](/stdlib/network#httprequest-str-url-str-method-map-str-params-map-str-headers-str)

## Типы

### hinfo

Тип *hinfo* используется для получения информации об url адресе и имеет следующие поля:

* **int Status** - статус ответа.
* **int Length** - размер содержимого. Может быть не указан (равен 0).
* **str Type** - тип содержимого. Например, *text/html; charset=UTF-8*.

## Функции для работы с HTTP

### Download( str url, str filename ) int

Функция *Download* загружает файл из указанного URL и сохранаяет его с указанным именем. Функция возвращает размер загруженного файла.

```go
    str ftemp = TempDir() + `/readme.html`
    int size = Download("https://github.com/gentee/gentee", ftemp)
```

### HeadInfo(str url) hinfo

Функция *HeadInfo* отправляет запрос **HEAD** по указанному параметру *url* и возвращает структуру *hinfo*.

### HTTPGet( str url ) buf

Функция *HTTPGet* отправляет GET запрос по указанному URL и возвращает ответ в виде переменной типа *buf*. Функция может использоваться для загрузки небольших файлов без сохранения их на диск.

### HTTPPage( str url ) str

Функция *HTTPPage* отправляет GET запрос по указанному URL и возвращает ответ в виде строки.

### HTTPRequest( str url, str method, map.str params, map.str headers ) str

Функция *HTTPRequest* отправляет HTTP запрос по указанному URL и возвращает ответ в виде строки. В параметре *method* необходимо указать метод вызова - **GET, POST, UPDATE, PUT, DELETE**. Также функция позволяет указывать параметры и заголовки запроса. Они описываются в виде ассоциативных массивов, где в качестве ключа указано имя параметра или имя заголовка. По умолчанию, при вызове *POST* параметры передаются как данные формы. Если вы хотите передавать их в JSON формате, то в параметре *headers* укажите *"Content-Type": "application/json; charset=UTF-8"*.

```go
    map empty
    Println(HTTPRequest(TESTURL, "GET", empty, empty))
    map params = { `name`: `Jong Doe`, `id`: `101` }
    Println(HTTPRequest(TESTURL, "GET", params, empty))
    Println(HTTPRequest(TESTURL, "POST", params, empty))
    map headjson = { `Content-Type`: `application/json; charset=UTF-8` }
    Println(HTTPRequest(TESTURL, "POST", params, headjson))
```


# Символьный тип

Здесь описаны операторы и функции для работы с символами **char**.

* [int( char c ) int](/stdlib/char#int-char-c-int)
* [str( char c ) str](/stdlib/char#str-char-c-str)

## Операторы

| Оператор         | Результат | Описание                                                                                     |
| ---------------- | --------- | -------------------------------------------------------------------------------------------- |
| char **+** char  | str       | Возвращает строку из двух символов.                                                          |
| char **+** str   | str       | Возвращает строку, как результат добавления строки к символу.                                |
| str **+** char   | str       | Возвращает строку, как результат добавления символа к строке.                                |
| char **=** char  | char      | Присваивание символа.                                                                        |
| str **+=** char  | str       | Добавляет символ к строке.                                                                   |
| char **==** char | bool      | Возвращает *true* если два символа равны и *false*, в противном случае.                      |
| char **>** char  | bool      | Возвращает *true* если первый символ больше второго и *false*, в противном случае.           |
| char **<** char  | bool      | Возвращает *true* если первый символ меньше второго и *false*, в противном случае.           |
| char **!=** char | bool      | Возвращает *true* если два символа не равны и *false*, в противном случае.                   |
| char **>=** char | bool      | Возвращает *true* если первый символ больше или равен второму и *false*, в противном случае. |
| char **<=** char | bool      | Возвращает *true* если первый символ меньше или равен второму и *false*, в противном случае. |

## Функции

### int(char c) int

Функция *int* возвращает числовое значение символа.

### str(char c) str

Функция *str* конвертирует символ в строку и возвращает строку (из указанного символа).


# Система

Здесь описаны общие системные функции.

* [GetEnv( str name ) str](/stdlib/system#getenv-str-name-str)
* [SetEnv( str name, bool|int|str val )](/stdlib/system#setenv-bool-or-int-or-str-name)
* [UnsetEnv( str name )](/stdlib/system#unsetenv-str-name)

## Функции

### GetEnv(str name) str

Функция *GetEnv* возвращает значение переменной окружения.

```go
Print( GetEnv("PATH"))
// the same as
Print( $PATH )
```

### SetEnv(bool|int|str name)

Функция *SetEnv* присваивает переменной окружения указанное значение.

```go
SetEnv("MYVARB", true)
SetEnv("MYVARI", 101)
SetEnv("MYVAR", "Test value")
// the same as
$MYVARB = true
$MYVARI = 101
$MYVARI = "Test value"
```

### UnsetEnv(str name)

Функция *UnsetEnv* удаляет переменную окружения.


# Строки

Здесь описаны операторы и функции для работы со строками (тип **str**).

* [bool( str s ) bool](/stdlib/string#bool-str-s-bool)
* [float( str s ) float](/stdlib/string#float-str-s-float)
* [int( str s ) int](/stdlib/string#int-str-s-int)
* [Find( str s, str substr ) int](/stdlib/string#find-str-s-str-substr-int)
* [Format( str s, anytype args... ) str](/stdlib/string#format-str-s-anytype-args-str)
* [HasPrefix( str s, str prefix ) bool](/stdlib/string#hasprefix-str-s-str-prefix-bool)
* [HasSuffix( str s, str suffix ) bool](/stdlib/string#hassuffix-str-s-str-suffix-bool)
* [Left( str s, int i ) string](/stdlib/string#left-str-s-int-i-str)
* [Lines( str s ) arr.str](/stdlib/string#lines-str-s-arr-str)
* [Lower( str s ) string](/stdlib/string#lower-str-s-str)
* [Repeat( str s, int count ) str](/stdlib/string#repeat-str-s-int-count-str)
* [Replace( str s, str old, str new ) str](/stdlib/string#replace-str-s-str-old-str-new-str)
* [Right( str s, int i ) string](/stdlib/string#right-str-s-int-i-str)
* [Size( int size, str format ) string](/stdlib/string#size-int-size-str-format-str)
* [Split( str s, str sep ) arr.str](/stdlib/string#split-str-s-str-sep-arr-str)
* [Substr( str s, int off, int length ) str](/stdlib/string#substr-str-s-int-off-int-length-str)
* [Trim( str s, str cutset ) str](/stdlib/string#trim-str-s-str-cutset-str)
* [TrimLeft( str s, str cutset ) str](/stdlib/string#trimleft-str-s-str-cutset-str)
* [TrimRight( str s, str cutset ) str](/stdlib/string#trimright-str-s-str-cutset-str)
* [TrimSpace( str s ) str](/stdlib/string#trimspace-str-s-str)
* [Upper( str s ) string](/stdlib/string#upper-str-s-str)

## Операторы

| Оператор             | Результат | Описание                                                                                                       |
| -------------------- | --------- | -------------------------------------------------------------------------------------------------------------- |
| str **+** str        | str       | Слияние двух строк.                                                                                            |
| **\*** str           | int       | Получить длину строки.                                                                                         |
| str **?**            | bool      | Вызов *bool(str)*.                                                                                             |
| **\|** str           | str       | Этот унарный оператор удаляет пробельные символы в начале, в конце строки и рядом с символами перевода строки. |
| str **==** str       | bool      | Возвращает *true* если две строки равны и *false*, в противном случае.                                         |
| str **>** str        | bool      | Возвращает *true* если первая строка больше второй и *false*, в противном случае.                              |
| str **<** str        | bool      | Возвращает *true* если первая строка меньше второй и *false*, в противном случае.                              |
| str **!=** str       | bool      | Возвращает *true* если две строки не равны и *false*, в противном случае.                                      |
| str **>=** str       | bool      | Возвращает *true* если первая строка больше или равна второй и *false*, в противном случае.                    |
| str **<=** str       | bool      | Возвращает *true* если первая строка меньше или равна второй и *false*, в противном случае.                    |
| str **=** str        | str       | Присваивание строки.                                                                                           |
| str **=** int        | str       | Конвертирует целое число в строку и присваивает её переменной.                                                 |
| str **=** bool       | str       | Присваивает переменной "true" или "false".                                                                     |
| str **+=** str       | str       | Добавляет к строковой переменной строку.                                                                       |
| str **\[** int **]** | int       | Установить/получить уникодный символ по индексу.                                                               |

## Функции

### bool(str s) bool

Функция *bool* возвращает *false*, если строка пустая, равна "0" или "false", в противном случае, возвращается *true*.

### float(str s) float

Функция *float* преобразует строку в число типа *float*. Если строка имеет неверный формат, то возвращается ошибка.

### int(str s) int

Функция *int* преобразует строку в число типа *int*. Если строка имеет неверный формат, то возвращается ошибка.

### Find(str s, str substr) int

Функция *Find* возвращает смещение первого вхождения подстроки *substr* в строке *s*, или -1, если *substr* отсутствует в строке *s*.

### Format(str s, anytype args...) str

Функция *Format* форматирует строку в соответствии со спецификатором *s* и возвращает результирующую строку. Имеются следующие управляющие команды:

#### Общие

* **%v** - значение в формате по умолчанию
* **%%** - знак процента&#x20;

#### bool

* **%t** -    слово true или false

#### int

* **%b** - по основанию 2
* **%c** - соответствующий символ Unicode
* **%d** - по основанию 10. Это формат по умолчанию для *int*.
* **%o** - по основанию 8
* **%x** - по основанию 16, с нижним регистром a-f
* **%X** - по основанию 16, с верхним регистром A-F
* **%U** - формат    Unicode: U+1234

#### float

* **%e** - научная запись, например -1.234456e+78
* **%E** - научная запись, например -1.234456E+78
* **%f** - десятичная точка без экспоненты, например 123.456. Вы можете указать общую ширину и мантиссу *%\[width].\[precision]f* - *%8.2f, %.3f, %7f*.
* **%g** - %e для большой экспоненты, и %f в противном случае. Это формат по умолчанию для *float*.

#### str

* **%s** - формат по умолчанию для строк.
* **%x** - по основанию 16 в нижнем регистре, два символа на 1 байт.
* **%X** - по основанию 16 в верхнем регистре, два символа на 1 байт.

Вы можете указать i-ый аргумент в форматируемой строке подобно этому - *Format("%d %\[1]d %\[1]d", 10)*

```
arr.int mya = {1,2,3}
time t
Format(`%s %v %v %g %6.2[4]f`, `ok`, mya, Now(t), 99.0 + 1.)
```

### HasPrefix(str s, str prefix) bool

Функция *HasPrefix* возвращает *true*, если строка *s* начинается со строки *prefix*.

### HasSuffix(str s, str suffix) bool

Функция *HasSuffix* возвращает *true*, если строка *s* заканчивается строкой *suffix*.

### Left(str s, int i) str

Функция *Left* возвращает подстроку из первых *i* символов строки *s*.

### Lines(str s) arr.str

Функция *Lines* разбивает строку *s* на подстроки по символам перевода строки. Все подстроки добавляются в возвращаемый массив строк.

### Lower(str s) str

Функция *Lower* приводит копию строки *s* к нижнему регистру и возвращает её.

### Repeat(str s, int count) str

Функция *Repeat* возвращает новую строку состоящую из *count* повторений строки *s*.

### Replace(str s, str old, str new) str

Функция *Replace* возвращает копию строки *s* со всеми подстроками *old* замененными на строку *new*.

### Right(str s, int i) str

Функция *Right* возвращает подстроку из последних *i* символов строки *s*.

### Size(int size, str format) str

Функция *Size* возвращает округленный размер в виде строки. В параметре *format* укажите шаблон вывода для десятичного числа с плавающей точкой и строки. Если *format* равен пустой строке, то используется формат *%.2f%s*.

```go
Print( Size(956348901, `%.1f %s `) + Size(62, `%[2]s%.2[1]f `) + Size(123789, ``))
// 912.0 MB B62 120.89KB
```

### Split(str s, str sep) arr.str

Функция *Split* разбивает строку *s* на подстроки разделенные строкой *sep*. Все подстроки добавляются в возвращаемый массив строк.

### Substr(str s, int off, int length) str

Функция *Substr* возвращает подстроку *s* с указанным смещением и длиной.

### Trim(str s, str cutset) str

Функция *Trim* возвращает подстроку строки *s* с удалёнными начальными и конечными символами, которые содержатся в строке *cutset*.

### TrimLeft(str s, str cutset) str

Функция *TrimLeft* возвращает подстроку строки *s* с удалёнными начальными символами, которые содержатся в строке *cutset*.

### TrimRight(str s, str cutset) str

Функция *TrimRight* возвращает подстроку строки *s* с удалёнными конечными символами, которые содержатся в строке *cutset*.

### TrimSpace(str s) str

Функция *TrimSpace* возвращает подстроку строки *s* с удалёнными начальными и конечными пробельными символами.

### Upper(str s) str

Функция *Upper* приводит копию строки *s* к верхнему регистру и возвращает её.


# Файлы

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

* [AppendFile( str filename, buf | str data )](/stdlib/file#appendfile-str-filename-buf-or-str-data)
* [ChDir( str dirname )](/stdlib/file#chdir-str-dirname)
* [ChMode( str name, int mode )](/stdlib/file#chmode-str-name-int-mode)
* [CloseFile( file f )](/stdlib/file#closefile-file-f)
* [CopyFile( str src, str dest ) int](/stdlib/file#copyfile-str-src-str-dest-int)
* [CreateDir( str dirname )](/stdlib/file#createdir-str-dirname)
* [CreateFile( str name, bool trunc )](/stdlib/file#createfile-str-name-bool-trunc)
* [ExistFile( str name ) bool](/stdlib/file#existfile-str-name-bool)
* [FileInfo( file f ) finfo](/stdlib/file#fileinfo-file-f-finfo)
* [FileInfo( str name ) finfo](/stdlib/file#fileinfo-str-name-finfo)
* [FileMode( str name ) int](/stdlib/file#filemode-str-name-int)
* [GetCurDir() str](/stdlib/file#getcurdir-str)
* [IsEmptyDir( str path ) bool](/stdlib/file#isemptydir-str-path-bool)
* [Md5File( str filename ) str](/stdlib/file#md-5-file-str-filename-str)
* [obj( finfo fi ) obj](/stdlib/file#obj-finfo-fi-obj)
* [OpenFile( str filename, int flags ) file](/stdlib/file#openfile-str-filename-int-flags-file)
* [Read( file f, int size ) buf](/stdlib/file#read-file-f-int-size-buf)
* [ReadDir( str dirname ) arr.finfo](/stdlib/file#readdir-str-dirname-arr-finfo)
* [ReadDir( str dirname, int flags, str pattern ) arr.finfo](/stdlib/file#readdir-str-dirname-int-flags-str-pattern-arr-finfo)
* [ReadDir( str dirname, int flags, arr.str patterns, arr.str ignore ) arr.finfo](/stdlib/file#readdir-str-dirname-int-flags-arr-str-patterns-arr-str-ignore-arr-finfo)
* [ReadFile( str filename ) str](/stdlib/file#readfile-str-filename-str)
* [ReadFile( str filename, buf out ) buf](/stdlib/file#readfile-str-filename-buf-out-buf)
* [ReadFile( str filename, int offset, int length ) buf](/stdlib/file#readfile-str-filename-int-offset-int-length-buf)
* [Remove( str name )](/stdlib/file#remove-str-name)
* [RemoveDir( str dirname )](/stdlib/file#removedir-str-dirname)
* [Rename( str oldpath, str newpath )](/stdlib/file#rename-str-oldpath-str-newpath)
* [SetFileTime( str name, time modtime )](/stdlib/file#setfiletime-str-name-time-modtime)
* [SetPos( file f, int off, int whence ) int](/stdlib/file#setpos-file-f-int-off-int-whence-int)
* [Sha256File( str filename ) str](/stdlib/file#sha-256-file-str-filename-str)
* [TempDir() str](/stdlib/file#tempdir-str)
* [TempDir( str path, str prefix ) str](/stdlib/file#tempdir-str-path-str-prefix-str)
* [Write( file f, buf b ) file](/stdlib/file#write-file-f-buf-b-file)
* [WriteFile( str filename, buf | str data )](/stdlib/file#writefile-str-filename-buf-or-str-data)

## Типы

### finfo

Тип *finfo* используется для получения информации о файле и имеет следующие поля:

* **str Name** - имя файла
* **int Size** - размер файла в байтах
* **int Mode** - флаги файла и разрешения
* **time Time** - время последнего изменения
* **bool IsDir** - true, если это директория
* **str Dir** - директория, где расположен файл. Данное поле заполняется только при вызове функции [ReadDir(str, int, str)](/stdlib/file#readdir-str-dirname-int-flags-str-pattern-arr-finfo).

### file

Тип *file* используется в функциях, которые работают с дескриптором открытого файла.

## Функции

### AppendFile(str filename, buf|str data)

Функция *AppendFile* добавляет данные переменной типа *buf* или *str* в конец файла *filename*. Если файл не существует, то *AppendFile* создает его с правами 0644.

### ChDir(str dirname)

Функция *ChDir* изменяет текущую директорию.

### ChMode(str name, int mode)

Функция *ChMode* изменяет атрибуты файла.

### CloseFile(file f)

Функция *CloseFile* закрывает дескриптор файла, который был открыт с помощью функции **OpenFile**.

### CopyFile(str src, str dest) int

Функция *CopyFile* копирует файл *src* в файл *dest*. Если файл *dest* существует, то он будет перезаписан. При копировании сохраняются атрибуты файла. Функция возвращает количество скопированных байт.

### CreateDir(str dirname)

Функция *CreateDir* создает директорию с именем *dirname*, включая все необходимые родительские директории. Если *dirname* уже существующая директория, то *CreateDir* ничего не делает.

### CreateFile(str name, bool trunc)

Функция *CreateFile* создает файл с указанным именем. Если параметр *trunc* равен *true* и файл уже существует, то в этом случае его размер станет 0.

### ExistFile(str name) bool

Функция *ExistFile* возвращает *true*, если указанный файл или директория существует. В противном случае, возвращается *false*.

### FileInfo(file f) finfo

Функция *FileInfo* получает информацию об указанном файле и возвращает структуру *finfo*. Файл должен быть октрыт с помощью функции **OpenFile**.

### FileInfo(str name) finfo

Функция *FileInfo* получает информацию об указанном файле и возвращает структуру *finfo*.

### FileMode(str name) int

Функция *FileMode* возвращает атрибуты файла.

### GetCurDir() str

Функция *GetCurDir* возвращает текущую директорию.

### IsEmptyDir(str path) bool

Функция *IsEmptyDir* возвращает *true*, если указанная директория пустая. В противном случае, возвращается *false*.

### Md5File(str filename) str

Функция *Md5File* возвращает MD5 хэш указанного файла в виде шестнадцатеричной строки.

### obj(finfo fi) obj

Функция *obj* конвертирует переменную типа finfo в объект. Полученный объект имеет поля: *name, size, mode, time, isdir, dir*.

### OpenFile(str filename, int flags) file

Функция *OpenFile* открывает указанный файл и возвращает переменную типа *file* с дескриптором открытого файла. После работы с файлом дескриптор открытого файла должен быть закрыт с помощью функции **CloseFile**. Параметр *flags* может быть нулем или комбинацией следующих флагов:

* *CREATE* - если файл не существует, то он будет создан.
* *TRUNC* - файл будет обрезан до нулевой длины после открытия.
* *READONLY* - файл будет открыт только для чтения.

```go
    file f = OpenFile(fname, CREATE)
    Write(f, buf("some test string"))
    SetPos(f, -15, 1)
    buf b &= Read(f, 5)
    CloseFile(f)
```

### Read(file f, int size) buf

Функция *Read* читает *size* количество байт с текущей позиции в файле, который был открыт с помощью функции **OpenFile**. Функция возвращает переменную типа *buf*, которая содержит прочитанные данные.

### ReadDir(str dirname) arr.finfo

Функция *ReadDir* читает директорию с указанным именем и возвращает список её поддиректорий и файлов.

### ReadDir(str dirname, int flags, str pattern) arr.finfo

Функция *ReadDir* читает директорию *dirname* с указанным именем и возвращает список её поддиректорий и файлов в соотвествии с указанными параметрами. Параметр *flags* может быть комбинацией следующих флагов:

* **RECURSIVE** - В этом случае будет рекурсивный поиск по всем поддиректориям.
* **ONLYFILES** - Возвращаемый массив будет содержать только файлы.
* **ONLYDIRS** - Возвращаемый массив будет содержать только директории.
* **REGEXP** - Параметр *pattern* содержит регулярное выражения для сравнения имён файлов.

Если вы укажете одновременно флаги **ONLYFILES** и **ONLYDIRS**, то будут искаться файлы и директории.

Параметр *pattern* может содержать маску для файлов или регулярное выражение. В этом случае, будут возвращаться файлы и директории, которые соответствуют указанному шаблону. Маска может содержать следующие символы:

* '\*' - любая последовательность, кроме символа разделителя
* '?' - любой одиночный символ, кроме символа разделителя

```go
for item in ReadDir(ftemp, RECURSIVE, `*fold*`) {
    ret += item.Name
}
for item in ReadDir(ftemp, RECURSIVE | ONLYFILES | REGEXP, `.*\.pdf`) {
    ret += item.Name
}
```

### ReadDir(str dirname, int flags, arr.str patterns, arr.str ignore) arr.finfo

Функция *ReadDir* читает директорию *dirname* с указанным именем и возвращает список её поддиректорий и файлов в соотвествии с указанными параметрами. Параметр *flags* описан выше. Параметр *patterns* является массивом строк и может содержать маски для файлов или регулярные выражения. Параметр *ignore* также содержит маски для файлов или регулярные выражения, но такие файлы или директории будут пропускаться. Если вы хотите указать в этих массивах регулярное выражение, то заключите его между символами **'/'**.

```go
arr.str aignore = {`/txt/`, `*.pak`}
arr.str amatch = {`/\d+/`, `*.p??`, `/di/`}
for item in ReadDir(ftemp, RECURSIVE, amatch, aignore) {
    ret += item.Name
}
```

### ReadFile(str filename) str

Функция *ReadFile* читает указанный файл и возвращает его содержимое в виде строки.

### ReadFile(str filename, buf out) buf

Функция *ReadFile* читает файл *filename* в переменную *out* типа *buf* и возвращает эту переменную.

### ReadFile(str filename, int offset, int length) buf

Функция *ReadFile* читает данные из файла *filename* начиная со смещения *offset* и длиной *length*. Если *offset* меньше нуля, то смещение считается от конца к началу файла.

### Remove(str name)

Функция *Remove* удаляет файл или пустую директорию.

### RemoveDir(str dirname)

Функция *RemoveDir* удаляет директорию *dirname* включая всё её содержимое.

### Rename(str oldpath, str newpath)

Функция *Rename* переименовывает (переносит) *oldpath* в *newpath*. Если *newpath* уже существует и является файлом, то *Rename* заменяет его.

### SetFileTime(str name, time modtime)

Функция *SetFileTime* изменяет время последней записи у указанного файла.

### SetPos(file f, int off, int whence) int

Функция *SetPos* устанавливает в файле текущую позицию для операций чтения или записи. Файл должен быть открыт с помощью функции **OpenFile**. Функция возвращает смещение новой позиции. Параметр *whence* может принимать следующие значения:

* *0* - смещение *off* указано от начало файла.
* *1* - смещение *off* указано от текущей позиции.
* *2* - смещение *off* указано от конца файла.

### Sha256File(str filename) str

Функция *Sha256File* возвращает SHA256 хэш указанного файла в виде шестнадцатеричной строки.

### TempDir() str

Функция *TempDir* возвращает временную директорию по умолчанию.

### TempDir(str path, str prefix) str

Функция *TempDir* создает новую временную директорию в директории *path* с именем, начинающемся на *prefix* и возвращает полное имя этой новой директории. Если *path* пустая строка, *TempDir* использует временную директорию по умолчанию.

### Write(file f, buf b) file

Функция *Write* записывает данные из переменной типа *buf* в файл, который был открыт с помощью функции **OpenFile**. Функция возвращает параметр *f*.

### WriteFile(str filename, buf|str data)

Функция *WriteFile* записывает данные из переменной типа *buf* или строки в файл *filename*. Если файл не существует, то он будет создан с разрешениями 0777, в противном случае, файл будет перезаписан заново.


# Целые числа

Здесь описаны операторы и функции для работы с целыми числами типа **int**.

* [Abs( int i ) int](/stdlib/integer#abs-int-i-int)
* [bool( int i ) bool](/stdlib/integer#bool-int-i-bool)
* [float( int i ) float](/stdlib/integer#float-int-i-float)
* [Max( int l, int r ) int](/stdlib/integer#max-int-l-int-r-int)
* [Min( int l, int r ) int](/stdlib/integer#min-int-l-int-r-int)
* [Random( int n ) int](/stdlib/integer#random-int-n-int)
* [str( int i ) str](/stdlib/integer#str-int-i-str)

## Операторы

| Оператор        | Результат | Описание                                                                                    |
| --------------- | --------- | ------------------------------------------------------------------------------------------- |
| int **?**       | bool      | *true*, если число не равно нулю.                                                           |
| int **+** int   | int       | Сложение двух целых чисел.                                                                  |
| int **-** int   | int       | Вычитание двух целых чисел.                                                                 |
| int **\*** int  | int       | Умножение двух целых чисел.                                                                 |
| int **/** int   | int       | Деление двух целых чисел. При делении на ноль возвращается ошибка.                          |
| int **==** int  | bool      | Возвращает *true* если два числа равны и *false*, в противном случае.                       |
| int **>** int   | bool      | Возвращает *true* если первое число больше второго и *false*, в противном случае.           |
| int **<** int   | bool      | Возвращает *true* если первое число меньше второго и *false*, в противном случае.           |
| int **!=** int  | bool      | Возвращает *true* если два числа не равны и *false*, в противном случае.                    |
| int **>=** int  | bool      | Возвращает *true* если первое число больше или равно второму и *false*, в противном случае. |
| int **<=** int  | bool      | Возвращает *true* если первое число меньше или равно второму и *false*, в противном случае. |
| int **%** int   | int       | Возвращает остаток после деления двух чисел.                                                |
| int **\|** int  | int       | Побитовый OR.                                                                               |
| int **^** int   | int       | Побитовый XOR.                                                                              |
| int **&** int   | int       | Побитовый AND.                                                                              |
| int **<<** int  | int       | Побитовый сдвиг влево.                                                                      |
| int **>>** int  | int       | Побитовый сдвиг вправо.                                                                     |
| **-** int       | int       | Смена знака.                                                                                |
| **^** int       | int       | Побитовый NOT.                                                                              |
| int **=** int   | int       | Присваивание переменной целого числа.                                                       |
| int **=** char  | int       | Присваивание переменной символа.                                                            |
| int **+=** int  | int       | Прибавление к переменной целого числа.                                                      |
| int **-=** int  | int       | Вычитание из переменной целого числа.                                                       |
| int **/=** int  | int       | Деление переменной на целое число.                                                          |
| int **\*=** int | int       | Умножение переменной на целое число.                                                        |
| int **%=** int  | int       | Деление переменной с остатком по модулю.                                                    |
| int **\|=** int | int       | Побитовый OR с переменной и присваивание ей результата.                                     |
| int **^=** int  | int       | Побитовый XOR с переменной и присваивание ей результата.                                    |
| int **&=** int  | int       | Побитовый AND с переменной и присваивание ей результата.                                    |
| int **<<=** int | int       | Побитовый сдвиг влево переменной и присваивание ей результата.                              |
| int **>>=** int | int       | Побитовый сдвиг вправо переменной и присваивание ей результата.                             |

## Функции

### Abs(int i) int

Функция *Abs* возвращает абсолютное значение числа.

### bool(int i) bool

Функция *bool* возвращает *false*, если передаваемый параметр равен 0, в противном случае, возвращается *true*.

### float(int i) float

Функция *float* преобразует целое число в число типа *float*.

### Max(int l, int r) int

Функция *Max* возвращает максимальное из двух значений.

### Min(int l, int r) int

Функция *Min* возвращает минимальное из двух значений.

### Random(int n) int

Функция *Random* возвращает случайное неотрицательное число меньше *n* в интервале \[0,n).

### str(int i) str

Функция *str* преобразует целое число в строку.


# Числа с плавающей точкой

Здесь описаны операторы и функции для работы с действительными числами типа **float**.

* [bool( float f ) bool](/stdlib/float#bool-float-f-bool)
* [Ceil( float f ) int](/stdlib/float#ceil-float-f-int)
* [Floor( float f ) int](/stdlib/float#floor-float-f-int)
* [int( float f ) int](/stdlib/float#intfloat-f-int)
* [Max( float fl, float fr ) float](/stdlib/float#max-float-fl-float-fr-float)
* [Min( float fl, float fr ) float](/stdlib/float#min-float-fl-float-fr-float)
* [Round( float f ) int](/stdlib/float#round-float-f-int)
* [Round( float f, int digit ) float](/stdlib/float#round-float-f-int-digit-float)
* [str( float f ) str](/stdlib/float#str-float-f-str)

## Операторы

| Оператор            | Результат | Описание                                                                                    |
| ------------------- | --------- | ------------------------------------------------------------------------------------------- |
| float **?**         | bool      | Вызов *bool(float)*.                                                                        |
| float **+** float   | float     | Сложение двух чисел.                                                                        |
| float **+** int     | float     |                                                                                             |
| int **+** float     | float     |                                                                                             |
| float **-** float   | float     | Вычитание второго числа из первого.                                                         |
| float **-** int     | float     |                                                                                             |
| int **-** float     | float     |                                                                                             |
| float **\*** float  | float     | Умножение двух чисел.                                                                       |
| float **\*** int    | float     |                                                                                             |
| int **\*** float    | float     |                                                                                             |
| float **/** float   | float     | Деление двух чисел. При делении на ноль возвращается ошибка.                                |
| float **/** int     | float     |                                                                                             |
| int **/** float     | float     |                                                                                             |
| float **==** float  | bool      | Возвращает *true* если два числа равны и *false*, в противном случае.                       |
| float **==** int    | bool      |                                                                                             |
| float **>** float   | bool      | Возвращает *true* если первое число больше второго и *false*, в противном случае.           |
| float **>** int     | bool      |                                                                                             |
| float **<** float   | bool      | Возвращает *true* если первое число меньше второго и *false*, в противном случае.           |
| float **<** int     | bool      |                                                                                             |
| float **!=** float  | bool      | Возвращает *true* если два числа не равны и *false*, в противном случае.                    |
| float **!=** int    | bool      |                                                                                             |
| float **>=** float  | bool      | Возвращает *true* если первое число больше или равно второму и *false*, в противном случае. |
| float **>=** int    | bool      |                                                                                             |
| float **<=** float  | bool      | Возвращает *true* если первое число меньше или равно второму и *false*, в противном случае. |
| float **<=** int    | bool      |                                                                                             |
| **-** float         | float     | Смена знака.                                                                                |
| float **=** float   | float     | Присваивание.                                                                               |
| float **+=** float  | float     | Сложение и присваивание действительных чисел с плавающей точкой.                            |
| float **-=** float  | float     | Вычитание и присваивание действительных чисел с плавающей точкой.                           |
| float **/=** float  | float     | Деление и присваивание действительных чисел с плавающей точкой.                             |
| float **\*=** float | float     | Умножение и присваивание действительных чисел с плавающей точкой.                           |

## Функции

### bool(float f) bool

Функция *bool* возвращает *false*, если передаваемый параметр равен 0.0, в противном случае, возвращается *true*.

### int(float f) int

Функция *int* преобразует действительное число с плавающей точкой в целое число типа *int*, которое меньше или равно данному числу.

### str(float f) str

Функция *str* преобразует действительное число с плавающей точкой в строку.

### Ceil(float f) int

Функция *Ceil* возвращает наименьшее целое число, которое больше или равно *f*.

### Floor(float f) int

Функция *Floor* наибольшее целое число, которое меньше или равно *f*.

### Max(float fl, float fr) float

Функция *Max* возвращает максимальное из двух значений.

### Min(float fl, float fr) float

Функция *Min* возвращает минимальное из двух значений.

### Round(float f) int

Функция *Round* округляет *f* до ближайшего целого.

```
   Round(4.5) // 5
   Round(4.1) // 4
   Round(4.9) // 5
```

### Round(float f, int digit) float

Функция *Round* округляет действительное число до указанного количества десятичных знаков.

```
   Round(4.567, 2) // 4.57
   Round(4.111, 1) // 4.1
```


# Интеграция с Go

Документация по использованию языка программирования Gentee в проектах на Go.


# Документация

Здесь описаны функции и структуры для использования языка программирования **Gentee** в проектах на **Golang**.

* [type Custom](/golang/reference#type-custom)
* [type EmbedItem](/golang/reference#type-embed-item)
* [type Settings](/golang/reference#type-settings)
* [type Progress](/golang/reference#type-progress)
* [Customize(custom \*Custom) error](/golang/reference#customize-custom-custom-error)
* [New() \*Gentee](/golang/reference#new-gentee)
* [(g \*Gentee) Compile(input, path string) (\*Exec, int, error)](/golang/reference#g-gentee-compile-input-path-string-exec-int-error)
* [(g \*Gentee) CompileAndRun(filename string) (interface{}, error)](/golang/reference#g-gentee-compileandrun-filename-string-interface-error)
* [(g \*Gentee) CompileAndRun(filename string) (\*Exec, int, error)](/golang/reference#g-gentee-compilefile-filename-string-exec-int-error)
* [(exec \*Exec) Run(settings Settings) (interface{}, error)](/golang/reference#exec-exec-run-settings-settings-interface-error)
* [Gentee2GoType(val interface{}, vtype... string) interface{}](/golang/reference#gentee-2-gotype-val-interface-vtype-string-interface)
* [Go2GenteeType(val interface{}, vtype... string) (interface{}, error)](/golang/reference#go-2-genteetype-val-interface-vtype-string-interface-error)
* [Version() string](/golang/reference#version-string)

## Типы

### type Custom

Тип *Custom* служит для дополнительной настройки компилятора и виртуальной машины. Передается при вызове функции **Customize**.

* **Embedded** \[]EmbedItem - массив дополнительных функций для стандартной библиотеки.

### type EmbedItem

Тип *EmbedItem* описывает функцию, подключаемую к стандартной библиотеки. Используется в типе **Custom**.

* **Prototype** string - описание функции на языке Gentee. Например, *myfunc(str,int) int*.
* **Object** interface{} - соответствующая golang функция.

### type Settings

Тип *Settings* служит для указания дополнительных параметров при запуске байт-кода в методе **Run**.

* **CmdLine** \[]string - массив параметров командной строки.
* **Stdin** \*os.File - свой собственный стандартный ввод.
* **Stdout** \*os.File - свой собственный стандартный вывод.
* **Stderr** \*os.File - свой собственный вывод для ошибок.
* **Input** \[]byte - предопределенный стандартный ввод (stdin). Может использоваться, например, в функции [ReadString](/stdlib/console#readstring-str-text-str).
* **Cycle** uint64 - максимальное количество итераций в цикле. По умолчанию, равно 16000000.
* **Depth** uint32 - максимальная вложенность исполняемых блоков. Ограничивает глубину рекурсии. По умолчанию, равно 1000.
* **SysChan** chan int - канал для отправки команд *SysSuspend* (1), *SysResume* (2), *SysTerminate* (3). Позволяет управлять выполнением скрипта извне.
  * *SysSuspend* - приостановить работу скрипта и всех потоков.
  * *SysResume* - возобновить работу скрипта и всех потоков.
  * *SysTerminate* - завершить работу скрипта и всех потоков.
* **IsPlayground** bool - присвойте *true*, если хотите запустить скрипт в безопасном режиме [песочницы](/golang/playground).
* **Playground** Playground - настройки режима песочницы.
  * *Path*  string - путь к временной директории для записи и чтения файлов. Если не указан, то будет будет создана поддиректория во временной директории.
  * *AllSizeLimit* int64 - суммарный размер файлов. По умолчанию, 10 MB.
  * *FilesLimit* int - максимальное количество файлов. По умолчанию, 100.
  * *SizeLimit* int64 - максимальный размер файла. По умолчанию, 5 MB.
* **ProgressFunc** gentee.ProgressFunc - функция для отображения процесса копирования, скачивания и т.д., например, в виде прогресс-бара. Функция должна иметь следующий тип: &#x20;

  *func MyProgress(progress \*gentee.Progress) bool* &#x20;

  и возвращать *true*. Тип *Progress* описан ниже. Функция *ProgressFunc* вызывается при копировании, скачивании файлов, а также при вызове функций [Progress](/stdlib/runtime#progress-int-id-inc).

```go
    settings.SysChan = make(chan int)
    go func() {
        _, err = exec.Run(settings)
    }()
    settings.SysChan <- gentee.SysTerminate
```

### type Progress

Тип *Progress* служит для отображения процесса копирования, скачивания. Переменная этого типа передается в функцию *ProgressFunc* и имеет следующие поля:

* **ID uint32** - уникальный идентификатор.
* **Type int32** - тип процесса.
  * *ProgressCopy (0)* - копирование.
  * *ProgressDownload (1)* - скачивание.
  * *ProgressCompress (2)* - сжатие.
  * *ProgressDecompress (3)* - распаковка.
* **Status int32** - статус.
  * *ProgStatusStart (0)* - начало процесса.
  * *ProgStatusActive (1)* - процесс идёт. &#x20;
  * *ProgStatusEnd (2)* - процесс закончен. &#x20;
* **Total int64** - общий размер.
* **Current int64** - текущий размер.
* **Source string** - источник процесса.
* **Dest string** - целевой объект процесса.
* **Ratio float64** - отношение *Current/Total*. Для получения процентов необходимо умножить на 100.
* **Custom interface{}** - служит для хранения любой дополнительной информации.

## Функции и методы

### Customize(custom \*Custom) error

Функция *Customize* служит для [дополнительной настройки компилятора](/golang/customize) и виртуальной машины. Она должна вызываться раньше всех функций. Функция возвращает значение ошибки.

### New() \*Gentee

Функция *New* создает рабочее пространство для компиляции исходного кода.

### (g \*Gentee) Compile(input, path string) (\*Exec, int, error)

Функция *Compile* компилирует скрипт переданный в *input*. В параметре *path* можно указать путь к скрипту. Функция возвращает структуру с байт-кодом, номер модуля и значение ошибки.

### (g \*Gentee) CompileAndRun(filename string) (interface{}, error)

Функция *CompileAndRun* компилирует скрипт из файле *filename* и выполняет его. Функция возвращает результат выполнения скрипта и значение ошибки.

### (g \*Gentee) CompileFile(filename string) (\*Exec, int, error)

Функция *CompileFile* компилирует скрипт из файла *filename*. Функция возвращает структуру с байт-кодом, номер модуля и значение ошибки.

### (exec \*Exec) Run(settings Settings) (interface{}, error)

Функция *Run* выполняет байт-код из структуры *exec*. В параметре *settings* можно указать дополнительные настройки. Функция возвращает результат выполнения скрипта и значение ошибки.

### Gentee2GoType(val interface{}, vtype... string) interface{}

Функция *Gentee2GoType* конвертирует переменную в стандартные типы Go. Во втором параметре можно указать тип Gentee переменной. Например, *arr.bool*. В этом случае, вы получите массив переменных типа *bool*, а не *int64*. Вы можете использовать эту функцию, в ваших встраиваемых функциях.

Таблица соответствия типов

| Gentee тип  | Получаемый тип | Возвращаемый тип (vtype) |
| ----------- | -------------- | ------------------------ |
| int         | int64          | int64                    |
| bool        | int64          | bool ("bool")            |
| char        | int64          | rune ("rune")            |
| float       | float64        | float64                  |
| str         | string         | string                   |
| arr         | \*core.Array   | \[]interface{}           |
| buf         | \*core.Buffer  | \[]byte                  |
| map         | \*core.Map     | map\[string]interface{}  |
| set         | \*core.Set     | \[]byte                  |
| struct type | \*core.Struct  | map\[string]interface{}  |
| obj         | \*core.Obj     | interface{}              |

```go
func cnv1(in *core.Map) (*core.Map, error) {
  my := gentee.Gentee2GoType(in).(map[string]interface{})
  for key, a := range my {
    for i, v := range a.([]interface{}) {
      a.([]interface{})[i] = v.(int64) + 1
    }
    delete(my, key)
    my[key+`2`] = a
  }
  ret, err := gentee.Go2GenteeType(my)
  return ret.(*core.Map), err
}
```

### Go2GenteeType(val interface{}, vtype... string) (interface{}, error)

Функция *Go2GenteeType* конвертирует стандартный тип Go в тип Gentee. Во втором параметре можно указать тип Gentee переменной. Например, *set*, если вы хотите сконвертировать *\[]byte* в \*core.Set. Вы можете использовать эту функцию, в ваших встраиваемых функциях.

Таблица соответствия типов

| Gentee тип | Получаемый Go тип       | Возвращаемый тип (vtype) |
| ---------- | ----------------------- | ------------------------ |
| int        | all int & uint          | int64                    |
| bool       | bool                    | int64                    |
| char       | rune                    | int64                    |
| float      | float64                 | float64                  |
| str        | string                  | string                   |
| arr        | \[]interface{}          | \*core.Array             |
| buf        | \[]byte                 | \*core.Buffer            |
| set        | \[]byte                 | \*core.Set ("set")       |
| map        | map\[string]interface{} | \*core.Map               |
| obj        | interface{}             | \*core.Obj ("obj")       |

```go
func cnv5(in *core.Set) (*core.Set, error) {
  my := gentee.Gentee2GoType(in).([]byte)
  for i, b := range my {
    if i > 10 {
      break
    }
    if b == 0 {
      my[i] = 1
    } else {
      my[i] = b - 1
    }
  }
  ret, err := gentee.Go2GenteeType(my, `set`)
  return ret.(*core.Set), err
}
```

### Version() string

Функция *Version* возвращает номер текущей версии языка.


# Компиляция и выполнение

Рассмотрим как использовать компилятор и виртуальную машину Gentee в проектах на языке программирования **Go**.

## Компиляция

Для начала, нужно создать структуру *Gentee* с помощью функции **New**. Эта структура будет хранить всю информацию о скомпилированных скриптах. Вам достаточно создать один экземпляр и компилировать любое количество скриптов.

Для компиляции скриптов нужно использовать методы **Compile**, **CompileFile**, **CompileAndRun**. Методы *Compile*, *CompileFile*, в случае успешной компиляции, возвращают структуру *Exec*, которая содержит байт-код. Вы можете сохранять или передавать эту структуру для дальнейшего выполнения с помощью метода **Run**. Метод *CompileAndRun* сразу после компиляции выполняет скрипт и возвращает его результат.

```go
package main
import (
    "fmt"
    "log"

    "github.com/gentee/gentee"
)

func main() {
    g := gentee.New()

    exec,_, err := g.Compile("run : Print(`Hello, world!`)", "")
    if err != nil {
        log.Fatal(err)
    }
    exec.Run(gentee.Settings{})
    exec,_, err = g.CompileFile("/home/ak/scripts/myscript.g")
    if err != nil {
        log.Fatal(err)
    }
    exec.Run(gentee.Settings{})

    var result interface{}
    result, err = g.CompileAndRun("../torun.g")
    fmt.Println(`Error:`, err, `Result:`, result)
}
```

## Выполнение байт-кода

Готовый байт-код скрипта хранится в структуре типа **Exec**. Для его выполнения необходимо вызвать метод **Run**. Параметр типа [**Settings**](/golang/reference#type-settings) позволяет передать параметры командной строки и указать дополнительные настройки виртуальной машины.

```go
package main
import (
    "fmt"
    "log"

    "github.com/gentee/gentee"
)

func main() {
    g := gentee.New()

    exec,_, err := g.CompileFile("myscript.g")
    if err != nil {
        log.Fatal(err)
    }
    var result interface{}
    result, err = exec.Run(gentee.Settings{
        CmdLine: []string{
            "-par1",
            "-o",
            "/home/ak/tmp",
        },
    })
    fmt.Println(`Error:`, err, `Result:`, result)
}
```


# Дополнительные возможности

## Как добавить свои функции в стандартную библиотеку

При использовании **Gentee** в других проектах может возникнуть потребность в расширении стандартной библиотеки. Функция **Customize** позволяет добавить любое количество go-функций в стандартную библиотеку и использовать их в скриптах. Следует заметить, что в этом случае скрипты не будут компилироваться оригинальным компилятором, так как там будут отсутствовать добавленные функции. Функцию **Customize** необходимо вызвать до вызова прочих функций из пакета gentee.

Для расширения стандартной библиотеки необходимо указать массив функций в параметрe типа [*Custom*](/golang/reference#type-custom). Каждая функция описывается структурой [*EmbedItem*](/golang/reference#type-embed-item), в которой указывается прототип на языке Gentee и сама функция. Функция может возвращать значение типа *error* и иметь переменное количество параметров.

### Соответствие типов

Параметры и возвращаемое значение подключаемых go-функций должны иметь типы в соответствии с данной таблицей. При использовании *core* типов необходимо импортировать *github.com/gentee/gentee/core*.

| Gentee тип  | Golang тип    |
| ----------- | ------------- |
| int         | int64         |
| bool        | int64         |
| char        | int64         |
| thread      | int64         |
| float       | float64       |
| str         | string        |
| arr         | \*core.Array  |
| buf         | \*core.Buffer |
| map         | \*core.Map    |
| set         | \*core.Set    |
| struct type | \*core.Struct |
| obj         | \*core.Obj    |

```go
func sum(x, y int64) int64 {
    return x + 2*y
}

func varInt(init int64, pars ...int64) int64 {
    for _, i := range pars {
        init += i
    }
    return init
}

func shortLen(s string) (int64, error) {
    if len(s) < 10 {
        return len(s), nil
    }
    return 0, fmt.Errorf("string %s is too long", s)
}

func main() {
    var customLib = []gentee.EmbedItem{
        {Prototype: `sum(int,int) int`, Object: sum},
        {Prototype: `InitSum(int) int`, Object: varInt},
        {Prototype: `ShortLen(str) int`, Object: shortLen},
    }
    err := gentee.Customize(&gentee.Custom{
        Embedded: customLib,
    })
    if err != nil {
        log.Fatal(err)
    }
    workspace := gentee.New()
    exec, _, err := workspace.Compile(`run {
    Println("Sum = %{sum(10, 6)}")
    Println("InitSum = " + InitSum(4, 67, 4, 22))
    ShortLen("this string is too long")
}`, ``)
    ...
}
```


# Песочница

Если вы хотите дать возможность третьим лицам запускать скрипты Gentee на вашем компьютере, то используйте при запуске скриптов режим *Playground*. Этот режим удобен для запуска скриптов в демонстрационных или учебных целях и защищает данные на компьютере от случайного или намеренного ущерба. Для включения этого режима укажите поле *IsPlayground* как *true* в структуре [*Settings*](/golang/reference) при запуске скрипта с помощью функции *Run*. Кроме этого, рекомендуется уменьшить параметры *Cycle* и *Depth* для установки ограничений на потребляемые ресурсы.

Работа скриптов в режиме *Playground* имеет следующие ограничения:

* **Процессы**. Отключены запуски любых процессов, включая открытие файлов в соответствующих приложениях. То есть функции *Open, OpenWith,Run, Start* работать не будут. Также не работает команда **$**.
* **Файловая система**. Запись и чтение файлов может происходить только в директории, которая указана в настройках Playground. Если она не указана, то создаётся поддиректория во временной директории. Эта директория становится текущей при запуске скрипта. Кроме этого, имеются ограничения на:
  * общее количество файлов (по умолчанию, 100).
  * суммарный размер файлов (по умолчанию, 10 MB).
  * максимальный размер файла (по умолчанию, 5 MB).
* **Сеть**. Отключена функция *HTTPRequest*. Вызов функций *Download, HTTPGet, HTTPPage* виртуально добавляет файл с соответствущим размером в директорию для записи. Таким образом, на эти функции также действуют ограничения файловой системы.

Если в процессе работы скрипта возникнет ошибка из-за ограничений режима *Playground*, то скрипт прекратит свою работу. В этом случае, текст ошибки будет начинаться с **\[Playground]**.

```go
run {
    $ echo "ooops"
}
// ERROR: [2:5] [Playground] starting any processes is disabled
run {
    AppendFile("../out.txt", "this is a test message")
}
// ERROR: [2:5] [Playground] access denied [../out.txt]
run  {
    for i in 1..110 {
        CreateFile(`%{i}.txt`, false)
    }
}
// ERROR: [3:9] [Playground] file limit reached [100]
```


