Extension:Winter/Documentation

= Welcome to Winter 2.0 =

This is the documentation for Winter v2.0+ and is currently incomplete. The documentation for Winter v1.5 and below is also available.

= Introduction = Winter was created in late 2005 to fill a need for simple scripting on wiki pages. It has since grown to become a full fledged language in its own right. Mostly reminiscent of PHP, it also has a bit of a LISP feel. Version 2.0.0 adds true array capability as well as many new functions (mostly direct wrappers of their PHP namesakes) and operations.

= Installation and Configuration =

Installation

 * 1) Place Winter.php in your wiki's the extensions directory.
 * 2) Add require_once("extensions/Winter.php"); to the bottom of LocalSettings.php.

Configuration
Winter has four options which may be set by defining variables in LocalSettings.php. These options must be set before the require_once(... call is made. The default settings should be acceptable for an average blog, though depending on your needs you may wish to modify them. This is especially if your wiki is heavily used and/or faces risk of DoS attacks.

$wgWinterMaxNesting
Sets the maximum number of nesting levels allowed. Default is 50

$wgWinterMaxNesting = 50;

$wgWinterMaxOperations
Sets the maximum number of operations per script allowed. Default is 10000.

$wgWinterMaxOperations = 10000;

$wgWinterMaxIterations
Set the maximum number of per-loop iterations allowed. Default is 1000

$wgWinterMaxIterations = 1000;

$wgWinterNotAllowed
Defines which functions are now allowed to be used. No functions are blocked by default.

// Default $wgWinterNotAllowed = ""; // Example $wgWinterNotAllowed = "preg_match xml_xpath html_to_xml";

Extending Winter with custom PHP functions
Winter also allows for functions written in PHP to be defined via LocalSettings.php. These functions must be defined after requiring the Winter php file.

$wgWinter->addFunction
Use the method $wgWinter->addFunction to add a custom function definition.

$wgWinter->addFunction('WinterFunction','PHPFunction');

When WinterFunction is called within the Winter script, it will trigger PHP to call the PHP function named PHPFunction. PHPFunction will be passed an array begining with the Winter function name followed by the parameter values.

$wgWinter->showError
$wgWinter->showError returns text formatted like other Winter error messages.

return $wgWinter->showError("There was a problem with a parameter");

Take care to ensure all data is properly formatted so that your script does not cause PHP errors. A Winter error message will appear in line with the rest of the text, as opposed to PHP error messages with end up at the top left (usually underneath the site logo) making the site look very broken.

Example
$wgWinter->addFunction('WinterFunction','PHPFunction');

function PHPFunction($params) {  if (count($params) == 3) {     if ($params[1] == 5) {          // show custom error message global $wgWinter; return $wgWinter->showError("First parameter in $params[0] can't be 5!"); }     else { return "Function $params[0] has two parameters: $params[1] and $params[2]"; }  }   else {  return false // will display general syntax error } }

= Language Specification =

Syntax
Winter functions follow a similar syntax to MediaWiki templates, beginning with double braces.

Any parameter may include nested functions, however the function name may not have nested functions within its text. After execution, the text of the function call will be replaced with its return value.

Like templates, white space surrounding the | character is ignored. Unlike templates, you may also use quotation marks (") to demarcate the beginning and ending of a string. This is useful when you would like to end or begin a parameter with whitespace. Only quotation marks at the end or beginning of a parameter string will have any effect on the string.

---> 'param' ---> 'param' ---> ' param ' ---> ' param' ---> 'par"am '

If all the parameters of a function are a single word without white space or nested functions, the following shortcut may be used:

--->   ---> invalid

Alphanumeric string
Generally speaking, almost all data in Winter is alphanumeric or can be expressed alphanumerically.

Boolean
Not a true data type. The following correspond to false:
 * 0
 * An empty string
 * An empty array

All other values evaluate to true. Functions which return a boolean value will return 0 for false and 1 for true.

List
Not a true data type, but rather an alphanumeric string which is a collection of alphanumeric strings delineated by pipe | characters; the alphanumeric expression of an array.

Array
Arrays are a compound data type consisting of one or more alphanumeric strings or arrays which have a an associated key by which the element is referenced. Arrays can have a maximum of 2 dimensions. Any arrays created having more than 2 dimensions (by copying a 2D array into another array for example) will have the additional dimensions 'flattened' or imploded into a list inside the array.

When an array is used where a string is expected, it is flattened and returned as a list.

Variables
Variables are defined, retrieved and operated on using #var. Undefined variables referenced with #var will be created and set to empty string.

Returns the value of variable var.

Performs an operation

Sets the value and returns it

Sets the value and returns nothing

Array data can also be accessed using #var.

You may also use the new []= operator to assign values to array. Again you may use @ to suppress the return value.

You may also use the depreciated #setvar to set variables and arrays.

Scope
Variables defined within function are local to the function. Variables defined outside of the function cannot be accessed directly inside the function; you must pass the value via function parameter.

Variable shortcut syntax
Variable names can have any characters excluding {. |, and }, though it is recommended to only use characters that are valid for functions in order to use variable shorthand: If an unknown function name is encountered, it will be converted into a variable reference.

The following pairs are equivalent: converted to --> converted to -->

Variable names must meet the qualifications as a function name to use the shortcut syntax. For example: ---> valid ---> valid ---> not valid ---> not valid

Operators
Both #op and #var support all of these operators, exluding the variable assignment operators which are supported by #var only.

{| style="border:1px solid black; padding:.5em" ! operator || Action
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * colspan="2" |
 * colspan="2" |

Variable assignment operators

 * colspan="2" style="background-color:black" |
 * @ || All of the following assignment operators may be preceded with the @ modifier, which will cause the operation to be silent (ie not return a value).
 * = || Assign value b to variable a and return the value.
 * += || Assign the sum of variable a and value b to variable a and return the value.
 * -= || Assign the difference of variable a and value b to variable a and return the value.
 * *= || Assign the product of variable a and value b to variable a and return the value.
 * /= || Assign the quotient of variable a and value b to variable a and return the value.
 * .= || Assign the concatenation of variable a and value b to variable a and return the value.
 * <- || Copy the contents of var value b to variable a and return value of value b (Useful for copying arrays)
 * <=> || variable a will become an alias for variable value b. In effect they are the same variable with two names.  Returns value.
 * colspan="2" style="background-color:black" |
 * colspan="2" | The following operators do not take a third parameter and do not use the @ modifier
 * ++ || Increment variable a by one and return the value.
 * -- || Decrement variable a by one and return the value.
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * <- || Copy the contents of var value b to variable a and return value of value b (Useful for copying arrays)
 * <=> || variable a will become an alias for variable value b. In effect they are the same variable with two names.  Returns value.
 * colspan="2" style="background-color:black" |
 * colspan="2" | The following operators do not take a third parameter and do not use the @ modifier
 * ++ || Increment variable a by one and return the value.
 * -- || Decrement variable a by one and return the value.
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * ++ || Increment variable a by one and return the value.
 * -- || Decrement variable a by one and return the value.
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * colspan="2" |
 * colspan="2" |

Arithmetic operators



 * colspan="2" style="background-color:black" |
 * + ||  returns a + b
 * - ||  returns a - b
 * * ||  returns a * b
 * / ||  returns a / b
 * ^ ||  returns the a to the bth power
 * mod || returns the remainder of a / b
 * / ||  returns a / b
 * ^ ||  returns the a to the bth power
 * mod || returns the remainder of a / b
 * ^ ||  returns the a to the bth power
 * mod || returns the remainder of a / b
 * mod || returns the remainder of a / b


 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * colspan="2" |
 * colspan="2" |

Bitwise operators

 * colspan="2" style="background-color:black" |
 * & ||  returns bits that are set in both a and b
 * | ||  returns bits that are set in either a or b
 * xor ||  returns bits that are set in either a or b but not both
 * << ||  returns bits of a shifted b steps to the left (each step means "multiply by two")
 * << ||  returns bits of a shifted b steps to the right (each step means "divide by two")
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * << ||  returns bits of a shifted b steps to the left (each step means "multiply by two")
 * << ||  returns bits of a shifted b steps to the right (each step means "divide by two")
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * colspan="2" style="background-color:black" |
 * colspan="2" |
 * colspan="2" |
 * colspan="2" |

Logic operators

 * colspan="2" style="background-color:black" |
 * == || Returns 1 if a is equal to b, otherwise returns 0
 * != || Returns 1 if a is not equal to b, otherwise returns 0
 * < || Returns 1 if a is less than to b, otherwise returns 0
 * > || Returns 1 if a is greater than to b, otherwise returns 0
 * <= || Returns 1 if a is less than or equal to b
 * >= || Returns 1 if a is greater than or equal to b
 * and || Returns 1 if a and b are true
 * or || Returns 1 if a or b are true
 * }
 * <= || Returns 1 if a is less than or equal to b
 * >= || Returns 1 if a is greater than or equal to b
 * and || Returns 1 if a and b are true
 * or || Returns 1 if a or b are true
 * }
 * and || Returns 1 if a and b are true
 * or || Returns 1 if a or b are true
 * }
 * }

Control Structures
Control structures affect program flow. The syntax for these commands isslightly modified; instead of using one pipe to delineate fields, a double pipe is used. Begining with Winter 2.0, any field of a structure may contain nested structures.

The following control structures are available in Winter:

#if #for
 * 1) while
 * 2) repeat
 * 1) foreach

