Error reporting on erroneous ":> void" in select component Topic is solved

Technical questions regarding the xTIMEcomposer, xSOFTip Explorer and Programming with XMOS.
User avatar
aclassifier
Respected Member
Posts: 332
Joined: Wed Apr 25, 2012 8:52 pm

Error reporting on erroneous ":> void" in select component

Postby aclassifier » Wed May 23, 2018 6:12 pm

Have a look at this. Search for "???".

My question is: is the error reporting correct? When that void is removed the compiler thinks the role has changed to ok, because then it compiles and runs.

By just removing the erronoeus ":> void" also these three are removed:

Code: Select all

// error: trying to call slave function from a client interface
// error: void value not ignored as it ought to be
// error: invalid side effect in select
Here is the code:

Code: Select all

#include <platform.h> // core
#include <stdio.h>
#include <timer.h> // delay_milliseconds(200), XS1_TIMER_HZ etc

#define DEBUG_PRINT_TEST 1
#define debug_print(fmt, ...) do { if(DEBUG_PRINT_TEST) printf(fmt, __VA_ARGS__); } while (0)

typedef enum {false,true} bool;
typedef signed int time32_t;
typedef unsigned data_t;

typedef interface notify_if_t {

    void start_collect_data (void);

    [[notification]]
    slave void data_ready (void);

    [[clears_notification]]
    data_t get_data (void);

} notify_if_t;

[[combinable]]
void server_task (server notify_if_t i_notify) {
    timer     tmr;
    time32_t  time;
    bool      collectData = false;
    data_t    data = 0;

    tmr :> time;

    while (1) {
        select {
            case i_notify.start_collect_data (void) : {
                collectData = true;
                debug_print ("\n%s\n", "start");
                tmr :> time;
            } break;
            case (collectData == true) => tmr when timerafter (time) :> void : {
                collectData = false;
                data++; // This is supposed to take a while, that's why we used notification: to get it decoupled
                debug_print ("inc %u\n", data);
                i_notify.data_ready();
            } break;
            case i_notify.get_data (void) -> data_t return_Data : {
                debug_print ("sent %u\n", data);
                return_Data = data;
            } break;
        }
    }
}

[[combinable]]
void client_task (client notify_if_t i_notify) {
    timer     tmr;
    time32_t  time;
    bool      expect_notification = false;

    tmr :> time;

    while (1) {
        select {
            case (expect_notification == false) => tmr when timerafter (time) :> void : {
                i_notify.start_collect_data();
                expect_notification = true;
            } break;
            case (expect_notification == true) => i_notify.data_ready() :> void : { // ???
                // error: trying to call slave function from a client interface
                // error: void value not ignored as it ought to be
                // error: invalid side effect in select
            // case (expect_notification == true) => i_notify.data_ready() : { // WORKS!
                data_t data = i_notify.get_data();
                debug_print ("got %u\n", data);
                expect_notification = false;
                time += XS1_TIMER_HZ; // 1 second
            } break;
        }
    }
}

int main() {
    notify_if_t if_notify;
    par {
        server_task(if_notify);
        client_task(if_notify);
    }
    return 0;
}
View Solution
robertxmos
XCore Addict
Posts: 169
Joined: Fri Oct 23, 2015 10:23 am

Postby robertxmos » Thu May 24, 2018 8:42 am

simple answer 'yes'.


The use of the trailing '->' is to specify the return type & variable.
The declaration:

Code: Select all

   [[clears_notification]] data_t get_data (void);
Become the definition:

Code: Select all

   case i_notify.get_data (void) -> data_t return_Data : {
      return_Data = ...
The use of the trailing ':>' inputs the resouce into a type & variable (or inputs and throws it away if 'void' is used):

Code: Select all

   case tmr when timerafter (time) :> void : {
For interface methods you should be using '->' as they are not a resource (although chanends are below the hood).
Changing to use the return type & variable it compiles (bit weird tho'):

Code: Select all

case (expect_notification == true) => i_notify.data_ready() -> void v: { // ???
(and yes the variable name is required, even if it is hard to write to!.. this could be releaxed but why not just drop the void too?)

N.B. I have not checked if the example line above works!
It is probably safer, and certainly more readable, to leave out the return type&variable as you do in your working example.

robert
User avatar
aclassifier
Respected Member
Posts: 332
Joined: Wed Apr 25, 2012 8:52 pm

Postby aclassifier » Thu May 24, 2018 9:43 am

Robert, yes, the -> void v both compiles and runs!

How in the world did you dream up the v, when in :> void to drop the timer value, any such named value is not required?

Of course, the message without the v goes like this. (And I would loop: should one accept that the compiler has us use 'weird' syntax just for its own sake? Because that is not understandable in my head. (But why does it require this?))

Code: Select all

../src/main.xc:1988:85: error: parse error before ':' token
                case (expect_notification == true) => i_notify.data_ready() -> void : {
                                                                                    ^
This is the first time I have come across a named void, even required named void.

But I am not sure whether you really answered my initial question. You may have, but then it's my eyes. When the compiler complains about error: trying to call slave function from a client interface and it changes its mind just by having the erroneous >: void removed. What quality does the erroneous :> void have to cause the compiler to issue such an error message? The compiler should, in my opinion, have dropped that message and complained about the void only. I think this is what my eyes saw explained rather well in your answer. When I get an error message I try to read it and understand it. I have hard time understanding the above. The side effect message is also interesting, but since the erroneous >: void makes it invalid XC then even that message seems out of scope to me. Is this about which order the compiler checks things, and then collects error messages up to some point in the abstract syntax tree (don't know if I got that right, but you know what I mean).

If I add this line of code I get this correct and understandable behaviour of that message from the compiler:

Code: Select all

[[combinable]]
void client_task (client notify_if_t i_notify) {
    timer     tmr;
    time32_t  time;
    bool      expect_notification = false;

    tmr :> time;
    i_notify.data_ready();
    // ../src/main.xc:1977:18: error: trying to call slave function from a client interface
    // ../src/main.xc:1977:18: error: void value not ignored as it ought to be 
    //                                i_notify.data_ready() :> void;

    while (1) {
        // ....
    }
}
Off Topic
Sorry about this rather lengthy message. I take your time. But then, I do think this may be interesting for the compiler writer and also for us users!
robertxmos
XCore Addict
Posts: 169
Joined: Fri Oct 23, 2015 10:23 am

Postby robertxmos » Thu May 24, 2018 11:14 am

The error is the compiler trying to make syntactic matches.
It sees there is a problem and reports why it is unhappy.
This is often not for the same reason you would be unhappy - you will be pattern matching in a different way.
Hopefully, there is enough information for you to reason what is going on - and yes your example perfectly demonstrates it's reasoning.
The joys of compiler error messages is most developed when it comes to deep template meta-type errors in C++ - yikes!
User avatar
aclassifier
Respected Member
Posts: 332
Joined: Wed Apr 25, 2012 8:52 pm

Postby aclassifier » Thu May 24, 2018 12:14 pm

Fair enough! Thanks, Robert!

I remember the compiler writers of occam compilers said that the syntax of occam "has only one error". And that was around something with newlines. I think that meant that they had to do an extra parsing around to find out, just for that single syntax problem. I dont' think it was David May who said this, but one of the guys who took over the occam compiler sources at UofKent, or a guy who did the SPOC at UofSouthampton. I have listened to them all at conferences. But I guess David May is largelig to "blame" (or rather praise!) for XC, but I guess, defining a syntax is very difficult. Even for the specialist. (I am not certain if they formally model the syntax? No lex/yacc-based language?)
Off Topic
By the way, the next conference in the series is here: http://wotug.cs.unlv.edu

Who is online

Users browsing this forum: No registered users and 1 guest