Table of Contents
All Biferno identifiers, including names of variables, constants, functions, classes and language keywords, do not start with special characters, unlike other scripting languages. This design choice is possible because the Biferno code is always separated from the rest of the text on the page (HTML or other languages).
Biferno is case sensitive, i.e. uppercase characters are considered
different from lowercase characters. The identifiers myString and MyString
are different.
In Biferno every entity that can hold data has an identifier (its name), a type, a class, and a scope, which determines the code region in which a reference to the entity is legal. The scope is discussed in detail in Chapter 9, Applications and Variable Scope.
The "type" of an entity defines the entity to be a variable or a constant. A variable holds a value that can be modified at runtime by the program that is being executed. A constant has a value that can not be modified at runtime by the program that is being executed.
We have already seen an example of variable initialization. To declare a Biferno variable one can simply use its identifier followed by the assign operator (=), followed by a value or expression. The keyword var before the variable identifier can be used, but it is optional.
To declare a constant, the use of the const keyword before its name is
mandatory:
<?
var a = 1 // the var keyword is optional
const b = 1024
?>
The main characteristics of object oriented languages, including Biferno, is the use of the "object" and "class" concepts.
A class can be defined as the union of a data structure (a set of variables), called the “properties” of the class, and of the operations that can be executed on the properties, the “methods” of the class. Properties and methods of a class are referred to as the “members” of the class. An object is an entity that has the structure of the class it belongs to and contains its own values for each of its properties. An object is created in a program and then manipulated using the methods and properties defined by the class it belongs to. We can also say that an object is an instance of a class. All variables and constants in Biferno are objects and therefore instances of a class. In Biferno there is a direct correspondence between a variable and the object created when the variable is initialized. For sake of simplicity we will refer in the following indifferently to the variable or the object, as if they were the same entity.
What determines the class a variable belongs to? Usually the data type that is assigned to the variable, as in the following example:
<? a = "Hello" //String class variable b = 1 // Int class variable c = 1.5 // Double class variable d = true // Boolean class variable e = a // String class variable ?>
It is also possible to explicitly assign a class to a variable when the variable is declared. This is done by following the assign operator with the identifier of the class, followed by the value that is to be assigned to variable enclosed in parenthesis. This syntax is equivalent to calling the constructor method of the class (constructor methods are discussed in Chapter 11, User classes).
<? a = 12 // Integer class variable with value 12 b = string(a) // String class variable with value "12" c = double(b) // Double class variable with value 12 d = int(b) // Int class variable with value 12 e = boolean(c) // Boolean class variable with value true ?>
The following is also correct:
<?
f = double("1.936,27") // Double class variable
// with value 1936.27
?>
This implies that the double class constructor automatically attempts to
convert strings containing numbers to real numbers, using the default
separator characters "," and ".". We will see later that a number of
separator combinations can be used in Biferno. Notice that it is mandatory
to use the decimal point character as the comma separator in literal strings representing real numbers (as in: a = 1.5).
An alternative is the use of a similar technique, called “TypeCast”, which consists in following the assign operator with the class identifier before the value or expression to be assigned. Using typecasting, the last example can be rewritten as:
<? a = 12 b = (string)a c = (double)b d = (int)b e = (boolean)c f = (double)"1.936,27" ?>
Once initialized, a variable belongs to the same class during its entire
lifetime, except when the "curScript.Undef" method is used, as we will see in the
following.
If a variable belongs to a class, all methods and properties of that class
can be applied to the variable. Method and property identifiers must be
separated from the variable (or class) name by a colon. E.g., by writing
myString.length we invoke a property of the string class called length that
contains the value of the length (number of characters) of the string
contained in myString. Methods behave similarly to functions in procedural
programming language, such as the C language. Methods can accept one or more
parameters and are always followed by a pair of parentheses when invoked.
E.g., by writing myString.Encode() we are applying to the myString variable
the Encode method of the string class (the meaning of this method will be
defined later).
If we are not certain of the class a variable belongs to, we can ask the
variable about the value of its class property, which is defined by
default. In the example above, a.class returns the "int" string. The class
property is read only.
If we need to know if a variable is defined or undefined, we can use the
curScript.IsDef predefined Biferno static method, with prototype:
boolean curScript.IsDef(string name)
This method requires a string called name as a parameter and returns the true value if a variable with identifier name exists, or false if no variable with identifier name exists:
<?
if (curScript.IsDef("myVar"))
print(myVar)
?>
The predefined static method curScript.Undef with prototype
void curScript.Undef(obj variable)
requires as a parameter an object identifier, i.e. a variable belonging to any class. The supplied object is made undefined and it will behave from now on as if it was have never defined. The Undef function returns void.
<?
curScript.Undef(myVar)
?>
Notice that the curScript.IsDef method, unlike curScript.Undef, does not take an object as
parameter, but rather a string containing the object name. This avoids an
error condition if the variable has never been defined. In the case of the
curScript.Undef method, an error condition should occur, because it is not legal to
invoke Undef on an undefined object. To validate the parameter to Undef, a
code fragment code similar to the following can be used:
<?
if (curScript.IsDef("myVar"))
curScript.Undef(myVar)
?>
A last remark: The Undef function cannot be used on "literal" variables or
on the result of an operation. The code fragments:
<?
curScript.Undef("foo") // error Err_IllegalUndef!
?>
and
<?
curScript.Undef(a + b) // error Err_IllegalUndef!
?>
both generate the Err_IllegalUndef error.