Mixed-case SOUL

From m204wiki
Jump to navigation Jump to search

You can compose a User Language (now SOUL) request in case-insensitive mode. When in this mode, all elements of a SOUL program excepting literal strings are processed after converting lowercase letters to uppercase. SOUL includes enhanced support for mixed case as of version 7.5 of Model 204.

Background

One of the principles generally accepted in object-oriented programming is that variable names and method names should be meaningful, that is, be full words or phrases rather than abbreviations or shorthands. For example, it is generally considered better to call a variable %FIRSTNAME rather than %FN. The reason for this is that most programmers spend much more time reading code than writing it, and meaningful variable names make reading much easier than terse abbreviations. And even when writing code, programmers will typically spend more time thinking about what they are writing than actually typing it and, here again, the thinking process is facilitated with meaningful names.

Meaningful names often involve creation of compound words as variable names such as %OLDESTCHILDBIRTHDATE. As this example illustrates, however, these names can become difficult to read as they become more descriptive. One way to deal with this problem is with the use of separator characters such as underscores or periods, as in %OLDEST_CHILD_BIRTH_DATE or %OLDEST.CHILD.BIRTH.DATE. The problem with this approach, however, is that it can make code look like "special-character soup" with a mish-mash of inter- and intra-variable separator characters which makes visual parsing difficult. The approach most commonly used in object-oriented programming is to use case to separate words in a compound word variable name, for example, %OldestChildBirthDate. There are basically two standards for compound word capitalization: the camel case format, where the first word is not capitalized as in %oldestChildBirthDate, and the Pascal format (after the programming language) where the first word is capitalized, as in %OldestChildBirthDate.

Regardless of the chosen scheme for capitalizing, mixed case is useful for providing code readability. This is true not just for compound variable names, but for SOUL statements in general — imagine if books were written entirely in uppercase. Mixed case facilitates the use of a coding style common to most object-oriented languages.

Historically, Model 204 User Language was actually a case-sensitive language with uppercase keywords. This means that keywords such as IF, THEN, FOR, ADD, etc. had to be written in uppercase. There are basically three approaches to providing support for mixed case:

  1. Case-sensitive with lowercase or mixed-case keywords. This is the approach used in languages such as C and Java. Unfortunately, it was too late for this approach in User Language as the language already has case-sensitivity with uppercase keywords. While it might have been possible to use this approach with lowercase variants of all keywords, such an approach would have been complex, and the case-sensitivity for variable names would make migration to mixed-case code extremely difficult as explained in the next item.
  2. Case-insensitive for keywords but case-sensitive for variable names. A few languages use this approach, but it is quite complex to implement because it makes case-insensitivity of tokens depend upon context. Furthermore, it makes code migration extremely difficult — all references to a variable must be changed to the correct mixed-case variant at once before any of them can be changed. This can be very difficult to do, especially for Common variables that are used in many different pieces of code, so it is likely that any case-sensitive approach would result in some variables remaining indefinitely in uppercase.
  3. Case-insensitivity for keywords and variable names. Because this seemed to provide the best migration path to using mixed case in existing applications, this approach was taken in SOUL. It is probably for these very reasons that many other languages with uppercase keyword roots such as Visual Basic, Cobol, Fortran, and many others have taken the same approach toward providing support for mixed case.

It is worth noting that, at least in theory, case-insensitive User Language is a major backward compatibility problem. Before the mixed-case support, %customer was a different variable from %Customer or %CUSTOMER. Fortunately, because of User Language's requirement for uppercase-only keywords, few people took advantage of this case-sensitivity because it just looked "funny" to have mixed-case variables afloat in a sea of uppercase keywords:

IF %status = 'new' THEN READ SCREEN newCustomer IF %newCustomer:PFKEY EQ 3 THEN STOP END IF END IF

So, probably most existing User Language applications will work fine in case-insensitive mode with no modifications. However, since there is no way for SOUL to know that this is the case, programmers must indicate that programs are to be case-insensitive.

Perhaps somewhat counter-intuitively, case-insensitivity is achieved by internally translating all unquoted tokens to uppercase. That is, %customer, %Customer, and %CUstOMer all refer to the same variable because they all get internally translated to %CUSTOMER before being processed. Similarly, if, If, and IF all get translated to IF before being compiled. This translation is useful in allowing reference to existing uppercase fieldnames in mixed case. For example, field RECTYPE could be referred to as recType when case-insensitive SOUL is enabled. Translation of tokens to uppercase also means that compiler error messages will sometimes indicate names or keywords in uppercase, even though they were entered in mixed case.

The following sections summarize the entities affected by uppercase translation and describe how to invoke it.

What is affected

If SOUL case-insensitivity is enabled, these entities become case-insensitive:

  • SOUL keywords. For example: For, If, Then, eq.
  • Names of members of SOUL classes. For example: XmlDoc API, File class, and HTTP Helper methods and variables.
  • Variable elements. For example: %variables, Screen/Image names and items, Class/Structure members. Note, however, that in this mode you cannot define two variable elements whose names differ only because some letters have different case.
  • Labels and subroutine names.

    Note: In this mode, you cannot define two labels whose names differ only because some letters are different case.

  • Field names.

    Note: In this mode, you cannot access field names containing lowercase letters.

  • $functions.

    Note: In this mode, you cannot access $functions containing lowercase letters.

  • Procedure names (on the Include statement).

    Note: In this mode, you cannot include procedures whose names contain lowercase letters.

  • SOUL object documentation. Keywords and variable name references use mixed case. Keywords will generally be indicated by an uppercase first letter.

What is not affected

If SOUL case-insensitivity is enabled, these entities do not become case-insensitive:

  • Model 204 commands (except for Begin, which is discussed below). Command processing usually works well, however, if you use *UPPER for command input, and let the modifications to the Model 204 editor (including the SIREDIT parameter and the editor CASE command) be in effect for working on SOUL.
  • Quoted strings (in a SOUL request). For example: 'Caps help with veryLongNames'.
  • Literal contents of a Text/Html block. In a Text/Html block, case is preserved for all elements except those enclosed in the evaluation brackets (curly braces). In the following example, empName and empAddress are references to fields named EMPNAME and ADDRESS, respectively:

    Html Name: {empName} Address: {empAddress} End Html

  • Non-compilation elements. Case-insensitive processing applies only to program elements encountered during compilation. For example, when setting a value for a fieldname variable or for Screen or Image indirection, the value must exactly match the name. If you have a field named EMPNAME and you reference it with a fieldname variable, the value used must be all uppercase:

    Begin %x String Len 20 %x = 'EMPNAME' FR Print %%x End For End

How to enable and disable: the Sirius Case statement

You can enable case-insensitive SOUL in one of these ways:

  • Start a program with a mixed-case or lowercase Begin statement.
  • Use the Sirius Case ToUpper compiler directive.
  • Use the COMPOPT system parameter to globally enable case-insensitive SOUL.

Because the following programs begin with mixed-case Begin statements, they are compiled with case-insensitivity:

b print 'Mixed case UL is easy' end

Or:

Begin Print 'Style is everything' End

Sometimes, however, one might be working on SOUL that is Included in many outer programs, some of which might not have been converted to case-insensitivity yet. In such a case, it is possible to enable internal translation to uppercase (and so case-insensitivity) with the Sirius Case compiler directive:

Sirius Case {ToUpper | Leave}

Specifying ToUpper requests internal uppercase translation; Leave means no such translation.

If procedure P contains a complex subroutine that might be included in outer procedures, some of which might not have been converted to use case-sensitivity, you can insert a Sirius Case directive at the top of the procedure:

sirius case toUpper subroutine mixedUp(%confusion is float) ... end subroutine

The Sirius Case directive affects case translation in Included procedures unless explicitly overridden in those procedures. The Sirius Case setting does not affect the procedure that Included the procedure with the setting (so, case-sensitivity in a procedure can never be changed by an Included procedure).

Because the Sirius Case directive is a compiler directive, it is not affected by any programming block structures (such as For loops). It simply affects all lines of code physically after the directive.

Sirius Case Leave can be used to turn off case-insensitivity in cases where case-sensitivity is required or desired. Note, though, that in such cases, all SOUL keywords must be in uppercase.

The COMPOPT system parameter

The system parameter COMPOPT facilitates migration to mixed-case SOUL. COMPOPT is a Model 204 bitmask parameter that must be set in the CCAIN (User 0 input) stream. The bits in COMPOPT have the following meanings:

X'01'
If on, all procedures start out in Sirius Case ToUpper mode, whether or not they begin with a mixed-case Begin statement. Sirius Case ToUpper mode translates all unquoted tokens to uppercase, so SOUL statements, keywords, variable names, etc. may be written in mixed case. By setting the COMPOPT X'01' bit, a site is essentially enabling mixed-case SOUL almost everywhere.
X'02'
If on, Sirius Case Leave compiler directives are to be ignored: if Sirius Case ToUpper is in effect, it remains in effect even if a Sirius Case Leave directive is encountered. Setting the COMPOPT X'02' bit along with the X'01' bit enables mixed-case SOUL everywhere, thus ensuring consistent language processing throughout an Online.
X'04'
If on, image or image-item names, either literal or in variables, are to be automatically converted to uppercase before being used in methods or $functions. Since mixed-case SOUL is accomplished by translating unquoted tokens to uppercase, this case conversion for image or image-item names is the runtime equivalent of the compiler mixed-case support.

Setting the COMPOPT X'04' bit enables image and image-item names that appear as literals in SOUL programs to be entered in mixed case. The only time this might be a problem is if there are true mixed-case image or image-item names in an application.

A true mixed-case image or image-item name is one written in mixed case, either inside quotation marks (image and image-item names can indeed be put in quotes) or without Sirius Case ToUpper in effect. In general, neither of these is too likely, so true mixed-case image or image-item names are not likely in most applications.