#if and #iff
If provides the basic program branching needed in any programming language.

The #if statement is now a true control structure in Winter 2.0 and double pipes must be used. Previously single pipes were used because #if was a function, but all function parameters are evaluated before being passed to the function, so both parameters were evaluated, but only one returned. If you desire this functionality you may use the #iff function, or simply use single pipes with the #if statement; #if will rewrite the statement as an #iff function.

#repeat
A very simple type of loop. #repeat evaluates and returns the expression for count iterations.

#while
Evaluates and returns the expression as long as bool evaluates to true. If the initial value of bool is false the expression will not be evaluated.

#for

 * 1) for is a special kind of while loop. First initialize is evaluated.  Then while bool evaluates to true, expression is evaluated and returned.  Before bool is tested again, step is evaluated.

#foreach
Foreach is for traversing arrays and is similar to its PHP counterpart.

The expression will be evaluated for each value contained within the array. During each iteration certain "magic variables" will be set. The names of those variables depend on if value var name and key var name are set.

Magic variables _key                ---> always contains the text of the key name _value              ---> always contains the value of the specific array item _k OR key var name  ---> contains the text of the key name _v OR value var name ---> contains the value of the specific array item

Functions
Functions are defined using #function.

Any valid Winter code may be contained within a function declaration, including other function declarations. If a function name is already defined, it will be overwritten by the new declaration Variables defined within a function are local to the function only.

Parameters
Parameters are passed to functions via "magic variables" which are set when the program code is evaluated. The variable names are ordinal values corresponding to their placement in the function call, eg the first parameter is named 1, the 2nd is named 2, and so on.

This example displays a familiar message: