Mixed-case SOUL: Difference between revisions
(5 intermediate revisions by 2 users not shown) | |||
Line 28: | Line 28: | ||
Mixed case facilitates the use of a coding style common to most object-oriented languages. | Mixed case facilitates the use of a coding style common to most object-oriented languages. | ||
Historically, <var class=" | Historically, <var class="product">[[Model 204]]</var> <var class="product">User Language</var> was actually a case-sensitive | ||
language with uppercase keywords. | language with uppercase keywords. | ||
This means that keywords such as IF, THEN, FOR, ADD, etc. had to be | This means that keywords such as IF, THEN, FOR, ADD, etc. had to be | ||
Line 34: | Line 34: | ||
There are basically three approaches to providing support for mixed case: | There are basically three approaches to providing support for mixed case: | ||
<ol> | <ol> | ||
<li>Case-sensitive with lowercase or mixed-case keywords. This is the approach used in languages such as [http://en.wikipedia.org/wiki/C_%28programming_language%29 C] and [http://en.wikipedia.org/wiki/Java_%28programming_language%29 Java]. Unfortunately, it was too late for this approach in <var class="product">User Language</var> 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. | <li>Case-sensitive with lowercase or mixed-case keywords. This is the approach used in languages such as [http://en.wikipedia.org/wiki/C_%28programming_language%29 C] and [http://en.wikipedia.org/wiki/Java_%28programming_language%29 Java]. Unfortunately, it was too late for this approach in <var class="product">User Language</var> 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. </li> | ||
<li>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. | <li>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. </li> | ||
<li>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 <var class="product">SOUL</var>. It is probably for these very reasons that many other languages with uppercase keyword roots such as [http://en.wikipedia.org/wiki/Visual_Basic Visual Basic], [http://en.wikipedia.org/wiki/COBOL Cobol], [http://en.wikipedia.org/wiki/Fortran Fortran], and many others have taken the same approach toward providing support for mixed case. | <li>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 <var class="product">SOUL</var>. It is probably for these very reasons that many other languages with uppercase keyword roots such as [http://en.wikipedia.org/wiki/Visual_Basic Visual Basic], [http://en.wikipedia.org/wiki/COBOL Cobol], [http://en.wikipedia.org/wiki/Fortran Fortran], and many others have taken the same approach toward providing support for mixed case. </li> | ||
</ol> | </ol> | ||
It is worth noting that, at least in theory, case-insensitive <var class="product">User Language</var> is a major backward compatibility problem. | It is worth noting that, at least in theory, case-insensitive <var class="product">User Language</var> is a major backward compatibility problem. | ||
Line 61: | Line 61: | ||
variable because they all get internally translated to <code>%CUSTOMER</code> before being processed. | variable because they all get internally translated to <code>%CUSTOMER</code> before being processed. | ||
Similarly, <code>if</code>, <code>If</code>, and <code>IF</code> all get translated to <code>IF</code> before being compiled. | Similarly, <code>if</code>, <code>If</code>, and <code>IF</code> all get translated to <code>IF</code> before being compiled. | ||
This translation is useful in allowing reference to existing uppercase fieldnames | This translation is useful in allowing reference to existing uppercase fieldnames in mixed case. | ||
in mixed case. | |||
For example, field <code>RECTYPE</code> could be referred to as <code>recType</code> when | For example, field <code>RECTYPE</code> could be referred to as <code>recType</code> when | ||
case-insensitive <var class="product">SOUL</var> is enabled. | case-insensitive <var class="product">SOUL</var> is enabled. | ||
Line 69: | Line 68: | ||
they were entered in mixed case. | they were entered in mixed case. | ||
The following sections summarize the entities affected by uppercase translation | The following sections summarize the entities affected by uppercase translation and describe how to invoke it. | ||
and describe how to invoke it. | |||
===What is affected=== | ===What is affected=== | ||
If <var class="product">SOUL</var> case-insensitivity is enabled, these entities become case-insensitive: | If <var class="product">SOUL</var> case-insensitivity is enabled, these entities become case-insensitive: | ||
<ul> | <ul> | ||
<li>'''SOUL keywords'''. For example: <var>For</var>, <var>If</var>, <var>Then</var>, <var>eq</var>. | <li>'''SOUL keywords'''. For example: <var>For</var>, <var>If</var>, <var>Then</var>, <var>eq</var>. </li> | ||
<li>'''Names of members of SOUL classes'''. For example: [[XmlDoc API]], [[File classes|File class]], and [[HTTP Helper]] methods and variables. | <li>'''Names of members of SOUL classes'''. For example: [[XmlDoc API]], [[File classes|File class]], and [[HTTP Helper]] methods and variables. </li> | ||
<li>'''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. | <li>'''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. </li> | ||
<li>'''Labels and subroutine names'''. <p class="note"><b>Note: </b>In this mode, you cannot define two labels whose names differ only because some letters are different case. </p> | <li>'''Labels and subroutine names'''. | ||
<p class="note"><b>Note: </b>In this mode, you cannot define two labels whose names differ only because some letters are different case. </p></li> | |||
<li>'''Field names'''. <p class="note"><b>Note: </b>In this mode, you cannot access field names containing lowercase letters. </p> | <li>'''Field names'''. | ||
<p class="note"><b>Note: </b>In this mode, you cannot access field names containing lowercase letters. </p></li> | |||
<li>'''$functions'''. <p class="note"><b>Note: </b>In this mode, you cannot access $functions containing lowercase letters. </p> | <li>'''$functions'''. | ||
<p class="note"><b>Note: </b>In this mode, you cannot access $functions containing lowercase letters. </p></li> | |||
<li>'''Procedure names''' (on the Include statement). <p class="note"><b>Note: </b>In this mode, you cannot include procedures whose names contain lowercase letters. </p> | <li>'''Procedure names''' (on the Include statement). | ||
<p class="note"><b>Note: </b>In this mode, you cannot include procedures whose names contain lowercase letters. </p></li> | |||
<li>'''SOUL object documentation'''. Keywords and variable name references use mixed case. Keywords will generally be indicated by an uppercase first letter. | <li>'''SOUL object documentation'''. Keywords and variable name references use mixed case. Keywords will generally be indicated by an uppercase first letter. </li> | ||
</ul> | </ul> | ||
Line 115: | Line 117: | ||
</ul> | </ul> | ||
< | ===<b id="sirCaseStmt"></b>How to enable and disable: the Sirius Case statement=== | ||
You can enable case-insensitive <var class="product">SOUL</var> in one of these ways: | You can enable case-insensitive <var class="product">SOUL</var> in one of these ways: | ||
<ul> | <ul> | ||
<li>Start a program with a mixed-case or lowercase <var>Begin</var> statement. | <li>Start a program with a mixed-case or lowercase <var>Begin</var> statement.</li> | ||
<li>Use the <code>Sirius Case ToUpper</code> compiler directive. | <li>Use the <code>Sirius Case ToUpper</code> compiler directive.</li> | ||
<li>Use the <var>[[COMPOPT parameter|COMPOPT]]</var> system parameter to globally enable case-insensitive <var class="product">SOUL</var>.</li> | <li>Use the <var>[[COMPOPT parameter|COMPOPT]]</var> system parameter to globally enable case-insensitive <var class="product">SOUL</var>.</li> | ||
Line 140: | Line 139: | ||
Sometimes, however, one might be working on <var class="product">SOUL</var> that is Included | Sometimes, however, one might be working on <var class="product">SOUL</var> that is Included | ||
in many outer programs, some of which might not have been converted to | in many outer programs, some of which might not have been converted to | ||
case-insensitivity yet. | case-insensitivity yet. In such a case, it is possible to enable internal translation to uppercase | ||
(and so case-insensitivity) with the <var>Sirius Case</var> compiler directive: | |||
<b id="sirCaseSyn"></b>{{Template:Sirius Case statement syntax}} | |||
< | Specifying <var>ToUpper</var> requests internal uppercase translation; <var>Leave</var> means no such translation. | ||
If procedure <code>P</code> contains a complex subroutine that might | |||
be included in outer procedures, some of which might not have been converted | be included in outer procedures, some of which might not have been converted | ||
to use case-sensitivity, you can insert a <var>Sirius Case</var> directive | to use case-sensitivity, you can insert a <var>Sirius Case</var> directive | ||
at the top of procedure: | at the top of the procedure: | ||
<p class="code">sirius case toUpper | <p class="code">sirius case toUpper | ||
Line 194: | Line 191: | ||
<dt>X'04' | <dt>X'04' | ||
<dd>If on, image or image-item names, either literal or in variables, | <dd>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 | are to be automatically converted to uppercase before being used in methods or $functions. | ||
$functions. | |||
Since mixed-case <var class="product">SOUL</var> is accomplished by translating unquoted tokens to | Since mixed-case <var class="product">SOUL</var> is accomplished by translating unquoted tokens to | ||
uppercase, this case conversion for image or image-item names is the runtime | uppercase, this case conversion for image or image-item names is the runtime | ||
equivalent of the compiler mixed-case support. | equivalent of the compiler mixed-case support. | ||
<p> | <p> | ||
Setting the <var>COMPOPT</var> X'04' bit enables image and image-item names that | Setting the <var>COMPOPT</var> X'04' bit enables image and image-item names that appear as literals in <var class="product">SOUL</var> programs to be entered in mixed case. | ||
appear as literals in <var class="product">SOUL</var> programs to be entered in mixed case. | |||
The only time this might be a problem is if there are true mixed-case image | The only time this might be a problem is if there are true mixed-case image | ||
or image-item names in an application. </p> | or image-item names in an application. </p> | ||
Line 211: | Line 206: | ||
image-item names are not likely in most applications. </p> | image-item names are not likely in most applications. </p> | ||
</dl> | </dl> | ||
[[Category:SOUL]] |
Latest revision as of 11:41, 4 August 2019
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:
- 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.
- 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.
- 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
andempAddress
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: ifSirius Case ToUpper
is in effect, it remains in effect even if aSirius 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.