Recent

Author Topic: class variables out of scope in class?  (Read 1394 times)

SA.Blackmon

  • New Member
  • *
  • Posts: 37
  • Just an old retired guy practicing what he enjoys.
class variables out of scope in class?
« on: November 19, 2021, 07:49:24 pm »
PLEASE: do not read any more into this than what I have asked. This is merely a scoping question.

I have been doing Python recently and this really took me by surprise.

-----------------------------------------
Please explain how/why the FWork_str class variable goes out of scope in the walk_the_parent_tree method. It is out of scope in the "pOutStr := pOutStr + FWork_str;" line and in the finally clause.

--my edit: I did a clean up and rebuild and now FWork_str is in scope in the "pOutStr := pOutStr + FWork_str;" line BUT still out of scope in the finally clause.

I originally had FWork_str as a variable of the method and that didn't work either, with same results.

Code: Pascal  [Select][+][-]
  1.   TNodeWalker = class(TTreeView)
  2.   private
  3.     function walk_the_parent_tree(parent_node : TTreeNode;
  4.                                  var pOutStr : String;
  5.                                          lvl : Integer = 0): Integer;  
  6.   public
  7.     FParentNodeAra : array of TTreeNode;
  8.     FLimitClause : String;
  9.     FWork_str : String;
  10.                            

Code: Pascal  [Select][+][-]
  1. function TNodeWalker.walk_the_parent_tree(parent_node : TTreeNode;
  2.                                          var pOutStr : String;
  3.                                                  lvl : Integer) : Integer;
  4. var
  5.   idx : Integer;
  6.   work_node : TTreeNode;
  7.   child_node_list : TObjectList;
  8. begin
  9.   child_node_list := TObjectList.Create;
  10.   {$IFDEF DEBUG}
  11.   WriteLn(_fl_);
  12.   WriteLn(_fl_, Format(_write_ln, [lvl, EmptyStr, parent_node.Text]));
  13.   {$ENDIF}
  14.  
  15.   Inc(lvl);
  16.   try
  17.     work_node := parent_node.GetFirstChild;
  18.     while Assigned(work_node) do
  19.     begin
  20.       FWork_str := work_node.Text;
  21.       child_node_list.Add(work_node);
  22.       {$IFDEF DEBUG}
  23.       WriteLn(_fl_, Format(_write_ln, [lvl, multiple_chars(SPACE, lvl), work_node.Text]));
  24.       {$ENDIF}
  25.       walk_the_parent_tree(work_node, pOutStr, lvl);
  26.       work_node := parent_node.GetNextChild(work_node)
  27.                 end;
  28.  
  29.     pOutStr := pOutStr + FWork_str;
  30.   finally
  31.     idx := 0;
  32.     FWork_str := EmptyStr;
  33.     while idx < child_node_list.Count do
  34.     begin
  35.       FWork_str := Concat(FWork_str, TTreeNode(child_node_list[idx]).Text);
  36.       Inc(idx);
  37.                 end;
  38.     pOutStr := FWork_str;
  39.                 child_node_list.Free;
  40.     Result := lvl
  41.   end;
  42. end;  

=================
I made a reply below.
Now, I'm convinced it may just be a debugger issue. I checked the var parameter pOutStr (TNodeWalker.walk_the_parent_tree) in the caller and it returns a value.
At this point I am confused.

« Last Edit: November 20, 2021, 12:51:00 am by SA.Blackmon »
Thank you for your help,
Sherril

jamie

  • Hero Member
  • *****
  • Posts: 5143
Re: class variables out of scope in class?
« Reply #1 on: November 19, 2021, 10:55:06 pm »
Do you have a large amount of code in a single unit ?

 Also, this could be an optimizing bug, have you tried different op levels ?
The only true wisdom is knowing you know nothing

MarkMLl

  • Hero Member
  • *****
  • Posts: 3689
Re: class variables out of scope in class?
« Reply #2 on: November 19, 2021, 11:41:18 pm »
Are you saying that it's in-scope between try and finally but out of scope between finally and end? Because that would be... strange.

Does it depend on the declaration order, i.e. because the function is declared before the variable?

Couple of points. This isn't actually a class variable (i.e. shared between every instance), it's a field in each instance. I think you're going to need to append a compilable program to your query so that other people can try it, you really should be posting the exact error message you're getting, and you really should be saying exactly what FPC version and platform you're seeing the problem on.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 9778
  • FPC developer.
Re: class variables out of scope in class?
« Reply #3 on: November 19, 2021, 11:57:47 pm »
Easiest is to minimize it. Keep removing unnecessary stuff (units, code, declarations) from a copy of the project, regularly compiling to check if the problem still exists. If it doesn't happy anymore, restore from versions you regularly backuped before cutting. Rinse, repeat.

Trying Delphi mode might also help, in objFPC mode FPC has some deliberate limitations where parameters and fields are not allowed to clash. If it doesn't happen in Delphi mode,  it is a sign to search in that direction.

SA.Blackmon

  • New Member
  • *
  • Posts: 37
  • Just an old retired guy practicing what he enjoys.
