How to update the class object in system verilog after constructing?

This is a follow up question for my question on NOA error in system verilog (Null Object Access error in system verilog). I am trying to build binary tree and do in order traverse for the inserted elements. First I created a class for node

class node;
  byte data;
  node left;
  node right;
  function new();
    this.data = data;
    this.left = null;
    this.right = null;
  endfunction
endclass

I then created an extended class with the following variables

class bin_search extends node;
  node newNode;
  node nd,root,current,parent;
  byte in_data;

  function new();
    super.new();
    this.in_data = in_data;
  endfunction

Below is the complete function to insert a number. To simply explain the functioning, if the current number is less than root the we add it to left node and if it is greater than root, we add it to right node.

 function insert(in_data);
    newNode.data = nd.data;
    if(root.data == null) begin
      root = newNode;
      return;
    end
    else begin
      current = root;
      parent = null;
    end
    forever begin
      parent = current;
      if(in_data < current.data) begin
        current = current.left;
        if(current.left == null) begin
          parent.left = newNode;
        return;
        end
      end
      else begin
        current = current.right;
        if(current.right == null) begin
          parent.right = newNode;
          return;
        end
      end
    end
  endfunction

The function for in ordedr transversing is given below.

  function automatic inorder_traverse(node node_tr);
    if(root.data == null) begin
      $display("Empty tree");
      return;
    end
    else begin
      if(node_tr.left!=null) begin
        inorder_traverse(node_tr.left);
      end
        $display("traverse data = %0d\t", node_tr.data);
      if(node_tr.right != null) begin
        inorder_traverse(node_tr.right);
      end
    end
  endfunction

After this the bin_search class is ended and insided the module each object is constructed and data is inserted using insert function.

module binary;
  bin_search bs;
  initial begin
    bs = new;
    bs.newNode = new();
    bs.nd = new();
    bs.root = new();
    bs.current = new();
    bs.parent = new();
    bs.insert(50);  
    bs.insert(30);  
    bs.insert(70);  
    bs.insert(60);  
    bs.insert(10);  
    bs.insert(90);  
            
    $display("Binary search tree after insertion:"); 
    bs.inorder_traverse(bs.root);
  end
endmodule

The output I am getting is as follows: Binary search tree after insertion: Empty tree But, I expect to see 10 30 50 60 70 90 as the output. I think this means the root value is not getting updated after bs.insert statement is used. Can anyone help me with what is going wrong here?


Solution 1:

Elaborating my comment. Here is your code:

 initial begin
    bs = new;
    bs.newNode = new();
    ...
    bs.insert(50);  
    bs.insert(30);  
    ...

and

function insert(in_data);
    newNode.data = nd.data;
    if(root.data == null) begin
      root = newNode;
      return;
    end
    ...
          parent.left = newNode;
    ...

So, you allocate a single newNode in the initial block. Then you issue several insert functions. Every insert function reuses the same node over and over again, just updatint its data member. As a result, the tree will be completely corrupted because you mangle not only data but also left/right pointers.

Also, constructor in your class variable makes no sense:

class node;
  byte data;
  node left;
  node right;
  function new();
    this.data = data; <<< what does it mean? it assigns node.data to node.data
    this.left = null;
    this.right = null;
  endfunction
endclass

What you should have done instead, was to allocate newNode every time you need it in the insert function. Something like the following.

class node;
  byte data;
  node left;
  node right;
  function new(byte in_data); << pass arg to the constructor
    this.data = in_data;
    this.left = null;
    this.right = null;
  endfunction
endclass
...
function insert(in_data);
    // newNode.data = nd.data;
    if(root.data == null) begin
      root = new(in_data);
      return;
    end
   
 ...

and yes, get rid of the newNode in the bs struct.