[BACK]Return to quote.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2018 / parse

File: [local] / OpenXM_contrib2 / asir2018 / parse / quote.c (download)

Revision 1.4, Thu Mar 11 09:20:49 2021 UTC (3 years ago) by noro
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +27 -11 lines

objtoquote() accepts a derivative of a pure function.

/* $OpenXM: OpenXM_contrib2/asir2018/parse/quote.c,v 1.4 2021/03/11 09:20:49 noro Exp $ */

#include "ca.h"
#include "parse.h"

void addquote(VL vl,QUOTE a,QUOTE b,QUOTE *c)
{
  FNODE fn;
  QUOTE t;

  objtoquote((Obj)a,&t); a = t; objtoquote((Obj)b,&t); b = t;
  fn = mkfnode(3,I_BOP,addfs,BDY(a),BDY(b));
  MKQUOTE(*c,fn);
}

void subquote(VL vl,QUOTE a,QUOTE b,QUOTE *c)
{
  FNODE fn;
  QUOTE t;

  objtoquote((Obj)a,&t); a = t; objtoquote((Obj)b,&t); b = t;
  fn = mkfnode(3,I_BOP,subfs,BDY(a),BDY(b));
  MKQUOTE(*c,fn);
}

void mulquote(VL vl,QUOTE a,QUOTE b,QUOTE *c)
{
  FNODE fn;
  QUOTE t;

  objtoquote((Obj)a,&t); a = t; objtoquote((Obj)b,&t); b = t;
  fn = mkfnode(3,I_BOP,mulfs,BDY(a),BDY(b));
  MKQUOTE(*c,fn);
}

void divquote(VL vl,QUOTE a,QUOTE b,QUOTE *c)
{
  FNODE fn;
  QUOTE t;

  objtoquote((Obj)a,&t); a = t; objtoquote((Obj)b,&t); b = t;
  fn = mkfnode(3,I_BOP,divfs,BDY(a),BDY(b));
  MKQUOTE(*c,fn);
}

void pwrquote(VL vl,QUOTE a,QUOTE b,QUOTE *c)
{
  FNODE fn;
  QUOTE t;

  objtoquote((Obj)a,&t); a = t; objtoquote((Obj)b,&t); b = t;
  fn = mkfnode(3,I_BOP,pwrfs,BDY(a),BDY(b));
  MKQUOTE(*c,fn);
}

void chsgnquote(QUOTE a,QUOTE *c)
{
  FNODE fn;
  QUOTE t;

  objtoquote((Obj)a,&t); a = t;
  fn = mkfnode(1,I_MINUS,BDY(a));
  MKQUOTE(*c,fn);
}

void objtoquote(Obj a,QUOTE *c)
{
  QUOTE nm,dn;
  NODE arg,t0,t,t1,t2,t3;
  FNODE fn;
  Obj obj;
  Obj *b;
  Obj **m;
  int i,j,len,row,col;
  Z q,qrow,qcol;
  FUNC f;

  if ( !a ) {
    MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)a));
    return;
  }
  switch ( OID(a) ) {
    case O_N:
      if ( negative_number((Num)a) ) {
        arf_chsgn(a,&obj);
        MKQUOTE(*c,mkfnode(1,I_MINUS,
          mkfnode(1,I_FORMULA,(pointer)obj)));
      } else {
        MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)a));
      }
      break;
    case O_STR:
      MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)a));
      break;
    case O_P:
      polytoquote((P)a,c);
      break;
    case O_R:
      polytoquote(NM((R)a),&nm);
      polytoquote(DN((R)a),&dn);
      divquote(CO,nm,dn,c);
      break;
    case O_LIST:
      t0 = 0;
      for ( arg = BDY((LIST)a); arg; arg = NEXT(arg) ) {
        NEXTNODE(t0,t);
        objtoquote(BDY(arg),&nm);
        BDY(t) = BDY(nm);
      }
      if ( t0 )
        NEXT(t) = 0;
      MKQUOTE(*c,mkfnode(1,I_LIST,t0));
      break;
    case O_VECT:
      len = ((VECT)a)->len;
      b = (Obj *)BDY(((VECT)a));
      t = 0;
      for ( i = len-1; i >= 0; i-- ) {
        objtoquote(b[i],&nm);
        MKNODE(t1,BDY(nm),t);
        t = t1;
      }
      STOZ(len,q); 
      t = mknode(2,mkfnode(1,I_FORMULA,q),mkfnode(1,I_LIST,t));
      gen_searchf("vector",&f);
      MKQUOTE(*c,mkfnode(2,I_FUNC,f,mkfnode(1,I_LIST,t)));
      break;
    case O_MAT:
      row = ((MAT)a)->row;
      col = ((MAT)a)->row;
      m = (Obj **)BDY(((MAT)a));
      t2 = 0;
      for ( i = row-1; i >= 0; i-- ) {
        t = 0;
        for ( j = col-1; j >= 0; j-- ) {
          objtoquote(m[i][j],&nm);
          MKNODE(t1,BDY(nm),t);
          t = t1;
        }
        fn = mkfnode(1,I_LIST,t);
        MKNODE(t3,fn,t2);
        t2 = t3;
      }
      fn = mkfnode(1,I_LIST,t2);

      STOZ(row,qrow); 
      STOZ(col,qcol); 
      t = mknode(3,
        mkfnode(1,I_FORMULA,qrow),mkfnode(1,I_FORMULA,qcol),fn);
      gen_searchf("matrix",&f);
      MKQUOTE(*c,mkfnode(2,I_FUNC,f,mkfnode(1,I_LIST,t)));
      break;
    case O_DP:
      dptoquote((DP)a,c);
      break;
    case O_QUOTE:
      *c = (QUOTE)a;
      break;
    default:
      error("objtoquote : not implemented");
  }
}

void polytoquote(P a,QUOTE *c)
{
  DCP dc,t;
  DCP *dca;
  int n,i,sgn;
  QUOTE v,r,s,u;

  if ( !a ) {
    MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)a));
    return;
  } else if ( OID(a) == O_N ) {
    MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)a));
    return;
  }
  vartoquote(VR((P)a),&v);
  dc = DC((P)a);
  dctoquote(dc,v,&r,&sgn);
  if ( sgn == -1 ) {
    MKQUOTE(u,mkfnode(1,I_MINUS,BDY(r)));
    r = u;
  }
  for (dc = NEXT(dc); dc; dc = NEXT(dc) ) {
    dctoquote(dc,v,&s,&sgn);
    if ( sgn == -1 )
      subquote(CO,r,s,&u);
    else
      addquote(CO,r,s,&u);
    r = u;
  }
  *c = r;
}

void dptoquote(DP a,QUOTE *c)
{
  MP t;
  MP m;
  int i,n,nv,sgn;
  QUOTE s,r,u;

  if ( !a ) {
    MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)a));
    return;
  }
  nv = NV(a);
  m = BDY(a);
  mptoquote(m,nv,&r,&sgn);
  if ( sgn == -1 ) {
    MKQUOTE(u,mkfnode(1,I_MINUS,BDY(r)));
    r = u;
  }
  for ( m = NEXT(m); m; m = NEXT(m) ) {
    mptoquote(m,nv,&s,&sgn);
    if ( sgn < 0 )
      subquote(CO,r,s,&u);
    else
      addquote(CO,r,s,&u);
    r = u;
  }
  *c = r;
}

void dctoquote(DCP dc,QUOTE v,QUOTE *q,int *sgn)
{
  QUOTE t,s,u,r;
  P c;
  Z d;

  if ( mmono(COEF(dc)) ) {
    /* -xyz... */
    chsgnp(COEF(dc),&c);
    *sgn = -1;
  } else {
    c = COEF(dc);
    *sgn = 1;
  }
  d = DEG(dc);
  if ( UNIQ(c) ) {
    if ( d ) {
      if ( UNIQ(d) )
        r = v;
      else {
        objtoquote((Obj)d,&t);
        pwrquote(CO,v,t,&r);
      }
    } else
      objtoquote((Obj)ONE,&r);  
  } else {
    objtoquote((Obj)c,&u);
    if ( !NUM(c) && NEXT(DC(c)) && d ) {
      MKQUOTE(t,mkfnode(1,I_PAREN,BDY(u)));
      u = t;
    }
    if ( d ) {
      if ( UNIQ(d) )
        s = v;
      else {
        objtoquote((Obj)d,&t);
        pwrquote(CO,v,t,&s);
      }
      mulquote(CO,u,s,&r);
    } else
      r = u;
  }
  *q = r;
}

