Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - language - compile.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31041-bd73e9fcdd) Lines: 90.4 % 1811 1637
Test Date: 2026-07-22 22:45:42 Functions: 96.7 % 92 89
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2006  The PARI group.
       2              : 
       3              : This file is part of the PARI package.
       4              : 
       5              : PARI/GP is free software; you can redistribute it and/or modify it under the
       6              : terms of the GNU General Public License as published by the Free Software
       7              : Foundation; either version 2 of the License, or (at your option) any later
       8              : version. It is distributed in the hope that it will be useful, but WITHOUT
       9              : ANY WARRANTY WHATSOEVER.
      10              : 
      11              : Check the License for details. You should have received a copy of it, along
      12              : with the package; see the file 'COPYING'. If not, write to the Free Software
      13              : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14              : 
      15              : #include "pari.h"
      16              : #include "paripriv.h"
      17              : #include "anal.h"
      18              : #include "tree.h"
      19              : #include "opcode.h"
      20              : 
      21              : #define DEBUGLEVEL DEBUGLEVEL_compiler
      22              : 
      23              : #define tree pari_tree
      24              : 
      25              : enum COflags {COsafelex=1, COsafedyn=2};
      26              : 
      27              : /***************************************************************************
      28              :  **                                                                       **
      29              :  **                           String constant expansion                   **
      30              :  **                                                                       **
      31              :  ***************************************************************************/
      32              : 
      33              : static char *
      34      3822454 : translate(const char **src, char *s)
      35              : {
      36      3822454 :   const char *t = *src;
      37     30150424 :   while (*t)
      38              :   {
      39     30151086 :     while (*t == '\\')
      40              :     {
      41          662 :       switch(*++t)
      42              :       {
      43           12 :         case 'e':  *s='\033'; break; /* escape */
      44          468 :         case 'n':  *s='\n'; break;
      45           14 :         case 't':  *s='\t'; break;
      46          168 :         default:   *s=*t; if (!*t) { *src=s; return NULL; }
      47              :       }
      48          662 :       t++; s++;
      49              :     }
      50     30150424 :     if (*t == '"')
      51              :     {
      52      3822454 :       if (t[1] != '"') break;
      53            0 :       t += 2; continue;
      54              :     }
      55     26327970 :     *s++ = *t++;
      56              :   }
      57      3822454 :   *s=0; *src=t; return s;
      58              : }
      59              : 
      60              : static void
      61           92 : matchQ(const char *s, char *entry)
      62              : {
      63           92 :   if (*s != '"')
      64            0 :     pari_err(e_SYNTAX,"expected character: '\"' instead of",s,entry);
      65           92 : }
      66              : 
      67              : /*  Read a "string" from src. Format then copy it, starting at s. Return
      68              :  *  pointer to char following the end of the input string */
      69              : char *
      70           46 : pari_translate_string(const char *src, char *s, char *entry)
      71              : {
      72           46 :   matchQ(src, entry); src++; s = translate(&src, s);
      73           46 :   if (!s) pari_err(e_SYNTAX,"run-away string",src,entry);
      74           46 :   matchQ(src, entry); return (char*)src+1;
      75              : }
      76              : 
      77              : static GEN
      78      3822408 : strntoGENexp(const char *str, long len)
      79              : {
      80      3822408 :   long n = nchar2nlong(len-1);
      81      3822408 :   GEN z = cgetg(1+n, t_STR);
      82      3822408 :   const char *t = str+1;
      83      3822408 :   z[n] = 0;
      84      3822408 :   if (!translate(&t, GSTR(z))) compile_err("run-away string",str);
      85      3822408 :   return z;
      86              : }
      87              : 
      88              : /***************************************************************************
      89              :  **                                                                       **
      90              :  **                           Byte-code compiler                          **
      91              :  **                                                                       **
      92              :  ***************************************************************************/
      93              : 
      94              : typedef enum {Llocal, Lmy} Ltype;
      95              : 
      96              : struct vars_s
      97              : {
      98              :   Ltype type; /*Only Llocal and Lmy are allowed */
      99              :   int inl;
     100              :   entree *ep;
     101              : };
     102              : 
     103              : struct frame_s
     104              : {
     105              :   long pc;
     106              :   GEN frame;
     107              : };
     108              : 
     109              : static THREAD pari_stack s_opcode, s_operand, s_data, s_lvar;
     110              : static THREAD pari_stack s_dbginfo, s_frame, s_accesslex;
     111              : static THREAD char *opcode;
     112              : static THREAD long *operand;
     113              : static THREAD long *accesslex;
     114              : static THREAD GEN *data;
     115              : static THREAD long offset, nblex;
     116              : static THREAD struct vars_s *localvars;
     117              : static THREAD const char **dbginfo, *dbgstart;
     118              : static THREAD struct frame_s *frames;
     119              : 
     120              : void
     121       378475 : pari_init_compiler(void)
     122              : {
     123       378475 :   pari_stack_init(&s_opcode,sizeof(*opcode),(void **)&opcode);
     124       378433 :   pari_stack_init(&s_operand,sizeof(*operand),(void **)&operand);
     125       378410 :   pari_stack_init(&s_accesslex,sizeof(*operand),(void **)&accesslex);
     126       378396 :   pari_stack_init(&s_data,sizeof(*data),(void **)&data);
     127       378388 :   pari_stack_init(&s_lvar,sizeof(*localvars),(void **)&localvars);
     128       378381 :   pari_stack_init(&s_dbginfo,sizeof(*dbginfo),(void **)&dbginfo);
     129       378388 :   pari_stack_init(&s_frame,sizeof(*frames),(void **)&frames);
     130       378396 :   offset=-1; nblex=0;
     131       378396 : }
     132              : void
     133       372183 : pari_close_compiler(void)
     134              : {
     135       372183 :   pari_stack_delete(&s_opcode);
     136       368787 :   pari_stack_delete(&s_operand);
     137       364075 :   pari_stack_delete(&s_accesslex);
     138       360963 :   pari_stack_delete(&s_data);
     139       358667 :   pari_stack_delete(&s_lvar);
     140       357201 :   pari_stack_delete(&s_dbginfo);
     141       356548 :   pari_stack_delete(&s_frame);
     142       356610 : }
     143              : 
     144              : struct codepos
     145              : {
     146              :   long opcode, data, localvars, frames, accesslex;
     147              :   long offset, nblex;
     148              :   const char *dbgstart;
     149              : };
     150              : 
     151              : static void
     152     10116637 : getcodepos(struct codepos *pos)
     153              : {
     154     10116637 :   pos->opcode=s_opcode.n;
     155     10116637 :   pos->accesslex=s_accesslex.n;
     156     10116637 :   pos->data=s_data.n;
     157     10116637 :   pos->offset=offset;
     158     10116637 :   pos->nblex=nblex;
     159     10116637 :   pos->localvars=s_lvar.n;
     160     10116637 :   pos->dbgstart=dbgstart;
     161     10116637 :   pos->frames=s_frame.n;
     162     10116637 :   offset=s_data.n-1;
     163     10116637 : }
     164              : 
     165              : void
     166          452 : compilestate_reset(void)
     167              : {
     168          452 :   s_opcode.n=0;
     169          452 :   s_operand.n=0;
     170          452 :   s_accesslex.n=0;
     171          452 :   s_dbginfo.n=0;
     172          452 :   s_data.n=0;
     173          452 :   s_lvar.n=0;
     174          452 :   s_frame.n=0;
     175          452 :   offset=-1;
     176          452 :   nblex=0;
     177          452 :   dbgstart=NULL;
     178          452 : }
     179              : 
     180              : void
     181      1432371 : compilestate_save(struct pari_compilestate *comp)
     182              : {
     183      1432371 :   comp->opcode=s_opcode.n;
     184      1432371 :   comp->operand=s_operand.n;
     185      1432371 :   comp->accesslex=s_accesslex.n;
     186      1432371 :   comp->data=s_data.n;
     187      1432371 :   comp->offset=offset;
     188      1432371 :   comp->nblex=nblex;
     189      1432371 :   comp->localvars=s_lvar.n;
     190      1432371 :   comp->dbgstart=dbgstart;
     191      1432371 :   comp->dbginfo=s_dbginfo.n;
     192      1432371 :   comp->frames=s_frame.n;
     193      1432371 : }
     194              : 
     195              : void
     196        56443 : compilestate_restore(struct pari_compilestate *comp)
     197              : {
     198        56443 :   s_opcode.n=comp->opcode;
     199        56443 :   s_operand.n=comp->operand;
     200        56443 :   s_accesslex.n=comp->accesslex;
     201        56443 :   s_data.n=comp->data;
     202        56443 :   offset=comp->offset;
     203        56443 :   nblex=comp->nblex;
     204        56443 :   s_lvar.n=comp->localvars;
     205        56443 :   dbgstart=comp->dbgstart;
     206        56443 :   s_dbginfo.n=comp->dbginfo;
     207        56443 :   s_frame.n=comp->frames;
     208        56443 : }
     209              : 
     210              : static GEN
     211     13976951 : gcopyunclone(GEN x) { GEN y = gcopy(x); gunclone(x); return y; }
     212              : 
     213              : static void
     214       117298 : access_push(long x)
     215              : {
     216       117298 :   long a = pari_stack_new(&s_accesslex);
     217       117298 :   accesslex[a] = x;
     218       117298 : }
     219              : 
     220              : static GEN
     221      9162201 : genctx(long nbmvar, long paccesslex)
     222              : {
     223      9162201 :   GEN acc = const_vec(nbmvar,gen_1);
     224      9162210 :   long i, lvl = 1 + nbmvar;
     225      9204850 :   for (i = paccesslex; i<s_accesslex.n; i++)
     226              :   {
     227        42640 :     long a = accesslex[i];
     228        42640 :     if (a > 0) { lvl+=a; continue; }
     229        37375 :     a += lvl;
     230        37375 :     if (a <= 0) pari_err_BUG("genctx");
     231        37375 :     if (a <= nbmvar)
     232        28917 :       gel(acc, a) = gen_0;
     233              :   }
     234      9162210 :   s_accesslex.n = paccesslex;
     235     32955746 :   for (i = 1; i<=nbmvar; i++)
     236     23793536 :     if (signe(gel(acc,i))==0)
     237        21040 :       access_push(i-nbmvar-1);
     238      9162210 :   return acc;
     239              : }
     240              : 
     241              : static GEN
     242     10116561 : getfunction(const struct codepos *pos, long arity, long nbmvar, GEN text,
     243              :             long gap)
     244              : {
     245     10116561 :   long lop  = s_opcode.n+1 - pos->opcode;
     246     10116561 :   long ldat = s_data.n+1 - pos->data;
     247     10116561 :   long lfram = s_frame.n+1 - pos->frames;
     248     10116561 :   GEN cl = cgetg(nbmvar && text? 8: (text? 7: 6), t_CLOSURE);
     249              :   GEN frpc, fram, dbg, op, dat;
     250              :   char *s;
     251              :   long i;
     252              : 
     253     10116536 :   cl[1] = arity;
     254     10116536 :   gel(cl,2) = cgetg(nchar2nlong(lop)+1, t_STR);
     255     10116503 :   gel(cl,3) = op = cgetg(lop, t_VECSMALL);
     256     10116507 :   gel(cl,4) = dat = cgetg(ldat, t_VEC);
     257     10116507 :   dbg = cgetg(lop,  t_VECSMALL);
     258     10116505 :   frpc = cgetg(lfram,  t_VECSMALL);
     259     10116501 :   fram = cgetg(lfram,  t_VEC);
     260     10116504 :   gel(cl,5) = mkvec3(dbg, frpc, fram);
     261     10116520 :   if (text) gel(cl,6) = text;
     262     10116520 :   s = GSTR(gel(cl,2)) - 1;
     263    169730304 :   for (i = 1; i < lop; i++)
     264              :   {
     265    159613784 :     long j = i+pos->opcode-1;
     266    159613784 :     s[i] = opcode[j];
     267    159613784 :     op[i] = operand[j];
     268    159613784 :     dbg[i] = dbginfo[j] - dbgstart;
     269    159613784 :     if (dbg[i] < 0) dbg[i] += gap;
     270              :   }
     271     10116520 :   s[i] = 0;
     272     10116520 :   s_opcode.n = pos->opcode;
     273     10116520 :   s_operand.n = pos->opcode;
     274     10116520 :   s_dbginfo.n = pos->opcode;
     275     10116520 :   if (lg(cl)==8)
     276      9151033 :     gel(cl,7) = genctx(nbmvar, pos->accesslex);
     277       965487 :   else if (nbmvar==0)
     278       954365 :     s_accesslex.n = pos->accesslex;
     279              :   else
     280              :   {
     281        11122 :     pari_sp av = avma;
     282        11122 :     (void) genctx(nbmvar, pos->accesslex);
     283        11168 :     set_avma(av);
     284              :   }
     285     14921330 :   for (i = 1; i < ldat; i++)
     286      4804762 :     if (data[i+pos->data-1]) gel(dat,i) = gcopyunclone(data[i+pos->data-1]);
     287     10116568 :   s_data.n = pos->data;
     288     10146148 :   while (s_lvar.n > pos->localvars && !localvars[s_lvar.n-1].inl)
     289              :   {
     290        29580 :     if (localvars[s_lvar.n-1].type==Lmy) nblex--;
     291        29580 :     s_lvar.n--;
     292              :   }
     293     19288847 :   for (i = 1; i < lfram; i++)
     294              :   {
     295      9172195 :     long j = i+pos->frames-1;
     296      9172195 :     frpc[i] = frames[j].pc - pos->opcode+1;
     297      9172195 :     gel(fram, i) = gcopyunclone(frames[j].frame);
     298              :   }
     299     10116652 :   s_frame.n = pos->frames;
     300     10116652 :   offset = pos->offset;
     301     10116652 :   dbgstart = pos->dbgstart;
     302     10116652 :   return cl;
     303              : }
     304              : 
     305              : static GEN
     306        20550 : getclosure(struct codepos *pos, long nbmvar)
     307              : {
     308        20550 :   return getfunction(pos, 0, nbmvar, NULL, 0);
     309              : }
     310              : 
     311              : static void
     312    159610393 : op_push_loc(op_code o, long x, const char *loc)
     313              : {
     314    159610393 :   long n=pari_stack_new(&s_opcode);
     315    159610367 :   long m=pari_stack_new(&s_operand);
     316    159610324 :   long d=pari_stack_new(&s_dbginfo);
     317    159610368 :   opcode[n]=o;
     318    159610368 :   operand[m]=x;
     319    159610368 :   dbginfo[d]=loc;
     320    159610368 : }
     321              : 
     322              : static void
     323    115727721 : op_push(op_code o, long x, long n)
     324              : {
     325    115727721 :   op_push_loc(o,x,tree[n].str);
     326    115727721 : }
     327              : 
     328              : static void
     329         3052 : op_insert_loc(long k, op_code o, long x, const char *loc)
     330              : {
     331              :   long i;
     332         3052 :   long n=pari_stack_new(&s_opcode);
     333         3052 :   (void) pari_stack_new(&s_operand);
     334         3052 :   (void) pari_stack_new(&s_dbginfo);
     335       636644 :   for (i=n-1; i>=k; i--)
     336              :   {
     337       633592 :     opcode[i+1] = opcode[i];
     338       633592 :     operand[i+1]= operand[i];
     339       633592 :     dbginfo[i+1]= dbginfo[i];
     340              :   }
     341         3052 :   opcode[k]  = o;
     342         3052 :   operand[k] = x;
     343         3052 :   dbginfo[k] = loc;
     344         3052 : }
     345              : 
     346              : static long
     347      4804762 : data_push(GEN x)
     348              : {
     349      4804762 :   long n=pari_stack_new(&s_data);
     350      4804762 :   data[n] = x?gclone(x):x;
     351      4804762 :   return n-offset;
     352              : }
     353              : 
     354              : static void
     355        66093 : var_push(entree *ep, Ltype type)
     356              : {
     357        66093 :   long n=pari_stack_new(&s_lvar);
     358        66093 :   localvars[n].ep   = ep;
     359        66093 :   localvars[n].inl  = 0;
     360        66093 :   localvars[n].type = type;
     361        66093 :   if (type == Lmy) nblex++;
     362        66093 : }
     363              : 
     364              : static void
     365      9172236 : frame_push(GEN x)
     366              : {
     367      9172236 :   long n=pari_stack_new(&s_frame);
     368      9172225 :   frames[n].pc = s_opcode.n-1;
     369      9172225 :   frames[n].frame = gclone(x);
     370      9172287 : }
     371              : 
     372              : static GEN
     373           55 : pack_localvars(void)
     374              : {
     375           55 :   GEN pack=cgetg(3,t_VEC);
     376           55 :   long i, l=s_lvar.n;
     377           55 :   GEN t=cgetg(1+l,t_VECSMALL);
     378           55 :   GEN e=cgetg(1+l,t_VECSMALL);
     379           55 :   gel(pack,1)=t;
     380           55 :   gel(pack,2)=e;
     381          139 :   for(i=1;i<=l;i++)
     382              :   {
     383           84 :     t[i]=localvars[i-1].type;
     384           84 :     e[i]=(long)localvars[i-1].ep;
     385              :   }
     386          139 :   for(i=1;i<=nblex;i++)
     387           84 :     access_push(-i);
     388           55 :   return pack;
     389              : }
     390              : 
     391              : void
     392          259 : push_frame(GEN C, long lpc, long dummy)
     393              : {
     394          259 :   const char *code=closure_codestr(C);
     395          259 :   GEN oper=closure_get_oper(C);
     396          259 :   GEN dbg=closure_get_dbg(C);
     397          259 :   GEN frpc=gel(dbg,2);
     398          259 :   GEN fram=gel(dbg,3);
     399          259 :   long pc, j=1, lfr = lg(frpc);
     400          259 :   if (lpc==-1)
     401              :   {
     402              :     long k;
     403           56 :     GEN e = gel(fram, 1);
     404          112 :     for(k=1; k<lg(e); k++)
     405           56 :       var_push(dummy?NULL:(entree*)e[k], Lmy);
     406           56 :     return;
     407              :   }
     408          259 :   if (lg(C)<8) while (j<lfr && frpc[j]==0) j++;
     409         1715 :   for(pc=0; pc<lpc; pc++) /* do not assume lpc was completed */
     410              :   {
     411         1512 :     if (pc>0 && (code[pc]==OClocalvar || code[pc]==OClocalvar0))
     412            0 :       var_push((entree*)oper[pc],Llocal);
     413         1512 :     if (j<lfr && pc==frpc[j])
     414              :     {
     415              :       long k;
     416          154 :       GEN e = gel(fram,j);
     417          399 :       for(k=1; k<lg(e); k++)
     418          245 :         var_push(dummy?NULL:(entree*)e[k], Lmy);
     419          154 :       j++;
     420              :     }
     421              :   }
     422              : }
     423              : 
     424              : void
     425            0 : debug_context(void)
     426              : {
     427              :   long i;
     428            0 :   for(i=0;i<s_lvar.n;i++)
     429              :   {
     430            0 :     entree *ep = localvars[i].ep;
     431            0 :     Ltype type = localvars[i].type;
     432            0 :     err_printf("%ld: %s: %s\n",i,(type==Lmy?"my":"local"),(ep?ep->name:"NULL"));
     433              :   }
     434            0 : }
     435              : 
     436              : GEN
     437        10992 : localvars_read_str(const char *x, GEN pack)
     438              : {
     439        10992 :   pari_sp av = avma;
     440              :   GEN code;
     441        10992 :   long l=0, nbmvar=nblex;
     442        10992 :   if (pack)
     443              :   {
     444        10992 :     GEN t=gel(pack,1);
     445        10992 :     GEN e=gel(pack,2);
     446              :     long i;
     447        10992 :     l=lg(t)-1;
     448        47171 :     for(i=1;i<=l;i++)
     449        36179 :       var_push((entree*)e[i],(Ltype)t[i]);
     450              :   }
     451        10992 :   code = compile_str(x);
     452        10992 :   s_lvar.n -= l;
     453        10992 :   nblex = nbmvar;
     454        10992 :   return gc_upto(av, closure_evalres(code));
     455              : }
     456              : 
     457              : long
     458            7 : localvars_find(GEN pack, entree *ep)
     459              : {
     460            7 :   GEN t=gel(pack,1);
     461            7 :   GEN e=gel(pack,2);
     462              :   long i;
     463            7 :   long vn=0;
     464            7 :   for(i=lg(e)-1;i>=1;i--)
     465              :   {
     466            0 :     if(t[i]==Lmy)
     467            0 :       vn--;
     468            0 :     if(e[i]==(long)ep)
     469            0 :       return t[i]==Lmy?vn:0;
     470              :   }
     471            7 :   return 0;
     472              : }
     473              : 
     474              : /*
     475              :  Flags for copy optimisation:
     476              :  -- Freturn: The result will be returned.
     477              :  -- FLsurvive: The result must survive the closure.
     478              :  -- FLnocopy: The result will never be updated nor part of a user variable.
     479              :  -- FLnocopylex: The result will never be updated nor part of dynamic variable.
     480              : */
     481              : enum FLflag {FLreturn=1, FLsurvive=2, FLnocopy=4, FLnocopylex=8};
     482              : 
     483              : static void
     484       276186 : addcopy(long n, long mode, long flag, long mask)
     485              : {
     486       276186 :   if (mode==Ggen && !(flag&mask))
     487              :   {
     488        27287 :     op_push(OCcopy,0,n);
     489        27287 :     if (!(flag&FLsurvive) && DEBUGLEVEL)
     490            0 :       pari_warn(warner,"compiler generates copy for `%.*s'",
     491            0 :                        tree[n].len,tree[n].str);
     492              :   }
     493       276186 : }
     494              : 
     495              : static void compilenode(long n, int mode, long flag);
     496              : 
     497              : typedef enum {PPend,PPstd,PPdefault,PPdefaultmulti,PPstar,PPauto} PPproto;
     498              : 
     499              : static PPproto
     500    153854345 : parseproto(char const **q, char *c, const char *str)
     501              : {
     502    153854345 :   char  const *p=*q;
     503              :   long i;
     504    153854345 :   switch(*p)
     505              :   {
     506     39969173 :   case 0:
     507              :   case '\n':
     508     39969173 :     return PPend;
     509       289550 :   case 'D':
     510       289550 :     switch(p[1])
     511              :     {
     512       196575 :     case 'G':
     513              :     case '&':
     514              :     case 'W':
     515              :     case 'V':
     516              :     case 'I':
     517              :     case 'E':
     518              :     case 'J':
     519              :     case 'n':
     520              :     case 'P':
     521              :     case 'r':
     522              :     case 's':
     523       196575 :       *c=p[1]; *q=p+2; return PPdefault;
     524        92975 :     default:
     525       562648 :       for(i=0;*p && i<2;p++) i+=*p==',';
     526              :       /* assert(i>=2) because check_proto validated the protototype */
     527        92975 :       *c=p[-2]; *q=p; return PPdefaultmulti;
     528              :     }
     529              :     break;
     530       144169 :   case 'C':
     531              :   case 'p':
     532              :   case 'b':
     533              :   case 'P':
     534              :   case 'f':
     535       144169 :     *c=*p; *q=p+1; return PPauto;
     536         1554 :   case '&':
     537         1554 :     *c='*'; *q=p+1; return PPstd;
     538        19060 :   case 'V':
     539        19060 :     if (p[1]=='=')
     540              :     {
     541        13790 :       if (p[2]!='G')
     542            0 :         compile_err("function prototype is not supported",str);
     543        13790 :       *c='='; p+=2;
     544              :     }
     545              :     else
     546         5270 :       *c=*p;
     547        19060 :     *q=p+1; return PPstd;
     548        46070 :   case 'E':
     549              :   case 's':
     550        46070 :     if (p[1]=='*') { *c=*p++; *q=p+1; return PPstar; }
     551              :     /*fall through*/
     552              :   }
     553    113399709 :   *c=*p; *q=p+1; return PPstd;
     554              : }
     555              : 
     556              : static long
     557       450848 : detag(long n)
     558              : {
     559       450848 :   while (tree[n].f==Ftag)
     560            0 :     n=tree[n].x;
     561       450848 :   return n;
     562              : }
     563              : 
     564              : /* return type for GP functions */
     565              : static op_code
     566     21688500 : get_ret_type(const char **p, long arity, Gtype *t, long *flag)
     567              : {
     568     21688500 :   *flag = 0;
     569     21688500 :   if (**p == 'v') { (*p)++; *t=Gvoid; return OCcallvoid; }
     570     21639367 :   else if (**p == 'i') { (*p)++; *t=Gsmall;  return OCcallint; }
     571     21632566 :   else if (**p == 'l') { (*p)++; *t=Gsmall;  return OCcalllong; }
     572     21606410 :   else if (**p == 'u') { (*p)++; *t=Gusmall; return OCcalllong; }
     573     21606410 :   else if (**p == 'm') { (*p)++; *flag = FLnocopy; }
     574     21606410 :   *t=Ggen; return arity==2?OCcallgen2:OCcallgen;
     575              : }
     576              : 
     577              : static void
     578            7 : U_compile_err(const char *s)
     579            7 : { compile_err("this should be a small non-negative integer",s); }
     580              : static void
     581            7 : L_compile_err(const char *s)
     582            7 : { compile_err("this should be a small integer",s); }
     583              : 
     584              : /*supported types:
     585              :  * type: Gusmall, Gsmall, Ggen, Gvoid, Gvec, Gclosure
     586              :  * mode: Gusmall, Gsmall, Ggen, Gvar, Gvoid
     587              :  */
     588              : static void
     589     27768323 : compilecast_loc(int type, int mode, const char *loc)
     590              : {
     591     27768323 :   if (type==mode) return;
     592     15528619 :   switch (mode)
     593              :   {
     594          214 :   case Gusmall:
     595          214 :     if (type==Ggen)        op_push_loc(OCitou,-1,loc);
     596          161 :     else if (type==Gvoid)  op_push_loc(OCpushlong,0,loc);
     597          161 :     else if (type!=Gsmall) U_compile_err(loc);
     598          214 :     break;
     599         5264 :   case Gsmall:
     600         5264 :     if (type==Ggen)        op_push_loc(OCitos,-1,loc);
     601            7 :     else if (type==Gvoid)  op_push_loc(OCpushlong,0,loc);
     602            7 :     else if (type!=Gusmall) L_compile_err(loc);
     603         5257 :     break;
     604     15510111 :   case Ggen:
     605     15510111 :     if (type==Gsmall)      op_push_loc(OCstoi,0,loc);
     606     15495600 :     else if (type==Gusmall)op_push_loc(OCutoi,0,loc);
     607     15495600 :     else if (type==Gvoid)  op_push_loc(OCpushgnil,0,loc);
     608     15510111 :     break;
     609         9014 :   case Gvoid:
     610         9014 :     op_push_loc(OCpop, 1,loc);
     611         9014 :     break;
     612         4016 :   case Gvar:
     613         4016 :     if (type==Ggen)        op_push_loc(OCvarn,-1,loc);
     614            7 :     else compile_varerr(loc);
     615         4009 :      break;
     616            0 :   default:
     617            0 :     pari_err_BUG("compilecast [unknown type]");
     618              :   }
     619              : }
     620              : 
     621              : static void
     622     18619663 : compilecast(long n, int type, int mode) { compilecast_loc(type, mode, tree[n].str); }
     623              : 
     624              : static entree *
     625        25295 : fetch_member_raw(const char *s, long len)
     626              : {
     627        25295 :   pari_sp av = avma;
     628        25295 :   char *t = stack_malloc(len+2);
     629              :   entree *ep;
     630        25295 :   t[0] = '_'; strncpy(t+1, s, len); t[++len] = 0; /* prepend '_' */
     631        25295 :   ep = fetch_entry_raw(t, len);
     632        25295 :   set_avma(av); return ep;
     633              : }
     634              : static entree *
     635     21943847 : getfunc(long n)
     636              : {
     637     21943847 :   long x=tree[n].x;
     638     21943847 :   if (tree[x].x==CSTmember) /* str-1 points to '.' */
     639        25295 :     return do_alias(fetch_member_raw(tree[x].str - 1, tree[x].len + 1));
     640              :   else
     641     21918552 :     return do_alias(fetch_entry_raw(tree[x].str, tree[x].len));
     642              : }
     643              : 
     644              : static entree *
     645       368010 : getentry(long n)
     646              : {
     647       368010 :   n = detag(n);
     648       368010 :   if (tree[n].f!=Fentry)
     649              :   {
     650           21 :     if (tree[n].f==Fseq)
     651            0 :       compile_err("unexpected character: ';'", tree[tree[n].y].str-1);
     652           21 :     compile_varerr(tree[n].str);
     653              :   }
     654       367989 :   return getfunc(n);
     655              : }
     656              : 
     657              : static entree *
     658        68081 : getvar(long n)
     659        68081 : { return getentry(n); }
     660              : 
     661              : static entree *
     662        13036 : getvarvec(long n)
     663              : {
     664        13036 :   n = detag(n);
     665        13036 :   if (tree[n].f==Fentry) return getentry(n);
     666           42 :   if (tree[n].f!=Fvec)
     667            7 :     compile_varerr(tree[n].str);
     668           35 :   return do_alias(fetch_entry_raw(tree[n].str, tree[n].len));
     669              : }
     670              : 
     671              : /* match Fentry that are not actually EpSTATIC functions called without parens*/
     672              : static entree *
     673          131 : getvardyn(long n)
     674              : {
     675          131 :   entree *ep = getentry(n);
     676          131 :   if (EpSTATIC(do_alias(ep)))
     677            0 :     compile_varerr(tree[n].str);
     678          131 :   return ep;
     679              : }
     680              : 
     681              : static long
     682     11145629 : getmvar(entree *ep)
     683              : {
     684              :   long i;
     685     11145629 :   long vn=0;
     686     12291315 :   for(i=s_lvar.n-1;i>=0;i--)
     687              :   {
     688      1226402 :     if(localvars[i].type==Lmy)
     689      1226129 :       vn--;
     690      1226402 :     if(localvars[i].ep==ep)
     691        80716 :       return localvars[i].type==Lmy?vn:0;
     692              :   }
     693     11064913 :   return 0;
     694              : }
     695              : 
     696              : static void
     697         9787 : ctxmvar(long n)
     698              : {
     699         9787 :   pari_sp av=avma;
     700              :   GEN ctx;
     701              :   long i;
     702         9787 :   if (n==0) return;
     703         4200 :   ctx = cgetg(n+1,t_VECSMALL);
     704        67648 :   for(n=0, i=0; i<s_lvar.n; i++)
     705        63448 :     if(localvars[i].type==Lmy)
     706        63448 :       ctx[++n]=(long)localvars[i].ep;
     707         4200 :   frame_push(ctx);
     708         4200 :   set_avma(av);
     709              : }
     710              : 
     711              : INLINE int
     712    118440864 : is_func_named(entree *ep, const char *s)
     713              : {
     714    118440864 :   return !strcmp(ep->name, s);
     715              : }
     716              : 
     717              : INLINE int
     718         4316 : is_node_zero(long n)
     719              : {
     720         4316 :   n = detag(n);
     721         4316 :   return (tree[n].f==Fsmall && tree[n].x==0);
     722              : }
     723              : 
     724              : static void
     725           55 : str_defproto(const char *p, const char *q, const char *loc)
     726              : {
     727           55 :   long len = p-4-q;
     728           55 :   if (q[1]!='"' || q[len]!='"')
     729            0 :     compile_err("default argument must be a string",loc);
     730           55 :   op_push_loc(OCpushgen,data_push(strntoGENexp(q+1,len)),loc);
     731           55 : }
     732              : 
     733              : static long
     734          464 : countmatrixelts(long n)
     735              : {
     736              :   long x,i;
     737          464 :   if (n==-1 || tree[n].f==Fnoarg) return 0;
     738         1096 :   for(x=n, i=0; tree[x].f==Fmatrixelts; x=tree[x].x)
     739          632 :     if (tree[tree[x].y].f!=Fnoarg) i++;
     740          464 :   if (tree[x].f!=Fnoarg) i++;
     741          464 :   return i;
     742              : }
     743              : 
     744              : static long
     745     52649460 : countlisttogen(long n, Ffunc f)
     746              : {
     747              :   long x,i;
     748     52649460 :   if (n==-1 || tree[n].f==Fnoarg) return 0;
     749    122041734 :   for(x=n, i=0; tree[x].f==f ;x=tree[x].x, i++);
     750     49380647 :   return i+1;
     751              : }
     752              : 
     753              : static GEN
     754     52649460 : listtogen(long n, Ffunc f)
     755              : {
     756     52649460 :   long x,i,nb = countlisttogen(n, f);
     757     52649460 :   GEN z=cgetg(nb+1, t_VECSMALL);
     758     52649460 :   if (nb)
     759              :   {
     760    122041734 :     for (x=n, i = nb-1; i>0; z[i+1]=tree[x].y, x=tree[x].x, i--);
     761     49380647 :     z[1]=x;
     762              :   }
     763     52649460 :   return z;
     764              : }
     765              : 
     766              : static long
     767     21597716 : first_safe_arg(GEN arg, long mask)
     768              : {
     769     21597716 :   long lnc, l=lg(arg);
     770     45807182 :   for (lnc=l-1; lnc>0 && (tree[arg[lnc]].flags&mask)==mask; lnc--);
     771     21597716 :   return lnc;
     772              : }
     773              : 
     774              : static void
     775        21157 : checkdups(GEN arg, GEN vep)
     776              : {
     777        21157 :   long l=vecsmall_duplicate(vep);
     778        21157 :   if (l!=0) compile_err("variable declared twice",tree[arg[l]].str);
     779        21157 : }
     780              : 
     781              : enum {MAT_range,MAT_std,MAT_line,MAT_column,VEC_std};
     782              : 
     783              : static int
     784        15774 : matindex_type(long n)
     785              : {
     786        15774 :   long x = tree[n].x, y = tree[n].y;
     787        15774 :   long fxx = tree[tree[x].x].f, fxy = tree[tree[x].y].f;
     788        15774 :   if (y==-1)
     789              :   {
     790        13686 :     if (fxy!=Fnorange) return MAT_range;
     791        13077 :     if (fxx==Fnorange) compile_err("missing index",tree[n].str);
     792        13077 :     return VEC_std;
     793              :   }
     794              :   else
     795              :   {
     796         2088 :     long fyx = tree[tree[y].x].f, fyy = tree[tree[y].y].f;
     797         2088 :     if (fxy!=Fnorange || fyy!=Fnorange) return MAT_range;
     798         1913 :     if (fxx==Fnorange && fyx==Fnorange)
     799            0 :       compile_err("missing index",tree[n].str);
     800         1913 :     if (fxx==Fnorange) return MAT_column;
     801         1102 :     if (fyx==Fnorange) return MAT_line;
     802          836 :     return MAT_std;
     803              :   }
     804              : }
     805              : 
     806              : static entree *
     807        49884 : getlvalue(long n)
     808              : {
     809        50894 :   while ((tree[n].f==Fmatcoeff && matindex_type(tree[n].y)!=MAT_range) || tree[n].f==Ftag)
     810         1010 :     n=tree[n].x;
     811        49884 :   return getvar(n);
     812              : }
     813              : 
     814              : INLINE void
     815        46258 : compilestore(long vn, entree *ep, long n)
     816              : {
     817        46258 :   if (vn)
     818         4806 :     op_push(OCstorelex,vn,n);
     819              :   else
     820              :   {
     821        41452 :     if (EpSTATIC(do_alias(ep)))
     822            0 :       compile_varerr(tree[n].str);
     823        41452 :     op_push(OCstoredyn,(long)ep,n);
     824              :   }
     825        46258 : }
     826              : 
     827              : INLINE void
     828          849 : compilenewptr(long vn, entree *ep, long n)
     829              : {
     830          849 :   if (vn)
     831              :   {
     832          261 :     access_push(vn);
     833          261 :     op_push(OCnewptrlex,vn,n);
     834              :   }
     835              :   else
     836          588 :     op_push(OCnewptrdyn,(long)ep,n);
     837          849 : }
     838              : 
     839              : static void
     840         1852 : compilelvalue(long n)
     841              : {
     842         1852 :   n = detag(n);
     843         1852 :   if (tree[n].f==Fentry)
     844          849 :     return;
     845              :   else
     846              :   {
     847         1003 :     long x = tree[n].x, y = tree[n].y;
     848         1003 :     long yx = tree[y].x, yy = tree[y].y;
     849         1003 :     long m = matindex_type(y);
     850         1003 :     if (m == MAT_range)
     851            0 :       compile_err("not an lvalue",tree[n].str);
     852         1003 :     if (m == VEC_std && tree[x].f==Fmatcoeff)
     853              :     {
     854          119 :       int mx = matindex_type(tree[x].y);
     855          119 :       if (mx==MAT_line)
     856              :       {
     857            0 :         int xy = tree[x].y, xyx = tree[xy].x;
     858            0 :         compilelvalue(tree[x].x);
     859            0 :         compilenode(tree[xyx].x,Gsmall,0);
     860            0 :         compilenode(tree[yx].x,Gsmall,0);
     861            0 :         op_push(OCcompo2ptr,0,y);
     862            0 :         return;
     863              :       }
     864              :     }
     865         1003 :     compilelvalue(x);
     866         1003 :     switch(m)
     867              :     {
     868          679 :     case VEC_std:
     869          679 :       compilenode(tree[yx].x,Gsmall,0);
     870          679 :       op_push(OCcompo1ptr,0,y);
     871          679 :       break;
     872          126 :     case MAT_std:
     873          126 :       compilenode(tree[yx].x,Gsmall,0);
     874          126 :       compilenode(tree[yy].x,Gsmall,0);
     875          126 :       op_push(OCcompo2ptr,0,y);
     876          126 :       break;
     877           98 :     case MAT_line:
     878           98 :       compilenode(tree[yx].x,Gsmall,0);
     879           98 :       op_push(OCcompoLptr,0,y);
     880           98 :       break;
     881          100 :     case MAT_column:
     882          100 :       compilenode(tree[yy].x,Gsmall,0);
     883          100 :       op_push(OCcompoCptr,0,y);
     884          100 :       break;
     885              :     }
     886              :   }
     887              : }
     888              : 
     889              : static void
     890        13642 : compilematcoeff(long n, int mode)
     891              : {
     892        13642 :   long x=tree[n].x, y=tree[n].y;
     893        13642 :   long yx=tree[y].x, yy=tree[y].y;
     894        13642 :   long m=matindex_type(y);
     895        13642 :   compilenode(x,Ggen,FLnocopy);
     896        13642 :   switch(m)
     897              :   {
     898        11593 :   case VEC_std:
     899        11593 :     compilenode(tree[yx].x,Gsmall,0);
     900        11593 :     op_push(OCcompo1,mode,y);
     901        11593 :     return;
     902          584 :   case MAT_std:
     903          584 :     compilenode(tree[yx].x,Gsmall,0);
     904          584 :     compilenode(tree[yy].x,Gsmall,0);
     905          584 :     op_push(OCcompo2,mode,y);
     906          584 :     return;
     907           70 :   case MAT_line:
     908           70 :     compilenode(tree[yx].x,Gsmall,0);
     909           70 :     op_push(OCcompoL,0,y);
     910           70 :     compilecast(n,Gvec,mode);
     911           70 :     return;
     912          611 :   case MAT_column:
     913          611 :     compilenode(tree[yy].x,Gsmall,0);
     914          611 :     op_push(OCcompoC,0,y);
     915          611 :     compilecast(n,Gvec,mode);
     916          611 :     return;
     917          784 :   case MAT_range:
     918          784 :     compilenode(tree[yx].x,Gsmall,0);
     919          784 :     compilenode(tree[yx].y,Gsmall,0);
     920          784 :     if (yy==-1)
     921          609 :       op_push(OCcallgen,(long)is_entry("_[_.._]"),n);
     922              :     else
     923              :     {
     924          175 :       compilenode(tree[yy].x,Gsmall,0);
     925          175 :       compilenode(tree[yy].y,Gsmall,0);
     926          175 :       op_push(OCcallgen,(long)is_entry("_[_.._,_.._]"),n);
     927              :     }
     928          784 :     compilecast(n,Gvec,mode);
     929          777 :     return;
     930            0 :   default:
     931            0 :     pari_err_BUG("compilematcoeff");
     932              :   }
     933              : }
     934              : 
     935              : static void
     936     30554273 : compilesmall(long n, long x, long mode)
     937              : {
     938     30554273 :   if (mode==Ggen)
     939     30466145 :     op_push(OCpushstoi, x, n);
     940              :   else
     941              :   {
     942        88128 :     if (mode==Gusmall && x < 0) U_compile_err(tree[n].str);
     943        88128 :     op_push(OCpushlong, x, n);
     944        88128 :     compilecast(n,Gsmall,mode);
     945              :   }
     946     30554266 : }
     947              : 
     948              : static void
     949     15460607 : compilevec(long n, long mode, op_code op)
     950              : {
     951     15460607 :   pari_sp ltop=avma;
     952     15460607 :   long x=tree[n].x;
     953              :   long i;
     954     15460607 :   GEN arg=listtogen(x,Fmatrixelts);
     955     15460607 :   long l=lg(arg);
     956     15460607 :   op_push(op,l,n);
     957     64012348 :   for (i=1;i<l;i++)
     958              :   {
     959     48551741 :     if (tree[arg[i]].f==Fnoarg)
     960            0 :       compile_err("missing vector element",tree[arg[i]].str);
     961     48551741 :     compilenode(arg[i],Ggen,FLsurvive);
     962     48551741 :     op_push(OCstackgen,i,n);
     963              :   }
     964     15460607 :   set_avma(ltop);
     965     15460607 :   op_push(OCpop,1,n);
     966     15460607 :   compilecast(n,Gvec,mode);
     967     15460607 : }
     968              : 
     969              : static void
     970         9687 : compilemat(long n, long mode)
     971              : {
     972         9687 :   pari_sp ltop=avma;
     973         9687 :   long x=tree[n].x;
     974              :   long i,j;
     975         9687 :   GEN line=listtogen(x,Fmatrixlines);
     976         9687 :   long lglin = lg(line), lgcol=0;
     977         9687 :   op_push(OCpushlong, lglin,n);
     978         9687 :   if (lglin==1)
     979         1001 :     op_push(OCmat,1,n);
     980        48052 :   for(i=1;i<lglin;i++)
     981              :   {
     982        38365 :     GEN col=listtogen(line[i],Fmatrixelts);
     983        38365 :     long l=lg(col), k;
     984        38365 :     if (i==1)
     985              :     {
     986         8686 :       lgcol=l;
     987         8686 :       op_push(OCmat,lgcol,n);
     988              :     }
     989        29679 :     else if (l!=lgcol)
     990            0 :       compile_err("matrix must be rectangular",tree[line[i]].str);
     991        38365 :     k=i;
     992       292545 :     for(j=1;j<lgcol;j++)
     993              :     {
     994       254180 :       k-=lglin;
     995       254180 :       if (tree[col[j]].f==Fnoarg)
     996            0 :         compile_err("missing matrix element",tree[col[j]].str);
     997       254180 :       compilenode(col[j], Ggen, FLsurvive);
     998       254180 :       op_push(OCstackgen,k,n);
     999              :     }
    1000              :   }
    1001         9687 :   set_avma(ltop);
    1002         9687 :   op_push(OCpop,1,n);
    1003         9687 :   compilecast(n,Gvec,mode);
    1004         9687 : }
    1005              : 
    1006              : static GEN
    1007        49142 : cattovec(long n, long fnum)
    1008              : {
    1009        49142 :   long x=n, y, i=0, nb;
    1010              :   GEN stack;
    1011        49142 :   if (tree[n].f==Fnoarg) return cgetg(1,t_VECSMALL);
    1012              :   while(1)
    1013          228 :   {
    1014        49370 :     long xx=tree[x].x;
    1015        49370 :     long xy=tree[x].y;
    1016        49370 :     if (tree[x].f!=Ffunction || xx!=fnum) break;
    1017          228 :     x=tree[xy].x;
    1018          228 :     y=tree[xy].y;
    1019          228 :     if (tree[y].f==Fnoarg)
    1020            0 :       compile_err("unexpected character: ", tree[y].str);
    1021          228 :     i++;
    1022              :   }
    1023        49142 :   if (tree[x].f==Fnoarg)
    1024            0 :     compile_err("unexpected character: ", tree[x].str);
    1025        49142 :   nb=i+1;
    1026        49142 :   stack=cgetg(nb+1,t_VECSMALL);
    1027        49370 :   for(x=n;i>0;i--)
    1028              :   {
    1029          228 :     long y=tree[x].y;
    1030          228 :     x=tree[y].x;
    1031          228 :     stack[i+1]=tree[y].y;
    1032              :   }
    1033        49142 :   stack[1]=x;
    1034        49142 :   return stack;
    1035              : }
    1036              : 
    1037              : static GEN
    1038          359 : compilelambda(long y, GEN vep, long nbmvar, struct codepos *pos)
    1039              : {
    1040          359 :   long lev = vep ? lg(vep)-1 : 0;
    1041          359 :   GEN text=cgetg(3,t_VEC);
    1042          359 :   gel(text,1)=strtoGENstr(lev? ((entree*) vep[1])->name: "");
    1043          359 :   gel(text,2)=strntoGENstr(tree[y].str,tree[y].len);
    1044          359 :   dbgstart = tree[y].str;
    1045          359 :   compilenode(y,Ggen,FLsurvive|FLreturn);
    1046          359 :   return getfunction(pos,lev,nbmvar,text,2);
    1047              : }
    1048              : 
    1049              : static void
    1050        23412 : compilecall(long n, int mode, entree *ep)
    1051              : {
    1052        23412 :   pari_sp ltop=avma;
    1053              :   long j;
    1054        23412 :   long x=tree[n].x, tx = tree[x].x;
    1055        23412 :   long y=tree[n].y;
    1056        23412 :   GEN arg=listtogen(y,Flistarg);
    1057        23412 :   long nb=lg(arg)-1;
    1058        23412 :   long lnc=first_safe_arg(arg, COsafelex|COsafedyn);
    1059        23412 :   long lnl=first_safe_arg(arg, COsafelex);
    1060        23412 :   long fl = lnl==0? (lnc==0? FLnocopy: FLnocopylex): 0;
    1061        23412 :   if (ep==NULL)
    1062          329 :     compilenode(x, Ggen, fl);
    1063              :   else
    1064              :   {
    1065        23083 :     long vn=getmvar(ep);
    1066        23083 :     if (vn)
    1067              :     {
    1068          571 :       access_push(vn);
    1069          571 :       op_push(OCpushlex,vn,n);
    1070              :     }
    1071              :     else
    1072        22512 :       op_push(OCpushdyn,(long)ep,n);
    1073              :   }
    1074        63131 :   for (j=1;j<=nb;j++)
    1075              :   {
    1076        39719 :     long x = tree[arg[j]].x, f = tree[arg[j]].f;
    1077        39719 :     if (f==Fseq)
    1078            0 :       compile_err("unexpected ';'", tree[x].str+tree[x].len);
    1079        39719 :     else if (f==Findarg)
    1080              :     {
    1081          126 :       long a = tree[arg[j]].x;
    1082          126 :       entree *ep = getlvalue(a);
    1083          126 :       long vn = getmvar(ep);
    1084          126 :       if (vn)
    1085           49 :         op_push(OCcowvarlex, vn, a);
    1086          126 :       compilenode(a, Ggen,FLnocopy);
    1087          126 :       op_push(OClock,0,n);
    1088        39593 :     } else if (tx==CSTmember)
    1089              :     {
    1090           28 :       compilenode(arg[j], Ggen,FLnocopy);
    1091           28 :       op_push(OClock,0,n);
    1092              :     }
    1093        39565 :     else if (f!=Fnoarg)
    1094        39313 :       compilenode(arg[j], Ggen,j>=lnl?FLnocopylex:0);
    1095              :     else
    1096          252 :       op_push(OCpushlong,0,n);
    1097              :   }
    1098        23412 :   op_push(OCcalluser,nb,x);
    1099        23412 :   compilecast(n,Ggen,mode);
    1100        23412 :   set_avma(ltop);
    1101        23412 : }
    1102              : 
    1103              : static GEN
    1104        20819 : compilefuncinline(long n, long c, long a, long flag, long isif, long lev, long *ev)
    1105              : {
    1106              :   struct codepos pos;
    1107        20819 :   int type=c=='I'?Gvoid:Ggen;
    1108        20819 :   long rflag=c=='I'?0:FLsurvive;
    1109        20819 :   long nbmvar = nblex;
    1110        20819 :   GEN vep = NULL;
    1111        20819 :   if (isif && (flag&FLreturn)) rflag|=FLreturn;
    1112        20819 :   getcodepos(&pos);
    1113        20819 :   if (c=='J') ctxmvar(nbmvar);
    1114        20819 :   if (lev)
    1115              :   {
    1116        12217 :     long i, slev = 0;
    1117        12217 :     GEN varg = cgetg(lev+1,t_VECSMALL);
    1118        12217 :     vep = cgetg(lev+1,t_VECSMALL);
    1119        25246 :     for (i = 1; i <= lev; i++)
    1120              :     {
    1121              :       entree *ve;
    1122        13036 :       long v = ev[i-1];
    1123        13036 :       if (v < 0)
    1124            0 :         compile_err("missing variable name", tree[a].str-1);
    1125        13036 :       ve = getvarvec(v);
    1126        13029 :       vep[i] = (long)ve;
    1127        13029 :       varg[i] = v;
    1128        13029 :       var_push(ve,Lmy);
    1129              :     }
    1130        12210 :     checkdups(varg,vep);
    1131        12210 :     if (c=='J')
    1132          359 :       op_push(OCgetargs,lev,n);
    1133        12210 :     access_push(lev);
    1134        12210 :     frame_push(vep);
    1135        25239 :     for (i = 1; i <= lev; i++)
    1136              :     {
    1137        13029 :       long v = ev[i-1];
    1138        13029 :       if (tree[v].f==Fvec)
    1139              :       {
    1140           35 :         GEN vpar = listtogen(tree[v].x,Fmatrixelts);
    1141           35 :         long k, l, lvv= lg(vpar), vlev = countmatrixelts(tree[v].x);
    1142           35 :         GEN vvep = cgetg(vlev+1,t_VECSMALL);
    1143          119 :         for (k = 1, l = 1; k < lvv; k++)
    1144           84 :           if (tree[vpar[k]].f!=Fnoarg)
    1145              :           {
    1146           77 :             entree *ve = getvar(vpar[k]);
    1147           77 :             vvep[l++]=(long)ve;
    1148           77 :             var_push(ve, Lmy);
    1149              :           }
    1150           35 :         access_push(vlev);
    1151           35 :         op_push(OCnewframe,vlev,v);
    1152           35 :         slev += vlev;
    1153           35 :         op_push(OCpushlex, i-lev-1-slev, v);
    1154           35 :         if (vlev > 1) op_push(OCdup,vlev-1,v);
    1155          119 :         for (k = 1, l = 1; k < lvv; k++)
    1156              :         {
    1157           84 :           long va = vpar[k];
    1158           84 :           if (tree[va].f!=Fnoarg)
    1159              :           {
    1160           77 :             op_push(OCpushlong,k,va);
    1161           77 :             op_push(OCcompo1,Ggen,va);
    1162           77 :             op_push(OCstorelex, (l++)-vlev-1, va);
    1163              :           }
    1164              :         }
    1165           35 :         frame_push(vvep);
    1166              :       }
    1167              :     }
    1168              :   }
    1169        20812 :   if (c=='J')
    1170          359 :     return compilelambda(a,vep,nbmvar,&pos);
    1171        20453 :   if (tree[a].f==Fnoarg)
    1172          119 :     compilecast(a,Gvoid,type);
    1173              :   else
    1174        20334 :     compilenode(a,type,rflag);
    1175        20453 :   return getclosure(&pos, nbmvar);
    1176              : }
    1177              : 
    1178              : static long
    1179         3621 : countvar(GEN arg)
    1180              : {
    1181         3621 :   long i, l = lg(arg);
    1182         3621 :   long n = l-1;
    1183        11078 :   for(i=1; i<l; i++)
    1184              :   {
    1185         7457 :     long a=arg[i];
    1186         7457 :     if (tree[a].f==Fassign)
    1187              :     {
    1188         4207 :       long x = detag(tree[a].x);
    1189         4207 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1190          429 :         n += countmatrixelts(tree[x].x)-1;
    1191              :     }
    1192              :   }
    1193         3621 :   return n;
    1194              : }
    1195              : 
    1196              : static void
    1197            6 : compileuninline(GEN arg)
    1198              : {
    1199              :   long j;
    1200            6 :   if (lg(arg) > 1)
    1201            0 :     compile_err("too many arguments",tree[arg[1]].str);
    1202           18 :   for(j=0; j<s_lvar.n; j++)
    1203           12 :     if(!localvars[j].inl)
    1204            0 :       pari_err(e_MISC,"uninline is only valid at top level");
    1205            6 :   s_lvar.n = 0; nblex = 0;
    1206            6 : }
    1207              : 
    1208              : static void
    1209         3593 : compilemy(GEN arg, const char *str, int inl)
    1210              : {
    1211         3593 :   long i, j, k, l = lg(arg);
    1212         3593 :   long n = countvar(arg);
    1213         3593 :   GEN vep = cgetg(n+1,t_VECSMALL);
    1214         3593 :   GEN ver = cgetg(n+1,t_VECSMALL);
    1215         3593 :   if (inl)
    1216              :   {
    1217           13 :     for(j=0; j<s_lvar.n; j++)
    1218            0 :       if(!localvars[j].inl)
    1219            0 :         pari_err(e_MISC,"inline is only valid at top level");
    1220              :   }
    1221        10994 :   for(k=0, i=1; i<l; i++)
    1222              :   {
    1223         7401 :     long a=arg[i];
    1224         7401 :     if (tree[a].f==Fassign)
    1225              :     {
    1226         4165 :       long x = detag(tree[a].x);
    1227         4165 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1228          415 :       {
    1229          415 :         GEN vars = listtogen(tree[x].x,Fmatrixelts);
    1230          415 :         long nv = lg(vars)-1;
    1231         1385 :         for (j=1; j<=nv; j++)
    1232          970 :           if (tree[vars[j]].f!=Fnoarg)
    1233              :           {
    1234          956 :             ver[++k] = vars[j];
    1235          956 :             vep[k] = (long)getvar(ver[k]);
    1236              :           }
    1237          415 :         continue;
    1238         3750 :       } else ver[++k] = x;
    1239         3236 :     } else ver[++k] = a;
    1240         6986 :     vep[k] = (long)getvar(ver[k]);
    1241              :   }
    1242         3593 :   checkdups(ver,vep);
    1243        11535 :   for(i=1; i<=n; i++) var_push(NULL,Lmy);
    1244         3593 :   op_push_loc(OCnewframe,inl?-n:n,str);
    1245         3593 :   access_push(lg(vep)-1);
    1246         3593 :   frame_push(vep);
    1247        10994 :   for (k=0, i=1; i<l; i++)
    1248              :   {
    1249         7401 :     long a=arg[i];
    1250         7401 :     if (tree[a].f==Fassign)
    1251              :     {
    1252         4165 :       long x = detag(tree[a].x);
    1253         4165 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1254          415 :       {
    1255          415 :         GEN vars = listtogen(tree[x].x,Fmatrixelts);
    1256          415 :         long nv = lg(vars)-1, m = nv;
    1257          415 :         compilenode(tree[a].y,Ggen,FLnocopy);
    1258         1385 :         for (j=1; j<=nv; j++)
    1259          970 :           if (tree[vars[j]].f==Fnoarg) m--;
    1260          415 :         if (m > 1) op_push(OCdup,m-1,x);
    1261         1385 :         for (j=1; j<=nv; j++)
    1262          970 :           if (tree[vars[j]].f!=Fnoarg)
    1263              :           {
    1264          956 :             long v = detag(vars[j]);
    1265          956 :             op_push(OCpushlong,j,v);
    1266          956 :             op_push(OCcompo1,Ggen,v);
    1267          956 :             k++;
    1268          956 :             op_push(OCstorelex,-n+k-1,a);
    1269          956 :             localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k];
    1270          956 :             localvars[s_lvar.n-n+k-1].inl=inl;
    1271              :           }
    1272          415 :         continue;
    1273              :       }
    1274         3750 :       else if (!is_node_zero(tree[a].y))
    1275              :       {
    1276         3602 :         compilenode(tree[a].y,Ggen,FLnocopy);
    1277         3602 :         op_push(OCstorelex,-n+k,a);
    1278              :       }
    1279              :     }
    1280         6986 :     k++;
    1281         6986 :     localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k];
    1282         6986 :     localvars[s_lvar.n-n+k-1].inl=inl;
    1283              :   }
    1284         3593 : }
    1285              : 
    1286              : static long
    1287           70 : localpush(op_code op, long a)
    1288              : {
    1289           70 :   entree *ep = getvardyn(a);
    1290           70 :   long vep  = (long) ep;
    1291           70 :   op_push(op,vep,a);
    1292           70 :   var_push(ep,Llocal);
    1293           70 :   return vep;
    1294              : }
    1295              : 
    1296              : static void
    1297           28 : compilelocal(GEN arg)
    1298              : {
    1299           28 :   long i, j, k, l = lg(arg);
    1300           28 :   long n = countvar(arg);
    1301           28 :   GEN vep = cgetg(n+1,t_VECSMALL);
    1302           28 :   GEN ver = cgetg(n+1,t_VECSMALL);
    1303           84 :   for(k=0, i=1; i<l; i++)
    1304              :   {
    1305           56 :     long a=arg[i];
    1306           56 :     if (tree[a].f==Fassign)
    1307              :     {
    1308           42 :       long x = detag(tree[a].x);
    1309           42 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1310           14 :       {
    1311           14 :         GEN vars = listtogen(tree[x].x,Fmatrixelts);
    1312           14 :         long nv = lg(vars)-1, m = nv;
    1313           14 :         compilenode(tree[a].y,Ggen,FLnocopy);
    1314           56 :         for (j=1; j<=nv; j++)
    1315           42 :           if (tree[vars[j]].f==Fnoarg) m--;
    1316           14 :         if (m > 1) op_push(OCdup,m-1,x);
    1317           56 :         for (j=1; j<=nv; j++)
    1318           42 :           if (tree[vars[j]].f!=Fnoarg)
    1319              :           {
    1320           28 :             long v = detag(vars[j]);
    1321           28 :             op_push(OCpushlong,j,v);
    1322           28 :             op_push(OCcompo1,Ggen,v);
    1323           28 :             vep[++k] = localpush(OClocalvar, v);
    1324           28 :             ver[k] = v;
    1325              :           }
    1326           14 :         continue;
    1327           28 :       } else if (!is_node_zero(tree[a].y))
    1328              :       {
    1329           21 :         compilenode(tree[a].y,Ggen,FLnocopy);
    1330           21 :         ver[++k] = x;
    1331           21 :         vep[k] = localpush(OClocalvar, ver[k]);
    1332           21 :         continue;
    1333              :       }
    1334              :       else
    1335            7 :         ver[++k] = x;
    1336              :     } else
    1337           14 :       ver[++k] = a;
    1338           21 :     vep[k] = localpush(OClocalvar0, ver[k]);
    1339              :   }
    1340           28 :   checkdups(ver,vep);
    1341           28 : }
    1342              : 
    1343              : static void
    1344           41 : compileexport(GEN arg)
    1345              : {
    1346           41 :   long i, l = lg(arg);
    1347           82 :   for (i=1; i<l; i++)
    1348              :   {
    1349           41 :     long a=arg[i];
    1350           41 :     if (tree[a].f==Fassign)
    1351              :     {
    1352           14 :       long x = detag(tree[a].x);
    1353           14 :       long v = (long) getvardyn(x);
    1354           14 :       compilenode(tree[a].y,Ggen,FLnocopy);
    1355           14 :       op_push(OCexportvar,v,x);
    1356              :     } else
    1357              :     {
    1358           27 :       long x = detag(a);
    1359           27 :       long v = (long) getvardyn(x);
    1360           27 :       op_push(OCpushdyn,v,x);
    1361           27 :       op_push(OCexportvar,v,x);
    1362              :     }
    1363              :   }
    1364           41 : }
    1365              : 
    1366              : static void
    1367            6 : compileunexport(GEN arg)
    1368              : {
    1369            6 :   long i, l = lg(arg);
    1370           12 :   for (i=1; i<l; i++)
    1371              :   {
    1372            6 :     long a = arg[i];
    1373            6 :     long x = detag(a);
    1374            6 :     long v = (long) getvardyn(x);
    1375            6 :     op_push(OCunexportvar,v,x);
    1376              :   }
    1377            6 : }
    1378              : 
    1379              : static void
    1380     10771708 : compilefunc(entree *ep, long n, int mode, long flag)
    1381              : {
    1382     10771708 :   pari_sp ltop=avma;
    1383              :   long j;
    1384     10771708 :   long x=tree[n].x, y=tree[n].y;
    1385              :   op_code ret_op;
    1386              :   long ret_flag;
    1387              :   Gtype ret_typ;
    1388              :   char const *p,*q;
    1389              :   char c;
    1390              :   const char *str;
    1391              :   PPproto mod;
    1392     10771708 :   GEN arg=listtogen(y,Flistarg);
    1393     10771708 :   long lnc=first_safe_arg(arg, COsafelex|COsafedyn);
    1394     10771708 :   long lnl=first_safe_arg(arg, COsafelex);
    1395     10771708 :   long nbpointers=0, nbopcodes;
    1396     10771708 :   long nb=lg(arg)-1, lev=0;
    1397              :   long ev[20];
    1398     10771708 :   if (x>=OPnboperator)
    1399       208489 :     str=tree[x].str;
    1400              :   else
    1401              :   {
    1402     10563219 :     if (nb==2)
    1403      1151401 :       str=tree[arg[1]].str+tree[arg[1]].len;
    1404      9411818 :     else if (nb==1)
    1405      9410785 :       str=tree[arg[1]].str;
    1406              :     else
    1407         1033 :       str=tree[n].str;
    1408     10569707 :     while(*str==')') str++;
    1409              :   }
    1410     10771708 :   if (tree[n].f==Fassign)
    1411              :   {
    1412            0 :     nb=2; lnc=2; lnl=2; arg=mkvecsmall2(x,y);
    1413              :   }
    1414     10771708 :   else if (is_func_named(ep,"if"))
    1415              :   {
    1416         4940 :     if (nb>=4)
    1417          112 :       ep=is_entry("_multi_if");
    1418         4828 :     else if (mode==Gvoid)
    1419         3084 :       ep=is_entry("_void_if");
    1420              :   }
    1421     10766768 :   else if (is_func_named(ep,"return") && (flag&FLreturn) && nb<=1)
    1422              :   {
    1423          105 :     if (nb==0) op_push(OCpushgnil,0,n);
    1424          105 :     else compilenode(arg[1],Ggen,FLsurvive|FLreturn);
    1425          105 :     set_avma(ltop);
    1426      9004065 :     return;
    1427              :   }
    1428     10766663 :   else if (is_func_named(ep,"inline"))
    1429              :   {
    1430           13 :     compilemy(arg, str, 1);
    1431           13 :     compilecast(n,Gvoid,mode);
    1432           13 :     set_avma(ltop);
    1433           13 :     return;
    1434              :   }
    1435     10766650 :   else if (is_func_named(ep,"uninline"))
    1436              :   {
    1437            6 :     compileuninline(arg);
    1438            6 :     compilecast(n,Gvoid,mode);
    1439            6 :     set_avma(ltop);
    1440            6 :     return;
    1441              :   }
    1442     10766644 :   else if (is_func_named(ep,"my"))
    1443              :   {
    1444         3580 :     compilemy(arg, str, 0);
    1445         3580 :     compilecast(n,Gvoid,mode);
    1446         3580 :     set_avma(ltop);
    1447         3580 :     return;
    1448              :   }
    1449     10763064 :   else if (is_func_named(ep,"local"))
    1450              :   {
    1451           28 :     compilelocal(arg);
    1452           28 :     compilecast(n,Gvoid,mode);
    1453           28 :     set_avma(ltop);
    1454           28 :     return;
    1455              :   }
    1456     10763036 :   else if (is_func_named(ep,"export"))
    1457              :   {
    1458           41 :     compileexport(arg);
    1459           41 :     compilecast(n,Gvoid,mode);
    1460           41 :     set_avma(ltop);
    1461           41 :     return;
    1462              :   }
    1463     10762995 :   else if (is_func_named(ep,"unexport"))
    1464              :   {
    1465            6 :     compileunexport(arg);
    1466            6 :     compilecast(n,Gvoid,mode);
    1467            6 :     set_avma(ltop);
    1468            6 :     return;
    1469              :   }
    1470              :   /*We generate dummy code for global() for compatibility with gp2c*/
    1471     10762989 :   else if (is_func_named(ep,"global"))
    1472              :   {
    1473              :     long i;
    1474           21 :     for (i=1;i<=nb;i++)
    1475              :     {
    1476           14 :       long a=arg[i];
    1477              :       long en;
    1478           14 :       if (tree[a].f==Fassign)
    1479              :       {
    1480            7 :         compilenode(tree[a].y,Ggen,0);
    1481            7 :         a=tree[a].x;
    1482            7 :         en=(long)getvardyn(a);
    1483            7 :         op_push(OCstoredyn,en,a);
    1484              :       }
    1485              :       else
    1486              :       {
    1487            7 :         en=(long)getvardyn(a);
    1488            7 :         op_push(OCpushdyn,en,a);
    1489            7 :         op_push(OCpop,1,a);
    1490              :       }
    1491              :     }
    1492            7 :     compilecast(n,Gvoid,mode);
    1493            7 :     set_avma(ltop);
    1494            7 :     return;
    1495              :   }
    1496     10762982 :   else if (is_func_named(ep,"O"))
    1497              :   {
    1498         4949 :     if (nb!=1)
    1499            0 :       compile_err("wrong number of arguments", tree[n].str+tree[n].len-1);
    1500         4949 :     ep=is_entry("O(_^_)");
    1501         4949 :     if (tree[arg[1]].f==Ffunction && tree[arg[1]].x==OPpow)
    1502              :     {
    1503         3731 :       arg = listtogen(tree[arg[1]].y,Flistarg);
    1504         3731 :       nb  = lg(arg)-1;
    1505         3731 :       lnc = first_safe_arg(arg,COsafelex|COsafedyn);
    1506         3731 :       lnl = first_safe_arg(arg,COsafelex);
    1507              :     }
    1508              :   }
    1509     10758033 :   else if (x==OPn && tree[y].f==Fsmall)
    1510              :   {
    1511      8995736 :     set_avma(ltop);
    1512      8995736 :     compilesmall(y, -tree[y].x, mode);
    1513      8995736 :     return;
    1514              :   }
    1515      1762297 :   else if (x==OPtrans && tree[y].f==Fvec)
    1516              :   {
    1517         4543 :     set_avma(ltop);
    1518         4543 :     compilevec(y, mode, OCcol);
    1519         4543 :     return;
    1520      1757754 :   } else if(x==OPlength && tree[y].f==Ffunction && tree[y].x==OPtrans)
    1521              :   {
    1522            7 :     arg[1] = tree[y].y;
    1523            7 :     lnc = first_safe_arg(arg,COsafelex|COsafedyn);
    1524            7 :     lnl = first_safe_arg(arg,COsafelex);
    1525            7 :     ep = is_entry("#_~");
    1526              :   }
    1527      1757747 :   else if (x==OPpow && nb==2)
    1528        73937 :   {
    1529        73937 :     long a = arg[2];
    1530        73937 :     if (tree[a].f==Fsmall)
    1531              :     {
    1532        69168 :       if(tree[a].x==2) { nb--; ep=is_entry("sqr"); }
    1533        49640 :       else ep=is_entry("_^s");
    1534              :     }
    1535         4769 :     else if (tree[a].f == Ffunction && tree[a].x == OPn)
    1536              :     {
    1537         1323 :       long ay = tree[a].y;
    1538         1323 :       if (tree[ay].f==Fsmall)
    1539              :       {
    1540         1176 :         if (tree[ay].x==1) {nb--; ep=is_entry("_inv"); }
    1541          798 :         else ep=is_entry("_^s");
    1542              :       }
    1543              :     }
    1544              :   }
    1545      1683810 :   else if (x==OPcat)
    1546            0 :     compile_err("expected character: ',' or ')' instead of",
    1547            0 :         tree[arg[1]].str+tree[arg[1]].len);
    1548      1767643 :   p=ep->code;
    1549      1767643 :   if (!ep->value)
    1550            0 :     compile_err("unknown function",tree[n].str);
    1551      1767643 :   nbopcodes = s_opcode.n;
    1552      1767643 :   ret_op = get_ret_type(&p, ep->arity, &ret_typ, &ret_flag);
    1553      1767643 :   j=1;
    1554      1767643 :   if (*p)
    1555              :   {
    1556      1758413 :     q=p;
    1557      4907830 :     while((mod=parseproto(&p,&c,tree[n].str))!=PPend)
    1558              :     {
    1559      3149466 :       if (j<=nb && tree[arg[j]].f!=Fnoarg
    1560      3037400 :           && (mod==PPdefault || mod==PPdefaultmulti))
    1561        68505 :         mod=PPstd;
    1562      3149466 :       switch(mod)
    1563              :       {
    1564      3022315 :       case PPstd:
    1565      3022315 :         if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1);
    1566      3022315 :         if (c!='I' && c!='E' && c!='J')
    1567              :         {
    1568      3001958 :           long x = tree[arg[j]].x, f = tree[arg[j]].f;
    1569      3001958 :           if (f==Fnoarg)
    1570            0 :             compile_err("missing mandatory argument", tree[arg[j]].str);
    1571      3001958 :           if (f==Fseq)
    1572            0 :             compile_err("unexpected ';'", tree[x].str+tree[x].len);
    1573              :         }
    1574      3022315 :         switch(c)
    1575              :         {
    1576      2901323 :         case 'G':
    1577      2901323 :           compilenode(arg[j],Ggen,j>=lnl?(j>=lnc?FLnocopy:FLnocopylex):0);
    1578      2901323 :           j++;
    1579      2901323 :           break;
    1580          546 :         case 'W':
    1581              :           {
    1582          546 :             long a = tree[arg[j]].f==Findarg ? tree[arg[j]].x: arg[j];
    1583          546 :             entree *ep = getlvalue(a);
    1584          532 :             long vn = getmvar(ep);
    1585          532 :             if (vn)
    1586          224 :               op_push(OCcowvarlex, vn, a);
    1587          308 :             else op_push(OCcowvardyn, (long)ep, a);
    1588          532 :             compilenode(a, Ggen,FLnocopy);
    1589          532 :             j++;
    1590          532 :             break;
    1591              :           }
    1592           84 :         case 'M':
    1593           84 :           if (tree[arg[j]].f!=Fsmall)
    1594              :           {
    1595           35 :             const char *flags = ep->code;
    1596           35 :             flags = strchr(flags, '\n'); /* Skip to the following '\n' */
    1597           35 :             if (!flags)
    1598            0 :               compile_err("missing flag in string function signature",
    1599            0 :                            tree[n].str);
    1600           35 :             flags++;
    1601           35 :             if (tree[arg[j]].f==Fconst && tree[arg[j]].x==CSTstr)
    1602           35 :             {
    1603           35 :               GEN str=strntoGENexp(tree[arg[j]].str,tree[arg[j]].len);
    1604           35 :               op_push(OCpushlong, eval_mnemonic(str, flags),n);
    1605           35 :               j++;
    1606              :             } else
    1607              :             {
    1608            0 :               compilenode(arg[j++],Ggen,FLnocopy);
    1609            0 :               op_push(OCevalmnem,(long)ep,n);
    1610              :             }
    1611           35 :             break;
    1612              :           }
    1613              :         case 'P': case 'L':
    1614        77177 :           compilenode(arg[j++],Gsmall,0);
    1615        77170 :           break;
    1616          221 :         case 'U':
    1617          221 :           compilenode(arg[j++],Gusmall,0);
    1618          214 :           break;
    1619         4016 :         case 'n':
    1620         4016 :           compilenode(arg[j++],Gvar,0);
    1621         4009 :           break;
    1622         2310 :         case '&': case '*':
    1623              :           {
    1624         2310 :             long vn, a=arg[j++];
    1625              :             entree *ep;
    1626         2310 :             if (c=='&')
    1627              :             {
    1628         1533 :               if (tree[a].f!=Frefarg)
    1629            0 :                 compile_err("expected character: '&'", tree[a].str);
    1630         1533 :               a=tree[a].x;
    1631              :             }
    1632         2310 :             a=detag(a);
    1633         2310 :             ep=getlvalue(a);
    1634         2310 :             vn=getmvar(ep);
    1635         2310 :             if (tree[a].f==Fentry)
    1636              :             {
    1637         2105 :               if (vn)
    1638              :               {
    1639          516 :                 access_push(vn);
    1640          516 :                 op_push(OCsimpleptrlex, vn,n);
    1641              :               }
    1642              :               else
    1643         1589 :                 op_push(OCsimpleptrdyn, (long)ep,n);
    1644              :             }
    1645              :             else
    1646              :             {
    1647          205 :               compilenewptr(vn, ep, a);
    1648          205 :               compilelvalue(a);
    1649          205 :               op_push(OCpushptr, 0, a);
    1650              :             }
    1651         2310 :             nbpointers++;
    1652         2310 :             break;
    1653              :           }
    1654        20357 :         case 'I':
    1655              :         case 'E':
    1656              :         case 'J':
    1657              :           {
    1658        20357 :             long a = arg[j++];
    1659        20357 :             GEN  d = compilefuncinline(n, c, a, flag, is_func_named(ep,"if"), lev, ev);
    1660        20350 :             op_push(OCpushgen, data_push(d), a);
    1661        20350 :             if (lg(d)==8) op_push(OCsaveframe,FLsurvive,n);
    1662        20350 :             break;
    1663              :           }
    1664         5579 :         case 'V':
    1665              :           {
    1666         5579 :             long a = arg[j++];
    1667         5579 :             ev[lev++] = a;
    1668         5579 :             break;
    1669              :           }
    1670         6895 :         case '=':
    1671              :           {
    1672         6895 :             long a = arg[j++];
    1673         6895 :             ev[lev++] = tree[a].x;
    1674         6895 :             compilenode(tree[a].y, Ggen, FLnocopy);
    1675              :           }
    1676         6895 :           break;
    1677         1083 :         case 'r':
    1678              :           {
    1679         1083 :             long a=arg[j++];
    1680         1083 :             if (tree[a].f==Fentry)
    1681              :             {
    1682         1020 :               op_push(OCpushgen, data_push(strntoGENstr(tree[tree[a].x].str,
    1683         1020 :                                                         tree[tree[a].x].len)),n);
    1684         1020 :               op_push(OCtostr, -1,n);
    1685              :             }
    1686              :             else
    1687              :             {
    1688           63 :               compilenode(a,Ggen,FLnocopy);
    1689           63 :               op_push(OCtostr, -1,n);
    1690              :             }
    1691         1083 :             break;
    1692              :           }
    1693         2773 :         case 's':
    1694              :           {
    1695         2773 :             long a = arg[j++];
    1696         2773 :             GEN g = cattovec(a, OPcat);
    1697         2773 :             long l, nb = lg(g)-1;
    1698         2773 :             if (nb==1)
    1699              :             {
    1700         2698 :               compilenode(g[1], Ggen, FLnocopy);
    1701         2698 :               op_push(OCtostr, -1, a);
    1702              :             } else
    1703              :             {
    1704           75 :               op_push(OCvec, nb+1, a);
    1705          225 :               for(l=1; l<=nb; l++)
    1706              :               {
    1707          150 :                 compilenode(g[l], Ggen, FLsurvive);
    1708          150 :                 op_push(OCstackgen,l, a);
    1709              :               }
    1710           75 :               op_push(OCpop, 1, a);
    1711           75 :               op_push(OCcallgen,(long)is_entry("Str"), a);
    1712           75 :               op_push(OCtostr, -1, a);
    1713              :             }
    1714         2773 :             break;
    1715              :           }
    1716            0 :         default:
    1717            0 :           pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,
    1718            0 :               tree[x].len, tree[x].str);
    1719              :         }
    1720      3022273 :         break;
    1721        34048 :       case PPauto:
    1722        34048 :         switch(c)
    1723              :         {
    1724        29681 :         case 'p':
    1725        29681 :           op_push(OCprecreal,0,n);
    1726        29681 :           break;
    1727         4312 :         case 'b':
    1728         4312 :           op_push(OCbitprecreal,0,n);
    1729         4312 :           break;
    1730            0 :         case 'P':
    1731            0 :           op_push(OCprecdl,0,n);
    1732            0 :           break;
    1733           55 :         case 'C':
    1734           55 :           op_push(OCpushgen,data_push(pack_localvars()),n);
    1735           55 :           break;
    1736            0 :         case 'f':
    1737              :           {
    1738              :             static long foo;
    1739            0 :             op_push(OCpushlong,(long)&foo,n);
    1740            0 :             break;
    1741              :           }
    1742              :         }
    1743        34048 :         break;
    1744        45065 :       case PPdefault:
    1745        45065 :         j++;
    1746        45065 :         switch(c)
    1747              :         {
    1748         6456 :         case 'E':
    1749              :         case 'I':
    1750              :           {
    1751              :             long i;
    1752         9090 :             for (i = 0; i<lev; i++)
    1753         2641 :               if (ev[i]>=0) getvar(ev[i]);
    1754              :           }
    1755              :         case 'G': /*FALLTHROUGH*/
    1756              :         case '&':
    1757              :         case 'r':
    1758              :         case 's':
    1759        34702 :           op_push(OCpushlong,0,n);
    1760        34702 :           break;
    1761         9055 :         case 'n':
    1762         9055 :           op_push(OCpushlong,-1,n);
    1763         9055 :           break;
    1764          958 :         case 'V':
    1765          958 :           ev[lev++] = -1;
    1766          958 :           break;
    1767          343 :         case 'P':
    1768          343 :           op_push(OCprecdl,0,n);
    1769          343 :           break;
    1770            0 :         default:
    1771            0 :           pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,
    1772            0 :               tree[x].len, tree[x].str);
    1773              :         }
    1774        45058 :         break;
    1775        32515 :       case PPdefaultmulti:
    1776        32515 :         j++;
    1777        32515 :         switch(c)
    1778              :         {
    1779            0 :         case 'G':
    1780            0 :           op_push(OCpushstoi,strtol(q+1,NULL,10),n);
    1781            0 :           break;
    1782        32426 :         case 'L':
    1783              :         case 'M':
    1784        32426 :           op_push(OCpushlong,strtol(q+1,NULL,10),n);
    1785        32426 :           break;
    1786           42 :         case 'U':
    1787           42 :           op_push(OCpushlong,(long)strtoul(q+1,NULL,10),n);
    1788           42 :           break;
    1789           47 :         case 'r':
    1790              :         case 's':
    1791           47 :           str_defproto(p, q, tree[n].str);
    1792           47 :           op_push(OCtostr, -1, n);
    1793           47 :           break;
    1794            0 :         default:
    1795            0 :           pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,
    1796            0 :               tree[x].len, tree[x].str);
    1797              :         }
    1798        32515 :         break;
    1799        15523 :       case PPstar:
    1800        15523 :         switch(c)
    1801              :         {
    1802          112 :         case 'E':
    1803              :           {
    1804          112 :             long k, n=nb+1-j;
    1805          112 :             GEN g=cgetg(n+1,t_VEC);
    1806          112 :             int ismif = is_func_named(ep,"_multi_if");
    1807          574 :             for(k=1; k<=n; k++)
    1808          528 :               gel(g, k) = compilefuncinline(n, c, arg[j+k-1], flag,
    1809          462 :                           ismif && (k==n || odd(k)), lev, ev);
    1810          112 :             op_push(OCpushgen, data_push(g), arg[j]);
    1811          112 :             j=nb+1;
    1812          112 :             break;
    1813              :           }
    1814        15411 :         case 's':
    1815              :           {
    1816        15411 :             long n=nb+1-j;
    1817              :             long k,l,l1,m;
    1818        15411 :             GEN g=cgetg(n+1,t_VEC);
    1819        37209 :             for(l1=0,k=1;k<=n;k++)
    1820              :             {
    1821        21798 :               gel(g,k)=cattovec(arg[j+k-1],OPcat);
    1822        21798 :               l1+=lg(gel(g,k))-1;
    1823              :             }
    1824        15411 :             op_push_loc(OCvec, l1+1, str);
    1825        37209 :             for(m=1,k=1;k<=n;k++)
    1826        43635 :               for(l=1;l<lg(gel(g,k));l++,m++)
    1827              :               {
    1828        21837 :                 compilenode(mael(g,k,l),Ggen,FLsurvive);
    1829        21837 :                 op_push(OCstackgen,m,mael(g,k,l));
    1830              :               }
    1831        15411 :             op_push_loc(OCpop, 1, str);
    1832        15411 :             j=nb+1;
    1833        15411 :             break;
    1834              :           }
    1835            0 :         default:
    1836            0 :           pari_err(e_MISC,"Unknown prototype code `%c*' for `%.*s'",c,
    1837            0 :               tree[x].len, tree[x].str);
    1838              :         }
    1839        15523 :         break;
    1840            0 :       default:
    1841            0 :         pari_err_BUG("compilefunc [unknown PPproto]");
    1842              :       }
    1843      3149417 :       q=p;
    1844              :     }
    1845              :   }
    1846      1767594 :   if (j<=nb)
    1847            0 :     compile_err("too many arguments",tree[arg[j]].str);
    1848      1767594 :   op_push_loc(ret_op, (long) ep, str);
    1849      1767594 :   if (mode==Ggen && (ret_flag&FLnocopy) && !(flag&FLnocopy))
    1850        10709 :     op_push_loc(OCcopy,0,str);
    1851      1767594 :   if (ret_typ==Ggen && nbpointers==0 && s_opcode.n>nbopcodes+128)
    1852              :   {
    1853         3052 :     op_insert_loc(nbopcodes,OCavma,0,str);
    1854         3052 :     op_push_loc(OCgc,0,str);
    1855              :   }
    1856      1767594 :   compilecast(n,ret_typ,mode);
    1857      1767594 :   if (nbpointers) op_push_loc(OCendptr,nbpointers, str);
    1858      1767594 :   set_avma(ltop);
    1859              : }
    1860              : 
    1861              : static void
    1862      9146850 : genclosurectx(const char *loc, long nbdata)
    1863              : {
    1864              :   long i;
    1865      9146850 :   GEN vep = cgetg(nbdata+1,t_VECSMALL);
    1866     32822441 :   for(i = 1; i <= nbdata; i++)
    1867              :   {
    1868     23675614 :     vep[i] = 0;
    1869     23675614 :     op_push_loc(OCpushlex,-i,loc);
    1870              :   }
    1871      9146827 :   frame_push(vep);
    1872      9146919 : }
    1873              : 
    1874              : static GEN
    1875      9157657 : genclosure(entree *ep, const char *loc, long nbdata, int check)
    1876              : {
    1877              :   struct codepos pos;
    1878      9157657 :   long nb=0;
    1879      9157657 :   const char *code=ep->code,*p,*q;
    1880              :   char c;
    1881              :   GEN text;
    1882      9157657 :   long index=ep->arity;
    1883      9157657 :   long arity=0, maskarg=0, maskarg0=0, stop=0, dovararg=0;
    1884              :   PPproto mod;
    1885              :   Gtype ret_typ;
    1886              :   long ret_flag;
    1887      9157657 :   op_code ret_op=get_ret_type(&code,ep->arity,&ret_typ,&ret_flag);
    1888      9157633 :   p=code;
    1889     41991125 :   while ((mod=parseproto(&p,&c,NULL))!=PPend)
    1890              :   {
    1891     32833492 :     if (mod==PPauto)
    1892         2066 :       stop=1;
    1893              :     else
    1894              :     {
    1895     32831426 :       if (stop) return NULL;
    1896     32831426 :       if (c=='V') continue;
    1897     32831426 :       maskarg<<=1; maskarg0<<=1; arity++;
    1898     32831426 :       switch(mod)
    1899              :       {
    1900     32830206 :       case PPstd:
    1901     32830206 :         maskarg|=1L;
    1902     32830206 :         break;
    1903          482 :       case PPdefault:
    1904          482 :         switch(c)
    1905              :         {
    1906           28 :         case '&':
    1907              :         case 'E':
    1908              :         case 'I':
    1909           28 :           maskarg0|=1L;
    1910           28 :           break;
    1911              :         }
    1912          482 :         break;
    1913          738 :       default:
    1914          738 :         break;
    1915              :       }
    1916              :     }
    1917              :   }
    1918      9157568 :   if (check && EpSTATIC(ep) && maskarg==0)
    1919         8919 :     return gen_0;
    1920      9148649 :   getcodepos(&pos);
    1921      9148678 :   dbgstart = loc;
    1922      9148678 :   if (nbdata > arity)
    1923            0 :     pari_err(e_MISC,"too many parameters for closure `%s'", ep->name);
    1924      9148678 :   if (nbdata) genclosurectx(loc, nbdata);
    1925      9148738 :   text = strtoGENstr(ep->name);
    1926      9148669 :   arity -= nbdata;
    1927      9148669 :   if (maskarg)  op_push_loc(OCcheckargs,maskarg,loc);
    1928      9148631 :   if (maskarg0) op_push_loc(OCcheckargs0,maskarg0,loc);
    1929      9148632 :   p=code;
    1930     41980127 :   while ((mod=parseproto(&p,&c,NULL))!=PPend)
    1931              :   {
    1932     32831470 :     switch(mod)
    1933              :     {
    1934          666 :     case PPauto:
    1935          666 :       switch(c)
    1936              :       {
    1937          666 :       case 'p':
    1938          666 :         op_push_loc(OCprecreal,0,loc);
    1939          666 :         break;
    1940            0 :       case 'b':
    1941            0 :         op_push_loc(OCbitprecreal,0,loc);
    1942            0 :         break;
    1943            0 :       case 'P':
    1944            0 :         op_push_loc(OCprecdl,0,loc);
    1945            0 :         break;
    1946            0 :       case 'C':
    1947            0 :         op_push_loc(OCpushgen,data_push(pack_localvars()),loc);
    1948           25 :         break;
    1949            0 :       case 'f':
    1950              :         {
    1951              :           static long foo;
    1952            0 :           op_push_loc(OCpushlong,(long)&foo,loc);
    1953            0 :           break;
    1954              :         }
    1955              :       }
    1956              :     default:
    1957     32831495 :       break;
    1958              :     }
    1959              :   }
    1960      9148638 :   q = p = code;
    1961     41980104 :   while ((mod=parseproto(&p,&c,NULL))!=PPend)
    1962              :   {
    1963     32831466 :     switch(mod)
    1964              :     {
    1965     32830033 :     case PPstd:
    1966     32830033 :       switch(c)
    1967              :       {
    1968     32785606 :       case 'G':
    1969     32785606 :         break;
    1970        32909 :       case 'M':
    1971              :       case 'L':
    1972        32909 :         op_push_loc(OCitos,-index,loc);
    1973        32909 :         break;
    1974        11479 :       case 'U':
    1975        11479 :         op_push_loc(OCitou,-index,loc);
    1976        11479 :         break;
    1977            0 :       case 'n':
    1978            0 :         op_push_loc(OCvarn,-index,loc);
    1979            0 :         break;
    1980            0 :       case '&': case '*':
    1981              :       case 'I':
    1982              :       case 'E':
    1983              :       case 'V':
    1984              :       case '=':
    1985            0 :         return NULL;
    1986           36 :       case 'r':
    1987              :       case 's':
    1988           36 :         op_push_loc(OCtostr,-index,loc);
    1989           36 :         break;
    1990              :       }
    1991     32830033 :       break;
    1992          666 :     case PPauto:
    1993          666 :       break;
    1994          412 :     case PPdefault:
    1995          412 :       switch(c)
    1996              :       {
    1997          216 :       case 'G':
    1998              :       case '&':
    1999              :       case 'E':
    2000              :       case 'I':
    2001              :       case 'V':
    2002          216 :         break;
    2003           14 :       case 'r':
    2004              :       case 's':
    2005           14 :         op_push_loc(OCtostr,-index,loc);
    2006           14 :         break;
    2007          112 :       case 'n':
    2008          112 :         op_push_loc(OCvarn,-index,loc);
    2009          112 :         break;
    2010           70 :       case 'P':
    2011           70 :         op_push_loc(OCprecdl,0,loc);
    2012           70 :         op_push_loc(OCdefaultlong,-index,loc);
    2013           70 :         break;
    2014            0 :       default:
    2015            0 :         pari_err(e_MISC,"Unknown prototype code `D%c' for `%s'",c,ep->name);
    2016              :       }
    2017          412 :       break;
    2018          327 :     case PPdefaultmulti:
    2019          327 :       switch(c)
    2020              :       {
    2021            0 :       case 'G':
    2022            0 :         op_push_loc(OCpushstoi,strtol(q+1,NULL,10),loc);
    2023            0 :         op_push_loc(OCdefaultgen,-index,loc);
    2024            0 :         break;
    2025          319 :       case 'L':
    2026              :       case 'M':
    2027          319 :         op_push_loc(OCpushlong,strtol(q+1,NULL,10),loc);
    2028          319 :         op_push_loc(OCdefaultlong,-index,loc);
    2029          319 :         break;
    2030            0 :       case 'U':
    2031            0 :         op_push_loc(OCpushlong,(long)strtoul(q+1,NULL,10),loc);
    2032            0 :         op_push_loc(OCdefaultulong,-index,loc);
    2033            0 :         break;
    2034            8 :       case 'r':
    2035              :       case 's':
    2036            8 :         str_defproto(p, q, loc);
    2037            8 :         op_push_loc(OCdefaultgen,-index,loc);
    2038            8 :         op_push_loc(OCtostr,-index,loc);
    2039            8 :         break;
    2040            0 :       default:
    2041            0 :         pari_err(e_MISC,
    2042              :             "Unknown prototype code `D...,%c,' for `%s'",c,ep->name);
    2043              :       }
    2044          327 :       break;
    2045           28 :     case PPstar:
    2046           28 :       switch(c)
    2047              :       {
    2048           28 :       case 's':
    2049           28 :         dovararg = 1;
    2050           28 :         break;
    2051            0 :       case 'E':
    2052            0 :         return NULL;
    2053            0 :       default:
    2054            0 :         pari_err(e_MISC,"Unknown prototype code `%c*' for `%s'",c,ep->name);
    2055              :       }
    2056           28 :       break;
    2057            0 :     default:
    2058            0 :       return NULL;
    2059              :     }
    2060     32831466 :     index--;
    2061     32831466 :     q = p;
    2062              :   }
    2063      9148599 :   op_push_loc(ret_op, (long) ep, loc);
    2064      9148662 :   if (ret_flag==FLnocopy) op_push_loc(OCcopy,0,loc);
    2065      9148662 :   compilecast_loc(ret_typ, Ggen, loc);
    2066      9148655 :   if (dovararg) nb|=VARARGBITS;
    2067      9148655 :   return getfunction(&pos,nb+arity,nbdata,text,0);
    2068              : }
    2069              : 
    2070              : GEN
    2071      9145218 : snm_closure(entree *ep, GEN data)
    2072              : {
    2073      9145218 :   long i, n = data ? lg(data)-1: 0;
    2074      9145218 :   GEN C = genclosure(ep,ep->name,n,0);
    2075     32814240 :   for(i = 1; i <= n; i++) gmael(C,7,i) = gel(data,i);
    2076      9145211 :   return C;
    2077              : }
    2078              : 
    2079              : GEN
    2080         1820 : strtoclosure(const char *s, long n,  ...)
    2081              : {
    2082         1820 :   pari_sp av = avma;
    2083         1820 :   entree *ep = is_entry(s);
    2084              :   GEN C;
    2085         1820 :   if (!ep) pari_err(e_NOTFUNC, strtoGENstr(s));
    2086         1820 :   ep = do_alias(ep);
    2087         1820 :   if ((!EpSTATIC(ep) && EpVALENCE(ep)!=EpINSTALL) || !ep->value)
    2088            0 :     pari_err(e_MISC,"not a built-in/install'ed function: \"%s\"",s);
    2089         1820 :   C = genclosure(ep,ep->name,n,0);
    2090         1820 :   if (!C) pari_err(e_MISC,"function prototype unsupported: \"%s\"",s);
    2091              :   else
    2092              :   {
    2093              :     va_list ap;
    2094              :     long i;
    2095         1820 :     va_start(ap,n);
    2096         8624 :     for(i = 1; i <= n; i++) gmael(C,7,i) = va_arg(ap, GEN);
    2097         1820 :     va_end(ap);
    2098              :   }
    2099         1820 :   return gc_GEN(av, C);
    2100              : }
    2101              : 
    2102              : GEN
    2103            0 : closuretoinl(GEN C)
    2104              : {
    2105            0 :   long i, n = closure_arity(C);
    2106            0 :   GEN text = closure_get_text(C);
    2107              :   struct codepos pos;
    2108              :   const char *loc;
    2109            0 :   getcodepos(&pos);
    2110            0 :   if (typ(text)==t_VEC) text = gel(text, 2);
    2111            0 :   loc = GSTR(text);
    2112            0 :   dbgstart = loc;
    2113            0 :   op_push_loc(OCpushgen, data_push(C), loc);
    2114            0 :   for (i = n; i >= 1 ; i--)
    2115            0 :     op_push_loc(OCpushlex, -i, loc);
    2116            0 :   op_push_loc(OCcalluser, n, loc);
    2117            0 :   return getfunction(&pos,0,0,text,0);
    2118              : }
    2119              : 
    2120              : GEN
    2121          119 : strtofunction(const char *s) { return strtoclosure(s, 0); }
    2122              : 
    2123              : GEN
    2124           28 : call0(GEN fun, GEN args)
    2125              : {
    2126           28 :   if (!is_vec_t(typ(args))) pari_err_TYPE("call",args);
    2127           28 :   switch(typ(fun))
    2128              :   {
    2129            7 :     case t_STR:
    2130            7 :       fun = strtofunction(GSTR(fun));
    2131           28 :     case t_CLOSURE: /* fall through */
    2132           28 :       return closure_callgenvec(fun, args);
    2133            0 :     default:
    2134            0 :       pari_err_TYPE("call", fun);
    2135              :       return NULL; /* LCOV_EXCL_LINE */
    2136              :   }
    2137              : }
    2138              : 
    2139              : static void
    2140        10618 : closurefunc(entree *ep, long n, long mode)
    2141              : {
    2142        10618 :   pari_sp ltop=avma;
    2143              :   GEN C;
    2144        10618 :   if (!ep->value) compile_err("unknown function",tree[n].str);
    2145        10618 :   C = genclosure(ep,tree[n].str,0,1);
    2146        10618 :   if (!C) compile_err("sorry, closure not implemented",tree[n].str);
    2147        10618 :   if (C==gen_0)
    2148              :   {
    2149         8919 :     compilefunc(ep,n,mode,0);
    2150         8919 :     return;
    2151              :   }
    2152         1699 :   op_push(OCpushgen, data_push(C), n);
    2153         1699 :   compilecast(n,Gclosure,mode);
    2154         1699 :   set_avma(ltop);
    2155              : }
    2156              : 
    2157              : static void
    2158        15308 : compileseq(long n, int mode, long flag)
    2159              : {
    2160        15308 :   pari_sp av = avma;
    2161        15308 :   GEN L = listtogen(n, Fseq);
    2162        15308 :   long i, l = lg(L)-1;
    2163        48676 :   for(i = 1; i < l; i++)
    2164        33368 :     compilenode(L[i],Gvoid,0);
    2165        15308 :   compilenode(L[l],mode,flag&(FLreturn|FLsurvive));
    2166        15308 :   set_avma(av);
    2167        15308 : }
    2168              : 
    2169              : static void
    2170     52957634 : compilenode(long n, int mode, long flag)
    2171              : {
    2172              :   long x,y;
    2173              : #ifdef STACK_CHECK
    2174     52957634 :   if (PARI_stack_limit && (void*) &x <= PARI_stack_limit)
    2175            0 :     pari_err(e_MISC, "expression nested too deeply");
    2176              : #endif
    2177     52957634 :   if (n<0) pari_err_BUG("compilenode");
    2178     52957634 :   x=tree[n].x;
    2179     52957634 :   y=tree[n].y;
    2180              : 
    2181     52957634 :   switch(tree[n].f)
    2182              :   {
    2183        15308 :   case Fseq:
    2184        15308 :     compileseq(n, mode, flag);
    2185     52957564 :     return;
    2186        13642 :   case Fmatcoeff:
    2187        13642 :     compilematcoeff(n,mode);
    2188        13635 :     if (mode==Ggen && !(flag&FLnocopy))
    2189         4289 :       op_push(OCcopy,0,n);
    2190        13635 :     return;
    2191        45999 :   case Fassign:
    2192        45999 :     x = detag(x);
    2193        45999 :     if (tree[x].f==Fvec && tree[x].x>=0)
    2194          812 :     {
    2195          812 :       GEN vars = listtogen(tree[x].x,Fmatrixelts);
    2196          812 :       long i, l = lg(vars)-1, d = mode==Gvoid? l-1: l;
    2197          812 :       compilenode(y,Ggen,mode==Gvoid?0:flag&FLsurvive);
    2198         2541 :       for (i=1; i<=l; i++)
    2199         1729 :         if (tree[vars[i]].f==Fnoarg) d--;
    2200          812 :       if (d) op_push(OCdup, d, x);
    2201         2541 :       for(i=1; i<=l; i++)
    2202         1729 :         if (tree[vars[i]].f!=Fnoarg)
    2203              :         {
    2204         1715 :           long a = detag(vars[i]);
    2205         1715 :           entree *ep=getlvalue(a);
    2206         1715 :           long vn=getmvar(ep);
    2207         1715 :           op_push(OCpushlong,i,a);
    2208         1715 :           op_push(OCcompo1,Ggen,a);
    2209         1715 :           if (tree[a].f==Fentry)
    2210         1708 :             compilestore(vn,ep,n);
    2211              :           else
    2212              :           {
    2213            7 :             compilenewptr(vn,ep,n);
    2214            7 :             compilelvalue(a);
    2215            7 :             op_push(OCstoreptr,0,a);
    2216              :           }
    2217              :         }
    2218          812 :       if (mode!=Gvoid)
    2219          469 :         compilecast(n,Ggen,mode);
    2220              :     }
    2221              :     else
    2222              :     {
    2223        45187 :       entree *ep=getlvalue(x);
    2224        45187 :       long vn=getmvar(ep);
    2225        45187 :       if (tree[x].f!=Fentry)
    2226              :       {
    2227          637 :         compilenewptr(vn,ep,n);
    2228          637 :         compilelvalue(x);
    2229              :       }
    2230        45187 :       compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive);
    2231        45187 :       if (mode!=Gvoid)
    2232        29843 :         op_push(OCdup,1,n);
    2233        45187 :       if (tree[x].f==Fentry)
    2234        44550 :         compilestore(vn,ep,n);
    2235              :       else
    2236          637 :         op_push(OCstoreptr,0,x);
    2237        45187 :       if (mode!=Gvoid)
    2238        29843 :         compilecast(n,Ggen,mode);
    2239              :     }
    2240        45999 :     return;
    2241      4775677 :   case Fconst:
    2242              :     {
    2243      4775677 :       pari_sp ltop=avma;
    2244      4775677 :       if (tree[n].x!=CSTquote)
    2245              :       {
    2246      4771841 :         if (mode==Gvoid) return;
    2247      4771841 :         if (mode==Gvar) compile_varerr(tree[n].str);
    2248              :       }
    2249      4775677 :       if (mode==Gsmall) L_compile_err(tree[n].str);
    2250      4775677 :       if (mode==Gusmall && tree[n].x != CSTint) U_compile_err(tree[n].str);
    2251      4775670 :       switch(tree[n].x)
    2252              :       {
    2253         6294 :       case CSTreal:
    2254         6294 :         op_push(OCpushreal, data_push(strntoGENstr(tree[n].str,tree[n].len)),n);
    2255         6294 :         break;
    2256       943222 :       case CSTint:
    2257       943222 :         op_push(OCpushgen,  data_push(strtoi((char*)tree[n].str)),n);
    2258       943222 :         compilecast(n,Ggen, mode);
    2259       943222 :         break;
    2260      3822318 :       case CSTstr:
    2261      3822318 :         op_push(OCpushgen,  data_push(strntoGENexp(tree[n].str,tree[n].len)),n);
    2262      3822318 :         break;
    2263         3836 :       case CSTquote:
    2264              :         { /* skip ' */
    2265         3836 :           entree *ep = fetch_entry_raw(tree[n].str+1,tree[n].len-1);
    2266         3836 :           if (EpSTATIC(ep)) compile_varerr(tree[n].str+1);
    2267         3836 :           op_push(OCpushvar, (long)ep,n);
    2268         3836 :           compilecast(n,Ggen, mode);
    2269         3836 :           break;
    2270              :         }
    2271            0 :       default:
    2272            0 :         pari_err_BUG("compilenode, unsupported constant");
    2273              :       }
    2274      4775670 :       set_avma(ltop);
    2275      4775670 :       return;
    2276              :     }
    2277     21558537 :   case Fsmall:
    2278     21558537 :     compilesmall(n, x, mode);
    2279     21558530 :     return;
    2280     15456064 :   case Fvec:
    2281     15456064 :     compilevec(n, mode, OCvec);
    2282     15456064 :     return;
    2283         9687 :   case Fmat:
    2284         9687 :     compilemat(n, mode);
    2285         9687 :     return;
    2286            0 :   case Frefarg:
    2287            0 :     compile_err("unexpected character '&':",tree[n].str);
    2288            0 :     return;
    2289            0 :   case Findarg:
    2290            0 :     compile_err("unexpected character '~':",tree[n].str);
    2291            0 :     return;
    2292       286804 :   case Fentry:
    2293              :     {
    2294       286804 :       entree *ep=getentry(n);
    2295       286804 :       long vn=getmvar(ep);
    2296       286804 :       if (vn)
    2297              :       {
    2298        73662 :         access_push(vn);
    2299        73662 :         op_push(OCpushlex,(long)vn,n);
    2300        73662 :         addcopy(n,mode,flag,FLnocopy|FLnocopylex);
    2301        73662 :         compilecast(n,Ggen,mode);
    2302              :       }
    2303       213142 :       else if (ep->valence==EpVAR || ep->valence==EpNEW)
    2304              :       {
    2305       202524 :         if (DEBUGLEVEL && mode==Gvoid)
    2306            0 :           pari_warn(warner,"statement with no effect: `%s'",ep->name);
    2307       202524 :         op_push(OCpushdyn,(long)ep,n);
    2308       202524 :         addcopy(n,mode,flag,FLnocopy);
    2309       202524 :         compilecast(n,Ggen,mode);
    2310              :       }
    2311              :       else
    2312        10618 :         closurefunc(ep,n,mode);
    2313       286804 :       return;
    2314              :     }
    2315     10785872 :   case Ffunction:
    2316              :     {
    2317     10785872 :       entree *ep=getfunc(n);
    2318     10785872 :       if (getmvar(ep) || EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)
    2319              :       {
    2320        23083 :         if (tree[n].x<OPnboperator) /* should not happen */
    2321            0 :           compile_err("operator unknown",tree[n].str);
    2322        23083 :         compilecall(n,mode,ep);
    2323              :       }
    2324              :       else
    2325     10762789 :         compilefunc(ep,n,mode,flag);
    2326     10785823 :       return;
    2327              :     }
    2328          329 :   case Fcall:
    2329          329 :     compilecall(n,mode,NULL);
    2330          329 :     return;
    2331         9428 :   case Flambda:
    2332              :     {
    2333         9428 :       pari_sp ltop=avma;
    2334              :       struct codepos pos;
    2335         9428 :       GEN arg=listtogen(x,Flistarg);
    2336         9428 :       long nb, lgarg, nbmvar, dovararg=0, gap;
    2337         9428 :       long strict = GP_DATA->strictargs;
    2338         9428 :       GEN vep = cgetg_copy(arg, &lgarg);
    2339         9428 :       GEN text=cgetg(3,t_VEC);
    2340         9428 :       gel(text,1)=strntoGENstr(tree[x].str,tree[x].len);
    2341         9428 :       if (lgarg==2 && tree[x].str[0]!='~' && tree[x].f==Findarg)
    2342              :         /* This occurs for member functions */
    2343           14 :         gel(text,1)=shallowconcat(strntoGENstr("~",1),gel(text,1));
    2344         9428 :       gel(text,2)=strntoGENstr(tree[y].str,tree[y].len);
    2345         9428 :       getcodepos(&pos);
    2346         9428 :       dbgstart=tree[x].str+tree[x].len;
    2347         9428 :       gap = tree[y].str-dbgstart;
    2348         9428 :       nbmvar = nblex;
    2349         9428 :       ctxmvar(nbmvar);
    2350         9428 :       nb = lgarg-1;
    2351         9428 :       if (nb)
    2352              :       {
    2353              :         long i;
    2354        13821 :         for(i=1;i<=nb;i++)
    2355              :         {
    2356         8495 :           long a = arg[i], f = tree[a].f;
    2357         8495 :           if (i==nb && f==Fvararg)
    2358              :           {
    2359           21 :             dovararg=1;
    2360           21 :             vep[i]=(long)getvar(tree[a].x);
    2361              :           }
    2362              :           else
    2363         8474 :             vep[i]=(long)getvar(f==Fassign||f==Findarg?tree[a].x:a);
    2364         8495 :           var_push(NULL,Lmy);
    2365              :         }
    2366         5326 :         checkdups(arg,vep);
    2367         5326 :         op_push(OCgetargs,nb,x);
    2368         5326 :         access_push(lg(vep)-1);
    2369         5326 :         frame_push(vep);
    2370        13821 :         for (i=1;i<=nb;i++)
    2371              :         {
    2372         8495 :           long a = arg[i], f = tree[a].f;
    2373         8495 :           long y = tree[a].y;
    2374         8495 :           if (f==Fassign && (strict || !is_node_zero(y)))
    2375              :           {
    2376          391 :             if (tree[y].f==Fsmall)
    2377          294 :               compilenode(y, Ggen, 0);
    2378              :             else
    2379              :             {
    2380              :               struct codepos lpos;
    2381           97 :               long nbmvar = nblex;
    2382           97 :               getcodepos(&lpos);
    2383           97 :               compilenode(y, Ggen, 0);
    2384           97 :               op_push(OCpushgen, data_push(getclosure(&lpos,nbmvar)),a);
    2385              :             }
    2386          391 :             op_push(OCdefaultarg,-nb+i-1,a);
    2387         8104 :           } else if (f==Findarg)
    2388           84 :             op_push(OCsetref, -nb+i-1, a);
    2389         8495 :           localvars[s_lvar.n-nb+i-1].ep=(entree*)vep[i];
    2390              :         }
    2391              :       }
    2392         9428 :       if (strict)
    2393           21 :         op_push(OCcheckuserargs,nb,x);
    2394         9428 :       dbgstart=tree[y].str;
    2395         9428 :       if (y>=0 && tree[y].f!=Fnoarg)
    2396         9428 :         compilenode(y,Ggen,FLsurvive|FLreturn);
    2397              :       else
    2398            0 :         compilecast(n,Gvoid,Ggen);
    2399         9428 :       if (dovararg) nb|=VARARGBITS;
    2400         9428 :       op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text,gap)),n);
    2401         9428 :       if (nbmvar) op_push(OCsaveframe,!!(flag&FLsurvive),n);
    2402         9428 :       compilecast(n, Gclosure, mode);
    2403         9428 :       set_avma(ltop);
    2404         9428 :       return;
    2405              :     }
    2406            0 :   case Ftag:
    2407            0 :     compilenode(x, mode,flag);
    2408            0 :     return;
    2409            7 :   case Fnoarg:
    2410            7 :     compilecast(n,Gvoid,mode);
    2411            7 :     return;
    2412          280 :   case Fnorange:
    2413          280 :     op_push(OCpushlong,LONG_MAX,n);
    2414          280 :     compilecast(n,Gsmall,mode);
    2415          280 :     return;
    2416            0 :   default:
    2417            0 :     pari_err_BUG("compilenode");
    2418              :   }
    2419              : }
    2420              : 
    2421              : GEN
    2422       937509 : gp_closure(long n)
    2423              : {
    2424              :   struct codepos pos;
    2425       937509 :   getcodepos(&pos);
    2426       937509 :   dbgstart=tree[n].str;
    2427       937509 :   compilenode(n,Ggen,FLsurvive|FLreturn);
    2428       937460 :   return getfunction(&pos,0,0,strntoGENstr(tree[n].str,tree[n].len),0);
    2429              : }
    2430              : 
    2431              : GEN
    2432          112 : closure_derivn(GEN G, long n)
    2433              : {
    2434          112 :   pari_sp ltop = avma;
    2435              :   struct codepos pos;
    2436          112 :   long arity = closure_arity(G);
    2437              :   const char *code;
    2438              :   GEN t, text;
    2439              : 
    2440          112 :   if (arity == 0 || closure_is_variadic(G)) pari_err_TYPE("derivfun",G);
    2441          112 :   t = closure_get_text(G);
    2442          112 :   code = GSTR((typ(t) == t_STR)? t: GENtoGENstr(G));
    2443          112 :   if (n > 1)
    2444              :   {
    2445           49 :     text = cgetg(1+nchar2nlong(9+strlen(code)+n),t_STR);
    2446           49 :     sprintf(GSTR(text), "derivn(%s,%ld)", code, n);
    2447              :   }
    2448              :   else
    2449              :   {
    2450           63 :     text = cgetg(1+nchar2nlong(4+strlen(code)),t_STR);
    2451           63 :     sprintf(GSTR(text), (typ(t) == t_STR)? "%s'": "(%s)'",code);
    2452              :   }
    2453          112 :   getcodepos(&pos);
    2454          112 :   dbgstart = code;
    2455          112 :   op_push_loc(OCpackargs, arity, code);
    2456          112 :   op_push_loc(OCpushgen, data_push(G), code);
    2457          112 :   op_push_loc(OCpushlong, n, code);
    2458          112 :   op_push_loc(OCprecreal, 0, code);
    2459          112 :   op_push_loc(OCcallgen, (long)is_entry("_derivfun"), code);
    2460          112 :   return gc_GEN(ltop, getfunction(&pos, arity, 0, text, 0));
    2461              : }
    2462              : 
    2463              : GEN
    2464            0 : closure_deriv(GEN G)
    2465            0 : { return closure_derivn(G, 1); }
    2466              : 
    2467              : static long
    2468     15558986 : vec_optimize(GEN arg)
    2469              : {
    2470     15558986 :   long fl = COsafelex|COsafedyn;
    2471              :   long i;
    2472     64444526 :   for (i=1; i<lg(arg); i++)
    2473              :   {
    2474     48885547 :     optimizenode(arg[i]);
    2475     48885540 :     fl &= tree[arg[i]].flags;
    2476              :   }
    2477     15558979 :   return fl;
    2478              : }
    2479              : 
    2480              : static void
    2481     15461848 : optimizevec(long n)
    2482              : {
    2483     15461848 :   pari_sp ltop=avma;
    2484     15461848 :   long x = tree[n].x;
    2485     15461848 :   GEN  arg = listtogen(x, Fmatrixelts);
    2486     15461848 :   tree[n].flags = vec_optimize(arg);
    2487     15461848 :   set_avma(ltop);
    2488     15461848 : }
    2489              : 
    2490              : static void
    2491         9687 : optimizemat(long n)
    2492              : {
    2493         9687 :   pari_sp ltop = avma;
    2494         9687 :   long x = tree[n].x;
    2495              :   long i;
    2496         9687 :   GEN line = listtogen(x,Fmatrixlines);
    2497         9687 :   long fl = COsafelex|COsafedyn;
    2498        48052 :   for(i=1;i<lg(line);i++)
    2499              :   {
    2500        38365 :     GEN col=listtogen(line[i],Fmatrixelts);
    2501        38365 :     fl &= vec_optimize(col);
    2502              :   }
    2503         9687 :   set_avma(ltop); tree[n].flags=fl;
    2504         9687 : }
    2505              : 
    2506              : static void
    2507        14645 : optimizematcoeff(long n)
    2508              : {
    2509        14645 :   long x=tree[n].x;
    2510        14645 :   long y=tree[n].y;
    2511        14645 :   long yx=tree[y].x;
    2512        14645 :   long yy=tree[y].y;
    2513              :   long fl;
    2514        14645 :   optimizenode(x);
    2515        14645 :   optimizenode(yx);
    2516        14645 :   fl=tree[x].flags&tree[yx].flags;
    2517        14645 :   if (yy>=0)
    2518              :   {
    2519         1764 :     optimizenode(yy);
    2520         1764 :     fl&=tree[yy].flags;
    2521              :   }
    2522        14645 :   tree[n].flags=fl;
    2523        14645 : }
    2524              : 
    2525              : static void
    2526     10766896 : optimizefunc(entree *ep, long n)
    2527              : {
    2528     10766896 :   pari_sp av=avma;
    2529              :   long j;
    2530     10766896 :   long x=tree[n].x;
    2531     10766896 :   long y=tree[n].y;
    2532              :   Gtype t;
    2533              :   PPproto mod;
    2534     10766896 :   long fl=COsafelex|COsafedyn;
    2535              :   const char *p;
    2536              :   char c;
    2537     10766896 :   GEN arg = listtogen(y,Flistarg);
    2538     10766896 :   long nb=lg(arg)-1, ret_flag;
    2539     10766896 :   if (is_func_named(ep,"if") && nb>=4)
    2540          112 :     ep=is_entry("_multi_if");
    2541     10766896 :   p = ep->code;
    2542     10766896 :   if (!p)
    2543         3681 :     fl=0;
    2544              :   else
    2545     10763215 :     (void) get_ret_type(&p, 2, &t, &ret_flag);
    2546     10766896 :   if (p && *p)
    2547              :   {
    2548     10756113 :     j=1;
    2549     22996056 :     while((mod=parseproto(&p,&c,tree[n].str))!=PPend)
    2550              :     {
    2551     12239971 :       if (j<=nb && tree[arg[j]].f!=Fnoarg
    2552     12056855 :           && (mod==PPdefault || mod==PPdefaultmulti))
    2553        64879 :         mod=PPstd;
    2554     12239971 :       switch(mod)
    2555              :       {
    2556     12041798 :       case PPstd:
    2557     12041798 :         if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1);
    2558     12041770 :         if (tree[arg[j]].f==Fnoarg && c!='I' && c!='E')
    2559            0 :           compile_err("missing mandatory argument", tree[arg[j]].str);
    2560     12041770 :         switch(c)
    2561              :         {
    2562     12002213 :         case 'G':
    2563              :         case 'n':
    2564              :         case 'M':
    2565              :         case 'L':
    2566              :         case 'U':
    2567              :         case 'P':
    2568     12002213 :           optimizenode(arg[j]);
    2569     12002213 :           fl&=tree[arg[j++]].flags;
    2570     12002213 :           break;
    2571        20357 :         case 'I':
    2572              :         case 'E':
    2573              :         case 'J':
    2574        20357 :           optimizenode(arg[j]);
    2575        20357 :           fl&=tree[arg[j]].flags;
    2576        20357 :           tree[arg[j++]].flags=COsafelex|COsafedyn;
    2577        20357 :           break;
    2578         2310 :         case '&': case '*':
    2579              :           {
    2580         2310 :             long a=arg[j];
    2581         2310 :             if (c=='&')
    2582              :             {
    2583         1533 :               if (tree[a].f!=Frefarg)
    2584            0 :                 compile_err("expected character: '&'", tree[a].str);
    2585         1533 :               a=tree[a].x;
    2586              :             }
    2587         2310 :             optimizenode(a);
    2588         2310 :             tree[arg[j++]].flags=COsafelex|COsafedyn;
    2589         2310 :             fl=0;
    2590         2310 :             break;
    2591              :           }
    2592          560 :         case 'W':
    2593              :         {
    2594          560 :           long a = tree[arg[j]].f==Findarg ? tree[arg[j]].x: arg[j];
    2595          560 :           optimizenode(a);
    2596          560 :           fl=0; j++;
    2597          560 :           break;
    2598              :         }
    2599         6662 :         case 'V':
    2600              :         case 'r':
    2601         6662 :           tree[arg[j++]].flags=COsafelex|COsafedyn;
    2602         6662 :           break;
    2603         6895 :         case '=':
    2604              :           {
    2605         6895 :             long a=arg[j++], y=tree[a].y;
    2606         6895 :             if (tree[a].f!=Fassign)
    2607            0 :               compile_err("expected character: '=' instead of",
    2608            0 :                   tree[a].str+tree[a].len);
    2609         6895 :             optimizenode(y);
    2610         6895 :             fl&=tree[y].flags;
    2611              :           }
    2612         6895 :           break;
    2613         2773 :         case 's':
    2614         2773 :           fl &= vec_optimize(cattovec(arg[j++], OPcat));
    2615         2773 :           break;
    2616            0 :         default:
    2617            0 :           pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,
    2618            0 :               tree[x].len, tree[x].str);
    2619              :         }
    2620     12041770 :         break;
    2621       106723 :       case PPauto:
    2622       106723 :         break;
    2623        75927 :       case PPdefault:
    2624              :       case PPdefaultmulti:
    2625        75927 :         if (j<=nb) optimizenode(arg[j++]);
    2626        75927 :         break;
    2627        15523 :       case PPstar:
    2628        15523 :         switch(c)
    2629              :         {
    2630          112 :         case 'E':
    2631              :           {
    2632          112 :             long n=nb+1-j;
    2633              :             long k;
    2634          574 :             for(k=1;k<=n;k++)
    2635              :             {
    2636          462 :               optimizenode(arg[j+k-1]);
    2637          462 :               fl &= tree[arg[j+k-1]].flags;
    2638              :             }
    2639          112 :             j=nb+1;
    2640          112 :             break;
    2641              :           }
    2642        15411 :         case 's':
    2643              :           {
    2644        15411 :             long n=nb+1-j;
    2645              :             long k;
    2646        37209 :             for(k=1;k<=n;k++)
    2647        21798 :               fl &= vec_optimize(cattovec(arg[j+k-1],OPcat));
    2648        15411 :             j=nb+1;
    2649        15411 :             break;
    2650              :           }
    2651            0 :         default:
    2652            0 :           pari_err(e_MISC,"Unknown prototype code `%c*' for `%.*s'",c,
    2653            0 :               tree[x].len, tree[x].str);
    2654              :         }
    2655        15523 :         break;
    2656            0 :       default:
    2657            0 :         pari_err_BUG("optimizefun [unknown PPproto]");
    2658              :       }
    2659              :     }
    2660     10756085 :     if (j<=nb)
    2661            0 :       compile_err("too many arguments",tree[arg[j]].str);
    2662              :   }
    2663        10783 :   else (void)vec_optimize(arg);
    2664     10766868 :   set_avma(av); tree[n].flags=fl;
    2665     10766868 : }
    2666              : 
    2667              : static void
    2668        23419 : optimizecall(long n)
    2669              : {
    2670        23419 :   pari_sp av=avma;
    2671        23419 :   long x=tree[n].x;
    2672        23419 :   long y=tree[n].y;
    2673        23419 :   GEN arg=listtogen(y,Flistarg);
    2674        23419 :   optimizenode(x);
    2675        23419 :   tree[n].flags = COsafelex&tree[x].flags&vec_optimize(arg);
    2676        23412 :   set_avma(av);
    2677        23412 : }
    2678              : 
    2679              : static void
    2680        15308 : optimizeseq(long n)
    2681              : {
    2682        15308 :   pari_sp av = avma;
    2683        15308 :   GEN L = listtogen(n, Fseq);
    2684        15308 :   long i, l = lg(L)-1, flags=-1L;
    2685        63984 :   for(i = 1; i <= l; i++)
    2686              :   {
    2687        48676 :     optimizenode(L[i]);
    2688        48676 :     flags &= tree[L[i]].flags;
    2689              :   }
    2690        15308 :   set_avma(av);
    2691        15308 :   tree[n].flags = flags;
    2692        15308 : }
    2693              : 
    2694              : void
    2695     62106088 : optimizenode(long n)
    2696              : {
    2697              :   long x,y;
    2698              : #ifdef STACK_CHECK
    2699     62106088 :   if (PARI_stack_limit && (void*) &x <= PARI_stack_limit)
    2700            0 :     pari_err(e_MISC, "expression nested too deeply");
    2701              : #endif
    2702     62106088 :   if (n<0)
    2703            0 :     pari_err_BUG("optimizenode");
    2704     62106088 :   x=tree[n].x;
    2705     62106088 :   y=tree[n].y;
    2706              : 
    2707     62106088 :   switch(tree[n].f)
    2708              :   {
    2709        15308 :   case Fseq:
    2710        15308 :     optimizeseq(n);
    2711     62024765 :     return;
    2712        16409 :   case Frange:
    2713        16409 :     optimizenode(x);
    2714        16409 :     optimizenode(y);
    2715        16409 :     tree[n].flags=tree[x].flags&tree[y].flags;
    2716        16409 :     break;
    2717        14645 :   case Fmatcoeff:
    2718        14645 :     optimizematcoeff(n);
    2719        14645 :     break;
    2720        50227 :   case Fassign:
    2721        50227 :     optimizenode(x);
    2722        50227 :     optimizenode(y);
    2723        50227 :     tree[n].flags=0;
    2724        50227 :     break;
    2725     35738088 :   case Fnoarg:
    2726              :   case Fnorange:
    2727              :   case Fsmall:
    2728              :   case Fconst:
    2729              :   case Fentry:
    2730     35738088 :     tree[n].flags=COsafelex|COsafedyn;
    2731     35738088 :     return;
    2732     15461848 :   case Fvec:
    2733     15461848 :     optimizevec(n);
    2734     15461848 :     return;
    2735         9687 :   case Fmat:
    2736         9687 :     optimizemat(n);
    2737         9687 :     return;
    2738            7 :   case Frefarg:
    2739            7 :     compile_err("unexpected character '&'",tree[n].str);
    2740            0 :     return;
    2741          126 :   case Findarg:
    2742          126 :     return;
    2743            0 :   case Fvararg:
    2744            0 :     compile_err("unexpected characters '..'",tree[n].str);
    2745            0 :     return;
    2746     10789986 :   case Ffunction:
    2747              :     {
    2748     10789986 :       entree *ep=getfunc(n);
    2749     10789986 :       if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)
    2750        23090 :         optimizecall(n);
    2751              :       else
    2752     10766896 :         optimizefunc(ep,n);
    2753     10789951 :       return;
    2754              :     }
    2755          329 :   case Fcall:
    2756          329 :     optimizecall(n);
    2757          329 :     return;
    2758         9428 :   case Flambda:
    2759         9428 :     optimizenode(y);
    2760         9428 :     tree[n].flags=COsafelex|COsafedyn;
    2761         9428 :     return;
    2762            0 :   case Ftag:
    2763            0 :     optimizenode(x);
    2764            0 :     tree[n].flags=tree[x].flags;
    2765            0 :     return;
    2766            0 :   default:
    2767            0 :     pari_err_BUG("optimizenode");
    2768              :   }
    2769              : }
        

Generated by: LCOV version 2.0-1