3 V and the V Command Processor
This chapter introduces the V language, describes the V Command Processor with which you can interactive with AVS/Express in V.
This chapter discusses:
3.1 Introduction
V is AVS/Express' language for defining objects and applications. V is a textual alternative to the Network Editor.
AVS/Express stores all object definitions as V text files or binary V files. This includes objects you create and save in the Network Editor.
A V file can contain comments, statements, and commands.
|
|
|
Document a V file. AVS/Express ignores them.
|
|
Create, modify, and delete objects.
|
|
Perform special operations. For example, $print prints an object's definition. $include includes a V file. #define allows you to define conditional code.
|
The V Command Processor (VCP) is a tool for viewing and maintaining V code within AVS/Express.
The VCP allows you to
- enter V statements and commands
- navigate the object hierarchy
3.2 V Command Processor
The V Command Processor (VCP) allows you to interactively manipulate AVS/Express objects using the V language. The VCP gives you a prompt that shows you the name of the object that you are currently editing and uses indentation to indicate the number of levels into the object hierarchy that the current object lives. Each command is executed when you terminate a command with a newline character.
3.2.1 Examples
To begin, here are several examples of the VCP. You enter the text to the right of the -> prompt.
For example, assume the current object is Root. The following VCP lines create objects var1 and UIfield as immediate subobjects of SingleWindowApp, set the value of UIfield's x subobject, then navigate back up to Root:
OM(Root) -> Applications {
OM(Applications) -> SingleWindowApp {
OM(SingleWindowApp) -> int var1;
OM(SingleWindowApp) -> UIfield UIfield {
OM(UIfield) -> x = 10;
OM(UIfield) -> };
OM(SingleWindowApp) -> };
OM(Applications) -> };
OM(Root) ->
Assume that SingleWindowApp has a subobject called UIfield. The following VCP lines print the value of UIfield's x subobject, then navigate back up to Root:
OM(Root) -> SingleWindowApp{
OM warning: jumping from: Root to Root.Applications.SingleWindowApp
OM(SingleWindowApp) -> UIfield{
OM(UIfield) -> $real x
10
OM(SingleWindowApp) -> };
OM(SingleWindowApp) -> };
OM(Root) ->
The following VCP lines create a group object called grp1, create subobjects for the group, then navigate back up to Root:
OM(Root) -> SingleWindowApp{
OM warning: jumping from: Root to Root.Applications.SingleWindowApp
OM(SingleWindowApp) -> group grp1{
OM(grp1) -> int x, y, z;
OM(grp1) -> };
OM(SingleWindowApp) -> };
OM(Root) ->
Assume that SingleWindowApp has a subobject called grp1. The following lines navigate from Root to grp1, modify grp1's x subobject, add a subobject called w, then navigate back up to Root:
OM(Root) -> SingleWindowApp.grp1 {
OM warning: jumping from: Root to Root.Applications.SingleWindowApp.grp1
OM(grp1) -> x = 3;
OM(grp1) -> int w;
OM(grp1) -> };
OM(Root) ->
3.2.2 VCP's appearance
The VCP appears in the window where you started AVS/Express. This is the VCP prompt:
The name of the current object appears in parentheses. When you start AVS/Express, the current object is always Root.
3.2.3 Entering statements and commands
You enter V statements and commands to the right of the prompt, pressing Return at the end of a line.
A V statement can continue across lines. A V command must appear all on one line.
For example, here is the $list command that lists the subobjects of the current object:
For details, see:
Section 3.5,
V commands [page 3-24]
3.2.4 Navigating the object hierarchy
3.2.4.1 Current object
The VCP considers one object in the object hierarchy to be current. At start-up, the current object is Root.
The current object is important because commands and statements you enter work in the context of the current object. For example:
- Several commands, such as $print and $list, operate on a particular object. The object must be the current object or is defined to be relative to the current object.
- In a create statement, the object you create becomes an immediate subobject of the current object.
- In a modify or delete object statement, the target object is defined to be relative to the current object.
The name of the current object appears in parentheses in the VCP prompt.
3.2.4.2 Navigating
You change the current object by navigating the object hierarchy. The object you navigate to becomes the current object.
|
|
|
Enter the name of an immediate subobject, followed by an open brace. (Note: You can list immediate subobjects with the $list command.) For example, assume that grp1 is an immediate subobject of SingleWindowApp:
OM(SingleWindowApp) -> grp1 { OM(grp1) ->
|
|
Enter a close brace followed by a semicolon. For example:
OM(grp1) -> }; OM(SingleWindowApp) ->
|
Down several levels at once
|
Enter a pathname followed by an open brace, where the pathname starts with an immediate subobject. For example, assume that grp2 is an immediate subobject of grp1:
OM(SingleWindowApp) -> grp1.grp2 { OM(grp2) ->
|
Up several levels at once
|
After navigating down several levels at once, enter a close brace followed by a semicolon. For example:
OM(grp2) -> }; OM(SingleWindowApp) ->
|
3.2.4.3 Navigating through Applications and libraries
The Applications object and many library objects have the global characteristic. In the context of VCP navigation, global means that you can navigate to an immediate subobject directly, as if the subobject were at the global object's level in the object hierarchy. AVS/Express prints a warning message.
All objects defined with the base type library are global. You can tell if other objects are global if the definition of their type contains +global.
For example, Applications has the global characteristic, so you can navigate directly from Root to SingleWindowApp:
OM(Root) -> SingleWindowApp {
OM warning: jumping from: Root to Root.Applications.SingleWindowApp
OM(SingleWindowApp) ->
If Applications did not have the global characteristic, you would have to do one of the following:
OM(Root) -> Applications {
OM(Applications) -> SingleWindowApp {
OM(SingleWindowApp) ->
or
OM(Root) -> Applications.SingleWindowApp {
OM(SingleWindowApp) ->
You can navigate through several levels of the object hierarchy at once if the object at each level has the global characteristic. This is often the case with libraries:
OM(Root) -> UIbutton {
OM warning: jumping from: Root to Root.Templates.UI.Controls.UIbutton
OM(UIbutton) -> };
When necessary, you can specify a partial pathname. In the following example, you navigate to Templates.MODS.Mappers.isosurface. Templates and Mappers have the global characteristic, so you an omit them in the pathname. MODS does not, so must be included:
OM(Root) -> MODS.isosurface {
OM warning: jumping from: Root to Root.Templates.MODS.Mappers.isosurface
OM(isosurface) ->
3.2.4.4 Navigation commands are really V modify statements
When you navigate down or up the object hierarchy, you are really entering V modify statements.
For example, assume you have a group object called grp1 and you want to assign a value to subobject x. Here is the V modify statement you would enter for grp1:
Notice that this is exactly what you would enter in the VCP. The object's name and the open brace indicate that you want to work with the object's immediate subobjects. The close brace and semicolon at the end indicate that you are finished working with the subobjects.
3.2.4.5 V statement rules apply
Because navigation commands are really modified V statements, V statement rules apply. So, for example, you can split a navigation command across several lines, or enter multiple navigation commands on the same line.
For example, here is how you typically enter navigation commands:
OM(Root) -> SingleWindowApp{
OM(SingleWindowApp) -> grp1 {
OM(grp1) -> x = 3;
OM(grp1) -> int w;
OM(grp1) -> };
OM(SingleWindowApp) -> };
OM(Root) ->
Here is the same example, but with the object name and open brace on separate lines:
OM(Root) -> SingleWindowApp
> {
OM(SingleWindowApp) -> grp1
> {
OM(grp1) -> x = 3;
OM(grp1) -> int w;
OM(grp1) -> };
OM(SingleWindowApp) -> };
OM(Root) ->
Here is the same example, but with consecutive }; on the same line:
OM(Root) -> SingleWindowApp {
OM(SingleWindowApp) -> grp1 {
OM(grp1) -> x = 3;
OM(grp1) -> int w;
OM(grp1) -> };};
OM(Root) ->
Here is the same example, but with everything strung together on the same line. It is difficult to read, but is valid V syntax:
OM(Root) -> SingleWindowApp{grp1{x=3;int w;};};
OM(Root) ->
3.3 V comments
V comments document a V file. You can insert comments into the body of a V file. AVS/Express ignores comments unless they are defined with a special syntax.
You can use:
- C-style comments
- C++-style comments
- Special syntax comments
3.3.1 C-style comments
A C-style comment begins with the delimiter /* and ends with the delimiter */. The delimiters can appear anywhere in the code and can span multiple lines. AVS/Express treats everything between the delimiters as part of the comment.
For example:
/* This is a comment.
AVS/Express ignores it. */
/* Below is a statement, with a comment on the same line. */
int var1; /* This is a comment. */
3.3.2 C++-style comments
A C++-style comment begins with the delimiter //. AVS/Express treats everything to the right of the delimiter to the end of the line as part of the comment.
For example:
// This is a comment.
// AVS/Express ignores it.
// Below is a statement, with a comment on the same line.
int var1; // This is a comment.
3.3.3 Special comments
When you enter a special comment in AVS/Express, it keeps track of the comment. The comment is defined as a special AVS/Express object that is kept as a child of the current object. This comment is displayed in the Network Editor and is saved and restored along with the current object. If the comment is moved or resized in the Network Editor, its size and position are maintained.
Special comments are defined using this syntax:
/*= Here is the body of the comment */
If you want to attach a size and position to the comment, you can use this syntax:
/*=100x50+30+30 Here is the text of the comment */
The statement above creates a comment that is 100x50 units in size and is offset 30 units in X and 30 units in Y. This units are in the same coordinate system as the NEx, NEy, NEwidth, and NEheight properties (usually pixels on most systems).
Special comments are created with a unique name. You can use the $list command to see the comments that you have created:
OM(grp1) -> $list
comment _comment
comment _comment#1
and you can delete them by deleting the object with the _comment name:
3.4 V statements
V statements add, modify, and delete objects. This section first provides an overview of the general coding rules that apply to V statements and then describes each available statement.
3.4.1 General coding rules
The following general coding rules apply to all V statements.
3.4.1.1 Clauses
A V statement consists of one or more clauses, such as object type, name, and value expression, terminated by a semicolon.
For example:
int var1<NEportLevels=2>[] => {a,b};
The clauses in this statement are
<NEportLevels=2> Objects' property specification
[] Array dimension declaration
=> {a,b} Connection expression
3.4.1.2 Order of clauses
Clauses must appear in the order indicated by the syntax.
For example, if a statement specifies both properties and an array declaration, the properties clause appears first:
int var1 <NEportLevels=2> [] => {a,b};
3.4.1.3 Operators
3.4.1.4 Where a statement can start
A statement can start anywhere on a line. It can start on the same line that another statement ends.
3.4.1.5 Separators
Clauses must be separated from one another by spaces, tabs, or newlines. You can insert any number of these between clauses.
Certain clauses use special characters, which can also act as separators. The reference-mode clause uses the special characters ^, &, and *; the array-declarator clause uses [ and ]; the properties clause uses < and >; and the subobjects clause uses { and }. You do not have to code a space, tab, or newline on either side of them.
Separators are not required before the semicolon that terminates a statement.
For example:
group &var1[3]; // Valid.
group&var1[3]; // Valid.
group & var1 [3] ; // Valid.
groupvar1[3]; // Invalid.
In the last example, the object's type and name must be separated from one another with a space, tab, newline, or special character as follows:
3.4.1.6 Continuation lines
A statement can appear on one line or be split across multiple lines. No special formatting is required for continuation lines.
For example, the following statements are equivalent:
3.4.1.7 Continuing character strings
You can continue a character string literal to another line, but the newline character is considered part of the string.
3.4.1.8 Case sensitivity
AVS/Express is case sensitive.
For example, assuming you want the object type to be int, the following statement is invalid:
3.4.2 Create statement
type_and_atts
[
ref_mode]
object_name
[
properties]
[
array_declarator]
[
subobjects]
[
value_expression]
;
The create statement creates an object.
The new object is an immediate subobject of the current object. For example, x is an immediate subobject of grp1:
You can create several objects at once if their types are the same, by separating the object definitions with commas. The terminating semicolon appears at the end of the last object's definition. For example, the following lines create three integer objects:
An object inherits the characteristics of its type. This includes attributes, mode, properties, array declaration, subobjects, and value expression. Characteristics you specify in a create statement override any inherited characteristics.
- The object's type and attributes. In a create statement, an object must be assigned at least one type.
|
|
A previously defined object, typically a base type or a template
|
int x; DefaultCamera camera1;
|
A plus-sign separated list of types and/or attributes
|
|
- The object's reference mode.
|
|
|
group ^x; // Same as group x;
|
|
|
|
|
- The object's name. Typically you specify a new name; i.e., a name that is unique among the object's siblings in the object hierarchy. But you can specify the name of a sibling, in which case AVS/Express deletes the sibling and replaces it with the new definition.
- A name can consist of letters, numbers, and the special characters # and _. In the Network Editor, the character _ appears as a space. A name cannot start with a digit. Names are case sensitive.
- Object properties. An object's properties includes both the properties specified here and any inherited properties.
- The properties clause is enclosed in angle brackets. For example, x has the properties NEx, NEy, and NEportLevels:
int x<NEx=100, NEy=100, NEportLevels={2,0}>;
|
|
prop_name = value
This sets a property to a particular numeric or string value.
|
int x <NEiconName="group">; int x <NEportLevels=2>;
The second example sets x's input and output port levels to 2.
|
prop_name = { value, ...} This sets a property to an array of values.
|
int x <NEportLevels={2,0}>;
This example sets x's input port level to 2 and output port level to 0.
|
- value can be a scalar expression.
- A C-style array declaration.
array_declarator can be...
|
|
[ size] This declares a one dimensional array.
|
int x [10*y]; GDobject_templ &objs [nobjs];
|
[] This declares a one dimensional array of unspecified bounds.
|
int x []; GDobject_templ &objs [];
|
[ size][ size]... This declares a multidimensional array.
|
byte data [height][width];
|
- size can be a scalar integer expression.
- One or more subobjects. Macros, groups, and libraries can have subobjects. Primitive data objects cannot.
- An object has both the subobjects defined here and the subobjects inherited from its type.
- subobjects begins with an open brace, continues with one or more create, modify, or delete statements, and finishes with a close brace.
- For example, grp1's subobject block creates three float objects and an int object:
group grp1
{
float x, y, z;
int a;
};
- This next example creates a group whose type is grp1, so it inherits grp1's subobjects, x, y, z, and a. grp2 creates an additional subobject, w, and modifies inherited subobjects x and y:
grp1 grp2
{
float w; // Create statement.
x<NEportLevels=2> = 1;// Modify statement.
y => varx; // Modify statement.
};
- A scalar or array value expression.
- An expression begins with an assignment (=) or connection (=>) operator, then continues with a C-style expression.
- Here are some examples of value expressions for primitive data objects:
int x
= 4; // Assignment of a constant.
int y
=> x; // Connection to an object.
int z
=> 4*max(a,b,c); // Connection to a multioperand
// expression.
int w[]
=> {x,y,z}; // Connection to an array
// of objects.
- Below is an example of a value expression for a group object. The example connects the object camera_in to the object view.picked_camera:
GDcamera_templ &camera_in
=> view.picked_camera.
3.4.3 Modify statement
[
mode]
object_name
[
additional_types_and_atts]
[
delete_atts]
[
properties]
[
array_declarator]
[
subobjects]
[
value_expression] ;
The modify statement modifies an object's definition. Only those clauses you specify are modified. Other clauses are unchanged.
A modify statement does not begin with a type clause. This is what distinguishes it from a create statement. If you specify a type before the object's name, AVS/Express deletes the existing definition of the object and creates a new one.
The clauses are similar to the create statement. The descriptions below highlight the differences.
- The object's reference mode. It is ^ (by-value), & (by-reference), or * (by-pointer).
- For example, you change object x's reference mode to value:
- The name of the object to be modified. You can specify the current object, one of its immediate subobjects, or, using a pathname, any lower-level subobject.
- For example, you create an object called c1, then change subobject x, one of the inherited subobjects:
group coordinates {
int x, y;
};
coordinates c1 {
x = 3;
};
- Assume you are in the VCP and want to modify subobject x. One way is to first navigate to x:
- Another way is to specify a pathname:
- To modify an object's name, use the V command $set_obj_name. For example, you change object x's name to int1:
additional_types_and_atts
- Additional types to be assigned to the object. additional_types_and_atts begins with a plus sign, followed by one or more plus-sign separated types and/or attributes.
- For example, you add the req and notify attributes to x:
- You cannot remove a previously assigned type. If this is what you want to do, you must recreate the object.
- You can remove a previously assigned attribute, by preceding it with a minus sign:
- You cannot remove a previously assigned object type.
- You can mix delete_atts with additional_types_and_atts. For example:
OM(SingleWindowApp) -> int x;
OM(SingleWindowApp) -> int+notify x;
OM(SingleWindowApp) -> x-notify+write;
OM(SingleWindowApp) -> $print x
int+write x;
- Additional properties and/or modifications to existing properties.
- For example, you set x's NEx property to 100:
- A new array declaration for the object. If the object is currently a single entity, it changes into an array of the specified dimensions. If the object is already an array, its dimensions change to those specified. You cannot change an array into a single entity, except to specify an array of size 1.
- For example:
x
[10]; // Change x to a 10 array.
x
[mdims][3]; // Change x to an mdims by 3 array.
- Additional subobjects and/or modifications or deletions to existing subobjects.
- For example, you modify c1 by modifying subobject x and adding subobject z:
my_coordinates
{
x = 100;
int z;
};
- Caution: Deleting an inherited subobject breaks an object's template hierarchy.
- A new value expression.
- For example, you connect object in to object invert.out:
- Below, you break the connection by specifying a null value expression:
- in =>;
3.4.4 Delete statement
The delete statement deletes an object.
Caution: Deleting an inherited subobject breaks an object's derivation hierarchy.
- The name of the object to be deleted. You can specify the current object, one of its immediate subobjects, or, using a pathname, any lower-level subobject.
For example, you create a macro:
macro mymacro {
Read_Geom geom_1;
Read_Geom geom_2;
Viewer3D Viewer;
};
You then delete geom_1: