Annotation of parser3/operators.txt, revision 1.275

1.260     moko        1: operators
                      2:     ^eval(expression)[format] expressions, apart from the usual functions, supports:
                      3:         #comments allowed
                      4:             they work until the end of the line or the closing parenthesis
                      5:             nested parentheses are allowed inside comments
                      6:         among the non-obvious operators:
                      7:             | bitwise XOR
                      8:             || logical XOR
                      9:             ~ bitwise negation
                     10:             \ integer division 10\3=3
                     11:         def checks if defined:
                     12:             an empty string is not defined
                     13:             an empty table is not defined
                     14:             an empty hash is not defined
                     15:         eq ne lt gt le ge for string comparison,
                     16:         in "/dir/" to check if the current document is located in the specified directory
                     17:             ["no expressions allowed inside; if you need a complex comparison, assign it to a variable"]
                     18:         is 'type' to check the type of the left operand,
                     19:             e.g., "is the method parameter not a hash?"
                     20:         -f checks if a file exists on disk,
                     21:         -d checks if a directory exists on disk,
                     22:         a quoted string (double or single quotes) is treated as a string, unquoted text is a string until the nearest whitespace
                     23:         numeric literals can be in hex format like 0xABC
                     24:         priorities:
1.250     moko       25:             /* logical */
                     26:             %left "!||"
                     27:             %left "||"
                     28:             %left "&&"
1.260     moko       29:             %left '<' '>' "<=" ">=" "lt" "gt" "le" "ge"
                     30:             %left "==" "!=" "eq" "ne"
1.250     moko       31:             %left "is" "def" "in" "-f" "-d"
                     32:             %left '!'
1.1       paf        33: 
1.259     moko       34:             /* bitwise */
1.250     moko       35:             %left '!|'
                     36:             %left '|'
1.260     moko       37:             %left '&'
1.250     moko       38:             %left '~'
1.1       paf        39: 
1.259     moko       40:             /* numerical */
1.250     moko       41:             %left '-' '+'
                     42:             %left '*' '/' '%' '\\'
                     43:             %left '~'     /* negation: unary */
1.259     moko       44: 
1.260     moko       45:         literals:
1.250     moko       46:             true
                     47:             false
                     48: 
1.260     moko       49:     ^if(condition){then}{else}
                     50:     ^if(condition1){yes}[(condition2){yes}[(condition3){yes}[...]]]{no}
                     51:         unlimited number of additional conditions (elseif)
1.250     moko       52: 
1.260     moko       53:     ^switch[value]{^case[var1[;var2...]]{action}^case[DEFAULT]{default action}}
1.250     moko       54: 
1.260     moko       55:     ^while(condition){body}[[delimiter]|{delimiter executed before each non-empty non-first body}]
1.250     moko       56: 
1.260     moko       57:     ^for[i](0;4){body}[[delimiter]|{delimiter executed before each non-empty non-first body}]
1.250     moko       58: 
                     59:     ^try{
1.21      paf        60:         ...
1.260     moko       61:         ^throw[sql.connect[;vasya[;mistaken]]] // previously ^error[text]
1.250     moko       62:         ^throw[
                     63:             $.type[sql.connect]
1.260     moko       64:             $.source[vasya]
                     65:             $.comment[mistaken]
1.207     misha      66:         ]
1.20      paf        67:         ...
                     68:     }{
1.207     misha      69:         ^if($exception.type eq "sql"){
1.260     moko       70:             $exception.handled(1|true)  ^rem{flag that exception is handled}
1.21      paf        71:             ....
                     72:         }
1.207     misha      73:         ^switch[$exception.type]{
1.21      paf        74:             ^case[sql;mail]{
                     75:                 $exception.handled(1)
1.260     moko       76:                 code handling sql error
1.21      paf        77:                 $exception.type = sql.connect
1.260     moko       78:                 $exception.file $exception.lineno $exception.colno [if not disabled at compile time]
                     79:                 $exception.source = vasya
                     80:                 $exception.comment = mistaken
1.21      paf        81:             }
1.194     misha      82:             ^case[DEFAULT]{
1.260     moko       83:                 code handling another error
1.207     misha      84:                 ^throw[$exception] << re-throw // DON'T! It's default behaviour!
1.21      paf        85:             }
                     86:         }
1.20      paf        87:     }
1.250     moko       88: 
1.259     moko       89:     ^break[]
1.260     moko       90:         breaks the loop
1.259     moko       91:     ^break(true|false)
1.260     moko       92:         breaks the loop if true
1.259     moko       93: 
                     94:     ^continue[]
1.260     moko       95:         breaks the current iteration of the loop
1.259     moko       96:     ^continue(true|false)
1.260     moko       97:         breaks the current iteration if true
1.259     moko       98: 
                     99:     ^return[]
1.260     moko      100:         stops method execution
1.259     moko      101:     ^return[value]
1.260     moko      102:         assigns $result the value and stops method execution
1.250     moko      103: 
1.260     moko      104:     ^untaint[[as-is|file-spec|uri|http-header|mail-header|sql|js|json|parser-code|regex|xml|html|optimized-[as-is|xml|html]]]{code}
1.1       paf       105:         default as-is
1.250     moko      106: 
1.260     moko      107:     ^taint[[lang]][code]
1.1       paf       108:         default "just tainted, language unknown"
1.250     moko      109: 
1.260     moko      110:     ^apply-taint[[lang;]text]
                    111:         applies transformations specified in the string, "indefinitely dirty" is considered as lang, producing a clean string
1.250     moko      112: 
1.260     moko      113:     ^process[[$caller.CLASS|$object|$CLASS:CLASS]]{string to be processed as code}[
                    114:         $.main[what to rename @main to]
                    115:         $.file[name of the file supposedly containing this text]
                    116:         $.lineno(line number in the file from where this text originated, can be negative)
1.151     paf       117:     ]
1.260     moko      118:     ^process..[path][what to rename @main to]
                    119:         by default, methods are compiled into $self [in case of operator, $self=$MAIN:CLASS]
1.250     moko      120: 
1.260     moko      121:     ^connect[protocol://connection-string]]{code with ^sql[...] calls}
1.254     moko      122:         mysql://user:pass@{host[:port][, host[:port]]|[/unix/socket]}/database?
1.161     paf       123:             ClientCharset=parser-charset << charset in which parser thinks client works
1.248     moko      124:             charset=UTF-8&
1.1       paf       125:             timeout=3&
1.210     misha     126:             compress=0&
1.136     paf       127:             named_pipe=1&
1.260     moko      128:             multi_statements=1&  allow executing more than one query in a single :sql{} request
1.254     moko      129:             config_file=.my.cnf&
                    130:             config_group=parser3&  use group name from .my.cnf
1.136     paf       131:             autocommit=1
1.260     moko      132:             if autocommit is set to 0, it will perform commit/rollback
1.1       paf       133: 
1.250     moko      134:         pgsql://user:pass@{host[:port]|[local]}/database?
1.163     paf       135:             client_encoding=win,[to-find-out]
                    136:             &datestyle=ISO,SQL,Postgres,European,NonEuropean=US,German,DEFAULT=ISO
                    137:             &ClientCharset=parser-charset << charset in which parser thinks client works
1.250     moko      138: 
                    139:         odbc://DSN=dsn^;UID=user^;PWD=password^;ClientCharset=parser-charset
1.162     paf       140:             ClientCharset << charset in which parser thinks client works
1.250     moko      141: 
                    142:         sqlite://DBfile?
1.230     misha     143:             ClientCharset=parser-charset& << charset in which parser thinks client works
                    144:             autocommit=1
1.1       paf       145: 
1.260     moko      146:         to use ^connect, the $SQL table must be defined beforehand (recommended in the system configuration auto.p)
1.1       paf       147: #sql drivers
                    148: $SQL[
1.207     misha     149:     $.drivers[^table::create{protocol  driver  client
1.259     moko      150: mysql  $prefix/libparser3mysql.so      libmysqlclient.so
                    151: pgsql  $prefix/libparser3pgsql.so      libpq.so
                    152: sqlite $prefix/libparser3sqlite.so     sqlite3.so
1.257     moko      153: odbc   parser3odbc.dll
1.1       paf       154: }]
                    155: ]
1.250     moko      156:     ^rem{}
1.260     moko      157:         a comment, removed at compile time
1.250     moko      158: 
1.267     moko      159:     ^syslog[ident;message[;info|warning|error|debug]]
                    160:         writes a message to syslog
                    161: 
1.260     moko      162:     ^cache[file](seconds){code}[{catch code}]
                    163:         relative time assignment
                    164:         caches the string resulting from the code execution for 'seconds' seconds
                    165:         if 0 seconds, do not cache, and remove any existing old cache
                    166:         in the catch code, $exception.handled[cache]  ^rem{flag that exception is handled}
                    167:     ^cache[file][expires date]{code}[{catch code}]
                    168:         absolute time assignment
                    169:     ^cache[file]
                    170:         deletes the file [no error if it doesn't exist]
                    171:     ^cache(seconds)
1.250     moko      172:     ^cache[expires date]
1.260     moko      173:         signals to the upper-level ^cache "reduce it to these many 'seconds'/'expires'"
                    174:         ultimately: ^cache(0) cancels caching
1.259     moko      175:     ^cache[]
1.260     moko      176:         returns the current expires date
1.250     moko      177: 
1.260     moko      178:     each method has a local variable $result. If you put something in it,
                    179:     that will be the method's result, not its body
1.250     moko      180: 
1.260     moko      181:     each method has a local variable $caller, containing the parent stack frame,
                    182:     you can write to its local variables
1.250     moko      183: 
1.260     moko      184:     use(^use or @USE) searches for and includes a file:
                    185:         1. If the path starts with /, it is considered a path from the web root
                    186:         2. Relative to the current directory
                    187:         3. Relative to strings from the $MAIN:CLASS_PATH table, bottom-up
                    188:            $MAIN:CLASS_PATH is a global string or table with a path or paths to a directory
                    189:            with classes (from the web root), set it in the configuration auto.p
                    190: 
                    191:     A global table $CHARSETS[$.name[filename]]
                    192:        defines which characters are considered what (whitespace, letter, etc.), as well as their Unicode
                    193:     format: tab-delimited file, with a header:
1.250     moko      194:         char    white-space    digit    hex-digit    letter    word    lowercase    unicode1    unicode2
1.260     moko      195:         A       x              x        x            a        0x0041  0xFF21
                    196:         where char and lowercase can be letters or 0xCODES
                    197:         if the character has a single Unicode representation equal to itself, you can omit unicode
                    198:     UTF-8 is always available and is the default encoding for request and response
                    199:     WARNING: the encoding name is case-insensitive
                    200: 
                    201: syntax
                    202:     $name[new value]
                    203:     $name(arithmetic expression of new value)
                    204:     $name{code of new value}
                    205:     $name whitespace or ${name}something - variable value
                    206:     ^name parameters - call
                    207:     $name.CLASS - class of the value
                    208:     $name.CLASS_NAME - name of the class
                    209:     $name[$.key[] () {}] - constructor of a hash variable with element $name.key
                    210:     ^method[$.key[] () {}] - constructor of a hash parameter with element $parameter.key
                    211:     $CLASS.name  access a class variable
                    212: 
                    213:     the name ends before: space tab linefeed ; ] } ) " < > + * / % & | = ! ' , ?
                    214:         i.e. you can do $name,aaaa
                    215:         but if you need a character after the name, say -, then ${name}-
                    216: 
                    217:     in expressions, + and - are additional name boundaries
                    218: 
                    219:     you can access compound objects as: $name.subname where subname can be:
                    220:         a string
                    221:         a $variable
                    222:         a string$variable
                    223:         [code computing a string]
                    224:     for example: $hash[$.age(88)] $get[$.field[age]] ^hash.[$get.field].format{%05d}
                    225: 
                    226: parameters := one or more parameters
                    227: parameter :=
                    228:     (arithmetic expression) evaluated multiple times inside the call,
                    229: |   [code] evaluated once before the call,
                    230: |   {code} evaluated zero or many times inside the call,
                    231:     ';' are allowed, making multiple parameters in a single bracket
                    232: 
