Expression Types

Every built-in assembler expression has a typeor, more correctly, a size, because the assembler regards the type of an expression simply as the size of its memory location. For example, the type of an Integer variable is four, because it occupies 4 bytes. The built-in assembler performs type checking whenever possible, so in the instructions the assembler checks that the size of QuitFlag is one a byte , and that the size of OutBufPtr is two a word . The instruction produces an error because DL...

Procedure Declarations

A procedure declaration has the form procedure procedureName parameterList directives result to I. Function calls cannot appear on the left side of an assignment syntax is enabled x , function calls - can be used as complete where procedureName is any valid identifier, statements is a sequence of statements that execute when the procedure is called, and parameterList , directives , and localDeclarations are optional. Here is an example of a procedure declaration Given this declaration, you can...

Method Resolution Clause

You can override the default name-based mappings by including method resolution clauses in a class declaration. When a class implements two or more interfaces that have identically named methods, use method resolution clauses to resolve the naming conflicts. A method resolution clause has the form procedure interface.interfaceMethod implementingMethod function interface.interfaceMethod implementingMethod where implementingMethod is a method declared in the class or one of its ancestors. The...

Automation Object MethodCall Syntax

The syntax of an Automation object method call or property access is similar to that of a normal method call or property access. Automation method calls, however, can use both positional and named parameters. But some Automation servers do not support named parameters. A positional parameter is simply an expression. A named parameter consists of a parameter identifier, followed by the symbol, followed by an expression. Positional parameters must precede any named parameters in a method call....

Message Methods

Message methods implement responses to dynamically dispatched messages. The message method syntax is supported on all platforms. VCL uses message methods to respond to Windows messages. A message method is created by including the message directive in a method declaration, followed by an integer constant between 1 and 49151 which specifies the message ID. For message methods in VCL controls, the integer constant can be one of the Win32 message IDs defined, along with corresponding record types,...

Open Array Constructors

Open array constructors allow you to construct arrays directly within function and procedure calls. They can be passed only as open array parameters or variant open array parameters. An open array constructor, like a set constructor, is a sequence of expressions separated by commas and enclosed in brackets. you could call the Add procedure with the statement Open array constructors can be passed only as value or const parameters. The expressions in a constructor must be assignment-compatible...

Procedural Types 1

On the Win32 platform, a procedure pointer is stored as a 32-bit pointer to the entry point of a procedure or function. A method pointer is stored as a 32-bit pointer to the entry point of a method, followed by a 32-bit pointer to an object. On the .NET platform, procedural types are implemented using the System.MulticastDelegate class types. Class Types The following discussion of the internal layout of class types applies to the Win32 platform only. On the .NET platform, class layout is...

Assignment Compatibility

Assignment-compatibility is not a symmetric relation. An expression of type T2 can be assigned to a variable of type T1 if the value of the expression falls in the range of T1 and at least one of the following conditions is satisfied. T1 and T2 are of the same type, and it is not a file type or structured type that contains a file type at any level. T1 and T2 are compatible ordinal types. T1 is a real type and T2 is an integer type. T1 is PChar, PWideChar or any string type and the expression...

Variant Type Conversions

All integer, real, string, character, and Boolean types are assignment-compatible with Variant. Expressions can be explicitly cast as variants, and the VarAsType and VarCast standard routines can be used to change the internal representation of a variant. The following code demonstrates the use of variants and some of the automatic conversions performed when variants are mixed with other types. The compiler performs type conversions according to the following rules. converts to string...

Short String Types

A string occupies as many bytes as its maximum length plus one. The first byte contains the current dynamic length of the string, and the following bytes contain the characters of the string. The length byte and the characters are considered unsigned values. Maximum string length is 255 characters plus a length byte string 255 . Note On the .NET platform, the short string type is implemented as an array of unsigned bytes. Long String Types A long string variable occupies four bytes of memory...

Operands

Inline assembler operands are expressions that consist of constants, registers, symbols, and operators. Within operands, the following reserved words have predefined meanings Built-in assembler reserved words Reserved words always take precedence over user-defined identifiers. For example, loads 1 into the CH register, not into the Ch variable. To access a user-defined symbol with the same name as a reserved word, you must use the ampersand amp override operator It is best to avoid user-defined...

Dynamic Array Types

On the Win32 platform, a dynamic-array variable occupies four bytes of memory which contain a pointer to the dynamically allocated array. When the variable is empty uninitialized or holds a zero-length array, the pointer is nil and no dynamic memory is associated with the variable. For a nonempty array, the variable points to a dynamically allocated block of memory that contains the array in addition to a 32-bit length indicator and a 32-bit reference count. The table below shows the layout of...

