AST MATCHER:How to match un init double param in constructor - constructor

I 'm having a question to match uninit double field in constructor.
Given the code below
class un_init_double {
public:
un_init_double() {
init_param_ = 0;
}
bool compare(un_init_double& other) {
if (other.un_init_param_ == un_init_param_) {
return true;
}
return false;
}
private:
double un_init_param_;
double init_param_;
};
I want to match the un_init_param_ field, which didn't call binary operator = in constructor. But I don't find the method to do that.
I type below command in clang-query
clang-query> match cxxRecordDecl(
has(fieldDecl(hasType(asString("double"))).bind("double_field")), has(cxxConstructorDecl(hasDescendant(binaryOperator(hasEitherOperand(memberExpr()))))))
But how to specify memberExpr is related with prew part fieldDecl? In another word, how to specify the connection of fieldDecl and the memberExpr?
I find a method to match init_param_, but how to find no match field?
clang-query> match cxxRecordDecl(has(cxxConstructorDecl(hasDescendant(binaryOperator(hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))))).bind("member")))))))
Match #1:
~/code_test/ast_matcher/test.cc:9:7: note: "member" binds here
init_param_ = 0;
^~~~~~~~~~~
~/code_test/ast_matcher/test.cc:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
1 match.
clang-query>

When debuging, I write a complicated method to perform this check:
// match record
cxxRecordDecl(
has(
// constuctor has init double fieldDecl with binaryoperator = , bind to init_double_field
cxxConstructorDecl(
hasDescendant(
binaryOperator(
hasOperatorName("="),
hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))).bind("init_double_field"))))
)
)
)
),
has(
// match double field which didn't call binaryoperator = in constructor
fieldDecl(hasType(asString("double")), unless(equalsBoundNode("init_double_field"))).bind("un_init_double_field")
)
)
It seems to work, but if I add a sentence: "un_init_param_ = 1;" in the constructor, it still takes un_init_param_ as uninit_field. Find that it's caused by ast matcher will only match the first one rather than match all. So I modify matcher to:
cxxRecordDecl(
has(
cxxConstructorDecl(
forEachDescendant(
binaryOperator(
hasOperatorName("="),
hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))).bind("init_double_field"))))
)
)
)
),
has(
fieldDecl(hasType(asString("double")), unless(equalsBoundNode("init_double_field"))).bind("un_init_double_field")
)
)
I modify original test.cpp to:
int f(int x) {
int result = (x / 42);
return result;
}
class un_init_double {
public:
un_init_double() {
init_param_0_ = 0;
init_param_1_ = 0;
}
bool compare(un_init_double& other) {
if (other.un_init_param_ == un_init_param_) {
return true;
}
return false;
}
private:
double un_init_param_;
double init_param_0_;
double init_param_1_;
};
New ast matcher can match it as follows:
Match #1:
/home/qcraft/code_test/ast_dump/test.cpp:20:5: note: "init_double_field" binds here
double init_param_0_;
^~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:19:5: note: "un_init_double_field" binds here
double un_init_param_;
^~~~~~~~~~~~~~~~~~~~~
Match #2:
/home/qcraft/code_test/ast_dump/test.cpp:21:5: note: "init_double_field" binds here
double init_param_1_;
^~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:19:5: note: "un_init_double_field" binds here
double un_init_param_;
^~~~~~~~~~~~~~~~~~~~~
2 matches.
clang-query>

Related

in defining a function in Dart, how to set an argument's default to { }, ie, an empty Map?

love how Dart treats function arguments, but cannot accomplish what should be a simple task:
void func( String arg1, [ Map args = {} ] ) {
...
}
get the error
expression is not a valid compile-time constant
have tried new Map() for example, with same error.
You have to use the const keyword :
void func( String arg1, [ Map args = const {} ] ) {
...
}
Warning : if you try to modify the default args you will get :
Unsupported operation: Cannot set value in unmodifiable Map
The default value must be a compile time constant, so 'const {}' will keep the compiler happy, but possibly not your function.
If you want a new modifiable map for each call, you can't use a default value on the function parameter. That same value is used for every call to the function, so you can't get a new value for each call that way.
To create a new object each time the function is called, you have to do it in the function itself. The typical way is:
void func(String arg1, [Map args]) {
if (args == null) args = {};
...
}

Default value for function argument, guaranteed to be unique

Just wondering, if i could provide default argument for function in ActionScript 3 which is never can be passed to the function by user. This is the case:
public function getAttr (obj:Object, key:String, def:* = DEFAULT_VALUE):* {
if (!obj.hasOwnProperty(key)) {
if (def === DEFAULT_VALUE) {
throw ReferenceError('Attribute not found: ' + key);
} else {
return def;
}
} else {
return obj[key];
}
}
I cannot use as DEFAULT_VALUE any of null, undefined, Number, Boolean or String here, cause, logically, user could use any of this values. I need something really unique here. In python, for example, i can do this:
_DEFAULT_VALUE = object()
def get_attr(obj, key, d=_DEFAULT_VALUE):
if not hasattr(obj, key):
if d is DEFAULT_VALUE:
raise KeyError('Attribute not found: {}'.format(key))
else:
return d
else:
return obj[d]
But in ActionScript 3 such approach produces an error:
Error code: 1047: Parameter initializer unknown or is not a compile-time constant.
Maybe some hack here?
Your problem here is that def value have to be a compile time constant so there is no way to store a default value into a var and pass it as a default value.
But what you really want here is to know if the user have passed an extra parameter into the def field of the function, so you can check the arguments array length and see if there is 2 or 3 parameters passed.
public function getAttr (obj:Object, key:String, def:* = null):* {
if (!obj.hasOwnProperty(key)) {
if (arguments.length==2) { // no default value passed to the function
throw new ReferenceError('Attribute not found: ' + key);
} else {
return def;
}
} else {
return obj[key];
}
}
Transfer null, and check for null. After all, null is a default value that's really nothing, if you require a parameter to be supplied and be valid, use null as default value so that if something will be supplied, it will not be null, thus valid.
Vesper's answer seems correct for your situation. But, I've used similar method for singletons though:
class Singleton
{
private var k_CONS_BLOCKER:Object = {};
public Singleton(cons_blocker:Object)
{
if(cons_blocker!=k_CONS_BLOCKER)
{
throw new Error("Use static getter to get the object");
}
}
public function getObject():Singleton
{
return obj;//you can of course create it now or do some other logic...
}
}
I know the answer isn't directly related to the question, but I think the idea solves the problem in general.
HTH.

How can I define a boolean function argument to be optional?

In ActionScript 3, is there a clean way to define a function that accepts an optional boolean argument ? As you may know, this is invalid :
public function test(param:Boolean = null):void {
trace(param);
}
This triggers the following error: VerifyError: Error #1102: Illegal default value for type Boolean. Since, Boolean is a primitive, I guess it makes sense that it cannot be set to null. The only workaround I found is to cast the parameter to an object :
public function test(param:Object = null):void {
trace(Boolean(param));
}
However, this does not feel very clean, particularly if you are developing libraries. ASDoc will generate API documentation that says the expected parameter is an Object whereas what is really needed is a Boolean.
Is there a better approach ?
When you say optional, I assume that you mean if there isn't a value supplied then something different should happen compared to if you had a default value of true or false.
You could make your own object to handle the three states that you need and maintain code readability by using a class like this:
public class Condition
{
private var _value:* = null;
public function Condition(initial:* = null)
{
value = initial;
}
public function set value(n:*):void
{
if(_value === null || _value === false || _value === true)
{
_value = n;
}
}
public function get value():*{ return _value; }
}
And then your function could be:
function test(param:Condition = null):void
{
if(param && param.value != null)
{
trace(param.value);
}
}
test( new Condition() );
test( new Condition(true) );
As you said Boolean can not be set to null value.
Therefore, you should specify a default value that is either true or false.
public function test(param:Boolean = false):void {
trace(param);
}
But because you need the third case where nothing is set, one option could be to accept any Object but throw an exception if it is not null and not a boolean:
public function test(param:* = null):void
{
if (param != null)
{
if ((param == true) || (param == false))
{
trace(Boolean(param).toString());
}
else
{
throw new CustomError("param should be a boolean");
}
}
else
{
// Do nothing
}
}
Note that this solution also accept objects or primitives that can be compared to true or false such as 0, 1, or [].
From the good suggestions and discussion above I think that, in a library scenario and for simplicity's sake, the best way remains to type the parameter as Object with a default value of null but to request a Boolean in the API documentation :
/**
* #param param Boolean object or null
*/
public function test(param:Object = null):void {
trace(Boolean(param));
}
This allow the user of the library to pass a either a Boolean or nothing at all. Thanks everyone.
There was a tonne of discussion on my previous answer, but this is the correct way to have a function that accepts one of three states. My previous answer attempted to retain the use of a Boolean value like you were requesting, but that is not the right way to go about it.
Create a class that defines three values:
class State
{
public static const EMPTY:int = -1;
public static const FALSE:int = 0;
public static const TRUE:int = 1;
}
Your function will accept an int (the type of each of the three properties within your State class). It will deal with the three possible values. You can use concise commenting to notify the developer of what thee values the function is expecting, referencing the State class. The default value can be -1 aka State.EMPTY.
/**
* Function description.
* #param state One of three states, defined by State.
*/
function test(state:int = -1):void
{
switch(state)
{
case State.EMPTY:
// No value given.
break;
case State.TRUE:
// True.
//
break;
case State.FALSE:
// False.
//
break;
default:
throw new ArgumentError("Unsupported value for test()");
break;
}
}

appropriate term for a predicate that has state

A predicate (an object that is a boolean-valued function which tests its input for a condition) is generally assumed to be stateless.
What's the most appropriate name for an object which has a testing function with state?
e.g. in Java, the CountTrigger class below returns true only on the Nth time it is tested against a value that matches a desired value, and false otherwise.
interface QuasiPredicate<T> // what should this be renamed to?
{
public boolean test(T value);
}
class CountTrigger<T> implements QuasiPredicate<T>
{
// for simplicity, ignore synchronization + null-value issues
private int remainingTriggers = 0;
final private T testValue;
public CountTrigger(T testValue, int count)
{
this.remainingTriggers = count;
this.testValue = testValue;
}
#Override public boolean test(T value)
{
if (!this.testValue.equals(value))
return false;
if (this.remainingTriggers == 0)
return false;
if (--this.remainingTriggers == 0)
return true;
}
}
Considering it's an interface and interfaces are implemented and not extended then I don't see the problem in your object implementing a predicate.
If you're going to put public CountTrigger(T testValue, int count) in the interface as well then maybe you need a different name. Perhaps IFiniteRule or another suitable synonym. Maybe ask at https://english.stackexchange.com/ ;-)

D compile-time function type extraction

D2.056
Function is a struct holding the name and the type of the function (Name and Type respectively). Binds iterates over a list of Function structs and returns a mixin string. This mixin defines for each function a new name with a '2' appended.
void f() { writeln("f"); }
void g() { writeln("g"); }
struct Function(string name, Prototype)
{
const string Name = name;
mixin("alias Prototype Type;");
}
string Binds(Functions...)()
{
string r;
foreach (F; Functions)
{
// error:
r ~= to!string(typeid(F.Type)) ~ " " ~ F.Name ~ "2 = &" ~ F.Name ~ ";";
}
return r;
}
int main()
{
mixin (Binds!(
Function!("f", void function()),
Function!("g", void function())
));
f();
//f2();
return 0;
}
When compiling, the to!string(typeid(F.Type)) gives an error:
Error: Cannot interpret & D13TypeInfo_PFZv6__initZ at compile time
called from here: to(& D13TypeInfo_PFZv6__initZ)
called from here: Binds()
Firstly, I don't see why an explicit conversion to string is required (isn't typeid already a string, if not, whats the difference between typeid and typeof?).
Secondly, I can't figure out how to get the explicit function type written out so that it can be executed in main. I can't use F.Type since it is local to the foreach.
You've got a couple problems here, but the main one is that typeid returns an object of type TypeInfo (typeid expression). Fortunately, you can just use F.Type.stringof. Also note that you don't need the mixin to alias Prototype as Type:
void f() { writeln("f"); }
void g() { writeln("g"); }
struct Function(string name, Prototype)
{
const string Name = name;
alias Prototype Type;
}
string Binds(Functions...)()
{
string r;
foreach (F; Functions)
{
// error:
r ~= F.Type.stringof ~ " " ~ F.Name ~ "2 = &" ~ F.Name ~ ";";
}
return r;
}
import std.stdio,
std.conv;
int main()
{
mixin (Binds!(
Function!("f", void function()),
Function!("g", void function())
));
f();
f2();
return 0;
}
Running this prints:
f
f
which I believe is what you're looking for.