one.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 #ifndef __ONE_HH
00018 # define __ONE_HH
00019 
00020 # include "../../terms/term.hh"
00021 # include "../strategies.hh"
00022 
00023 namespace aurelia {
00024 
00027   template <typename Strat>
00028   struct one_strategy {
00029   private:
00030     Strat s;
00031   public:
00032     one_strategy(const Strat& s): s(s) {
00033     }
00034 
00035     template <typename T>
00036     T operator()(const T& term) const {
00037       unsigned arity = term.constructor().arity();
00038       if (arity > 0) {
00039         for (unsigned i = 0;
00040              i < arity;
00041              ++i) {
00042           try {
00043             T success = s(term[i]);
00044             if (diff_no_conv(success, term[i])) {
00045               return term;
00046             }
00047             T *list = (T*)malloc(arity
00048                                  *sizeof(T));
00049             for (unsigned j = 0; j < arity; ++j) {
00050               if (j == i)
00051                 new (list+j) T(success);
00052               else
00053                 new (list+j) T(term[j]);
00054             }
00055             return T(term.constructor(), list);
00056           } catch (failure) {
00057           }
00058         }
00059         throw failure();
00060       }
00061       else
00062         throw failure();
00063     }
00064   };
00065 
00069   template <typename Strat>
00070   one_strategy<Strat> one(const Strat& s) {
00071     return one_strategy<Strat>(s);
00072   }
00073 
00074 }
00075 
00076 #endif