🛠️ P3/COBOL 25.1.0-SNAPSHOT is available for preview.
Reference Manual
JAS - Java Augmented Syntax

Java Augmented Syntax (JAS)

⚠️

JAS syntax and semantics is experimental preview and should be considered subject to change in this release of P3/COBOL. While specific changes are not anticipated, the work to fully integrate JAS into P3/COBOL in a way that completely fulfills its intent is ongoing and will likely require (probably minor) adjustments the capability described here. In any case, future changes that would necessitate changes to code written according to the following will be avoided if possible.

✨ JAS is a set of COBOL language extensions that facilitate the incremental migration of legacy COBOL to Java. Specifically, JAS provides the means of expressing business rules within COBOL in a way that is consistent with their Java equivalents. This allows the rules to be expressed in Java by using the JAS expression as model and with only local understanding of the business logic. By providing JAS, P3's use as a means to effectively migrate legacy COBOL business logic to a fully Java implementation in a safe and efficient way is greatly enhanced. It accomplishes this by providing a consistent "stepping stone" means of migration.

Specifically, JAS allows legacy algorithms to be expressed, within the COBOL context as augmented by localized application context information, in a way that allows them to be safely "relocated" into a Java context with only a very narrow understanding of the relocated code required.

This is in contrast to the, usually substantial, task of directly "rewriting" an entire legacy COBOL program into Java. While that approach, when performed automatically using a very low-level understanding of the legacy code as P3 also can do, can yield a functionally identical replica, the resulting Java code is neither extendable nor maintainable by human-programmer. This is in large part due to the many low-level COBOL nuances that must be honored in the generated code in order to ensure the functional fidelity of the transformation. On the other hand, when the same functionally identical application transformation is attempted by a human programmer, his understanding of the entire legacy application must be at the highest level. It is usually impractical to assume this degree of understanding is possessed by every person tasked with the conversion. As the scale of the application increases, the necessary interactions between those who understand the code and those who are converting the code expands geometrically, usually resulting in a failed effort for a large application unless a very large pool of effort and time is available to complete the task. Compounding this problem is the nature of the time period to accomplish the project. Many legacy COBOL business applications cannot be completely migrated before it becomes necessary to modify or update the original application, thus introducing a feedback path for functional changes that inevitably exacerbates the uncertainty of the schedule.

With P3/COBOL and JAS, however, the fully automatic conversion of the legacy COBOL to 100% Java and the relocation of the business rules from the generated Java to hand-crafted Java may be accomplished with substantially reduced risk and cost-uncertainty compared to the "application rewrite" approach. It becomes possible for those knowledgable in the design and implementation of the legacy application and the business rules it contains to refine, in COBOL with JAS, chosen portions of the application in order to replicate the original behavior within a context that can be converted to hand-crafted Java by any Java programmer with only a local understanding of the portion being converted. Furthermore, JAS allows this manual conversion to occur both in situ within the operational COBOL application generated as Java and externally to handcrafted Java classes. This, coupled with the functional generated Java always available, enables a truly incremental and risk-managed approach to business rule migration.

Functional Objectives of JAS Extensions

  1. "Fortify" the language for expression of business rules a. Reduce “fragility” (caused primarily by the COBOL "sentence" concept) and the programming errors associated with it. b. Permit traditional COBOL to be expressed using now-commonly understood programming constructs (in particular Java-aligned syntax alternatives). c. Allow inscrutable legacy COBOL code and logic to be made more "accessible" to non-COBOL programmers (particularly Java programmers). d. Provide the means to "localize" data scope and flow information when appropriate. e. Expose and highlight any elements of non-Java (i.e., COBOL) behavior within JAS expressions.
  2. Increase the "transparency" of the COBOL language a. Support and encourage the replacement of archaic, obscure, obsolete, and error-prone traditional COBOL constructs (e.g., sentence scoping) b. Enhance readability and clarity by enabling the reducion of the visual “noise” of distracting, now obsolete, statement-specific scope delimiters
  3. Enable practical and reliable incremental transition of COBOL business logic to clear, understandable, and maintainable hand-crafted Java.

While meeting these objectives, the solution

  1. Must coexist with traditional COBOL syntax and constructs within the same program (to permit fine-grained incremental enhancement),
  2. Must facilitate semantically identical conversion from traditional COBOL to JAS when desired,
  3. Must be easily usable by long-time COBOL practitioners with minimal training and/or knowledge of Java, and
  4. Must be easily accessible to Java practitioners, including both those with a COBOL background and those with no background or knowledge of COBOL.

P3/COBOL, comprising JAS extensions, meets these objectives within these constraints.

