Programming language PG0.5
Language specification
--
# Introduction
PG0.5 is a programming language designed for learning programming.

PG0.5 is extends the PG0 programming language.
The following features have been expanded from PG0:
* Strings
* Real numbers
* Bit operations
* Compound assignment operators
* Increment and decrement operators
* Associative arrays
* Functions
* else if
* for
* do..while
* switch, case, default
* break, continue
* Importing scripts written in separate files​​

# Types
## Integer Type
Handles 4-byte integers ranging from -2,147,483,648 to 2,147,483,647. 
	a = 1234 // Decimal
	a = -123 // Negative number
	a = 0123 // Octal (equivalent to 83 in decimal)
	a = 0x12 // Hexadecimal (equivalent to 18 in decimal)

## Real Number Type
Handles 64-bit double-precision real numbers.
	a = 0.5
	b = 2.5 - 0.5 // result is converted to an integer

## String Type
Represented by enclosing in single ('') or double ("") quotes.
String concatenation is done through addition.
	str = "abc" + "def" // "abcdef"
Escape characters
	-------+------------------
	\n      Newline
	\r      -
	\t      Tab	
	\b      Backspace
	\\      \
	\"      "
	\'      '
	\oooooo Octal character
	\xhhhh  Hexadecimal character
	-------+------------------
Internal string code is UTF-16.

## Array Type
Arrays are a collection of variables arranged in sequence.
They can function as either hash tables (associative arrays) or scalar arrays (vectors). 
To use an array, [] is specified after the variable.
	a[0] = "abc" // First elemen
	a[1] = "def" // Second element
	b["foo"] = 13 // Key "foo"
When accessed with a numeric index, it acts as an array index, starting from 0.
When accessed with a string, it functions as a key in an associative array, where keys are case-insensitive.
Arrays automatically expand in size.
	a[100]   // Creates an array with 101 elements
	b["100"] // Creates an array with the key "100"
For multi-dimensional arrays, append additional [key] for each dimension.
	a[1][0]     = f // 2-dimensional
	b["foo"][2] = f // Mixed numeric and associative indexing
Assigning a non-array type to an array variable converts it to that type, and vice versa.
	a = b[]   // Equivalent to a[] = b[]
	a[] = 0   // Equivalent to a = 0
	a[] = "aaa" // Equivalent to a = "aaa"
Array concatenation is performed through addition.
	b[] = {1,2}
	c[] = {3,4}
	a[] = b[] + c[] // Results in a containing {1,2,3,4}
To initialize an array, assign {value1, value2, value3}.
	a[] = {1,2,3} // Equivalent to setting a[0] = 1; a[1] = 2; a[2] = 3;
	a[] = {"aaa":10,"bbb":20} // Equivalent to a["aaa"] = 10; a["bbb"] = 20;
	a[] = {1,2,{10,20,{"a","b","c"}},3} // Multi-dimensional initialization
ince any variable or constant can be an array, expressions like 100[10] do not result in an error.
	b = {"A", "B", "C"}[1] // Results in b containing "B"

# Variables
Variables are containers for storing numerical values.
They are automatically allocated when used.
If not initially assigned, they are initialized to 0.
You can explicitly declare variables using 'var'.
	var i, j = 100 // Multiple variables can be declared with ','

Variables allocated within a block are only valid within that block.
Allocating the same variable name within the same block results in an error.
	var x
	{
		var x // A variable x valid only within the inner block
		x = 100
	}
	y = x // The value of x is 0

Variable names can include alphanumeric characters and underscores, but cannot start with a number.
Variable names are case-insensitive.

Stating only numerical values or only strings is a constant.

# Expressions
Variables and constants are calculated or compared using expressions.
All expressions return a value as a result.

Operators in expressions are primarily used with integers and real numbers.
Operations like subtraction or multiplication with strings or arrays are not allowed.
	str = "abc" - 3 // Error
When calculating between a string and an integer, the integer is converted to a string. 
	str = "abc" + "def"      //"abcdef"
	str = "abc" + 1          //"abc1"
	str = 1 + 2 + "abc"      //"3abc"
	str = "" + 1 + 2 + "abc" //"12abc"

The truth value in expressions is defined as follows.
	* False: 0, 0.0, ""
	* True: Everything else

## Arithmetic Operators
	-------+---------------
	a + b   Addition
	a - b   Subtraction
	a * b   Multiplication
	a / b   Division
	a % b   Modulus
	-------+---------------

## Unary Operators
	----+----------------------------------------------
	+a   Positive value.
	-a   Negative value.
	a++  Post-increment, increases the value of a by 1 after the expression is evaluated.
	a--  Post-decrement, decreases the value of a by 1 after the expression is evaluated.
	++a  Pre-increment, increases the value of a by 1 before the expression is evaluated.
	--a  Pre-decrement, decreases the value of a by 1 before the expression is evaluated.
	!a   If a is 0, becomes 1; otherwise, becomes 0.
	     For strings, an empty string ("") becomes 1, and a non-empty string becomes 0.
	~a   Bitwise NOT, inverts each bit of a​​.
	----+----------------------------------------------
	a++ and a-- are executed at the end of the expression.
		a = 1
		b = a++
		// At this point, b is 1 and a is 2.

