All data types used in Fore are derivatives from the Object object type. The object type is used to create a link to an object. The object type is a structure consisting of a fixed number of components. Each component is either a field, containing data of a certain type, or a method, processing the object. Just as for variables, the field description defines this field data type and field identifier; just as for procedures and functions, the method description defines the procedure, function, constructor, or destructor title.
The object type may inherit the other object type components. If T2 inherits from T1, the T2 is a descendant and T1 is a parent.
The inheritance procedure is transitive, which means that if T3 inherits from T2, and T2 inherits from T1, then T3 inherits from T1. The object type consists of the object itself and all of its descendants.
The following relation operators are available for two variables within objects (or references to objects): equal (=) and not equal (<>). The operation result is a logical value displaying the equality or inequality of two objects.
Class TestClass: Object
Public i: Integer;
Public Constructor Create(Value: Integer);
Begin
i := Value;
End Constructor Create;
End Class TestClass;
Sub SampleObject;
Var
o: Object;
Begin
o := Integer.MaxValue;
Debug.WriteLine(o);
o := "Program";
Debug.WriteLine(o);
o := New TestClass.Create(100);
If o Is TestClass Then
Debug.WriteLine((o As TestClass).i);
End If;
End Sub SampleObject;
Fore language data types can be grouped depending on whether the variables of a type store their data or point to them. A data type is a value type if it contains data within its memory space. The reference type contains a pointer to another memory space with data.
IMPORTANT. On describing, a custom class must inherit from any existing class or the Object basic class. Inheritance of classes of the Fore basic types is forbidden.
The logical data type consists of two logical values: True (truth) and False (lie).
Logical operators and relation operators are available for two logical variables. The NOT unary operator is also available for a logical variable.
Example:
Sub SampleBoolean;
Var
b: Boolean;
Begin
b := True;
Debug.WriteLine(b);
b := 1 < 0;
Debug.WriteLine(b);
b := Boolean.Parse("TRUE");
Debug.WriteLine(b);
b := Not b;
Debug.WriteLine(b);
End Sub SampleBoolean;
The Char type variables include one Unicode character. A double-byte number between 0 and 65535 corresponds to each character. To access the Char type constants, use the Char.Chr property or the #Code combination.
NOTE. Constants enclosed in double quotation marks are determined by the String ("Any text") type, and constants enclosed in apostrophes are determined by the Char ('A') type. Control character with 0 (#0) code in the Fore language is handled as the end of the string. All following characters will be truncated.
Relation operators and arithmetic operators of summation (+) are available for two character variables. The result of two character variables summation is a string value.
Example:
Sub SampleChar;
Var
c1, c2: Char;
s: String;
Begin
c1 := Char.Chr(163); //Franc sign - ₣
c2 := #8364; //Euro sign - €
s := "Franc: " + c1 + ". Euro: " + c2;
Debug.WriteLine(s);
End Sub SampleChar;
The Currency type variables (currency values) are stored as 64-bit (8-byte) integer numbers, which after division by 10000 give a number with a fixed decimal point: with 15 bits in the integer part, and 4 bits in the fractional part. Such a manner of representation enables the user to display numbers from -922 337 203 685 477.5808 up to 922 337 203 685 477.5807. The Currency data type is used for currency calculations and calculations of values with a fixed decimal point to provide high accuracy.
Relation operators and the arithmetic operators *, +, - are available for two variables with the currency data type. The result of arithmetic operations is the value of currency type.
Example:
Sub SampleCurrency;
Var
c: Currency;
Begin
c := 1.123;
Debug.WriteLine(c);
c := 1.123E-4;
Debug.WriteLine(c);
c := Currency.Parse("1.123");
Debug.WriteLine(c);
c := Currency.MaxValue;
Debug.WriteLine(c);
c := 1 / 3;
Debug.WriteLine(c);
End Sub SampleCurrency;
The DateTime data type is used to store date and time. Value of variables of the DateTime type is date and time within the range from 00:00:00 1 January 100 (A.D.) to 23:59:59 31 December 9999 (A.D.). If the date that is less than a valid one is specified, the date automatically includes the current century. For example, if the date 1 January 30 is specified, the date 1 January 2030 is automatically generated.
Relation operators and arithmetic operators of addition (+) and subtraction (-) are available for two variables including date and time. The result of summation operation is a value of the DateTime type; the result of subtraction operation is a value of the TimeSpan type.
Example:
Sub SampleDateTime;
Var
d, d1, d2, d3: DateTime;
Begin
d := DateTime.Now;
d1 := DateTime.AddYears(d, -1);
d2 := DateTime.ComposeDay(2000, 1, 1);
d3 := DateTime.Parse("01.01.2005 18:00:00");
End Sub SampleDateTime;
The Decimal type variables are stored as 16-byte integer numbers (negative and positive) scaled with a variable coefficient, which is a power of 10. The scale factor defines the number of digits after the delimiter (in the range from 0 to 28). For the zero scale (decimal fraction is absent) the maximum available value is +/-79 228 162 514 264 337 593 543 950 335. For a 28 bits number the maximum available value is +/-7.9228162514264337593543950335, and the minimum non-zero value is +/-0.0000000000000000000000000001 (+/-1E-28).
Numbers of the Decimal type can be indicated with the m or M suffix: 1.123m, 1.123e10m, 1.123E-10M. Numbers without the suffix are considered as real numbers; if they are assigned to the variable of the Decimal type, the compilation error "The Decimal and the Double types are not compatible" occurs. In this case it is required to use explicit conversion by means of the As statement.
NOTE. Data sources, which use the Decimal data type and created in Prognoz Platform versions, may not be supported in later versions. A data source may require to be recreated.
Relation operators and the arithmetic operators *, +, -, / are available for two variables of the Decimal type. The result of arithmetic operations is a value of the Decimal type.
Example:
Sub SampleDecimal;
Var
d: Decimal;
Begin
d := 1.123m;
d := 1.123E-10M;
d := Decimal.Parse("1.123");
d := Decimal.MaxValue;
End Sub SampleDecimal;
For variables that are number with floatpoint, the Double data type or real data type is used.
A type is a number of double accuracy with a floating point and the sign in the range of - 5.0 x 10^-324 .. 1.7 x 10^308 (8 bytes) (15-16 digits). Big values can be specified using exponential writing of numbers, for example, 1 000 000 = 1e6, 0.000015 = 1.5E-5.
Relation operators and the arithmetic operators *, +, -, / are available for two variables of the real type. The result of arithmetic operations are real-type values.
Example:
Sub SampleDouble;
Var
d: Double;
Begin
d := 1.123;
d := 1.123E3;
d := 1.5E-5;
d := Double.Parse("1.123");
d := Double.MaxValue;
End Sub SampleDouble;
For variables that are integer numbers, the Integer data type or the integer data type is used.
The type is a 32-bit (4 byte) integer with a sign in the range -2147483648..2147483647. 0-31 places are occupied with the number itself, 32 place is used to store a sign.
Relation operators, all arithmetic operators and logical operators are available for two integer variables. The result of arithmetic operations are integer type values except for division operator (/). The result of division is a real number. Logical operators are executed by converting a decimal number to the binary form. The operation result is reconverted to the decimal form.
Example:
Sub SampleInteger;
Var
i: Integer;
Begin
i := 1;
i := Integer.Parse("12345");
i := Integer.MaxValue;
End Sub SampleInteger;
The TimeSpan data type is a time interval. It is used to calculate a time interval. The methods of the object with the TimeSpan type initialize it basing on various measurement units (hours, minutes, seconds, beats, etc.). The subtraction, summation, and comparison operations are only available for TimeSpan objects.
Relation operators are available for two variables containing time.
Example:
Sub SampleTimeSpan;
Var
d1, d2: DateTime;
t: TimeSpan;
Begin
d1 := DateTime.Now;
Debug.WriteLine(d1);
t := TimeSpan.Compose(5, 10, 15, 1, 1);
d2 := DateTime.Add(d1, t);
Debug.WriteLine(d2);
Debug.WriteLine(t.Hours);
Debug.WriteLine(t.TotalHours);
End Sub SampleTimeSpan;
The Variant data type is used to describe the variables, for which it is not possible to define a data type, which will be stored in these variables during compilation. The data type stored in these variables may be changed during program execution. Any variable can be assigned and then taken from the Variant variable type. The object link may be stored in this variable.
It is important to note that Variant type variables are large and it takes much more time to process them, in comparison with variables of other types. This is because the Variant type variables store the variable value and information about the value type.
Default value of the Variant type variable is Null. This value means that this variable has no data.
When getting values from the variable of the Variant type and assigning this variable value having the definite type, the ability to transform to this type is checked. If the implicit conversion is available, the value will be set, otherwise an exception is thrown.
Sub Sample;
Var
s: String;
d: DateTime;
d1: Double;
i: Integer;
v: Variant;
Begin
s := "2000.01.01 12:00:00";
v := s;
d := v;
Debug.WriteLine(d.Date.ToString + " " + d.TimeOfDay.Hour.ToString);
d1 := 3.14;
v := d1;
i := v;
Debug.WriteLine(i);
End Sub Sample;
Implicit conversion can be executed not only between simple values types but also between system types and types determined in the application code. At the same time, if the transformation is available, the object reference, which is saved in the Variant type variable, will be available in the output variable.
Sub Sample1;
Var
b: IButton;
c: IControl;
v: Variant;
Begin
b := New Button.Create;
b.Text := "Button";
v := b;
c := v;
Debug.WriteLine(c.Text);
End Sub Sample1;
The implicit conversion is implemented in Fore on using variables of the Variant type in the If and ?: statements.
Sub Sample2;
Var
v: Variant;
Begin
v := True;
If v Then
Debug.WriteLine("TRUE");
Else
Debug.WriteLine("FALSE");
End If;
v := Math.RandBetweenI(0, 100);
Debug.WriteLine(v > 50 ? "Greater than 50" : "Less than 50");
End Sub Sample2;
An explicit conversion requires the As statement. The explicit conversion is used when data loss is possible during conversion or when the conversion may result in an exception due to some reasons. The Is statement can be used to check if the explicit conversion is possible.
Sub ConvertFromVariant;
Var
v: Variant;
i: Integer;
d: Double;
d1: DateTime;
s: String;
b: Boolean;
Begin
v := 21.9;
b := v Is Integer; //True
b := v Is Double; //True
b := v Is DateTime; //True
b := v Is String; //True
b := v Is Boolean; //True
i := v As Integer; //22
d := v As Double; //21,9 (NOTE: decimal separator depends on operating system settings)
d1 := v As DateTime; //20.01.1900 21:36:00
s := v As String; //"21.9"
b := v As Boolean; //True
End Sub ConvertFromVariant;
All operations defined in the Fore language are available for variables of the Variant type. The type of output value depends on values stored in variables. If required, an implicit type transformation is executed before executing the operation. If the operation cannot be executed after transformations, an exception is thrown.
The String data type is a text as a sequence of Unicode characters. Each string is a structured array consisting of a zero or more Unicode characters (that is, 2-byte integers without sign) named string elements. String elements are numbered, starting with zero. String length is a number of its elements. An empty string contains no elements.
A string may contain up to 2 Gb of data.
NOTE. Constants enclosed into double quotes are defined as a String type ("Any text"), and constants enclosed into apostrophes are defined as a Char type ('A'). Inheritance of class of the String basic type is forbidden.
Summation operators ("+") and comparison operators (">", "<", ">=", "<=", "<>") are available for string variables. The result of summation of strings S and S1 is a new string, in which characters of the S1 string follow the characters of the S string.
The result of comparing two strings is a logical value. The operator of comparison is executed on numeric values of Unicode characters composing the string. The string with a larger sum of numeric values of the characters is considered to be larger.
To compare strings taking into account its syntax features (letters' case, order of characters) you can use one of the comparison objects available in the Comparer class.
If string contains text with quotes, then to display quotes in the string, it is required to double quote text, for example, "Any text ""Text""".
2 Gb is the maximum theoretically possible size that can be stored in string variables. This size is determined by the maximum string length specified for the String type (4 bytes). In reality, the maximum size of an expression stored in a string variable depends on the number of factors.
Operating systems reserve some operating memory for the system's own requirements and for the needs of custom applications. 32-bit processes use 32-bit pointers for addresses in virtual memory that an create absolute upper limit equal to 4 Gb (2 ^ 32 ). By default, 32-bit Windows OS divides the address space into two equal shares for the system and application, setting a limit of 2 Gb for each. (If you change the settings you can create the ratio 1/4 for the OS needs and 3/4 for the applications' requirements). 64-bit processes use 64-bit pointers, thus, their theoretical maximum address space is 16 exabytes (2^64). However, Windows does not divide the address space in equal parts between the active processes and the system but instead defines an area in the address space for processes and other system resources. In 64-bit Windows, custom applications can use address space of 8192 GB (8 TB).
The operating system reserves a continuous block of memory required for the work of each application. When some operations with data are executed, the system also reserves continuous blocks of memory for temporary variables used during the calculation.
Usually, the work of applications and services leads to memory fragmentation. As the result, the number and volume of available continuous blocks of memory is reduced. In those situations when an application reaches the limits of the available memory space or the operating system for some reasons cannot grant the required memory volume to this application, the exception "Not enough memory" is thrown.
All these restrictions result in the following: various computers using various operating systems have different available memory space that can be used by Foresight Analytics Platform. In this turn this restricts the maximum available size of data to be stored in variables. It is recommended to avoid operations where large amount of data is involved and optimize algorithms for working with separate parts of data.
Relation operators and arithmetic operators of addition (+) are available for two string variables. The result of summation of two strings is a string value.
Example:
Sub SampleString;
Var
s1, s2: String;
c: Char;
Begin
s1 := "Program";
s2 := "Pro" + "gram";
Debug.WriteLine(s1 = s2); //Compare strings by contents
Debug.WriteLine((s1 As Object) = (s2 As Object)); //Compare strings as two objects
c := s1.Chars(0);
s1 := "Sign" + Char.Chr(160) + #169; //160-code of the space, 169-code of the © sign
Debug.WriteLine(s1);
End Sub SampleString;
For variables that are integer numbers of big size, the Int64 data type is used.
The type is a 64-bit (8 bytes) integer number with a sign ranging from 9223372036854775808 to 9223372036854775807. Places 0-63 are occupied with the number itself, place 64 is used to store a sign.
To specify the numbers with the Int64 type, use the l or L suffix: 100000l, -10l. The numbers with the Integer type can be indirectly cast to the Int64 type.
Relation operators, all arithmetic operators and logical operators are available for two Int64 variables. The result of arithmetic operators are the Int64 type values except for division operator (/). The result of division is a real number. Logical operators are executed by converting a decimal number to the binary form. The operation result is reconverted to the decimal form.
Example:
Sub SampleInt64;
Var
i: Integer;
i64: Int64;
ar: Array Of Int64;
Begin
i := Integer.MaxValue;
i64 := Int64.MaxValue - i;
// Array
ar := New Int64[3];
ar[0] := i;
ar[1] := i64;
ar[2] := Int64.Parse("1234567890");
End Sub SampleInt64;
The Guid data type is unique global 128-bit identifiers. The uniqueness of identifiers enables users to apply them without risk of conflicts caused by identifiers matching.
As a text, the unique global identifier contains five parts divided by hyphen, contains 32 sexadecimal digits and inclosed by curved brackets: {2F9B6356-CA0D-4C59-B414-93E027DE207B}.
For automatic generation of unique global identifiers, use methods of the GuidGenerator class.
For two unique global identifiers, the following relation operations are available: '=' and '<>'.
Example:
Sub SampleGuid;
Var
guid_: Guid;
guidStr_: String;
Begin
guidStr_ := GuidGenerator.Generate;
guid_ := GuidGenerator.GenerateGUID;
Debug.WriteLine(guidStr_);
Debug.WriteLine(guid_);
// Compare obtained unique global identifiers
If guid_ <> Guid.Parse(guidStr_) Then
Debug.WriteLine("Unique");
Else
Debug.WriteLine("Not unique");
End If;
End Sub SampleGuid;
The Array type is used to store several objects of one type regarded as one unit, that is, an array. Array size may be defined either during array declaration (static array), or during array initialization in the program text (dynamic array). An array consisting of one dimension is named a vector; an array consisting of two dimensions is named a table; an array consisting of more then two dimensions is named a multidimensional array. To describe arrays, use the syntax described in the Arrays section. To work with arrays, use properties and methods implemented in the Array class.
NOTE. Inheritance from class of the Array basic type is forbidden.
Sub SampleArray;
Var
Arr1: Array[3] Of Char;
Arr2: Array Of Integer;
Arr3: Array;
v: Variant;
Begin
Arr2 := New Integer[3];
Arr3 := New Variant[3];
Arr1[0] := 'A';
Arr1[1] := 'B';
Arr1[2] := 'C';
Arr2[0] := 0;
Arr2[1] := 1;
Arr2[2] := 2;
Arr3[0] := Arr1[0] + Arr2[0].ToString;
Arr3[1] := Arr1[1] + Arr2[1].ToString;
Arr3[2] := Arr1[2] + Arr2[2].ToString;
For Each v In Arr3 Do
Debug.WriteLine(v);
End For;
End Sub SampleArray;
See also: