view pv.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.                                   */
/*                                                                         */
/* Parsing: Tacit Verb Translator (13 : )                                  */

#include "j.h"
#include "p.h"

#define WTA         2     /* sizeof(TA)/sizeof(A) */
#define NTTAB       20
#define TC          5485900

#define CHK1        (!(stack[b].t)                          )
#define CHK2        (!(stack[b].t||stack[e].t)              )
#define CHK3        (!(stack[b].t||stack[1+b].t||stack[e].t))
#define CP          ds(CCAP)
#define DCASE(x,y)  (6*(x)+(y))
#define FGL(v)      folk(v->f,v->g,ds(CLEFT ))
#define FGR(v)      folk(v->f,v->g,ds(CRIGHT))
#define LF          ds(CLEFT )
#define RT          ds(CRIGHT)
#define RZZ(exp)    {if(!(exp))R zz;}


static TA zz={0,0};

static F1(jtvtokens){A t,*y,z;I n,*s;TA*x;
 RZ(t=tokens(vs(w))); n=AN(t); y=AAV(t);
 jt->tmonad=1; 
 GA(z,BOX,WTA*(5+n),2,0); s=AS(z); *s++=5+n; *s=WTA;
 x=(TA*)AV(z);
 x->a=mark; x->t=0; ++x;
 DO(n, x->a=t=*y++; x->t=0; ++x; if(t==xnam||jt->dotnames&&t==xdot)jt->tmonad=0;);
 x->a=mark; x->t=0; ++x;
 x->a=mark; x->t=0; ++x;
 x->a=mark; x->t=0; ++x;
 x->a=mark; x->t=0; ++x;
 R z;
}    /* build string sentence into queue suitable for parsing */

static F1(jtcfn){I j; R !AR(w)&&INT&AT(w)&&(j=*AV(w),-9<=j&&j<=9)?FCONS(w):qq(w,ainf);}
     /* constant function with value w */

static F1(jttine){V*v; R w&&jt->tmonad&&(v=VAV(w),CP==v->f&&RT==v->h)?v->g:w;}
     /* if monad and w = [: g ], then g; else just w itself */

static I tvi(A w){A x;I i,z=-1;V*v;
 if(w&&VERB&AT(w)){
  v=VAV(w);
  if(CQQ==v->id&&num[-1]==v->g){
   x=v->f; 
   if(!AR(x)&&INT&AT(x)){i=*AV(x)-TC; z=0<=i&&i<NTTAB?i:-1;}
 }}
 R z;
}

static C ctab[]={CEQ,CMIN,CMAX,CPLUS,CPLUSDOT,CPLUSCO,CSTAR,CSTARDOT,CSTARCO,CMATCH,CNE,0};

static F1(jtswapc){C c;
 if(!primitive(w))R swap(w);
 c=ID(w);
 R strchr(ctab,c)?w:c==CLT?ds(CGT):c==CGT?ds(CLT):c==CLE?ds(CGE):c==CGE?ds(CLE):swap(w);
}    /* w~ or equivalent */

TACT(jtvmonad){A fs;TA y,z={one};V*v;
 y=stack[e]; fs=stack[b].a;
 if(!y.t)z.a=df1(y.a,fs);
 else{
  v=VAV(y.t);
  if(!(CFORK==v->id&&0<=tvi(v->h)))z.t=folk(CP,fs,tine(y.t));
  else if(NOUN&AT(v->f))           z.t=folk(CP,folk(CP,fs,folk(v->f,v->g,RT)),tine(v->h));
  else                             z.t=folk(tine(v->f),folk(CP,fs,v->g),tine(v->h));
 }
 R z;
}

static I jtdcase(J jt,I xi,V*v){
 R !v ? 0 : 0>xi ? 1 : CFORK!=v->id ? 2 : NOUN&AT(v->f) ? 3 : CP==v->f ? 4 : 5;
}    
/* 0   x        */
/* 1      f     */
/* 2         t  */
/* 3   x  f  t  */
/* 4   [: f  t  */
/* 5   s  f  t  */

