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