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) Hit Total Coverage
Test: PARI/GP v2.18.1 lcov report (development 30862-ea47bd413c) Lines: 1631 1811 90.1 %
Date: 2026-05-06 09:26:47 Functions: 89 92 96.7 %
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     3822364 : translate(const char **src, char *s)
      35             : {
      36     3822364 :   const char *t = *src;
      37    30148648 :   while (*t)
      38             :   {
      39    30149296 :     while (*t == '\\')
      40             :     {
      41         648 :       switch(*++t)
      42             :       {
      43           0 :         case 'e':  *s='\033'; break; /* escape */
      44         466 :         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         648 :       t++; s++;
      49             :     }
      50    30148648 :     if (*t == '"')
      51             :     {
      52     3822364 :       if (t[1] != '"') break;
      53           0 :       t += 2; continue;
      54             :     }
      55    26326284 :     *s++ = *t++;
      56             :   }
      57     3822364 :   *s=0; *src=t; return s;
      58             : }
      59             : 
      60             : static void
      61           8 : matchQ(const char *s, char *entry)
      62             : {
      63           8 :   if (*s != '"')
      64           0 :     pari_err(e_SYNTAX,"expected character: '\"' instead of",s,entry);
      65           8 : }
      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           4 : pari_translate_string(const char *src, char *s, char *entry)
      71             : {
      72           4 :   matchQ(src, entry); src++; s = translate(&src, s);
      73           4 :   if (!s) pari_err(e_SYNTAX,"run-away string",src,entry);
      74           4 :   matchQ(src, entry); return (char*)src+1;
      75             : }
      76             : 
      77             : static GEN
      78     3822360 : strntoGENexp(const char *str, long len)
      79             : {
      80     3822360 :   long n = nchar2nlong(len-1);
      81     3822360 :   GEN z = cgetg(1+n, t_STR);
      82     3822360 :   const char *t = str+1;
      83     3822360 :   z[n] = 0;
      84     3822360 :   if (!translate(&t, GSTR(z))) compile_err("run-away string",str);
      85     3822360 :   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      373064 : pari_init_compiler(void)
     122             : {
     123      373064 :   pari_stack_init(&s_opcode,sizeof(*opcode),(void **)&opcode);
     124      373059 :   pari_stack_init(&s_operand,sizeof(*operand),(void **)&operand);
     125      373056 :   pari_stack_init(&s_accesslex,sizeof(*operand),(void **)&accesslex);
     126      373056 :   pari_stack_init(&s_data,sizeof(*data),(void **)&data);
     127      373056 :   pari_stack_init(&s_lvar,sizeof(*localvars),(void **)&localvars);
     128      373055 :   pari_stack_init(&s_dbginfo,sizeof(*dbginfo),(void **)&dbginfo);
     129      373054 :   pari_stack_init(&s_frame,sizeof(*frames),(void **)&frames);
     130      373055 :   offset=-1; nblex=0;
     131      373055 : }
     132             : void
     133      371407 : pari_close_compiler(void)
     134             : {
     135      371407 :   pari_stack_delete(&s_opcode);
     136      370020 :   pari_stack_delete(&s_operand);
     137      368487 :   pari_stack_delete(&s_accesslex);
     138      367550 :   pari_stack_delete(&s_data);
     139      366916 :   pari_stack_delete(&s_lvar);
     140      366376 :   pari_stack_delete(&s_dbginfo);
     141      366165 :   pari_stack_delete(&s_frame);
     142      366072 : }
     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    10108204 : getcodepos(struct codepos *pos)
     153             : {
     154    10108204 :   pos->opcode=s_opcode.n;
     155    10108204 :   pos->accesslex=s_accesslex.n;
     156    10108204 :   pos->data=s_data.n;
     157    10108204 :   pos->offset=offset;
     158    10108204 :   pos->nblex=nblex;
     159    10108204 :   pos->localvars=s_lvar.n;
     160    10108204 :   pos->dbgstart=dbgstart;
     161    10108204 :   pos->frames=s_frame.n;
     162    10108204 :   offset=s_data.n-1;
     163    10108204 : }
     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     1431855 : compilestate_save(struct pari_compilestate *comp)
     182             : {
     183     1431855 :   comp->opcode=s_opcode.n;
     184     1431855 :   comp->operand=s_operand.n;
     185     1431855 :   comp->accesslex=s_accesslex.n;
     186     1431855 :   comp->data=s_data.n;
     187     1431855 :   comp->offset=offset;
     188     1431855 :   comp->nblex=nblex;
     189     1431855 :   comp->localvars=s_lvar.n;
     190     1431855 :   comp->dbgstart=dbgstart;
     191     1431855 :   comp->dbginfo=s_dbginfo.n;
     192     1431855 :   comp->frames=s_frame.n;
     193     1431855 : }
     194             : 
     195             : void
     196       56429 : compilestate_restore(struct pari_compilestate *comp)
     197             : {
     198       56429 :   s_opcode.n=comp->opcode;
     199       56429 :   s_operand.n=comp->operand;
     200       56429 :   s_accesslex.n=comp->accesslex;
     201       56429 :   s_data.n=comp->data;
     202       56429 :   offset=comp->offset;
     203       56429 :   nblex=comp->nblex;
     204       56429 :   s_lvar.n=comp->localvars;
     205       56429 :   dbgstart=comp->dbgstart;
     206       56429 :   s_dbginfo.n=comp->dbginfo;
     207       56429 :   s_frame.n=comp->frames;
     208       56429 : }
     209             : 
     210             : static GEN
     211    13968644 : gcopyunclone(GEN x) { GEN y = gcopy(x); gunclone(x); return y; }
     212             : 
     213             : static void
     214      116741 : access_push(long x)
     215             : {
     216      116741 :   long a = pari_stack_new(&s_accesslex);
     217      116741 :   accesslex[a] = x;
     218      116741 : }
     219             : 
     220             : static GEN
     221     9154221 : genctx(long nbmvar, long paccesslex)
     222             : {
     223     9154221 :   GEN acc = const_vec(nbmvar,gen_1);
     224     9154239 :   long i, lvl = 1 + nbmvar;
     225     9196676 :   for (i = paccesslex; i<s_accesslex.n; i++)
     226             :   {
     227       42437 :     long a = accesslex[i];
     228       42437 :     if (a > 0) { lvl+=a; continue; }
     229       37215 :     a += lvl;
     230       37215 :     if (a <= 0) pari_err_BUG("genctx");
     231       37215 :     if (a <= nbmvar)
     232       28822 :       gel(acc, a) = gen_0;
     233             :   }
     234     9154239 :   s_accesslex.n = paccesslex;
     235    32927326 :   for (i = 1; i<=nbmvar; i++)
     236    23773084 :     if (signe(gel(acc,i))==0)
     237       20961 :       access_push(i-nbmvar-1);
     238     9154242 :   return acc;
     239             : }
     240             : 
     241             : static GEN
     242    10108103 : getfunction(const struct codepos *pos, long arity, long nbmvar, GEN text,
     243             :             long gap)
     244             : {
     245    10108103 :   long lop  = s_opcode.n+1 - pos->opcode;
     246    10108103 :   long ldat = s_data.n+1 - pos->data;
     247    10108103 :   long lfram = s_frame.n+1 - pos->frames;
     248    10108103 :   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    10108079 :   cl[1] = arity;
     254    10108079 :   gel(cl,2) = cgetg(nchar2nlong(lop)+1, t_STR);
     255    10108019 :   gel(cl,3) = op = cgetg(lop, t_VECSMALL);
     256    10108005 :   gel(cl,4) = dat = cgetg(ldat, t_VEC);
     257    10108004 :   dbg = cgetg(lop,  t_VECSMALL);
     258    10108001 :   frpc = cgetg(lfram,  t_VECSMALL);
     259    10107991 :   fram = cgetg(lfram,  t_VEC);
     260    10107997 :   gel(cl,5) = mkvec3(dbg, frpc, fram);
     261    10108029 :   if (text) gel(cl,6) = text;
     262    10108029 :   s = GSTR(gel(cl,2)) - 1;
     263   169676030 :   for (i = 1; i < lop; i++)
     264             :   {
     265   159568001 :     long j = i+pos->opcode-1;
     266   159568001 :     s[i] = opcode[j];
     267   159568001 :     op[i] = operand[j];
     268   159568001 :     dbg[i] = dbginfo[j] - dbgstart;
     269   159568001 :     if (dbg[i] < 0) dbg[i] += gap;
     270             :   }
     271    10108029 :   s[i] = 0;
     272    10108029 :   s_opcode.n = pos->opcode;
     273    10108029 :   s_operand.n = pos->opcode;
     274    10108029 :   s_dbginfo.n = pos->opcode;
     275    10108029 :   if (lg(cl)==8)
     276     9143126 :     gel(cl,7) = genctx(nbmvar, pos->accesslex);
     277      964903 :   else if (nbmvar==0)
     278      953895 :     s_accesslex.n = pos->accesslex;
     279             :   else
     280             :   {
     281       11008 :     pari_sp av = avma;
     282       11008 :     (void) genctx(nbmvar, pos->accesslex);
     283       11091 :     set_avma(av);
     284             :   }
     285    14912627 :   for (i = 1; i < ldat; i++)
     286     4804505 :     if (data[i+pos->data-1]) gel(dat,i) = gcopyunclone(data[i+pos->data-1]);
     287    10108122 :   s_data.n = pos->data;
     288    10137500 :   while (s_lvar.n > pos->localvars && !localvars[s_lvar.n-1].inl)
     289             :   {
     290       29378 :     if (localvars[s_lvar.n-1].type==Lmy) nblex--;
     291       29378 :     s_lvar.n--;
     292             :   }
     293    19272376 :   for (i = 1; i < lfram; i++)
     294             :   {
     295     9164145 :     long j = i+pos->frames-1;
     296     9164145 :     frpc[i] = frames[j].pc - pos->opcode+1;
     297     9164145 :     gel(fram, i) = gcopyunclone(frames[j].frame);
     298             :   }
     299    10108231 :   s_frame.n = pos->frames;
     300    10108231 :   offset = pos->offset;
     301    10108231 :   dbgstart = pos->dbgstart;
     302    10108231 :   return cl;
     303             : }
     304             : 
     305             : static GEN
     306       20436 : getclosure(struct codepos *pos, long nbmvar)
     307             : {
     308       20436 :   return getfunction(pos, 0, nbmvar, NULL, 0);
     309             : }
     310             : 
     311             : static void
     312   159564680 : op_push_loc(op_code o, long x, const char *loc)
     313             : {
     314   159564680 :   long n=pari_stack_new(&s_opcode);
     315   159564614 :   long m=pari_stack_new(&s_operand);
     316   159564556 :   long d=pari_stack_new(&s_dbginfo);
     317   159564576 :   opcode[n]=o;
     318   159564576 :   operand[m]=x;
     319   159564576 :   dbginfo[d]=loc;
     320   159564576 : }
     321             : 
     322             : static void
     323   115722482 : op_push(op_code o, long x, long n)
     324             : {
     325   115722482 :   op_push_loc(o,x,tree[n].str);
     326   115722482 : }
     327             : 
     328             : static void
     329        2975 : op_insert_loc(long k, op_code o, long x, const char *loc)
     330             : {
     331             :   long i;
     332        2975 :   long n=pari_stack_new(&s_opcode);
     333        2975 :   (void) pari_stack_new(&s_operand);
     334        2975 :   (void) pari_stack_new(&s_dbginfo);
     335      623659 :   for (i=n-1; i>=k; i--)
     336             :   {
     337      620684 :     opcode[i+1] = opcode[i];
     338      620684 :     operand[i+1]= operand[i];
     339      620684 :     dbginfo[i+1]= dbginfo[i];
     340             :   }
     341        2975 :   opcode[k]  = o;
     342        2975 :   operand[k] = x;
     343        2975 :   dbginfo[k] = loc;
     344        2975 : }
     345             : 
     346             : static long
     347     4804505 : data_push(GEN x)
     348             : {
     349     4804505 :   long n=pari_stack_new(&s_data);
     350     4804505 :   data[n] = x?gclone(x):x;
     351     4804505 :   return n-offset;
     352             : }
     353             : 
     354             : static void
     355       65891 : var_push(entree *ep, Ltype type)
     356             : {
     357       65891 :   long n=pari_stack_new(&s_lvar);
     358       65891 :   localvars[n].ep   = ep;
     359       65891 :   localvars[n].inl  = 0;
     360       65891 :   localvars[n].type = type;
     361       65891 :   if (type == Lmy) nblex++;
     362       65891 : }
     363             : 
     364             : static void
     365     9164177 : frame_push(GEN x)
     366             : {
     367     9164177 :   long n=pari_stack_new(&s_frame);
     368     9164170 :   frames[n].pc = s_opcode.n-1;
     369     9164170 :   frames[n].frame = gclone(x);
     370     9164245 : }
     371             : 
     372             : static GEN
     373          53 : pack_localvars(void)
     374             : {
     375          53 :   GEN pack=cgetg(3,t_VEC);
     376          53 :   long i, l=s_lvar.n;
     377          53 :   GEN t=cgetg(1+l,t_VECSMALL);
     378          53 :   GEN e=cgetg(1+l,t_VECSMALL);
     379          53 :   gel(pack,1)=t;
     380          53 :   gel(pack,2)=e;
     381         129 :   for(i=1;i<=l;i++)
     382             :   {
     383          76 :     t[i]=localvars[i-1].type;
     384          76 :     e[i]=(long)localvars[i-1].ep;
     385             :   }
     386         129 :   for(i=1;i<=nblex;i++)
     387          76 :     access_push(-i);
     388          53 :   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      274708 : addcopy(long n, long mode, long flag, long mask)
     485             : {
     486      274708 :   if (mode==Ggen && !(flag&mask))
     487             :   {
     488       27167 :     op_push(OCcopy,0,n);
     489       27167 :     if (!(flag&FLsurvive) && DEBUGLEVEL)
     490           0 :       pari_warn(warner,"compiler generates copy for `%.*s'",
     491           0 :                        tree[n].len,tree[n].str);
     492             :   }
     493      274708 : }
     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   153727933 : parseproto(char const **q, char *c, const char *str)
     501             : {
     502   153727933 :   char  const *p=*q;
     503             :   long i;
     504   153727933 :   switch(*p)
     505             :   {
     506    39939727 :   case 0:
     507             :   case '\n':
     508    39939727 :     return PPend;
     509      288091 :   case 'D':
     510      288091 :     switch(p[1])
     511             :     {
     512      195483 :     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      195483 :       *c=p[1]; *q=p+2; return PPdefault;
     524       92608 :     default:
     525      560388 :       for(i=0;*p && i<2;p++) i+=*p==',';
     526             :       /* assert(i>=2) because check_proto validated the protototype */
     527       92608 :       *c=p[-2]; *q=p; return PPdefaultmulti;
     528             :     }
     529             :     break;
     530      143473 :   case 'C':
     531             :   case 'p':
     532             :   case 'b':
     533             :   case 'P':
     534             :   case 'f':
     535      143473 :     *c=*p; *q=p+1; return PPauto;
     536        1550 :   case '&':
     537        1550 :     *c='*'; *q=p+1; return PPstd;
     538       18934 :   case 'V':
     539       18934 :     if (p[1]=='=')
     540             :     {
     541       13734 :       if (p[2]!='G')
     542           0 :         compile_err("function prototype is not supported",str);
     543       13734 :       *c='='; p+=2;
     544             :     }
     545             :     else
     546        5200 :       *c=*p;
     547       18934 :     *q=p+1; return PPstd;
     548       45882 :   case 'E':
     549             :   case 's':
     550       45882 :     if (p[1]=='*') { *c=*p++; *q=p+1; return PPstar; }
     551             :     /*fall through*/
     552             :   }
     553   113305144 :   *c=*p; *q=p+1; return PPstd;
     554             : }
     555             : 
     556             : static long
     557      448499 : detag(long n)
     558             : {
     559      448499 :   while (tree[n].f==Ftag)
     560           0 :     n=tree[n].x;
     561      448499 :   return n;
     562             : }
     563             : 
     564             : /* return type for GP functions */
     565             : static op_code
     566    21674844 : get_ret_type(const char **p, long arity, Gtype *t, long *flag)
     567             : {
     568    21674844 :   *flag = 0;
     569    21674844 :   if (**p == 'v') { (*p)++; *t=Gvoid; return OCcallvoid; }
     570    21625900 :   else if (**p == 'i') { (*p)++; *t=Gsmall;  return OCcallint; }
     571    21619103 :   else if (**p == 'l') { (*p)++; *t=Gsmall;  return OCcalllong; }
     572    21593067 :   else if (**p == 'u') { (*p)++; *t=Gusmall; return OCcalllong; }
     573    21593067 :   else if (**p == 'm') { (*p)++; *flag = FLnocopy; }
     574    21593067 :   *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    27755176 : compilecast_loc(int type, int mode, const char *loc)
     590             : {
     591    27755176 :   if (type==mode) return;
     592    15528277 :   switch (mode)
     593             :   {
     594         210 :   case Gusmall:
     595         210 :     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         210 :     break;
     599        5227 :   case Gsmall:
     600        5227 :     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        5220 :     break;
     604    15509871 :   case Ggen:
     605    15509871 :     if (type==Gsmall)      op_push_loc(OCstoi,0,loc);
     606    15495410 :     else if (type==Gusmall)op_push_loc(OCutoi,0,loc);
     607    15495410 :     else if (type==Gvoid)  op_push_loc(OCpushgnil,0,loc);
     608    15509871 :     break;
     609        8980 :   case Gvoid:
     610        8980 :     op_push_loc(OCpop, 1,loc);
     611        8980 :     break;
     612        3989 :   case Gvar:
     613        3989 :     if (type==Ggen)        op_push_loc(OCvarn,-1,loc);
     614           7 :     else compile_varerr(loc);
     615        3982 :      break;
     616           0 :   default:
     617           0 :     pari_err_BUG("compilecast [unknown type]");
     618             :   }
     619             : }
     620             : 
     621             : static void
     622    18614435 : compilecast(long n, int type, int mode) { compilecast_loc(type, mode, tree[n].str); }
     623             : 
     624             : static entree *
     625       25263 : fetch_member_raw(const char *s, long len)
     626             : {
     627       25263 :   pari_sp av = avma;
     628       25263 :   char *t = stack_malloc(len+2);
     629             :   entree *ep;
     630       25263 :   t[0] = '_'; strncpy(t+1, s, len); t[++len] = 0; /* prepend '_' */
     631       25263 :   ep = fetch_entry_raw(t, len);
     632       25263 :   set_avma(av); return ep;
     633             : }
     634             : static entree *
     635    21935875 : getfunc(long n)
     636             : {
     637    21935875 :   long x=tree[n].x;
     638    21935875 :   if (tree[x].x==CSTmember) /* str-1 points to '.' */
     639       25263 :     return do_alias(fetch_member_raw(tree[x].str - 1, tree[x].len + 1));
     640             :   else
     641    21910612 :     return do_alias(fetch_entry_raw(tree[x].str, tree[x].len));
     642             : }
     643             : 
     644             : static entree *
     645      366094 : getentry(long n)
     646             : {
     647      366094 :   n = detag(n);
     648      366094 :   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      366073 :   return getfunc(n);
     655             : }
     656             : 
     657             : static entree *
     658       67725 : getvar(long n)
     659       67725 : { return getentry(n); }
     660             : 
     661             : static entree *
     662       12956 : getvarvec(long n)
     663             : {
     664       12956 :   n = detag(n);
     665       12956 :   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    11140877 : getmvar(entree *ep)
     683             : {
     684             :   long i;
     685    11140877 :   long vn=0;
     686    12284813 :   for(i=s_lvar.n-1;i>=0;i--)
     687             :   {
     688     1224299 :     if(localvars[i].type==Lmy)
     689     1224026 :       vn--;
     690     1224299 :     if(localvars[i].ep==ep)
     691       80363 :       return localvars[i].type==Lmy?vn:0;
     692             :   }
     693    11060514 :   return 0;
     694             : }
     695             : 
     696             : static void
     697        9738 : ctxmvar(long n)
     698             : {
     699        9738 :   pari_sp av=avma;
     700             :   GEN ctx;
     701             :   long i;
     702        9738 :   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   118408132 : is_func_named(entree *ep, const char *s)
     713             : {
     714   118408132 :   return !strcmp(ep->name, s);
     715             : }
     716             : 
     717             : INLINE int
     718        4280 : is_node_zero(long n)
     719             : {
     720        4280 :   n = detag(n);
     721        4280 :   return (tree[n].f==Fsmall && tree[n].x==0);
     722             : }
     723             : 
     724             : static void
     725          39 : str_defproto(const char *p, const char *q, const char *loc)
     726             : {
     727          39 :   long len = p-4-q;
     728          39 :   if (q[1]!='"' || q[len]!='"')
     729           0 :     compile_err("default argument must be a string",loc);
     730          39 :   op_push_loc(OCpushgen,data_push(strntoGENexp(q+1,len)),loc);
     731          39 : }
     732             : 
     733             : static long
     734         462 : countmatrixelts(long n)
     735             : {
     736             :   long x,i;
     737         462 :   if (n==-1 || tree[n].f==Fnoarg) return 0;
     738        1092 :   for(x=n, i=0; tree[x].f==Fmatrixelts; x=tree[x].x)
     739         630 :     if (tree[tree[x].y].f!=Fnoarg) i++;
     740         462 :   if (tree[x].f!=Fnoarg) i++;
     741         462 :   return i;
     742             : }
     743             : 
     744             : static long
     745    52642929 : countlisttogen(long n, Ffunc f)
     746             : {
     747             :   long x,i;
     748    52642929 :   if (n==-1 || tree[n].f==Fnoarg) return 0;
     749   122029156 :   for(x=n, i=0; tree[x].f==f ;x=tree[x].x, i++);
     750    49374166 :   return i+1;
     751             : }
     752             : 
     753             : static GEN
     754    52642929 : listtogen(long n, Ffunc f)
     755             : {
     756    52642929 :   long x,i,nb = countlisttogen(n, f);
     757    52642929 :   GEN z=cgetg(nb+1, t_VECSMALL);
     758    52642929 :   if (nb)
     759             :   {
     760   122029156 :     for (x=n, i = nb-1; i>0; z[i+1]=tree[x].y, x=tree[x].x, i--);
     761    49374166 :     z[1]=x;
     762             :   }
     763    52642929 :   return z;
     764             : }
     765             : 
     766             : static long
     767    21591654 : first_safe_arg(GEN arg, long mask)
     768             : {
     769    21591654 :   long lnc, l=lg(arg);
     770    45790012 :   for (lnc=l-1; lnc>0 && (tree[arg[lnc]].flags&mask)==mask; lnc--);
     771    21591654 :   return lnc;
     772             : }
     773             : 
     774             : static void
     775       21009 : checkdups(GEN arg, GEN vep)
     776             : {
     777       21009 :   long l=vecsmall_duplicate(vep);
     778       21009 :   if (l!=0) compile_err("variable declared twice",tree[arg[l]].str);
     779       21009 : }
     780             : 
     781             : enum {MAT_range,MAT_std,MAT_line,MAT_column,VEC_std};
     782             : 
     783             : static int
     784       15737 : matindex_type(long n)
     785             : {
     786       15737 :   long x = tree[n].x, y = tree[n].y;
     787       15737 :   long fxx = tree[tree[x].x].f, fxy = tree[tree[x].y].f;
     788       15737 :   if (y==-1)
     789             :   {
     790       13659 :     if (fxy!=Fnorange) return MAT_range;
     791       13050 :     if (fxx==Fnorange) compile_err("missing index",tree[n].str);
     792       13050 :     return VEC_std;
     793             :   }
     794             :   else
     795             :   {
     796        2078 :     long fyx = tree[tree[y].x].f, fyy = tree[tree[y].y].f;
     797        2078 :     if (fxy!=Fnorange || fyy!=Fnorange) return MAT_range;
     798        1903 :     if (fxx==Fnorange && fyx==Fnorange)
     799           0 :       compile_err("missing index",tree[n].str);
     800        1903 :     if (fxx==Fnorange) return MAT_column;
     801        1098 :     if (fyx==Fnorange) return MAT_line;
     802         832 :     return MAT_std;
     803             :   }
     804             : }
     805             : 
     806             : static entree *
     807       49678 : getlvalue(long n)
     808             : {
     809       50686 :   while ((tree[n].f==Fmatcoeff && matindex_type(tree[n].y)!=MAT_range) || tree[n].f==Ftag)
     810        1008 :     n=tree[n].x;
     811       49678 :   return getvar(n);
     812             : }
     813             : 
     814             : INLINE void
     815       46054 : compilestore(long vn, entree *ep, long n)
     816             : {
     817       46054 :   if (vn)
     818        4779 :     op_push(OCstorelex,vn,n);
     819             :   else
     820             :   {
     821       41275 :     if (EpSTATIC(do_alias(ep)))
     822           0 :       compile_varerr(tree[n].str);
     823       41275 :     op_push(OCstoredyn,(long)ep,n);
     824             :   }
     825       46054 : }
     826             : 
     827             : INLINE void
     828         847 : compilenewptr(long vn, entree *ep, long n)
     829             : {
     830         847 :   if (vn)
     831             :   {
     832         259 :     access_push(vn);
     833         259 :     op_push(OCnewptrlex,vn,n);
     834             :   }
     835             :   else
     836         588 :     op_push(OCnewptrdyn,(long)ep,n);
     837         847 : }
     838             : 
     839             : static void
     840        1848 : compilelvalue(long n)
     841             : {
     842        1848 :   n = detag(n);
     843        1848 :   if (tree[n].f==Fentry)
     844         847 :     return;
     845             :   else
     846             :   {
     847        1001 :     long x = tree[n].x, y = tree[n].y;
     848        1001 :     long yx = tree[y].x, yy = tree[y].y;
     849        1001 :     long m = matindex_type(y);
     850        1001 :     if (m == MAT_range)
     851           0 :       compile_err("not an lvalue",tree[n].str);
     852        1001 :     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        1001 :     compilelvalue(x);
     866        1001 :     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          98 :     case MAT_column:
     882          98 :       compilenode(tree[yy].x,Gsmall,0);
     883          98 :       op_push(OCcompoCptr,0,y);
     884          98 :       break;
     885             :     }
     886             :   }
     887             : }
     888             : 
     889             : static void
     890       13609 : compilematcoeff(long n, int mode)
     891             : {
     892       13609 :   long x=tree[n].x, y=tree[n].y;
     893       13609 :   long yx=tree[y].x, yy=tree[y].y;
     894       13609 :   long m=matindex_type(y);
     895       13609 :   compilenode(x,Ggen,FLnocopy);
     896       13609 :   switch(m)
     897             :   {
     898       11566 :   case VEC_std:
     899       11566 :     compilenode(tree[yx].x,Gsmall,0);
     900       11566 :     op_push(OCcompo1,mode,y);
     901       11566 :     return;
     902         580 :   case MAT_std:
     903         580 :     compilenode(tree[yx].x,Gsmall,0);
     904         580 :     compilenode(tree[yy].x,Gsmall,0);
     905         580 :     op_push(OCcompo2,mode,y);
     906         580 :     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         609 :   case MAT_column:
     913         609 :     compilenode(tree[yy].x,Gsmall,0);
     914         609 :     op_push(OCcompoC,0,y);
     915         609 :     compilecast(n,Gvec,mode);
     916         609 :     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    30552615 : compilesmall(long n, long x, long mode)
     937             : {
     938    30552615 :   if (mode==Ggen)
     939    30465013 :     op_push(OCpushstoi, x, n);
     940             :   else
     941             :   {
     942       87602 :     if (mode==Gusmall && x < 0) U_compile_err(tree[n].str);
     943       87602 :     op_push(OCpushlong, x, n);
     944       87602 :     compilecast(n,Gsmall,mode);
     945             :   }
     946    30552608 : }
     947             : 
     948             : static void
     949    15460514 : compilevec(long n, long mode, op_code op)
     950             : {
     951    15460514 :   pari_sp ltop=avma;
     952    15460514 :   long x=tree[n].x;
     953             :   long i;
     954    15460514 :   GEN arg=listtogen(x,Fmatrixelts);
     955    15460514 :   long l=lg(arg);
     956    15460514 :   op_push(op,l,n);
     957    64011941 :   for (i=1;i<l;i++)
     958             :   {
     959    48551427 :     if (tree[arg[i]].f==Fnoarg)
     960           0 :       compile_err("missing vector element",tree[arg[i]].str);
     961    48551427 :     compilenode(arg[i],Ggen,FLsurvive);
     962    48551427 :     op_push(OCstackgen,i,n);
     963             :   }
     964    15460514 :   set_avma(ltop);
     965    15460514 :   op_push(OCpop,1,n);
     966    15460514 :   compilecast(n,Gvec,mode);
     967    15460514 : }
     968             : 
     969             : static void
     970        9680 : compilemat(long n, long mode)
     971             : {
     972        9680 :   pari_sp ltop=avma;
     973        9680 :   long x=tree[n].x;
     974             :   long i,j;
     975        9680 :   GEN line=listtogen(x,Fmatrixlines);
     976        9680 :   long lglin = lg(line), lgcol=0;
     977        9680 :   op_push(OCpushlong, lglin,n);
     978        9680 :   if (lglin==1)
     979        1001 :     op_push(OCmat,1,n);
     980       48031 :   for(i=1;i<lglin;i++)
     981             :   {
     982       38351 :     GEN col=listtogen(line[i],Fmatrixelts);
     983       38351 :     long l=lg(col), k;
     984       38351 :     if (i==1)
     985             :     {
     986        8679 :       lgcol=l;
     987        8679 :       op_push(OCmat,lgcol,n);
     988             :     }
     989       29672 :     else if (l!=lgcol)
     990           0 :       compile_err("matrix must be rectangular",tree[line[i]].str);
     991       38351 :     k=i;
     992      292503 :     for(j=1;j<lgcol;j++)
     993             :     {
     994      254152 :       k-=lglin;
     995      254152 :       if (tree[col[j]].f==Fnoarg)
     996           0 :         compile_err("missing matrix element",tree[col[j]].str);
     997      254152 :       compilenode(col[j], Ggen, FLsurvive);
     998      254152 :       op_push(OCstackgen,k,n);
     999             :     }
    1000             :   }
    1001        9680 :   set_avma(ltop);
    1002        9680 :   op_push(OCpop,1,n);
    1003        9680 :   compilecast(n,Gvec,mode);
    1004        9680 : }
    1005             : 
    1006             : static GEN
    1007       48924 : cattovec(long n, long fnum)
    1008             : {
    1009       48924 :   long x=n, y, i=0, nb;
    1010             :   GEN stack;
    1011       48924 :   if (tree[n].f==Fnoarg) return cgetg(1,t_VECSMALL);
    1012             :   while(1)
    1013         222 :   {
    1014       49146 :     long xx=tree[x].x;
    1015       49146 :     long xy=tree[x].y;
    1016       49146 :     if (tree[x].f!=Ffunction || xx!=fnum) break;
    1017         222 :     x=tree[xy].x;
    1018         222 :     y=tree[xy].y;
    1019         222 :     if (tree[y].f==Fnoarg)
    1020           0 :       compile_err("unexpected character: ", tree[y].str);
    1021         222 :     i++;
    1022             :   }
    1023       48924 :   if (tree[x].f==Fnoarg)
    1024           0 :     compile_err("unexpected character: ", tree[x].str);
    1025       48924 :   nb=i+1;
    1026       48924 :   stack=cgetg(nb+1,t_VECSMALL);
    1027       49146 :   for(x=n;i>0;i--)
    1028             :   {
    1029         222 :     long y=tree[x].y;
    1030         222 :     x=tree[y].x;
    1031         222 :     stack[i+1]=tree[y].y;
    1032             :   }
    1033       48924 :   stack[1]=x;
    1034       48924 :   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       23375 : compilecall(long n, int mode, entree *ep)
    1051             : {
    1052       23375 :   pari_sp ltop=avma;
    1053             :   long j;
    1054       23375 :   long x=tree[n].x, tx = tree[x].x;
    1055       23375 :   long y=tree[n].y;
    1056       23375 :   GEN arg=listtogen(y,Flistarg);
    1057       23375 :   long nb=lg(arg)-1;
    1058       23375 :   long lnc=first_safe_arg(arg, COsafelex|COsafedyn);
    1059       23375 :   long lnl=first_safe_arg(arg, COsafelex);
    1060       23375 :   long fl = lnl==0? (lnc==0? FLnocopy: FLnocopylex): 0;
    1061       23375 :   if (ep==NULL)
    1062         329 :     compilenode(x, Ggen, fl);
    1063             :   else
    1064             :   {
    1065       23046 :     long vn=getmvar(ep);
    1066       23046 :     if (vn)
    1067             :     {
    1068         567 :       access_push(vn);
    1069         567 :       op_push(OCpushlex,vn,n);
    1070             :     }
    1071             :     else
    1072       22479 :       op_push(OCpushdyn,(long)ep,n);
    1073             :   }
    1074       63044 :   for (j=1;j<=nb;j++)
    1075             :   {
    1076       39669 :     long x = tree[arg[j]].x, f = tree[arg[j]].f;
    1077       39669 :     if (f==Fseq)
    1078           0 :       compile_err("unexpected ';'", tree[x].str+tree[x].len);
    1079       39669 :     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       39543 :     } else if (tx==CSTmember)
    1089             :     {
    1090          28 :       compilenode(arg[j], Ggen,FLnocopy);
    1091          28 :       op_push(OClock,0,n);
    1092             :     }
    1093       39515 :     else if (f!=Fnoarg)
    1094       39263 :       compilenode(arg[j], Ggen,j>=lnl?FLnocopylex:0);
    1095             :     else
    1096         252 :       op_push(OCpushlong,0,n);
    1097             :   }
    1098       23375 :   op_push(OCcalluser,nb,x);
    1099       23375 :   compilecast(n,Ggen,mode);
    1100       23375 :   set_avma(ltop);
    1101       23375 : }
    1102             : 
    1103             : static GEN
    1104       20711 : compilefuncinline(long n, long c, long a, long flag, long isif, long lev, long *ev)
    1105             : {
    1106             :   struct codepos pos;
    1107       20711 :   int type=c=='I'?Gvoid:Ggen;
    1108       20711 :   long rflag=c=='I'?0:FLsurvive;
    1109       20711 :   long nbmvar = nblex;
    1110       20711 :   GEN vep = NULL;
    1111       20711 :   if (isif && (flag&FLreturn)) rflag|=FLreturn;
    1112       20711 :   getcodepos(&pos);
    1113       20711 :   if (c=='J') ctxmvar(nbmvar);
    1114       20711 :   if (lev)
    1115             :   {
    1116       12141 :     long i, slev = 0;
    1117       12141 :     GEN varg = cgetg(lev+1,t_VECSMALL);
    1118       12141 :     vep = cgetg(lev+1,t_VECSMALL);
    1119       25090 :     for (i = 1; i <= lev; i++)
    1120             :     {
    1121             :       entree *ve;
    1122       12956 :       long v = ev[i-1];
    1123       12956 :       if (v < 0)
    1124           0 :         compile_err("missing variable name", tree[a].str-1);
    1125       12956 :       ve = getvarvec(v);
    1126       12949 :       vep[i] = (long)ve;
    1127       12949 :       varg[i] = v;
    1128       12949 :       var_push(ve,Lmy);
    1129             :     }
    1130       12134 :     checkdups(varg,vep);
    1131       12134 :     if (c=='J')
    1132         359 :       op_push(OCgetargs,lev,n);
    1133       12134 :     access_push(lev);
    1134       12134 :     frame_push(vep);
    1135       25083 :     for (i = 1; i <= lev; i++)
    1136             :     {
    1137       12949 :       long v = ev[i-1];
    1138       12949 :       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       20704 :   if (c=='J')
    1170         359 :     return compilelambda(a,vep,nbmvar,&pos);
    1171       20345 :   if (tree[a].f==Fnoarg)
    1172         119 :     compilecast(a,Gvoid,type);
    1173             :   else
    1174       20226 :     compilenode(a,type,rflag);
    1175       20345 :   return getclosure(&pos, nbmvar);
    1176             : }
    1177             : 
    1178             : static long
    1179        3594 : countvar(GEN arg)
    1180             : {
    1181        3594 :   long i, l = lg(arg);
    1182        3594 :   long n = l-1;
    1183       11005 :   for(i=1; i<l; i++)
    1184             :   {
    1185        7411 :     long a=arg[i];
    1186        7411 :     if (tree[a].f==Fassign)
    1187             :     {
    1188        4175 :       long x = detag(tree[a].x);
    1189        4175 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1190         427 :         n += countmatrixelts(tree[x].x)-1;
    1191             :     }
    1192             :   }
    1193        3594 :   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        3566 : compilemy(GEN arg, const char *str, int inl)
    1210             : {
    1211        3566 :   long i, j, k, l = lg(arg);
    1212        3566 :   long n = countvar(arg);
    1213        3566 :   GEN vep = cgetg(n+1,t_VECSMALL);
    1214        3566 :   GEN ver = cgetg(n+1,t_VECSMALL);
    1215        3566 :   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       10921 :   for(k=0, i=1; i<l; i++)
    1222             :   {
    1223        7355 :     long a=arg[i];
    1224        7355 :     if (tree[a].f==Fassign)
    1225             :     {
    1226        4133 :       long x = detag(tree[a].x);
    1227        4133 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1228         413 :       {
    1229         413 :         GEN vars = listtogen(tree[x].x,Fmatrixelts);
    1230         413 :         long nv = lg(vars)-1;
    1231        1379 :         for (j=1; j<=nv; j++)
    1232         966 :           if (tree[vars[j]].f!=Fnoarg)
    1233             :           {
    1234         952 :             ver[++k] = vars[j];
    1235         952 :             vep[k] = (long)getvar(ver[k]);
    1236             :           }
    1237         413 :         continue;
    1238        3720 :       } else ver[++k] = x;
    1239        3222 :     } else ver[++k] = a;
    1240        6942 :     vep[k] = (long)getvar(ver[k]);
    1241             :   }
    1242        3566 :   checkdups(ver,vep);
    1243       11460 :   for(i=1; i<=n; i++) var_push(NULL,Lmy);
    1244        3566 :   op_push_loc(OCnewframe,inl?-n:n,str);
    1245        3566 :   access_push(lg(vep)-1);
    1246        3566 :   frame_push(vep);
    1247       10921 :   for (k=0, i=1; i<l; i++)
    1248             :   {
    1249        7355 :     long a=arg[i];
    1250        7355 :     if (tree[a].f==Fassign)
    1251             :     {
    1252        4133 :       long x = detag(tree[a].x);
    1253        4133 :       if (tree[x].f==Fvec && tree[x].x>=0)
    1254         413 :       {
    1255         413 :         GEN vars = listtogen(tree[x].x,Fmatrixelts);
    1256         413 :         long nv = lg(vars)-1, m = nv;
    1257         413 :         compilenode(tree[a].y,Ggen,FLnocopy);
    1258        1379 :         for (j=1; j<=nv; j++)
    1259         966 :           if (tree[vars[j]].f==Fnoarg) m--;
    1260         413 :         if (m > 1) op_push(OCdup,m-1,x);
    1261        1379 :         for (j=1; j<=nv; j++)
    1262         966 :           if (tree[vars[j]].f!=Fnoarg)
    1263             :           {
    1264         952 :             long v = detag(vars[j]);
    1265         952 :             op_push(OCpushlong,j,v);
    1266         952 :             op_push(OCcompo1,Ggen,v);
    1267         952 :             k++;
    1268         952 :             op_push(OCstorelex,-n+k-1,a);
    1269         952 :             localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k];
    1270         952 :             localvars[s_lvar.n-n+k-1].inl=inl;
    1271             :           }
    1272         413 :         continue;
    1273             :       }
    1274        3720 :       else if (!is_node_zero(tree[a].y))
    1275             :       {
    1276        3572 :         compilenode(tree[a].y,Ggen,FLnocopy);
    1277        3572 :         op_push(OCstorelex,-n+k,a);
    1278             :       }
    1279             :     }
    1280        6942 :     k++;
    1281        6942 :     localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k];
    1282        6942 :     localvars[s_lvar.n-n+k-1].inl=inl;
    1283             :   }
    1284        3566 : }
    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    10768714 : compilefunc(entree *ep, long n, int mode, long flag)
    1381             : {
    1382    10768714 :   pari_sp ltop=avma;
    1383             :   long j;
    1384    10768714 :   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    10768714 :   GEN arg=listtogen(y,Flistarg);
    1393    10768714 :   long lnc=first_safe_arg(arg, COsafelex|COsafedyn);
    1394    10768714 :   long lnl=first_safe_arg(arg, COsafelex);
    1395    10768714 :   long nbpointers=0, nbopcodes;
    1396    10768714 :   long nb=lg(arg)-1, lev=0;
    1397             :   long ev[20];
    1398    10768714 :   if (x>=OPnboperator)
    1399      207735 :     str=tree[x].str;
    1400             :   else
    1401             :   {
    1402    10560979 :     if (nb==2)
    1403     1149389 :       str=tree[arg[1]].str+tree[arg[1]].len;
    1404     9411590 :     else if (nb==1)
    1405     9410585 :       str=tree[arg[1]].str;
    1406             :     else
    1407        1005 :       str=tree[n].str;
    1408    10567424 :     while(*str==')') str++;
    1409             :   }
    1410    10768714 :   if (tree[n].f==Fassign)
    1411             :   {
    1412           0 :     nb=2; lnc=2; lnl=2; arg=mkvecsmall2(x,y);
    1413             :   }
    1414    10768714 :   else if (is_func_named(ep,"if"))
    1415             :   {
    1416        4921 :     if (nb>=4)
    1417         112 :       ep=is_entry("_multi_if");
    1418        4809 :     else if (mode==Gvoid)
    1419        3071 :       ep=is_entry("_void_if");
    1420             :   }
    1421    10763793 :   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     9003904 :     return;
    1427             :   }
    1428    10763688 :   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    10763675 :   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    10763669 :   else if (is_func_named(ep,"my"))
    1443             :   {
    1444        3553 :     compilemy(arg, str, 0);
    1445        3553 :     compilecast(n,Gvoid,mode);
    1446        3553 :     set_avma(ltop);
    1447        3553 :     return;
    1448             :   }
    1449    10760116 :   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    10760088 :   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    10760047 :   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    10760041 :   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    10760034 :   else if (is_func_named(ep,"O"))
    1497             :   {
    1498        4942 :     if (nb!=1)
    1499           0 :       compile_err("wrong number of arguments", tree[n].str+tree[n].len-1);
    1500        4942 :     ep=is_entry("O(_^_)");
    1501        4942 :     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    10755092 :   else if (x==OPn && tree[y].f==Fsmall)
    1510             :   {
    1511     8995602 :     set_avma(ltop);
    1512     8995602 :     compilesmall(y, -tree[y].x, mode);
    1513     8995602 :     return;
    1514             :   }
    1515     1759490 :   else if (x==OPtrans && tree[y].f==Fvec)
    1516             :   {
    1517        4543 :     set_avma(ltop);
    1518        4543 :     compilevec(y, mode, OCcol);
    1519        4543 :     return;
    1520     1754947 :   } 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     1754940 :   else if (x==OPpow && nb==2)
    1528       73319 :   {
    1529       73319 :     long a = arg[2];
    1530       73319 :     if (tree[a].f==Fsmall)
    1531             :     {
    1532       68556 :       if(tree[a].x==2) { nb--; ep=is_entry("sqr"); }
    1533       49141 :       else ep=is_entry("_^s");
    1534             :     }
    1535        4763 :     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     1681621 :   else if (x==OPcat)
    1546           0 :     compile_err("expected character: ',' or ')' instead of",
    1547           0 :         tree[arg[1]].str+tree[arg[1]].len);
    1548     1764810 :   p=ep->code;
    1549     1764810 :   if (!ep->value)
    1550           0 :     compile_err("unknown function",tree[n].str);
    1551     1764810 :   nbopcodes = s_opcode.n;
    1552     1764810 :   ret_op = get_ret_type(&p, ep->arity, &ret_typ, &ret_flag);
    1553     1764810 :   j=1;
    1554     1764810 :   if (*p)
    1555             :   {
    1556     1755594 :     q=p;
    1557     4899305 :     while((mod=parseproto(&p,&c,tree[n].str))!=PPend)
    1558             :     {
    1559     3143760 :       if (j<=nb && tree[arg[j]].f!=Fnoarg
    1560     3032169 :           && (mod==PPdefault || mod==PPdefaultmulti))
    1561       68217 :         mod=PPstd;
    1562     3143760 :       switch(mod)
    1563             :       {
    1564     3017142 :       case PPstd:
    1565     3017142 :         if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1);
    1566     3017142 :         if (c!='I' && c!='E' && c!='J')
    1567             :         {
    1568     2996893 :           long x = tree[arg[j]].x, f = tree[arg[j]].f;
    1569     2996893 :           if (f==Fnoarg)
    1570           0 :             compile_err("missing mandatory argument", tree[arg[j]].str);
    1571     2996893 :           if (f==Fseq)
    1572           0 :             compile_err("unexpected ';'", tree[x].str+tree[x].len);
    1573             :         }
    1574     3017142 :         switch(c)
    1575             :         {
    1576     2896914 :         case 'G':
    1577     2896914 :           compilenode(arg[j],Ggen,j>=lnl?(j>=lnc?FLnocopy:FLnocopylex):0);
    1578     2896914 :           j++;
    1579     2896914 :           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       76651 :           compilenode(arg[j++],Gsmall,0);
    1615       76644 :           break;
    1616         217 :         case 'U':
    1617         217 :           compilenode(arg[j++],Gusmall,0);
    1618         210 :           break;
    1619        3989 :         case 'n':
    1620        3989 :           compilenode(arg[j++],Gvar,0);
    1621        3982 :           break;
    1622        2308 :         case '&': case '*':
    1623             :           {
    1624        2308 :             long vn, a=arg[j++];
    1625             :             entree *ep;
    1626        2308 :             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        2308 :             a=detag(a);
    1633        2308 :             ep=getlvalue(a);
    1634        2308 :             vn=getmvar(ep);
    1635        2308 :             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         203 :               compilenewptr(vn, ep, a);
    1648         203 :               compilelvalue(a);
    1649         203 :               op_push(OCpushptr, 0, a);
    1650             :             }
    1651        2308 :             nbpointers++;
    1652        2308 :             break;
    1653             :           }
    1654       20249 :         case 'I':
    1655             :         case 'E':
    1656             :         case 'J':
    1657             :           {
    1658       20249 :             long a = arg[j++];
    1659       20249 :             GEN  d = compilefuncinline(n, c, a, flag, is_func_named(ep,"if"), lev, ev);
    1660       20242 :             op_push(OCpushgen, data_push(d), a);
    1661       20242 :             if (lg(d)==8) op_push(OCsaveframe,FLsurvive,n);
    1662       20242 :             break;
    1663             :           }
    1664        5534 :         case 'V':
    1665             :           {
    1666        5534 :             long a = arg[j++];
    1667        5534 :             ev[lev++] = a;
    1668        5534 :             break;
    1669             :           }
    1670        6867 :         case '=':
    1671             :           {
    1672        6867 :             long a = arg[j++];
    1673        6867 :             ev[lev++] = tree[a].x;
    1674        6867 :             compilenode(tree[a].y, Ggen, FLnocopy);
    1675             :           }
    1676        6867 :           break;
    1677        1075 :         case 'r':
    1678             :           {
    1679        1075 :             long a=arg[j++];
    1680        1075 :             if (tree[a].f==Fentry)
    1681             :             {
    1682        1012 :               op_push(OCpushgen, data_push(strntoGENstr(tree[tree[a].x].str,
    1683        1012 :                                                         tree[tree[a].x].len)),n);
    1684        1012 :               op_push(OCtostr, -1,n);
    1685             :             }
    1686             :             else
    1687             :             {
    1688          63 :               compilenode(a,Ggen,FLnocopy);
    1689          63 :               op_push(OCtostr, -1,n);
    1690             :             }
    1691        1075 :             break;
    1692             :           }
    1693        2757 :         case 's':
    1694             :           {
    1695        2757 :             long a = arg[j++];
    1696        2757 :             GEN g = cattovec(a, OPcat);
    1697        2757 :             long l, nb = lg(g)-1;
    1698        2757 :             if (nb==1)
    1699             :             {
    1700        2681 :               compilenode(g[1], Ggen, FLnocopy);
    1701        2681 :               op_push(OCtostr, -1, a);
    1702             :             } else
    1703             :             {
    1704          76 :               op_push(OCvec, nb+1, a);
    1705         228 :               for(l=1; l<=nb; l++)
    1706             :               {
    1707         152 :                 compilenode(g[l], Ggen, FLsurvive);
    1708         152 :                 op_push(OCstackgen,l, a);
    1709             :               }
    1710          76 :               op_push(OCpop, 1, a);
    1711          76 :               op_push(OCcallgen,(long)is_entry("Str"), a);
    1712          76 :               op_push(OCtostr, -1, a);
    1713             :             }
    1714        2757 :             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     3017100 :         break;
    1721       34006 :       case PPauto:
    1722       34006 :         switch(c)
    1723             :         {
    1724       29648 :         case 'p':
    1725       29648 :           op_push(OCprecreal,0,n);
    1726       29648 :           break;
    1727        4305 :         case 'b':
    1728        4305 :           op_push(OCbitprecreal,0,n);
    1729        4305 :           break;
    1730           0 :         case 'P':
    1731           0 :           op_push(OCprecdl,0,n);
    1732           0 :           break;
    1733          53 :         case 'C':
    1734          53 :           op_push(OCpushgen,data_push(pack_localvars()),n);
    1735          53 :           break;
    1736           0 :         case 'f':
    1737             :           {
    1738             :             static long foo;
    1739           0 :             op_push(OCpushlong,(long)&foo,n);
    1740           0 :             break;
    1741             :           }
    1742             :         }
    1743       34006 :         break;
    1744       44782 :       case PPdefault:
    1745       44782 :         j++;
    1746       44782 :         switch(c)
    1747             :         {
    1748        6411 :         case 'E':
    1749             :         case 'I':
    1750             :           {
    1751             :             long i;
    1752        9017 :             for (i = 0; i<lev; i++)
    1753        2613 :               if (ev[i]>=0) getvar(ev[i]);
    1754             :           }
    1755             :         case 'G': /*FALLTHROUGH*/
    1756             :         case '&':
    1757             :         case 'r':
    1758             :         case 's':
    1759       34449 :           op_push(OCpushlong,0,n);
    1760       34449 :           break;
    1761        9025 :         case 'n':
    1762        9025 :           op_push(OCpushlong,-1,n);
    1763        9025 :           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       44775 :         break;
    1775       32365 :       case PPdefaultmulti:
    1776       32365 :         j++;
    1777       32365 :         switch(c)
    1778             :         {
    1779           0 :         case 'G':
    1780           0 :           op_push(OCpushstoi,strtol(q+1,NULL,10),n);
    1781           0 :           break;
    1782       32284 :         case 'L':
    1783             :         case 'M':
    1784       32284 :           op_push(OCpushlong,strtol(q+1,NULL,10),n);
    1785       32284 :           break;
    1786          42 :         case 'U':
    1787          42 :           op_push(OCpushlong,(long)strtoul(q+1,NULL,10),n);
    1788          42 :           break;
    1789          39 :         case 'r':
    1790             :         case 's':
    1791          39 :           str_defproto(p, q, tree[n].str);
    1792          39 :           op_push(OCtostr, -1, n);
    1793          39 :           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       32365 :         break;
    1799       15465 :       case PPstar:
    1800       15465 :         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       15353 :         case 's':
    1815             :           {
    1816       15353 :             long n=nb+1-j;
    1817             :             long k,l,l1,m;
    1818       15353 :             GEN g=cgetg(n+1,t_VEC);
    1819       37058 :             for(l1=0,k=1;k<=n;k++)
    1820             :             {
    1821       21705 :               gel(g,k)=cattovec(arg[j+k-1],OPcat);
    1822       21705 :               l1+=lg(gel(g,k))-1;
    1823             :             }
    1824       15353 :             op_push_loc(OCvec, l1+1, str);
    1825       37058 :             for(m=1,k=1;k<=n;k++)
    1826       43445 :               for(l=1;l<lg(gel(g,k));l++,m++)
    1827             :               {
    1828       21740 :                 compilenode(mael(g,k,l),Ggen,FLsurvive);
    1829       21740 :                 op_push(OCstackgen,m,mael(g,k,l));
    1830             :               }
    1831       15353 :             op_push_loc(OCpop, 1, str);
    1832       15353 :             j=nb+1;
    1833       15353 :             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       15465 :         break;
    1840           0 :       default:
    1841           0 :         pari_err_BUG("compilefunc [unknown PPproto]");
    1842             :       }
    1843     3143711 :       q=p;
    1844             :     }
    1845             :   }
    1846     1764761 :   if (j<=nb)
    1847           0 :     compile_err("too many arguments",tree[arg[j]].str);
    1848     1764761 :   op_push_loc(ret_op, (long) ep, str);
    1849     1764761 :   if (mode==Ggen && (ret_flag&FLnocopy) && !(flag&FLnocopy))
    1850       10688 :     op_push_loc(OCcopy,0,str);
    1851     1764761 :   if (ret_typ==Ggen && nbpointers==0 && s_opcode.n>nbopcodes+128)
    1852             :   {
    1853        2975 :     op_insert_loc(nbopcodes,OCavma,0,str);
    1854        2975 :     op_push_loc(OCgc,0,str);
    1855             :   }
    1856     1764761 :   compilecast(n,ret_typ,mode);
    1857     1764761 :   if (nbpointers) op_push_loc(OCendptr,nbpointers, str);
    1858     1764761 :   set_avma(ltop);
    1859             : }
    1860             : 
    1861             : static void
    1862     9138962 : genclosurectx(const char *loc, long nbdata)
    1863             : {
    1864             :   long i;
    1865     9138962 :   GEN vep = cgetg(nbdata+1,t_VECSMALL);
    1866    32794187 :   for(i = 1; i <= nbdata; i++)
    1867             :   {
    1868    23655268 :     vep[i] = 0;
    1869    23655268 :     op_push_loc(OCpushlex,-i,loc);
    1870             :   }
    1871     9138919 :   frame_push(vep);
    1872     9139024 : }
    1873             : 
    1874             : static GEN
    1875     9149796 : genclosure(entree *ep, const char *loc, long nbdata, int check)
    1876             : {
    1877             :   struct codepos pos;
    1878     9149796 :   long nb=0;
    1879     9149796 :   const char *code=ep->code,*p,*q;
    1880             :   char c;
    1881             :   GEN text;
    1882     9149796 :   long index=ep->arity;
    1883     9149796 :   long arity=0, maskarg=0, maskarg0=0, stop=0, dovararg=0;
    1884             :   PPproto mod;
    1885             :   Gtype ret_typ;
    1886             :   long ret_flag;
    1887     9149796 :   op_code ret_op=get_ret_type(&code,ep->arity,&ret_typ,&ret_flag);
    1888     9149765 :   p=code;
    1889    41955176 :   while ((mod=parseproto(&p,&c,NULL))!=PPend)
    1890             :   {
    1891    32805411 :     if (mod==PPauto)
    1892        2066 :       stop=1;
    1893             :     else
    1894             :     {
    1895    32803345 :       if (stop) return NULL;
    1896    32803345 :       if (c=='V') continue;
    1897    32803345 :       maskarg<<=1; maskarg0<<=1; arity++;
    1898    32803345 :       switch(mod)
    1899             :       {
    1900    32802142 :       case PPstd:
    1901    32802142 :         maskarg|=1L;
    1902    32802142 :         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         721 :       default:
    1914         721 :         break;
    1915             :       }
    1916             :     }
    1917             :   }
    1918     9149678 :   if (check && EpSTATIC(ep) && maskarg==0)
    1919        8917 :     return gen_0;
    1920     9140761 :   getcodepos(&pos);
    1921     9140788 :   dbgstart = loc;
    1922     9140788 :   if (nbdata > arity)
    1923           0 :     pari_err(e_MISC,"too many parameters for closure `%s'", ep->name);
    1924     9140788 :   if (nbdata) genclosurectx(loc, nbdata);
    1925     9140841 :   text = strtoGENstr(ep->name);
    1926     9140772 :   arity -= nbdata;
    1927     9140772 :   if (maskarg)  op_push_loc(OCcheckargs,maskarg,loc);
    1928     9140720 :   if (maskarg0) op_push_loc(OCcheckargs0,maskarg0,loc);
    1929     9140720 :   p=code;
    1930    41944033 :   while ((mod=parseproto(&p,&c,NULL))!=PPend)
    1931             :   {
    1932    32803284 :     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          29 :         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    32803313 :       break;
    1958             :     }
    1959             :   }
    1960     9140739 :   q = p = code;
    1961    41944030 :   while ((mod=parseproto(&p,&c,NULL))!=PPend)
    1962             :   {
    1963    32803291 :     switch(mod)
    1964             :     {
    1965    32801866 :     case PPstd:
    1966    32801866 :       switch(c)
    1967             :       {
    1968    32758380 :       case 'G':
    1969    32758380 :         break;
    1970       31999 :       case 'M':
    1971             :       case 'L':
    1972       31999 :         op_push_loc(OCitos,-index,loc);
    1973       31999 :         break;
    1974       11455 :       case 'U':
    1975       11455 :         op_push_loc(OCitou,-index,loc);
    1976       11455 :         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          28 :       case 'r':
    1987             :       case 's':
    1988          28 :         op_push_loc(OCtostr,-index,loc);
    1989          28 :         break;
    1990             :       }
    1991    32801866 :       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         319 :     case PPdefaultmulti:
    2019         319 :       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           0 :       case 'r':
    2035             :       case 's':
    2036           0 :         str_defproto(p, q, loc);
    2037           0 :         op_push_loc(OCdefaultgen,-index,loc);
    2038           0 :         op_push_loc(OCtostr,-index,loc);
    2039           0 :         break;
    2040           0 :       default:
    2041           0 :         pari_err(e_MISC,
    2042             :             "Unknown prototype code `D...,%c,' for `%s'",c,ep->name);
    2043             :       }
    2044         319 :       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    32803291 :     index--;
    2061    32803291 :     q = p;
    2062             :   }
    2063     9140686 :   op_push_loc(ret_op, (long) ep, loc);
    2064     9140742 :   if (ret_flag==FLnocopy) op_push_loc(OCcopy,0,loc);
    2065     9140742 :   compilecast_loc(ret_typ, Ggen, loc);
    2066     9140739 :   if (dovararg) nb|=VARARGBITS;
    2067     9140739 :   return getfunction(&pos,nb+arity,nbdata,text,0);
    2068             : }
    2069             : 
    2070             : GEN
    2071     9137353 : snm_closure(entree *ep, GEN data)
    2072             : {
    2073     9137353 :   long i, n = data ? lg(data)-1: 0;
    2074     9137353 :   GEN C = genclosure(ep,ep->name,n,0);
    2075    32786151 :   for(i = 1; i <= n; i++) gmael(C,7,i) = gel(data,i);
    2076     9137332 :   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       10616 : closurefunc(entree *ep, long n, long mode)
    2141             : {
    2142       10616 :   pari_sp ltop=avma;
    2143             :   GEN C;
    2144       10616 :   if (!ep->value) compile_err("unknown function",tree[n].str);
    2145       10616 :   C = genclosure(ep,tree[n].str,0,1);
    2146       10616 :   if (!C) compile_err("sorry, closure not implemented",tree[n].str);
    2147       10616 :   if (C==gen_0)
    2148             :   {
    2149        8917 :     compilefunc(ep,n,mode,0);
    2150        8917 :     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       15220 : compileseq(long n, int mode, long flag)
    2159             : {
    2160       15220 :   pari_sp av = avma;
    2161       15220 :   GEN L = listtogen(n, Fseq);
    2162       15220 :   long i, l = lg(L)-1;
    2163       48422 :   for(i = 1; i < l; i++)
    2164       33202 :     compilenode(L[i],Gvoid,0);
    2165       15220 :   compilenode(L[l],mode,flag&(FLreturn|FLsurvive));
    2166       15220 :   set_avma(av);
    2167       15220 : }
    2168             : 
    2169             : static void
    2170    52951041 : compilenode(long n, int mode, long flag)
    2171             : {
    2172             :   long x,y;
    2173             : #ifdef STACK_CHECK
    2174    52951041 :   if (PARI_stack_limit && (void*) &x <= PARI_stack_limit)
    2175           0 :     pari_err(e_MISC, "expression nested too deeply");
    2176             : #endif
    2177    52951041 :   if (n<0) pari_err_BUG("compilenode");
    2178    52951041 :   x=tree[n].x;
    2179    52951041 :   y=tree[n].y;
    2180             : 
    2181    52951041 :   switch(tree[n].f)
    2182             :   {
    2183       15220 :   case Fseq:
    2184       15220 :     compileseq(n, mode, flag);
    2185    52950971 :     return;
    2186       13609 :   case Fmatcoeff:
    2187       13609 :     compilematcoeff(n,mode);
    2188       13602 :     if (mode==Ggen && !(flag&FLnocopy))
    2189        4283 :       op_push(OCcopy,0,n);
    2190       13602 :     return;
    2191       45809 :   case Fassign:
    2192       45809 :     x = detag(x);
    2193       45809 :     if (tree[x].f==Fvec && tree[x].x>=0)
    2194         805 :     {
    2195         805 :       GEN vars = listtogen(tree[x].x,Fmatrixelts);
    2196         805 :       long i, l = lg(vars)-1, d = mode==Gvoid? l-1: l;
    2197         805 :       compilenode(y,Ggen,mode==Gvoid?0:flag&FLsurvive);
    2198        2513 :       for (i=1; i<=l; i++)
    2199        1708 :         if (tree[vars[i]].f==Fnoarg) d--;
    2200         805 :       if (d) op_push(OCdup, d, x);
    2201        2513 :       for(i=1; i<=l; i++)
    2202        1708 :         if (tree[vars[i]].f!=Fnoarg)
    2203             :         {
    2204        1694 :           long a = detag(vars[i]);
    2205        1694 :           entree *ep=getlvalue(a);
    2206        1694 :           long vn=getmvar(ep);
    2207        1694 :           op_push(OCpushlong,i,a);
    2208        1694 :           op_push(OCcompo1,Ggen,a);
    2209        1694 :           if (tree[a].f==Fentry)
    2210        1687 :             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         805 :       if (mode!=Gvoid)
    2219         462 :         compilecast(n,Ggen,mode);
    2220             :     }
    2221             :     else
    2222             :     {
    2223       45004 :       entree *ep=getlvalue(x);
    2224       45004 :       long vn=getmvar(ep);
    2225       45004 :       if (tree[x].f!=Fentry)
    2226             :       {
    2227         637 :         compilenewptr(vn,ep,n);
    2228         637 :         compilelvalue(x);
    2229             :       }
    2230       45004 :       compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive);
    2231       45004 :       if (mode!=Gvoid)
    2232       29738 :         op_push(OCdup,1,n);
    2233       45004 :       if (tree[x].f==Fentry)
    2234       44367 :         compilestore(vn,ep,n);
    2235             :       else
    2236         637 :         op_push(OCstoreptr,0,x);
    2237       45004 :       if (mode!=Gvoid)
    2238       29738 :         compilecast(n,Ggen,mode);
    2239             :     }
    2240       45809 :     return;
    2241     4775577 :   case Fconst:
    2242             :     {
    2243     4775577 :       pari_sp ltop=avma;
    2244     4775577 :       if (tree[n].x!=CSTquote)
    2245             :       {
    2246     4771773 :         if (mode==Gvoid) return;
    2247     4771773 :         if (mode==Gvar) compile_varerr(tree[n].str);
    2248             :       }
    2249     4775577 :       if (mode==Gsmall) L_compile_err(tree[n].str);
    2250     4775577 :       if (mode==Gusmall && tree[n].x != CSTint) U_compile_err(tree[n].str);
    2251     4775570 :       switch(tree[n].x)
    2252             :       {
    2253        6290 :       case CSTreal:
    2254        6290 :         op_push(OCpushreal, data_push(strntoGENstr(tree[n].str,tree[n].len)),n);
    2255        6290 :         break;
    2256      943190 :       case CSTint:
    2257      943190 :         op_push(OCpushgen,  data_push(strtoi((char*)tree[n].str)),n);
    2258      943190 :         compilecast(n,Ggen, mode);
    2259      943190 :         break;
    2260     3822286 :       case CSTstr:
    2261     3822286 :         op_push(OCpushgen,  data_push(strntoGENexp(tree[n].str,tree[n].len)),n);
    2262     3822286 :         break;
    2263        3804 :       case CSTquote:
    2264             :         { /* skip ' */
    2265        3804 :           entree *ep = fetch_entry_raw(tree[n].str+1,tree[n].len-1);
    2266        3804 :           if (EpSTATIC(ep)) compile_varerr(tree[n].str+1);
    2267        3804 :           op_push(OCpushvar, (long)ep,n);
    2268        3804 :           compilecast(n,Ggen, mode);
    2269        3804 :           break;
    2270             :         }
    2271           0 :       default:
    2272           0 :         pari_err_BUG("compilenode, unsupported constant");
    2273             :       }
    2274     4775570 :       set_avma(ltop);
    2275     4775570 :       return;
    2276             :     }
    2277    21557013 :   case Fsmall:
    2278    21557013 :     compilesmall(n, x, mode);
    2279    21557006 :     return;
    2280    15455971 :   case Fvec:
    2281    15455971 :     compilevec(n, mode, OCvec);
    2282    15455971 :     return;
    2283        9680 :   case Fmat:
    2284        9680 :     compilemat(n, mode);
    2285        9680 :     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      285324 :   case Fentry:
    2293             :     {
    2294      285324 :       entree *ep=getentry(n);
    2295      285324 :       long vn=getmvar(ep);
    2296      285324 :       if (vn)
    2297             :       {
    2298       73346 :         access_push(vn);
    2299       73346 :         op_push(OCpushlex,(long)vn,n);
    2300       73346 :         addcopy(n,mode,flag,FLnocopy|FLnocopylex);
    2301       73346 :         compilecast(n,Ggen,mode);
    2302             :       }
    2303      211978 :       else if (ep->valence==EpVAR || ep->valence==EpNEW)
    2304             :       {
    2305      201362 :         if (DEBUGLEVEL && mode==Gvoid)
    2306           0 :           pari_warn(warner,"statement with no effect: `%s'",ep->name);
    2307      201362 :         op_push(OCpushdyn,(long)ep,n);
    2308      201362 :         addcopy(n,mode,flag,FLnocopy);
    2309      201362 :         compilecast(n,Ggen,mode);
    2310             :       }
    2311             :       else
    2312       10616 :         closurefunc(ep,n,mode);
    2313      285324 :       return;
    2314             :     }
    2315    10782843 :   case Ffunction:
    2316             :     {
    2317    10782843 :       entree *ep=getfunc(n);
    2318    10782843 :       if (getmvar(ep) || EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)
    2319             :       {
    2320       23046 :         if (tree[n].x<OPnboperator) /* should not happen */
    2321           0 :           compile_err("operator unknown",tree[n].str);
    2322       23046 :         compilecall(n,mode,ep);
    2323             :       }
    2324             :       else
    2325    10759797 :         compilefunc(ep,n,mode,flag);
    2326    10782794 :       return;
    2327             :     }
    2328         329 :   case Fcall:
    2329         329 :     compilecall(n,mode,NULL);
    2330         329 :     return;
    2331        9379 :   case Flambda:
    2332             :     {
    2333        9379 :       pari_sp ltop=avma;
    2334             :       struct codepos pos;
    2335        9379 :       GEN arg=listtogen(x,Flistarg);
    2336        9379 :       long nb, lgarg, nbmvar, dovararg=0, gap;
    2337        9379 :       long strict = GP_DATA->strictargs;
    2338        9379 :       GEN vep = cgetg_copy(arg, &lgarg);
    2339        9379 :       GEN text=cgetg(3,t_VEC);
    2340        9379 :       gel(text,1)=strntoGENstr(tree[x].str,tree[x].len);
    2341        9379 :       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        9379 :       gel(text,2)=strntoGENstr(tree[y].str,tree[y].len);
    2345        9379 :       getcodepos(&pos);
    2346        9379 :       dbgstart=tree[x].str+tree[x].len;
    2347        9379 :       gap = tree[y].str-dbgstart;
    2348        9379 :       nbmvar = nblex;
    2349        9379 :       ctxmvar(nbmvar);
    2350        9379 :       nb = lgarg-1;
    2351        9379 :       if (nb)
    2352             :       {
    2353             :         long i;
    2354       13702 :         for(i=1;i<=nb;i++)
    2355             :         {
    2356        8421 :           long a = arg[i], f = tree[a].f;
    2357        8421 :           if (i==nb && f==Fvararg)
    2358             :           {
    2359          21 :             dovararg=1;
    2360          21 :             vep[i]=(long)getvar(tree[a].x);
    2361             :           }
    2362             :           else
    2363        8400 :             vep[i]=(long)getvar(f==Fassign||f==Findarg?tree[a].x:a);
    2364        8421 :           var_push(NULL,Lmy);
    2365             :         }
    2366        5281 :         checkdups(arg,vep);
    2367        5281 :         op_push(OCgetargs,nb,x);
    2368        5281 :         access_push(lg(vep)-1);
    2369        5281 :         frame_push(vep);
    2370       13702 :         for (i=1;i<=nb;i++)
    2371             :         {
    2372        8421 :           long a = arg[i], f = tree[a].f;
    2373        8421 :           long y = tree[a].y;
    2374        8421 :           if (f==Fassign && (strict || !is_node_zero(y)))
    2375             :           {
    2376         385 :             if (tree[y].f==Fsmall)
    2377         294 :               compilenode(y, Ggen, 0);
    2378             :             else
    2379             :             {
    2380             :               struct codepos lpos;
    2381          91 :               long nbmvar = nblex;
    2382          91 :               getcodepos(&lpos);
    2383          91 :               compilenode(y, Ggen, 0);
    2384          91 :               op_push(OCpushgen, data_push(getclosure(&lpos,nbmvar)),a);
    2385             :             }
    2386         385 :             op_push(OCdefaultarg,-nb+i-1,a);
    2387        8036 :           } else if (f==Findarg)
    2388          84 :             op_push(OCsetref, -nb+i-1, a);
    2389        8421 :           localvars[s_lvar.n-nb+i-1].ep=(entree*)vep[i];
    2390             :         }
    2391             :       }
    2392        9379 :       if (strict)
    2393          21 :         op_push(OCcheckuserargs,nb,x);
    2394        9379 :       dbgstart=tree[y].str;
    2395        9379 :       if (y>=0 && tree[y].f!=Fnoarg)
    2396        9379 :         compilenode(y,Ggen,FLsurvive|FLreturn);
    2397             :       else
    2398           0 :         compilecast(n,Gvoid,Ggen);
    2399        9379 :       if (dovararg) nb|=VARARGBITS;
    2400        9379 :       op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text,gap)),n);
    2401        9379 :       if (nbmvar) op_push(OCsaveframe,!!(flag&FLsurvive),n);
    2402        9379 :       compilecast(n, Gclosure, mode);
    2403        9379 :       set_avma(ltop);
    2404        9379 :       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      937125 : gp_closure(long n)
    2423             : {
    2424             :   struct codepos pos;
    2425      937125 :   getcodepos(&pos);
    2426      937125 :   dbgstart=tree[n].str;
    2427      937125 :   compilenode(n,Ggen,FLsurvive|FLreturn);
    2428      937076 :   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    15558676 : vec_optimize(GEN arg)
    2469             : {
    2470    15558676 :   long fl = COsafelex|COsafedyn;
    2471             :   long i;
    2472    64443634 :   for (i=1; i<lg(arg); i++)
    2473             :   {
    2474    48884965 :     optimizenode(arg[i]);
    2475    48884958 :     fl &= tree[arg[i]].flags;
    2476             :   }
    2477    15558669 :   return fl;
    2478             : }
    2479             : 
    2480             : static void
    2481    15461746 : optimizevec(long n)
    2482             : {
    2483    15461746 :   pari_sp ltop=avma;
    2484    15461746 :   long x = tree[n].x;
    2485    15461746 :   GEN  arg = listtogen(x, Fmatrixelts);
    2486    15461746 :   tree[n].flags = vec_optimize(arg);
    2487    15461746 :   set_avma(ltop);
    2488    15461746 : }
    2489             : 
    2490             : static void
    2491        9680 : optimizemat(long n)
    2492             : {
    2493        9680 :   pari_sp ltop = avma;
    2494        9680 :   long x = tree[n].x;
    2495             :   long i;
    2496        9680 :   GEN line = listtogen(x,Fmatrixlines);
    2497        9680 :   long fl = COsafelex|COsafedyn;
    2498       48031 :   for(i=1;i<lg(line);i++)
    2499             :   {
    2500       38351 :     GEN col=listtogen(line[i],Fmatrixelts);
    2501       38351 :     fl &= vec_optimize(col);
    2502             :   }
    2503        9680 :   set_avma(ltop); tree[n].flags=fl;
    2504        9680 : }
    2505             : 
    2506             : static void
    2507       14610 : optimizematcoeff(long n)
    2508             : {
    2509       14610 :   long x=tree[n].x;
    2510       14610 :   long y=tree[n].y;
    2511       14610 :   long yx=tree[y].x;
    2512       14610 :   long yy=tree[y].y;
    2513             :   long fl;
    2514       14610 :   optimizenode(x);
    2515       14610 :   optimizenode(yx);
    2516       14610 :   fl=tree[x].flags&tree[yx].flags;
    2517       14610 :   if (yy>=0)
    2518             :   {
    2519        1756 :     optimizenode(yy);
    2520        1756 :     fl&=tree[yy].flags;
    2521             :   }
    2522       14610 :   tree[n].flags=fl;
    2523       14610 : }
    2524             : 
    2525             : static void
    2526    10763906 : optimizefunc(entree *ep, long n)
    2527             : {
    2528    10763906 :   pari_sp av=avma;
    2529             :   long j;
    2530    10763906 :   long x=tree[n].x;
    2531    10763906 :   long y=tree[n].y;
    2532             :   Gtype t;
    2533             :   PPproto mod;
    2534    10763906 :   long fl=COsafelex|COsafedyn;
    2535             :   const char *p;
    2536             :   char c;
    2537    10763906 :   GEN arg = listtogen(y,Flistarg);
    2538    10763906 :   long nb=lg(arg)-1, ret_flag;
    2539    10763906 :   if (is_func_named(ep,"if") && nb>=4)
    2540         112 :     ep=is_entry("_multi_if");
    2541    10763906 :   p = ep->code;
    2542    10763906 :   if (!p)
    2543        3654 :     fl=0;
    2544             :   else
    2545    10760252 :     (void) get_ret_type(&p, 2, &t, &ret_flag);
    2546    10763906 :   if (p && *p)
    2547             :   {
    2548    10753171 :     j=1;
    2549    22986567 :     while((mod=parseproto(&p,&c,tree[n].str))!=PPend)
    2550             :     {
    2551    12233424 :       if (j<=nb && tree[arg[j]].f!=Fnoarg
    2552    12051386 :           && (mod==PPdefault || mod==PPdefaultmulti))
    2553       64591 :         mod=PPstd;
    2554    12233424 :       switch(mod)
    2555             :       {
    2556    12036387 :       case PPstd:
    2557    12036387 :         if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1);
    2558    12036359 :         if (tree[arg[j]].f==Fnoarg && c!='I' && c!='E')
    2559           0 :           compile_err("missing mandatory argument", tree[arg[j]].str);
    2560    12036359 :         switch(c)
    2561             :         {
    2562    11997009 :         case 'G':
    2563             :         case 'n':
    2564             :         case 'M':
    2565             :         case 'L':
    2566             :         case 'U':
    2567             :         case 'P':
    2568    11997009 :           optimizenode(arg[j]);
    2569    11997009 :           fl&=tree[arg[j++]].flags;
    2570    11997009 :           break;
    2571       20249 :         case 'I':
    2572             :         case 'E':
    2573             :         case 'J':
    2574       20249 :           optimizenode(arg[j]);
    2575       20249 :           fl&=tree[arg[j]].flags;
    2576       20249 :           tree[arg[j++]].flags=COsafelex|COsafedyn;
    2577       20249 :           break;
    2578        2308 :         case '&': case '*':
    2579             :           {
    2580        2308 :             long a=arg[j];
    2581        2308 :             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        2308 :             optimizenode(a);
    2588        2308 :             tree[arg[j++]].flags=COsafelex|COsafedyn;
    2589        2308 :             fl=0;
    2590        2308 :             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        6609 :         case 'V':
    2600             :         case 'r':
    2601        6609 :           tree[arg[j++]].flags=COsafelex|COsafedyn;
    2602        6609 :           break;
    2603        6867 :         case '=':
    2604             :           {
    2605        6867 :             long a=arg[j++], y=tree[a].y;
    2606        6867 :             if (tree[a].f!=Fassign)
    2607           0 :               compile_err("expected character: '=' instead of",
    2608           0 :                   tree[a].str+tree[a].len);
    2609        6867 :             optimizenode(y);
    2610        6867 :             fl&=tree[y].flags;
    2611             :           }
    2612        6867 :           break;
    2613        2757 :         case 's':
    2614        2757 :           fl &= vec_optimize(cattovec(arg[j++], OPcat));
    2615        2757 :           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    12036359 :         break;
    2621      106069 :       case PPauto:
    2622      106069 :         break;
    2623       75503 :       case PPdefault:
    2624             :       case PPdefaultmulti:
    2625       75503 :         if (j<=nb) optimizenode(arg[j++]);
    2626       75503 :         break;
    2627       15465 :       case PPstar:
    2628       15465 :         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       15353 :         case 's':
    2643             :           {
    2644       15353 :             long n=nb+1-j;
    2645             :             long k;
    2646       37058 :             for(k=1;k<=n;k++)
    2647       21705 :               fl &= vec_optimize(cattovec(arg[j+k-1],OPcat));
    2648       15353 :             j=nb+1;
    2649       15353 :             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       15465 :         break;
    2656           0 :       default:
    2657           0 :         pari_err_BUG("optimizefun [unknown PPproto]");
    2658             :       }
    2659             :     }
    2660    10753143 :     if (j<=nb)
    2661           0 :       compile_err("too many arguments",tree[arg[j]].str);
    2662             :   }
    2663       10735 :   else (void)vec_optimize(arg);
    2664    10763878 :   set_avma(av); tree[n].flags=fl;
    2665    10763878 : }
    2666             : 
    2667             : static void
    2668       23382 : optimizecall(long n)
    2669             : {
    2670       23382 :   pari_sp av=avma;
    2671       23382 :   long x=tree[n].x;
    2672       23382 :   long y=tree[n].y;
    2673       23382 :   GEN arg=listtogen(y,Flistarg);
    2674       23382 :   optimizenode(x);
    2675       23382 :   tree[n].flags = COsafelex&tree[x].flags&vec_optimize(arg);
    2676       23375 :   set_avma(av);
    2677       23375 : }
    2678             : 
    2679             : static void
    2680       15220 : optimizeseq(long n)
    2681             : {
    2682       15220 :   pari_sp av = avma;
    2683       15220 :   GEN L = listtogen(n, Fseq);
    2684       15220 :   long i, l = lg(L)-1, flags=-1L;
    2685       63642 :   for(i = 1; i <= l; i++)
    2686             :   {
    2687       48422 :     optimizenode(L[i]);
    2688       48422 :     flags &= tree[L[i]].flags;
    2689             :   }
    2690       15220 :   set_avma(av);
    2691       15220 :   tree[n].flags = flags;
    2692       15220 : }
    2693             : 
    2694             : void
    2695    62098825 : optimizenode(long n)
    2696             : {
    2697             :   long x,y;
    2698             : #ifdef STACK_CHECK
    2699    62098825 :   if (PARI_stack_limit && (void*) &x <= PARI_stack_limit)
    2700           0 :     pari_err(e_MISC, "expression nested too deeply");
    2701             : #endif
    2702    62098825 :   if (n<0)
    2703           0 :     pari_err_BUG("optimizenode");
    2704    62098825 :   x=tree[n].x;
    2705    62098825 :   y=tree[n].y;
    2706             : 
    2707    62098825 :   switch(tree[n].f)
    2708             :   {
    2709       15220 :   case Fseq:
    2710       15220 :     optimizeseq(n);
    2711    62017802 :     return;
    2712       16366 :   case Frange:
    2713       16366 :     optimizenode(x);
    2714       16366 :     optimizenode(y);
    2715       16366 :     tree[n].flags=tree[x].flags&tree[y].flags;
    2716       16366 :     break;
    2717       14610 :   case Fmatcoeff:
    2718       14610 :     optimizematcoeff(n);
    2719       14610 :     break;
    2720       50005 :   case Fassign:
    2721       50005 :     optimizenode(x);
    2722       50005 :     optimizenode(y);
    2723       50005 :     tree[n].flags=0;
    2724       50005 :     break;
    2725    35734398 :   case Fnoarg:
    2726             :   case Fnorange:
    2727             :   case Fsmall:
    2728             :   case Fconst:
    2729             :   case Fentry:
    2730    35734398 :     tree[n].flags=COsafelex|COsafedyn;
    2731    35734398 :     return;
    2732    15461746 :   case Fvec:
    2733    15461746 :     optimizevec(n);
    2734    15461746 :     return;
    2735        9680 :   case Fmat:
    2736        9680 :     optimizemat(n);
    2737        9680 :     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    10786959 :   case Ffunction:
    2747             :     {
    2748    10786959 :       entree *ep=getfunc(n);
    2749    10786959 :       if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)
    2750       23053 :         optimizecall(n);
    2751             :       else
    2752    10763906 :         optimizefunc(ep,n);
    2753    10786924 :       return;
    2754             :     }
    2755         329 :   case Fcall:
    2756         329 :     optimizecall(n);
    2757         329 :     return;
    2758        9379 :   case Flambda:
    2759        9379 :     optimizenode(y);
    2760        9379 :     tree[n].flags=COsafelex|COsafedyn;
    2761        9379 :     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 1.16