Using Caché ObjectScript
Syntax Rules
[Back] [Next]
   
Server:docs2
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

This chapter describes the basic rules of ObjectScript syntax. Topics include:

Case Sensitivity
Some parts of ObjectScript are case-sensitive while others are not. Generally speaking, the user-definable parts of ObjectScript are case-sensitive while keywords are not:
Identifiers
User-defined identifiers (variable, routine, and label names) are case-sensitive. String, string, and STRING all refer to different variables. Global variable names are also case-sensitive, whether user-defined or system-supplied.
Note:
Caché SQL identifiers, in contrast, are not case-sensitive.
Keyword Names
Command, function, and system variable keywords (and their abbreviations) are not case-sensitive. You can use Write, write, WRITE, W, or w; all refer to the same command.
Class Names
All identifiers related to classes (class names, property names, method names, etc.) are case-sensitive. For purposes of uniqueness, however, such names are considered to be not case-sensitive; that is, two class names cannot differ by case alone.
Namespace Names
Namespace names are not case-sensitive, meaning that you can input a namespace name in any combination of uppercase and lowercase letters. Note however, that Caché always stores namespace names in uppercase. Therefore, Caché may return a namespace name to you in uppercase rather than in the case which you specified. For further details on namespace naming conventions, see Namespaces.
Unicode
Unicode characters are 16-bit characters, also known as wide characters. Your instance of Caché supports the Unicode international character set if you selected the Unicode option during Caché installation. If you selected the 8-bit option during Caché installation, characters beyond $CHAR(255) are not supported; the $CHAR function returns the empty string for integers larger than 255. The $ZVERSION special variable and the $SYSTEM.Version.IsUnicode() method show if your Caché installation supports Unicode.
On a Unicode installation of Caché, some names can contain Unicode letter characters, while other names cannot contain Unicode letters. Unicode letters are defined as alphabetic characters with ASCII values higher than 255. For example, the Greek lowercase lambda is $CHAR(955), a Unicode letter.
Unicode letter characters are permitted throughout Caché, with the following exceptions:
Note:
The Japanese locale does not support accented Latin letter characters in Caché names. Japanese names may contain (in addition to Japanese characters) the Latin letter characters A-Z and a-z (65–90 and 97–122), and the Greek capital letter characters (913–929 and 931–937).
Whitespace
Under certain circumstances, ObjectScript treats whitespace as syntactically meaningful. Unless otherwise specified, whitespace refers to blank spaces, tabs, and line feeds interchangeably. In brief, the rules are:
The Caché Studio provides built-in syntax checking, so that it will mark any illegal use of whitespace, such as the following insertion of multiple spaces before a command’s first argument:
Studio Syntax Checking
Comments
It is good practice to use comments to provide in-line documentation in code, as they are a valuable resource when modifying or maintaining code. Caché ObjectScript supports several types of comments which can appear in several kinds of locations:
Comments in INT Code for Routines and Methods
Within INT code, several types of comments are available, all of which must start in column 2 or greater:
A multiline comment (/* comment */) can be placed between command or function arguments, either before or after a comma separator. A multiline comment cannot be placed within an argument, or be placed between a command keyword and its first argument or a function keyword and its opening parenthesis. It can be placed between two commands on the same line, in which case it functions as the single space needed to separate the commands. You can immediately follow the end of a multiline comment (*/) with a command on the same line, or follow it with a single line comment on the same line. The following example shows these insertions of /* comment */ within a line:
  WRITE $PIECE("Fred&Ginger"/* WRITE "world" */,"&",2),!
  WRITE "hello",/* WRITE "world" */" sailor",!
  SET x="Fred"/* WRITE "world" */WRITE x,!
  WRITE "hello"/* WRITE "world" */// WRITE " sailor"
 
Comments in MAC Code for Routines and Methods
All comment types that are valid for INT code are also valid for MAC code and behave in MAC code just as they do in INT code. Two other comment types are also available:
Comments in Class Definitions Outside of Method Code
Within class definitions, but outside of method definitions, several comment types are available, all of which can start in any column:
Literals
A literal is a constant value consisting of a series of characters that represents a particular string or numeric value, such as “Hello” and “5” below:
  SET x = "Hello"
  SET y = 5
