home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / BuiltinCN.C < prev    next >
C/C++ Source or Header  |  1998-11-23  |  5KB  |  224 lines

  1. // $Id: BuiltinCN.C,v 1.8 1998/11/23 17:43:17 zeller Exp $
  2. // Builtin call VSL nodes
  3.  
  4. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char BuiltinCallNode_rcsid[] = 
  30.     "$Id: BuiltinCN.C,v 1.8 1998/11/23 17:43:17 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36.  
  37. #include "assert.h"
  38. #include "VSLLib.h"
  39.  
  40. #include "VSLBuiltin.h"
  41.  
  42. #include "VSLNode.h"
  43. #include "TrueBox.h"
  44. #include "BuiltinCN.h"
  45. #include "ListNode.h"
  46. #include "VSLDef.h"
  47. #include "TrueNode.h"
  48.  
  49. DEFINE_TYPE_INFO_1(BuiltinCallNode, CallNode)
  50.  
  51. // BuiltinCallNode
  52.  
  53. // Evaluate builtin function
  54. const Box *BuiltinCallNode::call(Box *a) const
  55. {
  56.     assert (a->isListBox());
  57.  
  58.     // If side effects are prohibited, return error.
  59.     if (sideEffectsProhibited && VSLBuiltin::hasSideEffects(_index))
  60.     {
  61.     sideEffectsOccured = true;
  62.     return 0;
  63.     }
  64.  
  65.     // Call function via function pointer
  66.     BuiltinFunc func = VSLBuiltin::func(_index);
  67.     return func((ListBox *)a);
  68. }
  69.  
  70.  
  71. // Optimization
  72.  
  73. // foldOps: Build `large' argument lists
  74. // In general: replace f(a, f(...), b) by f(a, ..., b)
  75.  
  76. // This Implementation only considers the case
  77. // f(f(a...), b...) => f(a..., b...)
  78.  
  79. int BuiltinCallNode::foldOps(VSLDef *cdef, VSLNode** node)
  80. {
  81.     assert (this == *node);
  82.     int changes = 0;
  83.  
  84.     // Apply on all arguments
  85.     changes += CallNode::foldOps(cdef, node);
  86.  
  87.     // If non-associative, return
  88.     if (!VSLBuiltin::isAssoc(_index))
  89.     return changes;
  90.  
  91.     // If arg is not a list, return
  92.     if (!arg()->isListNode())
  93.     return changes;
  94.  
  95.     ListNode *args = (ListNode *)arg(); // dirty trick
  96.  
  97.     // First arg must be a builtin call
  98.     if (!args->head()->isBuiltinCallNode())
  99.     return changes;
  100.  
  101.     BuiltinCallNode *callee = (BuiltinCallNode *)args->head(); // dirty trick
  102.  
  103.     // First arg must call the same function
  104.     if (_index != callee->_index)
  105.     return changes;
  106.  
  107.     // Arg must be a list
  108.     if (!callee->arg()->isListNode())
  109.     return changes;
  110.  
  111.     ListNode *callArgs = (ListNode *)callee->arg(); // dirty trick
  112.  
  113.     // Insert list
  114.     if (VSEFlags::show_optimize)
  115.     {
  116.     cout << "\n" << cdef->longname() << ": foldOps: replacing\n" 
  117.         << *this << '\n';
  118.     cout.flush();
  119.     }
  120.  
  121.     int err = callArgs->append(args->tail());
  122.     if (err)
  123.     {
  124.     if (VSEFlags::show_optimize)
  125.     {
  126.         cout << "ABORTING (no replace) since append impossible\n";
  127.         cout.flush();
  128.     }
  129.     return changes;
  130.     }
  131.  
  132.     VSLNode *newArgs = callee->arg();
  133.     callee->arg() = 0; args->tail() = 0; delete args;
  134.     arg() = newArgs;
  135.  
  136.     if (VSEFlags::show_optimize)
  137.     {
  138.     cout << "by " << *this << '\n';
  139.     cout.flush();
  140.     }
  141.  
  142.     changes++;
  143.  
  144.     return changes;
  145. }
  146.  
  147.  
  148. // foldConsts: Evaluate functions with constant args right now
  149. // Example: replace f(2 + 2) by f(4)
  150.  
  151. int BuiltinCallNode::foldConsts(VSLDef *cdef, VSLNode** node)
  152. {
  153.     // Apply standard optimization
  154.     int changes = CallNode::foldConsts(cdef, node);
  155.  
  156.     // If optimization was a success, return
  157.     if (*node != this || isConst())
  158.     return changes;
  159.  
  160.     // If non-associative, return
  161.     if (!VSLBuiltin::isAssoc(_index))
  162.     return changes;
  163.  
  164.     // Otherwise: isolate constant args in constant subexpressions and
  165.     // optimize them separately
  166.     for (VSLNode *a = arg();
  167.      a->isListNode() && ((ListNode *)a)->tail()->isListNode();
  168.      a = ((ListNode *)a)->tail())
  169.     {
  170.     ListNode *list = (ListNode *)a;
  171.     ListNode *tail = (ListNode *)list->tail();
  172.  
  173.     VSLNode *arg1 = list->head();
  174.     VSLNode *arg2 = tail->head();
  175.  
  176.     if (arg1->isConst() && arg2->isConst())
  177.     {
  178.         if (VSEFlags::show_optimize)
  179.         {
  180.         cout << "\n" << cdef->longname() << ": foldConsts: replacing\n"
  181.             << *this << '\n';
  182.         cout.flush();
  183.         }
  184.  
  185.         // Found 2 args arg1, arg2 that are both constant: Replace
  186.         // f(..., arg1, arg2, ...) by f(..., f(arg1, arg2), ...)
  187.  
  188.         // Create f(arg1, arg2)
  189.         ListNode *new_args = new FixListNode(arg1, arg2);
  190.         BuiltinCallNode *new_f = new BuiltinCallNode(_index, new_args);
  191.  
  192.         // Move nextarg into f(arg, nextarg)
  193.         list->head() = new_f;
  194.         list->tail() = tail->tail();
  195.  
  196.         tail->head() = 0; tail->tail() = 0; delete tail;
  197.  
  198.         if (VSEFlags::show_optimize)
  199.         {
  200.         cout << "by " << *this << '\n';
  201.         cout.flush();
  202.         }
  203.  
  204.         changes++;
  205.     }
  206.     }
  207.  
  208.     // Now try optimization once again
  209.     changes += CallNode::foldConsts(cdef, node);
  210.  
  211.     return changes;
  212. }
  213.  
  214.  
  215.  
  216. // Debugging
  217.  
  218. // Invariant
  219. bool BuiltinCallNode::OK() const
  220. {
  221.     assert (CallNode::OK());
  222.     return true;
  223. }
  224.