1.250     moko      233: 
                    234: void
1.260     moko      235:     all methods present in the string class object are available, the result behaves as if it were an empty string
                    236:     ^void:sql{query without result}{$.bind[see table::sql]}
1.250     moko      237: 
                    238: int,double
1.260     moko      239:     ^name.int[]
                    240:          integer value
                    241:     ^name.double[]
                    242:          double value
                    243:     ^name.bool[] ^name.bool(true|false)
                    244:          boolean value
                    245:     ^name.inc(how much +)
                    246:     ^name.dec(how much -)
1.271     moko      247:     ^name.++[] output the value, then increment by 1
                    248:     ^name.--[] output the value, then decrement by 1
1.260     moko      249:     ^name.mul(how much *)
                    250:     ^name.div(how much /)
                    251:     ^name.mod(how much %)
                    252:     ^name.format[format]
                    253:     ^int/double:sql{query}[[$.limit(2) $.offset(4) $.default{0} $.bind[see table::sql]]]
                    254:         the query result should be one column/one row
1.1       paf       255: 
1.250     moko      256: string
1.260     moko      257:     in expression
                    258:         def value means "not empty?"
                    259:         logical/numerical value equals an attempt to convert to double,
                    260:             an empty string quietly converts to 0
                    261:         example:
                    262:         ^if(def $form:name) not empty?
                    263:         ^if($user.isAlive) true? [auto-convert to number, not zero?]
                    264:     ^string:sql{query}[[$.limit(1) $.offset(4) $.default{n/a} $.bind[see table::sql]]]
                    265:         the query result should be one column/one row
                    266:     ^string.int[] ^string.int(default)
                    267:         integer value of the string, if conversion fails, default is taken
                    268:     ^string.double[] ^string.double(default)
                    269:         double value of the string, if conversion fails, default is taken
                    270:     ^string.bool[] ^string.bool(default)
                    271:         boolean value of the string, if conversion fails, default is taken
                    272:     ^string.format[format] %d  %.2f %02d...
                    273:     ^string.match[string-pattern|regex-pattern][[search options]] $prematch $match $postmatch $1 $2...
                    274:         search options:
1.21      paf       275:         i CASELESS
                    276:         x whitespace in regex ignored
1.260     moko      277:         s singleline = $ matches end of entire text
                    278:         m multiline = $ matches end of line[\n], not end of entire text
                    279:         g find all occurrences, not just one
                    280:         ' create columns prematch, match, postmatch
                    281:         n return the number of matches instead of a table
                    282:         U invert the meaning of the '?' modifier
                    283:     ^string.match[string-pattern|regex-pattern][search options]{replacement}
                    284:         additional search option:
                    285:         g replace all occurrences, not just one
                    286:     ^string.split[delimiter|regex][[lrhva]][[column name for vertical splitting]]
                    287:         l left to right [default]
                    288:         r right to left
                    289:         h nameless table with keys 0, 1, 2, ...
                    290:         v table of one column 'piece' or as provided [default]
                    291:         a array
                    292:     ^string.{l|r}split[delimiter] a table from the $piece column
                    293:         kept for compatibility
                    294:     ^string.upper|lower[]
                    295:     ^string.length[]
                    296:     ^string.mid(P[;N])
                    297:         without N - "until the end of the string"
                    298:     ^string.left(N), -1 returns the entire string
                    299:     ^string.right(N)
                    300:     ^string.pos[substring]
                    301:     ^string.pos[substring](position from which to search)
                    302:         <0 = not found
1.275   ! moko      303:     ^string.rpos[substring]
        !           304:         the last substring in the string
        !           305:     ^string.rpos[substring](maximum position of the substring start)
        !           306:         the last substring that starts at or before the position
        !           307:         <0 = not found
1.260     moko      308:     ^string.replace[$table_of_substitutions_string_to_string]
                    309:     ^string.replace[$what;$to]
                    310:     ^string.save[[append;]path]
                    311:     ^string.save[path[;$.charset[in which encoding save] $.append(true)]]
                    312:         saves the string to a file
                    313:     ^string.trim[start|both|end|left|right[;chars]]
                    314:         removes chars from the start/end/or both start and end
1.259     moko      315:         default 'chars' = whitespace chars
1.260     moko      316:     ^string.trim[chars]
                    317:         removes chars from start and end
                    318:     ^string.base64[ $.pad(bool) $.wrap(bool) $.url-safe(bool) ] encode
1.259     moko      319:     ^string:base64[encoded[; $.pad(bool) $.strict(bool) $.url-safe(bool) ]] decode
1.260     moko      320:     ^string.idna[]
                    321:         IDNA encoding, supports Cyrillic domains
1.250     moko      322:     ^string:idna[encoded]
1.260     moko      323:         IDNA decoding, supports Cyrillic domains
                    324:     ^string.js-escape[]
                    325:         encoding for passing to JS (%uXXXX)
1.257     moko      326:     ^string:js-unescape[escaped]
1.260     moko      327:         decoding from js
1.257     moko      328:     ^string:unescape[js|uri;escaped; $.charset[] ]
1.260     moko      329:         decoding passed from js or uri
                    330:     ^string.contains[key]
                    331:         for compatibility with hashtable
