Variable Declaration Primitives | |
Macros | |
__lexicalblock | Lexical scope. |
arg_list | Argument list. |
array | Declare a array symbol. |
bool | Declare a boolean symbol. |
const | Define a variable as being constant. |
declare | Declare a polymorphic symbol. |
double | Declare a double float symbol. |
extern | Declare an external variable. |
float | Declare a float symbol. |
get_parm | Retrieve the value of a macro parameter. |
getopt | Get options. |
getsubopt | Parse suboption arguments from a string. |
global | Declare a global variable. |
inq_symbol | Determine if the symbol exists. |
int | Declare an integer symbol. |
is_array | Determine whether an array type. |
is_float | Determine whether a float type. |
is_integer | Determine whether an integer type. |
is_list | Determine whether a list type. |
is_null | Determine whether a NULL type. |
is_string | Determine whether a string type. |
is_type | Determine whether an explicit type. |
make_local_variable | Make a buffer local variable. |
put_parm | Assign an argument value. |
ref_parm | Create a reference parameter. |
register | Define a variable as being a register. |
static | Define a function or module scope. |
string | Declare a string symbol. |
typeof | Determine the symbol type. |
__lexicalblock( .... block ... );
Lexical scope.
The __lexicalblock statement is used to implement lexical block scoping within function/macro bodies.
By default local variables are all function scoped unless lexical block scoping is enabled via the #pragma lexical_scoping.
#pragma scope(push, lexical)
void function() {
int i; // first variable, function scope
{
int i; // second variable, lexically block scope
}
}
#pragma scope(pop)
The __lexicalblock() primitive is internal to the macro language. It is generated by the GRIEF macro compiler when nested variable declarations are encountered within block statements. it is not intended for direct use.
nothing
list arg_list( [int eval = FALSE], [int start = 0], [int end = -1] )
Argument list.
The arg_list() primitive retrieves a list of the values representing the arguments which were passed to the current macro; allows for arbitrary argument processing.
eval | Optional boolean flag, if true each argument shall be evaluated (e.g. variables are referenced) with the result being retrieved, otherwise the raw value (e.g. variable name) shall be retrieved. |
start | Optional integer starting the index of the first argument to be including within the list. If omitted defaults to 1, being the first argument. |
end | Optional integer starting the index of the last argument to be including within the list. If omitted defaults to -1, being the last argument. |
The arg_list() primitive returns the arguments passed to the current macro as a list.
void
func()
{
message("%s", arg_list());
}
In the example above, the list of arguments will be shown. But in a call like
int val = 99;
func(val);
In this case, the message will show “val” and not 99. To get the values replaced, use
message("%s", arg_list(1));
Return value
List of arguments passed to calling macro.
The start and end parameters are GriefEdit extensions.
const <type> sym1, sym2 ...;
Define a variable as being constant.
The const qualifier explicitly declares a locally scoped data object as something that cannot be changed. Its an immutable variable can only be set during initialization.
You cannot use const data objects in expressions requiring a modifiable lvalue. If you try to give it a new value, it will return you an error.
For example, a const data object cannot appear on the lefthand side of an assignment statement.
nothing
An experimental GRIEF extension; functionality may change.
double sym1, sym2 ...;
Declare a double float symbol.
The double statement is an alias for the float type.
Unlike C and C++, both float and double are internally representing using a 64-bit double precision floating-point
nothing
n/a
extern <type> sym1, sym2, ..;
Declare an external variable.
The extern storage class specifier extends the visibility of variables and functions, allowing objects and functions to be accessed across several source files.
An extern variable, function definition, or declaration makes the described variable or function usable by the succeeding part of the current source file.
This declaration does not replace the definition. The declaration is used to describe the variable that is externally defined. Essentially the extern keyword creates a place holder in the symbol table to avoid undefined symbol reference errors.
You should note that we are using the words definition and declaration carefully when we refer to external variables in this section. Definition refers to the place where the variable is created or assigned storage; declaration refers to places where the nature of the variable is stated but no storage is allocated.
A variable must be defined once in one of the modules of the program; this sets aside storage. If there is no definition, a runtime error shall result since the storage of the variable would not have been created,
There may be none or more variable declarations. These can be declared extern in many modules, including the module where it was defined, and even many times in the same module. All the declarations must match, which is normally by the use of a common header file shared between all source files.
Any extern declaration of the same identifier found within a block refers to that same object. If no other declaration for the identifier exists at file scope, the identifier has external linkage.
Unlike C external linkage of variables occurs during macro execution, see Scope Rules. If a declaration for an identifier already exists in one of the visible namespaces they reference to the same image.
When searching for a variable definition, GRIEF searches the symbol tables in the following order:
Within the following example the variable x reference by the function foo is resolved against the global image of x, whereas b shall be resolved against the image within the caller bar.
static int x = 0;
void
foo()
{
extern int b, x;
b = 0; // resolved by 'i' within bar()
x = 0; // global 'x'
}
void
bar()
{
int b;
foo();
}
The extern statement applied to a function prototype does nothing; as extern is the default linkage. A function prototype is always a declaration and never a definition.
All functions across loaded macros which refer to the same external identifier refer to the same object, so care must be taken that the type and extent specified in the definition are compatible with those specified by each function which references the data. This is generally achieved by the use of a common header file shared between all source files (e.g. “grief.h”).
It is an error to include a declaration for the same function with the storage class specifier static before the declaration with no storage class specifier because of the incompatible declarations. Including the extern storage class specifier on the original declaration is valid and the function has internal linkage.
Builtin macros do not have explicit prototypes as the Macro compiler has internal knowledge of all visible primitives.
nothing
n/a
float sym1, sym2 ...;
Declare a float symbol.
The float statement declares a simple type that stores 64-bit floating-point values that stores values in the approximate range;
1.7E308 to 1.7E+308
Unlike C and C++, both float and double are internally representing using a 64-bit double precision floating-point
nothing
n/a
int get_parm( [int argument], declare & symbol, [string prompt], [int length = MAXPROMPT], [declare default], [int one = FALSE] )
Retrieve the value of a macro parameter.
The get_parm() primitive shall retrieve the value of the specified macro parameter argument optionally prompting the user if the referenced parameter was not given during the macro execution. When prompted the question within prompt is presented using the optional default which the user can then edit.
This function can also be used to always prompt the user for a reply by invoking with the argument parameter being omitted and specified as NULL.
Generally the user must complete the input using an enter unless the prompt is in single character mode, whereby the first key is taken as the input. The mode is either implied by the length parameter or an explicit one parameter, see below.
The following keys bindings are active during parameter prompts.
Key |
Function |
---|---|
Right, Left |
Move cursor the back/forward one character. |
Ctrl+Right, Ctrl+Left |
Move cursor the start/end of the current word. |
Home, End |
Move to first/last character within the edit field. |
Alt+I, Ctrl-O |
Toggle insert/overstrike mode. |
DEL |
Delete character under the cursor. |
Backspace, Ctrl+H |
Delete character prior to the cursor. |
Alt+K |
Delete from cursor to the end of line. |
Insert |
Paste from scape. |
Backspace, Ctrl+H |
Delete character prior to the cursor. |
ESC |
Abort current edit, restoring original content. |
Alt-D |
Delete current line. |
Alt-K |
Delete from cursor to the end of line. |
Alt+Q, Ctrl+Q |
Quote next character. |
Enter |
Process change. |
ALT+H |
Help. |
Ctrl+A (*) |
Move cursor to beginning of line. |
Ctrl+D (*) |
Delete character under cursor. |
Ctrl+K (*) |
Delete from cursor to the end of line. |
Ctrl+X, Ctrl+U (*) |
Delete current line. |
Ctrl+V, Ctrl+Y (*) |
Paste from clipboard. |
(*) Emacs style key mappings.
Arguments passed to macros are passed as call by name, that is every time a get_parm is issued against a particular parameter, that parameter is re-evaluated.
This lazy evaluation has a number of implications.
This feature can be very useful sometimes, and at other times it can cause anomalous side-effects ((see Lazy Evaluation )).
argument | An integer stating the associated macro argument index to be retrieved, starting at an offset of zero for the first parameter. |
symbol | Specifies the symbol reference into which the resulting parameter shall be stored. |
prompt | Option string which specifies the prompt which is represented to the user. If the prompt is omitted, the user is not prompted. |
length | Optional integer parameter that specifies the upper limit of the string length that is to be retrieved. When given as 1 then single character mode is implied unless overriden using the one parameter. If omitted the upper length is assumed to be MAXPROMPT. |
default | An optional value, whos type should match the type of symbol, if specified contains the value which shall initially be placed on the command line if a prompt is required. |
one | Optional integer flag, if specified as non-zero than the user shall be prompted for a single character. Generally the user must complete the input using an enter, whereas in single character mode the first key is taken as the input. In addition, single character mode disables the execution of the _prompt_begin and _prompt_end callbacks plus any associated prompt history. If omitted the character mode shall be implied from the specified length; a length of 1 being true otherwise false. |
The get_parm() primitive returns greater than zero on success, otherwise zero if either the user aborted or an error was encountered.
Return |
Description |
---|---|
0 |
Abort, invalid argument or conversion error. |
1 |
Success. |
2 |
Default was assigned (extension). |
Unlike BRIEF the default parameter is always the fifth, whereas with BRIEF the default value is either the fourth or fifth dependent on whether an integer length is stated since the default was only permitted to be a string.
The one option is a GriefEdit extension.
int getopt( string & value, [[string shortopts], list longopts, string|list args, [string caller]] )
Get options.
The getopt() primitive is a command-line parser similar to the system library function of the same name. The getopt() function provides a superset of the functionality of getopt, accepting options in two forms, words (long-options) and characters (short-options).
The getopt() primitive is designed to be executed within a loop, with the first invocation suppling the available options shortopts and/or longopts, the arguments to be parsed args and the application/macro name caller. Subsequent calls within the same execution loop only then request the next available option without additional arguments; the general form of getopt usage is as follows.
string value;
int ch;
if ((ch = getopt(value, shortopts, longopts, args)) > 0) {
do {
} while ((ch = getopt(value)) > 0);
The short option string shortopts may contain the following elements
For example, an option string “x” recognizes an option `-x’, and an option string “x:” recognizes an option and argument `-x argument’.
The long option list longopts may contain a list of strings each defining a long option, of the form:
"[tag][,[#]value][[:=][scinfd]]"
tag | Option tag or name. |
value | Index value returned upon an option match. The value is either a character or a numeric denoted by a leading #. If omitted the index shall be taken as the next within the sequence either following the previous index or using the opening index of zero(0). |
operator | Defines whether the value is optional (=) or required (:). If omitted, it is assumed no value is required. |
type | Optional value type against which the value shall be validated, stated as either a single character or it equivalent full name. |
a[nything] | Anything. |
s[tring] | String. |
c[haracter] | Character value. |
i[integer][+] | Decimal integer value plus optional positive only modifier. |
n[numeric][+] | Numeric (oct, dec and hex). |
f[loat] | Floating point including integer. |
d[ouble] | Double precision floating point including integer. |
b[oolean] | Boolean, 0/1, y[e]s/n[o], on/off, true/false; result being a string containing 0 or 1. |
Option value or index, starting at zero, otherwise one of the following negative error codes. If the case of error codes -2 or less, value shall contain an error condition descripting the condition.
-1 | End of the options (EOF). |
-2 | Unknown option. |
-3 | Ambiguous option. |
-4 | Argument required. |
-5 | Unexpected argument. |
Plus the following argument syntax error conditions.
-10 | Invalid value, for example “expected a numeric value”. |
-99 | Invalid option specification. |
A GriefEdit extension.
list longoptions = {
"help,h", // note duplicates result in first match
"verbose,v",
"verbose2,#2",
"integer" // extended format
};
int ch;
if ((ch = getopt(value, "hv", longoptions, get_parm(1))) > 0) {
do {
switch (ch) {
case 'h': // -h (short) or --help (long) option
break;
case 'v': // -v (short) or --verbose (long)
break;
case 2: // --verbose2
break;
case 3: // --integer=<value>
i = atoi(value);
break;
case '?': // error or unknown option
case ':': // or argument expected
if (length(value)) {
error("myfunction: %s", value);
}
break;
default:
break;
}
} while ((ch = getopt(value)) > 0);
}
int getsubopt( string value, [list options], [string|list args], [string delim], [string quotes] )
Parse suboption arguments from a string.
The getsubopt() primitive shall parse suboption arguments in a flag argument. Such options often result from the use of getopt.
options | Option declaration list of one more strings of the following form “tag[, index][[:=][type]]”, see below for more details. |
value | Tag value, otherwise set to an empty string. |
args | Argument buffer to be processed. Note, on success the buffer shall be modified with the leading matched option and trailing value removed. |
delim | Optional delimiter, if omitted defaults to a comma(,). |
Option index, otherwise one of the following negative error codes. If the case of error codes -2 or less, value shall contain an error condition descripting the condition,
-1 | End of the options (EOF). |
-2 | Unknown option. |
-4 | Argument required. |
-5 | Unexpected argument. |
-6 | Invalid value, for example “expected a numeric value”. |
-10 | Invalid option specification. |
A GriefEdit extension.
list suboptions = {
"help,h",
"verbose,v",
"verbose2,#2",
"integer:i"
};
if ((ch = getsubopt(value, suboptions, get_parm(1))) >= 0) {
do {
switch (ch) {
case 'h':
break;
case 'v':
break;
case 2:
break;
case 3:
break;
default:
break;
}
} while ((ch = getsubopt(value)) >= 0);
}
if (ch < 0) {
error(value);
}
global sym1, sym2, ..;
Declare a global variable.
The global() primitive promotes a local declaration and making symbol global to all macros.
Global variables maintain their value across macro invocation and occupy permanent storage (See: Scope), whereas local variables are destroyed upon the macro they are contained within is terminated.
A variable must have been specified in a previous int, string, list, float or declare statement before it can be made into a global.
The global is a managed primitive and shall be automaticlly invoked on global variable declarations as follows:
// global declarations
int global_int1 = 1234;
static int global_int2;
const static int global_int3 = 125;
string global_string2 = "Hello world";
static string global_string2;
float global_float1 = "Hello world";
static float global_float2;
list global_list1;
static list global_list2;
void
mymacro()
{
}
Each macro object containing global declarations shall contain an internal _init macro, which is utilised by the Macro Compiler to initialise file level variables.
Both global and _init are considered as internal primitives, reserved for exclusive use by the GRIEF Macro Compiler and may change without notice.
Management of variable scoping and argument binding shall be handling automatically by the compiler.
nothing
n/a
int inq_symbol( string symbol )
Determine if the symbol exists.
The inq_symbol() primitive determines whether the variable Iname exists at the current scope (See: Scope). One main use of this primitive is to determine if a specific local buffer symbol has been defined.
symbol | Name of the symbol. |
// required to resolve symbol at compile time
extern string my_buffer_var;
string
_set_buffer_var(string val)
{
if (inq_symbol("my_buffer_var")) {
my_buffer_var = mode; // buffer-scope
} else
{ // otherwise we must create
string my_buffer_var = mode;
make_local_variable( my_buffer_var );
}
}
string
_get_buffer_var()
{
if (inq_symbol("my_buffer_var")) {
return my_buffer_var;
}
return "";
}
The inq_symbol() primitive returns a positive value indicates that the symbol exists, otherwise 0 if not found within the current scope.
A GriefEdit extension.
int is_array( declare & symbol )
Determine whether an array type.
The is_array() primitive determines the type of a polymorphic expression and tests whether the specified symbol has of a array type.
Beware that the is_type collection of functions wont behave when given list elements, as these are not referenceable l-values.
symbol | Symbol reference. |
true if a array type, otherwise false.
n/a
int is_float( declare & symbol )
Determine whether a float type.
The is_float() primitive determines the type of a polymorphic expression and tests whether the specified symbol has of a floating-point type.
symbol | Symbol reference. |
true if a float type, otherwise false.
A GriefEdit extension.
int is_integer( declare & symbol )
Determine whether an integer type.
The is_integer() primitive determines the type of a polymorphic expression and tests whether the specified symbol has of an integer type.
symbol | Symbol reference. |
true if an integer type, otherwise false.
n/a
int is_list( declare & symbol )
Determine whether a list type.
The is_list() primitive determines the type of a polymorphic expression and tests whether the specified symbol has of a list type.
symbol | Symbol reference. |
true if a list type, otherwise false.
n/a
int is_null( declare & symbol )
Determine whether a NULL type.
The is_null() primitive determines the type of a polymorphic expression and tests whether the specified symbol has of a NULL type.
Beware that the is_type collection of functions wont behave when given list elements, as these are not referenceable l-values.
symbol | Symbol reference. |
true if a NULL type, otherwise false.
n/a
int is_string( declare & symbol )
Determine whether a string type.
The is_string() primitive determines the type of a polymorphic expression and tests whether the specified symbol has of a string type.
Beware that the is_type collection of functions wont behave when given list elements, as these are not referenceable l-values.
symbol | Symbol reference. |
true if a string type, otherwise false.
n/a
int is_type( declare & symbol, int|string type )
Determine whether an explicit type.
The is_type() primitive determines the type of a polymorphic expression and tests whether the specified symbol is of the type type.
Beware that the is_type collection of functions wont behave when given list elements, as these are not referenceable l-values.
symbol | Symbol reference. |
type | Type identifier or name as follows. |
Type |
Name |
---|---|
F_INT |
integer |
F_STR |
string |
F_FLOAT |
float, double |
F_LIST |
list |
F_ARRAY |
array |
F_NULL |
NULL |
F_HALT |
undef |
true if the stated type, otherwise false.
n/a
void make_local_variable( declare & sym, ... )
Make a buffer local variable.
The make_local_variable() primitive associates the specified variable with the current buffer, becoming a buffer local variable..
Unlike scoped variables that are destroyed when the block within which they are defines terminates, buffer local variables maintain their value across macro invocation and occupy permanent storage until the buffer is deleted (See: <scope>).
sym | Symbol reference. |
... | Optional additional symbol references. |
The make_local_variable() primitive returns nothing directly.
On error conditions the following diagnostics message shall be echoed on the command prompt, with xxx representing the symbol name.
missing symbol.
'xxx' not found at current scope.
cannot promote reference 'xxx'.
system variable 'xxx'.
n/a
inq_symbol, <types>
int put_parm( int argidx, declare val, [int optional = TRUE] )
Assign an argument value.
The put_parm() primitive assigns a value val to a parameter positioned at argidx that was passed to the current macro.
argidx | Integer argument index of the parameter passed to the current macro which is to be assigned a value; parameter indexs start at zero. |
val | Value to be assigned to the parameter; the value type should match the type of the parameter. |
optional | Optional boolean value, if true missing parameters shall not generate an error, otherwose if false or omitted an error will be echoed. |
The put_parm() primitive returns 1 or greater on sucesss, otherwise 0 or less on error.
On the detection of error conditions the following diagnostics messages shall be echoed on the command prompt where x is the associated argument number;
put_parm: argument index 'x' out of range
put_parm: argument 'x' incorrect type
put_parm: argument 'x' type conversion error
Assign the value 100 to the first parameter.
if (put_parm(0, 100)) {
message("assigned");
}
n/a
void ref_parm( int argument, string local_symbol, [int optional = FALSE] )
Create a reference parameter.
The ref_parm() primitive creates a local reference to one of the current macro arguments, this primitive is the underlying implementation of macro reference arguments.
int mymacro(int &iparm, string &sparm)
is equivalent to the following
int mymacro()
{
ref_parm(0, "iparm");
ref_parm(1, "sparm");
This interface should be considered as an internal primitive, reserved for exclusive use by the GRIEF Macro Compiler and may change without notice. Management of variable scoping and argument binding shall be handled automatically by the compiler.
argument | Argument index. |
local_symbol | Name of the local symbol used as the local alias to the referenced argument. |
optional | Optional integer flag determining whether the argument is optional, if omitted is assumed FALSE. |
nothing
A GriefEdit extension
register idx1, sym1, idx2, sym2 ...;
Define a variable as being a register.
The register qualifier explicitly declares a locally scoped data object as something that should be cached against the given index.
Registers are function scoped, being unique to each macro and are is visible only within the function.
nothing
An experimental GRIEF extension; functionality may change.
static var1, var2, ..;
Define a function or module scope.
The static statement can be used to change the storage scope of a variable or function. It is one of the major mechanism to enforce information hiding. static denotes that a function or data element is only known within the scope of the current module. This provides a form of object-hiding and can avoid name clashes with other macros (See: Scope).
In addition, if you use the static statement with a variable that is local to a function, it allows the last value of the variable to be preserved between successive calls to that function, including during recursions.
A static variable is initialized only once. Globals are performed within the body of the _init function, whereas a function static variable that has an initializer is initialized the first time it comes into existence.
Function::*
A static function is hidden from usage outside their own macro file (or module), this can present a problem with functionality which involves the usage of callbacks (e.g. assign_to_key). In this case, the :: (scope resolution) operator is used to qualify hidden names so that they can still be used.
void
main()
{
assign_to_key("<Alt-A>", "my_alt_a");
}
static void
my_alt_a()
{
//function body
}
The static declaration of my_alt_a() referenced by the assign_to_key() within main() wont be visible when the “Alt-A” key is processed as it shall be out of scope. The usage of “::my_alt_a” forces the my_alt_a reference to become fully qualified at the time of the key assignment. The following examples have the equivalent result:
Implicit current module, where if a null module name is specified (e.g. “::function”) then the symbol shall be bound to current module.
assign_to_key("<Alt-A>", "::my_alt_a");
or, explicit current module, where a named namespaces is specified (e.g. “module::function”):
module("my_module"");
assign_to_key("<Alt-A>", "my_module::my_alt_a");
or
module("my_module"");
assign_to_key("<Alt-A>", inq_module() + "::my_alt_a");
nothing
Module static declarations are a GRIEF extension.
string typeof( declare & symbol )
Determine the symbol type.
The typeof() primitive determines the type of a polymorphic expression returning a string describing the underlying type.
The typeof() primitive returns one of following strings dependent on the type of the specified symbol.
n/a
is_integer, is_string, is_float, is_list, is_null
$Id: $
To send feedback on this topic email: grie@gmai l.com fedit
Copyright © Adam Young All Rights Reserved.
Lexical scope.
__lexicalblock( .... block ... );
Argument list.
list arg_list( [int eval = FALSE], [int start = 0], [int end = -1] )
Declare a array symbol.
array sym1, sym2 ...;
Declare a boolean symbol.
bool sym1, sym2 ...;
Define a variable as being constant.
const <type> sym1, sym2 ...;
Declare a polymorphic symbol.
declare sym1, sym2 ...;
Declare a double float symbol.
double sym1, sym2 ...;
Declare an external variable.
extern <type> sym1, sym2, ..;
Declare a float symbol.
float sym1, sym2 ...;
Retrieve the value of a macro parameter.
int get_parm( [int argument], declare & symbol, [string prompt], [int length = MAXPROMPT], [declare default], [int one = FALSE] )
Get options.
int getopt( string & value, [[string shortopts], list longopts, string|list args, [string caller]] )
Parse suboption arguments from a string.
int getsubopt( string value, [list options], [string|list args], [string delim], [string quotes] )
Declare a global variable.
global sym1, sym2, ..;
Determine if the symbol exists.
int inq_symbol( string symbol )
Declare an integer symbol.
int sym1, sym2 ...;
Determine whether an array type.
int is_array( declare & symbol )
Determine whether a float type.
int is_float( declare & symbol )
Determine whether an integer type.
int is_integer( declare & symbol )
Determine whether a list type.
int is_list( declare & symbol )
Determine whether a NULL type.
int is_null( declare & symbol )
Determine whether a string type.
int is_string( declare & symbol )
Determine whether an explicit type.
int is_type( declare & symbol, int|string type )
Make a buffer local variable.
void make_local_variable( declare & sym, ... )
Assign an argument value.
int put_parm( int argidx, declare val, [int optional = TRUE] )
Create a reference parameter.
void ref_parm( int argument, string local_symbol, [int optional = FALSE] )
Define a variable as being a register.
register idx1, sym1, idx2, sym2 ...;
Define a function or module scope.
static var1, var2, ..;
Declare a string symbol.
string sym1, sym2 ...;
Determine the symbol type.
string typeof( declare & symbol )
Declare a list symbol.
list sym1, sym2 ...;
Command prompt session begin callback.
void _prompt_begin( string prompt )
Command prompt session end callback.
void _prompt_end()
Retrieve the prompt status.
int inq_prompt()
Argument split.
list split_arguments( string arguments )