ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/common/calexpr.c
(Generate patch)

Comparing ray/src/common/calexpr.c (file contents):
Revision 2.48 by greg, Sun Feb 25 04:41:44 2024 UTC vs.
Revision 2.53 by greg, Sat Dec 6 02:32:21 2025 UTC

# Line 37 | Line 37 | static const char      RCSid[] = "$Id$";
37  
38   #define  envalue(ep)    ((ep)->type==NUM ? (ep)->v.num : evalue(ep))
39  
40 < static double  euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *);
40 > static double  euminus(EPNODE *), enumber(EPNODE *);
41   static double  echannel(EPNODE *);
42   static double  eadd(EPNODE *), esubtr(EPNODE *),
43                 emult(EPNODE *), edivi(EPNODE *),
# Line 92 | Line 92 | eparse(                        /* parse an expression string */
92      EPNODE  *ep;
93  
94      initstr(expr, NULL, 0);
95 <    curfunc = NULL;
95 >    ecurfunc = NULL;
96      ep = getE1();
97      if (nextc != EOF)
98 <        syntax("unexpected character");
98 >        esyntax("unexpected character");
99      return(ep);
100   }
101  
# Line 208 | Line 208 | epfree(                        /* free a parse tree */
208      }
209      if (frep)
210          efree(epar);
211 +    else
212 +        memset(epar, 0, sizeof(EPNODE));
213   }
214  
215  
# Line 216 | Line 218 | epflatten(                     /* flatten hierarchies for '+', '*' */
218          EPNODE *epar
219   )
220   {
221 <    EPNODE      *ep;
221 >    EPNODE      *ep, *ep1, *ep2;
222 >    double      combined;
223  
224 <    if (epar->nkids < 0)        /* can't handle array allocations */
224 >    if (epar->nkids <= 0)       /* can't handle array allocations */
225          return;
226  
227      for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
228 <        while (ep->type == epar->type && ep->nkids > 0) {
229 <            EPNODE      *ep1 = ep->v.kid;
228 >        while ((ep->type == epar->type) & (ep->nkids > 0)) {
229 >            ep1 = ep->v.kid;
230              while (ep1->sibling != NULL)
231                  ep1 = ep1->sibling;
232              ep1->sibling = ep->sibling;
# Line 232 | Line 235 | epflatten(                     /* flatten hierarchies for '+', '*' */
235              *ep = *ep1;
236              efree(ep1);         /* not epfree()! */
237          }
238 +    if ((epar->nkids <= 2) | !(esupport & E_RCONST))
239 +        return;
240 +    ep1 = NULL;                 /* combine numbers in sum/product */
241 +    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
242 +        if (ep->type == NUM) {
243 +            if (ep1 == NULL) combined = (ep1 = ep)->v.num;
244 +            else if (epar->type == '+') combined += ep->v.num;
245 +            else combined *= ep->v.num;
246 +        }
247 +    if (ep1 == NULL)
248 +        return;
249 +    ep1->v.num = combined;      /* elide others */
250 +    while (ep1->sibling != NULL)
251 +        if (ep1->sibling->type == NUM) {
252 +            ep2 = ep1->sibling;
253 +            ep1->sibling = ep2->sibling;
254 +            efree(ep2);
255 +            if (--epar->nkids <= 2)
256 +                break;
257 +        } else
258 +                ep1 = ep1->sibling;
259   }
260  
261  
# Line 266 | Line 290 | epoptimize(                    /* flatten operations, lists -> arrays *
290  
291                                  /* the following used to be a switch */
292   static double
269 eargument(
270    EPNODE      *ep
271 )
272 {
273    return(argument(ep->v.chan));
274 }
275
276 static double
293   enumber(
294      EPNODE      *ep
295   )
# Line 429 | Line 445 | initfile(              /* prepare input file */
445      lineno = ln;
446      linepos = 0;
447      inpbuf[0] = '\0';
448 <    scan();
448 >    escan();
449   }
450  
451  
# Line 445 | Line 461 | initstr(               /* prepare input string */
461      lineno = ln;
462      linbuf = s;
463      linepos = 0;
464 <    scan();
464 >    escan();
465   }
466  
467  
# Line 465 | Line 481 | getscanpos(    /* return current scan position */
481  
482  
483   int
484 < scan(void)              /* scan next character, return literal next */
484 > escan(void)             /* scan next character, return literal next */
485   {
486      int  lnext = 0;
487  
# Line 487 | Line 503 | scan(void)             /* scan next character, return literal nex
503                  break;
504          }
505          if (nextc == '{') {
506 <            scan();
506 >            escan();
507              while (nextc != '}')
508                  if (nextc == EOF)
509 <                    syntax("'}' expected");
509 >                    esyntax("'}' expected");
510                  else
511 <                    scan();
512 <            scan();
511 >                    escan();
512 >            escan();
513          }
514      } while (isspace(nextc));
515      return(lnext);
# Line 528 | Line 544 | long2ascii(                          /* convert long to ascii */
544  
545  
546   void
547 < syntax(                 /* report syntax error and quit */
547 > esyntax(                        /* report syntax error and quit */
548      char  *err
549   )
550   {
# Line 583 | Line 599 | getname(void)                  /* scan an identifier */
599      int  i, lnext;
600  
601      lnext = nextc;
602 <    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
602 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = escan())
603          str[i] = lnext;
604      str[i] = '\0';
605      while (isid(lnext))         /* skip rest of name */
606 <        lnext = scan();
606 >        lnext = escan();
607  
608      return(str);
609   }
# Line 602 | Line 618 | getinum(void)                  /* scan a positive integer */
618      lnext = nextc;
619      while (isdigit(lnext)) {
620          n = n * 10 + lnext - '0';
621 <        lnext = scan();
621 >        lnext = escan();
622      }
623      return(n);
624   }
# Line 618 | Line 634 | getnum(void)                   /* scan a positive float */
634      lnext = nextc;
635      while (isdigit(lnext) && i < RMAXWORD) {
636          str[i++] = lnext;
637 <        lnext = scan();
637 >        lnext = escan();
638      }
639      if ((lnext == '.') & (i < RMAXWORD)) {
640          str[i++] = lnext;
641 <        lnext = scan();
641 >        lnext = escan();
642          if (i == 1 && !isdigit(lnext))
643 <            syntax("badly formed number");
643 >            esyntax("badly formed number");
644          while (isdigit(lnext) && i < RMAXWORD) {
645              str[i++] = lnext;
646 <            lnext = scan();
646 >            lnext = escan();
647          }
648      }
649      if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
650          str[i++] = lnext;
651 <        lnext = scan();
651 >        lnext = escan();
652          if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
653              str[i++] = lnext;
654 <            lnext = scan();
654 >            lnext = escan();
655          }
656          if (!isdigit(lnext))
657 <            syntax("missing exponent");
657 >            esyntax("missing exponent");
658          while (isdigit(lnext) && i < RMAXWORD) {
659              str[i++] = lnext;
660 <            lnext = scan();
660 >            lnext = escan();
661          }
662      }
663      str[i] = '\0';
# Line 660 | Line 676 | getE1(void)                    /* E1 -> E1 ADDOP E2 */
676      while ((nextc == '+') | (nextc == '-')) {
677          ep2 = newnode();
678          ep2->type = nextc;
679 <        scan();
679 >        escan();
680          addekid(ep2, ep1);
681          addekid(ep2, getE2());
682          if (esupport&E_RCONST &&
# Line 682 | Line 698 | getE2(void)                    /* E2 -> E2 MULOP E3 */
698      while ((nextc == '*') | (nextc == '/')) {
699          ep2 = newnode();
700          ep2->type = nextc;
701 <        scan();
701 >        escan();
702          addekid(ep2, ep1);
703          addekid(ep2, getE3());
704          if (esupport&E_RCONST) {
705 <                EPNODE  *ep3 = ep1->sibling;
706 <                if ((ep1->type == NUM) & (ep3->type == NUM)) {
707 <                        ep2 = rconst(ep2);
708 <                } else if (ep3->type == NUM) {
709 <                        if (ep2->type == '/') {
710 <                                if (ep3->v.num == 0)
711 <                                        syntax("divide by zero constant");
712 <                                ep2->type = '*';        /* for speed */
713 <                                ep3->v.num = 1./ep3->v.num;
714 <                        } else if (ep3->v.num == 0) {
715 <                                ep1->sibling = NULL;    /* (E2 * 0) */
716 <                                epfree(ep2,1);
717 <                                ep2 = ep3;
702 <                        }
703 <                } else if (ep1->type == NUM && ep1->v.num == 0) {
704 <                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
705 <                        ep1->sibling = NULL;
706 <                        efree(ep2);
707 <                        ep2 = ep1;
705 >            EPNODE      *ep3 = ep1->sibling;
706 >            if ((ep1->type == NUM) & (ep3->type == NUM)) {
707 >                ep2 = rconst(ep2);
708 >            } else if (ep3->type == NUM) {
709 >                if (ep2->type == '/') {
710 >                    if (ep3->v.num == 0)
711 >                        esyntax("divide by zero constant");
712 >                    ep2->type = '*';            /* for speed */
713 >                    ep3->v.num = 1./ep3->v.num;
714 >                } else if (ep3->v.num == 0) {
715 >                    ep1->sibling = NULL;        /* (E2 * 0) */
716 >                    epfree(ep2,1);
717 >                    ep2 = ep3;
718                  }
719 +            } else if (ep1->type == NUM && ep1->v.num == 0) {
720 +                epfree(ep3,1);                  /* (0 * E3) or (0 / E3) */
721 +                ep1->sibling = NULL;
722 +                efree(ep2);
723 +                ep2 = ep1;
724 +            }
725          }
726          ep1 = ep2;
727      }
# Line 724 | Line 740 | getE3(void)                    /* E3 -> E4 ^ E3 */
740                  return(ep1);
741          ep2 = newnode();
742          ep2->type = nextc;
743 <        scan();
743 >        escan();
744          addekid(ep2, ep1);
745          addekid(ep2, getE3());
746          if (esupport&E_RCONST) {
747 <                EPNODE  *ep3 = ep1->sibling;
748 <                if ((ep1->type == NUM) & (ep3->type == NUM)) {
749 <                        ep2 = rconst(ep2);
750 <                } else if (ep1->type == NUM && ep1->v.num == 0) {
751 <                        epfree(ep3,1);          /* (0 ^ E3) */
752 <                        ep1->sibling = NULL;
753 <                        efree(ep2);
754 <                        ep2 = ep1;
755 <                } else if ((ep3->type == NUM && ep3->v.num == 0) |
747 >            EPNODE      *ep3 = ep1->sibling;
748 >            if ((ep1->type == NUM) & (ep3->type == NUM)) {
749 >                ep2 = rconst(ep2);
750 >            } else if (ep1->type == NUM && ep1->v.num == 0) {
751 >                epfree(ep3,1);          /* (0 ^ E3) */
752 >                ep1->sibling = NULL;
753 >                efree(ep2);
754 >                ep2 = ep1;
755 >            } else if ((ep3->type == NUM && ep3->v.num == 0) |
756                                  (ep1->type == NUM && ep1->v.num == 1)) {
757 <                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
758 <                        ep2 = newnode();
759 <                        ep2->type = NUM;
760 <                        ep2->v.num = 1;
761 <                } else if (ep3->type == NUM && ep3->v.num == 1) {
762 <                        efree(ep3);     /* (E4 ^ 1) */
763 <                        ep1->sibling = NULL;
764 <                        efree(ep2);
765 <                        ep2 = ep1;
750 <                }
757 >                epfree(ep2,0);          /* (E4 ^ 0) or (1 ^ E3) */
758 >                ep2->type = NUM;
759 >                ep2->v.num = 1;
760 >            } else if (ep3->type == NUM && ep3->v.num == 1) {
761 >                efree(ep3);             /* (E4 ^ 1) */
762 >                ep1->sibling = NULL;
763 >                efree(ep2);
764 >                ep2 = ep1;
765 >            }
766          }
767          return(ep2);
768   }
# Line 760 | Line 775 | getE4(void)                    /* E4 -> ADDOP E5 */
775      EPNODE  *ep1, *ep2;
776  
777      if (nextc == '-') {
778 <        scan();
778 >        escan();
779          ep2 = getE5();
780          if (ep2->type == NUM) {
781 <                ep2->v.num = -ep2->v.num;
782 <                return(ep2);
781 >            ep2->v.num = -ep2->v.num;
782 >            return(ep2);
783          }
784          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
785              ep1 = ep2->v.kid;
# Line 777 | Line 792 | getE4(void)                    /* E4 -> ADDOP E5 */
792          return(ep1);
793      }
794      if (nextc == '+')
795 <        scan();
795 >        escan();
796      return(getE5());
797   }
798  
# Line 795 | Line 810 | getE5(void)                    /* E5 -> (E1) */
810          EPNODE  *ep1, *ep2;
811  
812          if (nextc == '(') {
813 <                scan();
814 <                ep1 = getE1();
815 <                if (nextc != ')')
816 <                        syntax("')' expected");
817 <                scan();
818 <                return(ep1);
813 >            escan();
814 >            ep1 = getE1();
815 >            if (nextc != ')')
816 >                esyntax("')' expected");
817 >            escan();
818 >            return(ep1);
819          }
820          if (esupport&E_INCHAN && nextc == '$') {
821 <                scan();
822 <                ep1 = newnode();
823 <                ep1->type = CHAN;
824 <                ep1->v.chan = getinum();
825 <                return(ep1);
821 >            escan();
822 >            ep1 = newnode();
823 >            ep1->type = CHAN;
824 >            ep1->v.chan = getinum();
825 >            return(ep1);
826          }
827          if (esupport&(E_VARIABLE|E_FUNCTION) &&
828                          (isalpha(nextc) | (nextc == CNTXMARK))) {
829 <                nam = getname();
830 <                ep1 = NULL;
831 <                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
832 <                                && curfunc != NULL)
833 <                        for (i = 1, ep2 = curfunc->v.kid->sibling;
834 <                                        ep2 != NULL; i++, ep2 = ep2->sibling)
835 <                                if (!strcmp(ep2->v.name, nam)) {
821 <                                        ep1 = newnode();
822 <                                        ep1->type = ARG;
823 <                                        ep1->v.chan = i;
824 <                                        break;
825 <                                }
826 <                if (ep1 == NULL) {
829 >            nam = getname();
830 >            ep1 = NULL;
831 >            if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
832 >                                && ecurfunc != NULL)
833 >                for (i = 1, ep2 = ecurfunc->v.kid->sibling;
834 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
835 >                    if (!strcmp(ep2->v.name, nam)) {
836                          ep1 = newnode();
837 <                        ep1->type = VAR;
838 <                        ep1->v.ln = varinsert(nam);
839 <                }
840 <                if (esupport&E_FUNCTION && nextc == '(') {
841 <                        ep2 = newnode();
842 <                        ep2->type = FUNC;
843 <                        addekid(ep2, ep1);
844 <                        ep1 = ep2;
845 <                        do {
846 <                                scan();
847 <                                addekid(ep1, getE1());
848 <                        } while (nextc == ',');
849 <                        if (nextc != ')')
850 <                                syntax("')' expected");
851 <                        scan();
852 <                } else if (!(esupport&E_VARIABLE))
853 <                        syntax("'(' expected");
854 <                if (esupport&E_RCONST && isconstvar(ep1))
855 <                        ep1 = rconst(ep1);
856 <                return(ep1);
837 >                        ep1->type = ARG;
838 >                        ep1->v.chan = i;
839 >                        break;
840 >                    }
841 >            if (ep1 == NULL) {
842 >                ep1 = newnode();
843 >                ep1->type = VAR;
844 >                ep1->v.ln = varinsert(nam);
845 >            }
846 >            if (esupport&E_FUNCTION && nextc == '(') {
847 >                ep2 = newnode();
848 >                ep2->type = FUNC;
849 >                addekid(ep2, ep1);
850 >                ep1 = ep2;
851 >                do {
852 >                    escan();
853 >                    addekid(ep1, getE1());
854 >                } while (nextc == ',');
855 >                if (nextc != ')')
856 >                    esyntax("')' expected");
857 >                escan();
858 >            } else if (!(esupport&E_VARIABLE))
859 >                esyntax("'(' expected");
860 >            if (esupport&E_RCONST && isconstvar(ep1))
861 >                ep1 = rconst(ep1);
862 >            return(ep1);
863          }
864          if (isdecimal(nextc)) {
865 <                ep1 = newnode();
866 <                ep1->type = NUM;
867 <                ep1->v.num = getnum();
868 <                return(ep1);
865 >            ep1 = newnode();
866 >            ep1->type = NUM;
867 >            ep1->v.num = getnum();
868 >            return(ep1);
869          }
870 <        syntax("unexpected character");
870 >        esyntax("unexpected character");
871          return NULL; /* pro forma return */
872   }
873  
# Line 869 | Line 884 | rconst(                        /* reduce a constant expression */
884      errno = 0;
885      ep->v.num = evalue(epar);
886      if ((errno == EDOM) | (errno == ERANGE))
887 <        syntax("bad constant expression");
887 >        esyntax("bad constant expression");
888      epfree(epar,1);
889  
890      return(ep);
# Line 908 | Line 923 | isconstfun(                    /* is ep linked to a constant function?
923   )
924   {
925      EPNODE  *dp;
926 <    LIBR  *lp;
926 >    ELIBR  *lp;
927  
928      if (ep->type != VAR)
929          return(0);

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)