TACT(jtvdyad){A fs,sf,xt,yt;B xl,xr,yl,yr;I xi=-1,yi=-1;TA x,y,z={one};V*u=0,*v=0;
 fs=stack[e-1].a; x=stack[b]; y=stack[e]; sf=swapc(fs);
 if(xt=tine(x.t)){xi=tvi(x.t); u=VAV(xt); if(0>xi&&CFORK==u->id){xi=tvi(u->f); if(0>xi)xi=tvi(u->h);}}
 if(yt=tine(y.t)){yi=tvi(y.t); v=VAV(yt); if(0>yi&&CFORK==v->id){yi=tvi(v->f); if(0>yi)yi=tvi(v->h);}}
 if(fs==ds(CLEFT)){if(xt)z.t=xt; else z.a=x.a; R z;}
 if(0>xi&&0>yi)switch((xt?2:0)+(yt?1:0)){
  case 0: z.a=df2(x.a,y.a,fs); break;
  case 1: z.t=folk(x.a,fs,yt); break;
  case 2: z.t=folk(y.a,sf,xt); break;
  case 3:
   xl=xt==LF; xr=xt==RT;
   yl=yt==LF; yr=yt==RT;
   if     (xl&&yr)                  z.t=fs;
   else if(xr&&(yl||yr&&jt->tmonad))z.t=sf;
   else z.t=CFORK==u->id&&primitive(yt)?folk(yt,sf,xt):folk(xt,fs,yt);
 }else{B b,c;I i,j,xj,yj;
  i=dcase(xi,u); if(u&&CFORK==u->id){xi=tvi(u->f); xj=tvi(u->h);}else{xi=-1; xj=tvi(xt);}
  j=dcase(yi,v); if(v&&CFORK==v->id){yi=tvi(v->f); yj=tvi(v->h);}else{yi=-1; yj=tvi(yt);}
  z.t=0; b=xj==yj; c=xj==yi;
  switch(DCASE(i,j)){
   case DCASE(0,2): z.t=folk(x.a,fs,yt); break;
   case DCASE(2,0): z.t=folk(y.a,sf,xt); break;
   case DCASE(0,3): z.t=folk(CP,folk(x.a,fs,FGR(v)),v->h); break;
   case DCASE(0,4): z.t=folk(CP,folk(x.a,fs,v->g  ),v->h); break;
   case DCASE(1,2): z.t=folk(xt,fs,yt); break;
   case DCASE(1,3): 
   case DCASE(1,4): z.t=folk(xt,folk(LF,fs,FGR(v)),v->h); break;
   case DCASE(2,1): z.t=folk(xt,fs,yt); break;
   case DCASE(3,1): z.t=folk(xt,fs,yt); break;
   case DCASE(4,1): z.t=folk(xt,fs,yt); break;
   case DCASE(2,2): z.t=folk(xt,fs,yt); break;
   case DCASE(2,3): z.t=b?folk(CP,folk(RT,    fs,FGR(v)),v->h):folk(xt,  folk(LF,    fs,FGR(v)),v->h); break;
   case DCASE(2,4): z.t=b?folk(CP,folk(RT,    fs,v->g  ),v->h):folk(xt,  folk(LF,    fs,FGR(v)),v->h); break;
   case DCASE(3,2): z.t=b?folk(CP,folk(FGR(u),fs,RT    ),yt  ):folk(u->h,folk(FGL(u),fs,RT    ),yt  ); break;
   case DCASE(3,3): z.t=b?folk(CP,folk(FGR(u),fs,FGR(v)),v->h):folk(u->h,folk(FGL(u),fs,FGR(v)),v->h); break;
   case DCASE(3,4): z.t=b?folk(CP,folk(FGR(u),fs,v->g  ),v->h):folk(u->h,folk(FGL(u),fs,FGR(v)),v->h); break;
   case DCASE(4,2): z.t=b?folk(CP,folk(u->g,  fs,RT    ),yt  ):folk(u->h,folk(FGL(u),fs,RT    ),yt  ); break;
   case DCASE(4,3): z.t=b?folk(CP,folk(u->g,  fs,FGR(v)),v->h):folk(u->h,folk(FGL(u),fs,FGR(v)),v->h); break;
   case DCASE(4,4): z.t=b?folk(CP,folk(u->g,  fs,v->g  ),v->h):folk(u->h,folk(FGL(u),fs,FGR(v)),v->h); break;
   case DCASE(0,5):         z.t=folk(v->f,folk(x.a,            fs,v->g),v->h); break; 
   case DCASE(2,5): if(b||c)z.t=folk(v->f,folk(b?RT:LF,        fs,v->g),v->h); break; 
   case DCASE(3,5):
   case DCASE(4,5): if(b||c)z.t=folk(v->f,folk(b?FGR(u):FGL(u),fs,v->g),v->h); break; 
   case DCASE(5,0):         z.t=folk(u->f,folk(y.a,            sf,u->g),u->h); break; 
   case DCASE(5,2): if(b||c)z.t=folk(u->f,folk(u->g,           fs,b?RT    :LF        ),yt  ); break; 
   case DCASE(5,3):
   case DCASE(5,4): if(b||c)z.t=folk(u->f,folk(u->g,           fs,b?FGR(v):FGL(v)    ),v->h); break; 
   case DCASE(5,5): if(xi==yi&&xj==yj||xi==yj&&xj==yi)
                     if(b||  v->g==swapc(v->g))z.t=folk(u->f,folk(u->g,fs,     v->g ),u->h);
                     else if(u->g==swapc(u->g))z.t=folk(v->f,folk(u->g,fs,     v->g ),v->h);
                     else                      z.t=folk(u->f,folk(u->g,fs,swap(v->g)),u->h);
  }
  RZZ(z.t);
 }
 R z;
}

TACT(jtvadv ){TA z={0}; if(CHK1)z.a=df1(stack[b].a,stack[e].a); R z;}

TACT(jtvconj){TA z={0}; if(CHK2)z.a=df2(stack[b].a,stack[e].a,stack[e-1].a); R z;}

TACT(jtvfolk){TA z={0}; if(CHK3)z.a=folk(stack[b].a,stack[1+b].a,stack[e].a); R z;}