Salient characteristics of JAS

  1. JAS is based on obvious Java analogs, when such analogs are functionally equivalent.
  2. JAS enables very small changes to traditional COBOL programming to achieve significant improvements in readability and comprehension by both Java and COBOL programmers.
  3. JAS is 100% compatible with any traditional COBOL remaining in the application.
  4. JAS is easy to remember/use, especially for programmers adept in a mixed language environment including Java or other "curly-brace" language.
  5. JAS enables improved compile-time detection and diagnosis of common programming errors that are indetectable in traditional COBOL.

Example

For example, in traditional COBOL you might write:

A.
IF CF-CUST-ID GREATER THAN 1000 THEN PERFORM LOOP-A
ELSE IF CF-PRICE-CHANGED COMPUTE NEW-PRICE = OLD-PRICE * (1.01) END-IF
PERFORM LOOP-B.
IF NEW-PRICE GREATER THAN 5000 THEN
    COMPUTE NEW-PRICE = NEW-PRICE - 100.
MOVE NEW-PRICE TO PRICE-FORMATTED.
DISPLAY "New price is " PRICE-FORMATTED.
 
LOOP-A.
...
 
LOOP-B.
...

Using P3/COBOL with JAS, the identical business logic could be written as:

a: {
    if (cf-cust-id > 1000) {
        loop-a;
    } else if (cf-price-changed) {
        new-price := old-price * 1.01;
    } else
        loop-b;
    }
    if (new-price > 5000) {
        new-price -= 100; // apply discount
    }
    price-formatted := new-price;
    display "New price is " price-formatted;
}
loop-a: { ... }
loop-b: { ... }

The JAS version is, to most programmers, much clearer in its intent and, most importantly, does not rely on the placement of period (.) to determine behavior, for example. Moreover, any programmer familiar with any modern programming language will quickly understand the general intent and flow of the JAS code. The same cannot be said for the original COBOL.

Specific areas of the P3/COBOL language supporting JAS equivalents include:

  1. Program (nested Programs) structure and syntax,
  2. Division structure,
  3. Data and Procedure Division section structure,
  4. Section and paragraph structure and syntax,
  5. IF statement structure and syntax,
  6. Statement-list structure, both within JAS statements and within traditional COBOL syntax,
  7. Actual Java business logic embedded in procedure division paragraphs,
  8. Actual Java defined accessible to the entire procedure division, and
  9. New JAS COBOL statements augmented to be aligned to Java, such as TRY/CATCH/FINALLY and FOR/WHILE/DO.

Formal Notation

For the following descriptions of the grammar used for JAS, these notational conventions are used:

  • bold is a reserved word or explicit special character in the P3/COBOL language. For example, division is a reserved word and = is a special character.
  • italicized_word is a grammatical construct defined in another area of this document or according to historical COBOL syntax.
  • ... (ellipsis) denotes the preceding construct or explicit element may occur one or more times.
  • [ and ] surrounding a grammar description indicates that the included grammatical elements are optional (i.e., may be present or not).
  • { and } surrounding grammatical elements groups the enclosed grammatical elements for purposes of applying ..., [], or | to more than one element. Items stacked indicate alternatives and, if they are enclosed in |’s, more than one alternative may occur provided none of the alternatives are repeated. Note that {, [, ], and/or } occurring in bold do not indicate grouping, but represent the explicit open and close curly-brace characters (similar to their Java meaning).

It is important to note that while JAS syntax may be used interchangeably with traditional COBOL syntax, within a JAS syntactic alternate element, only valid JAS may be used. For example, if you choose to use JAS syntax at the program level, then the entire program structure must follow the JAS syntax. However, if you choose to use traditional program structure, but JAS for the procedure division, then only the procedure division contents must conform to JAS syntax. In general at the statement level, traditional syntax is always acceptable, and the JAS form of the IF statement is always acceptable as well. Other than the IF statement described below, the other JAS statement forms may only be used within a JAS statement block, also described below.

Program Structure

Using JAS (at the highest level), a COBOL program can be structured in the following manner:

PROGRAM{programNameliteral}[[IS]{COMMONINITIALRECURSIVE}]\mathsf{PROGRAM} \begin{Bmatrix} \mathit{programName}\\ \mathit{literal} \end{Bmatrix} \begin{bmatrix} \begin{bmatrix} \mathsf{IS} \end{bmatrix} \begin{Bmatrix} \begin{vmatrix} \mathit{COMMON}\\ \mathit{INITIAL}\\ \mathit{RECURSIVE} \end{vmatrix} \end{Bmatrix} \end{bmatrix}

{[environmentDivision][dataDivision][procedureDivision][program]}\lbrace \\ \quad \begin{bmatrix} \mathit{environmentDivision} \end{bmatrix} \\ \quad \begin{bmatrix} \mathit{dataDivision} \end{bmatrix} \\ \quad \begin{bmatrix} \mathit{procedureDivision} \end{bmatrix} \\ \quad \begin{bmatrix} \mathit{program} \end{bmatrix} \\ \rbrace

