home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / unofficial-plug-ins / mathmap / overload.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-21  |  7.4 KB  |  300 lines

  1. /*
  2.  * overload.c
  3.  *
  4.  * MathMap
  5.  *
  6.  * Copyright (C) 1997-2000 Mark Probst
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License
  10.  * as published by the Free Software Foundation; either version 2
  11.  * of the License, or (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <assert.h>
  26. #include <ctype.h>
  27.  
  28. #include "lispreader.h"
  29. #include "tags.h"
  30.  
  31. #include "overload.h"
  32.  
  33. extern int intersamplingEnabled;
  34.  
  35. extern int oaparse (void);
  36.  
  37. static overload_entry_t *first_overload_entry = 0,
  38.     *last_overload_entry = 0;
  39. static named_binding_t *first_named_binding = 0;
  40.  
  41. binding_t*
  42. new_free_variable_binding (void)
  43. {
  44.     binding_t *binding = (binding_t*)malloc(sizeof(binding_t));
  45.  
  46.     binding->is_bound = 0;
  47.     binding->next = 0;
  48.  
  49.     return binding;
  50. }
  51.  
  52. binding_t*
  53. new_constant_binding (int value)
  54. {
  55.     binding_t *binding = (binding_t*)malloc(sizeof(binding_t));
  56.  
  57.     binding->is_bound = 1;
  58.     binding->value = value;
  59.     binding->next = 0;
  60.  
  61.     return binding;
  62. }
  63.  
  64. void
  65. clear_bindings (void)
  66. {
  67.     named_binding_t *binding = first_named_binding;
  68.  
  69.     while (binding != 0)
  70.     {
  71.     named_binding_t *next = binding->next;
  72.  
  73.     free(binding);
  74.     binding = next;
  75.     }
  76.  
  77.     first_named_binding = 0;
  78. }
  79.  
  80. binding_t*
  81. free_binding_with_name (const char *name)
  82. {
  83.     named_binding_t *binding;
  84.  
  85.     for (binding = first_named_binding; binding != 0; binding = binding->next)
  86.     if (strcmp(binding->name, name) == 0)
  87.         return binding->binding;
  88.  
  89.     binding = (named_binding_t*)malloc(sizeof(named_binding_t));
  90.     strncpy(binding->name, name, MAX_BINDING_LENGTH);
  91.     binding->name[MAX_BINDING_LENGTH] = '\0';
  92.     binding->binding = new_free_variable_binding();
  93.  
  94.     binding->next = first_named_binding;
  95.     first_named_binding = binding;
  96.  
  97.     return binding->binding;
  98. }
  99.  
  100. overload_arg_t*
  101. new_overload_argument (binding_t *tag, binding_t *length, overload_arg_t *next)
  102. {
  103.     overload_arg_t *arg = (overload_arg_t*)malloc(sizeof(overload_arg_t));
  104.  
  105.     arg->tag = tag;
  106.     arg->length = length;
  107.     arg->next = next;
  108.  
  109.     return arg;
  110. }
  111.  
  112. binding_t*
  113. string_to_binding (const char *str)
  114. {
  115.     if (strcmp(str, "_") == 0)
  116.     return new_free_variable_binding();
  117.     if (islower(str[0]))
  118.     return new_constant_binding(tag_number_for_name(str));
  119.     return free_binding_with_name(str);
  120. }
  121.  
  122. binding_t*
  123. lisp_object_to_binding (lisp_object_t *obj)
  124. {
  125.     switch (lisp_type(obj))
  126.     {
  127.     case LISP_TYPE_SYMBOL :
  128.         return string_to_binding(lisp_symbol(obj));
  129.     case LISP_TYPE_INTEGER :
  130.         return new_constant_binding(lisp_integer(obj));
  131.     default :
  132.         assert(0);
  133.     }
  134.     return 0;
  135. }
  136.  
  137. overload_arg_t*
  138. lisp_object_to_overload_arg (lisp_object_t *obj, overload_arg_t *next)
  139. {
  140.     return new_overload_argument(lisp_object_to_binding(lisp_car(obj)),
  141.                  lisp_object_to_binding(lisp_car(lisp_cdr(obj))),
  142.                  next);
  143. }
  144.  
  145. overload_arg_t*
  146. lisp_object_to_overload_args (lisp_object_t *obj)
  147. {
  148.     if (lisp_type(obj) == LISP_TYPE_NIL)
  149.     return 0;
  150.     return lisp_object_to_overload_arg(lisp_car(obj), lisp_object_to_overload_args(lisp_cdr(obj)));
  151. }
  152.  
  153. void
  154. interpret_arg_string (const char *string, overload_arg_t **result, overload_arg_t **args)
  155. {
  156.     lisp_object_t *obj = lisp_read_from_string(string);
  157.  
  158.     *result = lisp_object_to_overload_arg(lisp_car(obj), 0);
  159.     *args = lisp_object_to_overload_args(lisp_cdr(obj));
  160.  
  161.     lisp_free(obj);
  162. }
  163.  
  164. void
  165. register_overloaded_builtin (const char *name, const char *argstring, int sidefx,
  166.                  builtin_function_t func, generator_function_t gen)
  167. {
  168.     overload_entry_t *entry = (overload_entry_t*)malloc(sizeof(overload_entry_t));
  169.     overload_arg_t *arg;
  170.  
  171.     strncpy(entry->name, name, MAX_FUNCTION_LENGTH);
  172.     entry->name[MAX_FUNCTION_LENGTH] = '\0';
  173.     entry->type = OVERLOAD_BUILTIN;
  174.  
  175.     interpret_arg_string(argstring, &entry->result, &entry->args);
  176.  
  177.     for (arg = entry->args, entry->num_args = 0; arg != 0; arg = arg->next)
  178.     ++entry->num_args;
  179.     entry->v.builtin.sidefx = sidefx;
  180.     entry->v.builtin.builtin = func;
  181.     entry->v.builtin.generator = gen;
  182.  
  183.     entry->next = 0;
  184.  
  185.     if (first_overload_entry == 0)
  186.     first_overload_entry = last_overload_entry = entry;
  187.     else
  188.     last_overload_entry = last_overload_entry->next = entry;
  189. }
  190.  
  191. void
  192. register_overloaded_macro (const char *name, const char *argstring, macro_function_t func)
  193. {
  194.     overload_entry_t *entry = (overload_entry_t*)malloc(sizeof(overload_entry_t));
  195.     overload_arg_t *arg;
  196.  
  197.     strncpy(entry->name, name, MAX_FUNCTION_LENGTH);
  198.     entry->name[MAX_FUNCTION_LENGTH] = '\0';
  199.     entry->type = OVERLOAD_MACRO;
  200.  
  201.     interpret_arg_string(argstring, &entry->result, &entry->args);
  202.  
  203.     for (arg = entry->args, entry->num_args = 0; arg != 0; arg = arg->next)
  204.     ++entry->num_args;
  205.     entry->v.macro = func;
  206.  
  207.     entry->next = 0;
  208.  
  209.     if (first_overload_entry == 0)
  210.     first_overload_entry = last_overload_entry = entry;
  211.     else
  212.     last_overload_entry = last_overload_entry->next = entry;
  213. }
  214.  
  215. overload_entry_t*
  216. overloaded_builtin_with_function (builtin_function_t function)
  217. {
  218.     overload_entry_t *entry;
  219.  
  220.     for (entry = first_overload_entry; entry != 0; entry = entry->next)
  221.     if (entry->type == OVERLOAD_BUILTIN && entry->v.builtin.builtin == function)
  222.         return entry;
  223.  
  224.     return 0;
  225. }
  226.  
  227. overload_entry_t*
  228. resolve_function_call (const char *name, function_arg_info_t *args, tuple_info_t *result)
  229. {
  230.     binding_t **undo_array;
  231.     int num_undos = 0,
  232.     num_args = 0;
  233.     function_arg_info_t *func_arg;
  234.     overload_entry_t *entry;
  235.     overload_arg_t *ovld_arg;
  236.  
  237.     if (strcmp(name, "origVal") == 0)
  238.     if (intersamplingEnabled)
  239.         name = "origValIntersample";
  240.  
  241.     for (func_arg = args; func_arg != 0; func_arg = func_arg->next)
  242.     ++num_args;
  243.  
  244.     undo_array = (binding_t**)malloc(2 * num_args * sizeof(binding_t*));
  245.  
  246.     for (entry = first_overload_entry; entry != 0; entry = entry->next)
  247.     if (strcmp(entry->name, name) == 0 && entry->num_args == num_args)
  248.     {
  249.         int match = 1;
  250.  
  251.         for (ovld_arg = entry->args, func_arg = args;
  252.          func_arg != 0;
  253.          ovld_arg = ovld_arg->next, func_arg = func_arg->next)
  254.         {
  255.         if (ovld_arg->tag->is_bound && ovld_arg->tag->value != func_arg->info.number)
  256.         {
  257.             match = 0;
  258.             break;
  259.         }
  260.         else if (!ovld_arg->tag->is_bound)
  261.         {
  262.             undo_array[num_undos++] = ovld_arg->tag;
  263.             ovld_arg->tag->is_bound = 1;
  264.             ovld_arg->tag->value = func_arg->info.number;
  265.         }
  266.  
  267.         if (ovld_arg->length->is_bound && ovld_arg->length->value != func_arg->info.length)
  268.         {
  269.             match = 0;
  270.             break;
  271.         }
  272.         else if (!ovld_arg->length->is_bound)
  273.         {
  274.             undo_array[num_undos++] = ovld_arg->length;
  275.             ovld_arg->length->is_bound = 1;
  276.             ovld_arg->length->value = func_arg->info.length;
  277.         }
  278.         }
  279.  
  280.         if (match)
  281.         {
  282.         assert(entry->result->tag->is_bound && entry->result->length->is_bound);
  283.         *result = make_tuple_info(entry->result->tag->value, entry->result->length->value);
  284.         }
  285.  
  286.         for (--num_undos; num_undos >= 0; --num_undos)
  287.         undo_array[num_undos]->is_bound = 0;
  288.         num_undos = 0;
  289.  
  290.         if (match)
  291.         {
  292.         free(undo_array);
  293.         return entry;
  294.         }
  295.     }
  296.  
  297.     free(undo_array);
  298.     return 0;
  299. }
  300.