Update page 'P# 1.0 Draft Specification'

2018-07-19 10:05:07 +02:00
parent 31011fa36e
commit c5e4a5fa0a

@@ -68,7 +68,7 @@ A semicolon is used to mark the end of a statement in P# language. It is mandato
A variable is an identifier, which holds a value. In programming we say that we assign a value to a variable. Technically speaking, a variable is a reference to a computer memory, where the value is stored. In P# language, a variable can hold a string, a number, or various objects like a function or a class. Variables can be assigned different values over time. Variables in P# consist of the $ character, called a sigil, and a label. A label can be created from alphanumeric characters and an underscore _ character. A variable cannot begin with a number.
#### 3.3.6 P# Constants
A constant is an identifier for a value which cannot change during the execution of the script. Constants are created with the define() function. Constants differ from variables; we cannot assign a different value to an existing constant.
A constant is an identifier for a value which cannot change during the execution of the script. Constants are created with the define() function. Constants differ from variables; is is impossible to assign a different value to an existing constant.
## 4. Basic concept
TODO
@@ -193,7 +193,7 @@ If the string is enclosed in double-quotes, P# will interpret the following esca
When a string is specified in double quotes, variables are also parsed within it.
### 5.10. Void Values
Void is an empty data type and it is used as a return type of functions and methods that return no value.
Void is an empty data type and it is used as a return type of functions and methods that return no value. It is possible to declare a variable of void type, but it cannot store any value.
### 5.11. Null Values
Null is a special data type. Basically, the data type means non existent, not known or empty. In P#, a variable is NULL in three cases:
@@ -498,20 +498,18 @@ Above example prints a list of numbers that cannot be divided by 2 without a rem
## 8. Functions
P# is fully object-oriented programming language. However, it has a support for built-in functions. The built-in functions are part of the P# language.
## 9. Anonymous Functions
### 8.1. Anonymous Functions
Anonymous functions, also known as closures, allow the creation of functions which have no specified name. In P#, anonymous function arguments can take a default value exactly like standard function arguments. The default value associated with the function argument can be any complex expression including function calls.
<%
callback $anon = void(string $msg = 'Hello' + ' ' + 'World!' /* Complex expression */){
print($msg + PS_EOL);
}; // semicolon is required here
$anon(); // You should see 'Hello World!'
$anon('Welcome guest!'); //You should see 'Welcome guest!'
%>
callback $anon = void(string $msg = 'Hello' + ' ' + 'World!' /* Complex expression */){
print($msg + PS_EOL);
}; // semicolon is required here
$anon(); // You should see 'Hello World!'
$anon('Welcome guest!'); //You should see 'Welcome guest!'
Anonymous function can be defined in a method body.
## 10. Static Variables & Constant
## 9. Static Variables & Constant
P# lets use any complex expressions including method calls as an initialization values for your static variables and constants.
public void test() {
@@ -532,274 +530,248 @@ P# lets use any complex expressions including method calls as an initialization
In above example, the static variable $salt takes as its initialization value a random number between 0 and 1023 inclusive generated by the built-in rand() function while the constant MY_CONST takes at its initialization value a random string generated by the built-in rand_str() function. Also note that the 'const' construct can be used outside a class definition.
## 11. Object-Oriented Programming
## 10. Object-Oriented Programming
There are three widely used programming paradigms there: procedural programming, functional programming, and object-oriented programming. P# supports only object-oriented programming (OOP). This is a programming paradigm that uses objects and their interactions to design applications and computer programs. The basic programming concepts in OOP are:
* Abstraction
* Polymorphism
* Encapsulation
* Inheritance
### 11.1. Objects in P\#
### 10.1. Objects in P\#
Objects are basic building blocks of a P# script. An object is a combination of data and methods. In a OOP program, we create objects. These objects communicate together through methods. Each object can receive messages, send messages, and process data. There are two steps in creating an object. First, a class needs to be defined. A class is a template for an object. It is a blueprint which describes the state and behavior that the objects of the class all share. A class can be used to create many objects. Objects created at runtime from a class are called instances of that particular class.
class Demo { }
object $demo_object = new Demo();
### 11.2. Object Attributes
### 10.2. Object Attributes
Object attributes are the data bundled in an instance of a class. The object attributes are called instance variables or member fields. An instance variable is a variable defined in a class, for which each object in the class has a separate copy.
<%
class Person {
public string $name = '';
class Person {
public string $name = '';
}
class Main {
public void __construct() {
object $person1, $person2;
$person1 = new Person();
$person2 = new Person();
$person1->name = "John";
$person2->name = "Olivier";
print("Hello $person1->name and $person2->name");
}
object $person1, $person2;
$person1 = new Person();
$person2 = new Person();
$person1->name = "John";
$person2->name = "Olivier";
print("Hello $person1->name and $person2->name");
%>
}
In example above Person class contains one attribute - $name. This class has been instantiated twice and both objects contains different data stored.
### 11.3. Methods
### 10.3. Methods
Methods are functions defined inside the body of a class. They are used to perform operations with the attributes of objects. Methods are essential in encapsulation concept of the OOP paradigm.
<%
class Circle {
private float $radius;
class Circle {
private float $radius;
public void setRadius($radius) {
$this->radius = $radius;
}
public float area() {
return $this->radius * $this->radius * 3.14;
}
public void setRadius($radius) {
$this->radius = $radius;
}
object $c = new Circle();
$c->setRadius(5);
print('Area is: ' . $c->area());
%>
public float area() {
return $this->radius * $this->radius * 3.14;
}
}
class Main {
public void __construct() {
object $c = new Circle();
$c->setRadius(5);
print('Area is: ' . $c->area());
}
}
Example above shows a Circle class. It contains one member field. It is the radius of the circle. The private keyword is an access specifier. It tells that the variable is accessible only from inside of the class. There are also 2 methods definition: area() and setRadius(). The $this keyword is a special variable which is used to access the member fields from methods. The area() method returns the area of a circle.
#### 11.3.1 Return Keyword
#### 10.3.1 Return Keyword
The return keyword is used to return a value from the method. A method may or may not return a value.
#### 11.3.2 Method Arguments
#### 10.3.2 Method Arguments
Most methods accept arguments. Arguments are values that are sent to the method. The methods process the values and possibly return some outcome.
<%
void myFunc(string $who) {
print('Hello ' + $who + ' from my first function!');
}
void myFunc(string $who) {
print('Hello ' + $who + ' from my first function!');
}
%>
#### 11.3.3 Implicit Values
#### 10.3.3 Implicit Values
The arguments in P# methods may have implicit values. An implicit value is used if no value is provided. P# lets use any complex expressions including built-in function or method calls, math or string expressions and so on as a default values for function arguments.
<%
void test(string $name = 'P# ' + rand_str(4), int $age = 10 * 2 + 5) {
print("Name = $name\n");
print("Age = $age\n");
}
%>
void test(string $name = 'P# ' + rand_str(4), int $age = 10 * 2 + 5) {
print("Name = $name\n");
print("Age = $age\n");
}
### 11.4. Access Modifiers
### 10.4. Access Modifiers
Access modifiers set the visibility of methods and member fields. P# implements three access modifiers: public, protected, and private. The public members can be accessed from anywhere. The protected members can be accessed only within the class itself and by inherited and parent classes. The private members may only be accessed by the class that defines the member. Access modifiers protect data against accidental modifications. They make the programs more robust.
<%
class DemoClass {
public float $real;
protected string $text;
private int $age;
}
class DemoClass {
public float $real;
protected string $text;
private int $age;
}
class Demo extends DemoClass {}
%>
class Demo extends DemoClass {}
In the above script, there are three member fields; one is declared public, second protected and the last as private. Public visible attribute can be modified from anywhere. Protected argument, from DemoClass and Demo classes. Private argument can be modified only from DemoClass.
If there is no access modifier specified, public is assumed.
### 11.5. Method Overloading
### 10.5. Method Overloading
Method overloading allows the creation of several methods with the same name which differ from each other in the type of the input. P# implements a method overloading, well-known from languages like C#, Java or C++.
<%
virtual class Test {
virtual void function test();
virtual void function test(int $var);
}
%>
virtual class Test {
virtual void function test();
virtual void function test(int $var);
}
### 11.6. Constructors & Destructors
### 10.6. Constructors & Destructors
A constructor and destructor are a special kind of methods. Copnstructor is automatically called when the object is created. The purpose of the constructor is to initiate the state of the object. Destructor is automatically called when object is destroyed. The purpose of destructor is to close open handles (eg. close database connection).
<%
class Demo {
public void __construct() {
}
public void __destruct() {
}
class Demo {
public void __construct() {
}
%>
public void __destruct() {
}
}
Both constructor and destructor methods cannot return any value. Declaring a constructor with access modifier other to public will make the class uninstantiable, as it will be unable call private or protected method from outside this class. Solution to this can be some additional method that will return instantiate the object and return it:
<%
class Demo {
private void __construct() {
}
public object instance() {
return new Demo();
}
class Demo {
private void __construct() {
}
%>
### 11.7. Constructor Overloading
public object instance() {
return new Demo();
}
}
### 10.7. Constructor Overloading
P# supports constructor overloading like any other method.
### 11.8. Scope Resolution Operator
### 10.8. Scope Resolution Operator
In computer programming, scope is an enclosing context where values and expressions are associated. The scope resolution operator helps to identify and specify the context to which an identifier refers, particularly by specifying a namespace. The specific uses vary across different programming languages with the notions of scoping. In P# language the scope resolution operator is written "::".
### 11.9. Inheritance
### 10.9. Inheritance
The inheritance is a way to form new classes using classes that have already been defined. The newly formed classes are called derived classes, the classes that we derive from are called base classes. Important benefits of inheritance are code reuse and reduction of complexity of a program. The derived classes (descendants) override or extend the functionality of base classes (ancestors).
<%
class Base {
void __construct() {
print('World!');
}
class Base {
void __construct() {
print('World!');
}
}
class Derived extends Base {
void __construct() {
print('Hello ');
parent::__construct();
}
class Derived extends Base {
void __construct() {
print('Hello ');
parent::__construct();
}
%>
}
In this script, there are two classes: a Base class and a Derived class. The Derived class inherits from the Base class. In P#, the extends keyword is used to create inheritance relations. In the constructor of the Derived class, we call the parent constructor. We use the parent keyword, followed by two colons and a method name. The constructors of the parent classes must be called explicitly. Output od the above example is "Hello World!'.
Additionally, P# supports multiple inheritance:
<%
class Base1 {}
class Base2 {}
class Derived extends Base1, Base2 {}
%>
class Base1 {}
class Base2 {}
class Derived extends Base1, Base2 {}
Above code could be also written in the following way:
<%
class Base1 {}
class Base2 extends Base1 {}
Class Derived extends Base2{}
%>
class Base1 {}
class Base2 extends Base1 {}
Class Derived extends Base2{}
### 11.10. Virtual Classes & Methods
### 10.10. Virtual Classes & Methods
Virtual classes cannot be instantiated. If a class contains at least one virtual method, it must be declared virtual too. Virtual methods cannot be implemented, they merely declare the methods' signatures. When a class inherits from a virtual class, all virtual methods must be implemented by the derived class. Furthermore, these methods must be declared with the same or with a less restricted visibility.
Unlike interfaces, virtual classes may have methods with full implementation and may also have defined member fields. So virtual classes may provide a partial implementation.
<%
virtual class Drawing {
protected int $x = 0;
protected int $y = 0;
virtual class Drawing {
protected int $x = 0;
protected int $y = 0;
public abstract float area();
public abstract float area();
public void getCoordinates() {
print("\$x is $this->x\n");
print("\$y is $this->y\n");
}
public void getCoordinates() {
print("\$x is $this->x\n");
print("\$y is $this->y\n");
}
}
class Circle extends Drawing {
private int $radius;
public void __construct(int $x, int $y, int $r) {
$this->radius = $r;
$this->x = $x;
$this->y = $y;
}
class Circle extends Drawing {
private int $radius;
public void __construct(int $x, int $y, int $r) {
$this->radius = $r;
$this->x = $x;
$this->y = $y;
}
public float area() {
return $this->radius * $this->radius * 3.14;
}
public float area() {
return $this->radius * $this->radius * 3.14;
}
%>
}
### 11.11. Magic Methods
### 10.11. Magic Methods
When the print keyword is used with the object instance, the \__toString() magic method is called.
### 11.12. Class Constants
### 10.12. Class Constants
P# enables to create class constants. These constants do not belong to a concrete object. They belong to the class.
<%
class Math {
public const float PI = 3.14159265359;
class Math {
public const float PI = 3.14159265359;
public float getPI() {
print(self::PI);
}
public float getPI() {
print(self::PI);
}
%>
}
In above example, the const keyword is used to define a constant. Class constants are accessed from within methods using the self keyword followed by two colons.
### 11.13. Static Keyword
### 10.13. Static Keyword
P# allows to declare class properties and methods to be static. The static properties and methods do not belong to the instance of the class. They belong to the class itself. They are accessible through the scope resolution operator.
### 11.14. Final Keyword
### 10.14. Final Keyword
Final methods cannot be overridden and final classes cannot be extended. The final keyword is a matter of design of the application. Some classes should not be extended and some methods should not be overridden. This behaviour is enforced by the final keyword.
### 11.15. Instanceof Keyword
### 10.15. Instanceof Keyword
The instanceof keyword is used to determine whether a variable is an instantiated object of a certain class.
<%
object $obj = new MyClass();
if($obj instanceof MyClass) {
print("\$obj is instance of MyClass");
}
%>
object $obj = new MyClass();
if($obj instanceof MyClass) {
print("\$obj is instance of MyClass");
}
### 11.16. Interfaces
### 10.16. Interfaces
Object interfaces allow to create code which specifies which methods a class must implement, without having to define how these methods are implemented. Interfaces are defined in the same way as a class, but with the interface keyword replacing the class keyword and without any of the methods having their contents defined. All methods declared in an interface must be public; this is the nature of an interface. Note that it is possible to declare a constructor in an interface, what can be useful in some contexts, e.g. for use by factories.
<%
interface MyInterface {
public void myFunction();
}
interface MyInterface {
public void myFunction();
}
class MyClass implements MyInterface {
public void myFunction() {
}
class MyClass implements MyInterface {
public void myFunction() {
}
%>
}
### 11.17. Exceptions
### 10.17. Exceptions
Exceptions are designed to handle the occurrence of exceptions, special conditions that change the normal flow of program execution. Exceptions are raised or thrown and initiated. During the execution of script, many things might go wrong. A disk might get full and it might be unable to save a file. An Internet connection might go down while script tries to connect to a site. All these might result in a crash. To prevent happening this, script must cope with all possible errors that might occur. For this, thee exception handling can be used.
<%
try {
// some code to execute
} catch(Exception $e) {
// code to execute when Exception is thrown
} finally {
// code to execute regardless of whether an exception has been thrown
}
%>
try {
// some code to execute
} catch(Exception $e) {
// code to execute when Exception is thrown
} finally {
// code to execute regardless of whether an exception has been thrown
}
#### 11.17.1. Catch Block
#### 10.17.1. Catch Block
Multiple catch blocks can be used to catch different classes of exceptions. Normal execution (when no exception is thrown within the try block) will continue after that last catch block defined in sequence. Exceptions can be thrown (or re-thrown) within a catch block.
#### 11.17.2 Finally Block
#### 10.17.2 Finally Block
A finally block may also be specified after or instead of catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.