ESL0004 - Removing the end keyword

LEP

ESL0004

Author(s)

  1. Wilschut

Reviewer(s)

A.T. Hofkamp, T.J.L. Schuijbroek

Status

Accepted

Type

Standard (S)

Created

30-10-2019

Finalized

t.b.d.

Abstract

The end keyword, used to close a list of subclauses or a list of parameters of a bundle, is rather ‘techy’ and does not fit well within the natural language concept of ESL. Therefore, a syntax modification is proposed where the end keyword is no longer needed.

In the new syntax, all lines within a list, that was formerly closed with the end keyword, start with an asterisk. Furthermore, to prevent ambiguity, anonymous bundles are no longer allowed and groups are introduced to allow for (un)packing of declared variables.

Motivation

ESL is a natural language orientated specification language. The end keyword, used to close a list of subclauses or a list of parameters of a bundle, is rather ‘techy’ and does not fit well within the natural language concept. Moreover, the end keyword is only used to end a subset of listings. For example, it is needed to close a list of subclauses but not needed to close an argument list. This is rather inconsistent. Hence, a new syntax is proposed in which the end keyword is removed.

Rationale

Natural language oriented mark-up languages, such as Markdown (md) and reStructuredText (rst), typically use markers to indicated the items that are part of a list. Leading white space is used to indicate the level of nesting of items within a list. For example, the following listing shows a markdown example of a two level nested list.

1
2
3
4
5
6
7
8
my two level nested list:

* Item 1

  * Item 1.1
  * Item 1.2

* Item 2

In the new ESL syntax list item markers are used to indicate the items that are part of a list. For example, a specification of a goal-requirement gr-01 in the current version of ESL:

1
2
3
4
5
goal-requirement
  gr-01: blob must provide faa to blab with subclauses
    max-faa: faa must be at most 10 l/s
    min-faa: faa must be at least 5 l/s
  end

can easily be written as:

1
2
3
4
goal-requirement
  gr-01: blob must provide faa to blab with subclauses
    * max-faa: faa must be at most 10 l/s
    * min-faa: faa must be at least 5 l/s

where the end keyword is no longer needed. Bullet lists are commonly used in many languages and text editors. Therefore, item markers are considered to be a suitable replacement for the end keyword.

Nesting

The introduction of item markers, however, results in ambiguity within the definition of nested bundles. For example, in the listing below the bundle definition of foo it is ambiguous whether fee is an entry within the foo bundle or within the fii bundle if one ignores the indentation level (as the ESL compiler does).

1
2
3
4
5
6
define type
  foo is a bundle of
    * fii is a bundle of
      * fuu is a real
      * faa is a real
    * fee is a real

This issue could be resolved by making white space meaningful. That is, the indentation level of fee could indicate that it is an entry within the foo bundle rather than the fii bundle. However, bundles are the only ESL language construct in which an arbitrary level of nesting is allowed. Moreover, multi-level nested bundle definitions can easily be avoided by creating additional types. For example, in:

1
2
3
4
5
6
7
8
define type
  fuu-faa is a bundle of
    * fuu is a real
    * faa is a real

  foo is a bundle of
    * fii is a fuu-faa
    * fee is a real

the type foo-faa is defined and subsequently assigned to the fii entry within the foo bundle. This solution is preferred over nestings of arbitrary depth as it provides better readability. Therefore, nested bundle definitions are no longer allowed and white space remains meaningless.

Packing and unpacking of variables

In the current version of ESL one can pack and unpack variables using anonymous bundles. For example, in the listing below component definition blob (line 12) has parameters x-and-y which has type x-y-bundle and q and r which are both of type real. At world level we have the variables x and y which have type real and z which has type q-r-bundle. Upon instantiation of blob (line 24) variables x and y are packed into a bundle and variables q and r are unpacked from z, such that the argument list matches the parameter list.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
define type
  x-y-bundle is a bundle of
    x is a real
    y is a real
  end

  q-r-bundle is a bundle of
    q is a real
    r is a real
  end

define component blob
  parameter
    x-and-y is a x-y-bundle
    q is a real
    r is real

world
  variables
    x, y is a real
    z is a q-r-bundle

  component
    blib is a blob with arguments
      bundle of
        x
        y
      end
      z.q
      z.r

This mechanism fails when introducing the item markers. For example, removing the end keyword from the anonymous bundle and introducing the asterisk yields the following instantiation of blib:

1
2
3
4
5
6
7
component
  blib is a blob with arguments
    * bundle of
      * x
      * y
    * z.q
    * z.r

From this specification it is impossible to drive whether z.q and z.r are part of the anonymous bundle if one ignores the indentation level (as the ESL compiler does). As such, it becomes impossible to match the argument list with the parameter list.

