changeset 16072:ac672925fc98

Merge in Julien's changes
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Wed, 20 Feb 2013 11:36:36 -0500
parents 94e95309710c (diff) 0486a29d780f (current diff)
children 1c8234f0b642
files
diffstat 10 files changed, 145 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/interpfcn/symtab.cc	Sun Feb 17 21:17:46 2013 +0100
+++ b/libinterp/interpfcn/symtab.cc	Wed Feb 20 11:36:36 2013 -0500
@@ -1013,20 +1013,12 @@
 symbol_table::set_class_relationship (const std::string& sup_class,
                                       const std::string& inf_class)
 {
-  class_precedence_table_const_iterator p
-    = class_precedence_table.find (inf_class);
-
-  if (p != class_precedence_table.end ())
-    {
-      const std::set<std::string>& inferior_classes = p->second;
+  if (is_superiorto (inf_class, sup_class))
+    return false;
 
-      std::set<std::string>::const_iterator q
-        = inferior_classes.find (sup_class);
-
-      if (q != inferior_classes.end ())
-        return false;
-    }
-
+  // If sup_class doesn't have an entry in the precedence table,
+  // this will automatically create it, and associate to it a
+  // singleton set {inf_class} of inferior classes.
   class_precedence_table[sup_class].insert (inf_class);
 
   return true;
@@ -1034,7 +1026,7 @@
 
 // Has class A been marked as superior to class B?  Also returns
 // TRUE if B has been marked as inferior to A, since we only keep
-// one table, and convert inferiort information to a superiorto
+// one table, and convert inferiorto information to a superiorto
 // relationship.  Two calls are required to determine whether there
 // is no relationship between two classes:
 //
@@ -1048,20 +1040,14 @@
 bool
 symbol_table::is_superiorto (const std::string& a, const std::string& b)
 {
-  bool retval = false;
-
   class_precedence_table_const_iterator p = class_precedence_table.find (a);
+  // If a has no entry in the precedence table, return false
+  if (p == class_precedence_table.end ())
+    return false;
 
-  if (p != class_precedence_table.end ())
-    {
-      const std::set<std::string>& inferior_classes = p->second;
-      std::set<std::string>::const_iterator q = inferior_classes.find (b);
-
-      if (q != inferior_classes.end ())
-        retval = true;
-    }
-
-  return retval;
+  const std::set<std::string>& inferior_classes = p->second;
+  std::set<std::string>::const_iterator q = inferior_classes.find (b);
+  return (q != inferior_classes.end ());
 }
 
 static std::string
@@ -1480,7 +1466,7 @@
             {
               if (ours.is_global () || ours.is_persistent ())
                 ::error ("global and persistent may only be used in the topmost level in which a nested variable is used");
-                
+
               if (! ours.is_formal ())
                 {
                   ours.invalidate ();
--- a/libinterp/octave-value/ov-class.cc	Sun Feb 17 21:17:46 2013 +0100
+++ b/libinterp/octave-value/ov-class.cc	Wed Feb 20 11:36:36 2013 -0500
@@ -2191,42 +2191,34 @@
   octave_value retval;
 
   octave_function *fcn = octave_call_stack::caller ();
-
-  if (fcn && fcn->is_class_constructor ())
+  if ((! fcn) || (! fcn->is_class_constructor ()))
     {
-      for (int i = 0; i < args.length (); i++)
-        {
-          std::string class_name = args(i).string_value ();
-
-          if (! error_state)
-            {
-              if (! is_built_in_class (class_name))
-                {
-                  std::string this_class_name = fcn->name ();
+      error ("superiorto: invalid call from outside class constructor");
+      return retval;
+    }
 
-                  if (! symbol_table::set_class_relationship (this_class_name,
-                                                              class_name))
-                    {
-                      error ("superiorto: precedence already set for %s and %s",
-                             this_class_name.c_str (), class_name.c_str ());
-                      break;
-                    }
-                }
-              else
-                {
-                  // User defined classes always have higher precedence
-                  // than built-in classes.
-                }
-            }
-          else
-            {
+  for (int i = 0; i < args.length (); i++)
+    {
+      std::string inf_class = args(i).string_value ();
+      if (error_state)
+        {
               error ("superiorto: expecting argument to be class name");
               break;
-            }
+        }
+
+      // User defined classes always have higher precedence
+      // than built-in classes
+      if (is_built_in_class (inf_class))
+        break;
+
+      std::string sup_class = fcn->name ();
+      if (! symbol_table::set_class_relationship (sup_class, inf_class))
+        {
+          error ("superiorto: opposite precedence already set for %s and %s",
+                 sup_class.c_str (), inf_class.c_str ());
+          break;
         }
     }
-  else
-    error ("superiorto: invalid call from outside class constructor");
 
   return retval;
 }
@@ -2243,45 +2235,36 @@
   octave_value retval;
 
   octave_function *fcn = octave_call_stack::caller ();
-
-  if (fcn && fcn->is_class_constructor ())
+  if ((! fcn) || (! fcn->is_class_constructor ()))
     {
-      for (int i = 0; i < args.length (); i++)
-        {
-          std::string class_name = args(i).string_value ();
-
-          if (! error_state)
-            {
-              if (! is_built_in_class (class_name))
-                {
-                  std::string this_class_name = fcn->name ();
-
-                  symbol_table::set_class_relationship (class_name,
-                                                        this_class_name);
+      error ("inferiorto: invalid call from outside class constructor");
+      return retval;
+    }
 
-                  if (! symbol_table::set_class_relationship (this_class_name,
-                                                              class_name))
-                    {
-                      error ("inferiorto: precedence already set for %s and %s",
-                             this_class_name.c_str (), class_name.c_str ());
-                      break;
-                    }
-                }
-              else
-                {
-                  error ("inferiorto: cannot give user-defined class lower precedence than built-in class");
-                  break;
-                }
-            }
-          else
-            {
-              error ("inferiorto: expecting argument to be class name");
-              break;
-            }
+  for (int i = 0; i < args.length (); i++)
+    {
+      std::string sup_class = args(i).string_value ();
+      if (error_state)
+        {
+          error ("inferiorto: expecting argument to be class name");
+          break;
+        }
+
+      if (is_built_in_class (sup_class))
+        {
+          error ("inferiorto: cannot give user-defined class lower "
+                 "precedence than built-in class");
+          break;
+        }
+
+      std::string inf_class = fcn->name ();
+      if (! symbol_table::set_class_relationship (sup_class, inf_class))
+        {
+          error ("inferiorto: opposite precedence already set for %s and %s",
+                 inf_class.c_str (), sup_class.c_str ());
+          break;
         }
     }
-  else
-    error ("inferiorto: invalid call from outside class constructor");
 
   return retval;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester1/CPrecedenceTester1.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,8 @@
+function x = CPrecedenceTester1()
+
+  x = struct('useless_data', pi);
+  x = class(x, 'CPrecedenceTester1');
+
+  % don't change anything as far as precedence is concerned
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester1/tattack.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'CPrecedenceTester1';
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester2/CPrecedenceTester2.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,15 @@
+function x = CPrecedenceTester2(flag)
+
+  x = struct('useless_data', pi^2);
+  x = class(x, 'CPrecedenceTester2');
+
+  switch flag,
+    case 1, % CPrecedencetester2 > Snork
+      superiorto('Snork');
+    case 2, % CPrecedencetester2 < Snork
+      inferiorto('Snork');
+    otherwise,
+      error('Incorrect value for argument flag: %d', flag);
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester2/tattack.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'CPrecedenceTester2';
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester3/CPrecedenceTester3.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,15 @@
+function x = CPrecedenceTester3(flag)
+
+  x = struct('useless_data', pi^3);
+  x = class(x, 'CPrecedenceTester3');
+
+  switch flag,
+    case 1, % CPrecedencetester3 > Snork
+      superiorto('Snork');
+    case 2, % CPrecedencetester3 < Snork
+      inferiorto('Snork');
+    otherwise,
+      error('Incorrect value for argument flag: %d', flag);
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester3/tattack.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'CPrecedenceTester3';
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@Snork/tattack.m	Wed Feb 20 11:36:36 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'Snork';
+  
+end
--- a/test/classes/classes.tst	Sun Feb 17 21:17:46 2013 +0100
+++ b/test/classes/classes.tst	Wed Feb 20 11:36:36 2013 -0500
@@ -316,3 +316,29 @@
 %!xtest  s = [s1 x2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));
 %!xtest  s = [x1 s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));
 
+%%%%%%%%%%%%%%%%%%%%%%%%
+%% Testing precedence %%
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% default: leftmost object wins
+%!shared A, B
+%!test A = Snork(rand(2));
+%!test B = CPrecedenceTester1();  % no call to inferiorto/superiorto
+%!assert (isequal (tattack (A, B), 'Snork'))
+%!assert (isequal (tattack (B, A), 'CPrecedenceTester1'))  % idem
+
+%!shared A, B
+%!test A = Snork(rand(2));
+%!test B = CPrecedenceTester2(1);  % CPrecedenceTester2 > Snork
+%!assert (isequal (tattack (A, B), 'CPrecedenceTester2'))
+%!assert (isequal (tattack (B, A), 'CPrecedenceTester2'))
+%% Trying to change to CPrecendenceTester < Snork
+%!error D = CPrecedenceTester2(2);
+
+%!shared A, B
+%!test A = Snork(rand(2));
+%!test B = CPrecedenceTester3(2);  % CPrecedenceTester3 < Snork
+%!assert (isequal (tattack (A, B), 'Snork'))
+%!assert (isequal (tattack (B, A), 'Snork'))
+%% Trying to change to CPrecendenceTester3 > Snork
+%!error D = CPrecedenceTester3(1);