===== W Language Description =====
The W language is a procedural, loosely typed language with flexible and powerful data structures.
==== Comments ====
Comments are written after the semicolon (;). They can appear either alone on a line or at the end of a line after an instruction.
Empty lines are considered comments.
; First comment
; Other comment
; That's it!
==== Program Structure ====
The W language supports only ONE instruction per line, except for the comment, which can appear at the end of the line after the instruction.
A program consists of the start instruction, the code with the processing block and the exception block, and a finish instruction.
In each line (= instruction), the different elements of the instruction are separated by at least one space (space, tab). Accepted line breaks are those in Unix and Windows formats, interchangeably.
Comments can be written anywhere as indicated above.
Each program can call subroutines, called //sub//, as well as another program which in this case is called a //library// (or library).
The language's distinctive feature is that its syntax mandates a processing block and an exception block in each program and subroutine.
During execution, any exception automatically causes a jump to the beginning of the exception block of the current program or subroutine. This is the equivalent of a systematic ''try/catch'' loop.
Let's revisit the classic //Hello world// example :
; classic example...
begin hello ; start instruction, marking the beginning of the main block
; processing block
echonl "Hello world!" ; the echonl instruction allows writing to the console, with a line break
; Here, the process skips to the end (end)
except ; instruction marking the beginning of the exception block
; exception block
end ; end of the hello program
At runtime, the process starts at the beginning instruction of the main block, then executes all instructions up to the //except// instruction. At that point, the process goes directly to the end instruction and then terminates. The second possible start instruction is ''background '': the process works identically to that with ''begin'', except that the process runs in the background, and therefore returns control immediately. In this mode, all writes and reads from the console are automatically inhibited by the executor. The third and final possible start instruction is ''library ()''. It allows the program to be called from any other program or library, but the library cannot be the first program launched. During the call, the library is loaded on the fly at runtime only.
==== Include and External Calls ====
The //include// statement allows you to include another source in the current source stream. Recursion is not allowed and will throw an exception.
The source file to be included must be located in the [[w:env|WSRC]] directory.
include "calcul.w"
Library and method calls are made using the //do// //call// //invoke// instructions:
* Library call, external to the current source code: ''call (param1, param2, ...)'', library written in W, main block of type //library//, and available in the [[w:env|WBIN]] directory in compiled mode or [[w:env|WSRC]] in interpreted mode
* Module call, plugin type: ''invoke &(parameter)'', written in C and whose binary is located in [[w:env|WBIN]]
* Object sub/method call: ''do (param1, param2, ...)'', written in W and declared in the same source code as the current source code (including //include// files)
All passages of Parameters are passed by reference: in called subroutines, access to variables acts on the original variable.
==== Data Types ====
Variables must be declared, but without a type, and can be declared anywhere in the code. They only become usable after their declaration; otherwise, an exception will be thrown.
; declaration of 3 variables
declare x, y, tmp
The typing of each variable is done when it is assigned. There are 7 usable types:
* Null: a declared but unused variable
* Number: a fixed-point number with 13 digits before the decimal point and 5 decimal places
* Dynamic: stores structured strings or any binary content
* Hashtable: a key/value map, where each value is itself another variable from among the available types, including Hashtable
* Subroutine: stores the address of a subroutine
* Object: identical to Hashtable and allows storing/managing classes and objects
* Param: Since parameters passed to subroutines are all by reference, each parameter is of this type, pointing to the actual variable: each action on the parameter will actually act on the variable passed as a parameter.
An 8th type, Buffer, is used only internally by the W executor (for managing the expression and call stack).
=== Scope ===
Variables declared in the main block (begin/background) of the program have global scope.
Variables declared in libraries and subroutines have local scope to the subroutine.
Subroutines, classes, and objects have global scope, even if they appear in a subroutine (**__To be specified__** when created from a //library//).
Variables belonging to a hashtable are only accessible via the hashtable, except for classes and objects stored globally.
=== Usage ===
Variables are assigned using the //let// statement. It is possible to //de-assign// a variable with the //delet// instruction. In this case, the variable is deleted and is no longer declared. Adding variables to a Hashtable does not require declaration, but they are assigned and unassigned like other variables. The syntax to use is ''.''
declare h, n, d
let h = {} ; h is a Hashtable
let n = -12.34 ; n is a Number
let d = "coucou" ; d is a Dynamic
; h will contain 2 variables of type Number, x and y, which are not declared with "declare"
let h.x = 10
let h.y = 20
==== Exceptions ====
Every program and subroutine must contain an instruction [[w:instr:except|except]]. When an exception occurs, the executor automatically jumps to the exception block, that is, to the first instruction following the line //except//. Within the processing block, it is possible to force an exception to be thrown with the instruction [[w:instr:throw|throw]]. Within the exception block, by default, if nothing is coded, the exception propagates to the calling program, and thus travels back to the main program. In this case, the exception returns an exit code to the shell corresponding to the exception code (handling the return code using 8 bits). Also within the exception block, it is possible to cancel the current exception with the instruction [[w:instr:catch|catch]]: the program immediately exits the block without an exception. It is also possible to throw another exception with the `//throw//` instruction: the program also immediately exits the block, with the exception code specified in `//throw//`.
Finally, the system variable `[w:instr:varsys|@except]` contains the current exception, and `[w:instr:varsys|@exceptline]` gives the line number of the source code that caused the exception.
At any time, the `[w:instr:return|return]` instruction allows exiting the current block, either the processing block or the exception block, without changing the exit conditions (exception). When the current block is the main block, `//return//` causes the program to terminate and returns to the caller (the shell, etc.) with the current exception code (8 bits) returned, or 0 if there is no exception.
Example
begin test
declare x
let x = 10
let y = 20 ; => raises an EX_NOVAR exception (undeclared variable "y")
echo "Not displayed"; this line will not appear in the console
except
catch; => exits the program without error
echo "Exception"; this line will not appear in the console
end
===== List of instructions =====
In alphabetical order
===== Internal operation =====
The W source code is compiled into //p-code//.\\
This p-code is a series of elementary instructions specific to the W language.\\
It is the same program that analyzes the W source code and breaks it down into p-code instructions:
* in interpreted mode, the instructions are then executed directly
* in compiled mode, the instructions are written to the output assembler file. Finally, this assembler file is converted into binary, a digital translation of the p-code instructions.
The p-code executor can also be called from another process, with p-code serving as a plugin-type language/library. A provided FastCGI module facilitates the use of W as a server-side language for websites.
The binary format of p-code is big-endian, allowing the same W binary file to be used on any type of operating system and architecture.
Expressions only concern variables of type Dynamic and Number and are managed in a stack using Reverse Polish Notation.
List of instructions in W.
Compilation rules for transforming W source code into p-code (W assembler).