💡

Note that programs may be nested within other programs to any desired level by simply repeating the above structure at the point of inclusion at the end of the current program’s procedure division. A program_name is any legal COBOL user_defined_word that can be used as the name of a program and a literal is any quoted literal string that can be used as a program name. Note that while the name of the program in the literal form may be any string of characters, it will be modified ("munged") if necessary to form a valid Java class name References to the program name using the same string of characters will be munged in exactly the same manner in order to refer to the intended program.

An example of a P3/COBOL program structured using JAS is:

program count-orders is initial {
    environment division {
        configuration section {
            decimal-point is comma;
        }
    }
    data division {
        working-storage section {
            77 order-count pic 9(9).
        }
    }
    procedure division {
        ...
    }
}

JAS Environment Division

The COBOL environment division may be expressed using JAS in the following manner.

ENVIRONMENT[DIVISION]{[{configurationSectioninputOutputSection}]}\mathsf{ENVIRONMENT} \begin{bmatrix} \mathsf{DIVISION} \end{bmatrix} \lbrace \\ \quad \begin{bmatrix} \begin{Bmatrix} \begin{vmatrix*}[l] \mathit{configurationSection} \\ \mathit{inputOutputSection} \end{vmatrix*} \end{Bmatrix} \end{bmatrix}\\ \rbrace

JAS Data Division

The COBOL data division may be expressed using JAS in the following manner.

DATA[DIVISION]{[{fileSectionworkingStorageSectionlinkageStorageSectionlocalStorageSection}]}\mathsf{DATA} \begin{bmatrix} \mathsf{DIVISION} \end{bmatrix} \lbrace \\ \quad \begin{bmatrix} \begin{Bmatrix} \begin{vmatrix*}[l] \mathit{fileSection} \\ \mathit{workingStorageSection} \\ \mathit{linkageStorageSection} \\ \mathit{localStorageSection} \end{vmatrix*} \end{Bmatrix} \end{bmatrix}\\ \rbrace

Data Division Sections

Within the data division, JAS syntax may be used for the sections as follows:

FILE SECTION{[fileOrSortDescription{dataDescription}]}WORKING-STORAGE SECTION {[dataDescription]}LINKAGE SECTION {[dataDescription]}LOCAL-STORAGE SECTION {[dataDescription]}\mathsf{FILE} \space \mathsf{SECTION} \lbrace \\ \quad \begin{bmatrix} \mathit{fileOrSortDescription} \begin{Bmatrix} \mathit{dataDescription} \end{Bmatrix} \cdots \end{bmatrix} \cdots \\ \rbrace \\ \mathsf{WORKING} \text{-} \mathsf{STORAGE} \space \mathsf{SECTION} \space \lbrace \\ \quad \begin{bmatrix} \mathit{dataDescription} \end{bmatrix} \cdots \\ \rbrace \\ \mathsf{LINKAGE} \space \mathsf{SECTION} \space \lbrace \\ \quad \begin{bmatrix} \mathit{dataDescription} \end{bmatrix} \cdots \\ \rbrace \\ \mathsf{LOCAL} \text{-} \mathsf{STORAGE} \space \mathsf{SECTION} \space \lbrace \\ \quad \begin{bmatrix} \mathit{dataDescription} \end{bmatrix} \cdots \\ \rbrace

Where file_or_sort_description and data_description use the traditional COBOL syntax.

JAS Procedure Division

The COBOL procedure division may be expressed using JAS in the following manner.

[microJavaAnnotation]PROCEDURE[DIVISION][USING usingArguments][{RETURNINGGIVING}dataName]{[javaSection]{[declarative][paragraph]}[section]}\begin{bmatrix} \mathit{microJavaAnnotation} \end{bmatrix} \cdots \mathsf{PROCEDURE} \begin{bmatrix} \mathsf{DIVISION} \end{bmatrix} \begin{bmatrix} \mathsf{USING} \space \mathit{usingArguments} \end{bmatrix} \begin{bmatrix} \begin{Bmatrix*}[l] \mathsf{RETURNING} \\ \mathsf{GIVING} \end{Bmatrix*} \mathit{dataName} \end{bmatrix} \lbrace \\ \quad \begin{bmatrix} \mathit{javaSection} \end{bmatrix} \\ \quad \begin{Bmatrix*}[l] \begin{bmatrix} \mathit{declarative} \end{bmatrix} \cdots \\ \begin{bmatrix} \mathit{paragraph} \end{bmatrix} \cdots \\ \end{Bmatrix*} \\ \quad \begin{bmatrix} \mathit{section} \end{bmatrix} \\ \rbrace