void mptoquote(MP m,int n,QUOTE *r,int *sgn)
{
  QUOTE s,u;
  P c;
  NODE t,t1;
  FNODE f;
  Z q;
  DL dl;
  int i;

  if ( mmono((P)C(m)) ) {
    chsgnp((P)C(m),&c);
    *sgn = -1;
  } else {
    c = (P)C(m);
    *sgn = 1;
  }
  objtoquote((Obj)c,&s);
  if ( !NUM(c) && NEXT(DC(c)) ) {
    MKQUOTE(u,mkfnode(1,I_PAREN,BDY(s)));
    s = u;
  }
  dl = m->dl;
  for ( i = n-1, t = 0; i >= 0; i-- ) {
    STOZ(dl->d[i],q);
    f = mkfnode(1,I_FORMULA,q);
    MKNODE(t1,f,t);
    t = t1;
  }
  MKQUOTE(u,mkfnode(1,I_EV,t));
  if ( UNIQ(c) )
    *r = u;
  else
    mulquote(CO,s,u,r);
}

void vartoquote(V v,QUOTE *c)
{
  P x;
  PF pf;
  PFAD ad;
  QUOTE a,b,u;
  int i;
  FUNC f;
  Z z;
  FNODE fa,fd;
  NODE t,t1,s,s1;

  if ( NAME(v) ) {
    MKV(v,x);
    MKQUOTE(*c,mkfnode(1,I_FORMULA,(pointer)x));
  } else if ( (vid)v->attr == V_PF ) {
    /* pure function */
    pf = ((PFINS)v->priv)->pf;
    ad = ((PFINS)v->priv)->ad;
    if ( !strcmp(NAME(pf),"pow") ) {
      /* pow(a,b) = a^b */
      objtoquote(ad[0].arg,&a);
      x = (P)ad[0].arg;
      /* check whether x is a variable */
      if ( x && OID(x)==O_P && !NEXT(DC(x))
        && UNIQ(DEG(DC(x))) && UNIQ(COEF(DC(x))) ) {
        /* use a as is */
      } else {
        /* a => (a) */
        MKQUOTE(u,mkfnode(1,I_PAREN,BDY(a))); a = u;
      }
      objtoquote(ad[1].arg,&b);
      pwrquote(CO,a,b,c);
    } else {
      gen_searchf(NAME(pf),&f);
      for ( i = 0; i < pf->argc; i++ )
        if ( ad[i].d )
          break;
      if ( i < pf->argc ) {
        t = s = 0;
        for ( i = pf->argc-1; i >= 0; i-- ) {
          objtoquote(ad[i].arg,&a);
          MKNODE(t1,BDY(a),t);
          t = t1;
          STOZ(ad[i].d,z);
          objtoquote((Obj)z,&a);
          MKNODE(s1,BDY(a),s);
          s = s1;
        }
        fa = mkfnode(1,I_LIST,t);
        fd = mkfnode(1,I_LIST,s);
        MKQUOTE(*c,mkfnode(3,I_PFDERIV,f,fa,fd));
      } else {
        t = 0;
        for ( i = pf->argc-1; i >= 0; i-- ) {
          objtoquote(ad[i].arg,&a);
          MKNODE(t1,BDY(a),t);
          t = t1;
        }
        MKQUOTE(*c,mkfnode(2,I_FUNC,f,mkfnode(1,I_LIST,t)));
      }
    }
  }
}

/* 
 * A_arf : arithmetic function
 * A_int : machine integer
 * A_fnode : FNODE
 * A_node : NODE with FNODE bodies
 * A_internal : internal object
 * A_str : string
 * A_end : terminal
 * A_func : FUNC
 * A_notimpl : not implemented
 */