Forward and Interface Declarations

The forward directive replaces the block, including local variable declarations and statements, in a procedure or function declaration. For example, function Calculate X, Y Integer Real forward declares a function called Calculate. Somewhere after the forward declaration, the routine must be redeclared in a defining declaration that includes a block. The defining declaration for Calculate might look like this Ordinarily, a defining declaration does not have to repeat the routine's parameter...

Storage Specifiers

The optional stored, default, and nodefault directives are called storage specifiers. They have no effect on program behavior, but control whether or not to save the values of published properties in form files. The stored directive must be followed by True, False, the name of a Boolean field, or the name of a parameterless method that returns a Boolean value. For example, property Name TComponentName read FName write SetName stored False If a property has no stored directive, it is treated as...

Internal Data Formats

The following topics describe the internal formats of Delphi data types. Integer Types The format of an integer-type variable depends on its minimum and maximum bounds. lf both bounds are within the range 128 127 Shortint , the variable is stored as a signed byte. lf both bounds are within the range 0 255 Byte , the variable is stored as an unsigned byte. lf both bounds are within the range 32768 32767 Smallint , the variable is stored as a signed word. lf both bounds are within the range 0...

Operator Precedence

In complex expressions, rules of precedence determine the order in which operations are performed. Precedence of operators , , div, mod, and, shl, shr, as second , lt gt , lt , gt , lt , gt , in, is fourth lowest An operator with higher precedence is evaluated before an operator with lower precedence, while operators of equal precedence associate to the left. Hence the expression multiplies y times z, then adds X to the result is performed first, because is has a higher precedence than . But...

Library Initialization Code

The statements in a library's block constitute the library's initialization code. These statements are executed once every time the library is loaded. They typically perform tasks like registering window classes and initializing variables. Library initialization code can also install an entry point procedure using the DllProc variable. The DllProc variable is similar to an exit procedure, which is described in Exit procedures the entry point procedure executes when the library is loaded or...

Program Control 1

The concepts of passing parameters and function result processing are important to understand before you undertake your application projects Treatment of parameters and function results is determined by several factors, including calling conventions, parameter semantics, and the type and size of the value being passed. This following topics are covered in this material Understanding Exit Procedures.

Array Constants

To declare an array constant, enclose the values of the array's elements, separated by commas, in parentheses at the end of the declaration. These values must be represented by constant expressions. For example, const Digits array 0 9 of Char '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' declares a typed constant called Digits that holds an array of characters. Zero-based character arrays often represent null-terminated strings, and for this reason string constants can be used to initialize...

Declaring and Accessing Nested Classes

The following examples demonstrate how to declare and access fields and methods of a nested class. myInnerField Integer procedure innerProc end To implement the innerProc method of the inner class, you must qualify its name with the name of the outer class. For example procedure TOuterClass.TInnerClass.innerProc begin To access the members of the nested type, use dotted notation as with regular class member access. For example x TOuterClass y TOuterClass.TInnerClass x TOuterClass.Create...

Calling Conventions

When you declare a procedure or function, you can specify a calling convention using one of the directives register, pascal, cdecl, stdcall, and safecall. For example, function MyFunction X, Y Real Real cdecl Calling conventions determine the order in which parameters are passed to the routine. They also affect the removal of parameters from the stack, the use of registers for passing parameters, and error and exception handling. The default calling convention is register. The register and...

Variant Arrays

You cannot assign an ordinary static array to a variant. Instead, create a variant array by calling either of the standard functions VarArrayCreate or VarArrayOf. For example, V VarArrayCreate 0,9 , varlnteger creates a variant array of integers of length 10 and assigns it to the variant v. The array can be indexed using V 0 , V 1 , and so forth, but it is not possible to pass a variant array element as a var parameter. Variant arrays are always indexed with integers. The second parameter in...

Unit Initialization and Finalization

On the .NET platform, units that you depend on will be initialized prior to initializing your own unit. However, there is no way to guarantee the order in which units are initialized. Nor is there a way to guarantee when they will be initialized. Be aware of initialization code that depends on another unit's initialization side effects, such as the creation of a file. Such a dependency cannot be made to work reliably on the .NET platform. Unit finalization is subject to the same constraints and...

Wide String Types