TACT(jtvhook){TA z={0}; if(CHK2)z.a=hook(stack[b].a,stack[e].a); R z;}

TACT(jtvpunc){R stack[e-1];}

TACT(jtvis){A ea,et,n,t;I j;TA*u,z={0};
 n=stack[b].a;
 if(!(NAME&AT(n)&&CASGN==*CAV(stack[1+b].a)))R z;
 t=sfn(0,n); j=jt->ttabi; u=jt->ttab;
 if(!t||NTTAB==jt->ttabi)R z;
 DO(j, if(equ(t,u->a))R z; ++u;);
 ea=stack[e].a; et=stack[e].t;
 symbis(n,ea,jt->local);
 ++jt->ttabi; u->a=t; u->t=et?et:cfn(ea);
 z.a=ea;  z.t=jt->tsubst?qq(sc(TC+j),num[-1]):et;
 R z;
}

static TACT(jtvmove){A t;TA*u,x,z;
 x=stack[MAX(0,e)];
 if(!(NAME&AT(x.a))||ASGN&AT(stack[b].a))R x;
 z.a=nameref(x.a); z.t=0; t=sfn(0,x.a); u=jt->ttab;
 DO(jt->ttabi, if(equ(t,u->a)){z.t=jt->tsubst&&jt->ttabi0<=i?qq(sc(TC+i),num[-1]):u->t; break;} ++u;);
 R z;
}

/* final translator result                             */
/* modifies argument in place                          */
/* a. replaces 880i functions by jt->ttab[i].t entries */
/* b. replaces n0"_ v1 v2 by n0 v1 v2                  */
/* c. replaces [: g ] by g, if monad                   */

static F1(jtvfinal){I i;V*u,*v;
 RZ(w);
 if(!(VERB&AT(w)))R w;
 v=VAV(w);
 if(CFORK!=v->id){i=tvi(w); R 0<=i?vfinal(jt->ttab[i].t):w;}
 RZ(v->f=tine(vfinal(v->f)));
 RZ(v->g=tine(vfinal(v->g)));
 RZ(v->h=tine(vfinal(v->h)));
 if(VERB&AT(v->f)){
  u=VAV(v->f); 
  if(CFCONS==u->id)v->f=u->h;
  else if(CQQ==u->id&&NOUN&AT(u->f)&&equ(ainf,u->g))v->f=u->f;
  if(NOUN&AT(v->f))RZ(w=folk(v->f,v->g,v->h));
 }
 R tine(w);
}    

F1(jttparse){A*s,t,x;C d;I b,*c,e,i,j,k,m,n;TA*stack;
 RZ(w);
 stack=(TA*)AV(w); n=m=*AS(w)-4;
 do{
  for(i=0;i<NCASES;i++){
   c=cases[i].c; s=(A*)(n+stack); d=1;
   d=d&&*c++&AT(*s); s+=WTA;
   d=d&&*c++&AT(*s); s+=WTA;
   d=d&&*c++&AT(*s); s+=WTA;
   d=d&&*c++&AT(*s);
   if(d)break;
  }
  if(i<NCASES){
   b=cases[i].b; j=n+b;
   e=cases[i].e; k=n+e;
   stack[k]=(cases[i].vf)(jt,j,k,stack);
   RZ(stack[k].a);
   DO(b,stack[--k]=stack[--j];); n=k;
  } else {stack[n-1]=vmove(n,m-1,stack); RE(0); n-=0<m--;}
 } while(0<=m);
 x=stack[1+n].a; t=stack[1+n].t;
 ASSERT(NOUN&AT(x)&&MARK&AT(stack[2+n].a),EVSYNTAX);
 R t?vfinal(t):cfn(x);
}

F1(jtvtrans){PROLOG;A local,y,z=0;B tmonad,tsubst;I c,i;TA ttab[NTTAB],*ttab0;
 local=jt->local; tmonad=jt->tmonad; ttab0=jt->ttab; tsubst=jt->tsubst;
 RZ(ttab[0].a=cstr("x")); ttab[0].t=ds(CLEFT);
 RZ(ttab[1].a=cstr("y")); ttab[1].t=RT; c=2;
 if(jt->dotnames){
  RZ(ttab[2].a=spellout(CXDOT)); ttab[2].t=ds(CLEFT);
  RZ(ttab[3].a=spellout(CYDOT)); ttab[3].t=RT; c+=2;
 }
 for(i=0;!z&&2>i;++i){
  RZ(y=vtokens(w));
  jt->ttab=ttab; jt->ttabi=jt->ttabi0=c;
  RZ(jt->local=stcreate(2,1L,0L,0L));
  IS(ynam,one); if(!jt->tmonad)IS(xnam,one); 
  if(jt->dotnames){IS(ds(CYDOT),one); if(!jt->tmonad)IS(ds(CXDOT),one);}
  jt->tsubst=0==i;
  z=tparse(y); RESETERR;
  if(i&&!z)z=colon(num[4-jt->tmonad],w);
  symfreeh(jt->local,0L);
 }
 jt->local=local; jt->tmonad=tmonad; jt->ttab=ttab0; jt->tsubst=tsubst;
 EPILOG(z);
}