Defining a method for a struct

Hello,

I would like to do this:
 

struct toto{}
 
toto create(int x){
   Buffer b = create
   delete b
   string s = "something"
   return (addr_ s) toto
}

 


but this fails with the following error:

 

 

 

-E- DXL: <Line:4> incorrect use of identifier (create)
-I- DXL: all done with 1 error and 0 warnings


I suspect that the problem is related with the following discussion item on symbol scoping:

{link}
https://www.ibm.com/developerworks/forums/thread.jspa?messageID=14465130&#14465130
{link}

Any feedback is welcome.
Vincent.

 

 


SystemAdmin - Tue Oct 04 08:21:45 EDT 2011

Re: Defining a method for a struct
Tony_Goodman - Tue Oct 04 09:09:31 EDT 2011

I don't think you can use struct() in DXL. The word is defined as a keyword, but it never got implemented.

Instead, use the DxlObject type. This is not in the DXL reference manual, but has been used.
It can be used in a similar way to a C struct.
 

DxlObject d = new()
 
d->"Name" = "Tony"
d->"Age"  = 21  // I wish
 
myAge = (int d->"Age")
myName = (string d->"Name")
 
delete(d)

 


A larger example can be found at http://www.smartdxl.com/content/?p=418
Tony Goodman, www.smartdxl.com

 

Re: Defining a method for a struct
a_vestlin - Tue Oct 04 09:32:07 EDT 2011

Hi

The problem is that you "hide" all other create functions (in the global context) from the DXL parser , when you declare yours. The workaround is to rename your function, for example createToto.

There is no problem to use the struct keyword. I am using it on regural basis in combination with the DxlObject to define my own types.

/Anders

Re: Defining a method for a struct
SystemAdmin - Tue Oct 04 10:14:42 EDT 2011

a_vestlin - Tue Oct 04 09:32:07 EDT 2011
Hi

The problem is that you "hide" all other create functions (in the global context) from the DXL parser , when you declare yours. The workaround is to rename your function, for example createToto.

There is no problem to use the struct keyword. I am using it on regural basis in combination with the DxlObject to define my own types.

/Anders

Hello,

Thanks for the very quick feedback.

I do not understand why I hide the global =create=. My understanding is that in DXL a function prototype takes into account also the type of the returned value.

In my function below

toto create(int x)

 


the returned type is =toto=. Because in the global scope there is no such thing as a =create= function that returns a =toto=, there should not be such kind of conflict.

Vincent.

 

Re: Defining a method for a struct
SystemAdmin - Tue Oct 04 14:35:39 EDT 2011

SystemAdmin - Tue Oct 04 10:14:42 EDT 2011

Hello,

Thanks for the very quick feedback.

I do not understand why I hide the global =create=. My understanding is that in DXL a function prototype takes into account also the type of the returned value.

In my function below

toto create(int x)

 


the returned type is =toto=. Because in the global scope there is no such thing as a =create= function that returns a =toto=, there should not be such kind of conflict.

Vincent.

 

Here is some working code that uses struct and defines a custom type. Test code is at the bottom. It adds methods (member functions) to the custom type. Try it out and maybe you can adapt something similar for your particular needs.

If all goes well, you'll get this output:

Begining tests
Test1 of ParameterType
Param label=myLabel
Param value=myValue
Serialized string of Param is myLabel=myValue
Content of myParam is 106829456
Always set object reference to null after destruct.
Content of myParam is 0
Test2 of ParameterType
Param label=AnotherLabel
Param value=AnotherValue
Serialized string of Param is AnotherLabel=AnotherValue
Test3 of ParameterType
Param label=Label22
Param value=Value22
Serialized string of Param is Label22=Value22
Done with tests

// Example User type
 
/*
  Example User type
*/
//------------------------------------------------------------------------------
// BEGIN library type stuff
//------------------------------------------------------------------------------
 
// string library stuff
 
string rightTrim(string s) {
    if (null s) return "";
    int first = 0;
    int last = length(s) - 1;
    while( (last > -1) && (isspace(s[last])) ){
       last--;
    }
    return(s[first:last]);
}
 
string leftTrim(string s) {
    if (null s) return "";
    int first = 0;
    int last = length(s) - 1;
    while( (isspace(s[first])) && (first < last) ) {
       first++;
    }
    return(s[first:last]);
}
 
string trim(string s) {
    return(leftTrim(rightTrim(s)));
}
 
bool isFinite(string str) {
    if (null str) str = "";
    return (length(trim(str)) > 0);
}
 
int firstIndexOf(char ch, string s, bool &hasMoreThanOne) {
    hasMoreThanOne = false;
    int foundAtIndex = -1;
    int i = -1;
    int counter = 0;
    for (i = 0; i < length(s); i++ ) {
        if (s[i] == ch) {
            counter++;
            if (counter == 1) {
                foundAtIndex = i;
            } else {
                hasMoreThanOne = true;
                break;
            }
        }
    }
    return foundAtIndex;
}
 
// DxlObject library stuff
 
int getDxlField(DxlObject dxlObject, string fieldName) {
    int temp = (int (dxlObject)->(fieldName));
    return temp;
}
 
void setDxlField(DxlObject dxlObject, string fieldName, _m value) {
    // Store all as int
    // It does not matter as long as you convert to proper type on the way out
    (dxlObject)->(fieldName) = (int value);
}
 
//------------------------------------------------------------------------------
// END library type stuff
//------------------------------------------------------------------------------
 
 
//------------------------------------------------------------------------------
// TYPE DEFINITION ParameterType
//------------------------------------------------------------------------------
struct ParameterType {}
 
string TYPE_NAME(ParameterType this) {
    return "ParameterType";
}
 
//------------------------------------------------------------------------------
// STATIC FUNCTION: Allow "dot" syntax for static constant reference
// (e.g., provide Parameter.TYPE in lieu of TYPE(Parameter)
//------------------------------------------------------------------------------
ParameterType ::.(ParameterType this, //-
                  ParameterType function(ParameterType)) {
    return function(this);
}
 
//------------------------------------------------------------------------------
// STATIC FUNCTION: Allow "dot" syntax for static constant reference
// (e.g., Parameter.TYPE_NAME)
//------------------------------------------------------------------------------
string ::.(ParameterType this, string function(ParameterType)) {
    return function(this);
}
 
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
DxlObject DxlObjectOf(ParameterType this) {
    return (DxlObject addr_ this);
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
DxlObject& DxlObjectRefOf(ParameterType& this) {
    return addr_ this;
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType ParameterTypeOf(DxlObject dxlObject) {
    return (ParameterType addr_ dxlObject);
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType& ParameterTypeRefOf(DxlObject& dxlObject) {
    return (addr_ dxlObject);
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType Parameter() {
    return ParameterTypeOf(null);
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType TYPE(ParameterType this) {
    return Parameter();
}
 
//------------------------------------------------------------------------------
// PRIVATE GETTER FUNCTION
//------------------------------------------------------------------------------
string getLabel_(ParameterType this) {
    return (string (addr_ (getDxlField(DxlObjectOf(this), "label_"))));
}
 
//------------------------------------------------------------------------------
// PRIVATE SETTER FUNCTION
//------------------------------------------------------------------------------
void setLabel_(ParameterType this, string label_) {
    setDxlField(DxlObjectOf(this), "label_", label_);
}
 
//------------------------------------------------------------------------------
// PRIVATE GETTER FUNCTION
//------------------------------------------------------------------------------
string getValue_(ParameterType this) {
    return (string (addr_ (getDxlField(DxlObjectOf(this), "value_"))));
}
 
//------------------------------------------------------------------------------
// PRIVATE SETTER FUNCTION
//------------------------------------------------------------------------------
void setValue_(ParameterType this, string value_) {
    setDxlField(DxlObjectOf(this), "value_", value_);
}
 
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
string getLabel(ParameterType this) {
    return (getLabel_(this));
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
void setLabel(ParameterType this, string label) {
    setLabel_(this, trim(label))
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
string getValue(ParameterType this) {
    return (getValue_(this));
}
 
//------------------------------------------------------------------------------
// PUBLIC SETTER FUNCTION
//------------------------------------------------------------------------------
void setValue(ParameterType this, string value) {
    setValue_(this, trim(value));
}
 
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
// Sets label and value in one shot
//------------------------------------------------------------------------------
void set(ParameterType this, string label, string value) {
    setLabel(this, label);
    setValue(this, value);
}
 
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
string getSerializedString(ParameterType param) {
    string retVal = "";
    if (isFinite(getLabel(param))) {
        retVal = getLabel(param) "=" getValue(param);
    }
    return retVal;
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
void setFromSerializedString(ParameterType this, string serialStr) {
    // A "Serialized String" is form label=value
    string label = "";
    string value = "";
    bool hasMoreThanOne = false; // not used here
    int indexOfSeparator = -1;
    bool didOnce;
    for(didOnce = false; !didOnce; didOnce = true) {
        if (!isFinite(serialStr)) break;
        if (length(serialStr) < 2) break;
        int startingIndex = 0;
        int i = firstIndexOf('=', serialStr, hasMoreThanOne);
        if (i == -1) break;
        indexOfSeparator = i;
    }
    if (indexOfSeparator > 0) {
        label = serialStr[0:(indexOfSeparator-1)];
        value = serialStr[(indexOfSeparator+1):(length(serialStr)-1)];
        set(this, label, value);
    } else {
        ack "Bad serial param: " serialStr;
        halt;
    }
    return this;
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
// Master Constructor
//------------------------------------------------------------------------------
ParameterType Parameter_construct(string label, string value) {
    //--------------------------------------------------------------------------
    // Construct an instance of the base type for this type (starting point)
    //--------------------------------------------------------------------------
    DxlObject dxlObject = new();
    ParameterType this = ParameterTypeOf(dxlObject);
 
    //--------------------------------------------------------------------------
    // Give fields their initial values
    //--------------------------------------------------------------------------
    set(this, label, value);
 
    return this;
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType Parameter_construct(string label) {
    return Parameter_construct(label, "");
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType Parameter_construct() {
    return Parameter_construct("", "");
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
ParameterType Parameter_constructFromSerializedString(string serialStr) {
    ParameterType this = Parameter_construct();
    setFromSerializedString(this, serialStr);
    return this;
}
 
//------------------------------------------------------------------------------
// PUBLIC FUNCTION
//------------------------------------------------------------------------------
void destruct(ParameterType& this) {
    //--------------------------------------------------------------------------
    // If your new type has allocated memory consuming fields (e.g., Buffer,
    // Skip, etc.) unravel and delete them here BEFORE disposing the base
    // object that holds them
    //--------------------------------------------------------------------------
 
        // No memory-consuming fields in this example
 
    //--------------------------------------------------------------------------
    // Destruct the base type
    //--------------------------------------------------------------------------
    delete(DxlObjectRefOf(this));
    this = null;
}
 
//------------------------------------------------------------------------------
// END MODULE ParameterType
//------------------------------------------------------------------------------
 
//------------------------------------------------------------------------------
// BEGIN ParameterType Test Code
//------------------------------------------------------------------------------
 
int anyToInt(_m any) {
    return (int any);
}
 
void showParam(ParameterType param) {
    print "Param label=" getLabel(param) "\n";
    print "Param value=" getValue(param) "\n";
    print "Serialized string of Param is " getSerializedString(param) "\n";
}
 
void test1() {
    // Set individually
    ParameterType myParam = Parameter_construct();
    print "Test1 of " myParam.TYPE_NAME "\n";
    setLabel(myParam, "myLabel");
    setValue(myParam, "myValue");
    showParam(myParam);
    print "Content of myParam is " (anyToInt(myParam)) "\n";
    destruct(myParam);
    print "Always set object reference to null after destruct.\n";
    print "Content of myParam is " (anyToInt(myParam)) "\n";
}
 
void test2() {
    ParameterType myParam = Parameter_constructFromSerializedString(" AnotherLabel = AnotherValue");
    print "Test2 of " myParam.TYPE_NAME "\n";
    showParam(myParam);
    destruct(myParam);
}
 
void test3() {
    ParameterType myParam = Parameter_construct("  Label22 ", "  Value22    ");
    print "Test3 of " myParam.TYPE_NAME "\n";
    showParam(myParam);
    destruct(myParam);
}
 
 
print "Begining tests \n";
test1();
test2();
test3();
print "Done with tests \n";
 
 
//------------------------------------------------------------------------------
// END ParameterType Test Code
//------------------------------------------------------------------------------

Re: Defining a method for a struct
Mathias Mamsch - Tue Oct 04 15:45:30 EDT 2011

SystemAdmin - Tue Oct 04 10:14:42 EDT 2011

Hello,

Thanks for the very quick feedback.

I do not understand why I hide the global =create=. My understanding is that in DXL a function prototype takes into account also the type of the returned value.

In my function below

toto create(int x)

 


the returned type is =toto=. Because in the global scope there is no such thing as a =create= function that returns a =toto=, there should not be such kind of conflict.

Vincent.

 

We already discussed this in some earlier thread. You are right there should be no conflict. DXLs symbol lookup is flawed in several ways. Sometimes it does not handle return types correctly. Additionally it fails in disambiguation of top context / dxl context level, when you take functions with no parameters. Therefore I would recommend to never name a function like any of the Type XY() functions in DXL: create, read, count, all, bottom, bold, delete, ... are all bad names for functions, since they inevitably will hide the corresponding top level functions.

A good practice for me has been to always name your function createTypeName, e.g. createToto and also the destructor deleteToto.

If you encounter a case where some developer accidently used such a function a type cast or simply adding braces for the void function call, can resolve the issue as a workaround:
 

struct toto{}
 
toto create(int x){
   Buffer b = create() 
   delete b  
   string s = "something"
   return (addr_ s) toto
}

 


This works ... ;-) Don't ask, don't try to understand just try getting over it fast ... And follow the good practice. Regards, Mathias

P.S.: You will be in hell, once you have called a function "create" and now you want to search for every function call in your library of 300000 lines of code! Then you will start writing a DXL parser ... :-)

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Defining a method for a struct
llandale - Wed Oct 05 12:23:33 EDT 2011

Mathias Mamsch - Tue Oct 04 15:45:30 EDT 2011

We already discussed this in some earlier thread. You are right there should be no conflict. DXLs symbol lookup is flawed in several ways. Sometimes it does not handle return types correctly. Additionally it fails in disambiguation of top context / dxl context level, when you take functions with no parameters. Therefore I would recommend to never name a function like any of the Type XY() functions in DXL: create, read, count, all, bottom, bold, delete, ... are all bad names for functions, since they inevitably will hide the corresponding top level functions.

A good practice for me has been to always name your function createTypeName, e.g. createToto and also the destructor deleteToto.

If you encounter a case where some developer accidently used such a function a type cast or simply adding braces for the void function call, can resolve the issue as a workaround:
 

struct toto{}
 
toto create(int x){
   Buffer b = create() 
   delete b  
   string s = "something"
   return (addr_ s) toto
}

 


This works ... ;-) Don't ask, don't try to understand just try getting over it fast ... And follow the good practice. Regards, Mathias

P.S.: You will be in hell, once you have called a function "create" and now you want to search for every function call in your library of 300000 lines of code! Then you will start writing a DXL parser ... :-)

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

I use empty braces for parameterless functions routinely as it makes it clear to me that its a function.
A = B
A = B()
The 2nd one provides the reader more information.
I also rarely fail to use parens for single parameter functions:
A = B C
A = B(C)
Although I admit there are times its not really better:
if (null oOther)
if (null(oOther))

I'm also adopting a policy of naming functions generally "Topic_VerbNoun" and global variables "Topic_AdjectiveNoun". So in this case the function would be named "Toto_Create" and any global variables needed to support this toto would start with "Toto_". Its easier to find it in the library and it does remind me that its worthy of its own "topic" and therefore might be worth investigating what it all does. Other folks with sharper minds that can juggle 20 virtual balls in their heads may not need this as much as I do.

  • Louie

Re: Defining a method for a struct
SystemAdmin - Mon Oct 10 04:28:45 EDT 2011

llandale - Wed Oct 05 12:23:33 EDT 2011
I use empty braces for parameterless functions routinely as it makes it clear to me that its a function.
A = B
A = B()
The 2nd one provides the reader more information.
I also rarely fail to use parens for single parameter functions:
A = B C
A = B(C)
Although I admit there are times its not really better:
if (null oOther)
if (null(oOther))

I'm also adopting a policy of naming functions generally "Topic_VerbNoun" and global variables "Topic_AdjectiveNoun". So in this case the function would be named "Toto_Create" and any global variables needed to support this toto would start with "Toto_". Its easier to find it in the library and it does remind me that its worthy of its own "topic" and therefore might be worth investigating what it all does. Other folks with sharper minds that can juggle 20 virtual balls in their heads may not need this as much as I do.

  • Louie

Thanks to all for the good feedback.

I think that I will keep the "create" name for the function, and just use () for calling the create of Buffer and avoid the issue of the parser missing that this is a function call.

One of the advantage of overloading is that you can have contextual notation, so it would be a pitty to name it totoCreate or something like that just to work around some bug of DXL that may be solved in the future.

BTW, do you know if I should file a bug report concerning this.

Vincent.