programmatic insert of code into function.

I have a function with a number of if_endthen statements.  The expressions that I use in the statements need to be changed occassionally and at the moment I edit them manually.  Is it possible to use a string containing the text to be used within the if expression and to translate that text so that it operates within the code. 

if (x=1 && b=2)
  // do something
endif

string expression ="(x=1 && c=2)"

Above is an example of what I would like to be able to do.  At the moment I have a, say, the expression as shown, and I would like to program in someway so that the string or textwave item containing the replacement expression into the original code.  I am not a professional programmer (as you will have guessed) but I think it is called parsing?

 

Would you expect these statements to be infinite in variations or can you expect them to be finite in how many you need? I can suggest in the former case that you may have to resort to a function that is called with the string using Execute. I might suggest in the latter case that you could hard code the options entirely and simply comment / uncomment them as needed during editing.

I use the if statements as data filters which need testing and optimising for each experiment.  At present there are 10 statements and some 20 odd variables which are usually combined and have individual limits.  So, it is the former of your two suggestions I would need to use.

I have been using the comment / uncomment method but as each of the statements I wish to change could be entirely different  I sought another way.

I am still not sure what you want to do. I can guess in two different directions. Can you provide a minimum working example (MWE) of code block A that you want to change to code block B without having to make the change using manual editing?

/I'm not quite sure of your workflow, but could you use something along these lines? ...

Function myCondition(a, b)
    variable a, b
    if (a < b)
        return 1
    else
        return 0
    endif
End

Function DoStuff()
    variable v1, v2
    v1 = 1
    v2 = 2
    if (myCondition(v1, v2))
        print "expression is true"
    else
        print "expression is false"
    endif
End

You rewrite the function myCondition (which could be at the top of the given procedure window), and then the main functions would call this when it needs to. This saves having to look through many lines of code to find the desired if-statements to change.

If you want to programmatically change the condition function, then maybe FUNCREFs could help?

JJ a little difficult to do as I don't know what yopu have in mind.  So, I give you an edited/tidied section of the code I use to give you an idea of the stats waves  (at the top of this snippet) that I may want to use in the if statements (conjectures 0 to 9)  Conjecture 7 and 8 show the type of commenting out that I make.  All the stats wave have the same number of points (number of items) in the for.. endfor loop and the wave itemType[numberofItems][10] contains the result of the conjecture test

    // These are the stats used in the identification of logged item types
    wave Tstart     = $StatsDFN +":"+"Tstart"
    wave StartPnt   = $StatsDFN +":"+"StartPnt"
    wave Tend       = $StatsDFN +":"+"Tend"
    wave EndPnt     = $StatsDFN +":"+"EndPnt"
    wave Duration   = $StatsDFN +":"+"Duration"
    wave ItemPnts   = $StatsDFN +":"+"ItemPnts"
    wave Gap        = $StatsDFN +":"+"Gap" 
    wave SNRmax     = $StatsDFN +":"+"SNRmax"  
    wave SdBmax     = $StatsDFN +":"+"SdBmax"
    wave SdBsd      = $StatsDFN +":"+"SdBsd"
    wave SdBmean    = $StatsDFN +":"+"SdBmean"
    wave Fstart     = $StatsDFN +":"+"Fstart"
    wave Fend       = $StatsDFN +":"+"Fend"
    wave Fmax       = $StatsDFN +":"+"Fmax"
    wave Fmin       = $StatsDFN +":"+"Fmin"
    wave Fmean      = $StatsDFN +":"+"Fmean"
    wave Fsd        = $StatsDFN +":"+"Fsd"
    wave PeakNum    = $StatsDFN +":"+"PeakNum" 
    wave HEpnts     = $StatsDFN +":"+"HEpnts"        
    wave HEslope    = $StatsDFN +":"+"HEslope" 


    /// Test various conjectures concerning Item characteristics

    for (i=0;i<numOfItems;i+=1)
   
        // conjecture 0
        if(Fmin[i]<10 && Fmin[i]>-100)
            itemType[i][0] = 1
        endif  

        // conjecture 1
        if(SdBsd[i] > 4.5 && Fmean[i] <800)
            itemType[i][1] = 1
        endif      
       
        // conjecture 2
        if(HEpnts[i] >=3 && HEslope[i] <-600 && Fmin[i]<100 && Fmin[i]>-100)       
            itemType[i][2] = 1
        endif          
       
        // Conjecture 3
        if(PeakNum[i] >=0 && SdBsd[i]>4)
            itemType[i][3] = 1
        endif  
   
        // conjecture 4  
        if(ItemPnts[i]>500 && SdBsd[i]<4)
            itemType[i][4] = 1     
        endif

        //  conjecture 5  
        if(itemType[i][1] == 1 && itemType[i][2]==1 && ItemPnts[i]>60)
            itemType[i][5] = 1     
        endif

        //  conjecture 6       
        if(itemType[i][1] == 1 && itemType[i][2]==1 && ItemPnts[i]<=10)
            itemType[i][6] = 1
        endif  
       
        // conjecture 7