## Assignment Operator
	Assigns the value of the right expression to the left variable.
		a = 5 // a becomes 5
		b = a + 5 // b becomes 9

## Compound Assignment Operators
	Assignment operators can be combined with arithmetic and bitwise operators.
		a += 2  // a = a + 2
		a -= 2  // a = a - 2
		a *= 2  // a = a * 2
		a /= 2  // a = a / 2
		a %= 2  // a = a % 2
		a &= 2  // a = a & 2
		a |= 2  // a = a | 2
		a ^= 2  // a = a ^ 2
		a <<= 2  // a = a << 2
		a >>= 2  // a = a >> 2
		a <<<= 2  // a = a <<< 2
		a >>>= 2  // a = a >>> 2

## Bitwise Operators
	-------+---------------------+-----------------------------------------------------
	a & b   Bitwise AND           Returns bits that are set in both a and b.
	a | b   Bitwise OR            Returns bits that are set in either a or b.
	a ^ b   Bitwise XOR           Returns bits set in a or b but not both.
	a << b  Left Shift            Shifts the bits of a left by b bits (with sign).
	a >> b  Right Shift           Shifts the bits of a right by b bits (with sign).
	a <<< b Unsigned Left Shift   Shifts the bits of a left by b bits (without sign).
	a >>> b Unsigned Right Shift  Shifts the bits of a right by b bits (without sign)​​.
	-------+---------------------+-----------------------------------------------------

## Relational Operators
	Performs comparison and returns 1 or 0.
	-------+---------------------+-----------------------------------------
	a == b  Equal                 1 if a equals b
	a != b  Not equal             1 if a does not equal b
	a < b   Less than             1 if a is less than b
	a > b   Greater than          1 if a is greater than b
	a <= b  Less than or equal    1 if a is less than or equal to b
	a >= b  Greater than or equal 1 if a is greater than or equal to b
	-------+---------------------+-----------------------------------------
	For array comparisons, the data inside the arrays are compared. Only '==' and '!=' can be used for array comparisons.

## Logical Operators
	------+------------+------------------------------------------
	a && b Logical AND  1 if both a and b are true, otherwise 0
	a || b Logical OR   1 if either a
	------+------------+------------------------------------------
	The logical operator is short-circuit evaluated.

## Operator Precedence
	high
		() []
		! ~ + - ++ -- (Unary Operators)
		* / %
		+ -
		<< >> <<< >>>
		< > <= >=
		== !=
		&
		^
		|
		&&
		||
		: (Label identifier at array initialisation)
		= += -= *= /= %= &= |= ^= <<= >>= <<<= >>>=
		,
	low

# Basic Structures
## Sequence
### Statements
	A statement is separated by a newline or ';'.
	They are executed sequentially.
		a = 1 // First execution, assigns 1 to a
		b = 2 // Second execution, assigns 2 to b

	To write a statement over multiple lines, end the line with an operator.
	Example: Writing 'a = 1 + 2' over two lines.
		a = 1 + // Continues to next line
		    2
### Blocks
	Blocks are denoted by { to } and group multiple statements into a single unit.
		{
			a = 1
			b = 2
		}
## Branching
### if
	The if statement controls the execution of statements based on a condition.
	The statement following the if statement must be enclosed in a block.
		if (condition) {
			statement
		}
	The statement is executed if the expression is true; otherwise, it is skipped.
		if (a > b) {
			b = a // If a is greater than b, assign a to b
			a = 0
		}
	Using '=' for assignment in expressions is a syntax error.
## else
	Specifies the statement to execute when the if statement's expression evaluates to false.
	If the if statement executes, the else statement is skipped.
	The statement following else must be in a block.
		if (a > b) {
			b = a
		} else {
			a = b
		}
	Multiple conditional expressions can control a statement by following else with if.
		if (a == 0) {
			b = 0
		} else if (b == 0) {
			a = 0
		} else if (a > b) {
			b = a
		} else {
			a = b
		}
## switch
	The switch statement to execution of code starting from the point where the expression matches a given value.
	It is similar in function to a series of if statements.
		switch (expression) {
		case value1:
			statement1
			break
		case value2:
		case value3:
			statement2
			break
		default:
			statement3
			break
		}
	When a case matches the expression, the corresponding statements are executed until a break statement is reached or the block ends.
	The default clause is executed when no other case matches the expression​​.
## Looping
### while
	The while statement performs a loop based on an expression.
	The statement following while must be in a block.
		while (condition) {
			statement
		}
	As long as the expression is true, the statement continues to execute.
		i = 1
		while (i <= 10) { // Loop from 1 to 10
			i = i + 1
		}
	Using '=' for assignment in expressions is a syntax error.
## do..while
	The 'do..while' statement checks the condition at the end of the loop.
	This ensures that the loop's body is executed at least once.
		do {
			statement
		} while (condition)
