• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/README.md

  1 ## ABOUT
  2 
  3 An ucode template consists of arbitrary plain text which is outputted as-is
  4 while control flow or expression logic is embedded in blocks that may appear
  5 anywhere throughout the template.
  6 
  7 
  8 ## BLOCKS
  9 
 10 There are three kinds of blocks; expression blocks, statement blocks and
 11 comment blocks. The former two embed code logic using a JavaScript-like syntax
 12 while the latter comment block type is simply discarded during processing.
 13 
 14 
 15 ### 1. STATEMENT BLOCKS
 16 
 17 Statement blocks are enclosed in an opening `{%` and a closing `%}` tag and
 18 may contain any number of script code statements, even entire programs.
 19 
 20 It is allowed to omit the closing `%}` of a statement block to parse the
 21 entire remaining source text after the opening tag as ucode script.
 22 
 23 By default, statement blocks produce no output and the entire block is
 24 reduced to an empty string during template evaluation but contained script
 25 code might invoke functions such as `print()` to explicitly output contents.
 26 
 27 For example the following template would result in `The epoch is odd` or
 28 `The epoch is even`, depending on the current epoch value:
 29 
 30 `The epoch is {% if (time() % 2): %}odd{% else %}even{% endif %}!`
 31 
 32 
 33 ### 2. EXPRESSION BLOCKS
 34 
 35 Expression blocks are enclosed in an opening `{{` and a closing `}}` tag and
 36 may only contain a single expression statement (multiple expressions may be
 37 chained with comma). The implicit result of the rightmost evaluated expression
 38 is used as output when processing the block.
 39 
 40 For example the template `Hello world, {{ getenv("USER") }}!` would result in
 41 the output "Hello world, user!" where `user` would correspond to the name of
 42 the current user executing the ucode interpreter.
 43 
 44 
 45 ### 3. COMMENT BLOCKS
 46 
 47 Comment blocks, which are denoted with an opening `{#` and a closing `#}` tag
 48 may contain arbitrary text except the closing `#}` tag itself. Comments blocks
 49 are completely stripped during processing and are replaced with an empty string.
 50 
 51 The following example template would result in the output "Hello world":
 52 
 53 `Hello {# mad #}word`
 54 
 55 
 56 ### WHITESPACE
 57 
 58 Each block start tag may be suffixed with a dash to strip any whitespace
 59 before the block and likewise any block end tag may be prefixed with a dash
 60 to strip any whitespace following the block.
 61 
 62 Without using whitespace stripping, the following example:
 63 
 64 ```
 65 This is a first line
 66 {% for (x in [1, 2, 3]): %}
 67 This is item {{ x }}.
 68 {% endfor %}
 69 This is the last line
 70 ```
 71 
 72 Would result in the following output:
 73 
 74 ```
 75 This is a first line
 76 
 77 This is item 1.
 78 This is item 2.
 79 This is item 3.
 80 
 81 This is the last line
 82 ```
 83 
 84 By adding a trailing dash to apply whitespace stripping after the block, the
 85 empty lines can be eliminated:
 86 
 87 ```
 88 This is a first line
 89 {% for (x in [1, 2, 3]): -%}
 90 This is item {{ x }}.
 91 {% endfor -%}
 92 This is the last line
 93 ```
 94 
 95 Output:
 96 
 97 ```
 98 This is a first line
 99 This is item 1.
100 This is item 2.
101 This is item 3.
102 This is the last line
103 ```
104 
105 By applying whitespace stripping before the block, all lines can be joined
106 into a single output line:
107 
108 ```
109 This is a first line
110 {%- for (x in [1, 2, 3]): -%}
111 This is item {{ x }}.
112 {%- endfor -%}
113 This is the last line
114 ```
115 
116 Output:
117 
118 ```
119 This is a first lineThis is item 1.This is item 2.This is item 3.This is the last line
120 ```
121 
122 ## SCRIPT LANGUAGE
123 
124 The ucode script language used within statement and expression blocks uses
125 untyped variables and employs a simplified JavaScript like syntax.
126 
127 Ucode script implements function scoping and differentiates between local and
128 global variables. Each function has its own private scope while executing and
129 local variables declared inside a function are not accessible in the outer
130 calling scope.
131 
132 ### 1. Data types
133 
134 Ucode supports seven different basic types as well as two additional special
135 types; function values and ressource values. The supported types are:
136 
137  - Boolean values (`true` or `false`)
138  - Integer values (`-9223372036854775808` to `+9223372036854775807`)
139  - Double values (`-1.7e308` to `+1.7e308`)
140  - String values (e.g. `'Hello world!'` or `"Sunshine \u2600!"`)
141  - Array values (e.g. `[1, false, "foo"]`)
142  - Object values (e.g. `{ foo: true, "bar": 123 }`)
143  - Null value (`null`)
144 
145 Ucode utilizes reference counting to manage memory used for variables and values
146 and frees data automatically as soon as values go out of scope.
147 
148 Numeric values are either stored as signed 64bit integers or as IEEE 756 double
149 value. Conversion between integer and double values can happen implicitly, e.g.
150 through numeric operations, or explicitely, e.g. by invoking functions such as
151 `int()`.
152 
153 ### 2. Variables
154 
155 Variable names must start with a letter or an underscore and may only contain
156 the characters `A`..`Z`, `a`..`z`, `0`..`9` or `_`. By prefixing a variable
157 name with the keyword `let`, it is declared in the local block scope only
158 and not visible outside anymore.
159 
160 Variables may also be declared using the `const` keyword. Such variables follow
161 the same scoping rules as `let` declared ones but they cannot be modified after
162 they have been declared. Any attempt to do so will result in a syntax error
163 during compilation.
164 
165 ```javascript
166 {%
167 
168   a = 1;  // global variable assignment
169 
170   function test() {
171     let b = 2;  // declare `b` as local variable
172     a = 2;        // overwrite global a
173   }
174 
175   test();
176 
177   print(a, "\n");  // outputs "2"
178   print(b, "\n");  // outputs nothing
179 
180   const c = 3;
181   print(c, "\n");  // outputs "3"
182 
183   c = 4;           // raises syntax error
184   c++;             // raises syntax error
185 
186   const d;         // raises syntax error, const variables must
187                    // be initialized at declaration time
188 
189 %}
190 ```
191 
192 ### 3. Control statements
193 
194 Similar to JavaScript, ucode supports `if`, `for` and `while` statements to
195 control execution flow.
196 
197 #### 3.1. Conditional statement
198 
199 If/else blocks can be used execute statements depending on a condition.
200 
201 ```javascript
202 {%
203 
204   user = getenv("USER");
205 
206   if (user == "alice") {
207       print("Hello Alice!\n");
208   }
209   else if (user == "bob") {
210       print("Hello Bob!\n");
211   }
212   else {
213       print("Hello guest!\n");
214   }
215 
216 %}
217 ```
218 
219 If only a single statement is wrapped by an if or else branch, the enclosing
220 curly braces may be omitted:
221 
222 ```javascript
223 {%
224 
225   if (rand() == 3)
226       print("This is quite unlikely\n");
227 
228 %}
229 ```
230 
231 #### 3.2. Loop statements
232 
233 Ucode script supports three different flavors of loop control statements; a
234 `while` loop that executes enclosed statements as long as the loop condition is
235 fulfilled, a `for in` loop that iterates keys of objects or items of arrays and
236 a counting `for` loop that is a variation of the `while` loop.
237 
238 ```javascript
239 {%
240 
241   i = 0;
242   arr = [1, 2, 3];
243   obj = { Alice: 32, Bob: 54 };
244 
245   // execute as long as condition is true
246   while (i < length(arr)) {
247       print(arr[i], "\n");
248       i++;
249   }
250 
251   // execute for each item in arr
252   for (n in arr) {
253       print(n, "\n");
254   }
255 
256   // execute for each key in obj
257   for (person in obj) {
258       print(person, " is ", obj[person], " years old.\n");
259   }
260 
261   // execute initialization statement (j = 0) once
262   // execute as long as condition (j < length(arr)) is true
263   // execute step statement (j++) after each iteration
264   for (j = 0; j < length(arr); j++) {
265       print(arr[j], "\n");
266   }
267 
268 %}
269 ```
270 
271 #### 3.3. Alternative syntax
272 
273 Since conditional statements and loops are often used for template formatting
274 purposes, e.g. to repeat a specific markup for each item of a list, ucode
275 supports an alternative syntax that does not require curly braces to group
276 statements but that uses explicit end keywords to denote the end of the control
277 statement body for better readability instead.
278 
279 The following two examples first illustrate the normal syntax, followed by the
280 alternative syntax that is more suitable for statement blocks:
281 
282 ```
283 Printing a list:
284 {% for (n in [1, 2, 3]) { -%}
285   - Item #{{ n }}
286 {% } %}
287 ```
288 
289 The alternative syntax replaces the opening curly brace (`{`) with a colon
290 (`:`) and the closing curly brace (`}`) with an explicit `endfor` keyword:
291 
292 ```
293 Printing a list:
294 {% for (n in [1, 2, 3]): -%}
295   - Item #{{ n }}
296 {% endfor %}
297 ```
298 
299 For each control statement type, a corresponding alternative end keyword is defined:
300 
301   - `if (...): ... endif`
302   - `for (...): ... endfor`
303   - `while (...): ... endwhile`
304 
305 
306 ### 4. Functions
307 
308 Ucode scripts may define functions to group repeating operations into reusable
309 operations. Functions can be both declared with a name, in which case they're
310 automatically registered in the current scope, or anonymously which allows
311 assigning the resulting value to a variable, e.g. to build arrays or objects of
312 functions:
313 
314 ```javascript
315 {%
316 
317   function duplicate(n) {
318        return n * 2;
319   }
320 
321   let utilities = {
322       concat: function(a, b) {
323           return "" + a + b;
324       },
325       greeting: function() {
326           return "Hello, " + getenv("USER") + "!";
327       }
328   };
329 
330 -%}
331 
332 The duplicate of 2 is {{ duplicate(2) }}.
333 The concatenation of 'abc' and 123 is {{ utilities.concat("abc", 123) }}.
334 Your personal greeting is: {{ utilities.greeting() }}.
335 ```
336 
337 #### 4.1. Alternative syntax
338 
339 Function declarations support the same kind of alternative syntax as defined
340 for control statements (3.3.)
341 
342 The alternative syntax replaces the opening curly brace (`{`) with a colon
343 (`:`) and the closing curly brace (`}`) with an explicit `endfunction`
344 keyword:
345 
346 ```
347 {% function printgreeting(name): -%}
348   Hallo {{ name }}, nice to meet you.
349 {% endfunction -%}
350 
351 <h1>{{ printgreeting("Alice") }}</h1>
352 ```
353 
354 
355 ### 5. Operators
356 
357 Similar to JavaScript and C, ucode scripts support a range of different
358 operators to manipulate values and variables.
359 
360 #### 5.1. Arithmetic operations
361 
362 The operators `+`, `-`, `*`, `/`, `%`, `++` and `--` allow to perform
363 additions, substractions, multiplications, divisions, modulo, increment or
364 decrement operations respectively where the result depends on the type of
365 involved values.
366 
367 The `++` and `--` operators are unary, means that they only apply to one
368 operand. The `+` and `-` operators may be used in unary context to either
369 convert a given value to a numeric value or to negate a given value.
370 
371 If either operand of the `+` operator is a string, the other one is converted
372 to a string value as well and a concatenated string is returned.
373 
374 All other arithmetic operators coerce their operands into numeric values.
375 Fractional values are converted to doubles, other numeric values to integers.
376 
377 If either operand is a double, the other one is converted to a double value as
378 well and a double result is returned.
379 
380 Divisions by zero result in the special double value `Infinity`. If an operand
381 cannot be converted to a numeric value, the result of the operation is the
382 special double value `NaN`.
383 
384 ```javascript
385 {%
386   a = 2;
387   b = 5.2;
388   s1 = "125";
389   s2 = "Hello world";
390 
391   print(+s1);      // 125
392   print(+s2);      // NaN
393   print(-s1);      // -125
394   print(-s2);      // NaN
395   print(-a);       // -2
396 
397   print(a++);      // 2 (Return value of a, then increment by 1)
398   print(++a);      // 4 (Increment by 1, then return value of a)
399 
400   print(b--);      // 5.2 (Return value of b, then decrement by 1)
401   print(--b);      // 3.2 (Decrement by 1, then return value of b)
402 
403   print(4 + 8);    // 12
404   print(7 - 4);    // 3
405   print(3 * 3);    // 9
406 
407   print(10 / 4);   // 2 (Integer division)
408   print(10 / 4.0); // 2.5 (Double division)
409   print(10 / 0);   // Infinity
410 
411   print(10 % 7);   // 3
412   print(10 % 7.0); // NaN (Modulo is undefined for non-integers)
413 %}
414 ```
415 
416 #### 5.2. Bitwise operations
417 
418 The operators `&`, `|`, `^`, `<<`, `>>` and `~` allow to perform bitwise and,
419 or, xor, left shift, right shift and complement operations respectively.
420 
421 The `~` operator is unary, means that is only applies to one operand.
422 
423 ```javascript
424 {%
425   print(0 & 0, 0 & 1, 1 & 1);  // 001
426   print(0 | 0, 0 | 1, 1 | 1);  // 011
427   print(0 ^ 0, 0 ^ 1, 1 ^ 1);  // 010
428   print(10 << 2);              // 40
429   print(10 >> 2);              // 2
430   print(~15);                  // -16 (0xFFFFFFFFFFFFFFF0)
431 %}
432 ```
433 
434 An important property of bitwise operators is that they're coercing their
435 operand values to whole integers:
436 
437 ```javascript
438 {%
439   print(12.34 >> 0);   // 12
440   print(~(~12.34));    // 12
441 %}
442 ```
443 
444 #### 5.3. Relational operations
445 
446 The operators `==`, `!=`, `<`, `<=`, `>` and `>=` test whether their operands
447 are equal, inequal, lower than, lower than/equal to, higher than or higher
448 than/equal to each other respectively.
449 
450 If both operands are strings, their respective byte values are compared, if
451 both are objects or arrays, their underlying memory addresses are compared.
452 
453 In all other cases, both operands are coerced into numeric values and the
454 resulting values are compared with each other.
455 
456 This means that comparing values of different types will coerce them both to
457 numbers.
458 
459 The result of the relational operation is a boolean indicating truishness.
460 
461 ```javascript
462 {%
463   print(123 == 123);     // true
464   print(123 == "123");   // true!
465   print(123 < 456);      // true
466   print(123 > 456);      // false
467   print(123 != 456);     // true
468   print(123 != "123");   // false!
469   print({} == {});       // false (two different anonymous objects)
470   a = {}; print(a == a); // true (same object)
471 %}
472 ```
473 
474 #### 5.4. Logical operations
475 
476 The operators `&&`, `||` and `!` test whether their operands are all true,
477 partially true or false respectively.
478 
479 In the case of `&&` the rightmost value is returned while `||` results in the
480 first truish value.
481 
482 The unary `!` operator will result in `true` if the operand is not treish,
483 otherwise it will result in `false`.
484 
485 Operands are evaluated from left to right while testing truishness, which means
486 that expressions with side effects, such as function calls, are only executed
487 if the preceeding condition was satisifed.
488 
489 ```javascript
490 {%
491   print(1 && 2 && 3);    // 3
492   print(1 || 2 || 3);    // 1
493   print(2 > 1 && 3 < 4); // true
494   print(!false);         // true
495   print(!true);          // false
496 
497   res = test1() && test2();  // test2() is only called if test1() returns true
498 %}
499 ```
500 
501 #### 5.5. Assignment operations
502 
503 In addition to the basic assignment operator `=`, most other operators have a
504 corresponding shortcut assignment operator which reads the specified variable,
505 applies the operation and operand to it, and writes it back.
506 
507 The result of assignment expressions is the assigned value.
508 
509 ```javascript
510 {%
511   a = 1;     // assign 1 to variable a
512   a += 2;    // a = a + 2;
513   a -= 3;    // a = a - 3;
514   a *= 4;    // a = a * 4;
515   a /= 5;    // a = a / 5;
516   a %= 6;    // a = a % 6;
517   a &= 7;    // a = a & 7;
518   a |= 8;    // a = a | 8;
519   a ^= 9;    // a = a ^ 9;
520   a <<= 10;  // a = a << 10;
521   a >>= 11;  // a = a >> 11;
522 
523   print(a = 2);  // 2
524 %}
525 ```
526 
527 #### 5.6. Miscellaneous operators
528 
529 Besides the operators described so far, ucode script also supports a `delete`
530 operator which removes a property from an object value.
531 
532 ```javascript
533 {%
534   a = { test: true };
535 
536   delete a.test;         // true
537   delete a.notexisting;  // false
538 
539   print(a);              // { }
540 %}
541 ```
542 
543 ### 6. Functions
544 
545 Ucode scripts may call a number of builtin functions to manipulate values or
546 to output information.
547 
548 #### 6.1. `abs(x)`
549 
550 Returns the absolute value of the given operand. Results in `NaN` if operand is
551 not convertible to number.
552 
553 ```javascript
554 abs(1);        // 1
555 abs(-2);       // 2
556 abs(-3.5);     // 3.5
557 abs("0x123");  // 291
558 abs("-0x123"); // NaN
559 abs([]);       // NaN
560 ```
561 
562 #### 6.2. `atan2(x, y)`
563 
564 Calculates the principal value of the arc tangent of x/y, using the signs of
565 the two arguments to determine the quadrant of the result.
566 
567 #### 6.3. `chr(n1, ...)`
568 
569 Converts each given numeric value to a byte and return the resulting string.
570 Invalid numeric values or values < 0 result in `\0` bytes, values larger than
571 255 are truncated to 255.
572 
573 ```javascript
574 chr(65, 98, 99);  // "Abc"
575 chr(-1, 300);     // string consisting of an `0x0` and a `0xff` byte
576 ```
577 
578 #### 6.4. `cos(x)`
579 
580 Return the cosine of x, where x is given in radians.
581 
582 #### 6.5. `die(msg)`
583 
584 Raise an exception with the given message and abort execution.
585 
586 #### 6.6. `exists(obj, key)`
587 
588 Return `true` if the given key is present within the object passed as first
589 argument, otherwise `false`.
590 
591 #### 6.7. `exit(n)`
592 
593 Terminate the interpreter with the given exit code.
594 
595 #### 6.8. `exp(n)`
596 
597 Return the value of e (the base of natural logarithms) raised to the power
598 of n.
599 
600 #### 6.9. `filter(arr, fn)`
601 
602 Filter the array passed as first argument by invoking the function specified
603 in the second argument for each array item.
604 
605 If the invoked function returns a truish result, the item is retained,
606 otherwise it is dropped. The filter function is invoked with three arguments:
607 
608  1. The array value
609  2. The current index
610  3. The array being filtered
611 
612 Returns the filtered array.
613 
614 ```javascript
615 // filter out any empty string:
616 a = filter(["foo", "", "bar", "", "baz"], length)
617 // a = ["foo", "bar", "baz"]
618 
619 // filter out any non-number type:
620 a = filter(["foo", 1, true, null, 2.2], function(v) {
621     return (type(v) == "int" || type(v) == "double");
622 });
623 // a = [1, 2.2]
624 ```
625 
626 #### 6.10. `getenv(name)`
627 
628 Return the value of the given environment variable.
629 
630 #### 6.11. `hex(x)`
631 
632 Convert the given hexadecimal string into a number.
633 
634 #### 6.12. `index(arr_or_str, needle)`
635 
636 Find the given value passed as second argument within the array or string
637 specified in the first argument.
638 
639 Returns the first matching array index or first matching string offset or `-1`
640 if the value was not found.
641 
642 Returns `null` if the first argument was neither an array, nor a string.
643 
644 #### 6.13. `int(x)`
645 
646 Convert the given value to an integer. Returns `NaN` if the value is not
647 convertible.
648 
649 #### 6.14. `join(sep, arr)`
650 
651 Join the array passed as 2nd argument into a string, using the separator passed
652 in the first argument as glue. Returns `null` if the second argument is not an
653 array.
654 
655 #### 6.15. `keys(obj)`
656 
657 Return an array of all key names present in the passed object. Returns `null`
658 if the given argument is no object.
659 
660 #### 6.16. `lc(s)`
661 
662 Convert the given string to lowercase and return the resulting string.
663 Returns `null` if the given argument could not be converted to a string.
664 
665 #### 6.17. `length(x)`
666 
667 Return the length of the given object, array or string. Returns `null` if
668 the given argument is neither an object, array, nor a string.
669 
670 For objects, the length is defined as the number of keys within the object,
671 for arrays the length specifies the amount of contained items and for strings
672 it represents the number of contained bytes.
673 
674 ```javascript
675 length("test")                             // 4
676 length([true, false, null, 123, "test"])   // 5
677 length({foo: true, bar: 123, baz: "test"}) // 3
678 length({})                                 // 0
679 length(true)                               // null
680 length(10.0)                               // null
681 ```
682 
683 #### 6.18. `log(x)`
684 
685 Return the natural logarithm of x.
686 
687 #### 6.19. `ltrim(s, c)`
688 
689 Trim any of the specified characters in `c` from the start of `str`.
690 If the second argument is omitted, trims the characters, ` ` (space), `\t`,
691 `\r` and `\n`.
692 
693 ```javascript
694 ltrim("  foo  \n")     // "foo  \n"
695 ltrim("--bar--", "-")  // "bar--"
696 ```
697 
698 #### 6.20. `map(arr, fn)`
699 
700 Transform the array passed as first argument by invoking the function specified
701 in the second argument for each array item.
702 
703 The result of the invoked function is put into the resulting array.
704 The map function is invoked with three arguments:
705 
706  1. The array value
707  2. The current index
708  3. The array being filtered
709 
710 Returns the transformed array.
711 
712 ```javascript
713 // turn into array of string lengths:
714 a = map(["Apple", "Banana", "Bean"], length)
715 // a = [5, 6, 4]
716 
717 // map to type names:
718 a = map(["foo", 1, true, null, 2.2], type);
719 // a = ["string", "int", "bool", null, "double"]
720 ```
721 
722 #### 6.21. `ord(s, ...)`
723 
724 Without further arguments, this function returns the byte value of the first
725 character in the given string.
726 
727 If one or more index arguments are supplied, an array containing the byte
728 values at each given index is returned. If an invalid index is supplied, the
729 corresponding array entry will be `null`. Negative index entries are counted
730 towards the end of the string, e.g. `-2` will return the value of the second
731 last character.
732 
733 ```javascript
734 ord("Abc");                 // 65
735 ord("Abc", 0);              // [ 65 ]
736 ord("Abc", 1, -1);          // [ 98, 99 ]
737 ord("Abc", 2, 1, 0);        // [ 99, 98, 65 ]
738 ord("Abc", 10, -10, "nan"); // [ null, null, null ]
739 ```
740 
741 #### 6.22. `pop(arr)`
742 
743 Pops the last item from the given array and returns it. Returns `null` if the
744 array was empty or if a non-array argument was passed.
745 
746 #### 6.23. `print(x, ...)`
747 
748 Print any of the given values to stdout. Arrays and objects are converted to
749 their JSON representation.
750 
751 Returns the amount of bytes printed.
752 
753 #### 6.24. `push(arr, v1, ...)`
754 
755 Push the given argument(s) to the given array. Returns the last pushed value.
756 
757 #### 6.25. `rand()`
758 
759 Returns a random number. If `srand()` has not been called already, it is
760 automatically invoked passing the current time as seed.
761 
762 #### 6.26. `reverse(arr_or_str)`
763 
764 If an array is passed, returns the array in reverse order. If a string is
765 passed, returns the string with the sequence of the characters reversed.
766 
767 Returns `null` if neither an array nor a string were passed.
768 
769 #### 6.27. `rindex(arr_or_str, needle)`
770 
771 Find the given value passed as second argument within the array or string
772 specified in the first argument.
773 
774 Returns the last matching array index or last matching string offset or `-1`
775 if the value was not found.
776 
777 Returns `null` if the first argument was neither an array, nor a string.
778 
779 #### 6.28. `rtrim(str, c)`
780 
781 Trim any of the specified characters in `c` from the end of `str`.
782 If the second argument is omitted, trims the characters, ` ` (space), `\t`,
783 `\r` and `\n`.
784 
785 ```javascript
786 rtrim("  foo  \n")     // "  foo"
787 rtrim("--bar--", "-")  // "--bar"
788 ```
789 
790 #### 6.29. `shift(arr)`
791 
792 Pops the first item from the given array and returns it. Returns `null` if the
793 array was empty or if a non-array argument was passed.
794 
795 #### 6.30. `sin(x)`
796 
797 Return the sine of x, where x is given in radians.
798 
799 #### 6.31. `sort(arr, fn)`
800 
801 Sort the given array according to the given sort function. If no sort
802 function is provided, a default ascending sort order is applied.
803 
804 ```javascript
805 sort([8, 1, 5, 9]) // [1, 5, 8, 9]
806 sort(["Bean", "Orange", "Apple"], function(a, b) {
807     return length(a) < length(b);
808 }) // ["Bean", "Apple", "Orange"]
809 ```
810 
811 #### 6.32. `splice(arr, off, len, ...)`
812 
813 Removes the elements designated by `off` and `len` from  the given an array,
814 and replaces them with the additional arguments passed, if any. Returns the
815 last element removed, or `null` if no elements are removed. The array grows or shrinks as necessary.
816 
817 If `off` is negative then it starts that far from the end of the array. If
818 `len` is omitted, removes everything from `off` onward. If `len` is negative,
819 removes the elements from `off` onward except for `-len` elements at the end of
820 the array. If both `off` and `len` are omitted, removes everything.
821 
822 #### 6.33. `split(str, sep)`
823 
824 Split the given string using the separator passed as second argument and return
825 an array containing the resulting pieces.
826 
827 The separator may either be a plain string or a regular expression.
828 
829 ```javascript
830 split("foo,bar,baz", ",")     // ["foo", "bar", "baz"]
831 split("foobar", "")           // ["f", "o", "o", "b", "a", "r"]
832 split("foo,bar,baz", /[ao]/)  // ["f", "", ",b", "r,b", "z"]
833 ```
834 
835 #### 6.34. `sqrt(x)`
836 
837 Return the nonnegative square root of x.
838 
839 #### 6.35. `srand(n)`
840 
841 Seed the PRNG using the given number.
842 
843 #### 6.36. `substr(str, off, len)`
844 
845 Extracts a substring out of `str` and returns it. First character is at offset
846 zero. If `off` is negative, starts that far back from the end of the string.
847 If `len` is omitted, returns everything through the end of the string. If `len`
848 is negative, leaves that many characters off the end of the string.
849 
850 ```javascript
851 s = "The black cat climbed the green tree";
852 
853 substr(s, 4, 5);      // black
854 substr(s, 4, -11);    // black cat climbed the
855 substr(s, 14);        // climbed the green tree
856 substr(s, -4);        // tree
857 substr(s, -4, 2);     // tr
858 ```
859 
860 #### 6.37. `time()`
861 
862 Returns the current UNIX epoch.
863 
864 ```javascript
865 time();     // 1598043054
866 ```
867 
868 #### 6.38. `trim()`
869 
870 Trim any of the specified characters in `c` from the start and end of `str`.
871 If the second argument is omitted, trims the characters, ` ` (space), `\t`,
872 `\r` and `\n`.
873 
874 ```javascript
875 ltrim("  foo  \n")     // "foo"
876 ltrim("--bar--", "-")  // "bar"
877 ```
878 
879 #### 6.39. `type(x)`
880 
881 Returns the type of the given value as string which might be one of
882 `"function"`, `"object"`, `"array"`, `"double"`, `"int"` or `"bool"`.
883 
884 Returns `null` when no value or `null` is passed.
885 
886 #### 6.40. `uchr(n1, ...)`
887 
888 Converts each given numeric value to an utf8 escape sequence and returns the
889 resulting string. Invalid numeric values or values outside the range `0` ..
890 `0x10FFFF` are represented by the unicode replacement character `0xFFFD`.
891 
892 ```javascript
893 uchr(0x2600, 0x26C6, 0x2601);  // "☀⛆☁"
894 uchr(-1, 0x20ffff, "foo");     // "���"
895 ```
896 
897 #### 6.41. `uc(str)`
898 
899 Converts the given string to uppercase and return the resulting string.
900 Returns `null` if the given argument could not be converted to a string.
901 
902 #### 6.42. `unshift(arr, v1, ...)`
903 
904 Add the given values to the beginning of the array passed as first argument.
905 Returns the last value added to the array.
906 
907 #### 6.43. `values(obj)`
908 
909 Returns an array containing all values of the given object. Returns `null` if
910 no object was passed.
911 
912 ```javascript
913 values({ foo: true, bar: false });   // [true, false]
914 ```
915 
916 #### 6.44. `printf(fmt, ...)`
917 
918 Formats the given arguments according to the given format string and outputs the
919 result to stdout.
920 
921 Ucode supports a restricted subset of the formats allowed by the underlying
922 libc's `printf()` implementation, namely it allows the `d`, `i`, `o`, `u`, `x`,
923 `X`, `e`, `E`, `f`, `F`, `g`, `G`, `c` and `s` conversions.
924 
925 Additionally, an ucode specific `J` format is implemented, which causes the
926 corresponding value to be formatted as JSON string. By prefixing the `J` format
927 letter with a precision specifier, the resulting JSON output will be pretty
928 printed. A precision of `0` will use tabs for indentation, any other positive
929 precision will use that many spaces for indentation while a negative or omitted
930 precision specifier will turn off pretty printing.
931 
932 Other format specifiers such as `n` or `z` are not accepted and returned
933 verbatim. Format specifiers including `*` and `$` directives are rejected as
934 well.
935 
936 ```javascript
937 {%
938   printf("Hello %s\n", "world");  // Hello world
939   printf("%08x\n", 123);          // 0000007b
940   printf("%c%c%c\n", 65, 98, 99); // Abc
941   printf("%g\n", 10 / 3.0);       // 3.33333
942   printf("%J", [1,2,3]);          // [ 1, 2, 3 ]
943 
944   printf("%.J", [1,2,3]);
945   // [
946   //         1,
947   //         2,
948   //         3
949   // ]
950 
951   printf("%.2J", [1,2,3]);
952   // [
953   //   1,
954   //   2,
955   //   3
956   // ]
957 %}
958 ```
959 
960 #### 6.45. `sprintf(fmt, ...)`
961 
962 Formats the given arguments according to the given format string and returns the
963 resulting string.
964 
965 See `printf()` for details.
966 
967 #### 6.46. `match(str, /pattern/)`
968 
969 Match the given string against the regular expression pattern specified as
970 second argument.
971 
972 If the passed regular expression uses the `g` flag, the return value will be an
973 array of arrays describing all found occurences within the string.
974 
975 Without the `g` modifier, an array describing the first match is returned.
976 Returns `null` if the pattern was not found within the given string.
977 
978 ```javascript
979 match("foobarbaz", /b.(.)/)   // ["bar", "r"]
980 match("foobarbaz", /b.(.)/g)  // [["bar", "r"], ["baz", "z"]]
981 ```
982 
983 #### 6.47. `replace(str, /pattern/, replace)`
984 
985 Replace occurences of the specified pattern in the string passed as first
986 argument. The pattern value may be either a regular expression or a plain
987 string. The replace value may be a function which is invoked for each found
988 pattern or any other value which is converted into a plain string and used as
989 replacement.
990 
991 If the pattern is a regular expression and not using the `g` flag, then only the
992 first occurence in the string is replaced, if the `g` flag is used or if the
993 pattern is not a regular expression, all occurrences are replaced.
994 
995 If the replace value is a callback function, it is invoked with the found
996 substring as first and any capture group values as subsequent parameters.
997 
998 If the replace value is a string, the following special substrings are
999 substituted before it is inserted into the result:
1000 
1001  - `$$` - replaced by a literal `$`
1002  - ``$` `` - replaced by the text before the match
1003  - `$'` - replaced by the text after the match
1004  - `$&` - replaced by the matched substring
1005  - `$1`..`$9` - replaced by the value of the corresponding capture group, if the capture group is not defined, it is not substituted
1006 
1007 ```javascript
1008 replace("barfoobaz", /(f)(o+)/g, "[$$|$`|$&|$'|$1|$2|$3]")  // bar[$|bar|foo|baz|f|oo|$3]baz
1009 replace("barfoobaz", /(f)(o+)/g, uc)                        // barFOObaz
1010 replace("barfoobaz", "a", "X")                              // bXrfoobXz
1011 replace("barfoobaz", /(.)(.)(.)/g, function(m, c1, c2, c3) {
1012     return c3 + c2 + c1;
1013 })                                                          // raboofzab
1014 ```
1015 
1016 #### 6.48. `json(str)`
1017 
1018 Parse the given string as JSON and return the resulting value. Throws an
1019 exception on parse errors, trailing garbage or premature EOF.
1020 
1021 ```javascript
1022 json('{"a":true, "b":123}')   // { "a": true, "b": 123 }
1023 json('[1,2,')                 // Throws exception
1024 ```
1025 
1026 #### 6.49. `include(path[, scope])`
1027 
1028 Evaluate and include the file at the given path and optionally override the
1029 execution scope with the given scope object.
1030 
1031 By default, the file is executed within the same scope as the calling
1032 `include()` but by passing an object as second argument, it is possible to
1033 extend the scope available to the included file. This is useful to supply
1034 additional properties as global variables to the included code.
1035 
1036 To sandbox included code, that is giving it only access to explicitely
1037 provided properties, the `proto()` function can be used to create a scope
1038 object with an empty prototype. See the examples below for details.
1039 
1040 If the given path argument is not absolute, it is interpreted relative to the
1041 directory of the current template file, that is the file that is invoking the
1042 `include()` function.
1043 
1044 If the ucode interpreter executes program code from stdin, the given path is
1045 interpreted relative to the current working directory of the process.
1046 
1047 ```javascript
1048 // Load and execute "foo.uc" immediately
1049 include("./foo.uc")
1050 
1051 // Execute the "supplemental.ucode" in an extended scope and make the "foo" and
1052 // "bar" properties available as global variables
1053 include("./supplemental.uc", {
1054   foo: true,
1055   bar: 123
1056 })
1057 
1058 // Execute the "untrusted.ucode" in a sandboxed scope and make the "foo" and
1059 // "bar" variables as well as the "print" function available to it. By assigning
1060 // an empty prototype object to the scope, included code has no access to
1061 // other global values anymore
1062 include("./untrusted.uc", proto({
1063   foo: true,
1064   bar: 123,
1065   print: print
1066 }, {}))
1067 ```
1068 
1069 #### 6.50. `warn(x, ...)`
1070 
1071 Print any of the given values to stderr. Arrays and objects are converted to
1072 their JSON representation.
1073 
1074 Returns the amount of bytes printed.
1075 
1076 #### 6.51. `system(command, timeout)`
1077 
1078 Executes the given command, waits for completion and returns the resulting
1079 exit code.
1080 
1081 The command argument may be either a string, in which case it is passed to
1082 `/bin/sh -c`, or an array, which is directly converted into an `execv()`
1083 argument vector.
1084 
1085 If the program terminated normally, a positive integer holding the programs
1086 `exit()` code is returned. If the program was terminated by an uncatched
1087 signal, a negative signal number is returned, e.g. `-9` when the program was
1088 terminated by `SIGKILL`.
1089 
1090 If the optional timeout argument is specified, the program is terminated by
1091 `SIGKILL` after that many milliseconds when it didn't complete within the timeout.
1092 
1093 Omitting the timeout argument, or passing `0` disables the command timeout.
1094 
1095 ```javascript
1096 // Execute through `/bin/sh`
1097 system("echo 'Hello world' && exit 3");    // prints "Hello world" to stdout and returns 3
1098 
1099 // Execute argument vector
1100 system(["/usr/bin/date", "+%s"]);          // prints the UNIX timestamp to stdout and returns 0
1101 
1102 // Apply a timeout
1103 system("sleep 3 && echo 'Success'", 1000); // returns -9
1104 ```
1105 
1106 #### 6.52. `trace(level)`
1107 
1108 Enables or disables VM opcode tracing. When invoked with a positive non-zero
1109 level, opcode tracing is enabled and debug information is printed to stderr
1110 as the program is executed.
1111 
1112 Invoking `trace()` with zero as argument will turn off opcode tracing.
1113 
1114 Right now, any positive non-zero value will enable tracing while future
1115 implementation might provide different different verbosity levels or treat
1116 the level argument as bit mask to enable or disable individual debug
1117 elements.
1118 
1119 #### 6.53. `proto(val[, proto])`
1120 
1121 Get or set the prototype of the array or object value `val`.
1122 
1123 When invoked without a second argument, the function returns the current
1124 prototype of the value in `val` or `null` if there is no prototype or if
1125 the given value is neither an object, nor an array.
1126 
1127 When invoked with a second prototype argument, the given `proto` value is
1128 set as prototype on the array or object in `val`.
1129 
1130 Throws an exception if the given prototype value is not an object.
1131 
1132 #### 6.54. `sleep(milliseconds)`
1133 
1134 Pause execution for the given amount of milliseconds. Returns `false` if
1135 an invalid value was passed, otherwise `true`.
1136 
1137 #### 6.55. `assert(cond[, message])`
1138 
1139 Raise an exception with the given `message` parameter if the value in `cond`
1140 is not truish. When `message` is omitted, the default value is `Assertion failed`.
1141 
1142 #### 6.56. `render(path[, scope])`
1143 
1144 Like `include()` but capture output of included file as string and return it.
1145 
1146 See `include()` for details on scoping.
1147 
1148 #### 6.57. `regexp(source[, flags])`
1149 
1150 Construct a regular expression instance from the given `source` pattern string
1151 and any flags optionally specified by the `flags` argument.
1152 
1153 Throws a type error exception if `flags` is not a string or if the string in
1154 `flags` contains unrecognized regular expression flag characters.
1155 
1156 Throws a syntax error when the pattern in `source` cannot be compiled into a
1157 valid regular expression by the underlying C runtimes `regcomp(3)` function.
1158 
1159 Returns the compiled regular expression value.
1160 
1161 ```javascript
1162 regexp('foo.*bar', 'is');   // equivalent to /foo.*bar/is
1163 regexp('foo.*bar', 'x');    // throws "Type error: Unrecognized flag character 'x'"
1164 regexp('foo.*(');           // throws "Syntax error: Unmatched ( or \("
1165 ```
1166 
1167 #### 6.58. `wildcard(subject, pattern[, nocase])`
1168 
1169 Match the given subject against the supplied wildcard (file glob) pattern.
1170 
1171 If a truish value is supplied as 3rd argument, case insensitive matching is
1172 performed. If a non-string value is supplied as subject, it is converted into
1173 a string before being matched.
1174 
1175 Returns `true` when the subject matches the pattern or `false` when not.
1176 
1177 #### 6.59. `sourcepath([depth [, dironly]])`
1178 
1179 Determine the path of the source file currently being executed by ucode.
1180 
1181 The optional `depth` parameter allows walking up the call stack to determine
1182 the path of the parent sources including or requiring the current source file.
1183 If unspecified, the `depth` defaults to `0`, that is the currently executed
1184 file.
1185 
1186 If a truish value is passed in `dironly`, only the directory portion of the
1187 source file path is returned.
1188 
1189 If the ucode interpreter executes code from stdin or a code fragment passed
1190 via `-s` switch, the function returns `null` since there is no associated
1191 file path.
1192 
1193 If `depth` exceeds the size of the call stack, the function returns `null`
1194 as well.
1195 
1196 #### 6.60. `min([val1 [, val2 [, ...]]])`
1197 
1198 Return the smallest value among all parameters passed to the function.
1199 The function does a `val1 < val2` comparison internally, which means that
1200 the same value coercion rules as for relational operators apply. If both
1201 strings and numbers are passed to `min()`, then any string values will be
1202 effectively ignored since both `1 < "abc"` and `1 > "abc"` comparisons
1203 yield false results.
1204 
1205 ```javascript
1206 min(5, 2.1, 3, "abc", 0.3);   // 0.3
1207 min(1, "abc");                // 1
1208 min("1", "abc");              // "1"
1209 min("def", "abc", "ghi");     // "abc"
1210 min(true, false);             // false
1211 ```
1212 
1213 #### 6.61. `max([val1 [, val2 [, ...]]])`
1214 
1215 Return the largest value among all parameters passed to the function.
1216 The function does a `val1 > val2` comparison internally, which means that
1217 the same value coercion rules as for relational operators apply. If both
1218 strings and numbers are passed to `min()`, then any string values will be
1219 effectively ignored since both `1 < "abc"` and `1 > "abc"` comparisons
1220 yield false results.
1221 
1222 ```javascript
1223 max(5, 2.1, 3, "abc", 0.3);   // 5
1224 max(1, "abc");                // 1 (!)
1225 max("1", "abc");              // "abc"
1226 max("def", "abc", "ghi");     // "ghi"
1227 max(true, false);             // true
1228 ```
1229 
1230 #### 6.62. `b64dec(str)`
1231 
1232 Decodes the given base64 encoded string and returns the decoded result, any
1233 whitespace in the input string is ignored.
1234 
1235 If non-whitespace, non-base64 characters are encountered, if invalid padding
1236 or trailing garbage is found, the function returns `null`.
1237 
1238 If a non-string argument is given, the function returns `null`.
1239 
1240 ```javascript
1241 b64dec("VGhpcyBpcyBhIHRlc3Q=");   // "This is a test"
1242 b64dec(123);                      // null
1243 b64dec("XXX");                    // null
1244 ```
1245 
1246 #### 6.63. `b64enc(str)`
1247 
1248 Encodes the given string into base64 and returns the resulting encoded
1249 string.
1250 
1251 If a non-string argument is given, the function returns `null`.
1252 
1253 ```javascript
1254 b64enc("This is a test");         // "VGhpcyBpcyBhIHRlc3Q="
1255 b64enc(123);                      // null
1256 ```
1257 
1258 #### 6.64. `uniq(array)`
1259 
1260 Returns a new array containing all unique values of the given input
1261 array. The order is preserved, that is subsequent duplicate values
1262 are simply skipped.
1263 
1264 If a non-array argument is given, the function returns `null`.
1265 
1266 ```javascript
1267 uniq([ 1, true, "foo", 2, true, "bar", "foo" ]); // [ 1, true, "foo", 2, "bar" ]
1268 uniq("test");                                    // null
1269 ```

This page was automatically generated by LXR 0.3.1.  •  OpenWrt