This problem is solved by no longer allowing anonymous bundles and introducing variable groups to enable packing and unpacking of variables. For example, in the listing below group x-and-y is declared which contains variables x and y. Group x-and-y is subsequently passed along as argument to blib.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
world
  variables
    x, y is a real
    z is a q-r-bundle

  variable-group
    x-and-y is a group of
      * x
      * y

  component
    blib is a blob with arguments
      * x-and-y
      * z.foo
      * z.faa

For each unique grouping of variables one has to define a new group. A variable may be part of multiple groups. The usage of bundles and groups is similar but different.

Bundles can be used to quickly instantiate multiple variables defined within the bundle definition and pass them around as a single package. This enables one to reduce the length of parameter, variable and argument lists.

Groups can be used to organize already declared variables into packages and pass them along as arguments to component instantiations. Upon instantiation, a group within an argument list of a component instantiation is mapped onto the respective bundle within the parameter list of the component definition.

Argument and parameter lists

Besides lists of subclauses and bundle entries, ESL contains parameter lists within relation definitions and arguments lists within component and relation instantiations. For consistency reasons the asterisk item mark is introduced within these lists as well.

The following example shows the usage of asterisk within parameter lists of a relation definition (line 2), argument list of a component instantiation (line 17), and argument lists of a relation instantiation (line 23).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
define relation
  ohms-law requiring parameters
      * current is a real
      * resistance is a real
    returning parameter
      * voltage is a real

define component blob
  parameters
    I, R, U is a real

world
  variables
    I, R, U is a real

  component
    blab is a blob with arguments
      * I
      * R
      * U

  relation
    r1: ohms-law requiring arguments
        * I
        * R
      returning argument
        * U

Specification

The removal of the end keyword and introduction of the asterisk item marker affects the ESL syntax at multiple places. First of all, the argument-list, subclauses, and bundle-definition syntax is affected. The new syntax is given by:

1
2
3
4
5
6
7
8
9
argument-list ::= { "*" argument-name \n }+

subclauses ::=
  "with" "subclauses" \n
    { "*" SUBCLAUSE-NAME ":" subclause-literal \n }+

bundle-definition ::=
  BUNDLE-NAME "is" "a" "bundle" "of" \n
    { "*" ENTRY-NAME "is" ( "a" | "an" ) TYPE-NAME  \n }+

That is, all arguments are placed on separate lines that start with an *. Similarily, all subclauses start with an * and all bundle entries start with an *. Anonymous bundles are no longer allowed.

Secondly, the syntax of relation definitions and relation instantiations are affected. That is, each line within a parameter or argument list must start with an * as defined in the syntax below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 relation-definition ::=
   "define" "relation" \n
       { RELATION-KIND \n
           { ( "requiring" | "returning" | "relating" ) "parameter"  \n
               { "*" ["one" "or" "more"] PARAMETER-NAME "is" ("a" | "an") TYPE-NAME \n }+
           }+ (*At most one requiring, returning and relating.*)
       }+

 relation-section ::=
   "relation" \n
       { RELATION-NAME ":" RELATION-KIND \n
           { ( "requiring" | "returning" | "relating" ) "argument"  \n
               { "*" ARGUMENT-NAME \n }+
           }+ (*At most one requiring, returning and relating.*)
       }+

Finally, the group-section is introduced of which the syntax is given by:

1
2
3
4
5
6
7
group-section ::=
  "variable-group" \n
    { group-definition }+

group-definition ::=
  GROUP-NAME "is" "a" "group" "of" \n
    argument-list

That is, a group section starts with the key word variable-group followed by a new line and one ore more group-definitions. A group-definition start with a GROUP-NAME followed by is a group of and new line on which one finds the argument-list.

Backwards Compatibility

This modification will break all existing ESL specifications that contain argument lists, relations, subclauses and bundles. As such, backwards compatibility issues are expected.

To fix a specification one has to add the asterisks to argument-lists, subclauses, relations and bundles and remove all anonymous bundles. Anonymous bundles have to be defined within the type-section or replaced by groups.

Proof of concept

The section will be added once the new syntax is implemented.

Rejected Ideas

To following ideas where rejected.

Leading whitespace

As mentioned in the Rationale section, in many mark-up languages leading white space is used to indicate the level of nesting. Adopting this concept in ESL would suffice to remove the end keyword. However, it would, first of all, almost certainly break all existing ESL specifications. Secondly, it would put a significant burden on ESL writers as they have to ensure the proper indentation level of all elements within the specification. Third of all, different tab-settings between editors can break an ESL specification which hinders sharing between users. Finally, it would require a significant change to the compiler as currently all white space is ignored. Therefore, leading white space has been rejected.

Brackets

In many programming languages brackets are used to group things together and indicate the end of a list. Brackets however do not fit the natural language concept of ESL and are therefore rejected.

Alternative keywords for groups

Some alternative keywords for groups where considered. For example, composition and collection were considered. However, semantically group was preferred as it best captures the intended concept.

Open Issues

No open issues were identified.