Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2006 The PARI group.12This file is part of the PARI package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314#include "pari.h"15#include "paripriv.h"16#include "anal.h"17#include "tree.h"18#include "opcode.h"1920#define DEBUGLEVEL DEBUGLEVEL_compiler2122#define tree pari_tree2324enum COflags {COsafelex=1, COsafedyn=2};2526/***************************************************************************27** **28** String constant expansion **29** **30***************************************************************************/3132static char *33translate(const char **src, char *s)34{35const char *t = *src;36while (*t)37{38while (*t == '\\')39{40switch(*++t)41{42case 'e': *s='\033'; break; /* escape */43case 'n': *s='\n'; break;44case 't': *s='\t'; break;45default: *s=*t; if (!*t) { *src=s; return NULL; }46}47t++; s++;48}49if (*t == '"')50{51if (t[1] != '"') break;52t += 2; continue;53}54*s++ = *t++;55}56*s=0; *src=t; return s;57}5859static void60matchQ(const char *s, char *entry)61{62if (*s != '"')63pari_err(e_SYNTAX,"expected character: '\"' instead of",s,entry);64}6566/* Read a "string" from src. Format then copy it, starting at s. Return67* pointer to char following the end of the input string */68char *69pari_translate_string(const char *src, char *s, char *entry)70{71matchQ(src, entry); src++; s = translate(&src, s);72if (!s) pari_err(e_SYNTAX,"run-away string",src,entry);73matchQ(src, entry); return (char*)src+1;74}7576static GEN77strntoGENexp(const char *str, long len)78{79long n = nchar2nlong(len-1);80GEN z = cgetg(1+n, t_STR);81const char *t = str+1;82z[n] = 0;83if (!translate(&t, GSTR(z))) compile_err("run-away string",str);84return z;85}8687/***************************************************************************88** **89** Byte-code compiler **90** **91***************************************************************************/9293typedef enum {Llocal, Lmy} Ltype;9495struct vars_s96{97Ltype type; /*Only Llocal and Lmy are allowed */98int inl;99entree *ep;100};101102struct frame_s103{104long pc;105GEN frame;106};107108static THREAD pari_stack s_opcode, s_operand, s_data, s_lvar;109static THREAD pari_stack s_dbginfo, s_frame, s_accesslex;110static THREAD char *opcode;111static THREAD long *operand;112static THREAD long *accesslex;113static THREAD GEN *data;114static THREAD long offset, nblex;115static THREAD struct vars_s *localvars;116static THREAD const char **dbginfo, *dbgstart;117static THREAD struct frame_s *frames;118119void120pari_init_compiler(void)121{122pari_stack_init(&s_opcode,sizeof(*opcode),(void **)&opcode);123pari_stack_init(&s_operand,sizeof(*operand),(void **)&operand);124pari_stack_init(&s_accesslex,sizeof(*operand),(void **)&accesslex);125pari_stack_init(&s_data,sizeof(*data),(void **)&data);126pari_stack_init(&s_lvar,sizeof(*localvars),(void **)&localvars);127pari_stack_init(&s_dbginfo,sizeof(*dbginfo),(void **)&dbginfo);128pari_stack_init(&s_frame,sizeof(*frames),(void **)&frames);129offset=-1; nblex=0;130}131void132pari_close_compiler(void)133{134pari_stack_delete(&s_opcode);135pari_stack_delete(&s_operand);136pari_stack_delete(&s_accesslex);137pari_stack_delete(&s_data);138pari_stack_delete(&s_lvar);139pari_stack_delete(&s_dbginfo);140pari_stack_delete(&s_frame);141}142143struct codepos144{145long opcode, data, localvars, frames, accesslex;146long offset, nblex;147const char *dbgstart;148};149150static void151getcodepos(struct codepos *pos)152{153pos->opcode=s_opcode.n;154pos->accesslex=s_accesslex.n;155pos->data=s_data.n;156pos->offset=offset;157pos->nblex=nblex;158pos->localvars=s_lvar.n;159pos->dbgstart=dbgstart;160pos->frames=s_frame.n;161offset=s_data.n-1;162}163164void165compilestate_reset(void)166{167s_opcode.n=0;168s_operand.n=0;169s_accesslex.n=0;170s_dbginfo.n=0;171s_data.n=0;172s_lvar.n=0;173s_frame.n=0;174offset=-1;175nblex=0;176dbgstart=NULL;177}178179void180compilestate_save(struct pari_compilestate *comp)181{182comp->opcode=s_opcode.n;183comp->operand=s_operand.n;184comp->accesslex=s_accesslex.n;185comp->data=s_data.n;186comp->offset=offset;187comp->nblex=nblex;188comp->localvars=s_lvar.n;189comp->dbgstart=dbgstart;190comp->dbginfo=s_dbginfo.n;191comp->frames=s_frame.n;192}193194void195compilestate_restore(struct pari_compilestate *comp)196{197s_opcode.n=comp->opcode;198s_operand.n=comp->operand;199s_accesslex.n=comp->accesslex;200s_data.n=comp->data;201offset=comp->offset;202nblex=comp->nblex;203s_lvar.n=comp->localvars;204dbgstart=comp->dbgstart;205s_dbginfo.n=comp->dbginfo;206s_frame.n=comp->frames;207}208209static GEN210gcopyunclone(GEN x) { GEN y = gcopy(x); gunclone(x); return y; }211212static void213access_push(long x)214{215long a = pari_stack_new(&s_accesslex);216accesslex[a] = x;217}218219static GEN220genctx(long nbmvar, long paccesslex)221{222GEN acc = const_vec(nbmvar,gen_1);223long i, lvl = 1 + nbmvar;224for (i = paccesslex; i<s_accesslex.n; i++)225{226long a = accesslex[i];227if (a > 0) { lvl+=a; continue; }228a += lvl;229if (a <= 0) pari_err_BUG("genctx");230if (a <= nbmvar)231gel(acc, a) = gen_0;232}233s_accesslex.n = paccesslex;234for (i = 1; i<=nbmvar; i++)235if (signe(gel(acc,i))==0)236access_push(i-nbmvar-1);237return acc;238}239240static GEN241getfunction(const struct codepos *pos, long arity, long nbmvar, GEN text,242long gap)243{244long lop = s_opcode.n+1 - pos->opcode;245long ldat = s_data.n+1 - pos->data;246long lfram = s_frame.n+1 - pos->frames;247GEN cl = cgetg(nbmvar && text? 8: (text? 7: 6), t_CLOSURE);248GEN frpc, fram, dbg, op, dat;249char *s;250long i;251252cl[1] = arity;253gel(cl,2) = cgetg(nchar2nlong(lop)+1, t_STR);254gel(cl,3) = op = cgetg(lop, t_VECSMALL);255gel(cl,4) = dat = cgetg(ldat, t_VEC);256dbg = cgetg(lop, t_VECSMALL);257frpc = cgetg(lfram, t_VECSMALL);258fram = cgetg(lfram, t_VEC);259gel(cl,5) = mkvec3(dbg, frpc, fram);260if (text) gel(cl,6) = text;261s = GSTR(gel(cl,2)) - 1;262for (i = 1; i < lop; i++)263{264long j = i+pos->opcode-1;265s[i] = opcode[j];266op[i] = operand[j];267dbg[i] = dbginfo[j] - dbgstart;268if (dbg[i] < 0) dbg[i] += gap;269}270s[i] = 0;271s_opcode.n = pos->opcode;272s_operand.n = pos->opcode;273s_dbginfo.n = pos->opcode;274if (lg(cl)==8)275gel(cl,7) = genctx(nbmvar, pos->accesslex);276else if (nbmvar==0)277s_accesslex.n = pos->accesslex;278else279{280pari_sp av = avma;281(void) genctx(nbmvar, pos->accesslex);282set_avma(av);283}284for (i = 1; i < ldat; i++)285if (data[i+pos->data-1]) gel(dat,i) = gcopyunclone(data[i+pos->data-1]);286s_data.n = pos->data;287while (s_lvar.n > pos->localvars && !localvars[s_lvar.n-1].inl)288{289if (localvars[s_lvar.n-1].type==Lmy) nblex--;290s_lvar.n--;291}292for (i = 1; i < lfram; i++)293{294long j = i+pos->frames-1;295frpc[i] = frames[j].pc - pos->opcode+1;296gel(fram, i) = gcopyunclone(frames[j].frame);297}298s_frame.n = pos->frames;299offset = pos->offset;300dbgstart = pos->dbgstart;301return cl;302}303304static GEN305getclosure(struct codepos *pos, long nbmvar)306{307return getfunction(pos, 0, nbmvar, NULL, 0);308}309310static void311op_push_loc(op_code o, long x, const char *loc)312{313long n=pari_stack_new(&s_opcode);314long m=pari_stack_new(&s_operand);315long d=pari_stack_new(&s_dbginfo);316opcode[n]=o;317operand[m]=x;318dbginfo[d]=loc;319}320321static void322op_push(op_code o, long x, long n)323{324op_push_loc(o,x,tree[n].str);325}326327static void328op_insert_loc(long k, op_code o, long x, const char *loc)329{330long i;331long n=pari_stack_new(&s_opcode);332(void) pari_stack_new(&s_operand);333(void) pari_stack_new(&s_dbginfo);334for (i=n-1; i>=k; i--)335{336opcode[i+1] = opcode[i];337operand[i+1]= operand[i];338dbginfo[i+1]= dbginfo[i];339}340opcode[k] = o;341operand[k] = x;342dbginfo[k] = loc;343}344345static long346data_push(GEN x)347{348long n=pari_stack_new(&s_data);349data[n] = x?gclone(x):x;350return n-offset;351}352353static void354var_push(entree *ep, Ltype type)355{356long n=pari_stack_new(&s_lvar);357localvars[n].ep = ep;358localvars[n].inl = 0;359localvars[n].type = type;360if (type == Lmy) nblex++;361}362363static void364frame_push(GEN x)365{366long n=pari_stack_new(&s_frame);367frames[n].pc = s_opcode.n-1;368frames[n].frame = gclone(x);369}370371static GEN372pack_localvars(void)373{374GEN pack=cgetg(3,t_VEC);375long i, l=s_lvar.n;376GEN t=cgetg(1+l,t_VECSMALL);377GEN e=cgetg(1+l,t_VECSMALL);378gel(pack,1)=t;379gel(pack,2)=e;380for(i=1;i<=l;i++)381{382t[i]=localvars[i-1].type;383e[i]=(long)localvars[i-1].ep;384}385for(i=1;i<=nblex;i++)386access_push(-i);387return pack;388}389390void391push_frame(GEN C, long lpc, long dummy)392{393const char *code=closure_codestr(C);394GEN oper=closure_get_oper(C);395GEN dbg=closure_get_dbg(C);396GEN frpc=gel(dbg,2);397GEN fram=gel(dbg,3);398long pc, j=1, lfr = lg(frpc);399if (lpc==-1)400{401long k;402GEN e = gel(fram, 1);403for(k=1; k<lg(e); k++)404var_push(dummy?NULL:(entree*)e[k], Lmy);405return;406}407if (lg(C)<8) while (j<lfr && frpc[j]==0) j++;408for(pc=0; pc<lpc; pc++) /* do not assume lpc was completed */409{410if (pc>0 && (code[pc]==OClocalvar || code[pc]==OClocalvar0))411var_push((entree*)oper[pc],Llocal);412if (j<lfr && pc==frpc[j])413{414long k;415GEN e = gel(fram,j);416for(k=1; k<lg(e); k++)417var_push(dummy?NULL:(entree*)e[k], Lmy);418j++;419}420}421}422423void424debug_context(void)425{426long i;427for(i=0;i<s_lvar.n;i++)428{429entree *ep = localvars[i].ep;430Ltype type = localvars[i].type;431err_printf("%ld: %s: %s\n",i,(type==Lmy?"my":"local"),(ep?ep->name:"NULL"));432}433}434435GEN436localvars_read_str(const char *x, GEN pack)437{438pari_sp av = avma;439GEN code;440long l=0, nbmvar=nblex;441if (pack)442{443GEN t=gel(pack,1);444GEN e=gel(pack,2);445long i;446l=lg(t)-1;447for(i=1;i<=l;i++)448var_push((entree*)e[i],(Ltype)t[i]);449}450code = compile_str(x);451s_lvar.n -= l;452nblex = nbmvar;453return gerepileupto(av, closure_evalres(code));454}455456long457localvars_find(GEN pack, entree *ep)458{459GEN t=gel(pack,1);460GEN e=gel(pack,2);461long i;462long vn=0;463for(i=lg(e)-1;i>=1;i--)464{465if(t[i]==Lmy)466vn--;467if(e[i]==(long)ep)468return t[i]==Lmy?vn:0;469}470return 0;471}472473/*474Flags for copy optimisation:475-- Freturn: The result will be returned.476-- FLsurvive: The result must survive the closure.477-- FLnocopy: The result will never be updated nor part of a user variable.478-- FLnocopylex: The result will never be updated nor part of dynamic variable.479*/480enum FLflag {FLreturn=1, FLsurvive=2, FLnocopy=4, FLnocopylex=8};481482static void483addcopy(long n, long mode, long flag, long mask)484{485if (mode==Ggen && !(flag&mask))486{487op_push(OCcopy,0,n);488if (!(flag&FLsurvive) && DEBUGLEVEL)489pari_warn(warner,"compiler generates copy for `%.*s'",490tree[n].len,tree[n].str);491}492}493494static void compilenode(long n, int mode, long flag);495496typedef enum {PPend,PPstd,PPdefault,PPdefaultmulti,PPstar,PPauto} PPproto;497498static PPproto499parseproto(char const **q, char *c, const char *str)500{501char const *p=*q;502long i;503switch(*p)504{505case 0:506case '\n':507return PPend;508case 'D':509switch(p[1])510{511case 'G':512case '&':513case 'W':514case 'V':515case 'I':516case 'E':517case 'J':518case 'n':519case 'P':520case 'r':521case 's':522*c=p[1]; *q=p+2; return PPdefault;523default:524for(i=0;*p && i<2;p++) i+=*p==',';525/* assert(i>=2) because check_proto validated the protototype */526*c=p[-2]; *q=p; return PPdefaultmulti;527}528break;529case 'C':530case 'p':531case 'b':532case 'P':533case 'f':534*c=*p; *q=p+1; return PPauto;535case '&':536*c='*'; *q=p+1; return PPstd;537case 'V':538if (p[1]=='=')539{540if (p[2]!='G')541compile_err("function prototype is not supported",str);542*c='='; p+=2;543}544else545*c=*p;546*q=p+1; return PPstd;547case 'E':548case 's':549if (p[1]=='*') { *c=*p++; *q=p+1; return PPstar; }550/*fall through*/551}552*c=*p; *q=p+1; return PPstd;553}554555static long556detag(long n)557{558while (tree[n].f==Ftag)559n=tree[n].x;560return n;561}562563/* return type for GP functions */564static op_code565get_ret_type(const char **p, long arity, Gtype *t, long *flag)566{567*flag = 0;568if (**p == 'v') { (*p)++; *t=Gvoid; return OCcallvoid; }569else if (**p == 'i') { (*p)++; *t=Gsmall; return OCcallint; }570else if (**p == 'l') { (*p)++; *t=Gsmall; return OCcalllong; }571else if (**p == 'u') { (*p)++; *t=Gusmall; return OCcalllong; }572else if (**p == 'm') { (*p)++; *flag = FLnocopy; }573*t=Ggen; return arity==2?OCcallgen2:OCcallgen;574}575576/*supported types:577* type: Gusmall, Gsmall, Ggen, Gvoid, Gvec, Gclosure578* mode: Gusmall, Gsmall, Ggen, Gvar, Gvoid579*/580static void581compilecast_loc(int type, int mode, const char *loc)582{583if (type==mode) return;584switch (mode)585{586case Gusmall:587if (type==Ggen) op_push_loc(OCitou,-1,loc);588else if (type==Gvoid) op_push_loc(OCpushlong,0,loc);589else if (type!=Gsmall)590compile_err("this should be a small integer >=0",loc);591break;592case Gsmall:593if (type==Ggen) op_push_loc(OCitos,-1,loc);594else if (type==Gvoid) op_push_loc(OCpushlong,0,loc);595else if (type!=Gusmall)596compile_err("this should be a small integer",loc);597break;598case Ggen:599if (type==Gsmall) op_push_loc(OCstoi,0,loc);600else if (type==Gusmall)op_push_loc(OCutoi,0,loc);601else if (type==Gvoid) op_push_loc(OCpushgnil,0,loc);602break;603case Gvoid:604op_push_loc(OCpop, 1,loc);605break;606case Gvar:607if (type==Ggen) op_push_loc(OCvarn,-1,loc);608else compile_varerr(loc);609break;610default:611pari_err_BUG("compilecast [unknown type]");612}613}614615static void616compilecast(long n, int type, int mode) { compilecast_loc(type, mode, tree[n].str); }617618static entree *619fetch_member_raw(const char *s, long len)620{621pari_sp av = avma;622char *t = stack_malloc(len+2);623entree *ep;624t[0] = '_'; strncpy(t+1, s, len); t[++len] = 0; /* prepend '_' */625ep = fetch_entry_raw(t, len);626set_avma(av); return ep;627}628static entree *629getfunc(long n)630{631long x=tree[n].x;632if (tree[x].x==CSTmember) /* str-1 points to '.' */633return do_alias(fetch_member_raw(tree[x].str - 1, tree[x].len + 1));634else635return do_alias(fetch_entry_raw(tree[x].str, tree[x].len));636}637638static entree *639getentry(long n)640{641n = detag(n);642if (tree[n].f!=Fentry)643{644if (tree[n].f==Fseq)645compile_err("unexpected character: ';'", tree[tree[n].y].str-1);646compile_varerr(tree[n].str);647}648return getfunc(n);649}650651static entree *652getvar(long n)653{ return getentry(n); }654655/* match Fentry that are not actually EpSTATIC functions called without parens*/656static entree *657getvardyn(long n)658{659entree *ep = getentry(n);660if (EpSTATIC(do_alias(ep)))661compile_varerr(tree[n].str);662return ep;663}664665static long666getmvar(entree *ep)667{668long i;669long vn=0;670for(i=s_lvar.n-1;i>=0;i--)671{672if(localvars[i].type==Lmy)673vn--;674if(localvars[i].ep==ep)675return localvars[i].type==Lmy?vn:0;676}677return 0;678}679680static void681ctxmvar(long n)682{683pari_sp av=avma;684GEN ctx;685long i;686if (n==0) return;687ctx = cgetg(n+1,t_VECSMALL);688for(n=0, i=0; i<s_lvar.n; i++)689if(localvars[i].type==Lmy)690ctx[++n]=(long)localvars[i].ep;691frame_push(ctx);692set_avma(av);693}694695INLINE int696is_func_named(entree *ep, const char *s)697{698return !strcmp(ep->name, s);699}700701INLINE int702is_node_zero(long n)703{704n = detag(n);705return (tree[n].f==Fsmall && tree[n].x==0);706}707708static void709str_defproto(const char *p, const char *q, const char *loc)710{711long len = p-4-q;712if (q[1]!='"' || q[len]!='"')713compile_err("default argument must be a string",loc);714op_push_loc(OCpushgen,data_push(strntoGENexp(q+1,len)),loc);715}716717static long718countmatrixelts(long n)719{720long x,i;721if (n==-1 || tree[n].f==Fnoarg) return 0;722for(x=n, i=0; tree[x].f==Fmatrixelts; x=tree[x].x)723if (tree[tree[x].y].f!=Fnoarg) i++;724if (tree[x].f!=Fnoarg) i++;725return i;726}727728static long729countlisttogen(long n, Ffunc f)730{731long x,i;732if (n==-1 || tree[n].f==Fnoarg) return 0;733for(x=n, i=0; tree[x].f==f ;x=tree[x].x, i++);734return i+1;735}736737static GEN738listtogen(long n, Ffunc f)739{740long x,i,nb = countlisttogen(n, f);741GEN z=cgetg(nb+1, t_VECSMALL);742if (nb)743{744for (x=n, i = nb-1; i>0; z[i+1]=tree[x].y, x=tree[x].x, i--);745z[1]=x;746}747return z;748}749750static long751first_safe_arg(GEN arg, long mask)752{753long lnc, l=lg(arg);754for (lnc=l-1; lnc>0 && (tree[arg[lnc]].flags&mask)==mask; lnc--);755return lnc;756}757758static void759checkdups(GEN arg, GEN vep)760{761long l=vecsmall_duplicate(vep);762if (l!=0) compile_err("variable declared twice",tree[arg[l]].str);763}764765enum {MAT_range,MAT_std,MAT_line,MAT_column,VEC_std};766767static int768matindex_type(long n)769{770long x = tree[n].x, y = tree[n].y;771long fxx = tree[tree[x].x].f, fxy = tree[tree[x].y].f;772if (y==-1)773{774if (fxy!=Fnorange) return MAT_range;775if (fxx==Fnorange) compile_err("missing index",tree[n].str);776return VEC_std;777}778else779{780long fyx = tree[tree[y].x].f, fyy = tree[tree[y].y].f;781if (fxy!=Fnorange || fyy!=Fnorange) return MAT_range;782if (fxx==Fnorange && fyx==Fnorange)783compile_err("missing index",tree[n].str);784if (fxx==Fnorange) return MAT_column;785if (fyx==Fnorange) return MAT_line;786return MAT_std;787}788}789790static entree *791getlvalue(long n)792{793while ((tree[n].f==Fmatcoeff && matindex_type(tree[n].y)!=MAT_range) || tree[n].f==Ftag)794n=tree[n].x;795return getvar(n);796}797798INLINE void799compilestore(long vn, entree *ep, long n)800{801if (vn)802op_push(OCstorelex,vn,n);803else804{805if (EpSTATIC(do_alias(ep)))806compile_varerr(tree[n].str);807op_push(OCstoredyn,(long)ep,n);808}809}810811INLINE void812compilenewptr(long vn, entree *ep, long n)813{814if (vn)815{816access_push(vn);817op_push(OCnewptrlex,vn,n);818}819else820op_push(OCnewptrdyn,(long)ep,n);821}822823static void824compilelvalue(long n)825{826n = detag(n);827if (tree[n].f==Fentry)828return;829else830{831long x = tree[n].x, y = tree[n].y;832long yx = tree[y].x, yy = tree[y].y;833long m = matindex_type(y);834if (m == MAT_range)835compile_err("not an lvalue",tree[n].str);836if (m == VEC_std && tree[x].f==Fmatcoeff)837{838int mx = matindex_type(tree[x].y);839if (mx==MAT_line)840{841int xy = tree[x].y, xyx = tree[xy].x;842compilelvalue(tree[x].x);843compilenode(tree[xyx].x,Gsmall,0);844compilenode(tree[yx].x,Gsmall,0);845op_push(OCcompo2ptr,0,y);846return;847}848}849compilelvalue(x);850switch(m)851{852case VEC_std:853compilenode(tree[yx].x,Gsmall,0);854op_push(OCcompo1ptr,0,y);855break;856case MAT_std:857compilenode(tree[yx].x,Gsmall,0);858compilenode(tree[yy].x,Gsmall,0);859op_push(OCcompo2ptr,0,y);860break;861case MAT_line:862compilenode(tree[yx].x,Gsmall,0);863op_push(OCcompoLptr,0,y);864break;865case MAT_column:866compilenode(tree[yy].x,Gsmall,0);867op_push(OCcompoCptr,0,y);868break;869}870}871}872873static void874compilematcoeff(long n, int mode)875{876long x=tree[n].x, y=tree[n].y;877long yx=tree[y].x, yy=tree[y].y;878long m=matindex_type(y);879compilenode(x,Ggen,FLnocopy);880switch(m)881{882case VEC_std:883compilenode(tree[yx].x,Gsmall,0);884op_push(OCcompo1,mode,y);885return;886case MAT_std:887compilenode(tree[yx].x,Gsmall,0);888compilenode(tree[yy].x,Gsmall,0);889op_push(OCcompo2,mode,y);890return;891case MAT_line:892compilenode(tree[yx].x,Gsmall,0);893op_push(OCcompoL,0,y);894compilecast(n,Gvec,mode);895return;896case MAT_column:897compilenode(tree[yy].x,Gsmall,0);898op_push(OCcompoC,0,y);899compilecast(n,Gvec,mode);900return;901case MAT_range:902compilenode(tree[yx].x,Gsmall,0);903compilenode(tree[yx].y,Gsmall,0);904if (yy==-1)905op_push(OCcallgen,(long)is_entry("_[_.._]"),n);906else907{908compilenode(tree[yy].x,Gsmall,0);909compilenode(tree[yy].y,Gsmall,0);910op_push(OCcallgen,(long)is_entry("_[_.._,_.._]"),n);911}912compilecast(n,Gvec,mode);913return;914default:915pari_err_BUG("compilematcoeff");916}917}918919static void920compilesmall(long n, long x, long mode)921{922if (mode==Ggen)923op_push(OCpushstoi, x, n);924else925{926if (mode==Gusmall && x < 0)927compile_err("this should be a small integer >=0",tree[n].str);928op_push(OCpushlong, x, n);929compilecast(n,Gsmall,mode);930}931}932933static void934compilevec(long n, long mode, op_code op)935{936pari_sp ltop=avma;937long x=tree[n].x;938long i;939GEN arg=listtogen(x,Fmatrixelts);940long l=lg(arg);941op_push(op,l,n);942for (i=1;i<l;i++)943{944if (tree[arg[i]].f==Fnoarg)945compile_err("missing vector element",tree[arg[i]].str);946compilenode(arg[i],Ggen,FLsurvive);947op_push(OCstackgen,i,n);948}949set_avma(ltop);950op_push(OCpop,1,n);951compilecast(n,Gvec,mode);952}953954static void955compilemat(long n, long mode)956{957pari_sp ltop=avma;958long x=tree[n].x;959long i,j;960GEN line=listtogen(x,Fmatrixlines);961long lglin = lg(line), lgcol=0;962op_push(OCpushlong, lglin,n);963if (lglin==1)964op_push(OCmat,1,n);965for(i=1;i<lglin;i++)966{967GEN col=listtogen(line[i],Fmatrixelts);968long l=lg(col), k;969if (i==1)970{971lgcol=l;972op_push(OCmat,lgcol,n);973}974else if (l!=lgcol)975compile_err("matrix must be rectangular",tree[line[i]].str);976k=i;977for(j=1;j<lgcol;j++)978{979k-=lglin;980if (tree[col[j]].f==Fnoarg)981compile_err("missing matrix element",tree[col[j]].str);982compilenode(col[j], Ggen, FLsurvive);983op_push(OCstackgen,k,n);984}985}986set_avma(ltop);987op_push(OCpop,1,n);988compilecast(n,Gvec,mode);989}990991static GEN992cattovec(long n, long fnum)993{994long x=n, y, i=0, nb;995GEN stack;996if (tree[n].f==Fnoarg) return cgetg(1,t_VECSMALL);997while(1)998{999long xx=tree[x].x;1000long xy=tree[x].y;1001if (tree[x].f!=Ffunction || xx!=fnum) break;1002x=tree[xy].x;1003y=tree[xy].y;1004if (tree[y].f==Fnoarg)1005compile_err("unexpected character: ", tree[y].str);1006i++;1007}1008if (tree[x].f==Fnoarg)1009compile_err("unexpected character: ", tree[x].str);1010nb=i+1;1011stack=cgetg(nb+1,t_VECSMALL);1012for(x=n;i>0;i--)1013{1014long y=tree[x].y;1015x=tree[y].x;1016stack[i+1]=tree[y].y;1017}1018stack[1]=x;1019return stack;1020}10211022static GEN1023compilelambda(long y, GEN vep, long nbmvar, struct codepos *pos)1024{1025long lev = vep ? lg(vep)-1 : 0;1026GEN text=cgetg(3,t_VEC);1027gel(text,1)=strtoGENstr(lev? ((entree*) vep[1])->name: "");1028gel(text,2)=strntoGENstr(tree[y].str,tree[y].len);1029dbgstart = tree[y].str;1030compilenode(y,Ggen,FLsurvive|FLreturn);1031return getfunction(pos,lev,nbmvar,text,2);1032}10331034static void1035compilecall(long n, int mode, entree *ep)1036{1037pari_sp ltop=avma;1038long j;1039long x=tree[n].x, tx = tree[x].x;1040long y=tree[n].y;1041GEN arg=listtogen(y,Flistarg);1042long nb=lg(arg)-1;1043long lnc=first_safe_arg(arg, COsafelex|COsafedyn);1044long lnl=first_safe_arg(arg, COsafelex);1045long fl = lnl==0? (lnc==0? FLnocopy: FLnocopylex): 0;1046if (ep==NULL)1047compilenode(x, Ggen, fl);1048else1049{1050long vn=getmvar(ep);1051if (vn)1052{1053access_push(vn);1054op_push(OCpushlex,vn,n);1055}1056else1057op_push(OCpushdyn,(long)ep,n);1058}1059for (j=1;j<=nb;j++)1060{1061long x = tree[arg[j]].x, f = tree[arg[j]].f;1062if (f==Fseq)1063compile_err("unexpected ';'", tree[x].str+tree[x].len);1064else if (f==Findarg)1065{1066compilenode(tree[arg[j]].x, Ggen,FLnocopy);1067op_push(OClock,0,n);1068} else if (tx==CSTmember)1069{1070compilenode(arg[j], Ggen,FLnocopy);1071op_push(OClock,0,n);1072}1073else if (f!=Fnoarg)1074compilenode(arg[j], Ggen,j>=lnl?FLnocopylex:0);1075else1076op_push(OCpushlong,0,n);1077}1078op_push(OCcalluser,nb,x);1079compilecast(n,Ggen,mode);1080set_avma(ltop);1081}10821083static GEN1084compilefuncinline(long n, long c, long a, long flag, long isif, long lev, long *ev)1085{1086struct codepos pos;1087int type=c=='I'?Gvoid:Ggen;1088long rflag=c=='I'?0:FLsurvive;1089long nbmvar = nblex;1090GEN vep = NULL;1091if (isif && (flag&FLreturn)) rflag|=FLreturn;1092getcodepos(&pos);1093if (c=='J') ctxmvar(nbmvar);1094if (lev)1095{1096long i;1097GEN varg=cgetg(lev+1,t_VECSMALL);1098vep=cgetg(lev+1,t_VECSMALL);1099for(i=0;i<lev;i++)1100{1101entree *ve;1102if (ev[i]<0)1103compile_err("missing variable name", tree[a].str-1);1104ve = getvar(ev[i]);1105vep[i+1]=(long)ve;1106varg[i+1]=ev[i];1107var_push(ve,Lmy);1108}1109checkdups(varg,vep);1110if (c=='J')1111op_push(OCgetargs,lev,n);1112access_push(lg(vep)-1);1113frame_push(vep);1114}1115if (c=='J')1116return compilelambda(a,vep,nbmvar,&pos);1117if (tree[a].f==Fnoarg)1118compilecast(a,Gvoid,type);1119else1120compilenode(a,type,rflag);1121return getclosure(&pos, nbmvar);1122}11231124static long1125countvar(GEN arg)1126{1127long i, l = lg(arg);1128long n = l-1;1129for(i=1; i<l; i++)1130{1131long a=arg[i];1132if (tree[a].f==Fassign)1133{1134long x = detag(tree[a].x);1135if (tree[x].f==Fvec && tree[x].x>=0)1136n += countmatrixelts(tree[x].x)-1;1137}1138}1139return n;1140}11411142static void1143compileuninline(GEN arg)1144{1145long j;1146if (lg(arg) > 1)1147compile_err("too many arguments",tree[arg[1]].str);1148for(j=0; j<s_lvar.n; j++)1149if(!localvars[j].inl)1150pari_err(e_MISC,"uninline is only valid at top level");1151s_lvar.n = 0; nblex = 0;1152}11531154static void1155compilemy(GEN arg, const char *str, int inl)1156{1157long i, j, k, l = lg(arg);1158long n = countvar(arg);1159GEN vep = cgetg(n+1,t_VECSMALL);1160GEN ver = cgetg(n+1,t_VECSMALL);1161if (inl)1162{1163for(j=0; j<s_lvar.n; j++)1164if(!localvars[j].inl)1165pari_err(e_MISC,"inline is only valid at top level");1166}1167for(k=0, i=1; i<l; i++)1168{1169long a=arg[i];1170if (tree[a].f==Fassign)1171{1172long x = detag(tree[a].x);1173if (tree[x].f==Fvec && tree[x].x>=0)1174{1175GEN vars = listtogen(tree[x].x,Fmatrixelts);1176long nv = lg(vars)-1;1177for (j=1; j<=nv; j++)1178if (tree[vars[j]].f!=Fnoarg)1179{1180ver[++k] = vars[j];1181vep[k] = (long)getvar(ver[k]);1182}1183continue;1184} else ver[++k] = x;1185} else ver[++k] = a;1186vep[k] = (long)getvar(ver[k]);1187}1188checkdups(ver,vep);1189for(i=1; i<=n; i++) var_push(NULL,Lmy);1190op_push_loc(OCnewframe,inl?-n:n,str);1191access_push(lg(vep)-1);1192frame_push(vep);1193for (k=0, i=1; i<l; i++)1194{1195long a=arg[i];1196if (tree[a].f==Fassign)1197{1198long x = detag(tree[a].x);1199if (tree[x].f==Fvec && tree[x].x>=0)1200{1201GEN vars = listtogen(tree[x].x,Fmatrixelts);1202long nv = lg(vars)-1, m = nv;1203compilenode(tree[a].y,Ggen,FLnocopy);1204for (j=1; j<=nv; j++)1205if (tree[vars[j]].f==Fnoarg) m--;1206if (m > 1) op_push(OCdup,m-1,x);1207for (j=1; j<=nv; j++)1208if (tree[vars[j]].f!=Fnoarg)1209{1210long v = detag(vars[j]);1211op_push(OCpushlong,j,v);1212op_push(OCcompo1,Ggen,v);1213k++;1214op_push(OCstorelex,-n+k-1,a);1215localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k];1216localvars[s_lvar.n-n+k-1].inl=inl;1217}1218continue;1219}1220else if (!is_node_zero(tree[a].y))1221{1222compilenode(tree[a].y,Ggen,FLnocopy);1223op_push(OCstorelex,-n+k,a);1224}1225}1226k++;1227localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k];1228localvars[s_lvar.n-n+k-1].inl=inl;1229}1230}12311232static long1233localpush(op_code op, long a)1234{1235entree *ep = getvardyn(a);1236long vep = (long) ep;1237op_push(op,vep,a);1238var_push(ep,Llocal);1239return vep;1240}12411242static void1243compilelocal(GEN arg)1244{1245long i, j, k, l = lg(arg);1246long n = countvar(arg);1247GEN vep = cgetg(n+1,t_VECSMALL);1248GEN ver = cgetg(n+1,t_VECSMALL);1249for(k=0, i=1; i<l; i++)1250{1251long a=arg[i];1252if (tree[a].f==Fassign)1253{1254long x = detag(tree[a].x);1255if (tree[x].f==Fvec && tree[x].x>=0)1256{1257GEN vars = listtogen(tree[x].x,Fmatrixelts);1258long nv = lg(vars)-1, m = nv;1259compilenode(tree[a].y,Ggen,FLnocopy);1260for (j=1; j<=nv; j++)1261if (tree[vars[j]].f==Fnoarg) m--;1262if (m > 1) op_push(OCdup,m-1,x);1263for (j=1; j<=nv; j++)1264if (tree[vars[j]].f!=Fnoarg)1265{1266long v = detag(vars[j]);1267op_push(OCpushlong,j,v);1268op_push(OCcompo1,Ggen,v);1269vep[++k] = localpush(OClocalvar, v);1270ver[k] = v;1271}1272continue;1273} else if (!is_node_zero(tree[a].y))1274{1275compilenode(tree[a].y,Ggen,FLnocopy);1276ver[++k] = x;1277vep[k] = localpush(OClocalvar, ver[k]);1278continue;1279}1280else1281ver[++k] = x;1282} else1283ver[++k] = a;1284vep[k] = localpush(OClocalvar0, ver[k]);1285}1286checkdups(ver,vep);1287}12881289static void1290compileexport(GEN arg)1291{1292long i, l = lg(arg);1293for (i=1; i<l; i++)1294{1295long a=arg[i];1296if (tree[a].f==Fassign)1297{1298long x = detag(tree[a].x);1299long v = (long) getvardyn(x);1300compilenode(tree[a].y,Ggen,FLnocopy);1301op_push(OCexportvar,v,x);1302} else1303{1304long x = detag(a);1305long v = (long) getvardyn(x);1306op_push(OCpushdyn,v,x);1307op_push(OCexportvar,v,x);1308}1309}1310}13111312static void1313compileunexport(GEN arg)1314{1315long i, l = lg(arg);1316for (i=1; i<l; i++)1317{1318long a = arg[i];1319long x = detag(a);1320long v = (long) getvardyn(x);1321op_push(OCunexportvar,v,x);1322}1323}13241325static void1326compilefunc(entree *ep, long n, int mode, long flag)1327{1328pari_sp ltop=avma;1329long j;1330long x=tree[n].x, y=tree[n].y;1331op_code ret_op;1332long ret_flag;1333Gtype ret_typ;1334char const *p,*q;1335char c;1336const char *flags = NULL;1337const char *str;1338PPproto mod;1339GEN arg=listtogen(y,Flistarg);1340long lnc=first_safe_arg(arg, COsafelex|COsafedyn);1341long lnl=first_safe_arg(arg, COsafelex);1342long nbpointers=0, nbopcodes;1343long nb=lg(arg)-1, lev=0;1344long ev[20];1345if (x>=OPnboperator)1346str=tree[x].str;1347else1348{1349if (nb==2)1350str=tree[arg[1]].str+tree[arg[1]].len;1351else if (nb==1)1352str=tree[arg[1]].str;1353else1354str=tree[n].str;1355while(*str==')') str++;1356}1357if (tree[n].f==Fassign)1358{1359nb=2; lnc=2; lnl=2; arg=mkvecsmall2(x,y);1360}1361else if (is_func_named(ep,"if"))1362{1363if (nb>=4)1364ep=is_entry("_multi_if");1365else if (mode==Gvoid)1366ep=is_entry("_void_if");1367}1368else if (is_func_named(ep,"return") && (flag&FLreturn) && nb<=1)1369{1370if (nb==0) op_push(OCpushgnil,0,n);1371else compilenode(arg[1],Ggen,FLsurvive|FLreturn);1372set_avma(ltop);1373return;1374}1375else if (is_func_named(ep,"inline"))1376{1377compilemy(arg, str, 1);1378compilecast(n,Gvoid,mode);1379set_avma(ltop);1380return;1381}1382else if (is_func_named(ep,"uninline"))1383{1384compileuninline(arg);1385compilecast(n,Gvoid,mode);1386set_avma(ltop);1387return;1388}1389else if (is_func_named(ep,"my"))1390{1391compilemy(arg, str, 0);1392compilecast(n,Gvoid,mode);1393set_avma(ltop);1394return;1395}1396else if (is_func_named(ep,"local"))1397{1398compilelocal(arg);1399compilecast(n,Gvoid,mode);1400set_avma(ltop);1401return;1402}1403else if (is_func_named(ep,"export"))1404{1405compileexport(arg);1406compilecast(n,Gvoid,mode);1407set_avma(ltop);1408return;1409}1410else if (is_func_named(ep,"unexport"))1411{1412compileunexport(arg);1413compilecast(n,Gvoid,mode);1414set_avma(ltop);1415return;1416}1417/*We generate dummy code for global() for compatibility with gp2c*/1418else if (is_func_named(ep,"global"))1419{1420long i;1421for (i=1;i<=nb;i++)1422{1423long a=arg[i];1424long en;1425if (tree[a].f==Fassign)1426{1427compilenode(tree[a].y,Ggen,0);1428a=tree[a].x;1429en=(long)getvardyn(a);1430op_push(OCstoredyn,en,a);1431}1432else1433{1434en=(long)getvardyn(a);1435op_push(OCpushdyn,en,a);1436op_push(OCpop,1,a);1437}1438}1439compilecast(n,Gvoid,mode);1440set_avma(ltop);1441return;1442}1443else if (is_func_named(ep,"O"))1444{1445if (nb!=1)1446compile_err("wrong number of arguments", tree[n].str+tree[n].len-1);1447ep=is_entry("O(_^_)");1448if (tree[arg[1]].f==Ffunction && tree[arg[1]].x==OPpow)1449{1450arg = listtogen(tree[arg[1]].y,Flistarg);1451nb = lg(arg)-1;1452lnc = first_safe_arg(arg,COsafelex|COsafedyn);1453lnl = first_safe_arg(arg,COsafelex);1454}1455}1456else if (x==OPn && tree[y].f==Fsmall)1457{1458set_avma(ltop);1459compilesmall(y, -tree[y].x, mode);1460return;1461}1462else if (x==OPtrans && tree[y].f==Fvec)1463{1464set_avma(ltop);1465compilevec(y, mode, OCcol);1466return;1467}1468else if (x==OPpow && nb==2 && tree[arg[2]].f==Fsmall)1469ep=is_entry("_^s");1470else if (x==OPcat)1471compile_err("expected character: ',' or ')' instead of",1472tree[arg[1]].str+tree[arg[1]].len);1473p=ep->code;1474if (!ep->value)1475compile_err("unknown function",tree[n].str);1476nbopcodes = s_opcode.n;1477ret_op = get_ret_type(&p, ep->arity, &ret_typ, &ret_flag);1478j=1;1479if (*p)1480{1481q=p;1482while((mod=parseproto(&p,&c,tree[n].str))!=PPend)1483{1484if (j<=nb && tree[arg[j]].f!=Fnoarg1485&& (mod==PPdefault || mod==PPdefaultmulti))1486mod=PPstd;1487switch(mod)1488{1489case PPstd:1490if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1);1491if (c!='I' && c!='E' && c!='J')1492{1493long x = tree[arg[j]].x, f = tree[arg[j]].f;1494if (f==Fnoarg)1495compile_err("missing mandatory argument", tree[arg[j]].str);1496if (f==Fseq)1497compile_err("unexpected ';'", tree[x].str+tree[x].len);1498}1499switch(c)1500{1501case 'G':1502compilenode(arg[j],Ggen,j>=lnl?(j>=lnc?FLnocopy:FLnocopylex):0);1503j++;1504break;1505case 'W':1506{1507long a = tree[arg[j]].f==Findarg ? tree[arg[j]].x: arg[j];1508entree *ep = getlvalue(a);1509long vn = getmvar(ep);1510if (vn)1511{1512access_push(vn);1513op_push(OCcowvarlex, vn, a);1514}1515else op_push(OCcowvardyn, (long)ep, a);1516compilenode(a, Ggen,FLnocopy);1517j++;1518break;1519}1520case 'M':1521if (tree[arg[j]].f!=Fsmall)1522{1523if (!flags) flags = ep->code;1524flags = strchr(flags, '\n'); /* Skip to the following '\n' */1525if (!flags)1526compile_err("missing flag in string function signature",1527tree[n].str);1528flags++;1529if (tree[arg[j]].f==Fconst && tree[arg[j]].x==CSTstr)1530{1531GEN str=strntoGENexp(tree[arg[j]].str,tree[arg[j]].len);1532op_push(OCpushlong, eval_mnemonic(str, flags),n);1533j++;1534} else1535{1536compilenode(arg[j++],Ggen,0);1537op_push(OCpushlong,(long)flags,n);1538op_push(OCcallgen2,(long)is_entry("_eval_mnemonic"),n);1539}1540break;1541}1542case 'P': case 'L':1543compilenode(arg[j++],Gsmall,0);1544break;1545case 'U':1546compilenode(arg[j++],Gusmall,0);1547break;1548case 'n':1549compilenode(arg[j++],Gvar,0);1550break;1551case '&': case '*':1552{1553long vn, a=arg[j++];1554entree *ep;1555if (c=='&')1556{1557if (tree[a].f!=Frefarg)1558compile_err("expected character: '&'", tree[a].str);1559a=tree[a].x;1560}1561a=detag(a);1562ep=getlvalue(a);1563vn=getmvar(ep);1564if (tree[a].f==Fentry)1565{1566if (vn)1567{1568access_push(vn);1569op_push(OCsimpleptrlex, vn,n);1570}1571else1572op_push(OCsimpleptrdyn, (long)ep,n);1573}1574else1575{1576compilenewptr(vn, ep, a);1577compilelvalue(a);1578op_push(OCpushptr, 0, a);1579}1580nbpointers++;1581break;1582}1583case 'I':1584case 'E':1585case 'J':1586{1587long a = arg[j++];1588GEN d = compilefuncinline(n, c, a, flag, is_func_named(ep,"if"), lev, ev);1589op_push(OCpushgen, data_push(d), a);1590if (lg(d)==8) op_push(OCsaveframe,FLsurvive,n);1591break;1592}1593case 'V':1594{1595long a = arg[j++];1596(void)getvar(a);1597ev[lev++] = a;1598break;1599}1600case '=':1601{1602long a = arg[j++];1603ev[lev++] = tree[a].x;1604compilenode(tree[a].y, Ggen, FLnocopy);1605}1606break;1607case 'r':1608{1609long a=arg[j++];1610if (tree[a].f==Fentry)1611{1612op_push(OCpushgen, data_push(strntoGENstr(tree[tree[a].x].str,1613tree[tree[a].x].len)),n);1614op_push(OCtostr, -1,n);1615}1616else1617{1618compilenode(a,Ggen,FLnocopy);1619op_push(OCtostr, -1,n);1620}1621break;1622}1623case 's':1624{1625long a = arg[j++];1626GEN g = cattovec(a, OPcat);1627long l, nb = lg(g)-1;1628if (nb==1)1629{1630compilenode(g[1], Ggen, FLnocopy);1631op_push(OCtostr, -1, a);1632} else1633{1634op_push(OCvec, nb+1, a);1635for(l=1; l<=nb; l++)1636{1637compilenode(g[l], Ggen, FLsurvive);1638op_push(OCstackgen,l, a);1639}1640op_push(OCpop, 1, a);1641op_push(OCcallgen,(long)is_entry("Str"), a);1642op_push(OCtostr, -1, a);1643}1644break;1645}1646default:1647pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,1648tree[x].len, tree[x].str);1649}1650break;1651case PPauto:1652switch(c)1653{1654case 'p':1655op_push(OCprecreal,0,n);1656break;1657case 'b':1658op_push(OCbitprecreal,0,n);1659break;1660case 'P':1661op_push(OCprecdl,0,n);1662break;1663case 'C':1664op_push(OCpushgen,data_push(pack_localvars()),n);1665break;1666case 'f':1667{1668static long foo;1669op_push(OCpushlong,(long)&foo,n);1670break;1671}1672}1673break;1674case PPdefault:1675j++;1676switch(c)1677{1678case 'G':1679case '&':1680case 'E':1681case 'I':1682case 'r':1683case 's':1684op_push(OCpushlong,0,n);1685break;1686case 'n':1687op_push(OCpushlong,-1,n);1688break;1689case 'V':1690ev[lev++] = -1;1691break;1692case 'P':1693op_push(OCprecdl,0,n);1694break;1695default:1696pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,1697tree[x].len, tree[x].str);1698}1699break;1700case PPdefaultmulti:1701j++;1702switch(c)1703{1704case 'G':1705op_push(OCpushstoi,strtol(q+1,NULL,10),n);1706break;1707case 'L':1708case 'M':1709op_push(OCpushlong,strtol(q+1,NULL,10),n);1710break;1711case 'U':1712op_push(OCpushlong,(long)strtoul(q+1,NULL,10),n);1713break;1714case 'r':1715case 's':1716str_defproto(p, q, tree[n].str);1717op_push(OCtostr, -1, n);1718break;1719default:1720pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,1721tree[x].len, tree[x].str);1722}1723break;1724case PPstar:1725switch(c)1726{1727case 'E':1728{1729long k, n=nb+1-j;1730GEN g=cgetg(n+1,t_VEC);1731int ismif = is_func_named(ep,"_multi_if");1732for(k=1; k<=n; k++)1733gel(g, k) = compilefuncinline(n, c, arg[j+k-1], flag,1734ismif && (k==n || odd(k)), lev, ev);1735op_push(OCpushgen, data_push(g), arg[j]);1736j=nb+1;1737break;1738}1739case 's':1740{1741long n=nb+1-j;1742long k,l,l1,m;1743GEN g=cgetg(n+1,t_VEC);1744for(l1=0,k=1;k<=n;k++)1745{1746gel(g,k)=cattovec(arg[j+k-1],OPcat);1747l1+=lg(gel(g,k))-1;1748}1749op_push_loc(OCvec, l1+1, str);1750for(m=1,k=1;k<=n;k++)1751for(l=1;l<lg(gel(g,k));l++,m++)1752{1753compilenode(mael(g,k,l),Ggen,FLsurvive);1754op_push(OCstackgen,m,mael(g,k,l));1755}1756op_push_loc(OCpop, 1, str);1757j=nb+1;1758break;1759}1760default:1761pari_err(e_MISC,"Unknown prototype code `%c*' for `%.*s'",c,1762tree[x].len, tree[x].str);1763}1764break;1765default:1766pari_err_BUG("compilefunc [unknown PPproto]");1767}1768q=p;1769}1770}1771if (j<=nb)1772compile_err("too many arguments",tree[arg[j]].str);1773op_push_loc(ret_op, (long) ep, str);1774if ((ret_flag&FLnocopy) && !(flag&FLnocopy))1775op_push_loc(OCcopy,0,str);1776if (ret_typ==Ggen && nbpointers==0 && s_opcode.n>nbopcodes+128)1777{1778op_insert_loc(nbopcodes,OCavma,0,str);1779op_push_loc(OCgerepile,0,str);1780}1781compilecast(n,ret_typ,mode);1782if (nbpointers) op_push_loc(OCendptr,nbpointers, str);1783set_avma(ltop);1784}17851786static void1787genclosurectx(const char *loc, long nbdata)1788{1789long i;1790GEN vep = cgetg(nbdata+1,t_VECSMALL);1791for(i = 1; i <= nbdata; i++)1792{1793vep[i] = 0;1794op_push_loc(OCpushlex,-i,loc);1795}1796frame_push(vep);1797}17981799static GEN1800genclosure(entree *ep, const char *loc, long nbdata, int check)1801{1802struct codepos pos;1803long nb=0;1804const char *code=ep->code,*p,*q;1805char c;1806GEN text;1807long index=ep->arity;1808long arity=0, maskarg=0, maskarg0=0, stop=0, dovararg=0;1809PPproto mod;1810Gtype ret_typ;1811long ret_flag;1812op_code ret_op=get_ret_type(&code,ep->arity,&ret_typ,&ret_flag);1813p=code;1814while ((mod=parseproto(&p,&c,NULL))!=PPend)1815{1816if (mod==PPauto)1817stop=1;1818else1819{1820if (stop) return NULL;1821if (c=='V') continue;1822maskarg<<=1; maskarg0<<=1; arity++;1823switch(mod)1824{1825case PPstd:1826maskarg|=1L;1827break;1828case PPdefault:1829switch(c)1830{1831case '&':1832case 'E':1833case 'I':1834maskarg0|=1L;1835break;1836}1837break;1838default:1839break;1840}1841}1842}1843if (check && EpSTATIC(ep) && maskarg==0)1844return gen_0;1845getcodepos(&pos);1846dbgstart = loc;1847if (nbdata > arity)1848pari_err(e_MISC,"too many parameters for closure `%s'", ep->name);1849if (nbdata) genclosurectx(loc, nbdata);1850text = strtoGENstr(ep->name);1851arity -= nbdata;1852if (maskarg) op_push_loc(OCcheckargs,maskarg,loc);1853if (maskarg0) op_push_loc(OCcheckargs0,maskarg0,loc);1854p=code;1855while ((mod=parseproto(&p,&c,NULL))!=PPend)1856{1857switch(mod)1858{1859case PPauto:1860switch(c)1861{1862case 'p':1863op_push_loc(OCprecreal,0,loc);1864break;1865case 'b':1866op_push_loc(OCbitprecreal,0,loc);1867break;1868case 'P':1869op_push_loc(OCprecdl,0,loc);1870break;1871case 'C':1872op_push_loc(OCpushgen,data_push(pack_localvars()),loc);1873break;1874case 'f':1875{1876static long foo;1877op_push_loc(OCpushlong,(long)&foo,loc);1878break;1879}1880}1881default:1882break;1883}1884}1885q = p = code;1886while ((mod=parseproto(&p,&c,NULL))!=PPend)1887{1888switch(mod)1889{1890case PPstd:1891switch(c)1892{1893case 'G':1894break;1895case 'M':1896case 'L':1897op_push_loc(OCitos,-index,loc);1898break;1899case 'U':1900op_push_loc(OCitou,-index,loc);1901break;1902case 'n':1903op_push_loc(OCvarn,-index,loc);1904break;1905case '&': case '*':1906case 'I':1907case 'E':1908case 'V':1909case '=':1910return NULL;1911case 'r':1912case 's':1913op_push_loc(OCtostr,-index,loc);1914break;1915}1916break;1917case PPauto:1918break;1919case PPdefault:1920switch(c)1921{1922case 'G':1923case '&':1924case 'E':1925case 'I':1926case 'V':1927break;1928case 'r':1929case 's':1930op_push_loc(OCtostr,-index,loc);1931break;1932case 'n':1933op_push_loc(OCvarn,-index,loc);1934break;1935case 'P':1936op_push_loc(OCprecdl,0,loc);1937op_push_loc(OCdefaultlong,-index,loc);1938break;1939default:1940pari_err(e_MISC,"Unknown prototype code `D%c' for `%s'",c,ep->name);1941}1942break;1943case PPdefaultmulti:1944switch(c)1945{1946case 'G':1947op_push_loc(OCpushstoi,strtol(q+1,NULL,10),loc);1948op_push_loc(OCdefaultgen,-index,loc);1949break;1950case 'L':1951case 'M':1952op_push_loc(OCpushlong,strtol(q+1,NULL,10),loc);1953op_push_loc(OCdefaultlong,-index,loc);1954break;1955case 'U':1956op_push_loc(OCpushlong,(long)strtoul(q+1,NULL,10),loc);1957op_push_loc(OCdefaultulong,-index,loc);1958break;1959case 'r':1960case 's':1961str_defproto(p, q, loc);1962op_push_loc(OCdefaultgen,-index,loc);1963op_push_loc(OCtostr,-index,loc);1964break;1965default:1966pari_err(e_MISC,1967"Unknown prototype code `D...,%c,' for `%s'",c,ep->name);1968}1969break;1970case PPstar:1971switch(c)1972{1973case 's':1974dovararg = 1;1975break;1976case 'E':1977return NULL;1978default:1979pari_err(e_MISC,"Unknown prototype code `%c*' for `%s'",c,ep->name);1980}1981break;1982default:1983return NULL;1984}1985index--;1986q = p;1987}1988op_push_loc(ret_op, (long) ep, loc);1989if (ret_flag==FLnocopy) op_push_loc(OCcopy,0,loc);1990compilecast_loc(ret_typ, Ggen, loc);1991if (dovararg) nb|=VARARGBITS;1992return getfunction(&pos,nb+arity,nbdata,text,0);1993}19941995GEN1996snm_closure(entree *ep, GEN data)1997{1998long i, n = data ? lg(data)-1: 0;1999GEN C = genclosure(ep,ep->name,n,0);2000for(i = 1; i <= n; i++) gmael(C,7,i) = gel(data,i);2001return C;2002}20032004GEN2005strtoclosure(const char *s, long n, ...)2006{2007pari_sp av = avma;2008entree *ep = is_entry(s);2009GEN C;2010if (!ep) pari_err(e_NOTFUNC, strtoGENstr(s));2011ep = do_alias(ep);2012if ((!EpSTATIC(ep) && EpVALENCE(ep)!=EpINSTALL) || !ep->value)2013pari_err(e_MISC,"not a built-in/install'ed function: \"%s\"",s);2014C = genclosure(ep,ep->name,n,0);2015if (!C) pari_err(e_MISC,"function prototype unsupported: \"%s\"",s);2016else2017{2018va_list ap;2019long i;2020va_start(ap,n);2021for(i = 1; i <= n; i++) gmael(C,7,i) = va_arg(ap, GEN);2022va_end(ap);2023}2024return gerepilecopy(av, C);2025}20262027GEN2028strtofunction(const char *s) { return strtoclosure(s, 0); }20292030GEN2031call0(GEN fun, GEN args)2032{2033if (!is_vec_t(typ(args))) pari_err_TYPE("call",args);2034switch(typ(fun))2035{2036case t_STR:2037fun = strtofunction(GSTR(fun));2038case t_CLOSURE: /* fall through */2039return closure_callgenvec(fun, args);2040default:2041pari_err_TYPE("call", fun);2042return NULL; /* LCOV_EXCL_LINE */2043}2044}20452046static void2047closurefunc(entree *ep, long n, long mode)2048{2049pari_sp ltop=avma;2050GEN C;2051if (!ep->value) compile_err("unknown function",tree[n].str);2052C = genclosure(ep,tree[n].str,0,1);2053if (!C) compile_err("sorry, closure not implemented",tree[n].str);2054if (C==gen_0)2055{2056compilefunc(ep,n,mode,0);2057return;2058}2059op_push(OCpushgen, data_push(C), n);2060compilecast(n,Gclosure,mode);2061set_avma(ltop);2062}20632064static void2065compileseq(long n, int mode, long flag)2066{2067pari_sp av = avma;2068GEN L = listtogen(n, Fseq);2069long i, l = lg(L)-1;2070for(i = 1; i < l; i++)2071compilenode(L[i],Gvoid,0);2072compilenode(L[l],mode,flag&(FLreturn|FLsurvive));2073set_avma(av);2074}20752076static void2077compilenode(long n, int mode, long flag)2078{2079long x,y;2080#ifdef STACK_CHECK2081if (PARI_stack_limit && (void*) &x <= PARI_stack_limit)2082pari_err(e_MISC, "expression nested too deeply");2083#endif2084if (n<0) pari_err_BUG("compilenode");2085x=tree[n].x;2086y=tree[n].y;20872088switch(tree[n].f)2089{2090case Fseq:2091compileseq(n, mode, flag);2092return;2093case Fmatcoeff:2094compilematcoeff(n,mode);2095if (mode==Ggen && !(flag&FLnocopy))2096op_push(OCcopy,0,n);2097return;2098case Fassign:2099x = detag(x);2100if (tree[x].f==Fvec && tree[x].x>=0)2101{2102GEN vars = listtogen(tree[x].x,Fmatrixelts);2103long i, l = lg(vars)-1, d = mode==Gvoid? l-1: l;2104compilenode(y,Ggen,mode==Gvoid?0:flag&FLsurvive);2105for (i=1; i<=l; i++)2106if (tree[vars[i]].f==Fnoarg) d--;2107if (d) op_push(OCdup, d, x);2108for(i=1; i<=l; i++)2109if (tree[vars[i]].f!=Fnoarg)2110{2111long a = detag(vars[i]);2112entree *ep=getlvalue(a);2113long vn=getmvar(ep);2114op_push(OCpushlong,i,a);2115op_push(OCcompo1,Ggen,a);2116if (tree[a].f==Fentry)2117compilestore(vn,ep,n);2118else2119{2120compilenewptr(vn,ep,n);2121compilelvalue(a);2122op_push(OCstoreptr,0,a);2123}2124}2125if (mode!=Gvoid)2126compilecast(n,Ggen,mode);2127}2128else2129{2130entree *ep=getlvalue(x);2131long vn=getmvar(ep);2132if (tree[x].f!=Fentry)2133{2134compilenewptr(vn,ep,n);2135compilelvalue(x);2136}2137compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive);2138if (mode!=Gvoid)2139op_push(OCdup,1,n);2140if (tree[x].f==Fentry)2141compilestore(vn,ep,n);2142else2143op_push(OCstoreptr,0,x);2144if (mode!=Gvoid)2145compilecast(n,Ggen,mode);2146}2147return;2148case Fconst:2149{2150pari_sp ltop=avma;2151if (tree[n].x!=CSTquote)2152{2153if (mode==Gvoid) return;2154if (mode==Gvar) compile_varerr(tree[n].str);2155}2156if (mode==Gsmall)2157compile_err("this should be a small integer", tree[n].str);2158switch(tree[n].x)2159{2160case CSTreal:2161op_push(OCpushreal, data_push(strntoGENstr(tree[n].str,tree[n].len)),n);2162break;2163case CSTint:2164op_push(OCpushgen, data_push(strtoi((char*)tree[n].str)),n);2165compilecast(n,Ggen, mode);2166break;2167case CSTstr:2168op_push(OCpushgen, data_push(strntoGENexp(tree[n].str,tree[n].len)),n);2169break;2170case CSTquote:2171{ /* skip ' */2172entree *ep = fetch_entry_raw(tree[n].str+1,tree[n].len-1);2173if (EpSTATIC(ep)) compile_varerr(tree[n].str+1);2174op_push(OCpushvar, (long)ep,n);2175compilecast(n,Ggen, mode);2176break;2177}2178default:2179pari_err_BUG("compilenode, unsupported constant");2180}2181set_avma(ltop);2182return;2183}2184case Fsmall:2185compilesmall(n, x, mode);2186return;2187case Fvec:2188compilevec(n, mode, OCvec);2189return;2190case Fmat:2191compilemat(n, mode);2192return;2193case Frefarg:2194compile_err("unexpected character '&':",tree[n].str);2195return;2196case Findarg:2197compile_err("unexpected character '~':",tree[n].str);2198return;2199case Fentry:2200{2201entree *ep=getentry(n);2202long vn=getmvar(ep);2203if (vn)2204{2205access_push(vn);2206op_push(OCpushlex,(long)vn,n);2207addcopy(n,mode,flag,FLnocopy|FLnocopylex);2208compilecast(n,Ggen,mode);2209}2210else if (ep->valence==EpVAR || ep->valence==EpNEW)2211{2212if (DEBUGLEVEL && mode==Gvoid)2213pari_warn(warner,"statement with no effect: `%s'",ep->name);2214op_push(OCpushdyn,(long)ep,n);2215addcopy(n,mode,flag,FLnocopy);2216compilecast(n,Ggen,mode);2217}2218else2219closurefunc(ep,n,mode);2220return;2221}2222case Ffunction:2223{2224entree *ep=getfunc(n);2225if (getmvar(ep) || EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)2226{2227if (tree[n].x<OPnboperator) /* should not happen */2228compile_err("operator unknown",tree[n].str);2229compilecall(n,mode,ep);2230}2231else2232compilefunc(ep,n,mode,flag);2233return;2234}2235case Fcall:2236compilecall(n,mode,NULL);2237return;2238case Flambda:2239{2240pari_sp ltop=avma;2241struct codepos pos;2242GEN arg=listtogen(x,Flistarg);2243long nb, lgarg, nbmvar, dovararg=0, gap;2244long strict = GP_DATA->strictargs;2245GEN vep = cgetg_copy(arg, &lgarg);2246GEN text=cgetg(3,t_VEC);2247gel(text,1)=strntoGENstr(tree[x].str,tree[x].len);2248gel(text,2)=strntoGENstr(tree[y].str,tree[y].len);2249getcodepos(&pos);2250dbgstart=tree[x].str+tree[x].len;2251gap = tree[y].str-dbgstart;2252nbmvar = nblex;2253ctxmvar(nbmvar);2254nb = lgarg-1;2255if (nb)2256{2257long i;2258for(i=1;i<=nb;i++)2259{2260long a = arg[i], f = tree[a].f;2261if (i==nb && f==Fvararg)2262{2263dovararg=1;2264vep[i]=(long)getvar(tree[a].x);2265}2266else2267vep[i]=(long)getvar(f==Fassign||f==Findarg?tree[a].x:a);2268var_push(NULL,Lmy);2269}2270checkdups(arg,vep);2271op_push(OCgetargs,nb,x);2272access_push(lg(vep)-1);2273frame_push(vep);2274for (i=1;i<=nb;i++)2275{2276long a = arg[i], f = tree[a].f;2277long y = tree[a].y;2278if (f==Fassign && (strict || !is_node_zero(y)))2279{2280if (tree[y].f==Fsmall)2281compilenode(y, Ggen, 0);2282else2283{2284struct codepos lpos;2285long nbmvar = nblex;2286getcodepos(&lpos);2287compilenode(y, Ggen, 0);2288op_push(OCpushgen, data_push(getclosure(&lpos,nbmvar)),a);2289}2290op_push(OCdefaultarg,-nb+i-1,a);2291} else if (f==Findarg)2292op_push(OCsetref, -nb+i-1, a);2293localvars[s_lvar.n-nb+i-1].ep=(entree*)vep[i];2294}2295}2296if (strict)2297op_push(OCcheckuserargs,nb,x);2298dbgstart=tree[y].str;2299if (y>=0 && tree[y].f!=Fnoarg)2300compilenode(y,Ggen,FLsurvive|FLreturn);2301else2302compilecast(n,Gvoid,Ggen);2303if (dovararg) nb|=VARARGBITS;2304op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text,gap)),n);2305if (nbmvar) op_push(OCsaveframe,!!(flag&FLsurvive),n);2306compilecast(n, Gclosure, mode);2307set_avma(ltop);2308return;2309}2310case Ftag:2311compilenode(x, mode,flag);2312return;2313case Fnoarg:2314compilecast(n,Gvoid,mode);2315return;2316case Fnorange:2317op_push(OCpushlong,LONG_MAX,n);2318compilecast(n,Gsmall,mode);2319return;2320default:2321pari_err_BUG("compilenode");2322}2323}23242325GEN2326gp_closure(long n)2327{2328struct codepos pos;2329getcodepos(&pos);2330dbgstart=tree[n].str;2331compilenode(n,Ggen,FLsurvive|FLreturn);2332return getfunction(&pos,0,0,strntoGENstr(tree[n].str,tree[n].len),0);2333}23342335GEN2336closure_derivn(GEN G, long n)2337{2338pari_sp ltop = avma;2339struct codepos pos;2340long arity = closure_arity(G);2341const char *code;2342GEN t, text;23432344if (arity == 0 || closure_is_variadic(G)) pari_err_TYPE("derivfun",G);2345t = closure_get_text(G);2346code = GSTR((typ(t) == t_STR)? t: GENtoGENstr(G));2347if (n > 1)2348{2349text = cgetg(1+nchar2nlong(9+strlen(code)+n),t_STR);2350sprintf(GSTR(text), "derivn(%s,%ld)", code, n);2351}2352else2353{2354text = cgetg(1+nchar2nlong(4+strlen(code)),t_STR);2355sprintf(GSTR(text), (typ(t) == t_STR)? "%s'": "(%s)'",code);2356}2357getcodepos(&pos);2358dbgstart = code;2359op_push_loc(OCpackargs, arity, code);2360op_push_loc(OCpushgen, data_push(G), code);2361op_push_loc(OCpushlong, n, code);2362op_push_loc(OCprecreal, 0, code);2363op_push_loc(OCcallgen, (long)is_entry("_derivfun"), code);2364return gerepilecopy(ltop, getfunction(&pos, arity, 0, text, 0));2365}23662367GEN2368closure_deriv(GEN G)2369{ return closure_derivn(G, 1); }23702371static long2372vec_optimize(GEN arg)2373{2374long fl = COsafelex|COsafedyn;2375long i;2376for (i=1; i<lg(arg); i++)2377{2378optimizenode(arg[i]);2379fl &= tree[arg[i]].flags;2380}2381return fl;2382}23832384static void2385optimizevec(long n)2386{2387pari_sp ltop=avma;2388long x = tree[n].x;2389GEN arg = listtogen(x, Fmatrixelts);2390tree[n].flags = vec_optimize(arg);2391set_avma(ltop);2392}23932394static void2395optimizemat(long n)2396{2397pari_sp ltop = avma;2398long x = tree[n].x;2399long i;2400GEN line = listtogen(x,Fmatrixlines);2401long fl = COsafelex|COsafedyn;2402for(i=1;i<lg(line);i++)2403{2404GEN col=listtogen(line[i],Fmatrixelts);2405fl &= vec_optimize(col);2406}2407set_avma(ltop); tree[n].flags=fl;2408}24092410static void2411optimizematcoeff(long n)2412{2413long x=tree[n].x;2414long y=tree[n].y;2415long yx=tree[y].x;2416long yy=tree[y].y;2417long fl;2418optimizenode(x);2419optimizenode(yx);2420fl=tree[x].flags&tree[yx].flags;2421if (yy>=0)2422{2423optimizenode(yy);2424fl&=tree[yy].flags;2425}2426tree[n].flags=fl;2427}24282429static void2430optimizefunc(entree *ep, long n)2431{2432pari_sp av=avma;2433long j;2434long x=tree[n].x;2435long y=tree[n].y;2436Gtype t;2437PPproto mod;2438long fl=COsafelex|COsafedyn;2439const char *p;2440char c;2441GEN arg = listtogen(y,Flistarg);2442long nb=lg(arg)-1, ret_flag;2443if (is_func_named(ep,"if") && nb>=4)2444ep=is_entry("_multi_if");2445p = ep->code;2446if (!p)2447fl=0;2448else2449(void) get_ret_type(&p, 2, &t, &ret_flag);2450if (p && *p)2451{2452j=1;2453while((mod=parseproto(&p,&c,tree[n].str))!=PPend)2454{2455if (j<=nb && tree[arg[j]].f!=Fnoarg2456&& (mod==PPdefault || mod==PPdefaultmulti))2457mod=PPstd;2458switch(mod)2459{2460case PPstd:2461if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1);2462if (tree[arg[j]].f==Fnoarg && c!='I' && c!='E')2463compile_err("missing mandatory argument", tree[arg[j]].str);2464switch(c)2465{2466case 'G':2467case 'n':2468case 'M':2469case 'L':2470case 'U':2471case 'P':2472optimizenode(arg[j]);2473fl&=tree[arg[j++]].flags;2474break;2475case 'I':2476case 'E':2477case 'J':2478optimizenode(arg[j]);2479fl&=tree[arg[j]].flags;2480tree[arg[j++]].flags=COsafelex|COsafedyn;2481break;2482case '&': case '*':2483{2484long a=arg[j];2485if (c=='&')2486{2487if (tree[a].f!=Frefarg)2488compile_err("expected character: '&'", tree[a].str);2489a=tree[a].x;2490}2491optimizenode(a);2492tree[arg[j++]].flags=COsafelex|COsafedyn;2493fl=0;2494break;2495}2496case 'W':2497{2498long a = tree[arg[j]].f==Findarg ? tree[arg[j]].x: arg[j];2499optimizenode(a);2500fl=0; j++;2501break;2502}2503case 'V':2504case 'r':2505tree[arg[j++]].flags=COsafelex|COsafedyn;2506break;2507case '=':2508{2509long a=arg[j++], y=tree[a].y;2510if (tree[a].f!=Fassign)2511compile_err("expected character: '=' instead of",2512tree[a].str+tree[a].len);2513optimizenode(y);2514fl&=tree[y].flags;2515}2516break;2517case 's':2518fl &= vec_optimize(cattovec(arg[j++], OPcat));2519break;2520default:2521pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c,2522tree[x].len, tree[x].str);2523}2524break;2525case PPauto:2526break;2527case PPdefault:2528case PPdefaultmulti:2529if (j<=nb) optimizenode(arg[j++]);2530break;2531case PPstar:2532switch(c)2533{2534case 'E':2535{2536long n=nb+1-j;2537long k;2538for(k=1;k<=n;k++)2539{2540optimizenode(arg[j+k-1]);2541fl &= tree[arg[j+k-1]].flags;2542}2543j=nb+1;2544break;2545}2546case 's':2547{2548long n=nb+1-j;2549long k;2550for(k=1;k<=n;k++)2551fl &= vec_optimize(cattovec(arg[j+k-1],OPcat));2552j=nb+1;2553break;2554}2555default:2556pari_err(e_MISC,"Unknown prototype code `%c*' for `%.*s'",c,2557tree[x].len, tree[x].str);2558}2559break;2560default:2561pari_err_BUG("optimizefun [unknown PPproto]");2562}2563}2564if (j<=nb)2565compile_err("too many arguments",tree[arg[j]].str);2566}2567else (void)vec_optimize(arg);2568set_avma(av); tree[n].flags=fl;2569}25702571static void2572optimizecall(long n)2573{2574pari_sp av=avma;2575long x=tree[n].x;2576long y=tree[n].y;2577GEN arg=listtogen(y,Flistarg);2578optimizenode(x);2579tree[n].flags = COsafelex&tree[x].flags&vec_optimize(arg);2580set_avma(av);2581}25822583static void2584optimizeseq(long n)2585{2586pari_sp av = avma;2587GEN L = listtogen(n, Fseq);2588long i, l = lg(L)-1, flags=-1L;2589for(i = 1; i <= l; i++)2590{2591optimizenode(L[i]);2592flags &= tree[L[i]].flags;2593}2594set_avma(av);2595tree[n].flags = flags;2596}25972598void2599optimizenode(long n)2600{2601long x,y;2602#ifdef STACK_CHECK2603if (PARI_stack_limit && (void*) &x <= PARI_stack_limit)2604pari_err(e_MISC, "expression nested too deeply");2605#endif2606if (n<0)2607pari_err_BUG("optimizenode");2608x=tree[n].x;2609y=tree[n].y;26102611switch(tree[n].f)2612{2613case Fseq:2614optimizeseq(n);2615return;2616case Frange:2617optimizenode(x);2618optimizenode(y);2619tree[n].flags=tree[x].flags&tree[y].flags;2620break;2621case Fmatcoeff:2622optimizematcoeff(n);2623break;2624case Fassign:2625optimizenode(x);2626optimizenode(y);2627tree[n].flags=0;2628break;2629case Fnoarg:2630case Fnorange:2631case Fsmall:2632case Fconst:2633case Fentry:2634tree[n].flags=COsafelex|COsafedyn;2635return;2636case Fvec:2637optimizevec(n);2638return;2639case Fmat:2640optimizemat(n);2641return;2642case Frefarg:2643compile_err("unexpected character '&'",tree[n].str);2644return;2645case Findarg:2646return;2647case Fvararg:2648compile_err("unexpected characters '..'",tree[n].str);2649return;2650case Ffunction:2651{2652entree *ep=getfunc(n);2653if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)2654optimizecall(n);2655else2656optimizefunc(ep,n);2657return;2658}2659case Fcall:2660optimizecall(n);2661return;2662case Flambda:2663optimizenode(y);2664tree[n].flags=COsafelex|COsafedyn;2665return;2666case Ftag:2667optimizenode(x);2668tree[n].flags=tree[x].flags;2669return;2670default:2671pari_err_BUG("optimizenode");2672}2673}267426752676