CPAL v1.18 Release Notes

Home/CPAL v1.18 Release Notes
CPAL v1.18 Release Notes 2017-07-06T13:02:59+00:00

Version 1.18 – release date: April 26, 2017

We are pleased to announce the release of CPAL V1.18 which is a drop in replacement for v1.17, with several important new constructs in the language to improve its expressiveness and clarity. This release also irons out a few issues. Under the hood, the toolset evolves to prepare for C code generation that will be available in a coming release.

What is new

  • ADDED: finally block of code which is executed after any state of the process. This “post-state common code” block is the counterpart of the common block executed before any state. common and finally blocks are perfect locations to check resp. pre- and post-conditions.

    
    processdef A_Proc()
    {
        /* pre-state common code executed first whatever the current state */
        common {
            IO.println("pre-state common code");
        }
    	
        state First {
            /* state-specific code goes here */
    	    IO.println("state code");
    	}
    	
        /* post-state common code executed last whatever the current state */
        finally {
            IO.println("post-state common code");
        }
    }
    
    process A_Proc: p1[1s]();
    
  • ADDED: self.continue allows to execute several states of a FSM in a row before relinquishing the CPU (similar in the spirit to “forced states” in Opnet). In the example below, the execution of state First will always be followed by the execution of state Second:

    
    processdef Simple()
    {
        state First {
            IO.println("Time %t  - executing state First", time64.time());
            self.continue = true;
        }
        on (true)
          to Second;
    
        state Second {
            IO.println("Time %t - Executing state Second", time64.time());
        }
        on (true)
          to Third;
    
        state Third {
            IO.println("Time %t - Executing state Third", time64.time());
        }
        on (true)
          to First;
    }
    
    process Simple: p1[1s]();
    
  • ADDED: possibility to affect the result of a function through a mechanism called “currying”:

    
    double(
        in  uint8: x,
        out uint8: y)
    {
        y = 2 * x;
    }
    
    init()
    {
        var uint8:   result =     double(5);
        IO.println("result = %u", result);
    }
    
  • ADDED: possibility to test the result of a function (currying again):

    
    add_1ms(
        in  time64: a,
        out time64: res)
    {
        res = a + 1ms;
    }
    
    init()
    {
        var time64: t1       = 999ms;
        var time64: expected = 1s;
        assert(expected == add_1ms(t1));
    }
    
  • ADDED: possibility to test and store the state of a process, from within the process through self.current_state and from another process through a Process_State variable. The latter case is illustrated below:

    
    processdef Simple()
    {
        static var bool: change_state = false;
        common {
            change_state = bool.rand_uniform();
        }
    
        state First {
        }
        on (change_state)
          to Second;
    
        state Second {
        }
        on (change_state)
          to First;
    }
    
    process Simple: p1[1s]();
    
    processdef Observer()
    {
        static var Process_State: previous;
        state Single {
            IO.print("Current state of p1: ");
            if (p1.process_state == Process_State.First) {
                IO.println("First");
            } else {
                  IO.println("Second");
                }
        }
    }
    
    process Observer: p2[1s]();	
    

What has been fixed or changed

  • FIXED: Named blocks can be declared anywhere, e.g. inside if statement (#318):

    
    processdef Proc()
    {
      state Main {
        var bool: b;
        valid1: {
        }
        if (b) {
          valid2: {
          }
        }
      }
    }
    
  • CHANGED: break statement now forbidden in states, reserved for loops (#343).
  • CHANGED: @cpal:unknown annotations are rejected by the parser, user-defined annotations must be prefixed by anything other than @cpal) (#354).
  • CHANGED: Queue iteration: no more implicit continue statement after a call to remove_current() (#49). remove_current() does not support anymore the options restart and break (#49,#269) whose behavior can be achieved programmatically.

    	
    init(){
      var queue<uint8>: my_data[4] = {1, 5, 7, 9 };
      loop over my_data with it {
        IO.println("%u", it.current);
        if (it.current == 1) {
          it.remove_current(); 
          /* it points now to the next element of the collection */
        }
        if (it.current == 5) {
          it.remove_current();
        }
        if (it.current == 7) {
          it.remove_current();
        }
        IO.println("size of the collection: %u", my_data.count());
      }
    }
    
  • CHANGED: { } required after if statement (#352).
  • FIXED: correct parser issues with sub-processes (#358,#359,#360).

Test coverage metrics (figures for embedded Linux platform)

  • Test code coverage for the execution engine: 85.9% (lines of code), 82.2% (functions) and 72.8% (branches)
  • Tests: parser=3963, interpreter=857, cpal2x=3342