Zero or more microJava annotations may precede the PROCEDURE / PROCEDURE DIVISION header. They are emitted on the generated Program subclass for the current program unit.

Optional Java section

Immediately after the procedure division header and its optional USING / RETURNING / GIVING phrases, and before any declaratives or procedure body, a JAS procedure division may contain a single Java section. The section is a braced JAVA ... END-JAVA block:

procedure division {
    {
        java
            private final P3RuntimeOptions options = getRunUnit().getContext().getOptions();
            boolean p3RegMode = Boolean.parseBoolean(System.getProperty("p3.reg.mode", "false"));
        end-java
    }
 
    main section.
        *> ...
}

Unlike a statement-level JAVA block, which injects executable Java into a generated method body, the Java section injects class-body members into the generated Program subclass for the current program unit. Valid contents are those that would be legal in a Java class body: fields, instance or static initializers, and methods. The enclosed text is parsed as Java class-body declarations.

The Java section is optional and, when present, must appear at most once and must precede the declaratives and the remainder of the procedure division. Statement-level embedded Java elsewhere in the procedure division continues to use ordinary method-body Java; see Java Extensions and Calling Java from P3/COBOL.

Procedure Division Arguments

Within the procedure division using_arguments take the following form:

{[[BY]{REFERENCE[OPTIONAL]VALUE}OPTIONAL]dataName}\begin{Bmatrix} \begin{bmatrix} \begin{bmatrix} \mathsf{BY} \end{bmatrix} \begin{Bmatrix} \mathsf{REFERENCE} \begin{bmatrix} \mathsf{OPTIONAL} \end{bmatrix} \\ \mathsf{VALUE} \end{Bmatrix} \\ \mathsf{OPTIONAL} \end{bmatrix} \mathit{dataName} \end{Bmatrix} \cdots

JAS Sections and Paragraphs

A section within the procedure division may be specified using JAS syntax in the following manner:

sectionName SECTION{[paragraph]}\mathit{sectionName} \space \mathsf{SECTION} \begin{Bmatrix} \begin{bmatrix} \mathit{paragraph} \end{bmatrix} \cdots \end{Bmatrix}

Where the section_name is any user defined word that may be used as a section name.

A paragraph within the procedure division may be specified using JAS syntax in the following manner:

[microJavaAnnotation][{TESTINITIALPUBLIC}]paragraphName[:]{[statement]}\begin{bmatrix} \mathit{microJavaAnnotation} \end{bmatrix} \cdots \begin{bmatrix} \begin{Bmatrix} \mathsf{TEST} \\ \mathsf{INITIAL} \\ \mathsf{PUBLIC} \end{Bmatrix} \end{bmatrix} \mathit{paragraphName} \begin{bmatrix} \mathsf{:} \end{bmatrix} \begin{Bmatrix} \begin{bmatrix} \mathit{statement} \end{bmatrix} \cdots \end{Bmatrix}

Where paragraphName is any user-defined word that may be used as a paragraph name and statement is any valid COBOL or JAS statement. Optional microJava annotations and a single paragraph modifier may precede the paragraph name; see Extended Paragraph Features.

💡

The traditional COBOL sentence is not allowed within JAS-expressed paragraphs. This means that the period separator (.) will never occur inside a JAS paragraph and that no NEXT SENTENCE clauses may be used within the statements comprising the paragraph. Of course the sentence construct may be freely used within traditional syntax paragraphs, which may be intermixed with modern paragraphs within both traditional and JAS sections.

MicroJava Annotations

A microJava annotation injects one or more Java annotations at the next applicable annotation site in the generated Java. The annotation text is written in COBOL source between accent-grave delimiters:

`@SuppressWarnings("serial")`
procedure division {
    `@Tag("smoke")`
    test unit-functions {
        assert (1 + 1 = 2);
    }
}

The text between the accent graves must be valid Java annotation syntax. P3/COBOL validates it as such and emits it unchanged at the corresponding generation point. MicroJava annotations are distinct from statement-level JAVA ... END-JAVA blocks and from the optional Java section.

Supported attachment points:

  • Program class. Zero or more microJava annotations may precede the JAS PROCEDURE / PROCEDURE DIVISION header. They are emitted on the generated Program subclass.
  • Paragraph or wrapper. Zero or more microJava annotations may precede a modern paragraph. When the paragraph also has a test or public modifier, the annotations are emitted on the generated public wrapper method; otherwise they are emitted on the private paragraph method.

Extended Paragraph Features