## for
	The 'for' statement is used for loops with initialization and re-initialization expressions.
		for (initialization; condition; re-initialization) {
			文
		}
	Expression1 is executed before entering the loop.
	The loop continues as long as expression2 evaluates to true.
	Expression3 is executed at the end of each loop iteration. 
		for (i = 1; i <= 10; i++) {
			j = j + i
		}
	Expressions 1, 2, and 3 in the for statement are optional.
	Omitting expression2 results in an infinite loop.
		for (;;) {
			// Infinite loop
		}
	Using an assignment ('=') in expression2 is a syntax error.
## break
	The 'break' statement is used to exit from the current loop. 
		while (1) {
			while (1) {
				break // Exits the inner while loop
			}
			break // Exits the outer while loop
		}
## continue
	The continue statement skips the rest of the loop and checks the conditional expression.
	In the case of a for statement, re-initialisation is performed before checking the conditional expression.

# Function
Functions are defined with the following syntax:
	function functionName(argument1, [argument2, ...]) {
		function body
	}
To call a function, use the following form:
	functionName(argument1, [argument2, ...])
Functions can be called regardless of whether they are defined before or after the call in the script.
Function names are case-insensitive.
Functions always return 0 by default, but can return a specific value using the return statement.
It is necessary to specify 'function' before the function name.
	// Example of a function that performs addition
	function sum(arg_1, arg_2) {
		return arg_1 + arg_2
	}
Passing an argument by reference is done by placing an '&' before the argument name.
Arguments are copied when passed to functions, so it is more efficient to pass large arrays by reference.
	function func(&a) {
		a = 100
	}
	func(i) // i becomes 100
The number of arguments a function takes is determined by its definition.
Calling a function with fewer arguments than it requires results in an error.
To set default values for optional arguments, assign values in the function definition.
	function func(a, b = 100) { // The second argument defaults to 100 if omitted
	}
Recursive function calls are possible, but be aware that a stack overflow can cause the script to terminate.

# Preprocessor
The preprocessor is processed at the time of script loading.
The placement of these directives is not restricted and affects the entire script.
#option("pg0.5")
	The script operates as a PG0.5 script.
	This option is effective from the line where it is specified and also applies to any other scripts loaded afterward.
#option("strict")
	Enforces variable declaration using 'var'.
	This is effective only within the script where it is declared.
#import("filename")
	Imports another script file or a library file.
	Functions in the imported script or library can be called, but variables in the imported script are not accessible.

# Other
Comments are denoted by // to the end of the line.

Use 'exit' to terminate processing.
	exit
'exit' can have a return value.
	exit i

# Reference
## Standard functions
error(buf)
	* Description
		Outputs an error message.
	* Parameters
		buf - The error message to be output.
	* Return Value
		0

print(buf)
	* Description
		Outputs to the standard output.
	* Parameters
		buf - The string to be output.
	* Return Value
		0

input()
	* Description
		Reads from the standard input.
	* Parameters
		None
	* Return Value
		The input string.

isType(val)
	* Description
		Obtains the type of the given variable.
	* Parameters
		val - The variable whose type is to be determined.
	* Return Value
		0 - Integer type
		1 - Real number type
		2 - String type
		3 - Array

length(data)
	* Description
		Obtains the length of an array or a string.
	* Parameters
		data - The array or string whose length is to be determined. If a number is provided, it is converted to a string.
	* Return Value
		The length of the array or string as an integer.

array(buf)
	* Description
		Expands a string into an array.
	* Parameters
		buf - The string to be expanded. If a number is provided, it is converted to a string.
	* Return Value
		An array with each character of the string as an individual element.

string(list)
	* Description
		Converts an array to a string.
	* Parameters
		list[] - The array to be converted. If a number is provided, it is also converted to a string.
	* Return Value
		The resulting string after conversion.

number(str)
	* Description
		Converts a string to a numeric value (either integer or real number).
	* Parameters
		str - The string to be converted to a number.
	* Return Value
		The numeric value after conversion.

int(str)
	* Description
		Converts a string to integer value.
		Numbers exceeding 4 bytes are truncated.
	* Parameters
		str - String to be converted to an integer.
	* Return Value
		The integer value after conversion.

code(buf, index = 0)
	* Description
		Obtains the character code of a specified position in a string.
	* Parameters
		buf - String to get character code.
		index - Character position, 0 if omitted.
	* Return Value
		Character code of the specified position.
		Returns 0 if index exceeds the number of characters.

char(i)
	* Description
		Converting character codes to strings
	* Parameters
		i - Character codes to be converted
	* Return Value
		Converted string

getKey(list[], n)
	* Description
		Get the key name of an array.
		The third key in list[] is getKey(list[], 3)
	* Parameters
		list[] - Array
		n - Index (Integer value)
	* Return Value
		Key name(String)

setKey(&list[], n, key)
	* Description
		Set array key name.
		The third key in list[] is setKey(list[], 3, "name")
	* Parameters
		list[] - Array
		n - Index (Integer value)
		key - Key name to set (string)
	* Return Value
		0

--
Copyright (C) 1996-2023 by Ohno Tomoaki. All rights reserved.
    WEB SITE: https://www.nakka.com/
    E-MAIL: nakka@nakka.com