Few issues with uses clause

How (in TAtPascalScripter) is can reset module imported using uses clause;
In my scripter application I have my main module in editor where i run it like

      scripter.Clear;
      scripter.SourceCode.Assign( AdvMemo1.Lines ); 
      scripter.Compile;
      execute;

my main module uses few others modules.
If I modify modules used by uses clause - modifications don't affect until I restart my scripter application. Is there a way reset all modules?

Other question.
I declared a mehtod to my scripter application, which takes one parameter - method name and it should execute that method by calling ExecuteSubroutine.
It works fine when method is in main unit.But scripter doesn't find it if it's in unit used by uses clause.
Tried to use unitname.method.
I'm building tests for scripts so I'd like to split tests to smaller units by category and those method would be called by main unit.

Hi Mika, I believe I didn't understand your first question. By module you mean script-based libraries? Could you please give me a more direct example of what's not working?

Regarding your second question, ExecuteSubroutine (and Execute) always refer just to the current script. If you want to execute a procedure in another script, you must call it referencing that script directly, changing the CurrentScript property of the scripter component.

Yes, I meant exactly that. I have maintest.psc, which then uses TestCommons.psc,DocVariantTest.psc, and TmsCryptoTest.psc.
I open maintest, run it using scripter, try to fix compiletime errors in testCommons, but changes won't affect.
I changed scripter.clear to code

for i:= scripter.Scripts.Count-1 downto 1 do // scripts[0] = mainscript
      scripter.Scripts.Delete(i)

and managed to get it working .

Second question
should this do the trick. lUnit is the unit name of nit where subroutine is.

  lOldscript := scripter.CurrentScript ;
  try
        if lUnit <>'' then
        begin
          lNewScript := scripter.Scripts.FindByUnitName(lUnit); 
         scripter.CurrentScript := lNewScript;
        end;
        executeSubroutine(aRoutine);
 finally
      scripter.CurrentScript := lOldscript;
 end;

I still get Subroutine does not exists exception. FindBYUnitName does return valid script, checked with debugger.

Good. Yes, your second code should work fine. Are you sure the routine is declared in that unit?

Pretty sure..
I added following loop (lRoutine is same as aRoutine in code above, just renamet it )

for i := 0 to LNewScript.ScriptInfo.Routines.Count -1 do
   codesite.send('lRoutine = %s   LNewScript.ScriptInfo.Routines[%d].Name = %s are equal %s',[ lRoutine,i, LNewScript.ScriptInfo.Routines[i].Name, BoolToStr(sametext( lRoutine,LNewScript.ScriptInfo.Routines[i].Name), true)]);

Output

lRoutine = perusJsonLisaystesti   LNewScript.ScriptInfo.Routines[0].Name = perusJsonLisaystesti are equal True
lRoutine = perusJsonLisaystesti   LNewScript.ScriptInfo.Routines[1].Name = AliLuokkaJsontesti are equal False
lRoutine = perusJsonLisaystesti   LNewScript.ScriptInfo.Routines[2].Name = jsonstringtodatatesti are equal False
lRoutine = perusJsonLisaystesti   LNewScript.ScriptInfo.Routines[3].Name = jsonTestIncomingArray are equal False
lRoutine = perusJsonLisaystesti   LNewScript.ScriptInfo.Routines[4].Name = ___MAIN___ are equal False

Can you please provide a small simple project reproducing the issue?

I'll try to make - meanwhile - don't hold your breath .. this is my background improvement project which has lower priority than customer projects :)

1 Like

@wlandgraf I also have had problems with the script-based libraries. In my case, if I have a project that uses a script-based library. (And it doesn't matter how many unit files are in the project.) If I have a problem with a routine in the script-based library. I will go and load that specific Unit file into the same IDE, and make what changes are necessary. Then I save the updated file and yet keep the unit file loaded. But, if I run the project to see how my changes effected the routine. The IDE continues to work with the version that it had loaded when running project in the first place. It does not matter if the file is still loaded in the IDE or not. The only way to get the passed this. Is to shutdown the IDE, rerun the IDE, and then reload the project, including any and all script-based libraries files that might get used. Which leads me to a couple of more issues/bugs. (I'll mention them in another thread.)

I am not using custom code to load in a script file, as Mika_Koistinen is. I am using the Actions. Which in turn uses standard routines, as originally code by your guys, to load projects and unit files from a file. So, I do not believe that the solution that he was able to come up with. Would work for those of us using the provided routines to load files.

@Mika_Koistinen as for your second problem. The following code is from my ProcessEvents routine in my custom Library.

It may not be pretty, and it may not be efficient, but it works to find the script unit file that a subroutine is in. Make that unit file the active script file. Execute the subroutine. And then return back to the unit file when execution of the subroutine was needed. I do not know why you are needing to execute a subroutine this way. But for my, the once the execution of the subroutine is done. Returning the currently active file to the file we started in. Allows for the script to continue to run from where it was.

I hope that it helps you to come up with your own code.

var
  xPos: Integer;
  eventname: string;
  procname: String;
  bEvent: Boolean;
  sStartScript: String;
  sCurrentScript: String;
  sTempScript: String;
begin
  with AMachine do
  begin
    // Save The script we are starting the ProcessMessages from.
    sStartScript := Scripter.CurrentScript.UnitName;
    // Initially set the CurrentScript to the StartScript.
    sCurrentScript := sStartScript;
    sTempScript := sStartScript;
		
    //
    // Add code here to retreive the Routine's name here
    //
    procname := 

    // is the procedure in the current script unit?
    if Scripter.ScriptInfo.RoutineByName(procname) = nil then
    begin
      // No. So we need to find which script unit has the routine in it.
      // Enumerate through the units in the project's script collection.
      for xPos := 0 to Scripter.Scripts.Count-1 do
      begin
        // Usually the first entry in the Projects scripts collection. Has no name,
        // so we skip those entries that have no name.
        if Scripter.Scripts[xPos].ScriptInfo.UnitName <> '' then
        begin
          // Now we need to check to see if the current script we are checking
          // has the routine we need to run.
          if Scripter.Scripts[xPos].ScriptInfo.RoutineByName(procname) <> nil then
          begin
            // We found the script unit with the routine. Now save the script name
            // and break out of the loop.
            sTempScript := Scripter.Scripts[xPos].ScriptInfo.UnitName;
            Break;
          end;
        end;
      end;
    end;
    // Is the script unit we need the current unit?
    if sTempScript <> sCurrentScript then
    begin
      // No, then we make it the current script unit.
      Scripter.CurrentScript := Scripter.Scripts.FindByUnitName(sTempScript);
      sCurrentScript := sTempScript;
    end;
    // Now we execute the procedure for the current DivideEvent
    Scripter.ExecuteSubroutine(procname);
    // Now we check to see if the current script unit is the one that the
    // current processevents command was executed from. That way the script
    // will continue to run from where it had been prior to the execution of
    // of the subroutine
	if sCurrentScript <> sStartScript then
	  // If not, then we change back to the script unit that called us.
	  Scripter.CurrentScript := Scripter.Scripts.FindByUnitName(sStartScript);
  end;
end;
1 Like