cb22561995-10-11Fredrik Hübinette (Hubbe) /*\ ||| This file a part of uLPC, and is copyright by Fredrik Hubinette ||| uLPC is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. \*/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h" #include "types.h" #include "mapping.h" #include "svalue.h" #include "array.h" #include "macros.h" #include "language.h" #include "error.h" #include "memory.h" #include "dynamic_buffer.h" #include "interpret.h"
c94c371996-03-28Fredrik Hübinette (Hubbe) #include "gc.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *first_mapping; /* * This function puts looks up an index in a mapping and assigns * the value to dest. It does not free dest first though */ void mapping_index_no_free(struct svalue *dest, struct mapping *m, struct svalue *ind) { INT32 i; i=set_lookup(m->ind, ind); if(i < 0) { dest->type=T_INT; dest->subtype=NUMBER_UNDEFINED; dest->u.integer=0; }else{ array_index_no_free(dest, m->val, i); } } #if 0 /* * This funciton does the same thing as the one above, but * frees dest first. */ void mapping_index(struct svalue *dest, struct mapping *m, struct svalue *ind) { INT32 i; m->refs++; i=set_lookup(m->ind, ind); if(i < 0) { dest->type=T_INT; dest->subtype=NUMBER_UNDEFINED; dest->u.integer=0; }else{ array_index(dest, m->val, i); } free_mapping(m); } #endif /* * allocate and init a new mapping */ static struct mapping *allocate_mapping(struct array *ind, struct array *val) { struct mapping *m;
c94c371996-03-28Fredrik Hübinette (Hubbe)  GC_ALLOC();
5267b71995-08-09Fredrik Hübinette (Hubbe)  m=ALLOC_STRUCT(mapping); m->next = first_mapping; m->prev = 0; m->refs = 1; m->ind=ind; m->val=val; if(first_mapping) first_mapping->prev = m; first_mapping=m; return m; } /* * free a mapping */ void really_free_mapping(struct mapping *m) { #ifdef DEBUG if(m->refs) fatal("really free mapping on mapping with nonzero refs.\n"); #endif free_array(m->ind); free_array(m->val); if(m->prev) m->prev->next = m->next; if(m->next) m->next->prev = m->prev; if(first_mapping == m) first_mapping = 0; free((char *)m);
c94c371996-03-28Fredrik Hübinette (Hubbe)  GC_FREE();
5267b71995-08-09Fredrik Hübinette (Hubbe) } static void order_mapping(struct mapping *m) { INT32 *order; order = get_set_order(m->ind);
1b70ec1995-10-20Fredrik Hübinette (Hubbe)  if(!order) return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  m->ind = order_array(m->ind, order); m->val = order_array(m->val, order); free((char *)order); } struct mapping *mkmapping(struct array *ind, struct array *val) { struct mapping *m; m=allocate_mapping(copy_array(ind), copy_array(val)); order_mapping(m); return m; } void mapping_insert(struct mapping *m, struct svalue *ind, struct svalue *from) { INT32 i; i=set_lookup(m->ind, ind); if(i < 0) { i = ~i; m->ind=array_insert(m->ind, ind, i); m->val=array_insert(m->val, from, i); }else{ array_set_index(m->ind, i, ind); array_set_index(m->val, i, from); } } #if 0 struct array *mapping_indices(struct mapping *m) { return m->ind; } struct array *mapping_values(struct mapping *m) { return m->val; } #endif void map_delete(struct mapping *m,struct svalue *ind) { INT32 i; i=set_lookup(m->ind, ind); if(i >= 0) { m->ind=array_remove(m->ind, i); m->val=array_remove(m->val, i); } } void check_mapping_for_destruct(struct mapping *m) { INT32 i; check_array_for_destruct(m->val); while( (i=array_find_destructed_object(m->ind)) >= 0) { m->ind=array_remove(m->ind, i); m->val=array_remove(m->val, i); } } union anything *mapping_get_item_ptr(struct mapping *m, struct svalue *ind, TYPE_T t) { INT32 i; i=set_lookup(m->ind, ind); if(i < 0) { struct svalue from; from.type=T_INT; from.subtype=NUMBER_NUMBER; from.u.integer=0; i = ~i; m->ind=array_insert(m->ind, ind, i); m->val=array_insert(m->val, &from, i); } return low_array_get_item_ptr(m->val, i, t); } struct mapping *copy_mapping(struct mapping *tmp) { check_mapping_for_destruct(tmp); return allocate_mapping(copy_array(tmp->ind),copy_array(tmp->val)); } struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 operator) { struct mapping *ret; INT32 *zipper; check_mapping_for_destruct(a); check_mapping_for_destruct(b); zipper=merge(a->ind,b->ind,operator); ret=allocate_mapping(array_zip(a->ind,b->ind,zipper), array_zip(a->val,b->val,zipper)); free((char *)zipper); return ret; } struct mapping *add_mappings(struct svalue *argp,INT32 args) { struct mapping *ret,*a,*b; switch(args) { case 0:
99946c1996-02-17Fredrik Hübinette (Hubbe)  ret=allocate_mapping(allocate_array_no_init(0,0), allocate_array_no_init(0,0));
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case 1: ret=copy_mapping(argp->u.mapping); break; case 2: ret=merge_mappings(argp[0].u.mapping,argp[1].u.mapping,OP_ADD); break; case 3: a=merge_mappings(argp[0].u.mapping,argp[1].u.mapping,OP_ADD); ret=merge_mappings(a,argp[2].u.mapping,OP_ADD); free_mapping(a); break; default: a=add_mappings(argp,args/2); b=add_mappings(argp+args/2,args-args/2); ret=merge_mappings(a,b,OP_ADD); free_mapping(a); free_mapping(b); break; } return ret; } int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p) { if(a == b) return 1; check_mapping_for_destruct(a); check_mapping_for_destruct(b); return array_equal_p(a->ind, b->ind, p) && array_equal_p(a->val, b->val, p); } void describe_mapping(struct mapping *m,struct processing *p,int indent) { struct processing doing; INT32 e,d; char buf[40]; if(! m->ind->size) { my_strcat("([ ])"); return; } doing.next=p; doing.pointer_a=(void *)m; for(e=0;p;e++,p=p->next) { if(p->pointer_a == (void *)m) {
f90e541995-08-17Fredrik Hübinette (Hubbe)  sprintf(buf,"@%ld",(long)e);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_strcat(buf); return; } }
2a50961995-08-23Fredrik Hübinette (Hubbe)  sprintf(buf,"([ /* %ld elements */\n",(long) m->ind->size);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_strcat(buf); for(e=0;e<m->ind->size;e++) { if(e) my_strcat(",\n"); for(d=0; d<indent; d++) my_putchar(' '); describe_index(m->ind, e, &doing, indent+2); my_putchar(':'); describe_index(m->val, e, &doing, indent+2); } my_putchar('\n'); for(e=2; e<indent; e++) my_putchar(' '); my_strcat("])"); } node * make_node_from_mapping(struct mapping *m) { if(check_that_array_is_constant(m->ind) && check_that_array_is_constant(m->val)) { struct svalue s; s.type=T_MAPPING; s.subtype=0; s.u.mapping=m; return mkconstantsvaluenode(&s); }else{ return mkefuncallnode("mkmapping",mknode(F_ARG_LIST,make_node_from_array(m->ind),make_node_from_array(m->val))); } } void f_m_delete(INT32 args) { if(args < 2) error("Too few arguments to m_delete.\n"); if(sp[-args].type != T_MAPPING) error("Bad argument to to m_delete.\n"); map_delete(sp[-args].u.mapping,sp+1-args); pop_n_elems(args-1); } void f_aggregate_mapping(INT32 args) { INT32 e; struct array *ind,*val; struct svalue *s; struct mapping *m; if(args & 1) error("Uneven number of arguments to aggregage_mapping.\n");
99946c1996-02-17Fredrik Hübinette (Hubbe)  ind=allocate_array_no_init(args/2,0); val=allocate_array_no_init(args/2,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  s=sp-args; for(e=0;e<args/2;e++) { ITEM(ind)[e]=*(s++); ITEM(val)[e]=*(s++); } sp-=args; m=allocate_mapping(ind,val); order_mapping(m); sp->u.mapping=m; sp->type=T_MAPPING; sp++; } struct mapping *copy_mapping_recursively(struct mapping *m, struct processing *p) { struct processing doing; struct mapping *ret; doing.next=p; doing.pointer_a=(void *)m; for(;p;p=p->next) { if(p->pointer_a == (void *)m) { ret=(struct mapping *)p->pointer_b; ret->refs++; return ret; } }
c94c371996-03-28Fredrik Hübinette (Hubbe)  ret=allocate_mapping(&empty_array, &empty_array);
5267b71995-08-09Fredrik Hübinette (Hubbe)  doing.pointer_b=(void *)ret; ret->ind=copy_array_recursively(m->ind,&doing); ret->val=copy_array_recursively(m->val,&doing); order_mapping(ret); return ret; } void mapping_search_no_free(struct svalue *to, struct mapping *m, struct svalue *look_for, struct svalue *start) { INT32 start_pos; start_pos=0; if(start) { start_pos=set_lookup(m->ind, start); if(start_pos < 0) { to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0; return; } } start_pos=array_search(m->val,look_for,start_pos); if(start_pos < 0) { to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0; return; } array_index_no_free(to,m->ind,start_pos); } #ifdef DEBUG
624d091996-02-24Fredrik Hübinette (Hubbe) void check_mapping(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) { if(m->refs <=0) fatal("Mapping has zero refs.\n"); if(m->next && m->next->prev != m) fatal("Mapping ->next->prev != mapping.\n"); if(m->prev) { if(m->prev->next != m) fatal("Mapping ->prev->next != mapping.\n"); }else{ if(first_mapping != m) fatal("Mapping ->prev == 0 but first_mapping != mapping.\n"); } }
624d091996-02-24Fredrik Hübinette (Hubbe) void check_all_mappings()
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m; for(m=first_mapping;m;m=m->next)
624d091996-02-24Fredrik Hübinette (Hubbe)  check_mapping(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) } #endif
c94c371996-03-28Fredrik Hübinette (Hubbe)  #ifdef GC2 void gc_mark_mapping_as_referenced(struct mapping *m) { if(gc_mark(m)) { gc_mark_array_as_referenced(m->ind); gc_mark_array_as_referenced(m->val); } } void gc_check_all_mappings() { struct mapping *m; for(m=first_mapping;m;m=m->next) { gc_check(m->ind); gc_check(m->val); } } void gc_mark_all_mappings() { struct mapping *m; for(m=first_mapping;m;m=m->next) if(gc_is_referenced(m)) gc_mark_mapping_as_referenced(m); } void gc_free_all_unreferenced_mappings() { struct mapping *m,*next; for(m=first_mapping;m;m=next) { if(gc_do_free(m)) { m->refs++; free_svalues(ITEM(m->ind), m->ind->size, m->ind->type_field); free_svalues(ITEM(m->val), m->val->size, m->val->type_field); m->ind->size=0; m->val->size=0; next=m->next; free_mapping(m); }else{ next=m->next; } } } #endif /* GC2 */