struct fid_spec fid_spec_tab[] = {
  {I_BOP,A_arf,A_fnode,A_fnode,A_end},
  {I_COP,A_int,A_fnode,A_fnode,A_end},
  {I_AND,A_fnode,A_fnode,A_end},
  {I_OR,A_fnode,A_fnode,A_end},
  {I_NOT,A_fnode,A_end},
  {I_CE,A_fnode,A_fnode,A_end},
  {I_PRESELF,A_arf,A_fnode,A_end},
  {I_POSTSELF,A_arf,A_fnode,A_end},
  {I_FUNC,A_func,A_fnode,A_end},
  {I_FUNC_OPT,A_func,A_fnode,A_fnode,A_end},
  {I_IFUNC,A_fnode,A_fnode,A_end},
  {I_MAP,A_func,A_fnode,A_end},
  {I_RECMAP,A_func,A_fnode,A_end},
  {I_PFDERIV,A_func,A_fnode,A_fnode,A_end},
  {I_ANS,A_int,A_end},
  {I_PVAR,A_int,A_node,A_end},
  {I_ASSPVAR,A_fnode,A_fnode,A_end},
  {I_FORMULA,A_internal,A_end},
  {I_LIST,A_node,A_end},
  {I_STR,A_str,A_end},
  {I_NEWCOMP,A_int,A_end},
  {I_CAR,A_fnode,A_end},
  {I_CDR,A_fnode,A_end},
  {I_CAST,A_notimpl,A_end},
  {I_INDEX,A_fnode,A_node,A_end},
  {I_EV,A_node,A_end},
  {I_TIMER,A_fnode,A_fnode,A_fnode,A_end},
  {I_GF2NGEN,A_end},
  {I_GFPNGEN,A_end},
  {I_GFSNGEN,A_end},
  {I_LOP,A_int,A_fnode,A_fnode,A_end},
  {I_OPT,A_str,A_fnode,A_end},
  {I_GETOPT,A_str,A_end},
  {I_POINT,A_fnode,A_str,A_end},
  {I_PAREN,A_fnode,A_end},
  {I_MINUS,A_fnode,A_end},
  {I_NARYOP,A_arf,A_node,A_end},
  {I_CONS,A_node,A_fnode,A_end},
  {I_FUNC_QARG,A_func,A_fnode,A_end},
  {I_FUNC_HEAD,A_func,A_end},
};

#define N_FID_SPEC (sizeof(fid_spec_tab)/sizeof(struct fid_spec))

void get_fid_spec(fid id,fid_spec_p *spec)
{
  int i;

  for ( i = 0; i < N_FID_SPEC; i++ )
    if ( fid_spec_tab[i].id == id ) {
      *spec = &fid_spec_tab[i];
      return;
    }
  *spec = 0;
}

FNODE strip_paren(FNODE f)
{
  if ( !f || f->id != I_PAREN ) return f;
  else {
    return strip_paren((FNODE)FA0(f));
  }
}

NODE flatten_fnodenode(NODE n,char *opname);
FNODE flatten_fnode(FNODE f,char *opname);

NODE flatten_fnodenode(NODE n,char *opname)
{
  NODE r0,r,t;

  r0 = 0;
  for ( t = n; t; t = NEXT(t) ) {
    NEXTNODE(r0,r);
    BDY(r) = (pointer)flatten_fnode((FNODE)BDY(t),opname);
  }
  if ( r0 ) NEXT(r) = 0;
  return r0;
}

