Allow user defined functions to be parsed.
authorJens Vollinga <jensv@nikhef.nl>
Wed, 15 Jul 2009 06:26:33 +0000 (08:26 +0200)
committerJens Vollinga <jensv@nikhef.nl>
Wed, 15 Jul 2009 06:26:33 +0000 (08:26 +0200)
This patch is an ugly hack that does the same as the commit
f38cbcd651246fb5c1294705d29399f3cbfddaf5
but without changing the ABI (so it can be used in ginac_1-5).

ginac/function.pl
ginac/parser/default_reader.tpl
ginac/parser/parse_context.h
ginac/parser/parser.cpp

index e1533be..708d00e 100644 (file)
@@ -1388,7 +1388,9 @@ unsigned function::find_function(const std::string &name, unsigned nparams)
 /** Return the print name of the function. */
 std::string function::get_name() const
 {
-       GINAC_ASSERT(serial<registered_functions().size());
+       if ( serial >= registered_functions().size() ) {
+               throw std::runtime_error("unknown function");
+       }
        return registered_functions()[serial].name;
 }
 
index 3ae6ff8..244074f 100644 (file)
@@ -37,11 +37,22 @@ const prototype_table& get_default_reader()
        static bool initialized = false;
        static prototype_table reader;
        if (!initialized) {
-[+ FOR function +]
-               reader[make_pair("[+ (get "name") +]", [+ 
-                                   (if (exist? "args") (get "args") "1")
-                                +])] = [+ (get "name") +]_reader;[+
-   ENDFOR +]
+               try {
+                       for ( unsigned ser=0; ; ++ser ) {
+                               GiNaC::function f(ser);
+                               std::string name = f.get_name();
+                               for ( std::size_t nargs=0; ; ++nargs ) {
+                                       try {
+                                               function::find_function(name, nargs);
+                                               prototype proto = std::pair<std::string, std::size_t>(name, nargs);
+                                               std::pair<prototype_table::iterator, bool> ins = reader.insert(std::pair<prototype,reader_func>(proto, (reader_func)ser));
+                                               if ( ins.second ) break;
+                                       }
+                                       catch ( std::runtime_error ) { }
+                               }
+                       }
+               }
+               catch ( std::runtime_error ) { }
                initialized = true;
        }
        return reader;
index 15dfcd6..47b150c 100644 (file)
@@ -82,6 +82,11 @@ typedef ex (*reader_func)(const exvector& args);
  *    number of arguments.
  * 3. User can extend the parser via custom prototype tables. It's possible
  *    to read user defined classes, create abbreviations, etc.
+ *
+ * NOTE: due to a hack that allows user defined functions to be parsed, the map
+ *       value of type reader_func is internally treated as an unsigned and not as a
+ *       function pointer!! The unsigned has to correspond to the serial number of
+ *       the defined GiNaC function.
  */
 typedef std::map<prototype, reader_func> prototype_table;
 
index 42edf5b..4931466 100644 (file)
@@ -25,6 +25,7 @@
 #include "debug.h"
 #include "mul.h"
 #include "constant.h"
+#include "function.h"
 
 #include <sstream>
 #include <stdexcept>
@@ -65,7 +66,7 @@ ex parser::parse_identifier_expr()
                Parse_error_("no function \"" << name << "\" with " <<
                             args.size() << " arguments");
        }
-       ex ret = reader->second(args);
+       ex ret = GiNaC::function((unsigned)reader->second, args);
        return ret;
 }