ObjectScript recognizes two types of literals:
String Literals
A string literal is a set of zero or more characters delimited by quotation marks (unlike string literals, numeric literals do not need delimiters). Caché ObjectScript string literals are delimited with double quotation marks (for example, "myliteral"); Caché SQL string literals are delimited with single quotation marks (for example, 'myliteral'). These quotation mark delimiters are not counted in the length of the string.
A string literal can contain any characters, including whitespace and control characters. The length of a string literal is measured as the number of characters in the string, not the number of bytes. A string can contain just 8-bit ASCII characters. On Unicode systems, a string can also contain 16-bit Unicode characters (known as wide characters). If you include a single wide character in a string, Caché will represent all characters in the string as 16-bit characters. Because Caché almost always treats a string as characters, not bytes, this use of wide characters is usually invisible to the user. (One exception is the ZZDUMP command, as shown below.)
The maximum string size is configurable. If long strings are enabled, the maximum string size to 3,641,144 characters. Otherwise, the maximum string size is 32,767 characters. Long strings are enabled by default. See the Long Strings section in the “Data Types and Values” chapter.
The following Unicode example shows a string of 8-bit characters, a string of 16-bit characters (Greek letters), and a combined string:
  DO AsciiLetters
  IF $SYSTEM.Version.IsUnicode()  {
    DO GreekUnicodeLetters
    DO CombinedAsciiUnicode
    RETURN }
  ELSE { WRITE "Unicode not supported"
         RETURN }
AsciiLetters()
  SET a="abc"
  WRITE a
  WRITE !,"the length of string a is ",$LENGTH(a)
  ZZDUMP a
GreekUnicodeLetters()
  SET b=$CHAR(945)_$CHAR(946)_$CHAR(947)
  WRITE !!,b
  WRITE !,"the length of string b is ",$LENGTH(b)
  ZZDUMP b
CombinedAsciiUnicode()
  SET c=a_b
  WRITE !!,c
  WRITE !,"the length of string c is ",$LENGTH(c)
  ZZDUMP c
 
Not all string characters are typeable. You can specify non-typeable characters using the $CHAR function, as shown in the following Unicode example:
  SET greekstr=$CHAR(952,945,955,945,963,963,945)
  WRITE greekstr
 
Not all string characters are displayable. They can be non-printing characters or control characters. The WRITE command represents non-printing characters as a box symbol. The WRITE command causes control characters to execute. In the following example, a string contains printable characters alternating with the Null ($CHAR(0)), Tab ($CHAR(9)) and Carriage Return ($CHAR(13)) characters:
  SET a="a"_$CHAR(0)_"b"_$CHAR(9)_"c"_$CHAR(13)_"d"
  WRITE !,"the length of string a is ",$LENGTH(a)
  ZZDUMP a
  WRITE !,a
 
