Mixed-case SOUL: Difference between revisions

From m204wiki
Jump to navigation Jump to search
 
(26 intermediate revisions by 5 users not shown)
Line 1: Line 1:
As of [[Sirius Mods]] version 6.5, you can compose a User Language request in case-insensitive mode.
You can compose a <var class="product">User Language</var> (now <var class="product">SOUL</var>) request in case-insensitive mode.
When in this mode, all elements of a User Language program excepting ''literal strings'' are processed after converting lowercase letters to uppercase.
When in this mode, all elements of a <var class="product">SOUL</var> program excepting ''literal strings'' are processed after converting lowercase letters to uppercase. <var class="product">SOUL</var> includes enhanced support for mixed case as of version 7.5 of <var class="product">Model&nbsp;204</var>.
 
===Background===
===Background===
One of the principles generally accepted in object-oriented programming is that variable
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
names and method names should be meaningful, that is, be full words or phrases
rather than abbreviations or shorthands.
rather than abbreviations or shorthands.
For example, it is generally considered better to call a variable ''%FIRSTNAME'' rather than ''%FN''.
For example, it is generally considered better to call a variable <code>%FIRSTNAME</code> rather than <code>%FN</code>.
The reason for this is that most programmers spend much more time reading code
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
than writing it, and meaningful variable names make reading much easier than
Line 13: Line 14:
the thinking process is facilitated with meaningful names.
the thinking process is facilitated with meaningful names.
                                                                                
                                                                                
Meaningful names often involve creation of compound words as variable names such as ''%OLDESTCHILDBIRTHDATE''.
Meaningful names often involve creation of compound words as variable names such as <code>%OLDESTCHILDBIRTHDATE</code>.
As this example illustrates, however, these names can become difficult to read as they become more descriptive.
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''.
One way to deal with this problem is with the use of separator characters such as underscores or periods, as in <code>%OLDEST_CHILD_BIRTH_DATE</code> or <code>%OLDEST.CHILD.BIRTH.DATE</code>.
The problem with this approach, however, is that it can make code look like &ldquo.special-character soup&rdquo; with a mish-mash of inter- and
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.
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,
The approach most commonly used in object-oriented programming is to use case to separate words in a compound word variable name, for example, <code>%OldestChildBirthDate</code>.
''%OldestChildBirthDate''.
There are basically two standards for compound word capitalization:
There are basically two standards for compound word capitalization:
the [http://en.wikipedia.org/wiki/Camel_case camel case] format, where the first word is not capitalized as in ''%oldestChildBirthDate'', and the [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal] format (after the programming language) where the first word is capitalized, as in ''%OldestChildBirthDate''.
the [http://en.wikipedia.org/wiki/Camel_case camel case] format, where the first word is not capitalized as in <code>%oldestChildBirthDate</code>, and the [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal] format (after the programming language) where the first word is capitalized, as in <code>%OldestChildBirthDate</code>.
                                                                                
                                                                                
Regardless of the chosen scheme for capitalizing, mixed case is useful for providing code readability.
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 User Language
This is true not just for compound variable names, but for <var class="product">SOUL</var>
statements in general &mdash; imagine if books were written entirely in uppercase.
statements in general &mdash; imagine if books were written entirely in uppercase.
To facilitate the use of coding style common to most object-oriented languages,
Mixed case facilitates the use of a coding style common to most object-oriented languages.  
and to make User Language more readable, the [[Janus SOAP User Language Interface]] provides enhanced support for mixed case.


Historically, [[Model 204]] User Language has actually been a case-sensitive
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
written in uppercase.
written in uppercase.
There are basically three approaches to providing support for mixed case:
There are basically three approaches to providing support for mixed case:
#Case-sensitive with lowercase or mixed-case keywords.                    
<ol>
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 is 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,
<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>
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 make case-insensitivity of tokens depend upon context. Furthermore, it makes code migration extremely difficult &mdash; 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 &mdash; 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-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 the Janus SOAP User Language Interface. 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>
It is worth noting that, at least in theory, case-insensitive User Language is a major backward compatibility problem.
</ol>                                                                         
Before the Janus SOAP User Language Interface mixed-case support, ''%customer'' was a different variable
It is worth noting that, at least in theory, case-insensitive <var class="product">User Language</var> is a major backward compatibility problem.
from ''%Customer'' or ''%CUSTOMER''.
Before the mixed-case support, ''%customer'' was a different variable from <code>%Customer</code> or <code>%CUSTOMER</code>.
Fortunately, because of User Language's requirement for uppercase-only keywords, few people took advantage of this case-sensitivity
Fortunately, because of <var class="product">User Language</var>'s requirement for uppercase-only keywords, few people took advantage of this case-sensitivity
because it just looked &ldquo;funny&rdquo; to have mixed-case variables
because it just looked "funny" to have mixed-case variables afloat in a sea of uppercase keywords:
afloat in a sea of uppercase keywords:
<p class="code">IF %status = 'new' THEN
    IF %status = 'new' THEN
    READ SCREEN newCustomer
      READ SCREEN newCustomer
    IF %newCustomer:PFKEY EQ 3 THEN
      IF %newCustomer:PFKEY EQ 3 THEN
      STOP
          STOP
      END IF
     END IF
     END IF
So, ''probably'' most existing User Language applications will work
END IF
</p>
So, ''probably'' most existing <var class="product">User Language</var> applications will work
fine in case-insensitive mode with no modifications.
fine in case-insensitive mode with no modifications.
However, since there is no way for the Janus SOAP User Language Interface to know that this is the case,
However, since there is no way for <var class="product">SOUL</var> to know that this is the case,
programmers must indicate that programs are to be case-insensitive.
programmers must indicate that programs are to be case-insensitive.
                                                                                    
                                                                                    
Perhaps somewhat counter-intuitively, case-insensitivity is achieved
Perhaps somewhat counter-intuitively, case-insensitivity is achieved
by internally translating all unquoted tokens to uppercase.
by internally translating all unquoted tokens to uppercase.
That is, ''%customer'', ''%Customer'', and ''%CUstOMer'' all refer to the same
That is, <code>%customer</code>, <code>%Customer</code>, and <code>%CUstOMer</code> all refer to the same
variable because they all get internally translated to ''%CUSTOMER'' before being processed.
variable because they all get internally translated to <code>%CUSTOMER</code> before being processed.
Similarly, ''if'', ''If'', and ''IF'' all get translated to ''IF'' 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 ''RECTYPE'' could be referred to as ''recType'' when
case-insensitive <var class="product">SOUL</var> is enabled.
case-insensitive User Language is enabled.
Translation of tokens to uppercase also means that compiler error
Translation of tokens to uppercase also means that compiler error
messages will sometimes indicate names or keywords in uppercase, even though
messages will sometimes indicate names or keywords in uppercase, even though
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 User Language case-insensitivity is enabled, these entities become case-insensitive:
If <var class="product">SOUL</var> case-insensitivity is enabled, these entities become case-insensitive:
*'''User Language keywords'''. For example: ''For'', ''If'', ''Then'', ''eq''.
<ul>
*'''Names of members of Janus SOAP classes'''. For example: ''Xml*'', File class, and ''HTTP Helper'' methods and variables.
<li>'''SOUL keywords'''. For example: <var>For</var>, <var>If</var>, <var>Then</var>, <var>eq</var>. </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.
 
*'''Labels and subroutine names'''. Note: In this mode, you cannot define two labels whose names differ only because some letters are different case.
<li>'''Names of members of SOUL classes'''. For example: [[XmlDoc API]], [[File classes|File class]], and [[HTTP Helper]] methods and variables. </li>
*'''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.
<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>
*'''Procedure names''' (on the Include statement). Note: In this mode, you cannot include procedures whose names contain lowercase letters.
 
*'''Janus SOAP object documentation'''. Keywords and variable name references use mixed case. Keywords will generally be indicated by an uppercase first letter.
<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>
 
<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>
 
<li>'''SOUL object documentation'''. Keywords and variable name references use mixed case. Keywords will generally be indicated by an uppercase first letter. </li>
</ul>
 
===What is not affected===
===What is not affected===
If User Language case-insensitivity is enabled, these entities '''do not''' become case-insensitive:
If <var class="product">SOUL</var> 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 User Language.
<ul>
*'''Quoted strings''' (in a User Language request). For example: 'Caps help with veryLongNames'.
<li>'''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 <var>[[SIREDIT parameter|SIREDIT]]</var> parameter and the editor ''CASE'' command) be in effect for working on <var class="product">SOUL</var>.
*'''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
<li>'''Quoted strings''' (in a <var class="product">SOUL</var> request). For example: <code>'Caps help with veryLongNames'</code>.
    Name: {empName}
 
    Address: {empAddress}
<li>'''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, <code>empName</code> and <code>empAddress</code> are references to fields named EMPNAME and ADDRESS, respectively:
    End Html
<p class="code">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:
Name: {empName}
    Begin
Address: {empAddress}
    %x String Len 20
End Html </p>
    %x = 'EMPNAME'
 
    FR
<li>'''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:
      Print %%x
<p class="code">Begin
    End For
%x String Len 20
    End
%x = 'EMPNAME'
===How to enable and disable===                                      
FR
You can enable case-insensitive User Language in one of these ways:
  Print %%x
*Start a program with a mixed-case or lowercase Begin statement.          
End For
*Use the ''Sirius Case ToUpper'' compiler directive.
End </p>
*Use the system [[COMPOPT Parameter|COMPOPT parameter]] to globally enable case-insensitive User Language. This option is only available in Sirius Mods version 6.8 and later.
</ul>
Because the following programs begin with mixed-case Begin statements,
 
===<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:
<ul>
<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>
 
<li>Use the <var>[[COMPOPT parameter|COMPOPT]]</var> system parameter to globally enable case-insensitive <var class="product">SOUL</var>.</li>
</ul>
Because the following programs begin with mixed-case <var>Begin</var> statements,
they are compiled with case-insensitivity:
they are compiled with case-insensitivity:
    b
<p class="code">b
      print 'Mixed case UL is easy'
  print 'Mixed case UL is easy'
    end
end </p>
or
Or:
    Begin
<p class="code">Begin
      Print 'Style is everything'
  Print 'Style is everything'
    End
End </p>
Prior to Sirius Mods version 6.5, a mixed-case Begin statement was not recognized
                                                                         
as the start of a program, so no programs created prior to that version will
Sometimes, however, one might be working on <var class="product">SOUL</var> that is Included
accidentally start using case-insensitivity.
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
Sometimes, however, one might be working on User Language that is Included
(and so case-insensitivity) with the <var>Sirius Case</var> compiler directive:
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
<b id="sirCaseSyn"></b>{{Template:Sirius Case statement syntax}}
(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
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 Sirius Case 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:
  sirius case toUpper
 
  subroutine mixedUp(%confusion is float)
<p class="code">sirius case toUpper
    ...
subroutine mixedUp(%confusion is float)
  end subroutine
  ...
The ''Sirius Case'' directive affects case translation in Included
end subroutine </p>
 
The <var>Sirius Case</var> directive affects case translation in Included
procedures unless explicitly overridden in those procedures.
procedures unless explicitly overridden in those procedures.
The ''Sirius Case'' setting does '''not''' affect the procedure
The <var>Sirius Case</var> setting does '''not''' affect the procedure
that Included the procedure with the setting
that Included the procedure with the setting
(so, case-sensitivity in a procedure can never be changed by an Included procedure).
(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
Because the <var>Sirius Case</var> directive is a compiler directive, it is not
affected by any programming block structures (such as ''For'' loops).
affected by any programming block structures (such as <var>For</var> loops).
It simply affects all lines of code physically after the directive.
It simply affects all lines of code physically after the directive.


''Sirius Case Leave'' can be used to turn off case-insensitivity in
<code>Sirius Case Leave</code> can be used to turn off case-insensitivity in
cases where case-sensitivity is required or desired.
cases where case-sensitivity is required or desired.
Note, though, that in such cases, all User Language keywords must be in uppercase.
Note, though, that in such cases, all <var class="product">SOUL</var> keywords must be in uppercase.
   
   
In Sirius Mods version 6.5, field and screen name variable contents
are not converted to uppercase at run-time, so they must be loaded with
uppercase fieldnames or screen item names:
  if %custId ne '' then
      %field = 'CUSTID'
      %value = %custId
  else
      %field = 'LASTNAME'
      %value = %lastName
  end if
  find to %recordSet
      %%field eq %value
  end find
====The COMPOPT system parameter====
====The COMPOPT system parameter====
As of Sirius Mods version 6.8, the system parameter ''COMPOPT'' facilitates migration to mixed-case User Language.
The system parameter <var>[[COMPOPT parameter|COMPOPT]]</var> facilitates migration to mixed-case <var class="product">SOUL</var>.
COMPOPT is a [[Model 204]] bitmask parameter that must be set in the CCAIN (User 0 input) stream.
<var>COMPOPT</var> 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:
The bits in <var>COMPOPT</var> have the following meanings:
<dl>
<dl>
<dt>X'01'
<dt>X'01'
<dd>If on, all procedures start out in ''Sirius Case ToUpper'' mode,
<dd>If on, all procedures start out in <code>Sirius Case ToUpper</code> mode,
whether or not they begin with a mixed-case ''Begin'' statement.
whether or not they begin with a mixed-case <var>Begin</var> statement.
''Sirius Case ToUpper'' mode translates all unquoted tokens to uppercase, so
<code>Sirius Case ToUpper</code> mode translates all unquoted tokens to uppercase, so
User Language statements, keywords, variable names, etc. may be written in mixed case.
<var class="product">SOUL</var> 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 &UL. almost everywhere.
By setting the <var>COMPOPT</var> X'01' bit, a site is essentially enabling mixed-case <var class="product">SOUL</var> almost everywhere.
 
<dt>X'02'
<dt>X'02'
<dd>If on, ''Sirius Case Leave'' compiler directives are to be ignored:
<dd>If on, <code>Sirius Case Leave</code> compiler directives are to be ignored:
if ''Sirius Case ToUpper'' is in effect, it remains in effect even
if <code>Sirius Case ToUpper</code> is in effect, it remains in effect even
if a ''Sirius Case Leave'' directive is encountered.
if a <code>Sirius Case Leave</code> directive is encountered.
Setting the ''COMPOPT'' X'02' bit along with the X'01' bit enables mixed-case User Language
Setting the <var>COMPOPT</var> X'02' bit along with the X'01' bit enables mixed-case <var class="product">SOUL</var>
everywhere, thus ensuring consistent language processing throughout an
everywhere, thus ensuring consistent language processing throughout an Online.
Online.
 
<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 User Language 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>
Setting the ''COMPOPT'' 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 User Language 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.
or image-item names in an application. </p>
<p>
A true mixed-case image or image-item name is one written in mixed case,
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''
either inside quotation marks (image and image-item names can ''indeed''
be put in quotes) or without ''Sirius Case ToUpper'' in effect.
be put in quotes) or without <code>Sirius Case ToUpper</code> in effect.
In general, neither of these is too likely, so true mixed-case image or
In general, neither of these is too likely, so true mixed-case image or
image-item names are not likely in most applications.
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:

  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.