Epsilon User's Manual and Reference >
Epsilon Extension Language >
Initialization
Declarations for the formal parameters of functions work just as
described above, but you can additionally provide local and global variables
with a specific initial value.
local-variable-definition:
type-specifier local-declarator-list ;
local-declarator-list:
local-declarator
local-declarator , local-declarator-list
local-declarator:
declarator
declarator = expression
You can initialize a local variable with any expression so long as
the corresponding assignment
would be permitted. Since you cannot assign to variables with types
such as "array of ..." and "structure of ...", you
cannot initialize such local variables at compile time. Local
variables (those defined within a block) have undefined initial
values if no explicit initialization is present.
global-variable-definition:
type-specifier global-declarator-list ;
global-modifier-list global-declarator-list ;
global-modifier-list type-specifier global-declarator-list ;
global-modifier-list:
global-modifier
global-modifier global-modifier-list
global-modifier:
buffer
window
zeroed
user
volatile
global-declarator-list:
global-declarator
global-declarator , global-declarator-list
global-declarator:
declarator
declarator = string-constant
declarator = initializer
initializer:
constant-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
initializer
initializer , initializer-list
You may initialize
a global variable of type "array of characters" with a string
constant. If you omit the length of the array in a declaration with
such an initialization, it's set to just contain the initializing string
(including its terminating null character).
If no explicit initialization is specified, variables defined
globally are set to zero. If you provide a partial initialization
(for example, if you specify the first 5 characters in a 10 character
array), the remainder of the variable is set to zero. Initializers
for global variables must involve only constant
expressions known at compile
time, whereas initializers for local variables may involve arbitrary
expressions (including function calls, for example).
When Epsilon loads a file defining an initialized global variable and
the variable was already defined to have the same type, the
initialization has no effect: the variable's value remains the same.
If the new declaration specifies a different type for the variable,
however, the variable's value is indeed changed. (Actually, Epsilon
only compares the sizes of the variables. If you redefine an integer
as a four character array, Epsilon won't apply the new initialization.)
For example, suppose you declare foo to be an int and initialize it
to 5. If you later load a file which redeclares foo to be an int
and initializes it to 7, the value of foo would remain 5. If
instead you redeclare foo to be a char and reinitialize it to 'C' ,
then the value would change, since the size of a char is different from
the size of an int.
To tell Epsilon that it must reinitialize the
variable each time it reads a definition, use the volatile
keyword. Every time you load a bytecode file containing such a
variable definition, Epsilon will set the variable according to its
initialization.
If you declare a global variable that is a number, spot, or pointer,
the initializer must be a constant expression. In fact, if the
variable is a spot or pointer, you can only initialize it with the
constant zero. For example:
int i=3;
char *name="harold";
initializes the int variable i to be 3, and the
character pointer name to point to the first character in the
string "harold". The variable name must be a local
variable. If it were global, then you could initialize it only to
zero, which is equivalent to not initializing it at all (see above).
If you declare a global array, you can initialize each element
of the array. The initializer in this case would be a
sequence of constant expressions, separated by commas, with the whole
thing enclosed in braces {} . Consider the following examples:
int ary1[4] = { 10, 20, 30, 40 };
int ary2[ ] = { 10, 20, 30, 40 };
int ary3[4] = { 10, 20 };
Here we have ary1 declared to be an array of 4 ints. We
initialize the first element in the array to 10, the second to 20,
and so on. The declaration of ary2 does the same thing. Notice
that the square brackets in the declarator are empty. The EEL
compiler can tell from the initializer that the size must be 4. The
declaration of ary3 specifies the size of the array, but only
initializes the first two elements. The compiler initializes the
remaining two elements to zero.
The initializers for global structures are similar. The items
between the curly braces are a sequence of expressions, with each
expression's type matching the type of the corresponding field name.
For example, the declaration:
struct {
int f1;
char f2;
short f3;
} var = { 33, 't', 22 };
declares the variable var to be a structure with fields f1 ,
f2 , and f3 , with types int, char, and short
respectively. The declaration initializes the f1 to 33, the character
field f2 to 't' , and the short field f3
to 22.
You cannot initialize either unions or local structures. Global pointers
may only be initialized to zero (which is equivalent to not
initializing them at all).
If you initialize
an array or structure which has subarrays or
substructures, simply recursively apply the
rules for initialization. For example, consider the following:
struct {
char c;
int ary1[3];
} var = { 't', { 3, 4, 5} };
This declares var to be a structure containing a character and an
array of 3 ints. It initializes the character to 't' , and the
array of ints so that the first element is 3, the
second 4, and the third 5.
Epsilon Programmer's Editor 14.04 manual. Copyright (C) 1984, 2021 by Lugaru Software Ltd. All rights reserved.
|