The Programming Language DINO: Executive statements Next Previous Contents

7. Executive statements

Statements denote actions. There are simple and compound statements. Simple statements do not consist of any parts that are statements themselves. They are the assignment, procedure call, return, break, continue, throw, and the wait statements. Analogous to the language C the last symbol of a Dino simple statement is semicolon ;. Compound statements consists of parts that are statements themselves. They are used to express sequencing, exception handling, conditional, and repetitive execution.

7.1 Empty statement

There is an empty statement in Dino. It denotes no action. The empty statement is included in Dino for convenience.

          ExecutiveStmt = ";"

Example: Usage of an empty statement in a for-statement:

          for (i = 0; a[i] == 0; i++)
            ;

7.2 Block-statement

A block-statement is simply a block and can used to group statements into one statement and/or describe local declarations. For details on how the block is executed see the section Declaration and Scope Rules.

          ExecutiveStmt = BlockStmt

          BlockStmt = Block

Example: Usage of a block-statement in a for-statement:

          sum = 0;
          for (i = 0; i < #a; i++)
            {
              var value = a[i];
              if (value > 0)
                sum += value;
            }

7.3 Expression-statement

Dino has an expression statement. Although it seems that the expression value is not used, the expression evaluation can results in side-effects, e.g. through calling a function/class. An expression-statement as textually the last statement in the function block means a return of the expression value as the function call result. In REPL (see Appendix B. Implementation), execution of an expression-statement results in printing the expression value.

          ExecutiveStmt = Expr ";"

Examples:

          putln ("percent=" @ percent @ "%");
          newfiber ();
          5 + 10;

7.4 Assignment statements

Assignment-statements are used to change variable values or element values of a structured value which are referred through a designator (see sub-section Designator in section Expressions. The designator can not denote a final variable (see the section Variable Declaration). You can not change the element value of an immutable value (see the section Types and Values). In this case the exception immutable is generated. Assignment to a table element has a side effect, the element key becomes immutable.

A simple assignment statement looks like Designator = Expr;. That means that the expression value is assigned to a variable or element of a structured type value denoted by the designator. For the convenience of C programmers there are also the Dino assignments Designator op= Expr;, Designator++;, ++Designator;, Designator--;, and --Designator;. They are analogous correspondingly to Designator = Designator op Expr;, Designator = Designator + 1;, and Designator = Designator - 1;. The only difference is in the fact that the designator is evaluated only once, not twice as in the analogous form. It is important to know if you have side effects in the statement.

          ExecutiveStmt = Designator Assign Expr ";"
                        | Designator ("++" | "--")  ";"
                        | ("++" | "--")  Designator ";"
          Assign = "="
                 | "*="
                 | "/="
                 | "%="
                 | "+="
                 | "-="
                 | "@="
                 | "<<="
                 | ">>="
                 | ">>>="
                 | "&="
                 | "^="
                 | "|="

Examples:

          v = [10, 20];
          i = 1;
          i++;
          --i;
          i *= 20;

If the designator is a slice and the expression value is a slice too, they both should have the same form, otherwise the exception sliceform is generated. In this case each element referenced by the designator slice gets value of the corresponding element referenced by the expression slice. If the designator is a slice but the expression value is not, each element referenced by the designator slice gets the expression value. Examples of the slice assignment:

          v = [1, 2, 3, 4];
          v[:] += 1;
          v[::-1] = v[:]; // reverse v

7.5 If-statement

The Dino if-statement is analogous to the C language one. First, the expression after if is evaluated and an arithmetic conversion is done to it. The value should be an integer, a long integer, or a floating-point number, otherwise the exception optype is generated. If the value is nonzero the first statement is executed, otherwise the statement after else is executed (if any). The problem with dangling else is resolved analogous to the language C -- else part is associated with the closest if.

          ExecutiveStmt = if  "(" Expr ")" Stmt [ else Stmt ]

Examples:

          if (i < 0) i = 0;
          if (i < j) return -1; else if (i > 0) return 1; else return 0;

7.6 For-statement

The Dino for-statement is analogous to the C language one. The statement is executed in the following way.

  1. Execution of the first statement in the parentheses is done.
  2. The expression (for-guard) is evaluated and an implicit arithmetic conversion is applied to its value. The result value should be an integer, a long integer, or a floating point number. If this is not true, the exception optype is generated.
  3. If the value of for-guard is nonzero, the body of the loop (the last statement) is executed. Otherwise, the for-statement execution finishes.
  4. When the body has been executed, the second statement in the parentheses is executed and steps 2,3,4 (one iteration) are repeated again.
If the second statement is a simple statement, the statement semicolon can be omitted. The for-statement also can be finished by an execution of the statement break in the body. The rest body execution can be skipped by an execution of the statement continue. In this case, the for-statement execution continues with the step 4.
          ExecutiveStmt = for  "(" Stmt ForGuardExpr ";"  Stmt ")" Stmt

          ForGuardExpr = [Expr]

Examples:

          for (i = 0; i < 10; i++;) sum += v [i];
          for (i = 0; i < 10; i++) sum += v [i];
          for ({sum = 0; i = 0;} i < 10; i++) sum += v [i];

7.7 Foreach-statement

This statement is used to execution of the foreach-statement body (the statement) for all keys of table which is a value of the expression. The expression value should be a table. If this is not true, the exception keyop is generated. The current key value on each iteration is assigned to the designator. The order in which the key values are assigned on each iteration is undefined. One iteration can be finished with the aid of the statement continue and a foreach-statement can be finished by execution of statement break.

          ExecutiveStmt = for  "(" Designator in Expr ")" Stmt

Examples:

          putln ("The table is");
          for (k in t) {
            put ("key=");
            print (k);
            put (", element=");
            println (t{k});
          }

7.8 Match-statements

There are two kinds of the match-statement. One is used for pattern matching and another one is used for regular expression matching. They have practically the same syntax. They differ in usage of different start keywords pmatch and rmatch correspondingly for the pattern and regular expression matching.

The pattern or regular expression match statement is used to try matching the match-expression value (it is evaluated only once) and the patterns or regular expressions in given order and execute the statements corresponding to the first matched case.

Each case forms an own scope. The pattern variables in the pattern match statement are declared in the corresponding case scope. Each case scope of the regular expression match statement contains an implicitly declared variable m. If a regular expression in the case successfully matches the match-expression, value of the corresponding variable m is a vector of indexes describing matched substrings (see the result of function match for details).

In the case of regular expression matching the string conversion is implicitly applied to the match-expression and the case expression values. The exception optype occurs if the conversion results are not strings. A case with wildcard _ also can occur in a rmatch-statement. Matching with such case is always successful but the value of the variable m is undefined in this case.

Execution of a continue-statement in the case-statements results in continuing the process of matching the match-expression value with the subsequent patterns or regular expressions. Execution of a break-statement in the case-statements results in finishing the match-statement execution. There is an implicit break at the end of each case statement list.

If an optional case condition is given, then it is evaluated after the succesfull matching with the corresponding pattern and an arithmetic conversion is done to it. The value should be an integer, a long integer, or a floating-point number, otherwise the exception optype is generated. If the value is nonzero the all match is considered successfull, otherwise the subsequent case patterns are tried.

          ExecutiveStmt = (pmatch | rmatch) "(" Expr ")" "{" CaseList "}"
          CaseList = { case Pattern [CaseCond] ":" StmtList }
          CaseCond = if Expr

Examples:

          class c (a1, a2) {}
          pmatch (c (2, 3)) {
            case c (i, j): putln (i, j);
            case _: putln ("default");
          }
          pmatch (c (2, 3)) {
            case c (i, j) if i == j: putln ("eq=", i, j);
            case c (i, j) if i != j: putln ("neq=", i, j);
            case _: putln ("default");
          }

          rmatch (str) {
            case "[a-zA-Z]+": putln ("word starting at ", m[0]);
            case "[0-9]+": putln ("number starting at ", m[0]);
            case _: putln ("anything else, m is undefined");
          }

7.9 Break- and continue-statement

The statements break and continue are used correspondingly to finish execution of the closest-containing for-, foreach-, or match-statement covering the statement and to finish one iteration of the body of the for- or foreach-statement and to continue trying subsequent cases for the match-statement. These statement can be used only inside a for-, foreach-, or match-statement.

          ExecutiveStmt = break ";"
                        | continue ";"

Examples:

          for (i = 0; i < 10; i++) {
             if (ind [i] < 0)
               continue;
             val = v [ind[i]];
          }
          for (i in t)
            if (t{i} == elval)
              break;
          match (tree) {
            case leaf (n):
              putln ("leaf");
              if (n == 10) continue;
            case node (n1, n2):
              if (n1 != n2) break;
              putln ("special node");
            case _: putln ("might be a leaf with 10");             
          }

7.10 Return-statement

A return-statement is used to finish execution of a function, a fiber, or class block. The statement corresponds to the closest-containing function, fiber, or class covering the statement, so the return-statement can be placed only in a function, a fiber, or a class. The expression in a return-statement can be given only for functions. In this case, the expression value will be the value of the function call (instead of undefined value).

          ExecutiveStmt = return  [ Expr ] ";"

Examples:

          return;
          return [10, 2:0]

7.11 Throw-statement

This statement generates an exception which is given by value of the expression. The expression should evaluate to an object of predeclared class except or of its sub-class. If this is not true, the exception optype is generated. How exceptions are processed is described in the following section.

          ExecutiveStmt = throw  Expr ";"

Examples:

          class myexcept (msg) {use error former msg;}
          throw myexcept ("this is an user defined exception");

7.12 Try-block

Exceptions can be generated by the Dino interpreter when some conditions are not satisfied, by predeclared Dino functions, by other OS processes, by user interruptions, or by the user with the aid of a throw-statement. Actually, the exceptions are represented by an object of the predeclared class except or by an object of its sub-class. All predeclared exceptions are described in the section Predeclared Identifiers. To detect and process exceptions, a try-block can be used.

When an exception is generated, the closest-containing try-block which is covering the statement generating the exception or currently being executed (when this is is generated by an OS process or by an user interruption) is searched for. Then, expressions in the catch list elements are processed. The expression value in the catch list element being currently processed should be the predeclared class except or its sub-class. If the expression being processed is a class and the exception is an object of the class or an object of a sub-class of the class, the block corresponding to the given catch list element is executed. If there is no such catch expression, the closest-containing try-block covering the current try-block is searched for and processing the exception is repeated. If there are no more try-blocks, the program finishes with a diagnostic message which is dependent on the generated exception.

Blocks corresponding to catch list elements have a predeclared variable e. When the block execution starts, the variable contains the object representing the exception.

          ExecutiveStmt = TryBlockStmt

          TryBlockStmt = try Block { Catch }
        
          Catch = catch  "(" ExceptClassList ")" Block

          ExceptClassList = Expr { "," Expr }

Examples:

          try {
            var ln;
            for (;;)
              ln = getln ();
          } catch (eof) {
          }
          try {
            var v = [];
            v {1} = 0;
          } catch (except) {
            put ("catching and propagating exception"); println (class (e));
            throw e;
          }

7.13 Wait-statement

This statement is used for the synchronization of different threads in a Dino program. The expression can not contain a function, class, or a fiber call. The thread in which the statement has been executed waits until the expression value becomes nonzero. The expression value (after an implicit arithmetic conversion) should be an integer, a long integer, or a floating point number. Otherwise the exception optype is generated. When the expression value becomes nonzero, the statement after the expression (it is called a sync-statement) is executed without interruption by other threads. It is used as a critical region for the thread synchronization. In a critical region an execution of wait-statement is prohibited (it results in generation of the exception syncwait). Also fiber calls inside a critical region result in generation of the exception syncthreadcall.

          ExecutiveStmt = wait  "(" Expr ")" Stmt

An example:

          wait (!empty);

7.14 C code

All C code between pairs of brackets %{ and %} in one Dino file is concatenated in the same order as they occur in the file. The result code with some pre-appended C code providing an interface to the Dino interpreter internal data representation is compiled when the execution the first time achieves the location of the first %{ in the file. The result shared object is loaded and external variables and functions are searched lately in the same order as the shared objects are loaded.

          ExecutiveStmt = C_CODE

If an error during the compilation or loading the shared object file occurs, the exception compile is generated.

An example:

          %{
            #include <math.h>
            val_t isnan_p (int npars, val_t *vals) {
              val_t val;
              ER_node_t res = (ER_node_t) & val;

              ER_SET_MODE (res, ER_NM_int);
              ER_set_i (res, 0);
              if (npars == 1
                  && ER_NODE_MODE ((ER_node_t) vals) == ER_NM_float
                  && isnan (ER_f ((ER_node_t) vals)))
                ER_set_i (res, 1);
              return val;
            }
          %}

          extern isnan_p ();
          putln (isnan_p (10.0));


Next Previous Contents