//      if(HEpnts[i] >=5 && HEslope[i] <-600  && Fmin[i]<100 && Fmin[i]>-100)
//      if(HEpnts[i] >=5 && HEslope[i] <-600 && Fmin[i]<100 && Fmin[i]>-50)
        if(Fend[i]>100)
            itemType[i][7] = 1
        endif    
       
        // conjecture 8
        if(PeakNum[i] >=6)// && SdBsd[i]>4)
            itemType[i][8] = 1
        endif      

        // conjecture 9
        if(Fmin[i]>250 && SdBsd[i]<4)
            itemType[i][9] = 1
        endif          
           
    endfor

 

In reply to by KurtB

Another thought has come to me - perhaps you could use ProcedureText() to extract the code, swap in the changed line for the if statement, save, and then something like Execute "COMPILEPROCEDURES" (possibly with a /P, and after Execute/P "LOADFILE [filename.ipf]" ?

 

OK. Clearer now. Thanks.

Write your conjectures as separate functions. Use #define-#ifdef compiler directives.

#define Code7A

Function test_0(wave Fmin, variable pp)
    variable vrtn
    vrtn = ((Fmin[pp] < 10) && (Fmin[pp] > -100)) ? 1 : 0
    return vrtn
end

Function test_7(wave HEpnts, wave HEslope, wave Fmin, wave Fend, variable pp)
    variable rtn
#ifdef Code7A
    vrtn = ((HEpnts[pp] >= 5) && (HEslope[pp] < -600) && (Fmin[pp] < 100) && (Fmin[pp] > -100)) ? 1 : 0
#endif
#ifdef Code7B
    vrtn = ((HEpnts[pp] >= 5) && (HEslope[pp] < -600) && (Fmin[pp] < 100) && (Fmin[pp] > -50)) ? 1 : 0
#else
    vrtn = (Fend[pp] > 100) ? 1 : 0
#endif
    return vrtn
end

// replace the explicit for loop with implicit for loop

    itemType[][0] = test_0(Fmin, p)
    itemType[][7] = test_7(HEpnts, HEslope, Fmin, Fend, p)

This allows you to keep each conjecture clean in its own regard. It also allows you to change something simpler ... Code7A vs Code7B versus no definition (or Code7C). Finally, moving the explicit for-loop to implicit should speed up the processing.

Thanks JJ. 

I'm sure this will help   Seperate functions and implicit loops I will try and any speed improvement will be worthwhile. However, I am not familiar with the structure of compiler directives and how to use them.  From a quick look at the excellent Igor help I will need to swot up on conditional compilations!

What Kurt was referring to was dynamically changing the content of your procedure / code to modify what the functions are doing. I think it would be impossible or at least instable to modify the procedure file which you are executing at the same time. You can do something like this for modifying a different procedure file or the main procedure window, however. An example for the latter can be found here:

https://www.wavemetrics.com/forum/general/create-automatically-override…

I don't think this is the path you should follow. I think what JJ proposed is practical and safe for your case.

What chozo says is quite sound. Don't try to write self-modifying code. That way lies brittle code and madness. I know this from personal experience.

A possible option that hasn't been mentioned yet is to use an override function for your constantly changing conditional. Write the conditional as something like

if (ConditionalDuJour(A, B))
  // do something
endif

And in that same procedure file, define a version of the function:

Function ConditionalDuJour(Variable A, Variable B)
    return (A>1 && B>2)
end

In the main procedure window, write your currently desired version:

 

Override Function ConditionalDuJour(Variable A, Variable B)
    return (A<1 && B>1.5)
end

Read about override functions: DisplayHelpTopic "Function Overrides"