comparison src/symtab.cc @ 7972:5bf4e2c13ed8

make superiorto and inferiorto work
author John W. Eaton <jwe@octave.org>
date Fri, 25 Jul 2008 14:25:35 -0400
parents 0d607e8dbbfa
children a2ab20ba78f7
comparison
equal deleted inserted replaced
7971:dd5cc5016487 7972:5bf4e2c13ed8
50 std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances; 50 std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances;
51 51
52 std::map<std::string, octave_value> symbol_table::global_table; 52 std::map<std::string, octave_value> symbol_table::global_table;
53 53
54 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table; 54 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table;
55
56 std::map<std::string, std::set<std::string> > symbol_table::class_precedence_table;
55 57
56 const symbol_table::scope_id symbol_table::xglobal_scope = 0; 58 const symbol_table::scope_id symbol_table::xglobal_scope = 0;
57 const symbol_table::scope_id symbol_table::xtop_scope = 1; 59 const symbol_table::scope_id symbol_table::xtop_scope = 1;
58 60
59 symbol_table::scope_id symbol_table::xcurrent_scope = 1; 61 symbol_table::scope_id symbol_table::xcurrent_scope = 1;
355 p != dispatch_map.end (); p++) 357 p != dispatch_map.end (); p++)
356 retval += " " + p->second + " (" + p->first + ", ...)\n\n"; 358 retval += " " + p->second + " (" + p->first + ", ...)\n\n";
357 } 359 }
358 360
359 return retval; 361 return retval;
362 }
363
364 static std::string
365 get_dispatch_type (const octave_value_list& evaluated_args)
366 {
367 std::string dispatch_type;
368
369 int n = evaluated_args.length ();
370
371 if (n > 0)
372 {
373 // Find first object, if any.
374
375 int i;
376
377 for (i = 0; i < n; i++)
378 {
379 octave_value arg = evaluated_args(i);
380
381 if (arg.is_object ())
382 {
383 dispatch_type = arg.class_name ();
384 break;
385 }
386 }
387
388 for (int j = i+1; j < n; j++)
389 {
390 octave_value arg = evaluated_args(j);
391
392 if (arg.is_object ())
393 {
394 std::string cname = arg.class_name ();
395
396 // Only switch to type of ARG if it is marked superior
397 // to the current DISPATCH_TYPE.
398 if (! symbol_table::is_superiorto (dispatch_type, cname)
399 && symbol_table::is_superiorto (cname, dispatch_type))
400 dispatch_type = cname;
401 }
402 }
403
404 if (dispatch_type.empty ())
405 {
406 // No object found, so use class of first argument.
407
408 dispatch_type = evaluated_args(0).class_name ();
409 }
410 }
411
412 return dispatch_type;
360 } 413 }
361 414
362 // Find the definition of NAME according to the following precedence 415 // Find the definition of NAME according to the following precedence
363 // list: 416 // list:
364 // 417 //
517 if (n > 0 && ! args_evaluated) 570 if (n > 0 && ! args_evaluated)
518 evaluated_args.stash_name_tags (arg_names); 571 evaluated_args.stash_name_tags (arg_names);
519 572
520 args_evaluated = true; 573 args_evaluated = true;
521 574
522 // FIXME -- need to handle precedence. 575 if (n > 0)
523
524 std::string dispatch_type = evaluated_args(0).class_name ();
525
526 for (int i = 1; i < n; i++)
527 { 576 {
528 octave_value arg = evaluated_args(i); 577 std::string dispatch_type = get_dispatch_type (evaluated_args);
529 578
530 if (arg.is_object ()) 579 octave_value fcn = find_method (dispatch_type);
531 { 580
532 dispatch_type = arg.class_name (); 581 if (fcn.is_defined ())
533 break; 582 return fcn;
534 }
535 } 583 }
536
537 octave_value fcn = find_method (dispatch_type);
538
539 if (fcn.is_defined ())
540 return fcn;
541 } 584 }
542 else 585 else
543 return octave_value (); 586 return octave_value ();
544 } 587 }
545 588
702 function_on_path = octave_value (fcn); 745 function_on_path = octave_value (fcn);
703 } 746 }
704 } 747 }
705 748
706 return function_on_path; 749 return function_on_path;
750 }
751
752 // Insert INF_CLASS in the set of class names that are considered
753 // inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently
754 // marked as superior to SUP_CLASS.
755
756 bool
757 symbol_table::set_class_relationship (const std::string& sup_class,
758 const std::string& inf_class)
759 {
760 class_precedence_table_const_iterator p
761 = class_precedence_table.find (inf_class);
762
763 if (p != class_precedence_table.end ())
764 {
765 const std::set<std::string>& inferior_classes = p->second;
766
767 std::set<std::string>::const_iterator q
768 = inferior_classes.find (sup_class);
769
770 if (q != inferior_classes.end ())
771 return false;
772 }
773
774 class_precedence_table[sup_class].insert (inf_class);
775
776 return true;
777 }
778
779 // Has class A been marked as superior to class B? Also returns
780 // TRUE if B has been marked as inferior to A, since we only keep
781 // one table, and convert inferiort information to a superiorto
782 // relationship. Two calls are required to determine whether there
783 // is no relationship between two classes:
784 //
785 // if (symbol_table::is_superiorto (a, b))
786 // // A is superior to B, or B has been marked inferior to A.
787 // else if (symbol_table::is_superiorto (b, a))
788 // // B is superior to A, or A has been marked inferior to B.
789 // else
790 // // No relation.
791
792 bool
793 symbol_table::is_superiorto (const std::string& a, const std::string& b)
794 {
795 bool retval = false;
796
797 class_precedence_table_const_iterator p = class_precedence_table.find (a);
798
799 if (p != class_precedence_table.end ())
800 {
801 const std::set<std::string>& inferior_classes = p->second;
802 std::set<std::string>::const_iterator q = inferior_classes.find (b);
803
804 if (q != inferior_classes.end ())
805 retval = true;
806 }
807
808 return retval;
707 } 809 }
708 810
709 static std::string 811 static std::string
710 fcn_file_name (const octave_value& fcn) 812 fcn_file_name (const octave_value& fcn)
711 { 813 {