A modern JAS paragraph (one delimited by {...}) may be marked with a single modifier before the paragraph name. The modifier does not change ordinary COBOL control flow: the paragraph remains a normal procedure and will still execute if control reaches it in the source. If that is not desired, place the paragraph where normal COBOL flow cannot enter it (for example in a section that is never performed from COBOL and is invoked only through the generated Java wrapper).

ModifierGenerated effect
testAlso generates a no-argument public void wrapper whose name is the paragraph's public Java name with Test appended, preceded by @Test. Suitable as a JUnit test entry.
initialRegisters the paragraph to be performed at the end of program initialization (including after cancel and subsequent re-entry). No additional wrapper is generated.
publicAlso generates a no-argument public void wrapper whose name is the paragraph's public Java name, for invocation from Java outside the COBOL call hierarchy.

Example combining a microJava annotation with the test modifier:

`@Tag("smoke")`
test unit-functions {
    assert (1 + 1 = 2);
}

The test modifier already supplies @Test; additional microJava annotations on the paragraph are additive.

These facilities allow COBOL programs to expose business logic to Java GUI, web, and test frameworks without relocating the logic into hand-written Java. See the Mixed Language, Calculator Utility, and Modern Syntax sample projects for examples.

Within both JAS and traditional paragraphs, however, three types of COBOL statements may be specified in JAS syntax as described in the following section.

JAS Statement List

At any point where the traditional COBOL syntax permits a statement list JAS permits the list to be surrounded by {} delimiting a JAS statement block . This allows statement lists to be consistently represented within JAS statements, but it also allows a more Java-aligned scope within traditional statements that allow multiple statements such as PERFORM and EVALUATE.

Alternative Statement Forms

Within any JAS block, some of the traditional COBOL statements may be optionally expressed using equivalent JAS as an alternative to the traditional form. These JAS statements each have an analog in the Java language, together forming a cohort that performs the same or equivalent function, however, the JAS form is much clearer in its intent to a programmer familiar with Java. This permits relatively simple and safe relocation of the equivalent business logic from P3/COBOL to Java. The JAS/Java cohorts are:

  • expression statement
  • if
  • for/do/while
  • continue (within for/do)
  • switch/case
  • break
  • assert
  • try/catch/finally

As you can see, JAS statements are provided for all the Java cohort statements needed to express business logic in a COBOL program. This allows an entirely self-contained business rule to be expressed in a way that is easily and safely relocatable to Java while remaining within the legacy COBOL-language application specification and understandable by the COBOL programmer. Of course actual Java may also be embedded in the COBOL specification using the P3/COBOL embedded Java extensions described elsewhere when accessibility by the COBOL programmer is not required and the understanding of the remaining COBOL dependencies is fully understood.

expression statement

The expression statement is the JAS version of the Java expression cohort. It may be used to invoke (perform) a COBOL procedure (paragraph or section), evaluate a value expression, increment or decrement the value of a numeric item, or create a JAS block-local item with a specified initial value.

Its syntax is as follows:

{[{LETVAR}]assignmentExpression{++}identifierprocedureName}\begin{Bmatrix} \begin{bmatrix} \begin{Bmatrix} \mathsf{LET} \\ \mathsf{VAR} \end{Bmatrix} \end{bmatrix} \mathit{assignmentExpression} \\ \begin{Bmatrix} \underline{++}\\ \underline{--} \end{Bmatrix} \mathit{identifier} \\ \mathit{procedureName} \end{Bmatrix}

assignmentExpression

identifier assignmentOperator valueExpression\mathit{identifier} \space \mathsf{assignmentOperator} \space \mathit{valueExpression}

assignmentOperator

{<<>>>>>+/%:::}=\begin{Bmatrix} \mathsf{<\smash{<}} \\ \mathsf{>>} \\ \mathsf{>>>} \\ \mathsf{+} \\ \mathsf{-} \\ \mathsf{/} \\ \mathsf{*} \\ \mathsf{\%} \\ \mathsf{:} \\ \mathsf{::} \end{Bmatrix} \mathbf{=}

valueExpression

{assignmentExpressionarithmeticExpression}\begin{Bmatrix} \mathit{assignmentExpression} \\ \mathit{arithmeticExpression} \end{Bmatrix}

arithmeticExpression

Is similar to the COBOL COMPUTE statement, but with several powerful extensions. When only JAS syntax is used, it is basically equivalent to the Java expression cohort. When only traditional COBOL syntax is used, it is equivalent to a subset of the traditional COMPUTE statement. When a JAS expression is used, the operator precedence is consistent with the COBOL traditional precedence as augmented by the Java operations allowed:

PrecedenceOperatorTypeAssociativity
14()Parenthesis
Array subscript
Reference modification
Left to Right
13++
--
+
-
!
~
Unary pre-increment
Unary pre-decrement
Unary plus
Unary minus
Unary logical negation
Bitwise complement
Exponentiation
Right to Left
12**ExponentiationLeft to right
11*
/
%
Multiplication
Division
Modulus
Left to right
10+
-
Addition
Subtraction
Left to right
9<<
>>
>>>
Bitwise left shift
Bitwise right shift
Bitwise right shift with 0 extension
Left to right
8<
<=
>
>=
Relational less-than
Relational less-than-or-equal-to
Relational greater-than
Relational greater-than-or-equal-to
Left to right
7==
!=
Relational equal-to
Relational not-equal-to
Left to right
6&Bitwise ANDLeft to right
5^Bitwise exclusive ORLeft to right
4|Bitwise inclusive ORLeft to right
3&&Logical ANDLeft to right
2||Logical ORLeft to right
1=
+=
-=
*=
/=
%=
:=
::=
Assignment
Addition assignment
Subtraction assignment (Numeric only)
Multiplication assignment (Numeric only)
Division assignment (Numeric only)
Modulus assignment (Numeric only)
Value assignment (MOVE equivalent)
Rounded value assignment (Numeric only)
Right to left

The assignment operators that are syntactically the same as their Java cohorts may only be used to assign values to items such that the algebraic value would be assignable in Java employing either an identity conversion, a widening primitive conversion, or a narrowing primitive conversion. In the latter two cases, the actual conversion used is implicit in the JAS assignment. Expressed in Java the conversion must be explicitly stated, of course, but this restriction on JAS assignment allows the assumption of no Java exception conditions occurring during the assignment. This is essential to the desire to expose any COBOL "quirks" in JAS code.

If a traditional COBOL assignment is desired within an assignment expression , JAS provides the special := and ::= assignment operators. When the := operator is used, the assignment is made according to standard COBOL MOVE and COMPUTE rules, including any truncation, loss of precision, or side-effects that might occur. If the expression is enclosed in a try block, then the corresponding catch will occur consistent with the traditional ON EXCEPTION clause of the COMPUTE statement. If arithmetic rounding consistent with the rounded COMPUTE statement is desired, the ::= has that effect.

An example of a JAS expression statement is:

order-count = (filled-order-count += back-order-count);

This is semantically equivalent to the traditional syntax of:

COMPUTE order-count, filled-order-count = filled-order-count + back-order-count

Unlike the traditional COMPUTE with multiple subjects, the JAS expression statement operators result in an intermediate value that is the actual value of the left-hand item in the assignment. This means that any truncation or overflow that occurs in the setting of the left-hand item will then become the value of the expression at that point. If the value is then assigned to another item using an assignment operator, that is the value used. Note also that the JAS expression statement, just as the traditional COMPUTE, may only be used to compute and assign numeric items.

Block-local variables: let and var

Prefixing an assignment expression with let or var declares a new block-local item and assigns its initial value. The compiler infers the item's type from that initializer.

let maximum-orders = order-count + back-order-count;
var orders-remaining = maximum-orders;

A let declaration creates an immutable local. Its initializer is the only assignment permitted; a later direct, compound, increment, or decrement assignment is rejected at compile time. Use var when the local must change.

orders-remaining -= 1;       *> Valid: declared with VAR
maximum-orders = order-count; *> Error: declared with LET

Both forms:

  • require an initializer;
  • declare an unqualified scalar name, without subscripting or reference modification;
  • are scoped to the nearest enclosing JAS block or JAS control statement; and
  • may obscure a data-division item or a local declared in an enclosing block. A duplicate declaration in the same block is rejected.

Braced child blocks of JAS if, for, while, and do statements may all contain local declarations. Each child block forms a separate scope, and its locals are initialized each time control enters that block. A local declared in an enclosing block remains available in nested statement blocks and in the conditions of their enclosing control statements.

The initialization expression of a JAS for statement may itself be a let or var declaration. Like a Java induction variable, that local is scoped to the complete for statement and is available in its condition, iteration expression, and body. The conditions of if and while, including the trailing while condition of do, are boolean expressions and cannot themselves declare locals. They may reference an existing local from an enclosing scope, but a local declared inside a braced child block is not visible in a condition outside that block.

{
    var remaining = 3;
    do {
        let decrement = 1;
        remaining -= decrement;
    } while (remaining > 0)
}

The local exists only as a temporary generated-code value. It is not a COBOL storage item and therefore has no PICTURE, USAGE, level number, or storage address.

if

The COBOL IF statement may be expressed using modern syntax as follows:

IF(condition){{statementList}statement}[ELSE{{statementList}statement}]\mathsf{IF} \begin{pmatrix} \mathit{condition} \end{pmatrix} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \begin{bmatrix} \mathsf{ELSE} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \end{bmatrix}

A simple example of a JAS IF statement is:

if (order-count > 10) {
    order-count = 10;
} else if (order-count < 0) {
    order-count = 0;
} else {
    if (!is-stopping-on-zero) {
        display "bad order count";
    } else {
        exit program;
    }
}

This is semantically identical to the traditional syntax of:

IF order-count > 10
    COMPUTE order-count = 10
ELSE IF order-count < 0
    COMPUTE order-count = 0
ELSE IF NOT IS-STOPPING-ON-ZERO
    DISPLAY "bad order count"
ELSE EXIT PROGRAM.

It should be apparent that the JAS form of this is much clearer as to its intent and much less fragile when/if the logic is modified. Most importantly, the JAS version can be expressed in Java as:

class JasIfDemo {
    public static void main(String[] args){
 
        if (order_count > 10) {
            order_count = 10;
        } else if (order_count < 0) {
            order_count = 0;
        } else {
            if (!is_stopping_on_zero) {
                LOGGER.warning("bad order count");
            } else {
                return 0;
            }
        }
 
    }
}

This Java fragment will function precisely as the P3/COBOL (JAS) version. The Java version requires only that the data references be mapped to their Java syntax (a straightforward, application independent task) and that the traditional COBOL DISPLAY statement be converted into whatever Java equivalent makes sense for the Java system design.

for

The JAS for statement is the structural equivalent to its Java counterpart. The for predicate consists of an initial expression, followed by a loop beginning condition expression, followed by a loop ending expression. The initial expression is unconditionally executed once prior to the looping. For each loop, the condition expression is first evaluated and, if the result is true, the statement list following the predicate is executed. After the statement list is complete or a continue is encountered, the loop ending expression is evaluated and control returns to the loop conditional expression. If the loop condition evaluates to false control passes to the statement following the for statement (list).

FOR(initializationExpression iterationCondition iterationExpression){{statementList}statement}\mathsf{FOR} \begin{pmatrix} \mathit{initializationExpression} \space \mathit{iterationCondition} \space \mathit{iterationExpression} \end{pmatrix} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix}

  • initializationExpression: a JAS assignment statement
  • interationCondition: a COBOL conditional expression
  • iterationExpression: a JAS assignment statement

while

The JAS while statement is structurally equivalent to its Java counterpart. The enclosed statement or statement list is executed repeatedly until either a break statement is executed within the list, or the boolean while expression evaluates to a false value.

WHILE(booleanExpression){{statementList}statement}\mathsf{WHILE} \begin{pmatrix} \mathit{booleanExpression} \end{pmatrix} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix}

  • booleanExpression: is a COBOL conditional expression

do

The JAS do statement is structurally equivalent to its Java counterpart. The enclosed statement list is executed repeatedly until either a break statement is executed within the list, or the while expression following the statement list evaluates to a false value.

DO{{statementList}statement}WHILE(booleanExpression)\mathsf{DO} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \mathsf{WHILE} \begin{pmatrix} \mathit{booleanExpression} \end{pmatrix}

  • booleanExpression: is a COBOL conditional expression

continue

Within a JAS for, while, or do statement, a continue statement does not behave in the conventional COBOL sense. Instead of acting as a no-operation (or empty) statement, the JAS continue acts in a similar manner to the EXIT CYCLE traditional COBOL statement. Namely, it immediately advances control to the end of the nearest enclosing for/while/do statement.

CONTINUE\mathsf{CONTINUE}

switch

JAS provides a Java-consistent form of the traditional COBOL EVALUATE statement that may be expressed within a JAS block as follows:

SWITCH(valueExpression){{{CASEswitchConstant :}{{statementList}statement}DEFAULT :{{statementList}statement}}}\mathsf{SWITCH} \begin{pmatrix} \mathit{valueExpression} \end{pmatrix} \lbrace \\ \quad \begin{Bmatrix} \begin{vmatrix} \begin{Bmatrix} \mathsf{CASE} \mathit{switchConstant} \space \text{:} \end{Bmatrix} \cdots \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \\ \mathsf{DEFAULT} \space \text{:} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \end{vmatrix} \end{Bmatrix} \\ \rbrace

Where statement, subject, and case_clause are expressed using traditional COBOL syntax. Consistent with Java, the JAS switch permits only integer numeric or alphanumeric items to be the subject.

An example of a JAS EVALUATE statement is:

class JasSwitchDemo {
    public static void main(String[] args){
 
        switch (order-count) {
            case -1: {
                order-count = 0;
                display "order count negative; forced to 0";
                break;
            }
            case 99: {
                order-count = 10;
                display "order count excessive; forced to 10";
                break;
            }
            default:
                continue;
        }
 
    }
}
 

This is semantically equivalent to the traditional syntax of:

EVALUATE order-count
    WHEN -1
        COMPUTE order-count = 0
        DISPLAY "order count negative; forced to 0"
    WHEN 99
        COMPUTE order-count = 10
        DISPLAY "order count excessive; forced to 10"
    WHEN OTHER
        CONTINUE
END-EVALUATE

break

The JAS break statement functions in a fashion similar to the COBOL EXIT PERFORM statement when used within a JAS loop structure (see for/while/do). When used within a JAS switch/case/default statement it causes control to transfer to the statement following the current switch statement. In effect, the break always causes control to pass to the next statement following the nearest enclosing (i.e., ancestor) for/while/do/switch statement.

BREAK\mathsf{BREAK}

assert

A JAS statement not corresponding to any legacy COBOL statement is the assert. It serves the same purpose as its Java counterpart, namely to evaluate a boolean expression and, if at runtime it has a false value, throw a runtime exception that may be caught or, if not, terminates the running program. The assertion condition is only evaluated if assertions are enabled for the generated Java program. This allows assertions to be used without performance penalty unless assertions are so enabled.

ASSERT(booleanAssertion)[identifierliteral]\mathsf{ASSERT} \begin{pmatrix} \mathit{booleanAssertion} \end{pmatrix} \begin{bmatrix} \mathit{identifier}\\ \mathit{literal} \end{bmatrix}

  • booleanAssertion: is a COBOL conditional expression whose value is asserted to be true. If, at run time, assertions are enabled and the value is false, the assert throws a Java AssertionError exception with a description comprising the concatenation of the assert statement's arguments.

try

TRY{{statementList}statement}{CATCH{{statementList}statement}FINALLY{{statementList}statement}}\mathsf{TRY} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \begin{Bmatrix} \begin{vmatrix} \mathsf{CATCH} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \\ \mathsf{FINALLY} \begin{Bmatrix} \begin{Bmatrix} \mathit{statementList} \end{Bmatrix} \\ \mathit{statement} \end{Bmatrix} \end{vmatrix} \end{Bmatrix}

Complete Program Example

The following is an example of an entire program coded to use the JAS to the fullest extent possible. Remember, JAS is completely optional and may be freely mixed with traditional COBOL syntax. For example, you may wish to use only the modern form of delimiting statement lists ({...}) and no other JAS elements. Or, you might choose to use JAS IF statement structure without using JAS paragraph or section structure. The only restriction on this intermixing of modern and traditional syntax is that within a modern syntax paragraph no period separators may be used. This is because the entire contents of a modern paragraph consists of statements, not sentences.

You will notice in this example that the ; character is used frequently. The use of ; is entirely consistent with traditional COBOL syntax, in that it is a “noise” character equivalent to a separator space character. It is used here as a matter of style to visually delimit the end of a COBOL statement. As such, it can be replaced by a space or a comma without affecting the program logic.

// This P3/COBOL program illustrating maximum use of Java-augmented syntax (JAS).
// Note that its use is entirely optional, and JAS can be mixed with
// traditional syntax.  In any case, JAS mirrors the traditional COBOL functionality.
 
program sieve-of-eratosthenes {
 
    data division {
 
        working-storage section {
            78 n value 1000. // prime numbers <= this number will be found
            01 primes.
               10 prime-marker binary-char occurs n.
                  88 is-prime value 0 false 1.
            01 output-vars.
               05 last-prime-formatted pic z,zzz,zzz,zzz.
               05 prime-count-formatted pic z,zzz,zzz,zzz.
               05 n-formatted pic z,zzz,zzz,zzz.
        }
    }
 
    procedure division {
 
        main section {
            a: {
                enumerate-primes;
                print-it;
                exit program;
            }
        }
 
        enumerate-primes section {
 
            find-primes using is-prime: {
                let k = n;
                for (let i = 2; i * i <= k; ++i) { // this is the same format as Java, except more than one initializer statement must be enclosed in {} ADD ++i
                    if (is-prime(i)) {
                        for (let j = i * i; j <= k; j += i) { // += is the new additive assignment operator
                            set is-prime(j) to false; // is-prime(j) = false;
                        }
                    }
                }
            }
 
            count-primes: {
                let num-primes = 1; *> count "2" as only even prime
                let largest-prime = 1;
                let k = n;
                for (let i = 3; i <= k; i += 2) {  // += is the new additive assignment operator
                    if (is-prime(i)) {
                        largest-prime = i;
                        ++num-primes;
                    }
                }
                prime-count-formatted := num-primes;
                last-prime-formatted := largest-prime;
            }
        }
 
        print-it section using output-vars {
            a: {
                display last-prime-formatted " is the largest of " prime-count-formatted " primes <= " n-formatted;
            }
        }
    }
}