[Bf-blender-cvs] [eed93aaa07a] temp-multi-function-procedure: make dot output more compact

Jacques Lucke noreply at git.blender.org
Sun Aug 22 22:36:29 CEST 2021


Commit: eed93aaa07a95ba2fd5c8fdf947e4b430eed4c02
Author: Jacques Lucke
Date:   Sun Aug 22 22:34:25 2021 +0200
Branches: temp-multi-function-procedure
https://developer.blender.org/rBeed93aaa07a95ba2fd5c8fdf947e4b430eed4c02

make dot output more compact

===================================================================

M	source/blender/functions/FN_multi_function_procedure.hh
M	source/blender/functions/intern/multi_function_procedure.cc

===================================================================

diff --git a/source/blender/functions/FN_multi_function_procedure.hh b/source/blender/functions/FN_multi_function_procedure.hh
index aacc3f9331f..07aa84e0f94 100644
--- a/source/blender/functions/FN_multi_function_procedure.hh
+++ b/source/blender/functions/FN_multi_function_procedure.hh
@@ -78,6 +78,7 @@ class MFInstruction : NonCopyable, NonMovable {
  public:
   MFInstructionType type() const;
   Span<MFInstruction *> prev();
+  Span<const MFInstruction *> prev() const;
 };
 
 class MFCallInstruction : public MFInstruction {
@@ -268,6 +269,11 @@ inline Span<MFInstruction *> MFInstruction::prev()
   return prev_;
 }
 
+inline Span<const MFInstruction *> MFInstruction::prev() const
+{
+  return prev_;
+}
+
 /* --------------------------------------------------------------------
  * MFCallInstruction inline methods.
  */
diff --git a/source/blender/functions/intern/multi_function_procedure.cc b/source/blender/functions/intern/multi_function_procedure.cc
index 28c42b5a4e2..4eb7403ea09 100644
--- a/source/blender/functions/intern/multi_function_procedure.cc
+++ b/source/blender/functions/intern/multi_function_procedure.cc
@@ -222,16 +222,6 @@ MFProcedure::~MFProcedure()
   }
 }
 
-static std::string optional_variable_to_string(const MFVariable *variable)
-{
-  if (variable == nullptr) {
-    return "<null>";
-  }
-  std::stringstream ss;
-  ss << variable->name() << "$" << variable->id();
-  return ss.str();
-}
-
 bool MFProcedure::validate() const
 {
   if (entry_ == nullptr) {
@@ -498,108 +488,254 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
   return state;
 }
 
+static bool has_to_be_block_begin(const MFProcedure &procedure, const MFInstruction &instruction)
+{
+  if (procedure.entry() == &instruction) {
+    return true;
+  }
+  if (instruction.prev().size() != 1) {
+    return true;
+  }
+  if (instruction.prev()[0]->type() == MFInstructionType::Branch) {
+    return true;
+  }
+  return false;
+}
+
+static const MFInstruction &get_first_instruction_in_block(const MFProcedure &procedure,
+                                                           const MFInstruction &representative)
+{
+  const MFInstruction *current = &representative;
+  while (!has_to_be_block_begin(procedure, *current)) {
+    current = current->prev()[0];
+    if (current == &representative) {
+      /* There is a loop without entry or exit, just break it up here. */
+      break;
+    }
+  }
+  return *current;
+}
+
+static const MFInstruction *get_next_instruction_in_block(const MFProcedure &procedure,
+                                                          const MFInstruction &instruction,
+                                                          const MFInstruction &block_begin)
+{
+  const MFInstruction *next = nullptr;
+  switch (instruction.type()) {
+    case MFInstructionType::Call: {
+      next = static_cast<const MFCallInstruction &>(instruction).next();
+      break;
+    }
+    case MFInstructionType::Destruct: {
+      next = static_cast<const MFDestructInstruction &>(instruction).next();
+      break;
+    }
+    case MFInstructionType::Dummy: {
+      next = static_cast<const MFDummyInstruction &>(instruction).next();
+      break;
+    }
+    case MFInstructionType::Return:
+    case MFInstructionType::Branch: {
+      break;
+    }
+  }
+  if (next == nullptr) {
+    return nullptr;
+  }
+  if (next == &block_begin) {
+    return nullptr;
+  }
+  if (has_to_be_block_begin(procedure, *next)) {
+    return nullptr;
+  }
+  return next;
+}
+
+static Vector<const MFInstruction *> get_instructions_in_block(const MFProcedure &procedure,
+                                                               const MFInstruction &representative)
+{
+  Vector<const MFInstruction *> instructions;
+  const MFInstruction &begin = get_first_instruction_in_block(procedure, representative);
+  for (const MFInstruction *current = &begin; current != nullptr;
+       current = get_next_instruction_in_block(procedure, *current, begin)) {
+    instructions.append(current);
+  }
+  return instructions;
+}
+
+static void variable_to_string(const MFVariable *variable, std::stringstream &ss)
+{
+  if (variable == nullptr) {
+    ss << "<none>";
+  }
+  else {
+    ss << "$" << variable->id();
+    if (!variable->name().is_empty()) {
+      ss << "(" << variable->name() << ")";
+    }
+  }
+}
+
+static void instruction_to_string(const MFCallInstruction &instruction, std::stringstream &ss)
+{
+  const MultiFunction &fn = instruction.fn();
+  ss << fn.name() << " - ";
+  for (const int param_index : fn.param_indices()) {
+    const MFParamType param_type = fn.param_type(param_index);
+    const MFVariable *variable = instruction.params()[param_index];
+    switch (param_type.interface_type()) {
+      case MFParamType::Input: {
+        ss << "in";
+        break;
+      }
+      case MFParamType::Mutable: {
+        ss << "mut";
+        break;
+      }
+      case MFParamType::Output: {
+        ss << "out";
+        break;
+      }
+    }
+    ss << " ";
+    variable_to_string(variable, ss);
+    if (param_index < fn.param_amount() - 1) {
+      ss << ", ";
+    }
+  }
+}
+
+static void instruction_to_string(const MFDestructInstruction &instruction, std::stringstream &ss)
+{
+  ss << "Destruct ";
+  variable_to_string(instruction.variable(), ss);
+}
+
+static void instruction_to_string(const MFDummyInstruction &UNUSED(instruction),
+                                  std::stringstream &ss)
+{
+  ss << "Dummy";
+}
+
+static void instruction_to_string(const MFReturnInstruction &UNUSED(instruction),
+                                  std::stringstream &ss)
+{
+  ss << "Return";
+}
+
+static void instruction_to_string(const MFBranchInstruction &instruction, std::stringstream &ss)
+{
+  ss << "Branch on ";
+  variable_to_string(instruction.condition(), ss);
+}
+
 std::string MFProcedure::to_dot() const
 {
+  Vector<const MFInstruction *> all_instructions;
+  all_instructions.extend(call_instructions_.begin(), call_instructions_.end());
+  all_instructions.extend(branch_instructions_.begin(), branch_instructions_.end());
+  all_instructions.extend(destruct_instructions_.begin(), destruct_instructions_.end());
+  all_instructions.extend(dummy_instructions_.begin(), dummy_instructions_.end());
+  all_instructions.extend(return_instructions_.begin(), return_instructions_.end());
+
+  Set<const MFInstruction *> handled_instructions;
+
   dot::DirectedGraph digraph;
-  Map<MFInstruction *, dot::Node *> dot_nodes;
+  Map<const MFInstruction *, dot::Node *> dot_nodes_by_begin;
+  Map<const MFInstruction *, dot::Node *> dot_nodes_by_end;
 
-  for (MFCallInstruction *instruction : call_instructions_) {
+  for (const MFInstruction *representative : all_instructions) {
+    if (handled_instructions.contains(representative)) {
+      continue;
+    }
+    Vector<const MFInstruction *> block_instructions = get_instructions_in_block(*this,
+                                                                                 *representative);
     std::stringstream ss;
-    const MultiFunction &fn = instruction->fn();
-    ss << fn.name();
-    ss << "(";
-    for (const int param_index : fn.param_indices()) {
-      MFParamType param_type = fn.param_type(param_index);
-      switch (param_type.interface_type()) {
-        case MFParamType::Input: {
-          ss << "in: ";
+
+    for (const MFInstruction *current : block_instructions) {
+      handled_instructions.add_new(current);
+      switch (current->type()) {
+        case MFInstructionType::Call: {
+          instruction_to_string(*static_cast<const MFCallInstruction *>(current), ss);
           break;
         }
-        case MFParamType::Output: {
-          ss << "out: ";
+        case MFInstructionType::Destruct: {
+          instruction_to_string(*static_cast<const MFDestructInstruction *>(current), ss);
           break;
         }
-        case MFParamType::Mutable: {
-          ss << "mut: ";
+        case MFInstructionType::Dummy: {
+          instruction_to_string(*static_cast<const MFDummyInstruction *>(current), ss);
+          break;
+        }
+        case MFInstructionType::Return: {
+          instruction_to_string(*static_cast<const MFReturnInstruction *>(current), ss);
+          break;
+        }
+        case MFInstructionType::Branch: {
+          instruction_to_string(*static_cast<const MFBranchInstruction *>(current), ss);
           break;
         }
       }
-      MFVariable *variable = instruction->params()[param_index];
-      ss << optional_variable_to_string(variable);
-      if (param_index < fn.param_amount() - 1) {
-        ss << ", ";
-      }
+      ss << "\\l";
     }
-    ss << ")";
-    dot::Node &dot_node = digraph.new_node(ss.str());
-    dot_node.set_shape(dot::Attr_shape::Rectangle);
-    dot_nodes.add_new(instruction, &dot_node);
-  }
-  for (MFBranchInstruction *instruction : branch_instructions_) {
-    MFVariable *variable = instruction->condition();
-    std::stringstream ss;
-    ss << "Branch: " << optional_variable_to_string(variable);
-    dot::Node &dot_node = digraph.new_node(ss.str());
-    dot_node.set_shape(dot::Attr_shape::Rectangle);
-    dot_nodes.add_new(instruction, &dot_node);
-  }
-  for (MFDestructInstruction *instruction : destruct_instructions_) {
-    MFVariable *variable = instruction->variable();
-    std::stringstream ss;
-    ss << "Destruct: " << optional_variable_to_string(variable);
+
     dot::Node &dot_node = digraph.new_node(ss.str());
     dot_node.set_shape(dot::Attr_shape::Rectangle);
-    dot_nodes.add_new(instruction, &dot_node);
-  }
-  for (MFDummyInstruction *instruction : dummy_instructions_) {
-    dot::Node &dot_node = digraph.new_node("Dummy");
-    dot_node.set_shape(dot::Attr_shape::Rectangle);
-    dot_nodes.add_new(instruction, &dot_node);
-  }
-  for (MFReturnInstruction *instruction : return_instructions_) {
-    dot::Node &dot_node = digraph.new_node("");
-    dot_node.set_shape(dot::Attr_shape::Circle);
-    dot_nodes.add_new(instruction, &dot_node);
+    dot_nodes_by_begin.add_new(block_instructions.first(), &dot_node);
+    dot_nodes_by_end.add_new(block_instructions.last(), &dot_node);
   }
 
-  auto create_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list