[zetapush]Error in macro: code=SUB_ASSIGN - Message = Assignment failed - macros

When calling a macro I have the following error in response:
code=SUB_ASSIGN
Message = Assignment failed
Location= Reduce at line 65 of file mymacro.zms
the line 65 is
/** Reduce */
var b = gda(GDA).reduce {
table: 'myTable',
start: __parameters.key + '##',
stop: __parameters.key + '##a',
page: {
pageNumber: 0,
pageSize: 100000000
},
initialValue: {
tR: tR,
count: 0
},
'columns': ['col1', 'col2'],
'function': usr:myfunc
};
Seen on Android SDK (not on JS SDK) and not 100% reproducible.
What's the meaning of this error and how can I correct it?
Thanks.

The (poorly documented) meaning of SUB_ASSIGN is that an assignment with a syntax like a.b.c = d; has failed.
More precisely, the left hand operand is made of several hierarchical sub-parts (in my example a, b, and c).
Note that SUB_ASSIGN reports a programming error, which you should guard against :
when assigning a.b.c, at least a.b must exist and be not null.
A code pattern such as this one should do the trick:
// the ?? operator returns true when an expression is defined and not null
if (! a.b ??) {
a.b = {};
}
...
a.b.c = 0;
or, shorter, if applicable :
if (! a.b ??) {
a.b = {c:0};
}
The relevant documentation for '??' can be found in the official API reference documentation
As your code does not include such a statement anyway, I suppose that the actual error does not lie in your reduce call, but inside your callback function (usr:myfunc).
Moreover, to ease further debugging :
the error report you gave does not seem to contain the full stack trace up to the callback of the 'reduce' call. This might very well be a missing/not-yet-implemented feature of the zetapush API (which you could request...).

Related

Pre-compile textual replacement macro with arguments

I am trying to create some kind of a dut_error wrapper. Something that will take some arguments and construct them in a specific way to a dut_error.
I can't use a method to replace the calls to dut_error because to my understanding after check that ... then ... else can only come a dut_error (or dut_errorf). And indeed if I try to do something like:
my_dut_error(arg1: string, arg2: string) is {
dut_error("first argument is ", arg, " and second argument is ", arg2);
};
check that FALSE else my_dut_error("check1", "check2");
I get an error:
*** Error: Unrecognized exp
[Unrecognized expression 'FALSE else my_dut_error("check1", "check2")']
at line x in main.e
check that FALSE else my_dut_error("check1", "check2");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
So I thought about defining a macro to simply do a textual replace from my wrapper to an actual dut_error:
define <my_dut_error'exp> "my_dut_error(<arg1'name>, <arg2'name>)" as {
dut_error("first argument is ", <arg1'name>, " and second argument is ", <arg2'name>)
};
But got the same error.
Then I read about the preprocessor directive #define so tried:
#define my_dut_error(arg1, arg2) dut_error("first argument is ", arg, " and second argument is ", arg2)
But that just gave a syntax error.
How can I define a pre-compiled textual replacement macro that takes arguments, similar to C?
The reason I want to do that is to achieve some sort of an "interface" to the dut_error so all errors have a consistent structure. This way, different people writing different errors will only pass the arguments necessary by that interface and internally an appropriate message will be created.
not sure i understood what you want to do in the wrapper, but perhaps you can achieve what you want by using the dut_error_struct.
it has set of api, which you can use as hooks (do something when the error is caught) and to query about the specific error.
for example:
extend dut_error_struct {
pre_error() is also {
if source_method_name() == "post_generate" and
source_struct() is a BLUE packet {
out("\nProblem in generation? ", source_location());
// do something for error during generation
};
write() is first {
if get_mesage() ~ "AHB Error..." {
ahb_monitor::increase_errors();
};
};
};
dut_error accepts one parameter, one string. but you can decide of a "separator", that will define two parts to the message.
e.g. - instruct people to write "XXX" in the message, before "first arg" and "second arg".
check that legal else dut_error("ONE thing", "XXX", "another thing");
check that x < 7 else dut_error("failure ", "XXX", "of x not 7 but is ", x);
extend dut_error_struct {
write() is first {
var message_parts := str_split(get_message(), "XXX");
if message_parts.size() == 2 {
out ("First part of message is ", message_parts[0],
"\nand second part of message is ", message_parts[1]
);
};
};
I could get pretty close to what I want using the dut_errorf method combined with a preprocessor directive defining the format string:
#define DUT_FORMAT "first argument is %s and second argument is %s"
check that FALSE else dut_errorf(DUT_FORMAT, "check1", "check2");
but I would still prefer a way that doesn't require this DUT_FORMAT directive and instead uses dut_error_struct or something similar.

Trying to match to a typedef value in a receive statement causes "bad node type 44" error message

When I try to match a message in a receive statement I get a "bad node type 44" error message. This happens when the message's type is a typedef. The error message is rather cryptic and doesn't give much insight.
typedef t {
int i
}
init {
chan c = [1] of {t}
t x;
!(c ?? [eval(x)]) // <--- ERROR
}
Note: This may, or may not, be a bug in Spin: apparently, the grammar allows using a structure variable as an argument for eval(), but it does not look like this situation is handled correctly (within the extent of my limited understanding). I would encourage you to contact the maintainers of Promela/Spin and submit your model.
Nevertheless, there is a work-around for the issue you reported (see below).
Contrary to what is reported here:
NAME
eval - predefined unary function to turn an expression into a constant.
SYNTAX
eval( any_expr )
The actual promela grammar for EVAL looks a bit different:
receive : varref '?' recv_args /* normal receive */
| varref '?' '?' recv_args /* random receive */
| varref '?' '<' recv_args '>' /* poll with side-effect */
| varref '?' '?' '<' recv_args '>' /* ditto */
recv_args: recv_arg [ ',' recv_arg ] * | recv_arg '(' recv_args ')'
recv_arg : varref | EVAL '(' varref ')' | [ '-' ] const
varref : name [ '[' any_expr ']' ] [ '.' varref ]
Take-aways:
apparently, eval is allowed to take as argument a structure (because name may be the identifier of a typedef structure [?])
eval can also take as argument a structure field
when one aims to apply message filtering to an entire structure, it can expand the relevant fields of the structure itself
Example:
typedef Message {
int _filter;
int _value;
}
chan inout = [10] of { Message }
active proctype Producer()
{
Message msg;
byte cc = 0;
for (cc: 1 .. 10) {
int id;
select(id: 0..1);
msg._filter = id;
msg._value = cc;
atomic {
printf("Sending: [%d|%d]\n", msg._filter, msg._value);
inout!msg;
}
}
printf("Sender Stops.\n");
}
active proctype Consumer()
{
Message msg;
msg._filter = 0;
bool ignored;
do
:: atomic {
inout??[eval(msg._filter)] ->
inout??eval(msg._filter), msg._value;
printf("Received: [%d|%d]\n", msg._filter, msg._value);
}
:: timeout -> break;
od;
printf("Consumer Stops.\n");
}
simulation output:
~$ spin test.pml
Sending: [1|1]
Sending: [0|2]
Received: [0|2]
Sending: [0|3]
Received: [0|3]
Sending: [0|4]
Received: [0|4]
Sending: [0|5]
Received: [0|5]
Sending: [1|6]
Sending: [0|7]
Received: [0|7]
Sending: [0|8]
Received: [0|8]
Sending: [1|9]
Sending: [1|10]
Sender Stops.
timeout
Consumer Stops.
2 processes created
Generating a verifier does not result in a compilation error:
~$ spin -a test.pml
~$ gcc -o run pan.c
Note: when using both message filtering and message polling (like in your model sample), the fields of the structure that are subject to message filtering should be placed at the beginning of it.
Apparently it's a bug, link to github issue: https://github.com/nimble-code/Spin/issues/17
Update: Bug is now fixed.
Update 2: Bug was actually partially fixed, there are still some edge cases where it's behaving weirdly.
Update 3: As far as I can tell bug looks fixed now. The only downside is that it seems that now there is a strict restriction on what you put in the receive args. They have to match exactly the types declared in the channel. No more partial matches or unrolling struct fields.
My guess is that this error is related to the restrictions that structured types have. One restriction is that they can't be handled as a unit, to assign or compare them one must do it one field at a time.
For example, if one writes: x == y, where x and y are variables of a typedef type, the following error is shown: Error: incomplete structure ref 'x' saw 'operator: =='
Under the hood, when trying to compare the channel's queue to match the eval something is triggered that indicates that the comparison can't be done and then raises the "bad node type" message.

Where does a variable in a match arm in a loop come from?

I am trying to implement an HTTP client in Rust using this as a starting point. I was sent to this link by the rust-lang.org site via one of their rust-by-example suggestions in their TcpStream page. I'm figuring out how to read from a TcpStream. I'm trying to follow this code:
fn handle_client(mut stream: TcpStream) {
// read 20 bytes at a time from stream echoing back to stream
loop {
let mut read = [0; 1028];
match stream.read(&mut read) {
Ok(n) => {
if n == 0 {
// connection was closed
break;
}
stream.write(&read[0..n]).unwrap();
}
Err(err) => {
panic!(err);
}
}
}
}
Where does the n variable come from? What exactly is it? The author says it reads 20 bytes at a time; where is this coming from?
I haven't really tried anything yet because I want to understand before I do.
I strongly encourage you to read the documentation for the tools you use. In this case, The match Control Flow Operator from The Rust Programming Language explains what you need to know.
From the Patterns that Bind to Values section:
In the match expression for this code, we add a variable called state to the pattern that matches values of the variant Coin::Quarter. When a Coin::Quarter matches, the state variable will bind to the value of that quarter’s state. Then we can use state in the code for that arm, like so:
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
},
}
}
If we were to call value_in_cents(Coin::Quarter(UsState::Alaska)), coin would be Coin::Quarter(UsState::Alaska). When we compare that value with each of the match arms, none of them match until we reach Coin::Quarter(state). At that point, the binding for state will be the value UsState::Alaska. We can then use that binding in the println! expression, thus getting the inner state value out of the Coin enum variant for Quarter.
There is an entire chapter about the pattern matching syntax available and where it can be used.
Figured it out, this is what's happening:
match stream.read(&mut read) {
This line is telling the software to pass stream.read(&mut read) to Ok(n) because stream.read returns the number of bytes read. I'm still not sure why they specify 20 bytes at a time as being read.

how to compare expected value to be in the list [duplicate]

One of my test expects an error message text to be one of multiple values. Since getText() returns a promise I cannot use toContain() jasmine matcher. The following would not work since protractor (jasminewd under-the-hood) would not resolve a promise in the second part of the matcher, toContain() in this case:
expect(["Unknown Error", "Connection Error"]).toContain(page.errorMessage.getText());
Question: Is there a way to check if an element is in an array with jasmine+protractor where an element is a promise?
In other words, I'm looking for inverse of toContain() so that the expect() would implicitly resolve the promise passed in.
As a workaround, I can explicitly resolve the promise with then():
page.errorMessage.getText().then(function (text) {
expect(["Unknown Error", "Connection Error"]).toContain(text);
});
I'm not sure if this is the best option. I would also be okay with a solution based on third-parties like jasmine-matchers.
As an example, this kind of assertion exists in Python:
self.assertIn(1, [1, 2, 3, 4])
Looks like you need a custom matcher. Depending on the version of Jasmine you are using:
With Jasmine 1:
this.addMatchers({
toBeIn: function(expected) {
var possibilities = Array.isArray(expected) ? expected : [expected];
return possibilities.indexOf(this.actual) > -1;
}
});
With Jasmine 2:
this.addMatchers({
toBeIn: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var possibilities = Array.isArray(expected) ? expected : [expected];
var passed = possibilities.indexOf(actual) > -1;
return {
pass: passed,
message: 'Expected [' + possibilities.join(', ') + ']' + (passed ? ' not' : '') + ' to contain ' + actual
};
}
};
}
});
You'll have to execute this in the beforeEach section on each of your describe blocks it's going to be used in.
Your expect would look like:
expect(page.errorMessage.getText()).toBeIn(["Unknown Error", "Connection Error"]);
The alternative solution is to use .toMatch() matcher with Regular Expressions and specifically a special character | (called "or"), which allows to match only one entry to succeed:
expect(page.errorMessage.getText()).toMatch(/Unknown Error|Connection Error/);
To me, the work-around that you identified is the best solution. However, we should not forget that this is an asynchronous execution and you might want to consider Jasmine's asynchronous support.
Then, your test will look like the following one:
it('should check item is in array', function(done){ //Note the argument for callback
// do your stuff/prerequisites for the spec here
page.errorMessage.getText().then(function (text) {
expect(["Unknown Error", "Connection Error"]).toContain(text);
done(); // Spec is done!
});
});
Note: If you don't pass this done argument to the spec callback, it is going to run to completion without failures, but no assertions are going to be reported in the execution results for that spec (in other words, that spec will have 0 assertions) and it might lead to confusions.

Retrieving variable name in order to print them in specman

I wish to do the following in Specman:
my_task() is {
var my_var : int;
my_var = 5;
message(LOW,appendf("%s=[%d]",my_var.to_name(),my_var));
};
Currently, I'm in search of the internal task to_name(). I do not want to create a struct for this. I wish to only use Specman internals.
I'm not sure how you'd do this unless you somehow have the collection of all the fields, which would give you the name of all the fields.
So, I'm going to branch predict and assume that you want all the fields of a given struct/unit:
extend sys {
A : list of uint;
B : int;
cee : string;
run() is also {
var rf_sys: rf_struct = rf_manager.get_exact_subtype_of_instance(sys);
for each (field) in rf_sys.get_declared_fields() {
print field;
print field.get_long_name(); // <-- Here's your "get_name()" function
};
};
};
On version 8.2, this yields:
Usage: . env.sh [-32bit|-64bit] [-v] [[VAR=value]...]
Welcome to Specman Elite(64) (09.20.482-d) - Linked on Wed Mar 2 13:32:19
2011
Protected by U.S. Patents 6,141,630 ;6,182,258; 6,219,809; 6,347,388;
6,487,704; 6,499,132; 6,502,232; 6,519,727; 6,530,054; 6,675,138; 6,684,359;
6,687,662; 6,907,599; 6,918,076; 6,920,583; Other Patents Pending.
1 notification was modified by command 'set notify -severity=WARNING
DEPR_START_TCM_ARG_BY_REF'
Checking license ... OK
Loading /nfs/pdx/home/rbroger1/tmp.e ...
read...parse...update...patch...h code...code...clean...GC(sys)...
Doing setup ...
Generating the test using seed 1...
Starting the test ...
Running the test ...
field = rf_field 'time', Specman's private modules
field.get_long_name() = "time"
field = rf_field 'logger', Specman's private modules
field.get_long_name() = "logger"
field = rf_field 'A', line 5 in #tmp
field.get_long_name() = "A"
field = rf_field 'B', line 6 in #tmp
field.get_long_name() = "B"
field = rf_field 'cee', line 7 in #tmp
field.get_long_name() = "cee"
No actual running requested.
Checking the test ...
Checking is complete - 0 DUT errors, 0 DUT warnings.
If that doesn't quite answer your question, look more into Specman's introspection or reflection interface in the documentation for your version of Specman. Warning, details are a bit scarce from Cadence. Also, see my answer to "Specman: how to retrieve values of var which is stored in another var".. Finally, in specview you can use the data browser to browse the rf_manger itself ( introspection at its best). Then you can find all the functions that Cadence doesn't tell you about in their documentation.
You can't get the string name of a variable. Although you can get the name of a field using get_name().
This makes some sense, because the variable is only known at the location it is declared. You can't even access the variable in a later extension of my_task(). So if you are already editing the code at the location where the variable was declared, just say "my_var" rather than my_var.to_name(). (Yes, typos and cut and paste errors can happen.)
I think this is what you are looking for:
define <dump'action> "dump <exp>" as {
out("<exp>","=[",<exp>,"]");
};
you can use this macro in the specman command line or inside functions, for example:
foo() is {
var a : int = 5;
dump a;
};
will give:
a=[5]