| Procedural elements: |
| ==================== |
| |
| definition of terms: |
| <block> : zero or more values to be evaluated. |
| <test> : one value to be evaluated as branch or loop condition. |
| <result> : one value to be evaluated at the end of the execution of |
| the form; the value is returned. |
| <lvalue> : local variable/parameter, global variable, or an indexed |
| lvalue. |
| <expression>: one value to be evaluated. |
| <integer> : an integer constant |
| <string> : a string constant, or 0. |
| used EBNF operators: |
| { } iteration |
| [ ] option |
| | alternative |
| |
| forms: |
| ({#', <body> <result>}) |
| ({#'? { <test> <result> } [ <result> ] }) |
| ({#'?! { <test> <result> } [ <result> ] }) |
| ({#'&& { test } }) |
| ({#'|| { test } }) |
| ({#'while <test> <result> <body>...}) loop while test evaluates non-zero. |
| ({#'do <body> <test> <result>}) loop till test evaluates zero. |
| ({#'foreach <var> <expr> <body>...}) loop over all values of <expr>. |
| ({#'foreach ({ <var>...<var> }) <expr> <body>...}) |
| ({#'= { <lvalue> <value> } }) assignment |
| other assignment operators work too. |
| case_label: <integer> | <string> | #'default |
| generalized_case_label: case_label | <integer> #'.. <integer> |
| case_label_list: case_label | ({ { generalized_case_label } }) |
| case_delimiter: #', | #'break |
| ({#'switch <expression> { case_label_list <result> case_delimiter } }) |
| Evaluate expression, then evaluate the result form labeled with |
| the value equal to the value evaluated from expression. |
| If no matching label exists, the value of #'switch is 0. |
| ({#'catch, <body> [, 'nolog ] [, 'publish ], [, 'reserve, <expr> }) |
| Evaluates the <body> and catches any runtime error. If the symbol |
| 'nolog is also given, a caught error is not logged. If the |
| symbol 'publish is also given, master::runtime_error() is |
| called for the caught error. If the symbol 'reserve with a |
| following expression is given, this value is used as the |
| computing reserve. |
| |
| |
| lisp similars: |
| #', progn |
| #'? cond |
| #'&& and |
| #'|| or |
| #'while do /* but lisp has more syntactic candy here */ |
| #'= setq |
| |
| A parameter / local variable 'foo' is referenced as 'foo , a global |
| variable as ({#'foo}) . In lvalue positions (assignment), you need not |
| enclose global variable closures in arrays. |
| |
| Call by reference parameters are given with ({#'&, <lvalue>}) |
| |
| Some special efuns: |
| #'[ indexing |
| #'[< indexing from the end |
| #'negate unary - |
| |
| Unbound lambda closures |
| ======================= |
| |
| These closures are not bound to any object. They are created with the efun |
| unbound_lambda() . They cannot contain references to global variables, and |
| all lfun closures are inserted as is, since there is no native object for |
| this closure. |
| You can bind and rebind unbound lambda closures to an object with efun |
| bind_lambda() You need to bind it before it can be called. Ordinary objects |
| can obly bind to themselves, binding to other objects causes a privilege |
| violation(). |
| The point is that previous_object for calls done from inside the closure |
| will reflect the object doing bind_lambda(), and all object / uid based |
| security will also refer to this object. |
| |
| |