Note that the WRITE command executes some control characters from the Terminal command line which WRITE executing in a program displays as non-printing characters. For example, the Bell ($CHAR(7)) and Vertical Tab ($CHAR(11)) characters.
To include the quotation mark character (") within a string, double the character, as shown in the following example:
  SET x="This quote"
  SET y="This "" quote"
  WRITE x,!," string length=",$LENGTH(x)
  ZZDUMP x
  WRITE !!,y,!," string length=",$LENGTH(y)
  ZZDUMP y
 
A string that contains no value is known as a null string. It is represented by two quotation mark characters (""). A null string is considered to be a defined value. It has a length of 0. Note that the null string is not the same as a string consisting of the null character ($CHAR(0)), as shown in the following example:
  SET x=""
  WRITE "string=",x," length=",$LENGTH(x)," defined=",$DATA(x)
  ZZDUMP x
  SET y=$CHAR(0)
  WRITE !!,"string=",y," length=",$LENGTH(y)," defined=",$DATA(y)
  ZZDUMP y
 
For further details on strings, refer to Strings in the “Data Types and Values” chapter of this manual.
Numeric Literals
Numeric literals are values that ObjectScript evaluates as numbers. They do not require delimiters. Caché converts numeric literals to canonical form (their simplest numeric form):
   SET x = ++0007.00
   WRITE "length:     ",$LENGTH(x),!
   WRITE "value:      ",x,!
   WRITE "equality:   ",x = 7,!
   WRITE "arithmetic: ",x + 1
 
You can also represent a number as a string literal delimited with quotation marks; a numeric string literal is not converted to canonical form, but can be used as a number in arithmetic operations:
   SET y = "++0007.00"
   WRITE "length:     ",$LENGTH(y),!
   WRITE "value:      ",y,!
   WRITE "equality:   ",y = 7,!
   WRITE "arithmetic: ",y + 1
 
For further details refer to Strings as Numbers in the “Data Types and Values” chapter of this manual.
ObjectScript treats as a number any value that contains the following (and no other characters):
Value Quantity
The digits 0 through 9. Any quantity, but at least one.
Sign operators: Unary Minus (-) and Unary Plus (+). Any quantity, but must precede all other characters.
The decimal_separator character (by default this is the period or decimal point character; in European locales this is the comma character). At most one.
The Letter “E” (used in scientific notation). At most one. Must appear between two numbers.
For further details on the use and interpretation of these characters, refer to Fundamentals of Numbers in the “Data Types and Values” chapter.
ObjectScript can work with the following types of numbers:
Identifiers
An identifier is the name of a variable, a routine, or a label. In general, legal identifiers consist of letter and number characters; with few exceptions, punctuation characters are not permitted in identifiers. Identifiers are case-sensitive.
The naming conventions for user-defined commands, functions, and special variables are more restrictive (only letters permitted) than identifier naming conventions. Refer to Extending Languages with ^%ZLANG Routines in Caché Specialized System Tools and Utilities.
Naming conventions for local variables, process-private globals, and globals are provided in the Variables chapter of this document.
Punctuation Characters within Identifiers
Certain identifiers can contain one or more punctuation characters. These include:
Note that globals and process-private globals are identified by a caret (^) prefix of one or more characters, such as the following:
  Globals:                               Process-Private Globals:
^globname                                ^||ppgname
^|""|globname                            ^|"^"|ppgname
^|"mynspace"|globname            ^|"^",""|ppgname
^["mynspace"]globname          ^["^"]ppgname
These prefix characters are not part of the variable name; they identify the type of storage and (in the case of globals) the namespace used for this storage. The actual name begins after the final vertical bar or closing square bracket.
Labels
Any line of ObjectScript code can optionally include a label (also known as a tag). A label serves as a handle for referring to that line location in the code. A label is an identifier that is not indented; it is specified in column 1. All Caché ObjectScript commands must be indented.
Labels have the following naming conventions:
Note:
A block of ObjectScript code specified in an SQL command such as CREATE PROCEDURE or CREATE TRIGGER can contain labels. In this case, the first character of the label is prefixed by a colon (:) specified in column 1. The rest of the label follows the naming and usage requirements describe here.
A label can include or omit parameter parentheses. If included, these parentheses may be empty or may include one or more comma-separated parameter names. A label with parentheses identifies a procedure block.
A line can consist of only a label, a label followed by one or more commands, or a label followed by a comment. If a command or a comment follows the label on the same line, they must be separated from the label by a space or tab character.
The following are all unique labels:
maximum
Max
MAX
86
agent86
86agent
%control
You can use the $ZNAME function to validate a label name. Do not include parameter parentheses when validating a label name.
You can use the ZINSERT command to insert a label name into source code.
Using Labels
Labels are useful for identifying sections of code and for managing flow of control.
The DO and GOTO commands can specify their target location as a label. The $ZTRAP special variable can specify the location of its error handler as a label. The JOB command can specify the routine to be executed as a label.
Labels are also used by the PRINT, ZPRINT, ZZPRINT, ZINSERT, ZREMOVE, and ZBREAK commands and the $TEXT function to identify source code lines.
However, you cannot specify a label on the same line of code as a CATCH command, or between a TRY block and a CATCH block.
Ending a Labelled Section of Code
A label provides an entry point, but it does not define an encapsulated unit of code. This means that once the labelled code executes, execution continues into the next labelled unit of code unless execution is stopped or redirected elsewhere. There are three ways to stop execution of a unit of code:
In the following example, code execution continues from the code under “label0” to that under “label1”:
  SET x = $RANDOM(2)
  IF x=0 {DO label0
           WRITE "Finished Routine0",!
           QUIT }
  ELSE {DO label1
           WRITE "Finished Routine1",!
           QUIT }
label0
  WRITE "In Routine0",!
  FOR i=1:1:5 {
      WRITE "x = ",x,!
      SET x = x+1 }
  WRITE "At the end of Routine0",!
label1
  WRITE "In Routine1",!
  FOR i=1:1:5 {
      WRITE "x = ",x,!
      SET x = x+1 }
  WRITE "At the end of Routine1",!
 
In the following example, the labeled code sections end with either a QUIT or RETURN command. This causes execution to stop. Note that RETURN always stops execution, QUIT stops execution of the current context:
  SET x = $RANDOM(2)
  IF x=0 {DO label0
           WRITE "Finished Routine0",!
           QUIT }
  ELSE {DO label1
           WRITE "Finished Routine1",!
           QUIT }
label0
  WRITE "In Routine0",!
  FOR i=1:1:5 {
      WRITE "x = ",x,!
      SET x = x+1
      QUIT }
  WRITE "Quit the FOR loop, not the routine",!
  WRITE "At the end of Routine0",!
  QUIT
  WRITE "This should never print"
label1
  WRITE "In Routine1",!
  FOR i=1:1:5 {
      WRITE "x = ",x,!
      SET x = x+1 }
  WRITE "At the end of Routine1",!
  RETURN
  WRITE "This should never print"
 
In the following example, the second and third labels identify procedure blocks (a label specified with parameter parentheses). Execution stops when encountering a procedure block label:
  SET x = $RANDOM(2)
  IF x=0 {DO label0
           WRITE "Finished Routine0",!
           QUIT }
  ELSE {DO label1
           WRITE "Finished Routine1",!
           QUIT }
label0
  WRITE "In Routine0",!
  FOR i=1:1:5 {
      WRITE "x = ",x,!
      SET x = x+1 }
  WRITE "At the end of Routine0",!
label1()
  WRITE "In Routine1",!
  FOR i=1:1:5 {
      WRITE "x = ",x,!
      SET x = x+1 }
  WRITE "At the end of Routine1",!
label2()
  WRITE "This should never print"
 
Namespaces
A namespace name may be an explicit namespace name or an implied namespace name. An explicit namespace name is not case sensitive; regardless of the case of the letters with which it is input, it is always stored and returned in uppercase letters.
In an explicit namespace name, the first character must be a letter or a percent sign (%). The remaining characters must be letters, numbers, hyphens (–), or underscores (_). The name cannot be longer than 255 characters.
When Caché translates an explicit namespace name to a routine or class name (for example, when creating a cached query class/routine name), it replaces punctuation characters with lowercase letters, as follows: % = p, _ = u, – = d. An implied namespace name may contain other punctuation characters; when translating an implied namespace name, these punctuation characters are replaced by a lowercase "s". Thus the following seven punctuation characters are replaced as follows: @ = s, : = s, / = s, \ = s, [ = s, ] = s, ^ = s.
The following namespace names are reserved: %SYS, BIN, BROKER, DOCBOOK and DOCUMATIC.
When using the Caché SQL CREATE DATABASE command, creating an SQL database creates a corresponding Caché namespace.
When using Caché MultiValue, creating a MultiValue account creates a corresponding Caché namespace. The naming conventions for MultiValue accounts and Caché namespaces differ. For details about how MultiValue account names are translated to namespace names, refer to the CREATE.ACCOUNT command in the Caché MultiValue Commands Reference.
For information on using namespaces, see Namespaces and Databases in the Caché Programming Orientation Guide. For information on creating namespaces, see Configuring Namespaces in the Caché System Administration Guide.
Extended References
An extended reference is a reference to an entity that is located in another namespace. The namespace name can be specified as a string literal enclosed in quotes, as a variable that resolves to a namespace name, as an implied namespace name, or as a null string ("") a placeholder that specifies the current namespace. There are three types of extended references:
All extended references can, of course, specify the current namespace, either explicitly by name, or by specifying a null string placeholder.
Reserved Words
There are no reserved words in Caché ObjectScript; you can use any valid identifier as a variable name, function name, or label. At the same time, it is best to avoid using identifiers that are command names, function names, or other such strings. Also, since ObjectScript code includes support for embedded SQL, it is prudent to avoid naming any function, object, variable, or other entity with an SQL reserved word, as this may cause difficulties elsewhere.