Mercurial > hg > jgplsrc
view s.c @ 0:e0bbaa717f41 draft default tip
lol J
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Mon, 25 Nov 2013 11:56:30 -0500 |
parents | |
children |
line wrap: on
line source
/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ /* License in license.txt. */ /* */ /* Symbol Table */ #include "j.h" /* a symbol table aka locale is a type INT vector */ /* the length is prime and is one of ptab[i] */ /* zero elements mean unused entry */ /* non-zero elements are indices in the global symbol pool and */ /* are head pointers to a linked list */ /* the first element is symbol pool index for locale info */ /* the global symbol pool is a type INT matrix */ /* the number of columns is symcol=ceiling(sizeof(L)/sizeof(I)) */ /* elements are interpreted per type L (see jtype.h) */ /* A name - A name on LHS of assignment or locale name */ /* A val - value or locale search path */ /* I sn - script index */ /* I flag - various flags */ /* I next - pointer to successor in linked list */ /* I prev - pointer to predecessor in linked list */ /* if no predecessor then pointer to hash table entry, and */ /* flag will include LHEAD */ /* a stack of free entries is kept using the next pointer */ /* jt->symp: symbol pool array */ /* jt->sympv: symbol pool array pointer, (L*)AV(jt->symp) */ /* jt->symindex: symbol table index (monotonically increasing) */ /* numbered locales: */ /* jt->stnum: -1 means free; others are numbers in use */ /* jt->stptr: 0 means free; others are symbol tables */ /* jt->stused: # entries in stnum/stptr in use */ /* jt->stmax: 1 + maximum number extant */ /* named locales: */ /* jt->stloc: locales symbol table */ static I symcol=(sizeof(L)+SZI-1)/SZI; B jtsymext(J jt,B b){A x,y;I j,m,n,s[2],*v,xn,yn;L*u; if(b){y=jt->symp; j=((MS*)y-1)->j; n=*AS(y); yn=AN(y);} else { j=12; n=1; yn=0; } m=msize[1+j]; /* new size in bytes */ m-=sizeof(MS)+SZI*(AH+2); /* less array overhead */ m/=symcol*SZI; /* new # rows */ s[0]=m; s[1]=symcol; xn=m*symcol; /* new pool array shape */ GA(x,INT,xn,2,s); v=AV(x); /* new pool array */ if(b)ICPY(v,AV(y),yn); /* copy old data to new array */ memset(v+yn,C0,SZI*(xn-yn)); /* 0 unused area for safety */ u=n+(L*)v; j=1+n; DO(m-n-1, u++->next=j++;); /* build free list extension */ if(b)u->next=jt->sympv->next; /* push extension onto stack */ ((L*)v)->next=n; /* new stack top */ jt->symp =ra(x); /* preserve new array */ jt->sympv=(L*)AV(x); /* new array value ptr */ if(b)fa(y); /* release old array */ R 1; } /* 0: initialize (no old array); 1: extend old array */ L* jtsymnew(J jt,I*hv){I j;L*u,*v; while(!(j=jt->sympv->next))RZ(symext(1)); /* extend pool if req'd */ jt->sympv->next=(j+jt->sympv)->next; /* new top of stack */ u=j+jt->sympv; if(u->next=*hv){v=*hv+jt->sympv; v->prev=j; v->flag^=LHEAD;} u->prev=(I)hv; u->flag=LHEAD; *hv=j; R u; } /* allocate a new pool entry and insert into hash table entry hv */ B jtsymfree(J jt,L*u){I q; q=u->next; if(q)(q+jt->sympv)->prev=u->prev; if(LHEAD&u->flag){*(I*)u->prev=q; if(q)(q+jt->sympv)->flag|=LHEAD;} else (u->prev+jt->sympv)->next=q; fa(u->name); u->name=0; /* zero out data fields */ fa(u->val ); u->val =0; u->sn=u->flag=u->prev=0; u->next=jt->sympv->next; /* point to old top of stack */ jt->sympv->next=u-jt->sympv; /* new top of stack */ R 1; } /* free pool entry pointed to by u */ static SYMWALK(jtsymfreeha, B,B01,100,1, 1, RZ(symfree(d))) /* free pool table entries */ B jtsymfreeh(J jt,A w,L*v){I*wv;L*u; wv=AV(w); ASSERTSYS(*wv,"symfreeh"); u=*wv+jt->sympv; RZ(symfree(u)); RZ(symfreeha(w)); memset(wv,C0,AN(w)*SZI); fa(w); if(v){v->val=0; RZ(symfree(v));} R 1; } /* free entire hash table w, (optional) pointed by v */ static SYMWALK(jtsympoola, I,INT,100,1, 1, *zv++=j;) F1(jtsympool){A aa,*pu,q,x,y,*yv,z,*zv;I i,j,n,*u,*v,*xv;L*pv; RZ(w); ASSERT(1==AR(w),EVRANK); ASSERT(!AN(w),EVLENGTH); GA(z,BOX,3,1,0); zv=AAV(z); n=*AS(jt->symp); pv=jt->sympv; GA(x,INT,n*6,2,0); *AS(x)=n; *(1+AS(x))=6; xv= AV(x); zv[0]=x; GA(y,BOX,n, 1,0); yv=AAV(y); zv[1]=y; for(i=0;i<n;++i,++pv){ /* per pool entry */ *xv++=i; *xv++=(q=pv->val)?AT(pv->val):0; *xv++=pv->flag; *xv++=pv->sn; *xv++=pv->next; *xv++=pv->prev; RZ(*yv++=(q=pv->name)?sfn(1,q):mtv); } GA(y,BOX,n,1,0); yv=AAV(y); zv[2]=y; DO(n, yv[i]=mtv;); n=AN(jt->stloc); v=AV(jt->stloc); for(i=0;i<n;++i)if(j=v[i]){ /* per named locales */ x=(j+jt->sympv)->val; RZ(yv[j]=yv[*AV(x)]=aa=sfn(1,LOCNAME(x))); RZ(q=sympoola(x)); u=AV(q); DO(AN(q), yv[u[i]]=aa;); } n=AN(jt->stptr); pu=AAV(jt->stptr); for(i=0;i<n;++i)if(x=pu[i]){ /* per numbered locales */ RZ( yv[*AV(x)]=aa=sfn(1,LOCNAME(x))); RZ(q=sympoola(x)); u=AV(q); DO(AN(q), yv[u[i]]=aa;); } if(x=jt->local){ /* per local table */ RZ( yv[*AV(x)]=aa=cstr("**local**")); RZ(q=sympoola(x)); u=AV(q); DO(AN(q), yv[u[i]]=aa;); } R z; } /* 18!:31 symbol pool */ L*jtprobe(J jt,A a,A g){C*s;I*hv,k,m;L*v;NM*u; RZ(a&&g); u=NAV(a); m=u->m; s=u->s; k=u->hash%AN(g); hv=AV(g)+(k?k:1); if(!*hv)R jt->cursymb=0; /* (0) empty slot */ v=*hv+jt->sympv; while(1){ u=NAV(v->name); if(m==u->m&&!memcmp(s,u->s,m))R jt->cursymb=v; /* (1) exact match */ if(!v->next)R jt->cursymb=0; /* (2) link list end */ v=v->next+jt->sympv; }} static L*jtprobeis(J jt,A a,A g){C*s;I*hv,k,m;L*v;NM*u; u=NAV(a); m=u->m; s=u->s; k=u->hash%AN(g); hv=AV(g)+(k?k:1); if(*hv){ /* !*hv means (0) empty slot */ v=*hv+jt->sympv; while(1){ u=NAV(v->name); if(m==u->m&&!memcmp(s,u->s,m))R jt->cursymb=v; /* (1) exact match */ if(!v->next)break; /* (2) link list end */ v=v->next+jt->sympv; }} RZ(v=symnew(hv)); v->name=ra(a); R jt->cursymb=v; } /* probe for assignment */ static L*jtsyrd1(J jt,A a,A g,B b){A*v,x,y;L*e;NM*av; if(b&&jt->local&&(e=probe(a,jt->local))){av=NAV(a); R av->e=e;} RZ(g&&(y=LOCPATH(g))); if(e=probe(a,g))R e; v=AAV(y); DO(AN(y), x=v[i]; if(e=probe(a,stfind(1,AN(x),CAV(x))))break;); R e; } /* find name a where the current locale is g */ static A jtlocindirect(J jt,I n,C*u){A a,g=jt->global,x,y;B lcl=1;C*s,*v,*xv;I k,xn;L*e; s=n+u; while(u<s){ v=s; while('_'!=*--v); ++v; k=s-v; s=v-2; RZ(a=nfs(k,v)); e=syrd1(a,g,lcl); lcl=0; ASSERTN(e,EVVALUE,a); y=e->val; ASSERTN(!AR(y),EVRANK,a); ASSERTN(BOX&AT(y),EVDOMAIN,a); x=AAV0(y); xn=AN(x); xv=CAV(x); ASSERTN(1>=AR(x),EVRANK,a); ASSERTN(xn,EVLENGTH,a); ASSERTN(LIT&AT(x),EVDOMAIN,a); ASSERTN(vlocnm(xn,xv),EVILNAME,a); RZ(g=stfind(1,xn,xv)); } R g; } L*jtsyrd(J jt,A a,A*symb){A g=jt->global;I m,n;NM*v; RZ(a); n=AN(a); v=NAV(a); m=v->m; if(n>m)RZ(g=NMILOC&v->flag?locindirect(n-m-2,2+m+v->s):stfind(1,n-m-2,1+m+v->s)) if(symb)*symb=g; R syrd1(a,g,(B)(n==m)); } static A jtdllsymaddr(J jt,A w,C flag){A*wv,x,y,z;I i,n,wd,*zv;L*v; RZ(w); n=AN(w); wv=AAV(w); wd=(I)w*ARELATIVE(w); ASSERT(!n||BOX&AT(w),EVDOMAIN); GA(z,INT,n,AR(w),AS(w)); zv=AV(z); for(i=0;i<n;++i){ x=WVR(i); v=syrd(nfs(AN(x),CAV(x)),0L); ASSERT(v,EVVALUE); y=v->val; ASSERT(NOUN&AT(y),EVDOMAIN); zv[i]=flag?(I)AV(y):(I)v; } R z; } /* 15!:6 (0=flag) or 15!:14 (1=flag) */ F1(jtdllsymget){R dllsymaddr(w,0);} F1(jtdllsymdat){R dllsymaddr(w,1);} F1(jtsymbrd){L*v; RZ(w); ASSERTN(v=syrd(w,0L),EVVALUE,w); R v->val;} F1(jtsymbrdlock){A y; RZ(y=symbrd(w)); R FUNC&AT(y)&&(jt->glock||VLOCK&VAV(y)->flag)?nameref(w):y; } B jtredef(J jt,A w,L*v){A f,oldn;DC c,d; d=jt->sitop; while(d&&!(DCCALL==d->dctype&&d->dcj))d=d->dclnk; if(!(d&&DCCALL==d->dctype&&d->dcj))R 1; oldn=jt->curname; if(v==(L*)d->dcn){ jt->curname=d->dca; f=d->dcf; ASSERT(AT(f)==AT(w)&&(CCOLON==VAV(f)->id)==(CCOLON==VAV(w)->id),EVSTACK); d->dcf=w; if(CCOLON==VAV(w)->id)jt->redefined=(I)v; c=jt->sitop; while(c&&DCCALL!=c->dctype){c->dctype=DCJUNK; c=c->dclnk;} } c=d; while(c=c->dclnk){jt->curname=c->dca; ASSERT(!(DCCALL==c->dctype&&v==(L*)c->dcn),EVSTACK);} jt->curname=oldn; R 1; } /* check for changes to stack */ A jtsymbis(J jt,A a,A w,A g){A x;I m,n,wn,wr,wt;NM*v;L*e;V*wv; RZ(a&&w&&g); n=AN(a); v=NAV(a); m=v->m; if(n==m)ASSERT(!(jt->local&&g==jt->global&&probe(a,jt->local)),EVDOMAIN) else{C*s=1+m+v->s; RZ(g=NMILOC&v->flag?locindirect(n-m-2,1+s):stfind(1,n-m-2,s));} RZ(e=probeis(a,g)); if(jt->db)RZ(redef(w,e)); wt=AT(w); if(wt&FUNC&&(wv=VAV(w),wv->f)){if(wv->id==CCOLON)wv->flag|=VNAMED; if(jt->glock)wv->flag|=VLOCK;} x=e->val; ASSERT(!(x&&AFRO&AFLAG(x)),EVRO); if(!(x&&AFNJA&AFLAG(x))){ RZ(w=ra(AFNJA&AFLAG(w)?w:rca(w))); nvrredef(x); fa(x); e->val=w; }else if(x!=w){ /* replacing mapped data */ if(wt&BOX)R smmis(x,w); wn=AN(w); wr=AR(w); m=wn*bp(wt); ASSERT(wt&B01+INT+FL+CMPX+LIT,EVDOMAIN); ASSERT(AM(x)>=m,EVALLOC); AT(x)=wt; AN(x)=wn; AR(x)=wr; ICPY(AS(x),AS(w),wr); MC(AV(x),AV(w),m); } e->sn=jt->slisti; if(jt->stch&&(m<n||jt->local!=g&&jt->stloc!=g))e->flag|=LCH; R mark; } /* a: name; w: value; g: symbol table */