/*-------------------------------------------------------------------------*/ /* Prolog to Wam Compiler INRIA Rocquencourt - ChLoE Project */ /* C Run-time Daniel Diaz - 1991 */ /* */ /* Wam Implementation */ /* */ /* wam_engine.c */ /*-------------------------------------------------------------------------*/ #include #include #include #include #include #define WAM_ENGINE #include "wam_engine.h" LibPrototype(extern int sscanf()) /*---------------------------------*/ /* Constants */ /*---------------------------------*/ #define SIGNAL_HANDLER X7369676E616C5F68616E646C6572 #define ERR_UNKNOWN_STACK "Error: Unknown stack <%s>" /*---------------------------------*/ /* Type Definitions */ /*---------------------------------*/ /*---------------------------------*/ /* Global Variables */ /*---------------------------------*/ #ifdef WAM_PROFILE static int max_local_used_size =0; static int global_max_used_size =0; static int max_trail_used_size =0; static int nb_of_create_choice_point=0; static int nb_of_update_choice_point=0; static int nb_of_delete_choice_point=0; #endif static CodePtr cont_jmp; /* we use a global var to support DEC alpha */ /* copy term variables */ static WamWord *base_copy; static WamWord vars[2048*2]; /* needs 2 words for a variable */ static WamWord *top_vars; static WamWord glob_buff_save[NB_OF_USED_MACHINE_REGS + 1]; /*---------------------------------*/ /* Function Prototypes */ /*---------------------------------*/ static void Untrail (WamWord *low_adr); Bool Call_Next (CodePtr codep); void Call_Next1 (CodePtr codep); static void Signal_Handler (int sig); static void Copy_Term_Rec (WamWord *dst_adr,WamWord *src_adr, WamWord **p); /*-------------------------------------------------------------------------*/ /* CREATE_CHOICE_POINT */ /* */ /*-------------------------------------------------------------------------*/ void Create_Choice_Point(CodePtr codep_alt,int arity) { WamWord *adr; int i; #ifdef WAM_PROFILE nb_of_create_choice_point++; #endif adr=B; B=Local_Top+CHOICE_STATIC_SIZE+arity; ALTB(B)=codep_alt; CPB(B) =CP; EB(B) =E; BB(B) =adr; BCB(B) =BC; HB(B) =H; TRB(B) =TR; for(i=0;ilow_adr) { word=Trail_Pop; adr=(WamWord *) (Trail_Value_Of(word)); switch(Trail_Tag_Of(word)) { case TUV: *adr=Make_Self_Ref(adr); break; case TOV: *adr=Trail_Pop; break; case TMV: nb=Trail_Pop; TR-=nb; Mem_Word_Cpy(adr,TR,nb) break; default: /* TFC */ (* ((int (*)()) adr)) (); } } } /*-------------------------------------------------------------------------*/ /* GET_CONSTANT */ /* */ /*-------------------------------------------------------------------------*/ Bool Get_Constant(AtomInf *atom,WamWord start_word) { WamWord word,tag,*adr; Deref(start_word,word,tag,adr) switch(tag) { case REF: Bind_UV(adr,Tag_Value(CST,atom)) return TRUE; case CST: return (UnTag_CST(word)==atom); } return FALSE; } /*-------------------------------------------------------------------------*/ /* GET_INTEGER */ /* */ /*-------------------------------------------------------------------------*/ Bool Get_Integer(int n,WamWord start_word) { WamWord word,tag,*adr; Deref(start_word,word,tag,adr) switch(tag) { case REF: Bind_UV(adr,Tag_Value(INT,n)) return TRUE; case INT: return (UnTag_INT(word)==n); } return FALSE; } /*-------------------------------------------------------------------------*/ /* GET_NIL */ /* */ /*-------------------------------------------------------------------------*/ Bool Get_Nil(WamWord start_word) { WamWord word,tag,*adr; Deref(start_word,word,tag,adr) if (tag==REF) { Bind_UV(adr,word_nil) return TRUE; } return (word==word_nil); } /*-------------------------------------------------------------------------*/ /* GET_LIST */ /* */ /*-------------------------------------------------------------------------*/ Bool Get_List(WamWord start_word) { WamWord word,tag,*adr; Deref(start_word,word,tag,adr) switch(tag) { case REF: Bind_UV(adr,Tag_Value(LST,H)) S=WRITE_MODE; return TRUE; case LST: /* init S, i.e. MODE=READ */ S=(WamWord *) UnTag_LST(word)+OFFSET_CAR; return TRUE; } return FALSE; } /*-------------------------------------------------------------------------*/ /* GET_STRUCTURE */ /* */ /*-------------------------------------------------------------------------*/ Bool Get_Structure(AtomInf *f,int n,WamWord start_word) { WamWord word,tag,*adr; Deref(start_word,word,tag,adr) switch(tag) { case REF: Bind_UV(adr,Tag_Value(STC,H)) Global_Push(Functor_Arity(f,n)); S=WRITE_MODE; return TRUE; case STC: /* init S, i.e. MODE=READ */ adr=UnTag_STC(word); if (Functor_And_Arity(adr)!=Functor_Arity(f,n)) return FALSE; S=adr+OFFSET_ARG; return TRUE; } return FALSE; } /*-------------------------------------------------------------------------*/ /* PUT_X_VARIABLE */ /* */ /*-------------------------------------------------------------------------*/ void Put_X_Variable(int x,int a) { X(x)=A(a)=Make_Self_Ref(H); Global_Push(X(x)); } /*-------------------------------------------------------------------------*/ /* PUT_Y_VARIABLE */ /* */ /*-------------------------------------------------------------------------*/ void Put_Y_Variable(int y,int a) { WamWord word,*adr; word=Make_Self_Ref(adr= &Y(E,y)); A(a)= *adr=word; } /*-------------------------------------------------------------------------*/ /* PUT_Y_UNSAFE_VALUE */ /* */ /*-------------------------------------------------------------------------*/ void Put_Y_Unsafe_Value(int y,int a) { WamWord word,tag,*adr; Deref(Y(E,y),word,tag,adr) if (tag==REF && adr>=(WamWord *) EE(E)) { A(a)=Tag_Value(REF,H); Globalize_Local_Unbound_Var(adr) } else A(a)=(Global_UnMove(tag)) ? Tag_Value(REF,adr) : word; } /*-------------------------------------------------------------------------*/ /* PUT_CONSTANT */ /* */ /*-------------------------------------------------------------------------*/ void Put_Constant(AtomInf *atom,int a) { A(a)=Tag_Value(CST,atom); } /*-------------------------------------------------------------------------*/ /* PUT_LIST */ /* */ /*-------------------------------------------------------------------------*/ void Put_List(int a) { A(a)=Tag_Value(LST,H); S=WRITE_MODE; } /*-------------------------------------------------------------------------*/ /* PUT_STRUCTURE */ /* */ /*-------------------------------------------------------------------------*/ void Put_Structure(AtomInf *f,int n,int a) { A(a)=Tag_Value(STC,H); Global_Push(Functor_Arity(f,n)); S=WRITE_MODE; } /*-------------------------------------------------------------------------*/ /* UNIFY_VARIABLE */ /* */ /*-------------------------------------------------------------------------*/ void Unify_Variable(WamWord *start_adr) { WamWord word,tag; if (S!=WRITE_MODE) { tag=Tag_Of(word= *S); *start_adr=(Global_UnMove(tag)) ? Tag_Value(REF,S) : word; S++; } else { *start_adr=word=Make_Self_Ref(H); Global_Push(word); } } /*-------------------------------------------------------------------------*/ /* UNIFY_VALUE */ /* */ /*-------------------------------------------------------------------------*/ Bool Unify_Value(WamWord start_word) { if (S!=WRITE_MODE) { if (!Unify(start_word,*S)) return FALSE; S++; return TRUE; } Global_Push(start_word); return TRUE; } /*-------------------------------------------------------------------------*/ /* UNIFY_LOCAL_VALUE */ /* */ /*-------------------------------------------------------------------------*/ Bool Unify_Local_Value(WamWord start_word) { WamWord word,tag,*adr; if (S!=WRITE_MODE) return Unify(start_word,*S++); Deref(start_word,word,tag,adr) if (tag==REF && Is_A_Local_Adr(adr)) Globalize_Local_Unbound_Var(adr) else Global_Push((Global_UnMove(tag)) ? Tag_Value(REF,adr) : word); return TRUE; } /*-------------------------------------------------------------------------*/ /* UNIFY_VOID */ /* */ /*-------------------------------------------------------------------------*/ void Unify_Void(int n) { WamWord *end_adr; if (S!=WRITE_MODE) S+=n; else for(end_adr=H+(n);H= stk_tbl[i].stack && (*w==0 || *w==M_MAGIC)) w--; max_used=w-stk_tbl[i].stack+1; if (Global_Stack==stk_tbl[i].stack) { used +=REG_BANK_SIZE; /* see Init_Wam_Engine */ max_used+=REG_BANK_SIZE; } used*=sizeof(WamWord); max_used*=sizeof(WamWord); Lib5(printf," %-6s stack:%10d bytes %10d end use %10d max use\n", stk_tbl[i].name,stk_tbl[i].size*sizeof(WamWord),used,max_used); } Lib1(printf,"\n"); Lib1(printf,"\n"); Lib1(printf,"Choice points:\n"); Lib2(printf," create :%10d (try)\n", nb_of_create_choice_point); Lib2(printf," update :%10d (retry)\n",nb_of_update_choice_point); Lib2(printf," delete :%10d (trust)\n",nb_of_delete_choice_point); Lib1(printf,"\n"); #endif } /*-------------------------------------------------------------------------*/ /* CAPTURE_SIGNAL */ /* */ /*-------------------------------------------------------------------------*/ void Capture_Signal(sig) { Lib2(signal,sig,Signal_Handler); } /*-------------------------------------------------------------------------*/ /* SWITCH_REG_BANK */ /* */ /*-------------------------------------------------------------------------*/ void Switch_Reg_Bank(WamWord *new_reg_bank) { int i; WamWord *p1,*p2; if (reg_bank!=new_reg_bank) { p1=reg_bank+NB_OF_X_REGS; p2=new_reg_bank+NB_OF_X_REGS; for(i=0;ig_elem.val); if (b==0) { Lib2(printf,"system error - cannot catch throw(signal(%d))\n",sig); exit(2); } B=Local_Stack+b; #ifdef M_dec_alpha TR=TRB(B); /* to improve since vars are not untrailed */ #endif Update_Choice_Point(ALTB(B),0); /* restore WAM Registers */ Save_Machine_Regs(p_buff_save) longjmp(*p_jumper,-sig); } /*-------------------------------------------------------------------------*/ /* UNIFY */ /* */ /*-------------------------------------------------------------------------*/ Bool Unify(WamWord start_u_word,WamWord start_v_word) { WamWord u_word,u_tag,*u_adr; WamWord v_word,v_tag,*v_adr; int i; Deref(start_u_word,u_word,u_tag,u_adr) Deref(start_v_word,v_word,v_tag,v_adr) if (u_tag==REF) { if (v_tag==REF) { if (u_adr>v_adr) Bind_UV(u_adr,Tag_Value(REF,v_adr)) else if (v_adr>u_adr) Bind_UV(v_adr,Tag_Value(REF,u_adr)) } else if (Global_UnMove(v_tag)) Bind_UV(u_adr,Tag_Value(REF,v_adr)) else Bind_UV(u_adr,v_word) return TRUE; } switch(v_tag) { case REF: if (Global_UnMove(u_tag)) Bind_UV(v_adr,Tag_Value(REF,u_adr)) else Bind_UV(v_adr,u_word) return TRUE; case INT: case CST: return (u_word==v_word); /* test tag and value */ case LST: if (u_tag!=LST) return FALSE; u_adr=UnTag_LST(u_word); v_adr=UnTag_LST(v_word); if (u_adr==v_adr) return TRUE; return Unify(Car(u_adr),Car(v_adr)) && Unify(Cdr(u_adr),Cdr(v_adr)); default: /* v_tag==STC */ if (u_tag!=STC) return FALSE; u_adr=UnTag_STC(u_word); v_adr=UnTag_STC(v_word); if (u_adr==v_adr) return TRUE; if (Functor_And_Arity(u_adr) != Functor_And_Arity(v_adr)) return FALSE; i=Arity(u_adr); do { --i; if (!Unify(Arg(u_adr,i),Arg(v_adr,i))) return FALSE; } while(i); return TRUE; } } /*-------------------------------------------------------------------------*/ /* TERM_COMPARE */ /* */ /*-------------------------------------------------------------------------*/ int Term_Compare(WamWord start_u_word,WamWord start_v_word) { WamWord u_word,u_tag,*u_adr; WamWord v_word,v_tag,*v_adr; AtomInf *u_functor; int u_arity; WamWord *u_arg_adr; AtomInf *v_functor; int v_arity; WamWord *v_arg_adr; int i,x; Deref(start_u_word,u_word,u_tag,u_adr) Deref(start_v_word,v_word,v_tag,v_adr) switch(u_tag) { case REF: return (v_tag!=REF) ? -1 : u_adr-v_adr; case INT: if (v_tag==REF) return 1; return (v_tag!=INT) ? -1 : u_word-v_word; case CST: if (v_tag==REF || v_tag==INT) return 1; return (v_tag!=CST) ? -1 : Lib2(strcmp,UnTag_CST(u_word)->name, UnTag_CST(v_word)->name); } /* u_tag==LST/STC */ if ((v_functor=Get_Compound(v_tag,v_word,&v_arity,&v_arg_adr))==NULL) return 1; /* v_tag!=LST/STC */ u_functor=Get_Compound(u_tag,u_word,&u_arity,&u_arg_adr); if (u_arity!=v_arity) return u_arity-v_arity; if (u_functor!=v_functor) return Lib2(strcmp,u_functor->name,v_functor->name); for(i=0;i=base_copy) /* already a copy */ { *dst_adr=word; return; } *top_vars++ = word; /* word to restore */ *top_vars++ = (WamWord) adr; /* address to restore */ *adr=*dst_adr=Tag_Value(REF,dst_adr); /* bind to a new copy */ return; case INT: case CST: *dst_adr=word; return; case LST: adr=UnTag_LST(word); q=*p; *p=&Cdr(q)+1; Copy_Term_Rec(&Car(q),&Car(adr),p); Copy_Term_Rec(&Cdr(q),&Cdr(adr),p); *dst_adr=Tag_Value(LST,q); return; default: /* tag==STC */ adr=UnTag_STC(word); q=*p; Functor_And_Arity(q)=Functor_And_Arity(adr); n=Arity(adr); *p=&Arg(q,n-1)+1; for(i=0;isrc_adr) /* only useful for Global_UnMove() */ Copy_Contiguous_Term(q,adr); return; case INT: case CST: *dst_adr=word; return; case LST: adr=UnTag_LST(word); q=Old_Adr_To_New_Adr(adr); Copy_Contiguous_Term(&Car(q),&Car(adr)); Copy_Contiguous_Term(&Cdr(q),&Cdr(adr)); *dst_adr=Tag_Value(LST,q); return; default: /* tag==STC */ adr=UnTag_STC(word); q=Old_Adr_To_New_Adr(adr); Functor_And_Arity(q)=Functor_And_Arity(adr); n=Arity(adr); for(i=0;i