Re: class variables out of scope in class?
« Reply #4 on: November 20, 2021, 12:27:03 am »
Sorry for not providing all the information.
Code: Text  [Select][+][-]
  1. Are you saying that it's in-scope between try and finally but out of scope between finally and end? Because that would be... strange.
That is correct.
Hovering over the FWorkStr in the finally clause, gave this tooltip: (with gdb debugger)
Code: Text  [Select][+][-]
  1. FWork_str = No symbol \"FWORK_STR\" in current context.
  2. public
  3.  
  4. var
  5.  TNodeWalker.FWork_str: String
  6.  
  7. D:\LazApps\WordScape\frmcompword_w_db.pp(37,5)
  8.  
  9.  

with the dwarf debugger:
Code: Text  [Select][+][-]
  1. pOutStr = current stack frame does not contain a variable named `this'
  2.  
  3.  
  4. var
  5.  pOutStr:
  6. String
  7.  
  8. D:\LazApps\WordScape\frmcompword_w_db.pp(289,46)
  9.  
  10.  

this is delphi mode.

As regards the class variable: damn it all, Python.

I think I got everything you need for this issue. There is a mysql database with one relation but you won't
far enough to need that on this issue.

Now, I'm going to try the optimization jamie suggested.
Thank you for your help,
Sherril

jamie

  • Hero Member
  • *****
  • Posts: 5143
Re: class variables out of scope in class?
« Reply #5 on: November 20, 2021, 01:15:20 am »
I don't know if it makes any difference but I couldn't run your test app due to missing files however, I did notice you do not have a
{$H+} after the mode which forces large strings.

so at the top if your sources.

{$mode delphi} {$H+}
                         ^^^^^
The only true wisdom is knowing you know nothing

ASerge

  • Hero Member
  • *****
  • Posts: 1906
Re: class variables out of scope in class?
« Reply #6 on: November 20, 2021, 06:41:29 am »
PLEASE: do not read any more into this than what I have asked. This is merely a scoping question.
It is difficult to do this when the code contains a lot of logical errors, not to mention the style and design. If there is a desire, I can tell you more.
Maybe you wanted to do something similar (without any public fields):
Code: Pascal  [Select][+][-]
  1. procedure WalkTree(ParentNode: TTreeNode; Level: Integer; var OutStr: string);
  2. var
  3.   WorkNode: TTreeNode;
  4.   Indent: string;
  5. begin
  6.   Indent := StringOfChar(#32, Level * 2);
  7.   WorkNode := ParentNode.GetFirstChild;
  8.   while Assigned(WorkNode) do
  9.   begin
  10.     OutStr := OutStr + Indent + WorkNode.Text + LineEnding;
  11.     WalkTree(WorkNode, Level + 1, OutStr);
  12.     WorkNode := ParentNode.GetNextChild(WorkNode);
  13.   end;
  14. end;
  15.  
  16. procedure TForm1.Button1Click(Sender: TObject);
  17. var
  18.   S: string = '';
  19.   SelNode: TTreeNode;
  20. begin
  21.   SelNode := TreeView1.Selected;
  22.   if Assigned(SelNode) then
  23.   begin
  24.     WalkTree(SelNode, 1, S);
  25.     Memo1.Text := SelNode.Text + LineEnding + S;
  26.   end;
  27. end;
  28.  
  29. procedure TForm1.FormCreate(Sender: TObject);
  30. var
  31.   N, P: TTreeNode;
  32. begin
  33.   with TreeView1.Items do
  34.   begin
  35.     N := Add(nil, 'Item1');
  36.       AddChild(N, 'Item1_1');
  37.       AddChild(N, 'Item1_2');
  38.     N := Add(nil, 'Item2');
  39.       AddChild(N, 'Item2_1');
  40.       P := AddChild(N, 'Item2_2');
  41.         AddChild(P, 'Item2_2_1');
  42.         AddChild(P, 'Item2_2_2');
  43.       P := AddChild(N, 'Item2_3');
  44.         AddChild(P, 'Item2_3_1');
  45.   end;
  46.   TreeView1.Selected := N;
  47. end;
  48.  
  49. end.

SA.Blackmon

  • New Member
  • *
  • Posts: 37
  • Just an old retired guy practicing what he enjoys.
Re: class variables out of scope in class?
« Reply #7 on: November 20, 2021, 05:35:48 pm »
ASerge: like I said at the top of the issue, I was only interested in the scoping issue. I knew the logic sucked bilge water; I never have really got my hands around recursion though I have used it quite a bit (making the same mistakes repeatedly.) I really do appreciate your efforts.

I claim old age as the cause. :D (Unfortunately, there is no emoji with grey hair.)

Jamie: Thank you for your help. I did put the {+H} compiler directive at the top of the project file. At the point in the file that I was working when I bumbled onto this issue, I had no long strings but later I have to bundle the "discovered" words in order to send them to a stored procedure to check validity.

I didn't send the word file (which is the data in the database table) because of its size. It is easy enough to get; it is the word list that ships with Linux.
The table has just one column, I called it "word" and it is varchar(45).

I think that is all missing; I believe I have all the source in one directory; if not, please tell me.


Thank you for your help,
Sherril

 

TinyPortal © 2005-2018