1.255     moko      332: 
1.251     moko      333: table
1.260     moko      334:     in expression
                    335:         logical value means "not empty?"
                    336:         numerical value equals count[]
                    337:     $table.field
                    338:     $table.field[new value]
                    339:     $table.fields
                    340:         from a named table returns the current record as a Hash
                    341:     ^table::create[[nameless]]{data}[[$.separator[^#09] $.encloser[]]]
1.251     moko      342:     ^table::create[table][[$.limit(1) $.offset(5) $.offset[cur] $.reverse(1)]]
1.260     moko      343:         clones the table
                    344:         reverse - in reverse order
                    345:     ^table::load[[nameless;]path[;options]]
                    346:         if not nameless, column names are taken from the first line
                    347:         empty lines, and lines in the first column containing '#' are ignored
1.251     moko      348:         $.separator[^#09]
1.260     moko      349:         $.encloser["] by default, none
1.251     moko      350:     ^table::sql{query}[[$.limit(2) $.offset(4) $.bind[hash]]]
1.260     moko      351:         bind associates variables in the query with their values
                    352:         currently implemented only for oracle
                    353:         in the query you need to write ":name"
                    354:         in the bind parameter pass a hash from which the value is taken (or where it is written)
                    355:     ^table.save[[nameless|append;]path[;options, see load]]
                    356:         saves the table to a file
                    357:     ^table.menu{body}[[delimiter]]
                    358:         executes the body code for each row of the table
                    359:     ^table.foreach[position;value]{body}[[delimiter]]
                    360:     ^table.line[]
                    361:         current table row, starting from 1
                    362:     ^table.offset[]
                    363:         offset of the current row from the start, starting from 0
                    364:     ^table.offset[[whence]](5)
                    365:         shifts whence=cur|set, without whence = cur
                    366:     ^table.count[], ^table.count[rows]
                    367:         number of rows in the table
                    368:     ^table.count[columns]
                    369:         number of columns
                    370:     ^table.count[cells]
                    371:         number of cells in the current row
                    372:     ^table.sort{{string-key-maker}|(numeric-key-maker)}[{desc|asc}] default=asc
                    373:     ^table.append{data}
                    374:     ^table.append[ $.column_name[column_value] ]
                    375:     ^table.insert{data} add a record at the current position
                    376:     ^table.insert[ $.column_name[column_value] ]
                    377:     ^table.delete[]
                    378:         deletes the record at the current position
                    379:     ^table.join[table][$.limit(1) $.offset(5) $.offset[cur]]
                    380:         adds records from the table, tables must have the same structure
                    381:     ^table.flip[]
                    382:         returns the transposed version
                    383:     ^table.locate[field;value][[$.limit(1) $.offset(5) $.offset[cur] $.reverse(1)]]
                    384:         moves the current row if found. returns bool
                    385:     ^table.locate(logical expression)[[$.limit(1) $.offset(5) $.offset[cur] $.reverse(1)]]
                    386:         moves the current row if found. returns bool
                    387:     ^table.hash{[field]|{code}|(expression)}[[value field(s)|table of value fields]{value code}][[$.distinct(1) $.distinct[tables] $.type[hash]]]
                    388:         by default $hash.key value is a hash where value fields are keys
                    389:         value fields may not be specified, then they are all columns including the key
                    390:         if distinct is true, no error if duplicate keys
                    391:         if distinct is tables, a hash of tables is created, containing rows with that key
                    392:         $.type[string/table] changes the element value to a string (specify one column) or a table
                    393:     ^table.columns[[column name]]
                    394:         table of one column 'column' or as provided
                    395:     ^table.cells[], ^table.cells(limit)
                    396:         returns an array of cells of the current row
                    397:     ^table.array[]
                    398:         returns an array of hashes, each hash representing the data of one row
                    399:     ^table.array[column]
                    400:         returns an array of values from the specified column
                    401:     ^table.array{code}
                    402:         returns an array of results from executing the given code for each row
                    403:     ^table.rename[column name;new column name] ^table.rename[ $.column_name[new column name] ...]
                    404:         renames a column or multiple columns
                    405:     $selected[^table.select(expression)]
                    406:         a table from those columns and rows where the condition matched
1.86      paf       407:         $adults[^man.select($man.age>=18)]
1.260     moko      408:     ^table.color[color1;color2]
                    409:         alternates color1 and color2 for each row
1.1       paf       410: 
1.251     moko      411: hash
1.260     moko      412:     in expression
                    413:         logical value means "not empty?", a hash with _default is already not empty
                    414:         numerical value equals count[]
                    415:     $hash.key
                    416:         _default - a special key, if defined,
                    417:         then when accessing a non-existing key, _default value is returned
                    418:     $hash.fields
                    419:         returns $hash, making hash class more similar to table class
1.251     moko      420:     ^hash::create[[|copy_from_hash|copy_from_hashfile]]
1.260     moko      421:         creates a new hash, a copy of the old one
                    422:     ^hash.add[term]
                    423:         overwrites entries with the same name
                    424:     ^hash.sub[subtracted]
                    425:     ^hash.union[b]
                    426:         union, same-named remain
                    427:     ^hash.intersection[b][[$.order[self|arg]]]
                    428:         intersection, new hash, order defines the element order (as in the source hash or parameter hash)
                    429:     ^hash.intersects[b] = bool
                    430:     ^hash::sql{query}[[$.distinct(1) $.limit(2) $.offset(4) $.type[hash|string|table]]]
                    431:         results is hash(keys = values of the first column of the response) of hash(keys = names of the other columns), or
                    432:         string = each element's value is a string (need exactly two columns), or
                    433:         table = each element's value is a table
                    434:     ^hash.keys[[name of key column]]
                    435:         a table of one 'key' column or as provided
                    436:     ^hash.count[]
                    437:     ^hash.foreach[key;value]{body}[[delimiter]|{delimiter executed before each non-empty non-first body}]
                    438:     ^hash.delete[key]
                    439:         delete key
1.265     moko      440:     ^hash.contains[key]
1.260     moko      441:         checks if hash contains a key (bool)
                    442:     ^hash.at[first|last][[key|value|hash]]
                    443:     ^hash.at([-]N)[[key|value|hash]]
                    444:         access specified elements of an ordered hash
                    445:     ^hash.set[first|last;value]
                    446:     ^hash.set([-+]N)[value]
                    447:         sets the value of the specified ordered hash element
1.268     moko      448:     ^hash.array[[keys|values]]
                    449:         is equivalent to ^array::copy[$hash] or returns an array of the hash’s keys or values
1.260     moko      450:     ^hash.rename[old_key;new_key]
                    451:     ^hash.rename[ $.old_key[new_key] ...]
                    452:         renames the specified hash keys
                    453:     ^hash.sort[key;value]{{string-key-maker}|(numeric-key-maker)}[[desc|asc]] default=asc
                    454:     $reversed_hash[^hash.reverse[]]
                    455:     $selected[^hash.select[key;value](expression)[ $.limit(N) $.reverse(bool) $.default(bool) ]]
                    456:         a hash of keys and values for which the condition is true
1.255     moko      457: 
1.252     moko      458: hashfile
                    459:     ^hashfile::open[filename]
1.260     moko      460:     ^hashfile.clear[]
                    461:         forget all
                    462:     $hashfile.key[value]
                    463:         put value
                    464:     $hashfile.key[$.value[value] $.expires[VALUE]]
                    465:         put value until expires
                    466:         expires can be a date, or number of days (0days=forever)
                    467:     $hashfile.key retrieve
                    468:     ^hashfile.delete[key] delete key
                    469:     ^hashfile.delete[] delete files containing data
                    470:     ^hashfile.hash[]
                    471:         convert to a regular hash
                    472:         removing expired pairs along the way
                    473:     ^hashfile.foreach[key;value]{body}[[delimiter]|{delimiter executed before each non-empty non-first body}]
                    474:     ^hashfile.release[]
                    475:         write data and release locks.
                    476:         next access to elements will reopen automatically.
                    477:     ^hashfile.cleanup[]
                    478:         iterate all elements and delete expired ones.
1.132     paf       479: 
1.260     moko      480:     example:
1.170     paf       481:     $sessions[^hashfile::open[/db/sessions]]
                    482:     $sid[^math:uuid[]]
                    483:     $sessions.$sid[$.value[$uid] $.expires(1)]
                    484:     $uid[$sessions.$sid]
1.132     paf       485: 
1.255     moko      486: array
1.260     moko      487:     in expression
                    488:         logical value means "not empty?"
                    489:         numerical value equals count[]
                    490:     $array.index, $array.(expression)
                    491:         returns the value at the given index
                    492:     $array.index[value], $array.(expression)[value]
                    493:         assigns a value by index
                    494:     $array[value;value;...]
                    495:         creates an array with the given values
1.255     moko      496:     ^array::create[]
1.260     moko      497:     ^array::create[value;value;...]
                    498:         creates an array with the given values or an empty array
                    499:     ^array::copy[array or hash with numeric keys]
                    500:         copies an array or a hash with numeric keys
                    501:     ^array.add[array or hash with numeric keys]
                    502:         adds elements from another array or hash, overwriting values for matching indexes
                    503:     ^array.join[array or any hash]
                    504:         appends elements from another array or hash to the end of the array
                    505:     ^array.append[value;value;...]
                    506:         appends elements to the end of the array
                    507:     ^array.insert(index)[value;value;...]
                    508:         inserts elements at the specified position in the array
                    509:     ^array.left(n)
                    510:         returns a new array of the first n elements
                    511:     ^array.right(n)
                    512:         returns a new array of the last n elements
                    513:     ^array.mid(m;n)
                    514:         returns a new array containing n initialized elements starting from position m
                    515:     ^array.delete(index)
                    516:         deletes an array element, leaving an empty spot
                    517:     ^array.remove(index)
                    518:         deletes an element and shifts subsequent elements to fill the gap
                    519:     ^array.push[value]
                    520:         adds an element to the end of the array
                    521:     ^array.pop[]
                    522:         returns the last element and removes it from the array
1.265     moko      523:     ^array.contains(index)
1.260     moko      524:         checks if an element exists at the given index (bool)
                    525:     ^array::sql{query}[ $.sparse(false|true) $.distinct(false|true) $.limit(n) $.offset(n) $.type[hash|string|table] ]
                    526:         creates an array based on a database query
                    527:         $.sparse(false), default - create a normal array. Row values from the query are added sequentially
                    528:         $.sparse(true) - create a sparse array. The first column must contain indexes
                    529:         at which values will be placed (similar to ^hash::sql{})
                    530:         result is an array of hash (keys=column names of the rest of the answer) or
                    531:         string = each element's value is a string (need exactly two columns), or
                    532:         table = each element's value is a table
                    533:     ^array.keys[[column name for keys]]
                    534:         a table of one 'key' column (or as provided) with the indexes of initialized elements
                    535:     ^array.count[]
                    536:         the number of initialized elements in the array
                    537:     ^array.count[all]
                    538:         the total number of elements, including uninitialized ones
                    539:     ^array.foreach[index;value]{code}[[delimiter]|{delimiter executed before each non-empty non-first body}]
                    540:         iterates over all initialized elements
                    541:     ^array.for[index;value]{code}[[delimiter]|{delimiter executed before each non-empty non-first body}]
                    542:         iterates over all elements
                    543:     ^array.at[first|last][[key|value|hash]]
                    544:     ^array.at([-]number)[[key|value|hash]]
                    545:         accesses an array element by its ordinal number
                    546:     ^array.set[first|last][value]
                    547:     ^array.set([-]number)[value]
                    548:         sets the value of an array element by ordinal number
                    549:     ^array.compact[]
                    550:         removes uninitialized elements
                    551:     ^array.compact[undef]
                    552:         removes uninitialized and empty elements
                    553:     ^array.sort[key;value]{{string-key-maker}|(numeric-key-maker)}[[desc|asc]] default=asc
                    554:         sorts the array
                    555:     $reversed_array[^array.reverse[]]
                    556:         returns a new array with elements in reverse order
                    557:     $selected[^array.select[key;value](expression)[ $.limit(N) $.reverse(bool) ]]
                    558:         selects array elements for which the condition is true
1.255     moko      559: 
1.262     moko      560: date
                    561:     date type can be used in expressions, substituting the number of days since epoch [1 January 1970 (UTC)], fractional
                    562:     the string value is in local time, numerically in UTC, range from 0000-00-00 00:00:00 to 9999-12-31 23:59:59
                    563:     by default the OS-defined timezone is used
                    564: 
                    565:     ^date::now[]
                    566:     ^date::now(days offset)
                    567:         returns now+offset
                    568:     ^date::today[]
                    569:         date at 00:00:00 of the current day
                    570:     ^date::today(integer days offset)
                    571:         date at 00:00:00 of current day+offset
                    572:     ^date::create(days since epoch)
                    573:     ^date::create(year;month[;day[;hour[;minute[;second[;TZ]]]]])
                    574:     ^date::create[date in format %Y-%m-%d %H:%M:%S]
                    575:         convenient creation from a value from a database
                    576:         format1: %Y[-%m[-%d[ %H[:%M[:%S]]]]]
                    577:         format2: %H:%M[:%S]
                    578:     ^date::create[date in format %Y-%m-%dT%H:%M[:%S]TZ]
                    579:         for creation from ISO 8601 format
                    580:         TZ format: Z(UTC) or +-hour[:minute] (offset from UTC)
                    581:     ^date::unix-timestamp()
                    582:     ^date.unix-timestamp[]
                    583:     $date.year month day hour minute second weekday yearday(0...) daylightsaving TZ weekyear
                    584:         TZ="" << local zone
                    585:     $date.year month day hour minute second can be set to new values, others are read-only
                    586:     ^date.double[] ^date.int[]
                    587:         the number of days since epoch [1 January 1970 (UTC)], fractional or truncated
                    588:     ^date.roll[year|month|day](+-offset)
                    589:         shifts the date
                    590:     ^date.roll[TZ;New zone]
                    591:         says that the date is in such a timezone: affects .hour & Co
                    592:     ^date:roll[TZ;New zone]
                    593:         says that by default all dates are in that timezone
                    594:     ^date.sql-string[[datetime|date|time]]
                    595:         datetime or without parameter - %Y-%m-%d %H:%M:%S
                    596:         date                          - %Y-%m-%d
                    597:         time                          - %H:%M:%S
                    598:         where published='^date.sql-string[]'
1.269     moko      599:     ^date:sql-string[[datetime|date|time]]
                    600:         sql-string for now
1.262     moko      601:     ^date:calendar[rus|eng](year;month)
                    602:         returns an unnamed table, columns: 0..6, week, year
                    603:     ^date:calendar[rus|eng](year;month;day)
                    604:         returns a named table, columns: year, month, day, weekday
                    605:     ^date:last-day(year;month)
                    606:         returns the last day of the month
                    607:     ^date.last-day[]
                    608:         returns the last day of $date's month
                    609:     ^date.gmt-string[]
                    610:         Fri, 23 Mar 2001 09:32:23 GMT
1.269     moko      611:     ^date:gmt-string[]
                    612:         gmt-string for now
1.262     moko      613:     ^date.iso-string[]
                    614:         2001-03-23T12:32:23+03
1.269     moko      615:     ^date:iso-string[]
                    616:         iso-string for now
1.262     moko      617: 
                    618: file
                    619:     $uploaded_file_from_post.name
                    620:     $uploaded_file_from_post.size
                    621:     $uploaded_file_from_post.text
1.268     moko      622:     ^file.save[text|binary;filename[;$.charset[which charset to save in] $.append(false)]]
1.262     moko      623:     ^file:delete[filename]
1.275   ! moko      624:     ^file:rmdir[dirname[; $.exception(false) ]]
        !           625:         removes the empty directory
1.262     moko      626:     ^file:find[filename][{if not found}]
                    627:     ^file:list[path[;pattern-string|pattern-regex]]
                    628:         table with columns name dir
                    629:     ^file:list[path;$.filter[pattern-string|pattern-regex] $.stat(true)]
                    630:         table with columns name dir size [mca]date
                    631:     ^file::load[text|binary;big.zip[;domain_press_release_2001_03_01.zip][;options]]
                    632:     ^file::create[text|binary;filename;data]
                    633:     ^file::create[text|binary;filename;data[;$.charset[charset of the created file] $.content-type[...]]]
                    634:     ^file::create[string-or-file-content[;$.name[name] $.mode[text|binary] $.content-type[...] $.charset[...]]]
                    635:     $loaded_file.size
                    636:     $loaded_or_created_file.mode = text/binary
                    637:     ^file::stat[filename]
                    638:     $stated_or_loaded_file.size .adate .mdate .cdate
                    639:     ^file::cgi[[text|binary;]filename[;env hash +options[;1cmd[;2line[;3ar[;4g[;5s]]]]]]]
                    640:         any argument can be string or array of strings
                    641:         the returned header is split into $fields
                    642:         $status
                    643:         $stderr
                    644:     ^file::exec[[text|binary;]filename[;env hash[;1cmd[;2line[;3ar[;4g[;5s;...under unix max 50 args]]]]]]]
                    645:         any argument can be string or array of strings
                    646:         options:
                    647:             $.stdin[text|file] if empty, disables automatic passing of HTTP-POST data
                    648:     ^file:move[oldfilename;newfilename]
1.275   ! moko      649:         can rename and move files and directories, but not across disk boundaries
        !           650:         the existing file is replaced, as well as the empty directory if a directory is moved
1.262     moko      651:         directories for dest are created with 775 permissions
                    652:         source directory is removed if empty after move
                    653:     ^file:copy[filename;copy_filename[; $.append(1) ]]
                    654:         can only copy files
                    655:     ^file:lock[filename]{code}
                    656:         the file is created if necessary
                    657:         locked
                    658:         code executed
                    659:         unlocked
                    660:     ^file:dirname[/a/some.tar.gz|file]=/a (works like *nix command)
                    661:     ^file:dirname[/a/b/|file]=/a (works like *nix command)
                    662:     ^file:basename[/a/some.tar.gz|file]=some.tar.gz (like *nix)
                    663:     ^file:basename[/a/b/|file]=b (like *nix)
                    664:     ^file:justname[/a/some.tar.gz|file]=some.tar
                    665:     ^file:justext[/a/some.tar.gz|file]=gz
                    666:     /some/page.html: ^file:fullpath[a.gif] => /some/a.gif
                    667:     ^file.sql-string[]
                    668:         inside ^connect gives a correctly escaped string that can be used in queries
                    669:     ^file::sql{query}[[ $.name[filename_for_download] $.content-type[user content-type] ]]
                    670:         the query result should be "one row".
                    671:         columns:
                    672:         first column - data
                    673:         if second exists - filename
                    674:         if third - content-type
                    675:     ^file.base64[ $.pad(bool) $.wrap(bool) $.url-safe(bool) ]
                    676:         encode
                    677:     ^file:base64[filename[; $.pad(bool) $.wrap(bool) $.url-safe(bool) ]]
                    678:         encode
                    679:     ^file::base64[encoded string[; $.pad(bool) $.strict(bool) $.url-safe(bool) ]]
                    680:         decode
                    681:     ^file::base64[mode;filename;encoded string[; $.content-type[...] $.pad(bool) $.strict(bool) $.url-safe(bool) ]]
                    682:         decode
                    683:     ^file:crc32[filename]
                    684:         calculates crc32 of the specified file
                    685:     ^file.crc32[]
                    686:         calculates crc32 of the object
                    687:     ^file.md5[], ^file:md5[filename]
                    688:         returns the file's digest, 16 bytes as a string,
                    689:         bytes in hex, contiguous, lowercase
                    690: 
                    691: image
                    692:     $image[^image::measure[DATA[; $.exif(bool) $.xmp(bool) $.xmp-charset[] $.video(bool) ]]]
                    693:         checks the file extension case-insensitively
                    694:         can measure gif, jpg, tiff, bmp, webp and mp4 (mov)
                    695:     $image.exif << hash after measure jpeg with exif information and $.exif(true)
                    696:         $image.exif.DateTime & co
                    697:             [full list see https://exiftool.org/TagNames/EXIF.html]
                    698:         numbers as int/double,
                    699:         dates as date,
                    700:         enumerations as hash with keys 0..count-1
                    701:     $image.src .width .height
                    702:     $image.line-width  number=line width
                    703:     $image.line-style  string=line style '*** * '='*** * *** * *** * '
                    704:     ^image.html[[hash]]
                    705:         <img ...>
                    706:     ^image::load[background.gif]
                    707:         only gif so far
                    708:     ^image::create(width X;height Y[;background color default white]])
                    709:     ^image.line(x0;y0;x1;y1;0xffFFff)
                    710:     ^image.fill(x;y;0xffFFff)
                    711:     ^image.rectangle(x0;y0;x1;y1;0xffFFff)
                    712:     ^image.bar(x0;y0;x1;y1;0xffFFff)
                    713:     ^image.replace(hex-color1;hex-color2)[table x:y polygon_vertices]
                    714:     ^image.polyline(color)[table x:y points]
                    715:     ^image.polygon(color)[table x:y polygon_vertices]
                    716:     ^image.polybar(color)[table x;y polygon_vertices]
                    717:     ^image.font[set_of_letters;font_file.gif][(space_width[;char_width])]
                    718:         the character height = image height/number of letters in the set
                    719:         if char_width is specified, then monospaced, if 0, char_width = gif width
                    720:     ^image.font[set_of_letters;font_file.gif;
                    721:         $.space(space_width)      // default = gif width
                    722:         $.width(char_width)       // see above, default proportional
                    723:         $.spacing(letter_spacing) // default = 1
                    724:     ]
                    725:     ^image.text(x;y)[text] AS_IS
                    726:     ^image.length[text] AS_IS
                    727:     ^image.gif[optional filename]
                    728:         encodes to FILE with content-type=image/gif the filename will be used by $response:download
                    729:     ^image.arc(center x;center y;width;height;start in degrees;end in degrees;color)
                    730:     ^image.sector(center x;center y;width;height;start in degrees;end in degrees;color)
                    731:     ^image.circle(center x;center y;r;color)
                    732:     ^image.copy[source](src x;src y;src w;src h;dst x;dst y[;dest w[;dest h[;tolerance]]])
                    733:         if dest_w/dest_h are specified, resizes the piece
                    734:             when reducing size, does resample
                    735:             only suitable for simplifying low-color graphics like charts/pie,
                    736:             not suitable for thumbnails
                    737:         if dest_h is not specified, aspect ratio is kept
                    738:         tolerance - a number [square distance in RGB space to the target color],
                    739:             defining how greedy the color approximation from the palette is [default=150]
                    740:             smaller - more accurate but colors run out quickly
                    741:             larger - less accurate approximation, but covers a bigger part
                    742:     ^image.pixel(x;y)[(color)]
                    743:         get or set pixel color
                    744: 
                    745: regex
                    746:     in expression
                    747:         logical value is always true
                    748:         numerical value is equal to the number of bytes of the compiled pattern
                    749:     ^regex::create[pattern-string|regex][[search options]]
                    750:     ^pattern.size[]
                    751:         number of bytes of the compiled pattern
                    752:         if the value is very large - it is worth consulting pcre documentation and possibly rewriting the pattern
                    753:     ^pattern.study_size[]
                    754:         size of the study-structure. if == 0 - the pattern cannot be "studied"
                    755:     $pattern.pattern
                    756:         the text of the pattern
                    757:     $pattern.options
                    758:         the string with the original text of the options
                    759: 
1.273     moko      760: amqp
                    761:     ^amqp::create[[
                    762:         $.host[localhost] $.port(5672) $.user[guest] $.password[guest] $.vhost[/] $.locale[en_US]
                    763:         $.heartbeat(30) $.auto_reconnect(seconds)
                    764:         $.tls[ $.ca[file] $.cert[file] $.key[file] $.verify(true) ]
                    765:     ]]
                    766:         connects to a RabbitMQ broker
                    767:         auto_reconnect(N): after a lost connection reconnect before the next operation, waiting N seconds
                    768:         tls: the server certificate is verified only if ca is specified
                    769:     ^amqp.publish[message][[
                    770:         $.exchange[] $.routing_key[key]|$.queue[name] $.mandatory(false)
                    771:         message properties: $.content_type[] $.content_encoding[] $.delivery_mode(1|2) $.priority(N) $.correlation_id[] $.reply_to[]
                    772:             $.expiration[] $.message_id[] $.timestamp(N) $.type[] $.user_id[] $.app_id[] $.cluster_id[] $.headers[hash]
                    773:     ]]
                    774:     ^amqp.consume[ $.queue[name] $.ack(true) $.count(1) $.timeout(0) $.exclusive(false) $.consumer_tag[] ]
                    775:         array of messages ready within timeout seconds (only the first one is waited for)
                    776:     ^amqp.consume[ $.queue[name] $.callback[$method] ... ]
                    777:         calls @method[message] for each message until ^amqp.stop_consume[], count messages or timeout seconds without messages
                    778:         count and timeout are unlimited by default
                    779:     message: hash with msg, delivery_tag, routing_key, exchange, redelivered, consumer_tag and the properties set
                    780:     ^amqp.ack(delivery_tag)
                    781:         with $.ack(true) (default) received messages must be acknowledged
                    782:     ^amqp.nack(delivery_tag)[ $.requeue(false) ]
                    783:     ^amqp.reject(delivery_tag)[ $.requeue(true) ]
                    784:     ^amqp.qos[ $.prefetch_count(N) ]
                    785:     ^amqp.declare[ $.queue[name] $.durable(false) $.exclusive(false) $.auto_delete(false) $.passive(false) $.arguments[hash] ]
                    786:         for an empty name the server creates a queue with its own name, which is returned
                    787:     ^amqp.declare[ $.exchange[name] $.type[direct] $.durable(false) $.auto_delete(false) $.internal(false) $.passive(false) $.arguments[hash] ]
                    788:     ^amqp.delete[ $.queue[name]|$.exchange[name] $.if_unused(false) $.if_empty(false) ]
                    789:     ^amqp.bind[ $.exchange[name] $.queue[name] $.routing_key[] ]
                    790:     ^amqp.unbind[ $.exchange[name] $.queue[name] $.routing_key[] ]
                    791:     ^amqp.purge[ $.queue[name] ]
                    792:         number of deleted messages
                    793:     ^amqp.info[ $.queue[name] ]
                    794:         hash with queue, messages, consumers
                    795:     ^amqp.release[]
                    796:         closes the connection
                    797:     arguments and headers values: [string], (number), (true|false)
                    798: 
1.262     moko      799: console
                    800:     $console:timeout
                    801:     $console:line
                    802:         read/write string
                    803: 
                    804: cookie
                    805:     $cookie:name read old or newly set cookie
                    806:     $cookie:name[value] for 90 days
                    807:     $cookie:name[$.value[value] $.expires[VALUE] $.secure(true) $.domain[domain name] $.httponly(true)]
1.272     moko      808:         the expires field value can be 'session', a date, or a number of days (0days=session)
1.262     moko      809:         if it's a date, it will be converted to "Sun, 25-Aug-2002 12:03:45 GMT"
                    810:     $cookie:fields
                    811:         hash with all cookies
                    812: 
1.263     moko      813: curl
                    814:     ^curl:load[[
                    815:         $.url[http://URL]
                    816:         $.timeout(N)
                    817:         $.ssl_verifypeer(0)
                    818:         $.mode[text|binary] type of the created file
                    819:     ]]
                    820:         downloads a file from a remote server, can be called multiple times within one session;
                    821:         any libcurl option can be specified, option names in lowercase without the CURLOPT_ prefix
                    822:     ^curl:options[[
                    823:         $.library[libcurl.so.4]
                    824:         $.charset[UTF-8]
                    825:         ...
                    826:     ]]
                    827:         subsequent ^curl:load calls inherit the specified options, the path to libcurl must be set before using curl
                    828:     ^curl:session{code}
                    829:         creates a cURL session, common options can be set, multiple downloads performed
                    830:     ^curl:info[name], ^curl:info[]
                    831:         information about the last request (a value or a hash)
                    832:     ^curl:version[]
                    833:         the version of the cURL library in use
                    834: 
1.262     moko      835: env
                    836:     $env:variable
                    837:     $env:fields hash with environment variables
                    838:     $env:PARSER_VERSION parser version
                    839: 
1.252     moko      840: form
1.260     moko      841:     [the first element with the same name is taken from GET, then from POST]
                    842:     $form:field
1.257     moko      843:         string/file
                    844:     $form:nameless
1.260     moko      845:         field with a value from a nameless parameter "?value&...", "...&value&...", "...&value"
1.257     moko      846:     $form:qtail
1.260     moko      847:         string with the value after the second "?xxxxx" if there was no ',' [imap]
1.257     moko      848:     $form:fields
1.260     moko      849:         hash with all form fields
                    850:     $form:elements.field
                    851:         array with all values of the field - both string and file
                    852:     $form:tables.field
                    853:         table with one column "field" containing the values for multiple entries
                    854:     $form:files.field
                    855:         hash with file-type field values, keys - 0, 1, ..., value - file
1.257     moko      856:     $form:imap
1.260     moko      857:         a hash with keys 'x' and 'y' with ?1,2 suffixes when using server-side image map
1.1       paf       858: 
1.262     moko      859: inet
                    860:     ^inet:ntoa(long)
                    861:     ^inet:aton[IP]
                    862:     ^inet:name2ip[name][[ $.ipv[4|6|any] $.table(true) ]]
                    863:         direct conversion of a name to an IP address
                    864:     ^inet:ip2name[ip][ $.ipv[4|6|any] ]
                    865:         reverse conversion from IP address to name
                    866:     ^inet:hostname[]
                    867:         host name
1.252     moko      868: 
1.262     moko      869: json
                    870:     ^json:parse[-json-string-[;
                    871:         $.depth(maximum depth, default == 19)
                    872:         $.double(false)              disable built-in parsing of floating-point numbers (enabled by default)
                    873:                                      in this case they will appear in the resulting object as strings
                    874:         $.int(false)                 disable built-in parsing of integers (enabled by default)
                    875:                                      in this case they will appear in the resulting object as strings
                    876:         $.distinct[first|last|all]   how duplicate keys in objects are handled
                    877:                                      first - keep the first encountered element
                    878:                                      last  - keep the last encountered element
                    879:                                      all   - keep all elements. starting from the 2nd,
                    880:                                               they get numeric suffixes (key_2 etc)
                    881:                                      by default duplicate keys cause an exception
                    882:         $.object[method-junction]    user method[key;object], called for all parsed
                    883:                                      objects and object keys; method returns a new object
                    884:         $.array[method-junction]     user method called for arrays
                    885:         $.taint[taint language]      sets the transformation language for all result strings
                    886:     ]]
                    887:         parses a json-string into a hash
1.252     moko      888: 
1.262     moko      889:     ^json:string[system or user object[;
                    890:         $.skip-unknown(false)    disable exception and output 'null' when serializing objects of types
                    891:                                  other than void, bool, string, int, double, date, table, hash, and file
                    892:         $.indent(true)           format the resulting string with indentation according to nesting depth
                    893:         $.date[sql-string|gmt-string|iso-string|unix-timestamp]
                    894:                                  date output format, default = sql-string
                    895:         $.table[object|array|compact]
                    896:                                  format for tables, default=object
                    897:                                  object: [{"c1":"v11","c2":"v12",...},{"c1":"v21","c2":"v22",...},...]
                    898:                                  array:  [["c1","c2",...] || null (for nameless),["v11","v12",...],...]
                    899:                                  compact: ["v11" || ["v11","v12",...],...]
                    900:         $.file[text|base64|stat] output file content in the specified mode (by default file content
                    901:                                  is not included in output)
                    902:         $.xdoc[hash]             parameters for converting xdoc to string (as in ^xdoc.string[])
                    903:         $.type[method-junction]  any type can be output using a user method
                    904:                                  that must take 3 parameters: key, object of that type, and options
                    905:                                  of the ^json:string[] call
                    906:         $._default[method]       user method, called to output all user-class objects.
                    907:                                  The method must take 3 parameters: key, object, and call options.
                    908:         $._default[method name]  method name of a user method, if present it will be called for serialization
                    909:         $.void[null|string]      undefined value will be output as null (default)
                    910:                                  or as an empty string
                    911:     ]]
                    912:         serializes a system or user object into a json-string
1.220     misha     913: 
1.252     moko      914: mail
                    915:     $mail.received=MESSAGE:
1.51      paf       916:         .from
                    917:         .reply-to
                    918:         .subject
1.260     moko      919:         .date of class date
1.51      paf       920:         .message-id
                    921:         .raw[
1.260     moko      922:             .RAW_USER_HEADER_FIELD
1.51      paf       923:         ]
1.260     moko      924:         $.{text|html|file#}[ << numbered as in mail:send (text, text2, ...) (file, file2, ...)
1.51      paf       925:             $.content-type[
                    926:                 $.value[{text|...|x-unknown}/{plain|html|...|x-unknown}]
1.260     moko      927:                 [$.charset[windows-1251]] << in which it arrived, now already transcoded
                    928:                 $.USER_DEFINED_HEADER_FIELD
1.51      paf       929:             ]
                    930:             $.description
                    931:             $.content-id
                    932:             $.content-md5
                    933:             $.content-location
                    934:             .raw[
1.260     moko      935:                 .RAW_USER_HEADER_FIELD
1.51      paf       936:             ]
1.260     moko      937:             $.value[string|FILE]
1.51      paf       938:         ]
1.52      paf       939:         $.message#[MESSAGE] (message, message2, ...)
1.51      paf       940: 
1.252     moko      941:     ^mail:send[
1.230     misha     942:         $.options[-odd]
1.260     moko      943:             unix: a string that will be added to the sendmail startup command
                    944:                 -odd means "quickly put in the queue without email checking"
                    945:             win32: ignored
                    946:         $.charset[the encoding of the headers and text blocks]
1.252     moko      947:         $.any-header-field
1.51      paf       948:         $.text[string]
                    949:         $.text[
1.260     moko      950:             $.any-header-field
                    951:             $.value[string]
1.51      paf       952:         ]
                    953:         $.html{string}
                    954:         $.html[
1.252     moko      955:             $.any-header-field
1.51      paf       956:             $.value{string}
                    957:         ]
                    958:         $.file#[FILE]
                    959:         $.file#[
1.252     moko      960:             $.any-header-field
1.51      paf       961:             $value[FILE]
                    962:         ]
                    963:     ]
1.264     moko      964:         if charset is specified, the email is transcoded to this charset
                    965:         content-type.charset does not affect transcoding
                    966:         after the part name a # number can follow
1.252     moko      967: 
                    968:     ^mail:send[
1.260     moko      969: #       by default, matches the source encoding.
                    970: #       sets the body encoding
1.252     moko      971:         $.charset[windows-1251]
1.260     moko      972: #       no default
1.252     moko      973:         $.content-type[$.value[text/plain] $.charset[windows-1251]]
1.260     moko      974:         $.from["vasya" <vasya@design.ru>]
                    975:         $.to["petya" <petya@design.ru>]
                    976:         $.subject[subject]
1.252     moko      977:         $.body[
1.260     moko      978:             text
1.51      paf       979:         ]
1.252     moko      980:     ]
                    981: 
1.260     moko      982:     ^mail:send[$.header-field[] $.charset[mail encoding] $.body[if body is not a string, but a hash, a multipart email is sent]]
                    983:         if charset is specified, the email is transcoded to that charset
                    984:         content-type.charset does not affect transcoding
                    985:         after the part name, an integer can follow, parts go in numerical order.
                    986:         if body is a string, then it's just the email text, no attachments.
                    987:         if body is a hash, then these are parts, text blocks first, then attachments
                    988:         this is the old format, supported for backward compatibility
                    989:         if the part name begins with "text", it's a text block.
                    990:         if the part name begins with "file", it's an attachment, format:
1.253     moko      991:             $file[$.format[uue|base64] $.value[DATA] $.name[user-file-name]]
1.260     moko      992:         important: for multipart do not specify content-type
1.252     moko      993: 
1.1       paf       994:         ^mail:send[
1.260     moko      995: #           by default, matches the source encoding
                    996: #           sets the body encoding
1.252     moko      997:             $.charset[windows-1251]
1.260     moko      998: #           no default
1.1       paf       999:             $.content-type[$.value[text/plain] $.charset[windows-1251]]
1.260     moko     1000:             $.from["vasya" <vasya@design.ru>]
                   1001:             $.to["petya" <petya@design.ru>]
                   1002:             $.subject[subject]
1.1       paf      1003:             $.body[
1.260     moko     1004:                 text
1.1       paf      1005:             ]
                   1006:         ]
1.252     moko     1007: 
1.1       paf      1008:         ^mail:send[
1.260     moko     1009:             $.from["vasya" <vasya@design.ru>]
                   1010:             $.to["petya" <petya@design.ru>]
                   1011:             $.subject[subject]
1.1       paf      1012:             $.body[
                   1013:                 $.text[
1.260     moko     1014: #                   sets the body encoding
1.1       paf      1015:                     $.charset[windows-1251]
1.260     moko     1016: #                   no default
1.1       paf      1017:                     $.content-type[$.value[text/plain] $.charset[windows-1251]]
1.260     moko     1018:                     $.body[words]
1.1       paf      1019:                 ]
1.260     moko     1020: #               for convenience you can specify only one part, then it won't be multipart
1.189     misha    1021:                 $.file[
1.259     moko     1022:                     $.value[^file::load[my beloved.doc]]
                   1023:                     $.name[my beloved.doc]
                   1024:                     $.format[base64]
1.1       paf      1025:                 ]
1.189     misha    1026:                 $.file2[
1.259     moko     1027:                     $.value[^file::load[my beloved.doc]]
                   1028:                     $.name[my beloved.doc]
                   1029:                 ]
1.1       paf      1030:             ]
                   1031:         ]
1.260     moko     1032:     under unix, the program with arguments is used, set by
                   1033:         $MAIL.sendmail[command]
                   1034:     if not specified, checks if /usr/sbin/sendmail or
                   1035:     /usr/lib/sendmail is available and if so, runs with "-t".
1.252     moko     1036: 
1.260     moko     1037:     under Windows, SMTP protocol is used, server is set by
1.21      paf      1038:         $MAIL.SMTP[smtp.domain.ru]
1.1       paf      1039: 
1.253     moko     1040: math
                   1041:     $math:PI
                   1042:     ^math:round floor ceiling
                   1043:     ^math:trunc frac
                   1044:     ^math:abs sign
1.275   ! moko     1045:     ^math:min(a;b[;c...]) max(a;b[;c...])
1.256     moko     1046:     ^math:exp log log10
                   1047:     ^math:sin asin cos acos tan atan atan2
1.253     moko     1048:     ^math:degrees radians
                   1049:     ^math:pow sqrt
1.260     moko     1050:     ^math:random(range_width)
                   1051:     ^math:convert[number|file](base-from;base-to)[[ $.format[string|file] ]]
                   1052:     ^math:convert[number|file][alphabet](base-to)[[ $.format[string|file] ]]
                   1053:     ^math:convert[number|file](base-from)[alphabet][[ $.format[string|file] ]]
                   1054:         converts a string or file with a number from one numeral system to another
                   1055:         the numeral system can be set by an alphabet, a number from 2 to 16 (equivalent to the alphabet 0123456789ABCDEF), or 256 (all ASCII characters)
1.270     moko     1056:     ^math:eq(a;b[;max ULP])
                   1057:         true if difference between doubles less or equal max ULPs (default 3)
1.254     moko     1058:     ^math:uuid[ $.lower(bool) $.solid(bool) ]
1.113     paf      1059:         22C0983C-E26E-4169-BD07-77ECE9405BA5
1.260     moko     1060:         win32: uses cryptapi
                   1061:         unix: uses /dev/urandom,
                   1062:             if not present, /dev/random,
                   1063:             if not, rand
1.256     moko     1064:     ^math:uuid7[ $.lower(bool) $.solid(bool) ]
                   1065:         0193CBF0-7898-7000-A391-AC513CC15658
                   1066:         https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7
1.254     moko     1067:     ^math:uid64[ $.lower(bool) ]
1.253     moko     1068:         BA39BAB6340BE370
                   1069:     ^math:md5[string]
1.260     moko     1070:         returns the digest of the string, 16 bytes as a string,
                   1071:         bytes in hex, contiguous, lowercase
1.253     moko     1072:     ^math:crypt[password;salt]
1.260     moko     1073:         salt prefix $apr1$ triggers built-in MD5 algorithm,
                   1074:         if salt body is empty, it is generated randomly
                   1075:         $1$ calls the OS 'crypt' MD5 algorithm if supported.
                   1076:         for other salts see OS 'crypt' documentation.
1.253     moko     1077:     ^math:crc32[string]
1.260     moko     1078:         calculates crc32 of the string
1.253     moko     1079:     ^math:sha1[string]
1.260     moko     1080:     ^math:digest[[md5|sha1|sha256|sha512];string or file][[ $.format[hex|base64|file] $.hmac[key string|key file] ]]
                   1081:         combines the ability to use various cryptographic hashing algorithms.
                   1082:         $.hmac[key] for verifying the integrity of transmitted data
1.253     moko     1083: 
1.260     moko     1084: memory
                   1085:     ^memory:compact[]
                   1086:         collect garbage, freeing space for new data (warning: process memory is never released)
                   1087:         useful before XSL transform
                   1088:     ^memory:auto-compact(frequency)
                   1089:         sets automatic garbage collection frequency, from 0 (off) up to 5 (max)
                   1090: 
1.262     moko     1091: reflection
                   1092:     ^reflection:create[class;constructor[;pa[;ra[;ms]]]]
                   1093:         calls the specified class constructor (no more than 100 parameters)
                   1094:     ^reflection:create[ $.class[name] $.constructor[name] $.arguments[ $.1[pa] $.2[ra] $.3[ms] ] ]
                   1095:         calls the specified class constructor
                   1096:     ^reflection:classes[]
                   1097:         a hash of all classes. key = class name, value can be methoded (a class with methods) or void
                   1098:     ^reflection:class[object]
                   1099:         the class of the given object
                   1100:     ^reflection:class_name[object]
                   1101:         the class name of the given object
                   1102:     ^reflection:base[object]
                   1103:         the parent class of the given object
                   1104:     ^reflection:base_name[object]
                   1105:         the parent class name of the given object
                   1106:     ^reflection:class_by_name[class name]
                   1107:         obtains the class by name
                   1108:     ^reflection:class_alias[class name;new class name]
                   1109:         sets an alias for the specified class
                   1110:     ^reflection:def[class;class name]
                   1111:         checks if the class exists
                   1112:     ^reflection:methods[class]
                   1113:         a hash with a list of methods of the specified class, values are strings 'native' or 'parser'
                   1114:     ^reflection:method[class or object;method name]
                   1115:         returns the junction-method of the class or object
                   1116:     ^reflection:filename[object or class or method]
                   1117:         returns the filename where the object, class or method is defined
                   1118:     ^reflection:fields[class or object]
                   1119:         a hash with the list of static fields of the specified class or dynamic fields of the specified object
                   1120:     ^reflection:fields_reference[object]
                   1121:         an editable hash of the dynamic fields of the specified object
                   1122:     ^reflection:field[class or object;field name]
                   1123:         returns the value of the specified field of the class or object. getters are ignored.
                   1124:     ^reflection:copy[source;destination]
                   1125:         copies fields from one object or class to another
                   1126:     ^reflection:uid[class or object]
                   1127:         returns the identifier of the object or class
                   1128:     ^reflection:method_info[class;method]
                   1129:         a hash with parameters of the specified class method
                   1130:         $.inherited[class] name of the class where the method was defined (returned only if the method was defined in an ancestor)
                   1131:         $.overridden[class] name of the class where the method was defined (returned only if the method was defined in an ancestor)
                   1132:         for native classes a hash is returned:
                   1133:             .min_params(minimum required number of parameters)
                   1134:             .max_params(maximum possible number of parameters)
                   1135:             .call_type[dynamic|static|any]
                   1136:         for parser classes a hash is returned:
                   1137:             key is parameter number (0, 1, ...), value is parameter name
                   1138:     ^reflection:dynamical[[object or class, caller if absent]]
                   1139:         returns true if the method was called from a dynamic context when passing
                   1140:         a parameter returns true if a dynamic object was passed, false if a class
                   1141:     ^reflection:delete[class or object;variable name]
                   1142:         deletes the variable with the specified name in the specified class or object
                   1143:     ^reflection:is[element name;class name][[context]]
                   1144:         analogous to the 'is' operator, allowing to determine if the element is code.
                   1145:     ^reflection:tainting[[language|tainted|optimized];string]
                   1146:         a string in which each character of the original string corresponds to a character with a transformation code
                   1147:     ^reflection:stack[ $.args(false/true) $.locals(false/true) $.limit(n) $.offset(o)]
                   1148:         the current state of the method call stack in the parser
                   1149:     ^reflection:mixin[source; $.to[target] $.name[name] $.methods(true/false) $.fields(true/false) $.overwrite(false/true)]
                   1150:         copies methods and fields from one class to another
1.269     moko     1151:     ^reflection:override[method[; $.to[target] $.name[new_name]]]
                   1152:         overrides or defines a method
1.262     moko     1153: 
1.273     moko     1154: redis
                   1155:     ^redis::open[[
                   1156:         $.host[localhost] $.port(6379)|$.unix_socket[path]
                   1157:         $.user[] $.password[] $.db(0) $.timeout(2) $.protocol(3) $.auto_reconnect(seconds)
                   1158:         $.tls[ $.ca[file] $.cert[file] $.key[file] $.verify(true) ]
                   1159:     ]]
                   1160:         connects to a redis server
                   1161:         timeout in seconds for connecting and for each command, 0 - unlimited
                   1162:         protocol(2) for servers before redis 6
                   1163:         auto_reconnect(N): after a lost connection reconnect before the next command, waiting N seconds
                   1164:         tls: the server certificate is verified only if ca is specified
                   1165:     ^redis.command_name[arguments;...]
                   1166:         any redis command, e.g. ^redis.set[key;value] ^redis.get[key] ^redis.hgetall[key]
                   1167:     ^redis.call[command;arguments;...]
                   1168:     ^redis.f-command_name[arguments;...], ^redis.f-call[command;arguments;...]
                   1169:         the strings of the reply are files (binary data)
                   1170:     arguments: string, number, bool as 1/0, file as its content; array - its elements, hash - key value pairs
                   1171:     reply: string, int, double, bool, void (nil), array, hash (map); an error reply is an exception
                   1172:     ^redis.release[]
                   1173:         closes the connection
                   1174: 
1.262     moko     1175: request
1.266     moko     1176:     https://site.name/a%20b/?name=some%20value
1.262     moko     1177:     $request:query
1.266     moko     1178:         name=some%20value
1.262     moko     1179:     $request:uri
1.266     moko     1180:         /a%20b/?name=value
                   1181:     $request:path
                   1182:         /a b/
1.262     moko     1183:     $request:document-root
                   1184:         directory relative to which paths are considered in parser, default = $env:DOCUMENT_ROOT
                   1185:     $request:argv
                   1186:         hash with command-line parameters. keys 0, 1, ... [0 - name of the processed file]
                   1187:     $request:charset
                   1188:         the source document encoding
                   1189:         used in upper/lower and match[][i]
                   1190:         WARNING: you must set $request/response:charset before using form class fields
                   1191:     $request:method
                   1192:         request method (GET|POST|PUT)
                   1193:     $request:body
                   1194:         POST-request body as text
                   1195:     $request:body-file
                   1196:         POST-request body as a file
                   1197:     $request:body-charset
                   1198:         POST-request encoding
                   1199:     $request:headers
                   1200:         hash with request headers (without HTTP_ prefix)
                   1201: 
                   1202: response
                   1203:     $response:field[value] and can read old - $response:field
                   1204:         the value can be string or hash:
                   1205:             $value[abc] field: {abc}<<part
                   1206:             $attribute[zzz] field: abc; {attribute=zzz}<<part
                   1207:         field or attribute value can be string or date
                   1208:             if date, it will be converted to "Sun, 25-Aug-2002 12:03:45 GMT"
                   1209:     $response:headers
                   1210:          accumulated fields
                   1211:     $response:body[DATA]
                   1212:         replaces the standard response
                   1213:     $response:download[DATA]
                   1214:         replaces the standard response, sets a flag causing the browser to suggest download
                   1215:     $response:status
                   1216:     ^response:clear[] forget all set response fields
                   1217:     $response:charset
                   1218:         client encoding, i.e.:
                   1219:         1) from which $form: fields will be transcoded after retrieval from browser
                   1220:         2) into which the document will be transcoded before sending to browser
                   1221:         3) into which URI language text will be transcoded
                   1222:         does not add anything to content-type; if needed, do it manually
                   1223:         WARNING: you must set $request/response:charset before using form class fields
                   1224: 
1.260     moko     1225: status
                   1226:     $status:sql
                   1227:         cache table
                   1228:             url    time
                   1229:             url    time
                   1230:             url    time
                   1231:     $status:stylesheet
                   1232:         cache table
                   1233:             file    time
                   1234:             file    time
                   1235:             file    time
                   1236:     $status:rusage hash
                   1237:         utime user time used
                   1238:         stime system time used
                   1239:         maxrss max resident set size
                   1240:         ixrss integral shared text memory size
                   1241:         idrss integral unshared data size
                   1242:         isrss integral unshared stack size
                   1243:         tv_sec
                   1244:         tv_usec
                   1245:            $s[$status:rusage]
                   1246:            ^s.tv_sec.format[%.0f].^s.tv_usec.format[%06.0f]
                   1247:     $status:memory hash
                   1248:         used
                   1249:             includes some pages that were allocated but never written
                   1250:         free
                   1251:         ever_allocated_since_compact
                   1252:             return the number of bytes allocated since the last collection
                   1253:         ever_allocated_since_start
                   1254:             return the total number of bytes [EVER(c)PAF] allocated in this process,
                   1255:             never decreases
                   1256:     $status:pid
                   1257:         process id
                   1258:     $status:tid
                   1259:         thread id
                   1260:     $status:mode
                   1261:         working mode, cgi|console|mail|httpd|apache|isapi
                   1262:     $status:log-filename
                   1263:         path to parser3.log error log
                   1264: 
1.1       paf      1265: xdoc(xnode)
1.253     moko     1266:     $xdoc.search-namespaces hash, where keys=prefixes, values=urls
                   1267: 
1.1       paf      1268:     DOM1 attributes:
1.253     moko     1269:     readonly attribute DocumentType doctype
                   1270:     readonly attribute Element documentElement
1.1       paf      1271: 
                   1272:     DOM1 methods:
1.253     moko     1273:     Element createElement(in DOMString tagName)
                   1274:     DocumentFragment createDocumentFragment()
                   1275:     Text createTextNode(in DOMString data)
                   1276:     Comment createComment(in DOMString data)
                   1277:     CDATASection createCDATASection(in DOMString data)
                   1278:     ProcessingInstruction createProcessingInstruction(in DOMString target,in DOMString data)
                   1279:     Attr createAttribute(in DOMString name)
                   1280:     EntityReference createEntityReference(in DOMString name)
                   1281:     NodeList getElementsByTagName(in DOMString tagname)
1.1       paf      1282: 
                   1283:     DOM2 some methods:
1.253     moko     1284:     ^.getElementById[elementId] = xnode
                   1285:         The DOM implementation must have information that says which attributes are of type ID.
                   1286:         Attributes with the name "ID" are not of type ID unless so defined.
                   1287:         Implementations that do not know whether attributes are of type ID or not
1.1       paf      1288:         are expected to return null.
                   1289: 
1.260     moko     1290:     String encoding and default for $.encoding equals the current output page encoding, $response:charset
1.259     moko     1291: 
1.1       paf      1292:     ::sql{...}
1.260     moko     1293:     ::create[[URI]]{<?xml?><string/>} old name 'set'
1.253     moko     1294:     ::create[[URI]][qualifiedName]
1.260     moko     1295:         URI default = disk path to requested document
                   1296:         for directories a trailing / is mandatory
1.253     moko     1297:     ::create[file] can be usable:
                   1298:         $f[^file::load[binary;http://;some HTTP options here...]]
                   1299:         $x[^xdoc::create[$f]]
1.260     moko     1300:     ::load[file.xml[;options]]
                   1301:     .transform[rules.xsl|xdoc][[params hash]] returns dom
                   1302:         the template is cached, cache is updated if the template file date changes,
                   1303:         or the date of "template_name.stamp" changes [stamp date check has priority]
1.1       paf      1304:         <xsl:output
1.253     moko     1305:         method = "xml" | "html" | "text"
1.259     moko     1306:         version = nmtoken
                   1307:         encoding = string
1.253     moko     1308:         omit-xml-declaration = "yes" | "no"
                   1309:         standalone = "yes" | "no"
1.259     moko     1310:         cdata-section-elements = qnames
1.253     moko     1311:         indent = "yes" | "no"
1.259     moko     1312:         media-type = string />
1.260     moko     1313:         parameters are passed as is, not xpath expressions
1.253     moko     1314: 
                   1315:     .string[[output options]]
1.260     moko     1316:     .save[file.xml[;output options]] with header
1.253     moko     1317:     .file[[output options]] = file
1.260     moko     1318:         output options are identical to xsl:output attributes
                   1319:             [exception: cdata-section-elements ignored]
                   1320:         returns media-type when substituting $response:body[here]
1.1       paf      1321: 
1.260     moko     1322:     if the document is referenced as:
1.253     moko     1323:         parser://method/param/to/that/method
1.260     moko     1324:         then ^MAIN:method[/param/to/that/method] is used as the document
                   1325:         [note: the parameter always comes with a leading /, even if there were no parameters]
1.144     paf      1326: 
1.253     moko     1327: xnode
1.1       paf      1328:     DOM1 attributes:
1.253     moko     1329:     $node.nodeName
                   1330:     $node.nodeValue
                   1331:         read
                   1332:         write
                   1333:     $node.nodeType = int
                   1334:         ELEMENT_NODE                   = 1
                   1335:         ATTRIBUTE_NODE                 = 2
                   1336:         TEXT_NODE                      = 3
                   1337:         CDATA_SECTION_NODE             = 4
                   1338:         ENTITY_REFERENCE_NODE          = 5
                   1339:         ENTITY_NODE                    = 6
                   1340:         PROCESSING_INSTRUCTION_NODE    = 7
                   1341:         COMMENT_NODE                   = 8
                   1342:         DOCUMENT_NODE                  = 9
                   1343:         DOCUMENT_TYPE_NODE             = 10
                   1344:         DOCUMENT_FRAGMENT_NODE         = 11
                   1345:         NOTATION_NODE                  = 12
1.1       paf      1346:             $vasyaNode.type==$xnode:ELEMENT_NODE
1.253     moko     1347:     $node.parentNode
                   1348:     $node.childNodes = array of nodes
                   1349:     $node.firstChild
                   1350:     $node.lastChild
                   1351:     $node.previousSibling
                   1352:     $node.nextSibling
                   1353:     $node.ownerDocument = xdoc
                   1354:     $node.prefix
                   1355:     $node.namespaceURI
                   1356:     $element_node.attributes = hash of xnodes
                   1357:     $element_node.tagName
                   1358:     $attribute_node.specified = boolean
                   1359:         true if the attribute received its value explicitly in the XML document,
1.259     moko     1360:         or if a value was assigned programmatically with the setValue function.
1.253     moko     1361:         false if the attribute value came from the default value declared in the document's DTD.
                   1362:     $attribute_node.name
                   1363:     $attribute_node.value
1.1       paf      1364:     $text_node/cdata_node/comment_node.substringData
1.253     moko     1365:     $pi_node.target = target of this processing instruction
1.259     moko     1366:         XML defines this as the first token following the markup
1.1       paf      1367:         that begins the processing instruction.
1.253     moko     1368:     $pi_node.data = The content of this processing instruction
1.259     moko     1369:         From the first non-whitespace character after the target
1.253     moko     1370:         to the character immediately preceding the ?>.
1.1       paf      1371:     document_node.
                   1372:         readonly attribute DocumentType doctype
1.253     moko     1373:         readonly attribute DOMImplementation implementation
1.1       paf      1374:         readonly attribute Element documentElement
                   1375:     document_type_node.
1.253     moko     1376:         readonly attribute DOMString name
1.1       paf      1377:         readonly attribute NamedNodeMap entities
                   1378:         readonly attribute NamedNodeMap notations
1.253     moko     1379:     notation_node.
                   1380:         readonly attribute DOMString publicId
                   1381:         readonly attribute DOMString systemId
                   1382: 
                   1383:     DOM1 node methods:
                   1384:     Node insertBefore(in Node newChild,in Node refChild)
                   1385:     Node replaceChild(in Node newChild,in Node oldChild)
                   1386:     Node removeChild(in Node oldChild)
                   1387:     Node appendChild(in Node newChild)
                   1388:     boolean hasChildNodes()
                   1389:     Node cloneNode(in boolean deep)
                   1390: 
                   1391:     DOM1 element methods:
                   1392:     DOMString getAttribute(in DOMString name)
                   1393:     void setAttribute(in DOMString name, in DOMString value) raises(DOMException)
                   1394:     void removeAttribute(in DOMString name) raises(DOMException)
                   1395:     Attr getAttributeNode(in DOMString name)
                   1396:     Attr setAttributeNode(in Attr newAttr) raises(DOMException)
                   1397:     Attr removeAttributeNode(in Attr oldAttr) raises(DOMException)
                   1398:     NodeList getElementsByTagName(in DOMString name)
                   1399:     void normalize()
                   1400: 
                   1401:     Introduced in DOM Level 2:
                   1402:     Node importNode(in Node importedNode, in boolean deep) raises(DOMException)
                   1403:     NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName)
                   1404:     boolean hasAttributes()
1.1       paf      1405: 
1.253     moko     1406:     XPath:
1.260     moko     1407:     ^node.select[xpath/query/expression] = array of nodes,
1.21      paf      1408:         empty array if nothing found
1.253     moko     1409:     ^node.selectSingle[xpath/query/expression] = first node if any
                   1410:     ^node.selectBool[xpath/query/expression] = bool if any or die
                   1411:     ^node.selectNumber[xpath/query/expression] = double if any or die
                   1412:     ^node.selectString[xpath/query/expression] = string if any or die
1.1       paf      1413: 
1.176     paf      1414: DATA::=string | file | hash
1.260     moko     1415:     hash of the form
1.253     moko     1416:     [
1.260     moko     1417:         $.file[filename on disk]
                   1418:         $.name[filename for user]
1.253     moko     1419:         $.mdate[date]
                   1420:     ]
                   1421: 
                   1422: MAIN
1.260     moko     1423:     this is the class automatically loaded from the configuration auto.p, a bunch of auto.p and the requested document:
                   1424:         configuration auto.p
1.253     moko     1425:             cgi:
1.260     moko     1426:                 1. either full path from environment variable CGI_PARSER_SITE_CONFIG or next to parser binary
1.1       paf      1427:             isapi: windows directory
1.253     moko     1428:             apache module:
1.43      paf      1429:                 1) ParserConfig [can be in .htaccess]
1.260     moko     1430:         auto.p goes down from DOCUMENT_ROOT/ through the directory tree to the directory of the processed file, inclusive
                   1431:     the class is assembled from all these files, subsequent ones become parents of the previous ones
                   1432:     the name of the last loaded is MAIN, previous ones have no names
                   1433: 
                   1434:     after loading MAIN class, its @main[] is called
                   1435:     the result is passed to its @postprocess[data] if($data is string) ...
                   1436:     the result is then returned to the user
1.253     moko     1437: 
1.260     moko     1438: if an error occurs and try is not specified, it can be nicely reported to the user by defining
1.253     moko     1439:     @unhandled_exception[exception;stack]
1.260     moko     1440:         $exception.type  string "type of problem"
                   1441:         $exception.file $exception.lineno $exception.colno file, line and position where the problem occurred [if not disabled at compile time]
                   1442:         $exception.source line that caused the problem
                   1443:         $exception.comment English comment
                   1444:         stack table with columns file line name,
                   1445:             in reverse order the names[name] and places[file line] of the operators/methods that caused the error.
1.253     moko     1446: 
1.260     moko     1447: when loading a file (file::load, table::load, xdoc::load) you can specify such a filename:
1.253     moko     1448:     http://domain/document[?params<<deprecated, use $.form[...]]
1.260     moko     1449:     and possibly specify options:
1.253     moko     1450:         $.method[GET|POST|HEAD]
1.260     moko     1451:         $.timeout(3)  << in seconds, default=2
1.253     moko     1452:         $.cookies[
1.260     moko     1453:             $.name[value]
1.253     moko     1454:         ]
                   1455:         $.headers[
1.260     moko     1456:             $.field[value] << value format like $response:HEADER
1.253     moko     1457:         ]
1.166     paf      1458:         $.enctype[multipart/form-data]
                   1459:         $.form[
1.253     moko     1460:             $.field1[string]
                   1461:             $.field2[^table::create{one_column_only^#0Avalue1^#0Avalue2}]
1.166     paf      1462:             $.field3[file]
                   1463:         ]
1.253     moko     1464:         $.body[string|file]
1.260     moko     1465:         default user-agent=parser3
                   1466:         by default, getting http status != 200 >> creates http.status error, can be disabled by $.any-status(1)
                   1467:         $.charset[default encoding of remote documents], if server returns content-type:charset - IT OVERRIDES
                   1468:         $.response-charset[encoding of remote documents], not overridden by content-type:charset
                   1469:         $.user[user]
                   1470:         $.password[password]
                   1471:     file::load writes additional fields
                   1472:         FIELD:value (response field names in uppercase)
                   1473:         tables << a hash of FIELD->table with a single column "value"
                   1474:             in such tables you can get repeating headers, e.g. multiple set-cookies
                   1475:             todo: make separate cookies
                   1476: 
                   1477: system error types:
                   1478:     parser.compile       ^test[}                compilation (unmatched bracket, ...)
                   1479:     parser.runtime       ^if(0).                parameters (more/less than needed, wrong types, ...)
1.253     moko     1480:     number.zerodivision  ^eval(1/0) ^eval(1%0)
                   1481:     number.format        ^eval(abc*5)
                   1482:     file.lock                                                        shared/exclusive lock error
                   1483:     file.missing         ^file:delete[delme]                         not found
                   1484:     file.access          ^table::load[.]                             no rights
                   1485:     file.read            ^file::load[...]                            error while reading file
                   1486:     file.seek                                                        seek failed
                   1487:     file.execute         ^file::cgi[...]                             incorrect cgi header/can't execute
                   1488:     image.format         ^image::measure[index.html]                 not gif/jpg
                   1489:     sql.connect          ^connect[mysql://baduser:pass@host/db]{}    not found/timeout
                   1490:     sql.execute          ^void:sql{select bad}                       syntax error
1.57      paf      1491:     sql.duplicate
                   1492:     sql.access
                   1493:     sql.missing
1.253     moko     1494:     xml                  ^xdoc::create{<forgot?>}                    any error in xml/xslt libs
                   1495:     smtp.connect                                                     not found/timeout
                   1496:     smtp.execute                                                     communication error
1.259     moko     1497:     email.format         hren tam@null.ru                            wrong email format (bad chars/empty)
1.253     moko     1498:     email.send           $MAIL.sendmail[/shit]                       sendmail not executable
                   1499:     http.host            ^file::load[http://notfound/there]          host not found
1.259     moko     1500:     http.connect         ^file::load[http://not_accepting/there]     host found, but does not accept connections
                   1501:     http.timeout         ^file::load[http://host/doc]                load operation failed to complete in # seconds
1.253     moko     1502:     http.response        ^file::load[http://ok/there]                host found, connection accepted, bad answer
                   1503:     http.status          ^file::load[http://ok/there]                host found, connection accepted, status!=200
                   1504:     date.range           ^date::create(10000;1;1)                    date out of valid range
1.273     moko     1505:     amqp                 ^amqp::create[$.port(1)]                    connection failed/error from the broker
                   1506:     redis                ^redis::open[$.port(1)]                     connection failed/error reply
1.213     misha    1507: 
1.260     moko     1508: if the method description explicitly contains the local variable result (there is also an implicit variable),
                   1509:     then the code for outputting whitespace literals does not get into the final bytecode
1.261     moko     1510: 
1.275   ! moko     1511: $Id: operators.txt,v 1.274 2026/10/26 22:52:46 moko Exp $

E-mail: