Jump to content

Jabadahut50
 Share

You are about to reply to a thread that has been inactive for 290 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

A simple little function I whipped up to aid in debugging.

To use, you would call Bail = Assume() before and/or after another function that manipulates data to test to see if the data going in or out is what you expect it to be. If not, Bail becomes set to 0 and a simple if statement with

llSetScriptState(llGetScriptName(),FALSE);
llSleep(0.1);

will stop the script. As you can probably tell, I wrote this using the Firestorm Preprocessor, since I plan to use it frequently in 
debugging my scripts.

I'll hop back on here later and leave a more conventional copy/paste version for people who prefer not to use the Preprocessor.

EDIT: Updated code to include Quistess Alpha's recommendations, as well as a new call counter to aid in finding which exact call of Assume(); in your script caused a bail. Additionally, added some very basic example codes.

 

/*Assume and Bail

    Goal: Create functions and macros to enable easier debugging
        
    # Released under MIT License

    Copyright (c) 2023 Abel Skaeren(Jabadahut50.Resident)

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef DEBUG
#define DEBUG
#endif //DEBUG

#ifdef DEBUG
#ifndef ASSUMEANDBAIL
#define ASSUMEANDBAIL
integer Bail;//Global variable for bailing
integer AssumeCalls = 0;

integer Assume(list input, list test){//test to make sure the input is what you are expecting it to be.
    integer i; //for the loops
    ++AssumeCalls; //for tracking which assume call triggered the Bail.
    list TYPES = ["invalid","integer","float","key","string","vector","rotation"];//Thank you to Quistess Alpha's reccomendation for simplifying the testing using this.
    //test first to make sure there lengths are the same
    if(input != test){
        llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input and Test lists not the same length, Bailing!");
        return 0;
    }else{
      //test to make sure the inputs share types
        for(i = 0; i <= llGetListLength(input); ++i){
            if(llGetListEntryType(input, i) != llGetListEntryType(test, i)){
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input[" + (string)i + "] did not match type to Test[" + (string)i + "]");
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input[" + (string)i + "] was " + llList2String(TYPES,llGetListEntryType(input, i)) + ".");
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", expected " + (string)TYPES[llGetListEntryType(test, i)] + ". Bailing!");
                return 0;
            }
        }
      //finally, test to make sure the input actually matches
        for(i = 0; i<= llGetListLength(input); ++i){
            if((string)input[i] != (string)test[i]){
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input[" + (string)i + "]: " + (string)input[i] + " did not match Test[" + (string)i + "]: " + (string)test[i] + ". Bailing!");
                return 0;
            }
        }
    }
    llOwnerSay("Succes| Func: Assume Call " + (string)AssumeCalls + ", Complete. " + llList2CSV(input) + " matched test. Proceeding.");
    return 1;
}
#endif //ASSUMEANDBAIL
#endif //DEBUG

default{
    state_entry(){
        llOwnerSay("click to test");
    }
    touch(integer num_detected){
        //will pass as written
        Bail = Assume([1,2.5,"Wohoo"],[1,2.5,"Wohoo"]);
        if(Bail == FALSE){
            llSetScriptState(llGetScriptName(), FALSE);
            llSleep(0.1);
        }
        //will fail due to Element[3] not matching
        Bail = Assume([1,2.5,"woohoo"],[1,2.5,"wohoo"]);
        if(Bail == FALSE){
            llSetScriptState(llGetScriptName(), FALSE);
            llSleep(0.1);
        }
        // will fail for different list lengths
        Bail = Assume([1,2.5],[1,2.5,"wohoo"]);
        if(Bail == FALSE){
            llSetScriptState(llGetScriptName(), FALSE);
            llSleep(0.1);
        }
        //will fail for Element[1] bieng different types
        Bail = Assume([1,2.5,"Wohoo"],[1.0,2.5,"Wohoo"]);
        if(Bail== FALSE){
            llSetScriptState(llGetScriptName(), FALSE);
            llSleep(0.1);
        }
    }
}

 

Edited by Jabadahut50
Updated Code
  • Thanks 1
Link to comment
Share on other sites

This seems like a neat idea, but some small nitpicks:

1) instead of

llGetListLength(input) != llGetListLength(test)

you can just directly compare the lists, avoiding 2 function calls: input != test

2) instead of a block of switch statements differentiated only by the output message, use a simpler non-branching structure:

list TYPES = ["invalid","integer","float","key","string","vector","rotation"];
llOwnerSay("ERROR| Func: Assume, expected an "+llList2String(TYPES,llGetListEntryType(test, i))+". Bailing!");

3) if you value code simplicity over mild efficiency gains, do the same for the case where you know the types are the same, and just test the string representations.

Edited by Quistess Alpha
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

7 hours ago, Quistess Alpha said:

This seems like a neat idea, but some small nitpicks:

1) instead of

llGetListLength(input) != llGetListLength(test)

you can just directly compare the lists, avoiding 2 function calls: input != test

2) instead of a block of switch statements differentiated only by the output message, use a simpler non-branching structure:

list TYPES = ["invalid","integer","float","key","string","vector","rotation"];
llOwnerSay("ERROR| Func: Assume, expected an "+llList2String(TYPES,llGetListEntryType(test, i))+". Bailing!");

3) if you value code simplicity over mild efficiency gains, do the same for the case where you know the types are the same, and just test the string representations.

Excellent suggestions, will defiantly update the code when I can. The efficiency is less important to me on this script because it's only going to be used (by me at least) during debugging. When I go to make the script efficient and fast for publishing after getting it to work, I'll #undefine DEBUG removing all of this anyway.

7 hours ago, Love Zhaoying said:

For my use, I'd probably switch out the list usage for JSON_ARRAY, otherwise great!!

 

 

I've never personally used JSON_ARRAY's yet (I only started coding in LSL about a month ago) but feel free to modify for your uses if it helps ^.^

Edited by Jabadahut50
  • Thanks 1
Link to comment
Share on other sites

Won't let me edit the original again, so posting new modification here. This version makes Bail into a function and automatically removes it when you use #undefine DEBUG in your script, so you no longer need to put your Bail = Assume(); and following if statement into an #ifdef DEBUG block. The Preprocessor will simply automatically remove the new function for you.

/*Assume and Bail

    Goal: Create functions and macros to enable easier debugging
        
    # Released under MIT License

    Copyright (c) 2023 Abel Skaeren(Jabadahut50.Resident)

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef DEBUG
#define DEBUG
#endif //DEBUG

#ifndef ASSUMEANDBAIL
#define ASSUMEANDBAIL
#ifdef DEBUG
integer AssumeCalls = 0;

integer Assume(list input, list test){//test to make sure the input is what you are expecting it to be.
    integer i; //for the loops
    ++AssumeCalls; //for tracking which assume call triggered the Bail.
    list TYPES = ["invalid","integer","float","string","key","vector","rotation"];//Thank you to Quistess Alpha's reccomendation for simplifying the testing using this.
    //test first to make sure there lengths are the same
    if(input != test){
        llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input and Test lists not the same length, Bailing!");
        return 0;
    }else{
        for(i = 0; i <= llGetListLength(input); ++i){
            if(llGetListEntryType(input, i) != llGetListEntryType(test, i)){
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input[" + (string)i + "] did not match type to Test[" + (string)i + "]");
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input[" + (string)i + "] was " + llList2String(TYPES,llGetListEntryType(input, i)) + ".");
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", expected " + (string)TYPES[llGetListEntryType(test, i)] + ". Bailing!");
                return 0;
            }
        }
        for(i = 0; i<= llGetListLength(input); ++i){
            if((string)input[i] != (string)test[i]){
                llOwnerSay("ERROR| Func: Assume Call " + (string)AssumeCalls + ", Input[" + (string)i + "]: " + (string)input[i] + " did not match Test[" + (string)i + "]: " + (string)test[i] + ". Bailing!");
                return 0;
            }
        }
    }
    llOwnerSay("Succes| Func: Assume Call " + (string)AssumeCalls + ", Complete. " + llList2CSV(input) + " matched test. Proceeding.");
    return 1;
}

Bail(list input, list test){
    integer Bail;
    Bail = Assume(input, test);
    if(Bail == FALSE){
        llSetScriptState(llGetScriptName(), FALSE);
        llSleep(0.1);
    }
}
#else
#define Bail(x,y) /* Removed by #undef DEBUG */
#endif //DEBUG
#endif //ASSUMEANDBAIL

default{
    state_entry(){
        llOwnerSay("click to test");
    }
    touch(integer num_detected){
        /*will pass as written. Must include ()'s around lists not passed as variables in order to satisfy
        #undefine macro */
        Bail(([1,2.5,"Wohoo"]),([1,2.5,"Wohoo"]));
        //will fail due to Element[3] not matching
        Bail(([1,2.5,"woohoo"]),([1,2.5,"wohoo"]));
        // will fail for different list lengths
        Bail(([1,2.5]),([1,2.5,"wohoo"]));
        //will fail for Element[1] bieng different types
        Bail(([1,2.5,"Wohoo"]),([1.0,2.5,"Wohoo"]));
    }
}

 

Edited by Jabadahut50
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Another update. This time I moved the Bail function into the Assume function and then split the Assume function into two separate types, allowing to individually test for type and value. Additionally, I added the ability to return instead of Bailing by setting a new parameter the BailFlag to 0 to allow for error handling instead of automatically killing the script no matter what.

 

/*Assume and Bail

    Goal: Create functions and macros to enable easier debugging
        
    # Released under MIT License

    Copyright (c) 2023 Abel Skaeren(Jabadahut50.Resident)

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef DEBUG
#define DEBUG
#endif //DEBUG

#ifndef ASSUMEANDBAIL
#define ASSUMEANDBAIL
#ifdef DEBUG
integer AssumeTypesCalls = 0;
integer AssumeValuesCalls = 0;

integer AssumeTypes(list Assume, list Test, integer BailFlag){
    integer i;//for loops
    integer count;//for loops
    list types = ["Invalid","Integer","Float","String","Key","Vector","Rotation"];//Thank you to Quistess Alpha's reccomendation for simplifying the testing using this.
    
    ++AssumeTypesCalls;
    if(Assume != Test){
        if(BailFlag == TRUE){
            llOwnerSay("ERROR| Func: AssumeTypes Call " + (string)AssumeTypesCalls + ": Assume and Test are not the same length. Bailing!");
            llSetScriptState(llGetScriptName(),FALSE);
            llSleep(0.1);
        }else{
            llOwnerSay("ERROR| Func: AssumeTypes Call " + (string)AssumeTypesCalls + ": Assume and Test are not the same length. Returning.");
            return 0;
        }
    }
    count = llGetListLength(Test);
    for(i = 0; i < count; ++i){
        if(llGetListEntryType(Assume, i) != llGetListEntryType(Test, i)){
            if(BailFlag == TRUE){
                llOwnerSay("ERROR| Func: AssumeTypes Call " + (string) AssumeTypesCalls + ": Assume[" + (string)i + "] Type " + (string)types[llGetListEntryType(Assume, i)] + " did not match Test[" + (string)i + "] Type " + (string)types[llGetListEntryType(Test,i)] + ". Bailing!");
                llSetScriptState(llGetScriptName(),FALSE);
                llSleep(0.1);
            }else{
                llOwnerSay("ERROR| Func: AssumeTypes Call " + (string)AssumeTypesCalls + ": Assume[" + (string)i + "] Type " + (string)types[llGetListEntryType(Assume, i)] + " did not match Test[" + (string)i + "] Type " + (string)types[llGetListEntryType(Test,i)] + ". Returning.");
                return 0;
            }
        }
    }
    llOwnerSay("SUCCESS| Func: AssumeTypes Call " + (string)AssumeTypesCalls + ": Assume and Test share all types. Returning.");
    return 1;
}

integer AssumeValues(list Assume, list Test, integer BailFlag){
    integer i;
    integer count;
    
    ++AssumeValuesCalls;
    if(Assume != Test){
        if(BailFlag == TRUE){
            llOwnerSay("ERROR| Func: AssumeValues Call " + (string)AssumeValuesCalls + ": Assume and Test are not the same length. Bailing!");
            llSetScriptState(llGetScriptName(),FALSE);
            llSleep(0.1);
        }else{
            llOwnerSay("ERROR| Func: AssumeValues Call " + (string)AssumeValuesCalls + ": Assume and Test are not the same length. Returning!");
            return 0;
        }
    }else{
        count = llGetListLength(Assume);
        for(i = 0; i < count; ++i){
            if((string)Assume[i] != (string)Test[i]){
                if(BailFlag == TRUE){
                    llOwnerSay("ERROR| Func: AssumeValues Call " + (string)AssumeValuesCalls + ": Assume[" + (string)i + "] Value: " + (string)Assume[i] + " did not match Test[" + (string)i + "] Value: " + (string)Test[i] + ". Bailing!");
                    llSetScriptState(llGetScriptName(),FALSE);
                    llSleep(0.1);
                }else{
                    llOwnerSay("ERROR| Func: AssumeValues Call " + (string)AssumeValuesCalls + ": Assume[" + (string)i + "] Value: " + (string)Assume[i] + " did not match Test[" + (string)i + "] Value: " + (string)Test[i] + ". Returning.");
                    return 0;
                }
            }
        }
    }
    llOwnerSay("SUCCESS| Func: AssumeValues Call " + (string)AssumeValuesCalls + ": Assume and Test Values all equal. Returning.");
    return 1;
}
#else
#define AssumeType(x,y) /* Removed by #undef DEBUG */
#define AssumeValue(x,y) /* Removed by #undef DEBUG */
#endif //DEBUG
#endif //ASSUMEANDBAIL

default
{
    touch(integer num_detected)
    {
        integer i;
        //Passes and returns
        i = AssumeTypes([1,2,3],[1,2,3],0);
        //Fails and returns
        i = AssumeTypes([1,"2",3],[1,2,3],0);
        //Passes and returns
        i = AssumeValues([1,2,3],[1,2,3],0);
        //Fails and Bails.
        i = AssumeValues([1,2.1,3],[1,2,3],1);
    }
}

 

Edited by Jabadahut50
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 290 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...