Skip to content

Commit b6115f0

Browse files
committed
name:: (incomplete)
1 parent edb4fee commit b6115f0

10 files changed

Lines changed: 281 additions & 217 deletions

File tree

jsrc/cx.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ static A jtsent12b(J jt,A w){A t,*wv,y,*yv;I j,*v;
794794
// a valid hash of a locative name
795795
// actstv points to the chain headers, actstn is the number of chains
796796
// all the chains have had the non-PERMANENT flag cleared in the pointers
797-
// recur is set if *t is part of a recursive noun
797+
// recur is set if *t is part of a recursive noun.
798798
static A jtcalclocalbuckets(J jt, A *t, LX *actstv, I actstn, I dobuckets, I recur){LX k;
799799
A tv=*t; // the actual NAME block
800800
L *sympv=JT(jt,sympv); // base of symbol table
@@ -809,10 +809,13 @@ static A jtcalclocalbuckets(J jt, A *t, LX *actstv, I actstn, I dobuckets, I rec
809809
for(k=actstv[bucket];k;++compcount,k=sympv[k].next){ // k chases the chain of symbols in selected bucket
810810
if(NAV(tv)->m==NAV(sympv[k].name)->m&&!memcmpne(NAV(tv)->s,NAV(sympv[k].name)->s,NAV(tv)->m)){
811811
// match found. this is a local name. Replace it with the shared copy, flag as shared, set negative bucket#
812+
// suppress this step if the type is ornamented, i. e. if it is name:: - then we need a flagged copy
812813
A oldtv=tv;
813-
*t=tv=sympv[k].name; // use shared copy
814-
if(recur){ras(tv); fa(oldtv);} // if we are installing into a recursive box, increment/decr usecount new/old
815-
NAV(tv)->flag|=NMSHARED; // tag the shared copy as shared
814+
if(likely(!(AT(tv)&NAMEABANDON))){ // not name::
815+
*t=tv=sympv[k].name; // use shared copy
816+
if(recur){ras(tv); fa(oldtv);} // if we are installing into a recursive box, increment/decr usecount new/old
817+
NAV(tv)->flag|=NMSHARED; // tag the shared copy as shared
818+
}
816819
// Remember the exact location of the symbol. It will not move as long as this symbol table is alive. We can
817820
// use it only when we are in this primary symbol table
818821
NAV(tv)->symx=k; // keep index of the allocated symbol
@@ -869,7 +872,7 @@ A jtcrelocalsyms(J jt, A l, A c,I type, I dyad, I flags){A actst,*lv,pfst,t,wds;
869872
ln=AN(l); lv=AAV(l); // Get # words, address of first box
870873
for(j=1;j<ln;++j) { // start at 1 because we look at previous word
871874
t=lv[j-1]; // t is the previous word
872-
// look for 'names' =./=: . If found (and the names do not begin with `, replace the string with a special form: a list of boxes where each box contains a name.
875+
// look for 'names' =./=: . If found (and the names do not begin with `), replace the string with a special form: a list of boxes where each box contains a name.
873876
// This form can appear only in compiled definitions
874877
if(AT(lv[j])&ASGN&&AT(t)&LIT&&AN(t)&&CAV(t)[0]!=CGRAVE){
875878
A neww=words(t);
@@ -882,7 +885,13 @@ A jtcrelocalsyms(J jt, A l, A c,I type, I dyad, I flags){A actst,*lv,pfst,t,wds;
882885
if((AT(lv[j])&ASGN+ASGNLOCAL)==(ASGN+ASGNLOCAL)) { // local assignment
883886
if(AT(lv[j])&ASGNTONAME){ // preceded by name?
884887
// Lookup the name, which will create the symbol-table entry for it
885-
RZ(probeis(t,pfst));
888+
// name:: causes a little trouble. The name carries with it the :: flag, but we will eventually replace all refs with the srade ref from
889+
// this table. That means we have to remove the :: flag from the stored value, lest every reference appear flagged just because the last one was.
890+
// Note that we are here looking only before =., so we are specifically checking for name:: =. ... . This should be an error, and we might catch
891+
// it when executed; but we are just making sure that it doesn't make the refs invalid. name:: also sets NAMEXY, and we have to leave that because
892+
// any valid ref to mnuvxy will need that set; so there is a chance that name:: =. will result in an ordinary reference to the name's having the NAMEXY
893+
// flag. That won't hurt anything significant.
894+
L *nml; RZ(nml=probeis(t,pfst)); AT(nml->name)&=~NAMEABANDON; // put name in symbol table, with ABANDON flag cleared
886895
} else if(AT(t)&LIT) {
887896
// LIT followed by =. Probe each word. Now that we support lists of NAMEs, this is used only for AR assignments
888897
// First, convert string to words
@@ -892,13 +901,13 @@ A jtcrelocalsyms(J jt, A l, A c,I type, I dyad, I flags){A actst,*lv,pfst,t,wds;
892901
for(kk=0;kk<wdsn;++kk) {
893902
// Convert word to NAME; if local name, add to symbol table
894903
if((wnm=onm(wdsv[kk]))) {
895-
if(!(NAV(wnm)->flag&(NMLOC|NMILOC)))RZ(probeis(wnm,pfst));
904+
if(!(NAV(wnm)->flag&(NMLOC|NMILOC))){L *nml; RZ(nml=probeis(wnm,pfst)); AT(nml->name)&=~NAMEABANDON;} // see above
896905
} else RESETERR
897906
}
898907
} else RESETERR // if invalid words, ignore - we don't catch it here
899908
}else if((AT(t)&BOX+BOXMULTIASSIGN)==BOX+BOXMULTIASSIGN){ // not NAME, not LIT; is it NAMEs box?
900909
// the special form created above. Add each non-global name to the symbol table
901-
A *tv=AAV(t); DO(AN(t), if(!(NAV(tv[i])->flag&(NMLOC|NMILOC)))RZ(probeis(tv[i],pfst));)
910+
A *tv=AAV(t); DO(AN(t), if(!(NAV(tv[i])->flag&(NMLOC|NMILOC))){L *nml; RZ(nml=probeis(tv[i],pfst)); AT(nml->name)&=~NAMEABANDON;})
902911
}
903912
} // end 'local assignment'
904913
} // for each word in sentence

jsrc/d.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static I jtdisp(J jt,A w,I nflag){B b=1&&AT(w)&NAME+NUMERIC;
113113
// If this is an array of names, turn it back into a character string with spaces between
114114
else{w=curtail(raze(every2(every(w,(A)&sfn0overself),chrspace,(A)&sfn0overself)));} // }: (string&.> names) ,&.> ' ' then fall through to display it
115115
case LITX: eputq(w,(nflag&1)); break;
116-
case NAMEX: ep(AN(w),NAV(w)->s); break;
116+
case NAMEX: ep(AN(w),NAV(w)->s); if(unlikely((AT(w)&NAMEABANDON)!=0)){ep(2,"::");} break;
117117
case LPARX: eputc('('); break;
118118
case RPARX: eputc(')'); break;
119119
case ASGNX: dspell(CAV(w)[0],w,(nflag&1)); break;

jsrc/ja.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,10 +1204,11 @@
12041204
// Handle top level of tpush(). push the current block, and recur if it is traversible and does not have recursive usecount
12051205
// We can have an inplaceable but recursible block, if it was gc'd. We never push a PERMANENT block, so that we won't try to free it
12061206
// NOTE that PERMANENT blocks are always marked traversible if they are of traversible type, so we will not recur on them internally
1207-
#define tpushcommon(x,suffix) {if(likely(!ACISPERM(AC(x)))){I tt=AT(x); A *pushp=jt->tnextpushp; *pushp++=(x); \
1208-
if(unlikely(!((I)pushp&(NTSTACKBLOCK-1)))){RZ(pushp=tg(pushp));} if(unlikely(((tt^AFLAG(x))&TRAVERSIBLE)!=0))RZ(pushp=jttpush(jt,(x),tt,pushp)); jt->tnextpushp=pushp; suffix}}
1209-
#define tpush(x) tpushcommon(x,if(MEMAUDIT&2)audittstack(jt);)
1210-
#define tpushna(x) tpushcommon(x,) // suppress audit
1207+
#define tpushcommon(x,tmask,suffix) {if(likely(!ACISPERM(AC(x)))){I tt=AT(x); A *pushp=jt->tnextpushp; *pushp++=(x); \
1208+
if(unlikely(!((I)pushp&(NTSTACKBLOCK-1)))){RZ(pushp=tg(pushp));} if(unlikely(((tt^AFLAG(x))&(tmask))!=0))RZ(pushp=jttpush(jt,(x),tt,pushp)); jt->tnextpushp=pushp; suffix}}
1209+
#define tpush(x) tpushcommon(x,TRAVERSIBLE,if(MEMAUDIT&2)audittstack(jt);)
1210+
#define tpushna(x) tpushcommon(x,TRAVERSIBLE,) // suppress audit
1211+
#define tpushnr(x) tpushcommon(x,0,if(MEMAUDIT&2)audittstack(jt);) // suppress recursion
12111212
// Internal version, used when the local name pushp is known to hold jt->tnextpushp
12121213
#define tpushi(x) {if(likely(!ACISPERM(AC(x)))){I tt=AT(x); *pushp++=(x); if(unlikely(!((I)pushp&(NTSTACKBLOCK-1)))){RZ(pushp=tg(pushp));} if((unlikely((tt^AFLAG(x))&TRAVERSIBLE)!=0))RZ(pushp=jttpush(jt,(x),tt,pushp)); }}
12131214
// tpush1 is like tpush, but it does not recur to lower levels. Used only for virtual block (which cannot be PERMANENT)

jsrc/jtype.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ typedef I SI;
323323
#define NAMEX 23
324324
#define NAME ((I)1L<<NAMEX) /* NM name */
325325
#define NAMESIZE sizeof(C) // when we allocate a NAME type, the length is the length of the name string
326+
// NOTE: VERB, SYMB, and LPAR are used as flags in names
326327
#define SYMBX 24
327328
#define SYMB ((I)1L<<SYMBX) /* I locale (symbol table) */
328329
#define SYMBSIZE sizeof(LX)
@@ -341,15 +342,13 @@ typedef I SI;
341342
#define LPAR ((I)1L<<LPARX) /* I left parenthesis */
342343
// note: LPAR used as flag to cvt() see below; also as modifier to ADV type
343344
#define LPARSIZE sizeof(I)
344-
// CONJ must be 1 bit below RPAR, with no parsable type (including any flags that might be set, see below) higher than RPAR
345+
// CONJ must be 1 bit below RPAR, with no parsable type (including any flags that might be set, see below) in CONJ or RPAR
345346
#define CONJX 29
346347
#define CONJ ((I)1L<<CONJX) /* V conjunction */
347348
#define CONJSIZE sizeof(V)
348349
#define RPARX 30
349350
#define RPAR ((I)1L<<RPARX) /* I right parenthesis */
350351
#define RPARSIZE sizeof(I)
351-
#define SPARSEX 31 // NOTE this extends to the sign bit
352-
#define SPARSE (-((I)1L<<SPARSEX)) /* P sparse boxed */
353352

354353
#define ASGNX 21
355354
#define ASGN ((I)1L<<ASGNX) /* I assignment */
@@ -361,8 +360,13 @@ typedef I SI;
361360
// NOTE: The parser assumes that CONW always means ASGNTONAME, so don't use it in any parseable type (such as NAME, NOUN)
362361
// ** NOUN types can have the following informational bits set
363362
#define NOUNCVTVALIDCT ((I)1L<<SYMBX) // Flag for jtcvt arg only: if set, convert only the #atoms given in the parameter Aliases with SYMB
363+
#define SPARSEX 31 // NOTE this extends to the sign bit
364+
#define SPARSE (-((I)1L<<SPARSEX)) /* P sparse boxed */
364365
// ** NAME type can have the following information flags set
365366
#define NAMEBYVALUE ((I)1L<<SYMBX) // set if the name is one of x x. m m. etc that is always passed by value, never by name Aliases with SYMB
367+
#define NAMEABANDONX LPARX
368+
#define NAMEABANDON ((I)1L<<NAMEABANDONX) // name is name::, which will be deassigned after the value is stacked. NAMEBYVALUE must also be set
369+
// in the parser VERB is set in a NAME type to indicate use of global symbol table
366370
// ** BOX type can have the following informational flags set
367371
#define BOXMULTIASSIGN ((I)1L<<MARKX) // set for the target of a direct multiple assignment (i. e. 'x y' =.), which is stored as a boxed list whose contents are NAMEs aliases with MARK
368372
// Restriction: CONW must be reserved for use as ASGNTONAME because of how parser tests for it
@@ -477,7 +481,7 @@ typedef I SI;
477481
#define ACINCR(a) ACINCRLOCAL(a)
478482
#define ACDECR(a) ACDECRLOCAL(a)
479483
#define ACINIT(a,v) AC(a)=(v); // used when it is known that a has just been allocated & is not shared
480-
#define ACRESET(a,v) AC(a)=(v); // used when it is known that a has is not shared (perhaps it's UNINCORPABLE)
484+
#define ACRESET(a,v) AC(a)=(v); // used when it is known that a is not shared (perhaps it's UNINCORPABLE)
481485
#define ACSET(a,v) AC(a)=(v); // used when a might be shared, but atomic not needed
482486
#define ACFAUX(a,v) AC(a)=(v); // used when a is known to be a faux block
483487
#define ACINITZAP(a) {*AZAPLOC(a)=0; ACINIT(a,ACUC1)} // effect ra() immediately after allocation, by zapping
@@ -562,6 +566,7 @@ typedef I SI;
562566
#define AMNVRDECR(a,am) (am=AM(a),AM(a)-=AMNVRCT,am) // save count, decrement, return old value
563567
#define AMNVRSET(a,x) (AM(a)=(x))
564568
#define AMNVRAND(a,x) (AM(a)&=(x)); // AND, no return
569+
#define AMNVROR(a,x) (AM(a)|=(x)); // OR, no return
565570
// decide action and new AM value to free a
566571
// nvrct!=0, !free -> set free
567572
// nvrct!=0, free -> no chg, fa

jsrc/m.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ static A raonlys(AD * RESTRICT w) { RZQ(w);
767767

768768
// This routine handles the recursion for ra(). ra() itself does the top level, this routine handles the contents
769769
I jtra(AD* RESTRICT wd,I t){I n=AN(wd);
770+
// we use if rather than switch because the first leg is most likely and the first two legs get almost everything
770771
if(t&BOX){AD* np;
771772
// boxed. Loop through each box, recurring if called for. Two passes are intertwined in the loop
772773
A* RESTRICT wv=AAV(wd); // pointer to box pointers

0 commit comments

Comments
 (0)