Chapter 4. Identifiers, Types, Objects and Classes

Table of Contents

1. The IsDef and Undef Methods

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).

What class are you?

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.

1. The IsDef and Undef Methods

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.