On Win32, a wide string variable occupies four bytes of memory which contain a pointer to a dynamically allocated string. When a wide string variable is empty contains a zero-length string , the string pointer is nil and no dynamic memory is associated with the string variable. For a nonempty string value, the string pointer points to a dynamically allocated block of memory that contains the string value in addition to a 32-bit length indicator. The table below shows the layout of a wide string...

Forward Declarations and Mutually Dependent Classes

If the declaration of a class type ends with the word class and a semicolon - that is, if it has the form type className class with no ancestor or class members listed after the word class, then it is a forward declaration. A forward declaration must be resolved by a defining declaration of the same class within the same type declaration section. In other words, between a forward declaration and its defining declaration, nothing can occur except other type declarations. Forward declarations...

Special Symbols

Special symbols are non-alphanumeric characters, or pairs of such characters, that have fixed meanings. The following single characters are special symbols amp ' , - . lt gt The following character pairs are also special symbols . . lt gt lt gt The following table shows equivalent symbols The left bracket is equivalent to the character pair of left parenthesis and period . The right bracket is equivalent to the character pair of period and right parenthesis . The left brace is equivalent to the...

Record Types

On the .NET platform, field layout in record types is determined at runtime, and can vary depending on the architecture of the target hardware. The following discussion of record alignment applies to the Win32 platform only packed records are supported on the .NET platform, however . When a record type is declared in the a state the default , and when the declaration does not include a packed modifier, the type is an unpacked record type, and the fields of the record are aligned for efficient...

Multiunit Namespaces

Multiple units can be grouped together into one namespace using an extension of the in clause in the project source file. The file name string can list multiple unit source files in a semicolon-delimited list. MyProgram.MyNamespace in In this example, the namespace MyProgram.MyNamespace logically contains all the interface symbols from Symbol names in a namespace must be unique, across all units in the namespace. In the example above, if unitl and unit2 both define a global interface symbol...

Constructors

A constructor is a special method that creates and initializes instance objects. The declaration of a constructor looks like a procedure declaration, but it begins with the word constructor. Examples constructor Create AOwner TComponent Constructors must use the default register calling convention. Although the declaration specifies no return value, a constructor returns a reference to the object it creates or is called in. A class can have more than one constructor, but most have only one. It...

Comments and Compiler Directives

Comments are ignored by the compiler, except when they function as separators delimiting adjacent tokens or compiler directives. There are several ways to construct comments Text between a left brace and a right brace constitutes a comment. Text between a left-parenthesis-plus-asterisk and an asterisk-plus-right-parenthesis is also a comment Any text between a double-slash and the end of the line constitutes a comment. Comments that are alike cannot be nested. For instance, will not work, but...

Function Declarations

A function declaration is like a procedure declaration except that it specifies a return type and a return value. Function declarations have the form function functionName parameterList returnType directives where functionName is any valid identifier, returnType is a type identifier, statements is a sequence of statements that execute when the function is called, and parameterList , directives , and localDeclarations are optional. The function's statement block is governed by the same rules...

ClassReference Types

A class-reference type, sometimes called a metaclass, is denoted by a construction of the form class of type where type is any class type. The identifier type itself denotes a value whose type is class of type. If typei is an ancestor of type2, then class of type2 is assignment-compatible with class of typei. Thus type TClass class of TObject var AnyObj TClass declares a variable called AnyObj that can hold a reference to any class. The definition of a class-reference type cannot occur directly...

Package Declarations and Source Files

Each package is declared in a separate source file, which should be saved with the .dpk extension to avoid confusion with other files containing Delphi code. A package source file does not contain type, data, procedure, or function declarations. Instead, it contains a list of other packages required by the new package. These are packages to which the new package is linked. a list of unit files contained by, or bound into, the package when it is compiled. The package is essentially a wrapper for...

Interface Identification

An interface declaration can specify a globally unique identifier GUID , represented by a string literal enclosed in brackets immediately preceding the member list. The GUID part of the declaration must have the form where each x is a hexadecimal digit 0 through 9 or A through F . The Type Library editor automatically generates GUIDs for new interfaces. You can also generate GUIDs by pressing Ctrl Shift G in the code editor. A GUID is a 16-byte binary value that uniquely identifies an...

Compiling Packages

Packages are ordinarily compiled from the IDE using .dpk files generated by the Project Manager. You can also compile .dpk files directly from the command line. When you build a project that contains a package, the package is implicitly recompiled, if necessary. The following table lists the files produced by the successful compilation of a package. Compiled package files File extension Contents DCP Win32 or DCPIL .NET A binary image containing a package header and the concatenation of all .dcu...