source: git/Singular/newstruct.cc @ 916586

spielwiese
Last change on this file since 916586 was a04a05, checked in by Alexander Dreyer <alexander.dreyer@…>, 12 years ago
chg: encapsulating newstruct's overloaded '=' and use in pyobject
  • Property mode set to 100644
File size: 17.3 KB
Line 
1#include <ctype.h>
2
3#include "config.h"
4#include <kernel/mod2.h>
5#include <Singular/ipid.h>
6#include <Singular/blackbox.h>
7#include <Singular/lists.h>
8#include <Singular/ipid.h>
9#include <Singular/ipshell.h>
10#include <Singular/newstruct.h>
11
12struct newstruct_member_s;
13typedef struct newstruct_member_s *newstruct_member;
14struct  newstruct_member_s
15{
16  newstruct_member next;
17  char *         name;
18  int            typ;
19  int            pos;
20};
21
22struct newstruct_proc_s;
23typedef struct newstruct_proc_a *newstruct_proc;
24struct  newstruct_proc_a
25{
26  newstruct_proc next;
27  int            t; /*tok id */
28  int            args; /* number of args */
29  procinfov      p;
30};
31
32struct newstruct_desc_s
33{
34  newstruct_member member;
35  newstruct_desc   parent;
36  newstruct_proc   procs;
37  int            size; // number of mebers +1
38  int            id;   // the type id assigned to this bb
39};
40
41int newstruct_desc_size() 
42{
43  return sizeof(newstruct_desc_s);
44}
45
46char * newstruct_String(blackbox *b, void *d)
47{
48  if (d==NULL) return omStrDup("oo");
49  else
50  {
51    newstruct_desc ad=(newstruct_desc)(b->data);
52    lists l=(lists)d;
53    newstruct_member a=ad->member;
54    StringSetS("");
55    loop
56    {
57      StringAppendS(a->name);
58      char *tmp=omStrDup(StringAppendS("="));
59      if ((!RingDependend(a->typ))
60      || ((l->m[a->pos-1].data==(void *)currRing)
61         && (currRing!=NULL)))
62      {
63        if (l->m[a->pos].rtyp==LIST_CMD)
64        {
65          StringAppendS("<list>");
66        }
67        else
68        {
69          StringSetS("");
70          char *tmp2=omStrDup(l->m[a->pos].String());
71          StringSetS(tmp);
72          if ((strlen(tmp2)>80)||(strchr(tmp2,'\n')!=NULL))
73          {
74            StringAppend("<%s>",Tok2Cmdname(l->m[a->pos].rtyp));
75          }
76          else StringAppendS(tmp2);
77          omFree(tmp2);
78        }
79      }
80      else StringAppendS("??");
81      omFree(tmp);
82      if (a->next==NULL) break;
83      StringAppendS("\n");
84      if(errorreported) break;
85      a=a->next;
86    }
87    return omStrDup(StringAppendS(""));
88  }
89}
90lists lCopy_newstruct(lists L)
91{
92  lists N=(lists)omAlloc0Bin(slists_bin);
93  int n=L->nr;
94  ring save_ring=currRing;
95  N->Init(n+1);
96  for(;n>=0;n--)
97  {
98    if (RingDependend(L->m[n].rtyp))
99    {
100      assume((L->m[n-1].rtyp==RING_CMD) || (L->m[n-1].data==NULL));
101      if(L->m[n-1].data!=NULL)
102      {
103        if (L->m[n-1].data!=(void*)currRing)
104          rChangeCurrRing((ring)(L->m[n-1].data));
105        N->m[n].Copy(&L->m[n]);
106      }
107      else
108      {
109        N->m[n].rtyp=L->m[n].rtyp;
110        N->m[n].data=idrecDataInit(L->m[n].rtyp);
111      }
112    }
113    else if(L->m[n].rtyp==LIST_CMD)
114    {
115      N->m[n].rtyp=L->m[n].rtyp;
116      N->m[n].data=(void *)lCopy((lists)(L->m[n].data));
117    }
118    else if(L->m[n].rtyp>MAX_TOK)
119    {
120      N->m[n].rtyp=L->m[n].rtyp;
121      blackbox *b=getBlackboxStuff(N->m[n].rtyp);
122      N->m[n].data=(void *)b->blackbox_Copy(b,L->m[n].data);
123    }
124    else
125      N->m[n].Copy(&L->m[n]);
126  }
127  if (currRing!=save_ring) rChangeCurrRing(save_ring);
128  return N;
129}
130void * newstruct_Copy(blackbox*, void *d)
131{
132  lists n1=(lists)d;
133  return (void*)lCopy_newstruct(n1);
134}
135
136// Used by newstruct_Assign for overloaded '='
137BOOLEAN newstruct_equal(int op, leftv l, leftv r)
138{
139  blackbox *ll=getBlackboxStuff(op);
140  assume(ll->data != NULL);
141  newstruct_desc nt=(newstruct_desc)ll->data;
142  newstruct_proc p=nt->procs;
143 
144  while( (p!=NULL) && ((p->t!='=')||(p->args!=1)) ) p=p->next;
145
146  if (p!=NULL)
147  {
148    idrec hh;
149    memset(&hh,0,sizeof(hh));
150    hh.id=Tok2Cmdname(p->t);
151    hh.typ=PROC_CMD;
152    hh.data.pinf=p->p;
153    sleftv tmp;
154    memset(&tmp,0,sizeof(sleftv));
155    tmp.Copy(r);
156    leftv sl = iiMake_proc(&hh, NULL, &tmp);
157    if (sl != NULL)
158    {
159      if (sl->Typ() == op) { l->Copy(sl); return FALSE;}
160      else sl->CleanUp();
161    }
162  }
163  return TRUE;
164}
165
166BOOLEAN newstruct_Assign(leftv l, leftv r)
167{
168  if (r->Typ()>MAX_TOK)
169  {
170    blackbox *rr=getBlackboxStuff(r->Typ());
171    if (l->Typ()!=r->Typ())
172    {
173      newstruct_desc rrn=(newstruct_desc)rr->data;
174
175      if (!rrn)
176      {
177        Werror("custom type %s(%d) cannot be assigned to newstruct %s(%d)",
178               Tok2Cmdname(r->Typ()), r->Typ(), Tok2Cmdname(l->Typ()), l->Typ());
179        return TRUE;
180      }
181
182      newstruct_desc rrp=rrn->parent;
183      while ((rrp!=NULL)&&(rrp->id!=l->Typ())) rrp=rrp->parent;
184      if (rrp!=NULL)
185      {
186        if (l->rtyp==IDHDL)
187        {
188          IDTYP((idhdl)l->data)=r->Typ();
189        }
190        else
191        {
192          l->rtyp=r->Typ();
193        }
194      }
195      else                      // unrelated types - look for custom conversion
196      {
197        sleftv tmp;
198        BOOLEAN newstruct_Op1(int, leftv, leftv);  // forward declaration
199        if (! newstruct_Op1(l->Typ(), &tmp, r))  return newstruct_Assign(l, &tmp);
200      }
201    }
202    if (l->Typ()==r->Typ())
203    {
204      if (l->Data()!=NULL)
205      {
206        lists n1=(lists)l->Data();
207        n1->Clean(); n1=NULL;
208      }
209      lists n2=(lists)r->Data();
210      n2=lCopy_newstruct(n2);
211      if (l->rtyp==IDHDL)
212      {
213        IDDATA((idhdl)l->data)=(char *)n2;
214      }
215      else
216      {
217        l->data=(void *)n2;
218      }
219      return FALSE;
220    }
221  }
222
223  else if(l->Typ() > MAX_TOK)
224  {
225    assume(l->Typ() > MAX_TOK);
226    sleftv tmp;
227    if(!newstruct_equal(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp);
228  }
229  Werror("assign %s(%d) = %s(%d)",
230        Tok2Cmdname(l->Typ()),l->Typ(),Tok2Cmdname(r->Typ()),r->Typ());
231  return TRUE;
232}
233
234BOOLEAN newstruct_Op1(int op, leftv res, leftv arg)
235{
236  // interpreter: arg is newstruct
237  blackbox *a=getBlackboxStuff(arg->Typ());
238  newstruct_desc nt=(newstruct_desc)a->data;
239  newstruct_proc p=nt->procs;
240
241  while((p!=NULL) &&( (p->t!=op) || (p->args!=1) )) p=p->next;
242
243  if (p!=NULL)
244  {
245    leftv sl;
246    sleftv tmp;
247    memset(&tmp,0,sizeof(sleftv));
248    tmp.Copy(arg);
249    idrec hh;
250    memset(&hh,0,sizeof(hh));
251    hh.id=Tok2Cmdname(p->t);
252    hh.typ=PROC_CMD;
253    hh.data.pinf=p->p;
254    sl=iiMake_proc(&hh,NULL,&tmp);
255    if (sl==NULL) return TRUE;
256    else
257    {
258      res->Copy(sl);
259      return FALSE;
260    }
261  }
262  return blackboxDefaultOp1(op,res,arg);
263}
264
265
266
267BOOLEAN newstruct_Op2(int op, leftv res, leftv a1, leftv a2)
268{
269  // interpreter: a1 or a2 is newstruct
270  blackbox *a=getBlackboxStuff(a1->Typ());
271  newstruct_desc nt;
272  lists al=(lists)a1->Data();
273  if (a!=NULL)
274  {
275    nt=(newstruct_desc)a->data;
276    switch(op)
277    {
278      case '.':
279      {
280        if (a2->name!=NULL)
281        {
282          BOOLEAN search_ring=FALSE;
283          newstruct_member nm=nt->member;
284          while ((nm!=NULL)&&(strcmp(nm->name,a2->name)!=0)) nm=nm->next;
285          if ((nm==NULL) && (strncmp(a2->name,"r_",2)==0))
286          {
287            nm=nt->member;
288            while ((nm!=NULL)&&(strcmp(nm->name,a2->name+2)!=0)) nm=nm->next;
289            if ((nm!=NULL)&&(RingDependend(nm->typ)))
290              search_ring=TRUE;
291            else
292              nm=NULL;
293          }
294          if (nm==NULL)
295          {
296            Werror("member %s nor found", a2->name);
297            return TRUE;
298          }
299          if (search_ring)
300          {
301            ring r;
302            res->rtyp=RING_CMD;
303            res->data=al->m[nm->pos-1].data;
304            r=(ring)res->data;
305            if (r==NULL) { res->data=(void *)currRing; r=currRing; }
306            if (r!=NULL) r->ref++;
307            else Werror("ring of this member is not set and no basering found");
308            return r==NULL;
309          }
310          else if (RingDependend(nm->typ))
311          {
312            if (al->m[nm->pos].data==NULL)
313            {
314              // NULL belongs to any ring
315              ring r=(ring)al->m[nm->pos-1].data;
316              if (r!=NULL)
317              {
318                r->ref--;
319                al->m[nm->pos-1].data=NULL;
320                al->m[nm->pos-1].rtyp=DEF_CMD;
321              }
322            }
323            else
324            {
325              //Print("checking ring at pos %d for dat at pos %d\n",nm->pos-1,nm->pos);
326              if ((al->m[nm->pos-1].data!=(void *)currRing)
327              &&(al->m[nm->pos-1].data!=(void*)0L))
328              {
329                Werror("different ring %lx(data) - %lx(basering)",
330                  (long unsigned)(al->m[nm->pos-1].data),(long unsigned)currRing);
331                return TRUE;
332              }
333            }
334            if ((currRing!=NULL)&&(al->m[nm->pos-1].data==NULL))
335            {
336              // remember the ring, if not already set
337              al->m[nm->pos-1].data=(void *)currRing;
338              al->m[nm->pos-1].rtyp=RING_CMD;
339              currRing->ref++;
340            }
341          }
342          Subexpr r=(Subexpr)omAlloc0Bin(sSubexpr_bin);
343          r->start = nm->pos+1;
344          memcpy(res,a1,sizeof(sleftv));
345          memset(a1,0,sizeof(sleftv));
346          if (res->e==NULL) res->e=r;
347          else
348          {
349            Subexpr sh=res->e;
350            while (sh->next != NULL) sh=sh->next;
351            sh->next=r;
352          }
353          return FALSE;
354        }
355        else
356        {
357          WerrorS("name expected");
358          return TRUE;
359        }
360      }
361    }
362  }
363  else
364  {
365    a=getBlackboxStuff(a2->Typ());
366    nt=(newstruct_desc)a->data;
367    al=(lists)a2->Data();
368  }
369  newstruct_proc p=nt->procs;
370  while((p!=NULL) && ( (p->t!=op) || (p->args!=2) )) p=p->next;
371  if (p!=NULL)
372  {
373    leftv sl;
374    sleftv tmp;
375    memset(&tmp,0,sizeof(sleftv));
376    tmp.Copy(a1);
377    tmp.next=(leftv)omAlloc0(sizeof(sleftv));
378    tmp.next->Copy(a2);
379    idrec hh;
380    memset(&hh,0,sizeof(hh));
381    hh.id=Tok2Cmdname(p->t);
382    hh.typ=PROC_CMD;
383    hh.data.pinf=p->p;
384    sl=iiMake_proc(&hh,NULL,&tmp);
385    if (sl==NULL) return TRUE;
386    else
387    {
388      res->Copy(sl);
389      return FALSE;
390    }
391  }
392  return blackboxDefaultOp2(op,res,a1,a2);
393}
394
395// BOOLEAN opM(int op, leftv res, leftv args)
396BOOLEAN newstruct_OpM(int op, leftv res, leftv args)
397{
398  // interpreter: args->1. arg is newstruct
399  blackbox *a=getBlackboxStuff(args->Typ());
400  newstruct_desc nt=(newstruct_desc)a->data;
401  switch(op)
402  {
403    case STRING_CMD:
404    {
405      res->data=(void *)a->blackbox_String(a,args->Data());
406      res->rtyp=STRING_CMD;
407      return FALSE;
408    }
409    default:
410      break;
411  }
412  newstruct_proc p=nt->procs;
413 
414  while((p!=NULL) &&( (p->t!=op) || (p->args!=4) )) p=p->next;
415
416  if (p!=NULL)
417  {
418    leftv sl;
419    sleftv tmp;
420    memset(&tmp,0,sizeof(sleftv));
421    tmp.Copy(args);
422    idrec hh;
423    memset(&hh,0,sizeof(hh));
424    hh.id=Tok2Cmdname(p->t);
425    hh.typ=PROC_CMD;
426    hh.data.pinf=p->p;
427    sl=iiMake_proc(&hh,NULL,&tmp);
428    if (sl==NULL) return TRUE;
429    else
430    {
431      res->Copy(sl);
432      return FALSE;
433    }
434  }
435  return blackbox_default_OpM(op,res,args);
436}
437
438void lClean_newstruct(lists l)
439{
440  if (l->nr>=0)
441  {
442    int i;
443    ring r=NULL;
444    for(i=l->nr;i>=0;i--)
445    {
446      if ((i>0) && (l->m[i-1].rtyp==RING_CMD))
447        r=(ring)(l->m[i-1].data);
448      else
449        r=NULL;
450      l->m[i].CleanUp(r);
451    }
452    omFreeSize((ADDRESS)l->m, (l->nr+1)*sizeof(sleftv));
453    l->nr=-1;
454  }
455  omFreeBin((ADDRESS)l,slists_bin);
456}
457
458void newstruct_destroy(blackbox *b, void *d)
459{
460  if (d!=NULL)
461  {
462    lists n=(lists)d;
463    lClean_newstruct(n);
464  }
465}
466
467void *newstruct_Init(blackbox *b)
468{
469  newstruct_desc n=(newstruct_desc)b->data;
470  lists l=(lists)omAlloc0Bin(slists_bin);
471  l->Init(n->size);
472  newstruct_member nm=n->member;
473  while (nm!=NULL)
474  {
475    l->m[nm->pos].rtyp=nm->typ;
476    l->m[nm->pos].data=idrecDataInit(nm->typ);
477    nm=nm->next;
478  }
479  return l;
480}
481
482BOOLEAN newstruct_Check(blackbox *b, void *d)
483{
484  newstruct_desc n=(newstruct_desc)b->data;
485  lists l=(lists)d;
486  newstruct_member nm=n->member;
487  while (nm!=NULL)
488  {
489    if ((l->m[nm->pos].rtyp!=nm->typ)
490    &&( nm->typ!=DEF_CMD))
491    {
492      Werror("type change in member %s (%s(%d) -> %s(%d))",nm->name,
493          Tok2Cmdname(nm->typ),nm->typ,
494          Tok2Cmdname(l->m[nm->pos].rtyp),l->m[nm->pos].rtyp);
495      return TRUE;
496    }
497    nm=nm->next;
498  }
499  return FALSE;
500}
501
502BOOLEAN newstruct_serialize(blackbox *b, void *d, si_link f)
503{
504  newstruct_desc dd=(newstruct_desc)b->data;
505  sleftv l;
506  memset(&l,0,sizeof(l));
507  l.rtyp=STRING_CMD;
508  l.data=(void*)getBlackboxName(dd->id);
509  f->m->Write(f, &l);
510  lists ll=(lists)d;
511  memset(&l,0,sizeof(l));
512  l.rtyp=LIST_CMD;
513  l.data=ll;
514  f->m->Write(f, &l);
515  return FALSE;
516}
517
518BOOLEAN newstruct_deserialize(blackbox **b, void **d, si_link f)
519{
520  // newstruct is serialiazed as a list,
521  // just read a list and take data,
522  // rtyp must be set correctly (to the blackbox id) by routine calling
523  // newstruct_deserialize
524  leftv l=f->m->Read(f);
525  //newstruct_desc n=(newstruct_desc)b->data;
526  //TODO: check compatibility of list l->data with description in n
527  *d=l->data;
528  return FALSE;
529}
530
531void newstruct_Print(blackbox *b,void *d)
532{
533  newstruct_desc dd=(newstruct_desc)b->data;
534  newstruct_proc p=dd->procs;
535  while((p!=NULL)&&(p->t!=PRINT_CMD))
536    p=p->next;
537  if (p!=NULL)
538  {
539    leftv sl;
540    sleftv tmp;
541    memset(&tmp,0,sizeof(tmp));
542    tmp.rtyp=dd->id;
543    tmp.data=(void*)newstruct_Copy(b,d);
544    idrec hh;
545    memset(&hh,0,sizeof(hh));
546    hh.id=Tok2Cmdname(p->t);
547    hh.typ=PROC_CMD;
548    hh.data.pinf=p->p;
549    sl=iiMake_proc(&hh,NULL,&tmp);
550  }
551  else
552    blackbox_default_Print(b,d);
553}
554void newstruct_setup(const char *n, newstruct_desc d )
555{
556  blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox));
557  // all undefined entries will be set to default in setBlackboxStuff
558  // the default Print is quite useful,
559  // all other are simply error messages
560  b->blackbox_destroy=newstruct_destroy;
561  b->blackbox_String=newstruct_String;
562  b->blackbox_Print=newstruct_Print;//blackbox_default_Print;
563  b->blackbox_Init=newstruct_Init;
564  b->blackbox_Copy=newstruct_Copy;
565  b->blackbox_Assign=newstruct_Assign;
566  b->blackbox_Op1=newstruct_Op1;
567  b->blackbox_Op2=newstruct_Op2;
568  //b->blackbox_Op3=blackbox_default_Op3;
569  b->blackbox_OpM=newstruct_OpM;
570  b->blackbox_Check=newstruct_Check;
571  b->blackbox_serialize=newstruct_serialize;
572  b->blackbox_deserialize=newstruct_deserialize;
573  b->data=d;
574  b->properties=1; // list_like
575  int rt=setBlackboxStuff(b,n);
576  d->id=rt;
577  //Print("create type %d (%s)\n",rt,n);
578}
579
580static newstruct_desc scanNewstructFromString(const char *s, newstruct_desc res)
581{
582  char *ss=omStrDup(s);
583  char *p=ss;
584  char *start;
585  int t;
586  char c;
587  newstruct_member elem;
588
589  idhdl save_ring=currRingHdl;
590  currRingHdl=(idhdl)1; // fake ring detection
591  loop
592  {
593    // read type:
594    while (*p==' ') p++;
595    start=p;
596    while (isalpha(*p)) p++;
597    *p='\0';
598    IsCmd(start,t);
599    if (t==0)
600    {
601      Werror("unknown type `%s`",start);
602      omFree(ss);
603      omFree(res);
604      currRingHdl=save_ring;
605      return NULL;
606    }
607    if (RingDependend(t))
608      res->size++;    // one additional field for the ring (before the data)
609    //Print("found type %s at real-pos %d",start,res->size);
610    elem=(newstruct_member)omAlloc0(sizeof(*elem));
611    // read name:
612    p++;
613    while (*p==' ') p++;
614    start=p;
615    while (isalpha(*p)) p++;
616    c=*p;
617    *p='\0';
618    elem->typ=t;
619    elem->pos=res->size;
620    if (*start=='\0') /*empty name*/
621    {
622      WerrorS("empty name for element");
623      goto error_in_newstruct_def;
624    }
625    elem->name=omStrDup(start);
626    //Print(" name:%s\n",start);
627    elem->next=res->member;
628    res->member=elem;
629    res->size++;
630
631    // next ?
632    *p=c;
633    while (*p==' ') p++;
634    if (*p!=',')
635    {
636      if (*p!='\0')
637      {
638        Werror("unknown character in newstruct:>>%s<<",p);
639        goto error_in_newstruct_def;
640      }
641      break; // end-of-list
642    }
643    p++;
644  }
645  omFree(ss);
646  currRingHdl=save_ring;
647  //Print("new type with %d elements\n",res->size);
648  return res;
649error_in_newstruct_def:
650   omFree(elem);
651   omFree(ss);
652   omFree(res);
653   currRingHdl=save_ring;
654   return NULL;
655}
656newstruct_desc newstructFromString(const char *s)
657{
658  newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res));
659  res->size=0;
660
661  return scanNewstructFromString(s,res);
662}
663newstruct_desc newstructChildFromString(const char *parent, const char *s)
664{
665  // find parent:
666  int parent_id=0;
667  blackboxIsCmd(parent,parent_id);
668  if (parent_id<MAX_TOK)
669  {
670    Werror(">>%s< not found",parent);
671    return NULL;
672  }
673  blackbox *parent_bb=getBlackboxStuff(parent_id);
674  // check for the correct type:
675  if (parent_bb->blackbox_destroy!=newstruct_destroy)
676  {
677    Werror(">>%s< is not a user defined type",parent);
678    return NULL;
679  }
680  // setup for scanNewstructFromString:
681  newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res));
682  newstruct_desc parent_desc=(newstruct_desc)parent_bb->data;
683  res->size=parent_desc->size;
684  res->member=parent_desc->member;
685  res->parent=parent_desc;
686
687  return scanNewstructFromString(s,res);
688}
689void newstructShow(newstruct_desc d)
690{
691  newstruct_member elem;
692  Print("id: %d\n",d->id);
693  elem=d->member;
694  while (elem!=NULL)
695  {
696    Print(">>%s<< at pos %d, type %d\n",elem->name,elem->pos,elem->typ);
697    elem=elem->next;
698  }
699}
700
701BOOLEAN newstruct_set_proc(const char *bbname,const char *func, int args,procinfov pr)
702{
703  int id=0;
704  blackboxIsCmd(bbname,id);
705  blackbox *bb=getBlackboxStuff(id);
706  newstruct_desc desc=(newstruct_desc)bb->data;
707  newstruct_proc p=(newstruct_proc)omAlloc(sizeof(*p));
708  p->next=desc->procs; desc->procs=p;
709
710  idhdl save_ring=currRingHdl;
711  currRingHdl=(idhdl)1; // fake ring detection
712
713  if(!IsCmd(func,p->t))
714  {
715    int t=0;
716    if (func[1]=='\0') p->t=func[0];
717    else if((t=iiOpsTwoChar(func))!=0)
718    {
719      p->t=t;
720    }
721    else
722    {
723      Werror(">>%s<< is not a kernel command",func);
724      currRingHdl = save_ring;
725      return TRUE;
726    }
727  }
728  p->args=args;
729  p->p=pr; pr->ref++;
730  currRingHdl = save_ring;
731  return FALSE;
732}
Note: See TracBrowser for help on using the repository browser.