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 / exprtree.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-21  |  12.8 KB  |  611 lines

  1. /*
  2.  * exprtree.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 <stdio.h>
  24. #include <stdlib.h>
  25. #include <assert.h>
  26.  
  27. #include "exprtree.h"
  28. #include "userval.h"
  29. #include "builtins.h"
  30. #include "tags.h"
  31. #include "internals.h"
  32. #include "macros.h"
  33. #include "overload.h"
  34. #include "mathmap.h"
  35. #include "jump.h"
  36.  
  37. extern double currentX,
  38.     currentY,
  39.     currentR,
  40.     currentA;
  41. extern int imageWidth,
  42.     imageHeight;
  43. extern int intersamplingEnabled;
  44.  
  45. exprtree*
  46. alloc_exprtree (void)
  47. {
  48.     exprtree *tree = (exprtree*)malloc(sizeof(exprtree));
  49.  
  50.     tree->next = 0;
  51.  
  52.     return tree;
  53. }
  54.  
  55. exprtree*
  56. make_number (float num)
  57. {
  58.     exprtree *tree = alloc_exprtree();
  59.  
  60.     tree->type = EXPR_TUPLE_CONST;
  61.     tree->val.tuple_const.number = nil_tag_number;
  62.     tree->val.tuple_const.length = 1;
  63.     tree->val.tuple_const.data[0] = num;
  64.  
  65.     tree->result = make_tuple_info(nil_tag_number, 1);
  66.  
  67.     return tree;
  68. }
  69.  
  70. exprtree*
  71. make_range (int first, int last)
  72. {
  73.     if (first > last)
  74.     {
  75.     sprintf(error_string, "Invalid range %d..%d.", first, last);
  76.     JUMP(1);
  77.     }
  78.     else if (first == last)
  79.     return make_number(first);
  80.     else
  81.     {
  82.     exprtree *tree = make_number(first);
  83.  
  84.     tree->next = make_range(first + 1, last);
  85.  
  86.     return tree;
  87.     }
  88. }
  89.  
  90. exprtree*
  91. make_var (const char *name)
  92. {
  93.     tuple_info_t info;
  94.     exprtree *tree = 0;
  95.  
  96.     if (lookup_internal(name, &info) != 0)
  97.     {
  98.     tree = alloc_exprtree();
  99.  
  100.     tree->type = EXPR_INTERNAL;
  101.     tree->val.internal = lookup_internal(name, &tree->result);
  102.     tree->result = info;
  103.     }
  104.     else if (lookup_variable_macro(name, &info) != 0)
  105.     {
  106.     macro_function_t function = lookup_variable_macro(name, &info);
  107.  
  108.     tree = function(0);
  109.     }
  110.     else if (lookup_variable(name, &info) != 0)
  111.     {
  112.     tree = alloc_exprtree();
  113.  
  114.     tree->type = EXPR_VARIABLE;
  115.     tree->val.var = lookup_variable(name, &tree->result);
  116.     tree->result = info;
  117.     }
  118.     else
  119.     {
  120.     sprintf(error_string, "Undefined variable %s.", name);
  121.     JUMP(1);
  122.     }
  123.  
  124.     return tree;
  125. }
  126.  
  127. exprtree*
  128. make_tuple (exprtree *elems)
  129. {
  130.     exprtree *tree, *elem;
  131.     int is_const = 1, length;
  132.  
  133.     length = 0;
  134.     for (elem = elems; elem != 0; elem = elem->next)
  135.     {
  136.     ++length;
  137.  
  138.     if (elem->result.length != 1)
  139.     {
  140.         sprintf(error_string, "Tuples cannot contain tuples of length other than 1.");
  141.         JUMP(1);
  142.     }
  143.  
  144.     if (elem->type != EXPR_TUPLE_CONST)
  145.         is_const = 0;
  146.     }
  147.  
  148.     tree = alloc_exprtree();
  149.  
  150.     if (is_const)
  151.     {
  152.     int i;
  153.  
  154.     tree->type = EXPR_TUPLE_CONST;
  155.     tree->val.tuple_const.number = nil_tag_number;
  156.     tree->val.tuple_const.length = length;
  157.  
  158.     elem = elems;
  159.     for (i = 0; i < length; ++i)
  160.     {
  161.         tree->val.tuple_const.data[i] = elem->val.tuple_const.data[0];
  162.         elem = elem->next;
  163.     }
  164.     }
  165.     else
  166.     {
  167.     tree->type = EXPR_TUPLE;
  168.     tree->val.tuple.length = length;
  169.     tree->val.tuple.elems = elems;
  170.     }
  171.     tree->result = make_tuple_info(nil_tag_number, length);
  172.  
  173.     return tree;
  174. }
  175.  
  176. exprtree*
  177. make_select (exprtree *tuple, exprtree *subscripts)
  178. {
  179.     exprtree *tree = alloc_exprtree();
  180.  
  181.     tree->type = EXPR_SELECT;
  182.     tree->val.select.tuple = tuple;
  183.     tree->val.select.subscripts = subscripts;
  184.     if (subscripts->result.length == 1)
  185.     tree->result = make_tuple_info(nil_tag_number, 1);
  186.     else
  187.     tree->result = make_tuple_info(tuple->result.number, subscripts->result.length);
  188.  
  189.     return tree;
  190. }
  191.  
  192. exprtree*
  193. make_cast (const char *tagname, exprtree *tuple)
  194. {
  195.     exprtree *tree = alloc_exprtree();
  196.     int tagnum = tag_number_for_name(tagname);
  197.  
  198.     if (tuple->type == EXPR_TUPLE_CONST)
  199.     {
  200.     tree->type = EXPR_TUPLE_CONST;
  201.     tree->val.tuple_const = tuple->val.tuple_const;
  202.     tree->val.tuple_const.number = tagnum;
  203.     }
  204.     else
  205.     {
  206.     tree->type = EXPR_CAST;
  207.     tree->val.cast.tagnum = tagnum;
  208.     tree->val.cast.tuple = tuple;
  209.     }
  210.     tree->result = make_tuple_info(tagnum, tuple->result.length);
  211.  
  212.     return tree;
  213. }
  214.  
  215. exprtree*
  216. make_convert (const char *tagname, exprtree *tuple)
  217. {
  218.     exprtree *tree = alloc_exprtree();
  219.  
  220.     tree->type = EXPR_CONVERT;
  221.     tree->val.convert.tagnum = tag_number_for_name(tagname);
  222.     tree->val.convert.tuple = tuple;
  223.     tree->result = make_tuple_info(tree->val.convert.tagnum, tuple->result.length);
  224.  
  225.     return tree;
  226. }
  227.  
  228. exprtree*
  229. make_function (const char *name, exprtree *args)
  230. {
  231.     exprtree *tree = 0,
  232.     *arg = args;
  233.     function_arg_info_t *first,
  234.     *last;
  235.     overload_entry_t *entry;
  236.     tuple_info_t info;
  237.  
  238.     if (args == 0)
  239.     {
  240.     sprintf(error_string, "Function %s must be called with at least one argument.", name);
  241.     JUMP(1);
  242.     }
  243.  
  244.     first = last = (function_arg_info_t*)malloc(sizeof(function_arg_info_t));
  245.     last->info = arg->result;
  246.     last->next = 0;
  247.     while (arg->next != 0)
  248.     {
  249.     arg = arg->next;
  250.     last = last->next = (function_arg_info_t*)malloc(sizeof(function_arg_info_t));
  251.     last->info = arg->result;
  252.     last->next = 0;
  253.     }
  254.  
  255.     entry = resolve_function_call(name, first, &info);
  256.     if (entry != 0)
  257.     {
  258.     if (entry->type == OVERLOAD_BUILTIN)
  259.     {
  260.         int is_constant = 1;
  261.  
  262.         for (arg = args; arg != 0; arg = arg->next)
  263.         if (arg->type != EXPR_TUPLE_CONST)
  264.         {
  265.             is_constant = 0;
  266.             break;
  267.         }
  268.  
  269.         tree = alloc_exprtree();
  270.  
  271.         tree->type = EXPR_FUNC;
  272.         tree->val.func.entry = entry;
  273.         tree->val.func.args = args;
  274.         tree->result = info;
  275.  
  276.         if (is_constant && !entry->v.builtin.sidefx)
  277.         {
  278.         tuple_t *result;
  279.         int i;
  280.  
  281.         make_postfix(tree);
  282.         printf("foldings constants:\n");
  283.         output_postfix();
  284.         result = eval_postfix();
  285.  
  286.         tree->type = EXPR_TUPLE_CONST;
  287.         for (i = 0; i < tree->result.length; ++i)
  288.             tree->val.tuple_const.data[i] = result->data[i];
  289.         tree->val.tuple_const.number = tree->result.number;
  290.         tree->val.tuple_const.length = tree->result.length;
  291.         }
  292.     }
  293.     else if (entry->type == OVERLOAD_MACRO)
  294.         tree = entry->v.macro(args);
  295.     else
  296.         assert(0);
  297.     }
  298.     else
  299.     {
  300.     sprintf(error_string, "Unable to resolve invocation of %s.", name);
  301.     JUMP(1);
  302.     }
  303.  
  304.     /*
  305.     while (first != 0)
  306.     {
  307.     function_arg_info_t *next = first->next;
  308.  
  309.     free(first);
  310.     first = next;
  311.     }
  312.     */
  313.  
  314.     return tree;
  315. }
  316.  
  317. exprtree*
  318. make_userval (const char *type, const char *name, exprtree *args)
  319. {
  320.     userval_t *userval;
  321.     exprtree *tree = alloc_exprtree();
  322.  
  323.     if (strcmp(type, "user_slider") == 0)
  324.     {
  325.     float min, max;
  326.  
  327.     if (exprlist_length(args) != 2)
  328.     {
  329.         sprintf(error_string, "user_slider takes 2 arguments.");
  330.         JUMP(1);
  331.     }
  332.     if (args->type != EXPR_TUPLE_CONST || args->val.tuple_const.length != 1
  333.         || args->next->type != EXPR_TUPLE_CONST || args->next->val.tuple_const.length != 1)
  334.     {
  335.         sprintf(error_string, "user_slider min and max must be constants with length 1.");
  336.         JUMP(1);
  337.     }
  338.  
  339.     min = args->val.tuple_const.data[0];
  340.     max = args->next->val.tuple_const.data[0];
  341.  
  342.     userval = register_slider(name, min, max);
  343.  
  344.     if (userval == 0)
  345.     {
  346.         sprintf(error_string, "user_slider %s has a mismatch.", name);
  347.         JUMP(1);
  348.     }
  349.  
  350.     tree->result.number = nil_tag_number;
  351.     tree->result.length = 1;
  352.     }
  353.     else if (strcmp(type, "user_bool") == 0)
  354.     {
  355.     if (exprlist_length(args) != 0)
  356.     {
  357.         sprintf(error_string, "user_bool takes no arguments.");
  358.         JUMP(1);
  359.     }
  360.  
  361.     userval = register_bool(name);
  362.  
  363.     if (userval == 0)
  364.     {
  365.         sprintf(error_string, "user_bool %s has a mismatch.", name);
  366.         JUMP(1);
  367.     }
  368.  
  369.     tree->result.number = nil_tag_number;
  370.     tree->result.length = 1;
  371.     }
  372.     else if (strcmp(type, "user_color") == 0)
  373.     {
  374.     if (exprlist_length(args) != 0)
  375.     {
  376.         sprintf(error_string, "user_bool takes no arguments.");
  377.         JUMP(1);
  378.     }
  379.  
  380.     userval = register_color(name);
  381.  
  382.     if (userval == 0)
  383.     {
  384.         sprintf(error_string, "user_bool %s has a mismatch.", name);
  385.         JUMP(1);
  386.     }
  387.  
  388.     tree->result.number = rgba_tag_number;
  389.     tree->result.length = 4;
  390.     }
  391.     else if (strcmp(type, "user_curve") == 0)
  392.     {
  393.     if (exprlist_length(args) != 1)
  394.     {
  395.         sprintf(error_string, "user_curve takes 1 argument.");
  396.         JUMP(1);
  397.     }
  398.     if (args->result.length != 1)
  399.     {
  400.         sprintf(error_string, "user_curve argument must have length 1.");
  401.         JUMP(1);
  402.     }
  403.  
  404.     userval = register_curve(name);
  405.  
  406.     if (userval == 0)
  407.     {
  408.         sprintf(error_string, "user_curve %s has mismatch.", name);
  409.         JUMP(1);
  410.     }
  411.  
  412.     tree->result.number = nil_tag_number;
  413.     tree->result.length = 1;
  414.     }
  415.     else if (strcmp(type, "user_image") == 0)
  416.     {
  417.     if (exprlist_length(args) != 0)
  418.     {
  419.         sprintf(error_string, "user_image takes no arguments.");
  420.         JUMP(1);
  421.     }
  422.  
  423.     userval = register_image(name);
  424.  
  425.     if (userval == 0)
  426.     {
  427.         sprintf(error_string, "user_image %s has a mismatch.", name);
  428.         JUMP(1);
  429.     }
  430.  
  431.     tree->result.number = image_tag_number;
  432.     tree->result.length = 1;
  433.     }
  434.     else
  435.     {
  436.     sprintf(error_string, "Unknown userval function %s.", type);
  437.     JUMP(1);
  438.     }
  439.  
  440.     tree->type = EXPR_USERVAL;
  441.     tree->val.userval.userval = userval;
  442.     tree->val.userval.args = args;
  443.  
  444.     return tree;
  445. }
  446.  
  447. exprtree*
  448. make_sequence (exprtree *left, exprtree *right)
  449. {
  450.     exprtree *tree = alloc_exprtree();
  451.  
  452.     tree->type = EXPR_SEQUENCE;
  453.     tree->val.operator.left = left;
  454.     tree->val.operator.right = right;
  455.     tree->result = right->result;
  456.  
  457.     return tree;
  458. }
  459.  
  460. exprtree*
  461. make_assignment (char *name, exprtree *value)
  462. {
  463.     exprtree *tree = alloc_exprtree();
  464.     variable_t *var = lookup_variable(name, &tree->result);
  465.  
  466.     if (var == 0)
  467.     {
  468.     var = register_variable(name, value->result);
  469.     tree->result = value->result;
  470.     }
  471.  
  472.     if (tree->result.number != value->result.number || tree->result.length != value->result.length)
  473.     {
  474.     sprintf(error_string, "Variable %s is being assigned two different types.", name);
  475.     JUMP(1);
  476.     }
  477.  
  478.     tree->type = EXPR_ASSIGNMENT;
  479.     tree->val.assignment.var = var;
  480.     tree->val.assignment.value = value;
  481.  
  482.     return tree;
  483. }
  484.  
  485. exprtree*
  486. make_sub_assignment (char *name, exprtree *subscripts, exprtree *value)
  487. {
  488.     exprtree *tree = alloc_exprtree();
  489.     tuple_info_t info;
  490.     variable_t *var = lookup_variable(name, &info);
  491.  
  492.     if (var == 0)
  493.     {
  494.     sprintf(error_string, "Undefined variable %s.", name);
  495.     JUMP(1);
  496.     }
  497.  
  498.     if (subscripts->result.length != value->result.length)
  499.     {
  500.     sprintf(error_string, "Lhs does not match rhs in sub assignment.");
  501.     JUMP(1);
  502.     }
  503.  
  504.     tree->type = EXPR_SUB_ASSIGNMENT;
  505.     tree->val.sub_assignment.var = var;
  506.     tree->val.sub_assignment.subscripts = subscripts;
  507.     tree->val.sub_assignment.value = value;
  508.     tree->result = value->result;
  509.  
  510.     return tree;
  511. }
  512.  
  513. exprtree*
  514. make_if_then (exprtree *condition, exprtree *consequent)
  515. {
  516.     exprtree *tree = alloc_exprtree();
  517.  
  518.     if (condition->result.length != 1)
  519.     {
  520.     sprintf(error_string, "Condition to if statement must have length 1.");
  521.     JUMP(1);
  522.     }
  523.  
  524.     tree->type = EXPR_IF_THEN;
  525.     tree->val.ifExpr.condition = condition;
  526.     tree->val.ifExpr.consequent = consequent;
  527.     tree->result = consequent->result;
  528.  
  529.     return tree;
  530. }
  531.  
  532. exprtree*
  533. make_if_then_else (exprtree *condition, exprtree *consequent, exprtree *alternative)
  534. {
  535.     exprtree *tree = alloc_exprtree();
  536.  
  537.     if (condition->result.length != 1)
  538.     {
  539.     sprintf(error_string, "Condition to if statement must have length 1.");
  540.     JUMP(1);
  541.     }
  542.     if (consequent->result.number != alternative->result.number
  543.     || consequent->result.length != alternative->result.length)
  544.     {
  545.     sprintf(error_string, "Consequent and alternative must have the same type in if statement.");
  546.     JUMP(1);
  547.     }
  548.  
  549.     tree->type = EXPR_IF_THEN_ELSE;
  550.     tree->val.ifExpr.condition = condition;
  551.     tree->val.ifExpr.consequent = consequent;
  552.     tree->val.ifExpr.alternative = alternative;
  553.     tree->result = consequent->result;
  554.  
  555.     return tree;
  556. }
  557.  
  558. exprtree*
  559. make_while (exprtree *invariant, exprtree *body)
  560. {
  561.     exprtree *tree = alloc_exprtree();
  562.  
  563.     tree->type = EXPR_WHILE;
  564.     tree->val.whileExpr.invariant = invariant;
  565.     tree->val.whileExpr.body = body;
  566.     tree->result = make_tuple_info(nil_tag_number, 1);
  567.  
  568.     return tree;
  569. }
  570.  
  571. exprtree*
  572. make_do_while (exprtree *body, exprtree *invariant)
  573. {
  574.     exprtree *tree = alloc_exprtree();
  575.  
  576.     tree->type = EXPR_DO_WHILE;
  577.     tree->val.whileExpr.invariant = invariant;
  578.     tree->val.whileExpr.body = body;
  579.     tree->result = make_tuple_info(nil_tag_number, 1);
  580.  
  581.     return tree;
  582. }
  583.  
  584. int
  585. exprlist_length (exprtree *list)
  586. {
  587.     int l;
  588.  
  589.     l = 0;
  590.     while (list != 0)
  591.     {
  592.     ++l;
  593.     list = list->next;
  594.     }
  595.  
  596.     return l;
  597. }
  598.  
  599. exprtree*
  600. exprlist_append (exprtree *list1, exprtree *list2)
  601. {
  602.     exprtree *tree = list1;
  603.  
  604.     while (tree->next != 0)
  605.     tree = tree->next;
  606.  
  607.     tree->next = list2;
  608.  
  609.     return list1;
  610. }
  611.