FNODE flatten_fnode(FNODE f,char *opname)
{
  fid_spec_p spec;
  farg_type *type;
  fid id;
  FNODE f1,f2,r;
  int i;

  if ( !f ) return f;
  id = f->id;
  get_fid_spec(id,&spec);
  /* unknown fid */
  if ( !spec ) return f;
  if ( id == I_BOP && !strcmp(((ARF)FA0(f))->name,opname) ) {
    f1 = (pointer)flatten_fnode(FA1(f),opname);
    f1 = strip_paren(f1);
    f2 = (pointer)flatten_fnode(FA2(f),opname);
    f2 = strip_paren(f2);
    if ( f1->id == I_BOP && !strcmp(((ARF)FA0(f1))->name,opname) ) {
      /* [op [op A B] C] => [op A [op B C]] */
      f2 = flatten_fnode(mkfnode(3,I_BOP,(ARF)FA0(f),FA2(f1),f2),opname);
      return mkfnode(3,I_BOP,(ARF)FA0(f),FA1(f1),f2);
    } else
      return mkfnode(3,I_BOP,(ARF)FA0(f),f1,f2);
  } else {
    type = spec->type;
    for ( i = 0; type[i] != A_end; i++ );
    NEWFNODE(r,i); ID(r) = f->id;
    for ( i = 0; type[i] != A_end; i++ ) {
      if ( type[i] == A_fnode )
        r->arg[i] = (pointer)flatten_fnode(f->arg[i],opname);
      else if ( type[i] == A_node )
        r->arg[i] = (pointer)flatten_fnodenode(f->arg[i],opname);
      else
        r->arg[i] = f->arg[i];
    }
    return r;
  }
}

/* comparison of QUOTE */

int compquote(VL vl,QUOTE q1,QUOTE q2)
{
  return compfnode(BDY(q1),BDY(q2));
}

/* comparison of QUOTEARG */
/* XXX : executes a non-sense comparison for bodies */

int compqa(VL vl,QUOTEARG q1,QUOTEARG q2)
{
  if ( !q1 ) return q2?-1:0;
  else if ( !q2 ) return 1;
  else if ( OID(q1) > OID(q2) ) return 1;
  else if ( OID(q1) < OID(q2) ) return -1;
  else if ( q1->type > q2->type ) return 1;
  else if ( q1->type < q2->type ) return -1;
  else switch ( q1->type ) {
    case A_func:
      return strcmp(((FUNC)q1->body)->name,((FUNC)q2->body)->name);    
    case A_arf:
      return strcmp(((ARF)q1->body)->name,((ARF)q2->body)->name);    
    default:
      if ( (unsigned long)q1->body  > (unsigned long)q2->body ) return 1;
      else if ( (unsigned long)q1->body  < (unsigned long)q2->body ) return -1;
      else return 0;
  }
}

int compfnode(FNODE f1,FNODE f2)
{
  fid_spec_p spec;
  int t,s1,s2,i;
  NODE n1,n2;

  if ( !f1 ) return f2 ? -1 : 1;
  else if ( !f2 ) return 1;
    else if ( f1->id > f2->id ) return 1;
  else if ( f1->id < f2->id ) return -1;
  spec = fid_spec_tab+f1->id;
  for ( i = 0; spec->type[i] != A_end; i++ ) {
    switch ( spec->type[i] ) {
      case A_fnode:
        t = compfnode((FNODE)f1->arg[i],(FNODE)f2->arg[i]);
        if ( t ) return t;
        break;
      case A_int:
        s1 = (long)f1->arg[i];
        s2 = (long)f2->arg[i];
        if ( s1 > s2 ) return 1;
        else if ( s1 < s2 ) return -1;
        break;
      case A_str:
        t = strcmp((char *)f1->arg[i],(char *)f2->arg[i]);
        if ( t ) return t;
        break;
      case A_internal:
        t = arf_comp(CO,(Obj)f1->arg[i],(Obj)f2->arg[i]);
        if ( t ) return t;
        break;
      case A_node:
        n1 = (NODE)f1->arg[i];
        n2 = (NODE)f2->arg[i];
        for ( ; n1 && n2; n1 = NEXT(n1), n2 = NEXT(n2) ) {
          t = compfnode(BDY(n1),BDY(n2));
          if ( t ) return t;
        }
        if ( n1 ) return 1;
        else if ( n2 ) return -1;
        break;
      case A_arf:
         t = strcmp(((ARF)f1->arg[i])->name,((ARF)f2->arg[i])->name);
        if ( t ) return t;
        break;
      case A_func:
         t = strcmp(((FUNC)f1->arg[i])->name,((FUNC)f2->arg[i])->name);
        if ( t ) return t;
        break;
      case A_notimpl:
      default:
        error("compfnode : not implemented");
        break;
    }
  }
  return 0;
}