Infinite recursion in Rust derive macro? - macros

I have made the following attampt at a derive macro in Rust:
extern crate proc_macro;
use crate::proc_macro::TokenStream;
use quote::quote;
use syn;
#[proc_macro_derive(DeserializeConfigurable)]
pub fn deserialize_configurable_derive(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;
let gen = quote! {
impl<'de> Deserialize<'de> for #name {
fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
where
D: Deserializer<'de>,
{
let config = <#name as Configurable>::Config::deserialize(deserializer)?;
Ok(#name::from_config(config))
}
}
};
gen.into()
}
The goal is to provide a specific blanket implementation for deserialize based on another trait, Configurable.
However, the compiler has the following complaint regarding my quote statement:
recursion limit reached while expanding the macro stringify
I don't see the recursion here. I am not even using stringify! What is calling what in infinity here?

Trying to compile this locally gives this full error message:
error: recursion limit reached while expanding the macro `stringify`
--> src/lib.rs:13:15
|
13 | let gen = quote! {
| _______________^
14 | | impl<'de> Deserialize<'de> for #name {
15 | | fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
16 | | where
... |
22 | | }
23 | | };
| |_____^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error
Putting the following as the first line of the crate makes the error go away. My guess is that the default recursion_limit is simply too low for a macro this complex (which IMO isn't that complex). I'm sure there's a good reason, and I'm glad the error message contained the solution:
#![recursion_limit="128"]

Related

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

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...).

How to use NSEventMask with Swift

Why am I getting a compiler error indicating the boolean OR function "|" cannot be used with in the following manner:
localEvent = self.window.nextEventMatchingMask(NSEventMask.LeftMouseUpMask | NSEventMask.LeftMouseDraggedMask)
EDIT:
Here is what I eventually found to work
localEvent = self.window!.nextEventMatchingMask(Int(NSEventMask.LeftMouseUpMask.rawValue | NSEventMask.LeftMouseDraggedMask.rawValue))!
Try like this:
localEvent = window.nextEventMatchingMask(Int(NSEventMask.LeftMouseUpMask.rawValue))
or
localEvent = window.nextEventMatchingMask(
Int(NSEventMask.LeftMouseUpMask.union(.LeftMouseDraggedMask).rawValue))

Fitnesse smartrics.rest.fitnesse.fixture.RestFixture.setBaseUrl

I have a requirement for a test to make a call to one REST endpoint that generates a security token then make a second to the actual system under test. In order to do this I am using smartrics.rest.fitnesse.fixture.RestFixture and setting the baseurl in instantiation to the first base. I am trying to make this call and then set the new baseurl to the new location but am having trouble doing so.
It appears from perusing the code that there is a method setBaseUrl(Url url) but I cannot find an example of using this and am failing trying to figure it out myself.
Has anyone had any luck with this or is there another, better/easier way to achieve this?
The problem lies in RestFixture:processRow - since it uses Java reflection, it attempts to call method without parameters. This will fail since setBaseUrl accepts one argument (Url). I have tried one modification, though not the best way to achieve it - current code RestFixture v3.0 (RestFixture.processRow()):
method1 = getClass().getMethod(methodName);
method1.invoke(this);
Modified code in RestFixture.processRow():
Method[] methods = getClass().getMethods();
int i = 0;
for(i = 0; i < methods.length; i++){
if(methodName.equals(methods[i].getName())){
method1 = methods[i];
break;
}
}
Class[] paramTypes = method1.getParameterTypes();
List<Object> params = new ArrayList<Object>();
for(i = 0; i < paramTypes.length; i++){
String cellText = row.getCell(i+1).text();
Object param = paramTypes[i].getConstructor(String.class).newInstance(cellText);
params.add(param);
}
method1.invoke(this, params.toArray());
Once this modification is done (you might need to add required imports - java.lang.InstantiationException, java.lang.Object, java.util.ArrayList; and an exception handler for InstantiationException), re-build the RestFixture and that should work.
We had what sounds like a similar requirement - we needed to use RestFixture(POST) to retrieve a URL for use in a subsequent RestFixture call(GET).
(Note that we're using an ancient RestFixture 1.1)
I modified the processArguments() method in RestFixture.java thus:
// baseUrl = new Url(args[0]); // original line
baseUrl = new Url(resolve(args[0])); // modified
With this modification in place, my Fitnesse test looks like this:
`!| RestFixture | http:///fds |
| setBody |{"param1":"blah","param2":"blather"} |
| POST | /GetThatUrl | 200 | | |
| let | $urlresult | body | |
!| RestFixture | $urlresult |
| GET| | 200 | Content-Length:[\d]+ | ||`
Without the code change, $urlresult was not resolved and I could not pass in the URL as a variable.

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]

How to further improve error messages in Scala parser-combinator based parsers?

I've coded a parser based on Scala parser combinators:
class SxmlParser extends RegexParsers with ImplicitConversions with PackratParsers {
[...]
lazy val document: PackratParser[AstNodeDocument] =
((procinst | element | comment | cdata | whitespace | text)*) ^^ {
AstNodeDocument(_)
}
[...]
}
object SxmlParser {
def parse(text: String): AstNodeDocument = {
var ast = AstNodeDocument()
val parser = new SxmlParser()
val result = parser.parseAll(parser.document, new CharArrayReader(text.toArray))
result match {
case parser.Success(x, _) => ast = x
case parser.NoSuccess(err, next) => {
tool.die("failed to parse SXML input " +
"(line " + next.pos.line + ", column " + next.pos.column + "):\n" +
err + "\n" +
next.pos.longString)
}
}
ast
}
}
Usually the resulting parsing error messages are rather nice. But sometimes it becomes just
sxml: ERROR: failed to parse SXML input (line 32, column 1):
`"' expected but `' found
^
This happens if a quote characters is not closed and the parser reaches the EOT. What I would like to see here is (1) what production the parser was in when it expected the '"' (I've multiple ones) and (2) where in the input this production started parsing (which is an indicator where the opening quote is in the input). Does anybody know how I can improve the error messages and include more information about the actual internal parsing state when the error happens (perhaps something like a production rule stacktrace or whatever can be given reasonably here to better identify the error location). BTW, the above "line 32, column 1" is actually the EOT position and hence of no use here, of course.
I don't know yet how to deal with (1), but I was also looking for (2) when I found this webpage:
https://wiki.scala-lang.org/plugins/viewsource/viewpagesrc.action?pageId=917624
I'm just copying the information:
A useful enhancement is to record the input position (line number and column number) of the significant tokens. To do this, you must do three things:
Make each output type extend scala.util.parsing.input.Positional
invoke the Parsers.positioned() combinator
Use a text source that records line and column positions
and
Finally, ensure that the source tracks positions. For streams, you can simply use scala.util.parsing.input.StreamReader; for Strings, use scala.util.parsing.input.CharArrayReader.
I'm currently playing with it so I'll try to add a simple example later
In such cases you may use err, failure and ~! with production rules designed specifically to match the error.