just a mirror
This commit is contained in:
parent
3209078bda
commit
6798b40dbf
|
@ -1 +0,0 @@
|
|||
Subproject commit bea2431c3ed833d81f5297e32c3776760c047561
|
|
@ -0,0 +1,201 @@
|
|||
The Artistic License 2.0
|
||||
|
||||
Copyright (c) 2000-2006, The Perl Foundation.
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
This license establishes the terms under which a given free software
|
||||
Package may be copied, modified, distributed, and/or redistributed.
|
||||
The intent is that the Copyright Holder maintains some artistic
|
||||
control over the development of that Package while still keeping the
|
||||
Package available as open source and free software.
|
||||
|
||||
You are always permitted to make arrangements wholly outside of this
|
||||
license directly with the Copyright Holder of a given Package. If the
|
||||
terms of this license do not permit the full use that you propose to
|
||||
make of the Package, you should contact the Copyright Holder and seek
|
||||
a different licensing arrangement.
|
||||
|
||||
Definitions
|
||||
|
||||
"Copyright Holder" means the individual(s) or organization(s)
|
||||
named in the copyright notice for the entire Package.
|
||||
|
||||
"Contributor" means any party that has contributed code or other
|
||||
material to the Package, in accordance with the Copyright Holder's
|
||||
procedures.
|
||||
|
||||
"You" and "your" means any person who would like to copy,
|
||||
distribute, or modify the Package.
|
||||
|
||||
"Package" means the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection and/or of
|
||||
those files. A given Package may consist of either the Standard
|
||||
Version, or a Modified Version.
|
||||
|
||||
"Distribute" means providing a copy of the Package or making it
|
||||
accessible to anyone else, or in the case of a company or
|
||||
organization, to others outside of your company or organization.
|
||||
|
||||
"Distributor Fee" means any fee that you charge for Distributing
|
||||
this Package or providing support for this Package to another
|
||||
party. It does not mean licensing fees.
|
||||
|
||||
"Standard Version" refers to the Package if it has not been
|
||||
modified, or has been modified only in ways explicitly requested
|
||||
by the Copyright Holder.
|
||||
|
||||
"Modified Version" means the Package, if it has been changed, and
|
||||
such changes were not explicitly requested by the Copyright
|
||||
Holder.
|
||||
|
||||
"Original License" means this Artistic License as Distributed with
|
||||
the Standard Version of the Package, in its current version or as
|
||||
it may be modified by The Perl Foundation in the future.
|
||||
|
||||
"Source" form means the source code, documentation source, and
|
||||
configuration files for the Package.
|
||||
|
||||
"Compiled" form means the compiled bytecode, object code, binary,
|
||||
or any other form resulting from mechanical transformation or
|
||||
translation of the Source form.
|
||||
|
||||
|
||||
Permission for Use and Modification Without Distribution
|
||||
|
||||
(1) You are permitted to use the Standard Version and create and use
|
||||
Modified Versions for any purpose without restriction, provided that
|
||||
you do not Distribute the Modified Version.
|
||||
|
||||
|
||||
Permissions for Redistribution of the Standard Version
|
||||
|
||||
(2) You may Distribute verbatim copies of the Source form of the
|
||||
Standard Version of this Package in any medium without restriction,
|
||||
either gratis or for a Distributor Fee, provided that you duplicate
|
||||
all of the original copyright notices and associated disclaimers. At
|
||||
your discretion, such verbatim copies may or may not include a
|
||||
Compiled form of the Package.
|
||||
|
||||
(3) You may apply any bug fixes, portability changes, and other
|
||||
modifications made available from the Copyright Holder. The resulting
|
||||
Package will still be considered the Standard Version, and as such
|
||||
will be subject to the Original License.
|
||||
|
||||
|
||||
Distribution of Modified Versions of the Package as Source
|
||||
|
||||
(4) You may Distribute your Modified Version as Source (either gratis
|
||||
or for a Distributor Fee, and with or without a Compiled form of the
|
||||
Modified Version) provided that you clearly document how it differs
|
||||
from the Standard Version, including, but not limited to, documenting
|
||||
any non-standard features, executables, or modules, and provided that
|
||||
you do at least ONE of the following:
|
||||
|
||||
(a) make the Modified Version available to the Copyright Holder
|
||||
of the Standard Version, under the Original License, so that the
|
||||
Copyright Holder may include your modifications in the Standard
|
||||
Version.
|
||||
|
||||
(b) ensure that installation of your Modified Version does not
|
||||
prevent the user installing or running the Standard Version. In
|
||||
addition, the Modified Version must bear a name that is different
|
||||
from the name of the Standard Version.
|
||||
|
||||
(c) allow anyone who receives a copy of the Modified Version to
|
||||
make the Source form of the Modified Version available to others
|
||||
under
|
||||
|
||||
(i) the Original License or
|
||||
|
||||
(ii) a license that permits the licensee to freely copy,
|
||||
modify and redistribute the Modified Version using the same
|
||||
licensing terms that apply to the copy that the licensee
|
||||
received, and requires that the Source form of the Modified
|
||||
Version, and of any works derived from it, be made freely
|
||||
available in that license fees are prohibited but Distributor
|
||||
Fees are allowed.
|
||||
|
||||
|
||||
Distribution of Compiled Forms of the Standard Version
|
||||
or Modified Versions without the Source
|
||||
|
||||
(5) You may Distribute Compiled forms of the Standard Version without
|
||||
the Source, provided that you include complete instructions on how to
|
||||
get the Source of the Standard Version. Such instructions must be
|
||||
valid at the time of your distribution. If these instructions, at any
|
||||
time while you are carrying out such distribution, become invalid, you
|
||||
must provide new instructions on demand or cease further distribution.
|
||||
If you provide valid instructions or cease distribution within thirty
|
||||
days after you become aware that the instructions are invalid, then
|
||||
you do not forfeit any of your rights under this license.
|
||||
|
||||
(6) You may Distribute a Modified Version in Compiled form without
|
||||
the Source, provided that you comply with Section 4 with respect to
|
||||
the Source of the Modified Version.
|
||||
|
||||
|
||||
Aggregating or Linking the Package
|
||||
|
||||
(7) You may aggregate the Package (either the Standard Version or
|
||||
Modified Version) with other packages and Distribute the resulting
|
||||
aggregation provided that you do not charge a licensing fee for the
|
||||
Package. Distributor Fees are permitted, and licensing fees for other
|
||||
components in the aggregation are permitted. The terms of this license
|
||||
apply to the use and Distribution of the Standard or Modified Versions
|
||||
as included in the aggregation.
|
||||
|
||||
(8) You are permitted to link Modified and Standard Versions with
|
||||
other works, to embed the Package in a larger work of your own, or to
|
||||
build stand-alone binary or bytecode versions of applications that
|
||||
include the Package, and Distribute the result without restriction,
|
||||
provided the result does not expose a direct interface to the Package.
|
||||
|
||||
|
||||
Items That are Not Considered Part of a Modified Version
|
||||
|
||||
(9) Works (including, but not limited to, modules and scripts) that
|
||||
merely extend or make use of the Package, do not, by themselves, cause
|
||||
the Package to be a Modified Version. In addition, such works are not
|
||||
considered parts of the Package itself, and are not subject to the
|
||||
terms of this license.
|
||||
|
||||
|
||||
General Provisions
|
||||
|
||||
(10) Any use, modification, and distribution of the Standard or
|
||||
Modified Versions is governed by this Artistic License. By using,
|
||||
modifying or distributing the Package, you accept this license. Do not
|
||||
use, modify, or distribute the Package, if you do not accept this
|
||||
license.
|
||||
|
||||
(11) If your Modified Version has been derived from a Modified
|
||||
Version made by someone other than you, you are nevertheless required
|
||||
to ensure that your Modified Version complies with the requirements of
|
||||
this license.
|
||||
|
||||
(12) This license does not grant you the right to use any trademark,
|
||||
service mark, tradename, or logo of the Copyright Holder.
|
||||
|
||||
(13) This license includes the non-exclusive, worldwide,
|
||||
free-of-charge patent license to make, have made, use, offer to sell,
|
||||
sell, import and otherwise transfer the Package with respect to any
|
||||
patent claims licensable by the Copyright Holder that are necessarily
|
||||
infringed by the Package. If you institute patent litigation
|
||||
(including a cross-claim or counterclaim) against any party alleging
|
||||
that the Package constitutes direct or contributory patent
|
||||
infringement, then this Artistic License to you shall terminate on the
|
||||
date that such litigation is filed.
|
||||
|
||||
(14) Disclaimer of Warranty:
|
||||
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
|
||||
IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
|
||||
LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,295 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: eam compiler data structures and routines *
|
||||
*************************************************************************/
|
||||
|
||||
#define Print_Code 0
|
||||
/* To help on compiler debuging
|
||||
1 -> show predicates info
|
||||
2 -> show YAP abstract machine code (YAAM)
|
||||
4 -> show YAAM after transformation
|
||||
8 -> show indexing code
|
||||
|
||||
16 -> show EAM intermediate code
|
||||
32 -> show EAM intermediate code with direct_calls
|
||||
128 -> show EAM abstrac machine code
|
||||
*/
|
||||
|
||||
#define Variavel 1
|
||||
#define Lista 2
|
||||
#define Estrutura 4
|
||||
#define Constante 8
|
||||
|
||||
typedef unsigned long Cell;
|
||||
|
||||
|
||||
typedef struct PCODE{
|
||||
struct PCODE *nextInst;
|
||||
int op, new1;
|
||||
unsigned long new4;
|
||||
} CInstr;
|
||||
|
||||
struct Clauses {
|
||||
unsigned int idx; /* info for indexing on first arg */
|
||||
Cell val; /* atom or functor in first arg */
|
||||
unsigned int nr_vars; /* nr of local vars */
|
||||
struct Predicates *predi; /* predicate struct */
|
||||
int side_effects; /* clause has side effects */
|
||||
Cell *code;
|
||||
|
||||
struct Clauses *next; /* next clause within the same predicate */
|
||||
};
|
||||
|
||||
|
||||
struct HASH_TABLE {
|
||||
Cell value;
|
||||
Cell *code;
|
||||
struct HASH_TABLE *next;
|
||||
};
|
||||
|
||||
struct Predicates { /* To register information about predicates */
|
||||
unsigned long id;
|
||||
unsigned char *name;
|
||||
unsigned int arity;
|
||||
unsigned int nr_alt; /* nr of alternativas */
|
||||
unsigned int calls; /* nr of existent calls to this predicate */
|
||||
struct Clauses *first;
|
||||
struct Clauses *last;
|
||||
int idx; /* is code indexed ? 0= needs compilation -1= no indexing possible 1= indexed */
|
||||
unsigned int idx_var; /* nr clauses with 1st argument var */
|
||||
unsigned int idx_list; /* nr clauses with 1st argument list */
|
||||
unsigned int idx_atom; /* nr clauses with 1st argument atom */
|
||||
unsigned int idx_functor; /* nr clauses with 1st argument functor */
|
||||
short int eager_split; /* allow eager splitting */
|
||||
|
||||
Cell *code; /* try, retry and trust code or Indexing code */
|
||||
struct HASH_TABLE **atom;
|
||||
struct HASH_TABLE **functor;
|
||||
Cell *list;
|
||||
Cell *vars;
|
||||
struct Predicates *next;
|
||||
};
|
||||
|
||||
/**************************** EAM TRUE STUFF *************/
|
||||
|
||||
struct SUSPENSIONS {
|
||||
struct AND_BOX *and_box; /* And_box where the variable has suspended */
|
||||
short int reason; /* suspended before executing call number nr_call */
|
||||
struct SUSPENSIONS *next; /* Pointer to the next suspention */
|
||||
struct SUSPENSIONS *prev;
|
||||
};
|
||||
|
||||
struct SUSPENSIONS_VAR {
|
||||
struct AND_BOX *and_box; /* And_box where the variable has suspended */
|
||||
struct SUSPENSIONS_VAR *next; /* Pointer to the next suspention */
|
||||
};
|
||||
|
||||
struct PERM_VAR {
|
||||
Cell value; /* value assigned to the variable */
|
||||
struct AND_BOX *home; /* pointer to the goal_box structure of the variable */
|
||||
Cell *yapvar;
|
||||
struct SUSPENSIONS_VAR *suspensions; /* Pointer to a Suspension List */
|
||||
struct PERM_VAR *next;
|
||||
};
|
||||
|
||||
struct EXTERNAL_VAR { /* to be used as some kind of trail */
|
||||
Cell value; /* value assign to the variable */
|
||||
struct PERM_VAR *var; /* pointer to the local_var struct */
|
||||
struct EXTERNAL_VAR *next;
|
||||
};
|
||||
|
||||
struct status_and {
|
||||
struct OR_BOX *call; /* POINTER TO A OR_BOX */
|
||||
Cell *locals; /* temporary vars vector */
|
||||
Cell *code; /* Pointer to the start code */
|
||||
int state; /* State of the OR_BOX */
|
||||
struct status_and *previous;
|
||||
struct status_and *next;
|
||||
};
|
||||
|
||||
struct status_or {
|
||||
struct AND_BOX *alternative; /* POINTER TO A AND_BOX */
|
||||
Cell *args; /* Saved Arguments */
|
||||
Cell *code; /* Pointer to Start Code */
|
||||
int state; /* State of the AND_BOX */
|
||||
struct status_or *previous;
|
||||
struct status_or *next;
|
||||
};
|
||||
|
||||
struct OR_BOX {
|
||||
struct AND_BOX *parent;
|
||||
struct status_and *nr_call; /* order of this box */
|
||||
short int nr_all_alternatives; /* number of existing alternatives */
|
||||
struct status_or *alternatives; /* alternatives of the or_box */
|
||||
short int eager_split;
|
||||
};
|
||||
|
||||
struct AND_BOX {
|
||||
struct OR_BOX *parent; /* pointer to the parent or-box */
|
||||
struct status_or *nr_alternative; /* This box is alternative id */
|
||||
short int nr_all_calls; /* numger of all goals */
|
||||
struct PERM_VAR *perms;
|
||||
struct status_and *calls;
|
||||
|
||||
short int level; /* indicates the level in the tree */
|
||||
struct EXTERNAL_VAR *externals; /* pointer to a list of external_vars */
|
||||
struct SUSPENSIONS *suspended; /* pointer to a list of suspended boxes */
|
||||
short int side_effects; /* to mark if are calls to builtins with side_efects (like write) */
|
||||
};
|
||||
|
||||
|
||||
/* TYPE OF STATES */
|
||||
#define ZERO 0 /* No State yet */
|
||||
#define SUCCESS 1
|
||||
#define FAILS 2
|
||||
#define READY 4 /* Is ready to start execution */
|
||||
#define RUNNING 8 /* Is running */
|
||||
#define RUNAGAIN 16 /* Is running again */
|
||||
#define SUSPEND 32 /* Has suspended */
|
||||
#define WAKE 64 /* Was Suspended, but now is Ready again */
|
||||
#define CHANGED 128 /* Has received some change on it's external variables, needs to re-run */
|
||||
#define END 256 /* Has suspended on end, on wake up can pass to a success state */
|
||||
#define WAITING 512 /* The clause is waiting for the previous predicates to leave the Suspended state */
|
||||
#define FAILED 1024 /* has failed */
|
||||
|
||||
#define CUT_RIGHT 2048
|
||||
#define SKIP_VAR 4096
|
||||
#define LEFTMOST_PARENT 8192
|
||||
#define FIRST 16384
|
||||
#define LEFTMOST 32768
|
||||
|
||||
#define WAITING_TO_BE_FIRST (WAITING + FIRST)
|
||||
#define WAITING_TO_BE_LEFTMOST (WAITING + LEFTMOST)
|
||||
#define WAITING_TO_BE_LEFTMOST_PARENT (WAITING + LEFTMOST_PARENT)
|
||||
#define WAITING_TO_CUT (WAITING + CUT_RIGHT)
|
||||
#define WAITING_SKIP_VAR (WAITING + SKIP_VAR)
|
||||
#define SUSPEND_END (SUSPEND+END)
|
||||
#define WAKE_END (WAKE+END)
|
||||
|
||||
|
||||
#define NORMAL_SUSPENSION 0
|
||||
#define LEFTMOST_SUSPENSION 1
|
||||
#define WAIT_SUSPENSION 2
|
||||
#define CUT_SUSPENSION 3
|
||||
#define WRITE_SUSPENSION 4
|
||||
#define VAR_SUSPENSION 5
|
||||
#define YAP_VAR_SUSPENSION 6
|
||||
|
||||
/* TYPE OF SIDE_EFFECTS */
|
||||
|
||||
#define WRITE 1
|
||||
#define COMMIT 2
|
||||
#define VAR 4
|
||||
#define SEQUENCIAL 8
|
||||
|
||||
#define CUT 32 /* Greater than 32 always cut */
|
||||
|
||||
|
||||
/**********************************************************************************/
|
||||
|
||||
struct EAM_TEMP {
|
||||
|
||||
|
||||
|
||||
struct EAM_TEMP *previous;
|
||||
struct EAM_TEMP *next;
|
||||
};
|
||||
|
||||
struct EAM_Global {
|
||||
Cell *pc;
|
||||
Cell *_H;
|
||||
Cell *_S;
|
||||
short _Mode; /* read or write mode */
|
||||
short ES; /* goal shoud do Eager Split yes or no ? */
|
||||
short MemGoing; /* Direction the that stacks use to grow */
|
||||
Cell *varlocals; /* local vars to the working AND-BOX */
|
||||
struct AND_BOX *ABX; /* working AND-BOX */
|
||||
struct OR_BOX *OBX; /* working OR-BOX */
|
||||
struct SUSPENSIONS *su; /* list with suspended work */
|
||||
struct AND_BOX *top;
|
||||
|
||||
struct status_and *USE_SAME_ANDBOX; /* when only 1 alternative */
|
||||
struct status_or *nr_alternative; /* working alternative */
|
||||
struct status_and *nr_call; /* working goal */
|
||||
|
||||
Cell *VAR_TRAIL;
|
||||
int VAR_TRAIL_NR;
|
||||
int Mem_FULL; /* if mem_full, then perform GC */
|
||||
int nr_call_forking; /* number of splits already performed */
|
||||
unsigned long START_ADDR_HEAP, START_ADDR_BOXES, END_BOX, END_H;
|
||||
unsigned int nr_gc_heap;
|
||||
unsigned int nr_gc_boxed;
|
||||
Cell **IndexFree;
|
||||
Cell *NextFree;
|
||||
Cell *sp;
|
||||
struct PERM_VAR *NextVar;
|
||||
|
||||
#if Memory_Stat
|
||||
unsigned long TOTAL_MEM, MEM_REUSED, TOTAL_TEMPS,TEMPS_REUSED, TOTAL_PERMS, PERMS_REUSED;
|
||||
unsigned long Memory_STAT[5000][5];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#define beam_X XREGS /* use the same X-Regs as YAP */
|
||||
|
||||
#define beam_pc (eamGlobal->pc)
|
||||
#define beam_H (eamGlobal->_H)
|
||||
#define beam_S (eamGlobal->_S)
|
||||
#define beam_Mode (eamGlobal->_Mode)
|
||||
#define beam_ES (eamGlobal->ES)
|
||||
#define beam_MemGoing (eamGlobal->MemGoing)
|
||||
#define beam_varlocals (eamGlobal->varlocals)
|
||||
#define beam_ABX (eamGlobal->ABX)
|
||||
#define beam_OBX (eamGlobal->OBX)
|
||||
#define beam_su (eamGlobal->su)
|
||||
#define beam_top (eamGlobal->top)
|
||||
#define beam_USE_SAME_ANDBOX (eamGlobal->USE_SAME_ANDBOX)
|
||||
#define beam_nr_alternative (eamGlobal->nr_alternative)
|
||||
#define beam_nr_call (eamGlobal->nr_call)
|
||||
#define beam_VAR_TRAIL (eamGlobal->VAR_TRAIL)
|
||||
#define beam_VAR_TRAIL_NR (eamGlobal->VAR_TRAIL_NR)
|
||||
#define beam_Mem_FULL (eamGlobal->Mem_FULL)
|
||||
#define beam_nr_call_forking (eamGlobal->nr_call_forking)
|
||||
#define beam_START_ADDR_HEAP (eamGlobal->START_ADDR_HEAP)
|
||||
#define beam_START_ADDR_BOXES (eamGlobal->START_ADDR_BOXES)
|
||||
#define beam_END_BOX (eamGlobal->END_BOX)
|
||||
#define beam_END_H (eamGlobal->END_H)
|
||||
#define beam_nr_gc_heap (eamGlobal->nr_gc_heap)
|
||||
#define beam_nr_gc_boxed (eamGlobal->nr_gc_boxed)
|
||||
#define beam_IndexFree (eamGlobal->IndexFree)
|
||||
#define beam_NextFree (eamGlobal->NextFree)
|
||||
#define beam_sp (eamGlobal->sp)
|
||||
#define beam_NextVar (eamGlobal->NextVar)
|
||||
#if Memory_Stat
|
||||
#define beam_TOTAL_MEM (eamGlobal->TOTAL_MEM)
|
||||
#define beam_MEM_REUSED (eamGlobal->MEM_REUSED)
|
||||
#define beam_TOTAL_TEMPS (eamGlobal->TOTAL_TEMPS)
|
||||
#define beam_TEMPS_REUSED (eamGlobal->TEMPS_REUSED)
|
||||
#define beam_TOTAL_PERMS (eamGlobal->TOTAL_PERMS)
|
||||
#define beam_PERMS_REUSED (eamGlobal->PERMS_REUSED)
|
||||
#define beam_Memory_STAT (eamGlobal->Memory_STAT)
|
||||
#endif
|
||||
|
||||
#define arg1 *(beam_pc+1)
|
||||
#define arg2 *(beam_pc+2)
|
||||
#define arg3 *(beam_pc+3)
|
||||
#define arg4 *(beam_pc+4)
|
||||
|
||||
#define CELL_SIZE (sizeof(Cell))
|
||||
#define POINTER_SIZE (sizeof(Cell *))
|
||||
#define ANDBOX_SIZE (sizeof(struct AND_BOX))
|
||||
#define ORBOX_SIZE (sizeof(struct OR_BOX))
|
||||
#define PERM_VAR_SIZE (sizeof(struct PERM_VAR))
|
||||
#define EXTERNAL_VAR_SIZE (sizeof(struct EXTERNAL_VAR))
|
||||
#define SUSPENSIONS_SIZE (sizeof(struct SUSPENSIONS))
|
||||
#define SUSPENSIONS_VAR_SIZE (sizeof(struct SUSPENSIONS_VAR))
|
||||
#define STATUS_AND_SIZE (sizeof(struct status_and))
|
||||
#define STATUS_OR_SIZE (sizeof(struct status_or))
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,498 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: garbage collector routines *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
void garbage_collector(void);
|
||||
struct OR_BOX *move_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call);
|
||||
struct AND_BOX *move_andbox(struct AND_BOX *a,struct OR_BOX *parent,struct status_or *alt);
|
||||
Cell refresh_structures(Cell c);
|
||||
Cell move_structures(Cell c);
|
||||
void refresh_andbox(struct AND_BOX *a);
|
||||
void refresh_orbox(struct OR_BOX *o);
|
||||
|
||||
Cell refresh_structures(Cell c)
|
||||
{
|
||||
Cell *C, OldC;
|
||||
|
||||
OldC=deref((Cell) c);
|
||||
|
||||
if (isvar(OldC)) {
|
||||
return(OldC);
|
||||
}
|
||||
if (isatom(OldC)) {
|
||||
return(OldC);
|
||||
}
|
||||
|
||||
if (isappl(OldC)) {
|
||||
int i,arity;
|
||||
|
||||
C=(Cell *) repappl(OldC);
|
||||
arity = ((int) ArityOfFunctor((Functor) *C));
|
||||
for(i=0;i<arity ;i++) {
|
||||
C++;
|
||||
*C=refresh_structures((Cell) C);
|
||||
}
|
||||
return(OldC);
|
||||
}
|
||||
/* else if (ispair(c)) { */
|
||||
C=(Cell *) reppair(OldC);
|
||||
*C=refresh_structures((Cell) C);
|
||||
C++;
|
||||
*C=refresh_structures((Cell) C);
|
||||
return(OldC);
|
||||
}
|
||||
|
||||
Cell move_structures(Cell c)
|
||||
{
|
||||
Cell *NewC, *NewH;
|
||||
Cell OldC,LOCAL_OldH;
|
||||
|
||||
OldC=deref((Cell) c);
|
||||
/*
|
||||
if (beam_MemGoing==1 && ((unsigned long) OldC) <beam_START_ADDR_HEAP+beam_MEM_H/2) return(OldC);
|
||||
if (beam_MemGoing==-1 && ((unsigned long) OldC)>=beam_START_ADDR_HEAP+beam_MEM_H/2 && ((unsigned long) OldC) <beam_START_ADDR_BOXES) return(OldC);
|
||||
*/
|
||||
if (isvar(OldC)) {
|
||||
return(OldC);
|
||||
}
|
||||
if (isatom(OldC)) {
|
||||
return(OldC);
|
||||
}
|
||||
|
||||
LOCAL_OldH=(Cell) beam_H;
|
||||
NewH=beam_H;
|
||||
if (isappl(OldC)) {
|
||||
int i,arity;
|
||||
|
||||
NewC=(Cell *) repappl(OldC);
|
||||
arity = ((int) ArityOfFunctor((Functor) *NewC));
|
||||
*NewH++=*NewC++;
|
||||
beam_H+=arity+1;
|
||||
for(i=0;i<arity ;i++) {
|
||||
*NewH=move_structures((Cell) NewC);
|
||||
NewH++;
|
||||
NewC++;
|
||||
}
|
||||
return(absappl(LOCAL_OldH));
|
||||
}
|
||||
/* else if (ispair(c)) { */
|
||||
NewC=(Cell *) reppair(OldC);
|
||||
beam_H+=2;
|
||||
*NewH=move_structures((Cell) NewC);
|
||||
NewC++;
|
||||
NewH++;
|
||||
*NewH=move_structures((Cell) NewC);
|
||||
return(abspair(LOCAL_OldH));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void garbage_collector()
|
||||
{
|
||||
#if GARBAGE_COLLECTOR==2
|
||||
struct AND_BOX *new_top;
|
||||
#endif
|
||||
|
||||
if (beam_Mem_FULL & 2) beam_nr_gc_heap++; else beam_nr_gc_boxed++;
|
||||
#if Debug || Debug_GC
|
||||
printf("Entering Garbage Collector for the %dth time (Reason=%d)\n",beam_nr_gc_heap+beam_nr_gc_boxed,beam_Mem_FULL);
|
||||
#endif
|
||||
#if Debug_Dump_State & 2
|
||||
dump_eam_state();
|
||||
printf("--------------------------------------------------------------------\n");
|
||||
#endif
|
||||
|
||||
beam_Mem_FULL=0;
|
||||
|
||||
#if Memory_Stat
|
||||
if (beam_MemGoing==1) {
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][1]=(unsigned long) beam_H-beam_START_ADDR_HEAP;
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][2]=(unsigned long) beam_NextFree-beam_START_ADDR_BOXES;
|
||||
} else {
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][1]=(unsigned long) beam_H-beam_START_ADDR_HEAP-MEM_H/2;
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][2]=beam_END_BOX- ((unsigned long) beam_NextFree);
|
||||
}
|
||||
if (GARBAGE_COLLECTOR==1)
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][2]=beam_END_BOX- ((unsigned long) beam_NextFree);
|
||||
#endif
|
||||
|
||||
#if GARBAGE_COLLECTOR==1
|
||||
if (beam_MemGoing==1) {
|
||||
if (beam_H < (Cell *) (beam_START_ADDR_HEAP+MEM_H/2)) beam_H=(Cell *) (beam_START_ADDR_HEAP+MEM_H/2); else beam_H++;
|
||||
beam_MemGoing=-1;
|
||||
beam_sp=(Cell *) beam_START_ADDR_HEAP+MEM_H/2;
|
||||
beam_sp--;
|
||||
} else {
|
||||
beam_H=(Cell *) beam_START_ADDR_HEAP;
|
||||
beam_MemGoing=1;
|
||||
beam_sp=(Cell *) beam_END_H;
|
||||
beam_sp--;
|
||||
}
|
||||
refresh_andbox(beam_top);
|
||||
|
||||
#if Clear_MEMORY
|
||||
if (beam_MemGoing==-1) {
|
||||
memset(beam_START_ADDR_HEAP,0,MEM_H/2);
|
||||
} else {
|
||||
memset(beam_START_ADDR_HEAP+MEM_H/2,0,MEM_H/2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
memset(beam_IndexFree,0,INDEX_SIZE*POINTER_SIZE);
|
||||
if (beam_MemGoing==1) {
|
||||
if (beam_H < (Cell *) (beam_START_ADDR_HEAP+MEM_H/2)) beam_H=(Cell *) (beam_START_ADDR_HEAP+MEM_H/2); else beam_H++;
|
||||
beam_NextFree=(Cell *) beam_END_BOX;
|
||||
beam_MemGoing=-1;
|
||||
beam_sp=(Cell *) beam_START_ADDR_HEAP+MEM_H/2; beam_sp-=2;
|
||||
} else {
|
||||
if (beam_H>=(Cell *) beam_START_ADDR_BOXES) beam_NextFree=beam_H+1; else beam_NextFree=(Cell *) beam_START_ADDR_BOXES;
|
||||
beam_H=(Cell *) beam_START_ADDR_HEAP;
|
||||
beam_MemGoing=1;
|
||||
beam_sp=(Cell *) beam_END_H; beam_sp-=2;
|
||||
}
|
||||
beam_Mem_FULL=0;
|
||||
|
||||
beam_su=NULL;
|
||||
new_top=move_andbox(beam_top,NULL,NULL);
|
||||
beam_top=new_top;
|
||||
|
||||
#if Clear_MEMORY
|
||||
if (beam_MemGoing==-1) {
|
||||
memset((void *) beam_START_ADDR_HEAP,0,MEM_H/2);
|
||||
memset((void *) beam_START_ADDR_BOXES,0,MEM_BOXES/2);
|
||||
} else {
|
||||
memset((void *) beam_START_ADDR_HEAP+MEM_H/2,0,MEM_H/2);
|
||||
memset((void *) beam_START_ADDR_BOXES+MEM_BOXES/2,0,MEM_BOXES/2);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if Memory_Stat
|
||||
if (beam_MemGoing==1) {
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][3]=(unsigned long) beam_H- beam_START_ADDR_HEAP;
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][4]=(unsigned long) beam_NextFree- beam_START_ADDR_BOXES;
|
||||
} else {
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][3]=(unsigned long) beam_H- beam_START_ADDR_HEAP-MEM_H/2;
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][4]= beam_END_BOX- ((unsigned long) beam_NextFree);
|
||||
}
|
||||
if (GARBAGE_COLLECTOR==1)
|
||||
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][4]= beam_END_BOX- ((unsigned long) beam_NextFree);
|
||||
#endif
|
||||
|
||||
#if Debug_Dump_State & 2
|
||||
dump_eam_state();
|
||||
#endif
|
||||
#if Debug
|
||||
printf("End of Garbage Collector\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if GARBAGE_COLLECTOR!=1
|
||||
|
||||
|
||||
struct OR_BOX *move_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call)
|
||||
{
|
||||
struct OR_BOX *new_orbox;
|
||||
struct status_or *old, *new, *first=NULL, *last=NULL;
|
||||
Cell *args,*newargs;
|
||||
|
||||
if (o==NULL) return(NULL);
|
||||
#if !Fast_go
|
||||
if ((Cell *) o<(Cell *) beam_START_ADDR_BOXES || (Cell *) o>(Cell *) beam_END_BOX) return (NULL);
|
||||
#endif
|
||||
new_orbox=(struct OR_BOX *) request_memory(ORBOX_SIZE);
|
||||
if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n");
|
||||
if (beam_OBX==o) beam_OBX=new_orbox;
|
||||
new_orbox->parent=parent;
|
||||
new_orbox->nr_call=nr_call;
|
||||
new_orbox->nr_all_alternatives=o->nr_all_alternatives;
|
||||
|
||||
old=o->alternatives;
|
||||
while(old!=NULL) {
|
||||
new=(struct status_or *) request_memory(STATUS_OR_SIZE);
|
||||
if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n");
|
||||
|
||||
if (beam_nr_alternative==old) beam_nr_alternative=new;
|
||||
new->args=old->args;
|
||||
new->code=old->code;
|
||||
new->state=old->state;
|
||||
new->alternative=move_andbox(old->alternative,new_orbox,new);
|
||||
|
||||
if (first==NULL) first=new;
|
||||
else last->next=new;
|
||||
new->previous=last;
|
||||
new->next=NULL;
|
||||
last=new;
|
||||
old=old->next;
|
||||
}
|
||||
new_orbox->alternatives=first;
|
||||
|
||||
args=NULL;
|
||||
newargs=NULL;
|
||||
while(last!=NULL) {
|
||||
if (last->args==NULL) {
|
||||
args=NULL;
|
||||
newargs=NULL;
|
||||
} else if (args!=last->args) {
|
||||
int y;
|
||||
args=last->args;
|
||||
#if Debug
|
||||
printf("Request args=%d \n",(int) args[0]);
|
||||
#endif
|
||||
newargs=(Cell *)request_memory((args[0])*sizeof(Cell));
|
||||
if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n");
|
||||
newargs[0]=args[0];
|
||||
for(y=1;y<args[0];y++) newargs[y]=move_structures(args[y]);
|
||||
}
|
||||
last->args=newargs;
|
||||
last=last->previous;
|
||||
}
|
||||
|
||||
return(new_orbox);
|
||||
}
|
||||
|
||||
struct AND_BOX *move_andbox(struct AND_BOX *a,struct OR_BOX *parent, struct status_or *alt )
|
||||
{
|
||||
int OLD_VAR_TRAIL_NR;
|
||||
struct AND_BOX *new_andbox;
|
||||
struct PERM_VAR *l;
|
||||
struct EXTERNAL_VAR *old_externals,*externals;
|
||||
|
||||
if (a==NULL) return(NULL);
|
||||
OLD_VAR_TRAIL_NR=beam_VAR_TRAIL_NR;
|
||||
|
||||
new_andbox=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
|
||||
if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n");
|
||||
if (beam_ABX==a) beam_ABX=new_andbox;
|
||||
new_andbox->parent=parent;
|
||||
new_andbox->nr_alternative=alt;
|
||||
new_andbox->level=a->level;
|
||||
new_andbox->side_effects=a->side_effects;
|
||||
new_andbox->suspended=NULL;
|
||||
if (a->suspended) {
|
||||
new_andbox->suspended=addto_suspensions_list(new_andbox,a->suspended->reason);
|
||||
}
|
||||
new_andbox->perms=a->perms;
|
||||
l=a->perms;
|
||||
while(l!=NULL) { /* ainda nao estou a fazer GC nas Var Perm */
|
||||
l->value=move_structures(l->value);
|
||||
l->home=new_andbox;
|
||||
l->suspensions=NULL;
|
||||
l=l->next;
|
||||
}
|
||||
|
||||
old_externals=a->externals;
|
||||
externals=NULL;
|
||||
while(old_externals) {
|
||||
struct EXTERNAL_VAR *e;
|
||||
struct SUSPENSIONS_VAR *s;
|
||||
|
||||
e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE);
|
||||
|
||||
e->next=externals;
|
||||
externals=e;
|
||||
|
||||
e->value=move_structures(old_externals->value);
|
||||
e->var=(struct PERM_VAR *) old_externals->var;
|
||||
//e->var=(struct PERM_VAR *) old_externals->var; CUIDADO QUANDO FIZER GC PERM_VARS
|
||||
|
||||
if (isvar(e->var)) {
|
||||
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE);
|
||||
s->and_box=new_andbox;
|
||||
s->next=e->var->suspensions;
|
||||
e->var->suspensions=s;
|
||||
}
|
||||
old_externals=old_externals->next;
|
||||
}
|
||||
new_andbox->externals=externals;
|
||||
if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n");
|
||||
|
||||
|
||||
/* CUIDADO: Preciso agora de duplicar os vectores das variaveis locais */
|
||||
{ struct status_and *calls;
|
||||
#if !Fast_go
|
||||
Cell **backup=NULL; int i, counted=0,max=1000;
|
||||
backup=(Cell **) malloc(max);
|
||||
#else
|
||||
Cell *backup[1000]; int i, counted=0;
|
||||
#endif
|
||||
|
||||
calls=a->calls;
|
||||
while(calls!=NULL) {
|
||||
if (calls->locals!=NULL) {
|
||||
/* primeiro vou ver se já foi copiado */
|
||||
for(i=0;i<counted;i+=2) {
|
||||
if (backup[i]==calls->locals) {
|
||||
calls->locals=backup[i+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i==counted) { /* afinal ainda nao foi copiado: fazer copia em duas fases*/
|
||||
Cell *c, *newvars, *oldvars; int nr;
|
||||
|
||||
oldvars=calls->locals;
|
||||
nr=oldvars[-1];
|
||||
newvars=request_memory_locals(nr);
|
||||
|
||||
if (beam_varlocals==oldvars) beam_varlocals=newvars;
|
||||
|
||||
calls->locals=newvars;
|
||||
/* primeiro actualizo as variaveis */
|
||||
for(i=0;i<nr;i++) {
|
||||
c=&oldvars[i];
|
||||
if ((Cell *)*c==c) {
|
||||
newvars[i]=(Cell) &newvars[i];
|
||||
*c=newvars[i];
|
||||
} else {
|
||||
newvars[i]= (Cell) *c;
|
||||
*c=(Cell) &newvars[i];
|
||||
}
|
||||
}
|
||||
/* depois copio as estruturas */
|
||||
for(i=0;i<nr;i++) {
|
||||
newvars[i]=move_structures(oldvars[i]);
|
||||
}
|
||||
#if !Fast_go
|
||||
if (max<counted+2) {
|
||||
max+=200;
|
||||
backup=realloc(backup,max);
|
||||
if (backup==NULL) abort_eam("No more memory... realloc in gc \n");
|
||||
}
|
||||
#else
|
||||
if (counted>=998) abort_eam("No more memory... realloc in gc \n");
|
||||
#endif
|
||||
backup[counted]=oldvars;
|
||||
backup[counted+1]=newvars;
|
||||
counted+=2;
|
||||
}
|
||||
}
|
||||
calls=calls->next;
|
||||
}
|
||||
#if !Fast_go
|
||||
free(backup);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
new_andbox->nr_all_calls=a->nr_all_calls;
|
||||
{ struct status_and *first=NULL, *last=NULL,*calls,*calls_new;
|
||||
calls=a->calls;
|
||||
while(calls!=NULL){
|
||||
calls_new=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
||||
if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n");
|
||||
calls_new->code=calls->code;
|
||||
calls_new->state=calls->state;
|
||||
calls_new->locals=calls->locals;
|
||||
if (beam_nr_call==calls) beam_nr_call=calls_new;
|
||||
|
||||
calls_new->call=move_orbox(calls->call,new_andbox,calls_new);
|
||||
|
||||
if (first==NULL) first=calls_new;
|
||||
else last->next=calls_new;
|
||||
calls_new->previous=last;
|
||||
calls_new->next=NULL;
|
||||
last=calls_new;
|
||||
calls=calls->next;
|
||||
}
|
||||
new_andbox->calls=first;
|
||||
}
|
||||
|
||||
return(new_andbox);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else /* used by GC Only on Heap || Keep boxes on same memory */
|
||||
|
||||
void refresh_orbox(struct OR_BOX *o)
|
||||
{
|
||||
struct status_or *old, *last=NULL;
|
||||
Cell *args;
|
||||
|
||||
if (o==NULL) return;
|
||||
|
||||
old=o->alternatives;
|
||||
while(old!=NULL) {
|
||||
refresh_andbox(old->alternative);
|
||||
last=old;
|
||||
old=old->next;
|
||||
}
|
||||
|
||||
args=NULL;
|
||||
while(last!=NULL) {
|
||||
if (last->args==NULL) {
|
||||
args=NULL;
|
||||
}else if (args!=last->args) {
|
||||
int y;
|
||||
args=last->args;
|
||||
for(y=1;y<args[0];y++) {
|
||||
args[y]=move_structures(args[y]);
|
||||
}
|
||||
}
|
||||
last=last->previous;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void refresh_andbox(struct AND_BOX *a)
|
||||
{
|
||||
struct PERM_VAR *l;
|
||||
struct EXTERNAL_VAR *externals;
|
||||
struct status_and *calls;
|
||||
|
||||
if (a==NULL) return;
|
||||
|
||||
l=a->perms;
|
||||
while(l!=NULL) {
|
||||
l->value=move_structures(l->value);
|
||||
l=l->next;
|
||||
}
|
||||
|
||||
externals=a->externals;
|
||||
while(externals) {
|
||||
externals->value=move_structures(externals->value);
|
||||
externals=externals->next;
|
||||
}
|
||||
|
||||
calls=a->calls;
|
||||
while(calls!=NULL) {
|
||||
// if (calls->calls!=NULL) {
|
||||
if (calls->locals!=NULL && ((int) calls->locals[-1]>0) {
|
||||
int nr,i;
|
||||
nr=calls->locals[-1];
|
||||
calls->locals[-1]=-nr;
|
||||
for(i=0;i<nr;i++) {
|
||||
calls->locals[i]=move_structures(calls->locals[i]);
|
||||
}
|
||||
}
|
||||
refresh_orbox(calls->call);
|
||||
// }
|
||||
calls=calls->next;
|
||||
}
|
||||
calls=a->calls;
|
||||
while(calls!=NULL) {
|
||||
if (calls->locals!=NULL && ((int) calls->locals[-1])<0) {
|
||||
int nr;
|
||||
nr=calls->locals[-1];
|
||||
calls->locals[-1]=-nr;
|
||||
}
|
||||
calls=calls->next;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,374 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: eam show abstract machine assembler *
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef BEAM
|
||||
|
||||
#include<stdio.h>
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "eam.h"
|
||||
#include "eamamasm.h"
|
||||
|
||||
void eam_showcode(Cell *code);
|
||||
extern int am_to_inst(Cell inst);
|
||||
|
||||
void eam_showcode(Cell *code)
|
||||
{
|
||||
int n;
|
||||
#define carg1 *(code+1)
|
||||
#define carg2 *(code+2)
|
||||
#define carg3 *(code+3)
|
||||
#define carg4 *(code+4)
|
||||
|
||||
printf("--------------------------------------------------\n");
|
||||
while (1) {
|
||||
n=am_to_inst(*code);
|
||||
printf("%ld->",(long) code);
|
||||
switch(n) {
|
||||
case(_exit_eam):
|
||||
printf("_exit\n");
|
||||
code++;
|
||||
if (*(code)==-1) return;
|
||||
break;
|
||||
case(_top_tree):
|
||||
printf("_top_tree \n");
|
||||
code++;
|
||||
break;
|
||||
case(_scheduler):
|
||||
printf("_scheduler \n");
|
||||
code++;
|
||||
break;
|
||||
case(_prepare_tries):
|
||||
printf("_prepare_tries for %d clauses with arity=%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_prepare_calls ):
|
||||
printf("_prepare_calls %d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_get_var_X_op ):
|
||||
printf("_get_var_X_op X%d, X%d\n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_get_var_Y_op ):
|
||||
printf("_get_var_Y_op X%d, Y%d\n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_get_val_X_op ):
|
||||
printf("_get_val_X_op X%d, X%d\n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_get_val_Y_op ):
|
||||
printf("_get_val_Y_op X%d, Y%d\n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_get_atom_op ):
|
||||
printf("_get_atom_op X%d, %d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_get_list_op ):
|
||||
printf("_get_list_op X%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_get_struct_op ):
|
||||
printf("_get_struct_op X%d, %lX/%d\n",(int) carg1,(unsigned long) carg2,(int) carg3);
|
||||
code+=4;
|
||||
break;
|
||||
case(_unify_void_op ):
|
||||
printf("_unify_void_op\n");
|
||||
code++;
|
||||
break;
|
||||
case(_unify_val_X_op ):
|
||||
printf("_unify_val_X_op X%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_val_Y_op ):
|
||||
printf("_unify_val_Y_op Y%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_var_X_op ):
|
||||
printf("_unify_var_X_op X%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_var_Y_op ):
|
||||
printf("_unify_var_Y_op Y%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_atom_op ):
|
||||
printf("_unify_atom_op 0x%lX\n",(unsigned long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_list_op ):
|
||||
printf("_unify_list_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_unify_last_list_op ):
|
||||
printf("_unify_last_list_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_unify_struct_op ):
|
||||
printf("_unify_struct_op 0x%lX,%d\n",(unsigned long) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_unify_last_struct_op ):
|
||||
printf("_unify_last_struct_op 0x%lX,%d\n",(unsigned long) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_unify_last_atom_op ):
|
||||
printf("_unify_last_atom_op 0x%lX\n",(unsigned long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_local_X_op ):
|
||||
printf("_unify_local_X_op X%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_unify_local_Y_op ):
|
||||
printf("_unify_local_Y_op X%d\n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_put_var_X_op ):
|
||||
printf("_put_var_X_op X%d,X%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_put_var_Y_op ):
|
||||
printf("_put_var_Y_op X%d,Y%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_put_var_P_op ):
|
||||
printf("_put_var_P_op X%d,Y%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_put_val_X_op ):
|
||||
printf("_put_val_X_op X%d,X%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_put_val_Y_op ):
|
||||
printf("_put_val_Y_op X%d,Y%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_put_atom_op ):
|
||||
printf("_put_atom_op X%d, %d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_put_list_op ):
|
||||
printf("_put_list_op X%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_put_struct_op ):
|
||||
printf("_put_struct_op X%d,%d,%d \n",(int) carg1,(int) carg2,(int) carg3);
|
||||
code+=4;
|
||||
break;
|
||||
case(_put_unsafe_op ):
|
||||
printf("_put_unsafe_op X%d, Y%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_write_void ):
|
||||
printf("_write_void \n");
|
||||
code++;
|
||||
break;
|
||||
case(_write_var_X_op ):
|
||||
printf("_write_var_X_op X%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_var_Y_op ):
|
||||
printf("_write_var_Y_op Y%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_var_P_op ):
|
||||
printf("_write_var_P_op Y%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_val_X_op ):
|
||||
printf("_write_val_X_op X%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_val_Y_op ):
|
||||
printf("_write_val_Y_op Y%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_atom_op ):
|
||||
printf("_write_atom_op %d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_list_op ):
|
||||
printf("_write_list_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_write_struct_op ):
|
||||
printf("_write_struct_op %d,%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_write_last_list_op ):
|
||||
printf("_write_last_list_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_write_last_struct_op ):
|
||||
printf("_write_last_struct_op %d,%d \n",(int) carg1,(int) carg2);
|
||||
code+=3;
|
||||
break;
|
||||
case(_write_local_X_op ):
|
||||
printf("_write_local_X_op X%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_write_local_Y_op ):
|
||||
printf("_write_local_Y_op Y%d \n",(int) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_pop_op ):
|
||||
printf("_pop_read_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_jump_op ):
|
||||
printf("_jump_op %ld\n",(long int) carg1);
|
||||
code+=4;
|
||||
break;
|
||||
case(_proceed_op ):
|
||||
printf("_proceed_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_call_op ):
|
||||
printf("_call_op %s/%d \n", ((PredEntry *) carg1)->beamTable->name,((PredEntry *) carg1)->beamTable->arity);
|
||||
code+=2;
|
||||
break;
|
||||
case(_safe_call_op ):
|
||||
printf("_safe_call_op %ld \n",(long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_safe_call_unary_op ):
|
||||
printf("_safe_call_unary_op %ld \n",(long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_safe_call_binary_op ):
|
||||
printf("_safe_call_binary_op %ld \n",(long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
|
||||
case(_only_1_clause_op ):
|
||||
printf("_only_1_clause_op -> Use the same AND_BOX for the %dth clause of predicate %s/%d (Yvars=%d) \n",(int) carg4,((struct Clauses *)carg1)->predi->name,(int) carg2,(int) carg3);
|
||||
code+=4;
|
||||
break;
|
||||
case(_try_me_op ):
|
||||
printf("_try_me_op (not final)\n");
|
||||
code+=5;
|
||||
break;
|
||||
case(_retry_me_op ):
|
||||
printf("_retry_me_op (not final)\n");
|
||||
code+=5;
|
||||
break;
|
||||
case(_trust_me_op ):
|
||||
printf("_trust_me_op (not final)\n");
|
||||
code+=5;
|
||||
break;
|
||||
case(_do_nothing_op ):
|
||||
printf("do_nothing_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_direct_safe_call_op ):
|
||||
printf("_direct_safe_call_op %ld \n",(long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_direct_safe_call_unary_op ):
|
||||
printf("_direct_safe_call_unary_op %ld \n",(long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
case(_direct_safe_call_binary_op ):
|
||||
printf("_direct_safe_call_binary_op %ld \n",(long) carg1);
|
||||
code+=2;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case(_skip_while_var ):
|
||||
printf("_skip_while_var \n");
|
||||
code++;
|
||||
break;
|
||||
case(_wait_while_var ):
|
||||
printf("_wait_while_var \n");
|
||||
code++;
|
||||
break;
|
||||
case(_force_wait ):
|
||||
printf("_force_wait \n");
|
||||
code++;
|
||||
break;
|
||||
case(_write_call ):
|
||||
printf("_write_call \n");
|
||||
code++;
|
||||
break;
|
||||
case(_is_call ):
|
||||
printf("_is_call \n");
|
||||
code++;
|
||||
break;
|
||||
case(_equal_call ):
|
||||
printf("_equal_call \n");
|
||||
code++;
|
||||
break;
|
||||
case(_cut_op ):
|
||||
printf("_cut_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_commit_op ):
|
||||
printf("_commit_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_fail_op ):
|
||||
printf("_fail_op \n");
|
||||
code++;
|
||||
break;
|
||||
|
||||
case(_save_b_X_op ):
|
||||
printf("_save_b_X_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_save_b_Y_op ):
|
||||
printf("_save_b_Y_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_save_appl_X_op ):
|
||||
printf("_save_appl_X_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_save_appl_Y_op ):
|
||||
printf("_save_appl_Y_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_save_pair_X_op ):
|
||||
printf("_save_pair_X_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_save_pair_Y_op ):
|
||||
printf("_save_pair_Y_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_either_op ):
|
||||
printf("_either_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_orelse_op ):
|
||||
printf("_orelse_op \n");
|
||||
code++;
|
||||
break;
|
||||
case(_orlast_op ):
|
||||
printf("_orlast_op \n");
|
||||
code++;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (n!=*code) printf("inst(%d)\n",n);
|
||||
else printf("Label Next Call %d\n",n);
|
||||
code++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* BEAM */
|
|
@ -0,0 +1,478 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: split related functions *
|
||||
*************************************************************************/
|
||||
|
||||
void do_forking_andbox(struct AND_BOX *a);
|
||||
Cell copy_structures(Cell c);
|
||||
void replicate_local_variables(struct AND_BOX *a);
|
||||
struct OR_BOX *copy_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call);
|
||||
struct AND_BOX *copy_andbox(struct AND_BOX *a,struct OR_BOX *parent);
|
||||
|
||||
|
||||
void do_forking_andbox(struct AND_BOX *a)
|
||||
{
|
||||
struct OR_BOX *op,*opp, *new_orbox;
|
||||
struct AND_BOX *ap, *new_andbox;
|
||||
int nr_all_alternatives, nr_all_calls;
|
||||
struct status_and *nr_call,*new_call;
|
||||
struct status_or *nr_alternative, *alternatives, *new_alternatives;
|
||||
|
||||
beam_nr_call_forking++;
|
||||
op=a->parent; /* or box parent */
|
||||
ap=op->parent; /* and box parent */
|
||||
opp=ap->parent; /* or box parent parent */
|
||||
if (opp==NULL) {
|
||||
abort_eam("Forking with orbox parent parent NULL, maybe I'm on top ?????");
|
||||
}
|
||||
|
||||
alternatives=opp->alternatives;
|
||||
nr_all_alternatives=opp->nr_all_alternatives;
|
||||
nr_alternative=ap->nr_alternative;
|
||||
nr_all_calls=ap->nr_all_calls;
|
||||
nr_call=op->nr_call;
|
||||
|
||||
new_andbox=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
|
||||
new_orbox=(struct OR_BOX *) request_memory(ORBOX_SIZE);
|
||||
new_andbox->parent=opp;
|
||||
// new_andbox->nr_alternative=nr_alternative; /* seted after creating a new status_or */
|
||||
new_andbox->nr_all_calls=nr_all_calls;
|
||||
new_andbox->level=ap->level;
|
||||
new_andbox->perms=ap->perms;
|
||||
new_andbox->suspended=NULL;
|
||||
if (ap->suspended) new_andbox->suspended=addto_suspensions_list(new_andbox,ap->suspended->reason);
|
||||
new_andbox->side_effects=ap->side_effects;
|
||||
|
||||
if (ap->externals) {
|
||||
struct EXTERNAL_VAR *old_externals, *list=NULL;
|
||||
old_externals=ap->externals;
|
||||
while (old_externals) {
|
||||
struct EXTERNAL_VAR *e;
|
||||
struct SUSPENSIONS_VAR *s;
|
||||
|
||||
e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE);
|
||||
e->value=old_externals->value;
|
||||
e->var=(struct PERM_VAR *) old_externals->var;
|
||||
e->next=list;
|
||||
list=e;
|
||||
|
||||
if (isvar(e->var)) {
|
||||
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); /* Add and_box to suspension list of var*/
|
||||
s->and_box=new_andbox;
|
||||
s->next=e->var->suspensions;
|
||||
e->var->suspensions=s;
|
||||
}
|
||||
|
||||
old_externals=old_externals->next;
|
||||
}
|
||||
new_andbox->externals=list;
|
||||
} else new_andbox->externals=NULL;
|
||||
|
||||
new_call=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
||||
new_call->call=new_orbox;
|
||||
new_call->locals=nr_call->locals;
|
||||
new_call->code=nr_call->code;
|
||||
new_call->state=WAKE;
|
||||
nr_call->state=WAKE; /* NEW PARA TORNAR A CALL NUM WAKE STATE */
|
||||
|
||||
new_orbox->parent=new_andbox;
|
||||
new_orbox->nr_call=new_call;
|
||||
new_orbox->nr_all_alternatives=1;
|
||||
new_alternatives=a->nr_alternative;
|
||||
new_orbox->alternatives=new_alternatives;
|
||||
|
||||
/* remove andbox from op */
|
||||
op->nr_all_alternatives-=1;
|
||||
if (new_alternatives->previous==NULL) op->alternatives=new_alternatives->next;
|
||||
else new_alternatives->previous->next=new_alternatives->next;
|
||||
if (new_alternatives->next!=NULL) new_alternatives->next->previous=new_alternatives->previous;
|
||||
new_alternatives->next=NULL;
|
||||
new_alternatives->previous=NULL;
|
||||
|
||||
a->parent=new_orbox;
|
||||
|
||||
/* increase the nr_alternatives by 1 in opp or_box parent parent and conect new_andbox*/
|
||||
new_alternatives=(struct status_or *) request_memory(STATUS_OR_SIZE);
|
||||
new_andbox->nr_alternative=new_alternatives;
|
||||
|
||||
new_alternatives->next=nr_alternative;
|
||||
new_alternatives->previous=nr_alternative->previous;
|
||||
if (nr_alternative->previous==NULL) opp->alternatives=new_alternatives;
|
||||
else nr_alternative->previous->next=new_alternatives;
|
||||
nr_alternative->previous=new_alternatives;
|
||||
|
||||
new_alternatives->args=nr_alternative->args;
|
||||
new_alternatives->code=nr_alternative->code;
|
||||
new_alternatives->state=nr_alternative->state;
|
||||
new_alternatives->alternative=new_andbox;
|
||||
|
||||
opp->nr_all_alternatives=nr_all_alternatives+1;
|
||||
|
||||
/* copy and_box ap to new_and-box */
|
||||
{ struct status_and *first=NULL, *last=NULL,*calls,*calls_new;
|
||||
calls=ap->calls;
|
||||
while(calls!=NULL) {
|
||||
if (calls==nr_call) {
|
||||
calls_new=new_call;
|
||||
} else {
|
||||
calls_new=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
||||
calls_new->code=calls->code;
|
||||
calls_new->locals=calls->locals;
|
||||
calls_new->state=calls->state;
|
||||
calls_new->call=copy_orbox(calls->call,new_andbox,calls_new); /* Do a exact copy of the tree*/
|
||||
|
||||
}
|
||||
if (first==NULL) first=calls_new;
|
||||
else last->next=calls_new;
|
||||
calls_new->previous=last;
|
||||
calls_new->next=NULL;
|
||||
last=calls_new;
|
||||
calls=calls->next;
|
||||
}
|
||||
new_andbox->calls=first;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* remove and_box a from suspension list on vars */
|
||||
if (a->externals) {
|
||||
struct EXTERNAL_VAR *e;
|
||||
e=a->externals;
|
||||
while(e) {
|
||||
if (e->var->home->level>=a->parent->parent->level)
|
||||
remove_from_perm_var_suspensions(e->var,a);
|
||||
e=e->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have to create new local vars and refresh the external vars to point to those */
|
||||
|
||||
if (beam_MemGoing==1) {
|
||||
beam_VAR_TRAIL=((Cell *) beam_START_ADDR_BOXES)-1;
|
||||
} else beam_VAR_TRAIL=(Cell *) beam_START_ADDR_HEAP;
|
||||
beam_VAR_TRAIL_NR=0;
|
||||
replicate_local_variables(new_andbox);
|
||||
}
|
||||
|
||||
|
||||
struct OR_BOX *copy_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call)
|
||||
{
|
||||
struct OR_BOX *new_orbox;
|
||||
struct status_or *old,*new,*first=NULL,*last=NULL;
|
||||
|
||||
if (o==NULL) return(NULL);
|
||||
|
||||
new_orbox=(struct OR_BOX *) request_memory(ORBOX_SIZE);
|
||||
new_orbox->parent=parent;
|
||||
new_orbox->nr_call=nr_call;
|
||||
new_orbox->nr_all_alternatives=o->nr_all_alternatives;
|
||||
old=o->alternatives;
|
||||
while(old!=NULL) {
|
||||
new=(struct status_or *) request_memory(STATUS_OR_SIZE);
|
||||
new->args=old->args;
|
||||
new->code=old->code;
|
||||
new->state=old->state;
|
||||
new->alternative=copy_andbox(old->alternative,new_orbox);
|
||||
if (new->alternative!=NULL) new->alternative->nr_alternative=new;
|
||||
|
||||
if (first==NULL) first=new;
|
||||
else last->next=new;
|
||||
new->previous=last;
|
||||
new->next=NULL;
|
||||
last=new;
|
||||
old=old->next;
|
||||
}
|
||||
new_orbox->alternatives=first;
|
||||
|
||||
return(new_orbox);
|
||||
}
|
||||
|
||||
struct AND_BOX *copy_andbox(struct AND_BOX *a,struct OR_BOX *parent)
|
||||
{
|
||||
struct AND_BOX *new_andbox;
|
||||
|
||||
if (a==NULL) return(NULL);
|
||||
|
||||
new_andbox=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
|
||||
new_andbox->parent=parent;
|
||||
// new_andbox->nr_alternative=a->nr_alternative; /* this is seted in the copy_orbox, after calling copy_andbox */
|
||||
new_andbox->nr_all_calls=a->nr_all_calls;
|
||||
new_andbox->level=a->level;
|
||||
new_andbox->perms=a->perms;
|
||||
new_andbox->externals=a->externals;
|
||||
new_andbox->side_effects=a->side_effects;
|
||||
new_andbox->suspended=NULL;
|
||||
if (a->suspended) {
|
||||
new_andbox->suspended=addto_suspensions_list(new_andbox,a->suspended->reason);
|
||||
}
|
||||
|
||||
{ struct status_and *first=NULL, *last=NULL,*calls,*calls_new;
|
||||
calls=a->calls;
|
||||
while(calls!=NULL) {
|
||||
calls_new=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
||||
calls_new->code=calls->code;
|
||||
calls_new->locals=calls->locals;
|
||||
calls_new->state=calls->state;
|
||||
calls_new->call=copy_orbox(calls->call,new_andbox,calls_new); /* Do a exact copy of the tree*/
|
||||
|
||||
if (first==NULL) first=calls_new;
|
||||
else last->next=calls_new;
|
||||
calls_new->previous=last;
|
||||
calls_new->next=NULL;
|
||||
last=calls_new;
|
||||
calls=calls->next;
|
||||
}
|
||||
new_andbox->calls=first;
|
||||
}
|
||||
|
||||
return(new_andbox);
|
||||
}
|
||||
|
||||
|
||||
void replicate_local_variables(struct AND_BOX *a) /* used by fork -ABX is set*/
|
||||
{
|
||||
struct PERM_VAR *l,*new_list;
|
||||
int i,OLD_VAR_TRAIL_NR;
|
||||
struct EXTERNAL_VAR *old_externals,*externals;
|
||||
|
||||
if (a==NULL) return;
|
||||
|
||||
OLD_VAR_TRAIL_NR=beam_VAR_TRAIL_NR;
|
||||
l=a->perms;
|
||||
new_list=NULL;
|
||||
while(l) {
|
||||
struct PERM_VAR *new;
|
||||
Cell *c;
|
||||
|
||||
new=request_permVar(a);
|
||||
new->yapvar=l->yapvar;
|
||||
new->next=new_list;
|
||||
new_list=new;
|
||||
|
||||
c=&l->value;
|
||||
beam_VAR_TRAIL[beam_VAR_TRAIL_NR]=(Cell) c;
|
||||
beam_VAR_TRAIL_NR-=beam_MemGoing;
|
||||
beam_VAR_TRAIL[beam_VAR_TRAIL_NR]=(Cell) *c;
|
||||
beam_VAR_TRAIL_NR-=beam_MemGoing;
|
||||
|
||||
if ((Cell *)*c==c) {
|
||||
new->value=(Cell) &new->value;
|
||||
*c=new->value;
|
||||
} else {
|
||||
new->value= (Cell) *c;
|
||||
*c=(Cell) &new->value;
|
||||
}
|
||||
l=l->next;
|
||||
}
|
||||
a->perms=new_list;
|
||||
l=new_list;
|
||||
while(l) {
|
||||
l->value=copy_structures(l->value);
|
||||
l=l->next;
|
||||
}
|
||||
|
||||
/* At this point all old local vars are pointing to the new local vars */
|
||||
|
||||
if (a==beam_ABX) { /* Nao preciso de criar um novo vector das externals */
|
||||
old_externals=a->externals;
|
||||
while(old_externals) {
|
||||
if (old_externals->var->home->level>=beam_ABX->parent->parent->level) {
|
||||
old_externals->value=copy_structures((Cell ) old_externals->value);
|
||||
old_externals->var=(struct PERM_VAR *) old_externals->var->value;
|
||||
if (isvar(old_externals->var)) {
|
||||
struct SUSPENSIONS_VAR *s;
|
||||
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); /* Add and_box to suspension list of var*/
|
||||
s->and_box=a;
|
||||
s->next=old_externals->var->suspensions;
|
||||
old_externals->var->suspensions=s;
|
||||
}
|
||||
}
|
||||
old_externals=old_externals->next;
|
||||
}
|
||||
} else {
|
||||
|
||||
old_externals=a->externals;
|
||||
externals=NULL;
|
||||
a->externals=NULL;
|
||||
|
||||
while(old_externals) {
|
||||
struct EXTERNAL_VAR *e;
|
||||
struct SUSPENSIONS_VAR *s;
|
||||
|
||||
e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE);
|
||||
e->next=externals;
|
||||
externals=e;
|
||||
|
||||
if (old_externals->var->home->level>=beam_ABX->parent->parent->level) {
|
||||
e->value=copy_structures((Cell ) old_externals->value);
|
||||
e->var=(struct PERM_VAR *) old_externals->var->value;
|
||||
} else {
|
||||
e->value=old_externals->value;
|
||||
e->var=(struct PERM_VAR *) old_externals->var->value;
|
||||
}
|
||||
|
||||
if (isvar(e->var)) {
|
||||
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); /* Add and_box to suspension list of var*/
|
||||
s->and_box=a;
|
||||
s->next=e->var->suspensions;
|
||||
e->var->suspensions=s;
|
||||
}
|
||||
|
||||
old_externals=old_externals->next;
|
||||
}
|
||||
a->externals=externals;
|
||||
}
|
||||
|
||||
|
||||
/* CUIDADO: Preciso agora de duplicar os vectores das variaveis locais */
|
||||
{ struct status_and *calls;
|
||||
#if !Fast_go
|
||||
Cell **backup=NULL; int i, counted=0,max=1000;
|
||||
backup=(Cell **) malloc(max);
|
||||
#else
|
||||
Cell *backup[1000]; int i, counted=0;
|
||||
#endif
|
||||
|
||||
calls=a->calls;
|
||||
while(calls!=NULL) {
|
||||
if (calls->locals!=NULL) {
|
||||
/* primeiro vou ver se já foi copiado */
|
||||
for(i=0;i<counted;i+=2) {
|
||||
if (backup[i]==calls->locals) {
|
||||
calls->locals=backup[i+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i==counted) { /* afinal ainda nao foi copiado: fazer copia em duas fases*/
|
||||
Cell *c, *newvars, *oldvars; int nr;
|
||||
|
||||
oldvars=calls->locals;
|
||||
nr=oldvars[-1];
|
||||
newvars=request_memory_locals_noinit(nr);
|
||||
calls->locals=newvars;
|
||||
/* primeiro actualizo as variaveis */
|
||||
for(i=0;i<nr;i++) {
|
||||
c=&oldvars[i];
|
||||
beam_VAR_TRAIL[beam_VAR_TRAIL_NR]=(Cell) c;
|
||||
beam_VAR_TRAIL_NR-=beam_MemGoing;
|
||||
beam_VAR_TRAIL[beam_VAR_TRAIL_NR]=(Cell) *c;
|
||||
beam_VAR_TRAIL_NR-=beam_MemGoing;
|
||||
|
||||
if ((Cell *)*c==c) {
|
||||
newvars[i]=(Cell) &newvars[i];
|
||||
*c=newvars[i];
|
||||
} else {
|
||||
newvars[i]= (Cell) *c;
|
||||
*c=(Cell) &newvars[i];
|
||||
}
|
||||
}
|
||||
/* depois copio as estruturas */
|
||||
for(i=0;i<nr;i++) {
|
||||
newvars[i]=copy_structures(oldvars[i]);
|
||||
}
|
||||
#if !Fast_go
|
||||
if (max<counted+2) {
|
||||
max+=200;
|
||||
backup=realloc(backup,max);
|
||||
if (backup==NULL) abort_eam("No more memory... realloc in gc \n");
|
||||
}
|
||||
#else
|
||||
if (counted>=998) abort_eam("No more memory... realloc in gc \n");
|
||||
#endif
|
||||
backup[counted]=oldvars;
|
||||
backup[counted+1]=newvars;
|
||||
counted+=2;
|
||||
}
|
||||
}
|
||||
calls=calls->next;
|
||||
}
|
||||
#if !Fast_go
|
||||
free(backup);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* redo the process to the inner boxes */
|
||||
{ struct status_and *calls;
|
||||
|
||||
calls=a->calls;
|
||||
while(calls!=NULL) {
|
||||
|
||||
if (calls->call!=NULL) {
|
||||
register struct OR_BOX *o;
|
||||
register struct status_or *nr;
|
||||
|
||||
o=calls->call;
|
||||
nr=o->alternatives;
|
||||
while(nr!=NULL) {
|
||||
replicate_local_variables(nr->alternative);
|
||||
nr=nr->next;
|
||||
}
|
||||
}
|
||||
calls=calls->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (beam_MemGoing==1) {
|
||||
for(i=OLD_VAR_TRAIL_NR;i>beam_VAR_TRAIL_NR;i-=2) {
|
||||
Cell *c;
|
||||
c=(Cell *) beam_VAR_TRAIL[i];
|
||||
*c=(Cell) beam_VAR_TRAIL[i-1];
|
||||
}
|
||||
} else {
|
||||
for(i=OLD_VAR_TRAIL_NR;i<beam_VAR_TRAIL_NR;i+=2) {
|
||||
Cell *c;
|
||||
c=(Cell *) beam_VAR_TRAIL[i];
|
||||
*c=(Cell) beam_VAR_TRAIL[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
beam_VAR_TRAIL_NR=OLD_VAR_TRAIL_NR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Cell copy_structures(Cell c)
|
||||
{
|
||||
Cell *NewC, *NewH;
|
||||
Cell OldC,LOCAL_OldH;
|
||||
|
||||
OldC=deref((Cell) c);
|
||||
|
||||
if (isvar(OldC)) {
|
||||
return(OldC);
|
||||
}
|
||||
if (isatom(OldC)) {
|
||||
return(OldC);
|
||||
}
|
||||
|
||||
LOCAL_OldH=(Cell) beam_H;
|
||||
NewH=beam_H;
|
||||
if (isappl(OldC)) {
|
||||
int i,arity;
|
||||
|
||||
NewC=(Cell *) repappl(OldC);
|
||||
arity = ((int) ArityOfFunctor((Functor) *NewC));
|
||||
*NewH++=*NewC++;
|
||||
beam_H+=arity+1;
|
||||
for(i=0;i<arity ;i++) {
|
||||
*NewH=copy_structures((Cell) NewC);
|
||||
NewH++;
|
||||
NewC++;
|
||||
}
|
||||
return(absappl(LOCAL_OldH));
|
||||
}
|
||||
/* else if (ispair(c)) { */
|
||||
NewC=(Cell *) reppair(OldC);
|
||||
beam_H+=2;
|
||||
*NewH=copy_structures((Cell) NewC);
|
||||
NewC++;
|
||||
NewH++;
|
||||
*NewH=copy_structures((Cell) NewC);
|
||||
return(abspair(LOCAL_OldH));
|
||||
}
|
|
@ -0,0 +1,588 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: abstract machine assembler *
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef BEAM
|
||||
|
||||
#include "Yap.h"
|
||||
#include "compile.h"
|
||||
#include "clause.h"
|
||||
#include "eam.h"
|
||||
#include "eamamasm.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
Cell *inst_code;
|
||||
int pass=0;
|
||||
Cell *labels[1000];
|
||||
|
||||
Cell *Code_Start;
|
||||
Cell Area_Code[200000];
|
||||
Cell area_code=0;
|
||||
|
||||
extern Cell inst_am(int n);
|
||||
void emit_inst(long int i);
|
||||
void emit_par(long int i);
|
||||
void emit_upar(Cell i);
|
||||
Cell *get_addr(void);
|
||||
int Is_X_Var(Ventry *ve);
|
||||
int Is_P_Var(Ventry *ve);
|
||||
int X_Var(Ventry *ve);
|
||||
int Y_Var(Ventry *ve);
|
||||
void eam_pass(CInstr *ppc);
|
||||
Cell *eam_assemble(CInstr *code);
|
||||
int next_not_nop_inst(CInstr *ppc);
|
||||
extern void *alloc_mem(Cell);
|
||||
|
||||
void emit_inst(long int i)
|
||||
{
|
||||
if (pass) *inst_code=inst_am(i);
|
||||
inst_code++;
|
||||
}
|
||||
|
||||
void emit_par(long int i)
|
||||
{
|
||||
if (pass) *inst_code=i;
|
||||
inst_code++;
|
||||
}
|
||||
|
||||
void emit_upar(Cell i)
|
||||
{
|
||||
if (pass) *inst_code=i;
|
||||
inst_code++;
|
||||
}
|
||||
|
||||
|
||||
Cell *get_addr(void)
|
||||
{
|
||||
return(inst_code);
|
||||
}
|
||||
|
||||
|
||||
int Is_P_Var(Ventry *ve)
|
||||
{
|
||||
if (ve->FirstOfVE>0) return (1); /* var aparece pela primeira no corpo da clausula */
|
||||
return(0);
|
||||
}
|
||||
|
||||
int Is_X_Var(Ventry *ve)
|
||||
{
|
||||
if (ve->KindOfVE == PermVar) return(0);
|
||||
if (ve->KindOfVE == VoidVar) return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
int X_Var(Ventry *ve)
|
||||
{
|
||||
int var;
|
||||
|
||||
if (ve->KindOfVE == PermVar || ve->KindOfVE == VoidVar ) {
|
||||
printf("Erro no tipo de variavel X ->eamamas.c \n");
|
||||
exit(1);
|
||||
}
|
||||
var = ((ve->NoOfVE) & MaskVarAdrs);
|
||||
|
||||
return (var);
|
||||
}
|
||||
|
||||
extern int nperm;
|
||||
|
||||
int Y_Var(Ventry *ve)
|
||||
{
|
||||
int var;
|
||||
if (ve->KindOfVE != PermVar) {
|
||||
printf("Erro no tipo de variavel Y ->eamamas.c \n");
|
||||
exit(1);
|
||||
}
|
||||
var = ((ve->NoOfVE) & MaskVarAdrs);
|
||||
return (var);
|
||||
}
|
||||
|
||||
|
||||
int next_not_nop_inst(CInstr *ppc) {
|
||||
while(ppc) {
|
||||
if ((int) ppc->op!=nop_op) return ((int) ppc->op);
|
||||
ppc = ppc->nextInst;
|
||||
}
|
||||
return exit_op;
|
||||
}
|
||||
|
||||
void eam_pass(CInstr *ppc)
|
||||
{
|
||||
int alloc_found=0;
|
||||
int body=0;
|
||||
|
||||
while (ppc) {
|
||||
switch ((int) ppc->op) {
|
||||
|
||||
case get_var_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_get_var_X_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_get_var_Y_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
case get_val_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_get_val_X_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_get_val_Y_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
|
||||
case get_num_op:
|
||||
case get_atom_op:
|
||||
emit_inst(_get_atom_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
|
||||
case get_list_op:
|
||||
emit_inst(_get_list_op);
|
||||
emit_par(ppc->new1);
|
||||
break;
|
||||
case get_struct_op:
|
||||
emit_inst(_get_struct_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(ArityOfFunctor((Functor ) ppc->new4));
|
||||
break;
|
||||
|
||||
case unify_last_local_op:
|
||||
case unify_local_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_unify_local_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_unify_local_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
|
||||
case unify_last_val_op:
|
||||
case unify_val_op:
|
||||
if (((Ventry *)(ppc->new4))->KindOfVE!=VoidVar) {
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_unify_val_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_unify_val_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
|
||||
}
|
||||
} else { emit_inst(_unify_void_op); }
|
||||
break;
|
||||
|
||||
case unify_last_var_op:
|
||||
case unify_var_op:
|
||||
if (((Ventry *)(ppc->new4))->KindOfVE!=VoidVar) {
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_unify_var_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_unify_var_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
} else { emit_inst(_unify_void_op); }
|
||||
break;
|
||||
|
||||
case unify_last_atom_op:
|
||||
case unify_last_num_op:
|
||||
emit_inst(_unify_last_atom_op);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
case unify_num_op:
|
||||
case unify_atom_op:
|
||||
emit_inst(_unify_atom_op);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
case unify_list_op:
|
||||
emit_inst(_unify_list_op);
|
||||
break;
|
||||
case unify_last_list_op:
|
||||
emit_inst(_unify_last_list_op);
|
||||
break;
|
||||
case unify_struct_op:
|
||||
emit_inst(_unify_struct_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(ArityOfFunctor((Functor )ppc->new4));
|
||||
break;
|
||||
case unify_last_struct_op:
|
||||
emit_inst(_unify_last_struct_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(ArityOfFunctor((Functor )ppc->new4));
|
||||
break;
|
||||
|
||||
case put_unsafe_op:
|
||||
/*
|
||||
printf("Got a put_unsafe...\n");
|
||||
emit_inst(_put_unsafe_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
break;
|
||||
*/
|
||||
case put_val_op:
|
||||
/*
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_put_val_X_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
break;
|
||||
} else {
|
||||
emit_inst(_put_val_Y_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case put_var_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_put_var_X_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
if (Is_P_Var((Ventry *) ppc->new4)) emit_inst(_put_var_P_op);
|
||||
else emit_inst(_put_var_Y_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
|
||||
case put_num_op:
|
||||
case put_atom_op:
|
||||
emit_inst(_put_atom_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
case put_list_op:
|
||||
emit_inst(_put_list_op);
|
||||
emit_par(ppc->new1);
|
||||
break;
|
||||
case put_struct_op:
|
||||
emit_inst(_put_struct_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(ArityOfFunctor((Functor )ppc->new4));
|
||||
break;
|
||||
|
||||
case write_local_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_write_local_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_write_local_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
|
||||
case write_val_op:
|
||||
if (((Ventry *)(ppc->new4))->KindOfVE!=VoidVar) {
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_write_val_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_write_val_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
} else emit_inst(_write_void);
|
||||
break;
|
||||
|
||||
case write_var_op:
|
||||
if (((Ventry *)(ppc->new4))->KindOfVE!=VoidVar) {
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_write_var_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
if (Is_P_Var((Ventry *) ppc->new4)) emit_inst(_write_var_P_op);
|
||||
else emit_inst(_write_var_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
} else emit_inst(_write_void);
|
||||
break;
|
||||
|
||||
|
||||
case write_num_op:
|
||||
case write_atom_op:
|
||||
emit_inst(_write_atom_op);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
case write_list_op:
|
||||
emit_inst(_write_list_op);
|
||||
break;
|
||||
case write_last_list_op:
|
||||
emit_inst(_write_last_list_op);
|
||||
break;
|
||||
case write_struct_op:
|
||||
emit_inst(_write_struct_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(ArityOfFunctor((Functor )ppc->new4));
|
||||
break;
|
||||
case write_last_struct_op:
|
||||
emit_inst(_write_last_struct_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(ArityOfFunctor((Functor )ppc->new4));
|
||||
break;
|
||||
|
||||
case fail_op:
|
||||
emit_inst(_fail_op);
|
||||
break;
|
||||
case cutexit_op:
|
||||
printf("cutexit \n");
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case cut_op:
|
||||
emit_inst(_cut_op);
|
||||
break;
|
||||
case commit_op:
|
||||
emit_inst(_commit_op);
|
||||
break;
|
||||
|
||||
case procceed_op:
|
||||
emit_inst(_proceed_op);
|
||||
break;
|
||||
case pop_op:
|
||||
emit_inst(_pop_op);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
case save_b_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_save_b_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_save_b_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
case save_pair_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_save_pair_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_save_pair_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
case save_appl_op:
|
||||
if (Is_X_Var((Ventry *) ppc->new4)) {
|
||||
emit_inst(_save_appl_X_op);
|
||||
emit_par(X_Var((Ventry *) ppc->new4));
|
||||
} else {
|
||||
emit_inst(_save_appl_Y_op);
|
||||
emit_par(Y_Var((Ventry *) ppc->new4));
|
||||
}
|
||||
break;
|
||||
case std_base_op:
|
||||
emit_inst(_std_base+ppc->new4);
|
||||
break;
|
||||
|
||||
case safe_call_op:
|
||||
if (ppc->new1==1) {
|
||||
emit_inst(_safe_call_unary_op);
|
||||
} else if (ppc->new1==2) {
|
||||
emit_inst(_safe_call_binary_op);
|
||||
} else {
|
||||
emit_inst(_safe_call_op);
|
||||
}
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
|
||||
case direct_safe_call_op:
|
||||
if (ppc->new1==1) {
|
||||
emit_inst(_direct_safe_call_unary_op);
|
||||
} else if (ppc->new1==2) {
|
||||
emit_inst(_direct_safe_call_binary_op);
|
||||
} else {
|
||||
emit_inst(_direct_safe_call_op);
|
||||
}
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
|
||||
case call_op:
|
||||
emit_inst(_call_op);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
|
||||
case skip_while_var_op:
|
||||
emit_inst(_skip_while_var);
|
||||
break;
|
||||
case wait_while_var_op:
|
||||
emit_inst(_wait_while_var);
|
||||
break;
|
||||
case force_wait_op:
|
||||
emit_inst(_force_wait);
|
||||
break;
|
||||
case write_op:
|
||||
if (ppc->new1=='\n') {
|
||||
static Atom a=NULL;
|
||||
if (a==NULL) a=Yap_LookupAtom("\n");
|
||||
emit_inst(_put_atom_op);
|
||||
emit_par(1);
|
||||
emit_par((Cell) MkAtomTerm(a));
|
||||
}
|
||||
emit_inst(_write_call);
|
||||
break;
|
||||
case is_op:
|
||||
emit_inst(_is_call);
|
||||
break;
|
||||
case equal_op:
|
||||
emit_inst(_equal_call);
|
||||
break;
|
||||
|
||||
case either_op:
|
||||
emit_inst(_either_op);
|
||||
emit_par(ppc->new1);
|
||||
emit_upar((Cell) Code_Start+ (Cell) labels[ppc->new4]);
|
||||
break;
|
||||
case orelse_op:
|
||||
emit_inst(_orelse_op);
|
||||
emit_upar((Cell) Code_Start+ (Cell) labels[ppc->new4]);
|
||||
break;
|
||||
case orlast_op:
|
||||
emit_inst(_orlast_op);
|
||||
break;
|
||||
|
||||
case create_first_box_op:
|
||||
case create_box_op:
|
||||
case create_last_box_op:
|
||||
emit_upar((Cell) Code_Start+ (Cell) labels[ppc->new4]);
|
||||
alloc_found=1;
|
||||
break;
|
||||
|
||||
case remove_box_op:
|
||||
case remove_last_box_op:
|
||||
break;
|
||||
|
||||
case jump_op:
|
||||
emit_inst(_jump_op);
|
||||
emit_upar((Cell) Code_Start+ (Cell) labels[ppc->new4]);
|
||||
break;
|
||||
case label_op:
|
||||
if (pass==0) labels[ppc->new4] = get_addr();
|
||||
break;
|
||||
|
||||
case run_op:
|
||||
/* se ficar vazio, retirar no eam_am.c o +5 das linhas pc=clause->code+5 no only_1_clause e no call */
|
||||
emit_inst(_try_me_op);
|
||||
emit_par(0);
|
||||
emit_par(0);
|
||||
emit_par(0);
|
||||
emit_par(0);
|
||||
break;
|
||||
|
||||
case only_1_clause_op:
|
||||
emit_inst(_only_1_clause_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(((struct Clauses *)ppc->new4)->predi->arity);
|
||||
emit_par(((struct Clauses *)ppc->new4)->nr_vars);
|
||||
emit_par(0); /* Nr da alternativa */
|
||||
break;
|
||||
case try_me_op:
|
||||
emit_inst(_try_me_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(((struct Clauses *)ppc->new4)->predi->arity);
|
||||
emit_par(((struct Clauses *)ppc->new4)->nr_vars);
|
||||
emit_par(0); /* Nr da alternativa */
|
||||
break;
|
||||
case retry_me_op:
|
||||
emit_inst(_retry_me_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(((struct Clauses *)ppc->new4)->predi->arity);
|
||||
emit_par(((struct Clauses *)ppc->new4)->nr_vars);
|
||||
emit_par(ppc->new1);
|
||||
break;
|
||||
case trust_me_op:
|
||||
emit_inst(_trust_me_op);
|
||||
emit_par(ppc->new4);
|
||||
emit_par(((struct Clauses *)ppc->new4)->predi->arity);
|
||||
emit_par(((struct Clauses *)ppc->new4)->nr_vars);
|
||||
emit_par(ppc->new1);
|
||||
break;
|
||||
|
||||
case body_op:
|
||||
if (next_not_nop_inst(ppc->nextInst)==procceed_op) {
|
||||
//emit_inst(_proceed_op);
|
||||
break;
|
||||
} else if (next_not_nop_inst(ppc->nextInst)==fail_op) {
|
||||
//emit_inst(_fail_op);
|
||||
break;
|
||||
}
|
||||
if (ppc->new4!=0) {
|
||||
emit_inst(_prepare_calls);
|
||||
emit_par(ppc->new4); /* nr_calls */
|
||||
}
|
||||
body=1;
|
||||
break;
|
||||
|
||||
case prepare_tries:
|
||||
emit_inst(_prepare_tries);
|
||||
emit_par(ppc->new1);
|
||||
emit_par(ppc->new4);
|
||||
break;
|
||||
|
||||
case exit_op:
|
||||
emit_inst(_exit_eam);
|
||||
break;
|
||||
|
||||
case mark_initialized_pvars_op:
|
||||
break;
|
||||
case fetch_args_for_bccall:
|
||||
case bccall_op:
|
||||
printf("[ Fatal Error: fetch and bccall instructions not supported ]\n");
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case endgoal_op:
|
||||
case nop_op:
|
||||
case name_op:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (pass) {
|
||||
printf("[ Sorry, there is at least one unsupported instruction in your code... %3d] %d\n",ppc->op,exit_op);
|
||||
printf("[ please note that beam still does not support a lot of builtins ]\n");
|
||||
}
|
||||
emit_inst(_fail_op);
|
||||
|
||||
}
|
||||
ppc = ppc->nextInst;
|
||||
}
|
||||
emit_inst(_exit_eam);
|
||||
emit_par(-1);
|
||||
}
|
||||
|
||||
|
||||
Cell *eam_assemble(CInstr *code)
|
||||
{
|
||||
|
||||
Code_Start=0;
|
||||
pass=0;
|
||||
inst_code=0;
|
||||
eam_pass(code);
|
||||
|
||||
pass=1;
|
||||
Code_Start=alloc_mem((Cell) inst_code);
|
||||
inst_code=Code_Start;
|
||||
eam_pass(code);
|
||||
|
||||
return(Code_Start);
|
||||
}
|
||||
|
||||
|
||||
#endif /* BEAM */
|
|
@ -0,0 +1,130 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: abstract machine instructions *
|
||||
*************************************************************************/
|
||||
|
||||
#define _exit_eam 0
|
||||
#define _top_tree 1
|
||||
#define _scheduler 2
|
||||
#define _prepare_tries 3
|
||||
#define _prepare_calls 4
|
||||
|
||||
#define _first_get _prepare_calls
|
||||
#define _get_var_X_op _first_get+1
|
||||
#define _get_var_Y_op _first_get+2
|
||||
#define _get_val_X_op _first_get+3
|
||||
#define _get_val_Y_op _first_get+4
|
||||
#define _get_atom_op _first_get+5
|
||||
#define _get_list_op _first_get+6
|
||||
#define _get_struct_op _first_get+7
|
||||
|
||||
#define _first_unify _get_struct_op
|
||||
#define _unify_void_op _first_unify + 1
|
||||
#define _unify_val_X_op _first_unify + 2
|
||||
#define _unify_val_Y_op _first_unify + 3
|
||||
#define _unify_var_X_op _first_unify + 4
|
||||
#define _unify_var_Y_op _first_unify + 5
|
||||
#define _unify_atom_op _first_unify + 6
|
||||
#define _unify_list_op _first_unify + 7
|
||||
#define _unify_last_list_op _first_unify + 8
|
||||
#define _unify_struct_op _first_unify + 9
|
||||
#define _unify_last_struct_op _first_unify + 10
|
||||
#define _unify_last_atom_op _first_unify + 11
|
||||
#define _unify_local_X_op _first_unify + 12
|
||||
#define _unify_local_Y_op _first_unify + 13
|
||||
|
||||
#define _first_put _unify_local_Y_op
|
||||
#define _put_var_X_op _first_put + 1
|
||||
#define _put_var_Y_op _first_put + 2
|
||||
#define _put_val_X_op _first_put + 3
|
||||
#define _put_val_Y_op _first_put + 4
|
||||
#define _put_atom_op _first_put + 5
|
||||
#define _put_list_op _first_put + 6
|
||||
#define _put_struct_op _first_put + 7
|
||||
#define _put_unsafe_op _first_put + 8
|
||||
#define _put_var_P_op _first_put + 9
|
||||
|
||||
#define _first_write _put_var_P_op
|
||||
#define _write_void _first_write + 1
|
||||
#define _write_var_X_op _first_write + 2
|
||||
#define _write_var_Y_op _first_write + 3
|
||||
#define _write_val_X_op _first_write + 4
|
||||
#define _write_val_Y_op _first_write + 5
|
||||
#define _write_atom_op _first_write + 6
|
||||
#define _write_list_op _first_write + 7
|
||||
#define _write_struct_op _first_write + 8
|
||||
#define _write_last_list_op _first_write + 9
|
||||
#define _write_last_struct_op _first_write + 10
|
||||
#define _write_local_X_op _first_write + 11
|
||||
#define _write_local_Y_op _first_write + 12
|
||||
#define _write_var_P_op _first_write + 13
|
||||
|
||||
#define _geral _write_var_P_op
|
||||
#define _pop_op _geral + 1
|
||||
#define _jump_op _geral + 2
|
||||
#define _proceed_op _geral + 3
|
||||
#define _call_op _geral + 4
|
||||
#define _safe_call_op _geral + 5
|
||||
#define _safe_call_unary_op _geral + 6
|
||||
#define _safe_call_binary_op _geral + 7
|
||||
#define _only_1_clause_op _geral + 8
|
||||
#define _try_me_op _geral + 9
|
||||
#define _retry_me_op _geral + 10
|
||||
#define _trust_me_op _geral + 11
|
||||
#define _do_nothing_op _geral + 12
|
||||
#define _direct_safe_call_op _geral + 13
|
||||
#define _direct_safe_call_unary_op _geral + 14
|
||||
#define _direct_safe_call_binary_op _geral + 15
|
||||
#define _skip_while_var _geral + 16
|
||||
#define _wait_while_var _geral + 17
|
||||
#define _force_wait _geral + 18
|
||||
#define _write_call _geral + 19
|
||||
#define _is_call _geral + 20
|
||||
#define _equal_call _geral + 21
|
||||
#define _cut_op _geral + 22
|
||||
#define _commit_op _geral + 23
|
||||
#define _fail_op _geral + 24
|
||||
|
||||
#define _others _fail_op
|
||||
#define _save_b_X_op _others + 1
|
||||
#define _save_b_Y_op _others + 2
|
||||
#define _comit_b_X_op _others + 3
|
||||
#define _comit_b_Y_op _others + 4
|
||||
#define _save_appl_X_op _others + 5
|
||||
#define _save_appl_Y_op _others + 6
|
||||
#define _save_pair_X_op _others + 7
|
||||
#define _save_pair_Y_op _others + 8
|
||||
#define _either_op _others + 9
|
||||
#define _orelse_op _others + 10
|
||||
#define _orlast_op _others + 11
|
||||
|
||||
#define _std_base _orlast_op
|
||||
#define _p_atom (_std_base+1)
|
||||
#define _p_atomic (_std_base+2)
|
||||
#define _p_equal (_std_base+3)
|
||||
#define _p_integer (_std_base+4)
|
||||
#define _p_nonvar (_std_base+5)
|
||||
#define _p_number (_std_base+6)
|
||||
#define _p_var (_std_base+7)
|
||||
#define _p_db_ref (_std_base+8)
|
||||
#define _p_primitive (_std_base+9)
|
||||
#define _p_cut_by (_std_base+10)
|
||||
#define _p_save_by (_std_base+11)
|
||||
#define _p_succ (_std_base+12)
|
||||
#define _p_predc (_std_base+13)
|
||||
#define _p_plus (_std_base+14)
|
||||
#define _p_minus (_std_base+15)
|
||||
#define _p_times (_std_base+16)
|
||||
#define _p_div (_std_base+17)
|
||||
#define _p_dif (_std_base+18)
|
||||
#define _p_eq (_std_base+19)
|
||||
#define _p_arg (_std_base+20)
|
||||
#define _p_functor (_std_base+21)
|
||||
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: indexing related functions *
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef BEAM
|
||||
|
||||
#include "Yap.h"
|
||||
#include "compile.h"
|
||||
#include "clause.h"
|
||||
#include "eam.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
CInstr *StartCode,*inter_code;
|
||||
|
||||
extern void eam_showcode(Cell *code);
|
||||
extern unsigned int index_of_hash_table_atom(Cell c, int nr);
|
||||
extern unsigned int index_of_hash_table_appl(Cell c, int nr);
|
||||
|
||||
extern CInstr *emit_new(int o, int r1,CELL r4);
|
||||
Cell *gera_codigo_try(struct Predicates *);
|
||||
Cell *gera_codigo_try_list(struct Predicates *predi);
|
||||
Cell *gera_codigo_try_only_vars(struct Predicates *predi);
|
||||
struct HASH_TABLE **gera_codigo_try_atom(struct Predicates *predi);
|
||||
struct HASH_TABLE **gera_codigo_try_functor(struct Predicates *predi);
|
||||
extern Cell *eam_assemble(CInstr *code);
|
||||
void do_eam_indexing(struct Predicates *p);
|
||||
void ver_predicados(struct Predicates *p);
|
||||
int exists_on_table(Cell a,struct HASH_TABLE **table, int i);
|
||||
|
||||
int exists_on_table(Cell a,struct HASH_TABLE **table, int i)
|
||||
{
|
||||
struct HASH_TABLE *t;
|
||||
|
||||
t=table[i];
|
||||
|
||||
while(t) {
|
||||
if (t->value==a) return(1);
|
||||
|
||||
t=t->next;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
Cell *gera_codigo_try(struct Predicates *predi) /* gerar os try's para o predicado i */
|
||||
{
|
||||
struct Clauses *c;
|
||||
int nr=0;
|
||||
|
||||
StartCode=NULL;
|
||||
inter_code=NULL;
|
||||
c=predi->first;
|
||||
|
||||
emit_new(prepare_tries,predi->nr_alt,predi->arity);
|
||||
if (predi->nr_alt==1) {
|
||||
emit_new(only_1_clause_op,0,(unsigned long) c);
|
||||
} else if (predi->nr_alt>1) {
|
||||
while(c!=NULL) {
|
||||
if (nr+1==predi->nr_alt) emit_new(trust_me_op,nr,(unsigned long) c);
|
||||
else if (nr==0) emit_new(try_me_op,predi->nr_alt,(unsigned long) c);
|
||||
else emit_new(retry_me_op,nr,(unsigned long) c);
|
||||
|
||||
c=c->next;
|
||||
nr++;
|
||||
}
|
||||
} else {
|
||||
emit_new(fail_op,0,0);
|
||||
}
|
||||
|
||||
return(eam_assemble(StartCode));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Cell *gera_codigo_try_list(struct Predicates *predi) /* gerar os try's para o predicado i */
|
||||
{
|
||||
struct Clauses *c;
|
||||
int nr=0,nr_preds;
|
||||
|
||||
StartCode=NULL;
|
||||
inter_code=NULL;
|
||||
nr_preds=predi->idx_list+predi->idx_var;
|
||||
c=predi->first;
|
||||
|
||||
emit_new(prepare_tries,nr_preds,predi->arity);
|
||||
if (nr_preds>=1) {
|
||||
while(c!=NULL) {
|
||||
if (c->predi==predi && (c->idx==Lista || c->idx==Variavel)) {
|
||||
if (nr_preds==1) {
|
||||
emit_new(only_1_clause_op,0,(unsigned long) c);
|
||||
break;
|
||||
}
|
||||
if (nr+1==nr_preds) { emit_new(trust_me_op,nr,(unsigned long) c); break; }
|
||||
else if (nr==0) emit_new(try_me_op,nr_preds,(unsigned long) c);
|
||||
else emit_new(retry_me_op,nr,(unsigned long) c);
|
||||
nr++;
|
||||
}
|
||||
c=c->next;
|
||||
}
|
||||
} else {
|
||||
emit_new(fail_op,0,0);
|
||||
}
|
||||
|
||||
return(eam_assemble(StartCode));
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct HASH_TABLE **gera_codigo_try_atom(struct Predicates *predi)
|
||||
{
|
||||
int j,nr_preds,nr_atoms;
|
||||
struct HASH_TABLE **table;
|
||||
struct HASH_TABLE *t;
|
||||
struct Clauses *cla;
|
||||
|
||||
nr_atoms=predi->idx_atom;
|
||||
nr_preds=nr_atoms+predi->idx_var;
|
||||
table=malloc(sizeof(struct HASH_TABLE *)*(nr_atoms+1));
|
||||
for (j=0;j<=nr_atoms;j++) table[j]=NULL;
|
||||
|
||||
cla=predi->first;
|
||||
while(cla) {
|
||||
if (cla->idx==Constante) {
|
||||
Cell a;
|
||||
unsigned int index;
|
||||
int nr;
|
||||
|
||||
a=cla->val;
|
||||
if (a && nr_atoms) {
|
||||
index=index_of_hash_table_atom(a,nr_atoms);
|
||||
} else index=nr_atoms;
|
||||
|
||||
/* printf("nr_atoms=%d index=%d -> 0x%X \n",nr_atoms,index,a); */
|
||||
|
||||
if (!exists_on_table(a,table,index)) {
|
||||
CInstr *first,*last=NULL,*prepare;
|
||||
struct Clauses *cla2;
|
||||
|
||||
/* printf("a gerar codigo para atom index=%d value %ld\n",index,cla->val); */
|
||||
t=malloc(sizeof(struct HASH_TABLE));
|
||||
t->next=table[index];
|
||||
table[index]=t;
|
||||
t->value=a;
|
||||
|
||||
StartCode=NULL;
|
||||
inter_code=NULL;
|
||||
prepare=emit_new(prepare_tries,0,predi->arity);
|
||||
cla2=predi->first;
|
||||
nr=0;
|
||||
first=NULL;
|
||||
while(cla2) {
|
||||
if ((cla2->idx==Constante && cla2->val==a) || cla2->idx==Variavel) {
|
||||
last=emit_new(retry_me_op,nr,(unsigned long) cla2);
|
||||
if (first==NULL) first=last;
|
||||
nr++;
|
||||
}
|
||||
cla2=cla2->next;
|
||||
}
|
||||
prepare->new1=nr;
|
||||
if (first==last) {
|
||||
first->op=only_1_clause_op;
|
||||
} else {
|
||||
first->op=try_me_op;
|
||||
last->op=trust_me_op;
|
||||
}
|
||||
t->code=eam_assemble(StartCode);
|
||||
}
|
||||
}
|
||||
cla=cla->next;
|
||||
}
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
struct HASH_TABLE **gera_codigo_try_functor(struct Predicates *predi) /*gerar os try's para o predicado i*/
|
||||
{
|
||||
int j,nr_preds,nr_appls;
|
||||
struct HASH_TABLE **table;
|
||||
struct HASH_TABLE *t;
|
||||
struct Clauses *cla;
|
||||
|
||||
nr_appls=predi->idx_functor;
|
||||
nr_preds=nr_appls+predi->idx_var;
|
||||
table=malloc(sizeof(struct HASH_TABLE *)*(nr_appls+1));
|
||||
for (j=0;j<=nr_appls;j++) table[j]=NULL;
|
||||
|
||||
cla=predi->first;
|
||||
while(cla) {
|
||||
if (cla->idx==Estrutura) {
|
||||
Cell a;
|
||||
long int index;
|
||||
int nr;
|
||||
|
||||
a=cla->val;
|
||||
if (a && nr_appls) {
|
||||
index=index_of_hash_table_appl(a,nr_appls);
|
||||
} else index=nr_appls;
|
||||
|
||||
if (!exists_on_table(a,table,index)) {
|
||||
CInstr *first,*last=NULL,*prepare;
|
||||
struct Clauses *cla2;
|
||||
|
||||
/* printf("a gerar codigo para appl index=%d value %ld\n",index,cla->val); */
|
||||
t=malloc(sizeof(struct HASH_TABLE));
|
||||
t->next=table[index];
|
||||
table[index]=t;
|
||||
t->value=a;
|
||||
|
||||
StartCode=NULL;
|
||||
inter_code=NULL;
|
||||
prepare=emit_new(prepare_tries,0,predi->arity);
|
||||
cla2=predi->first;
|
||||
nr=0;
|
||||
first=NULL;
|
||||
while(cla2) {
|
||||
if ((cla2->idx==Estrutura && cla2->val==a) || cla2->idx==Variavel) {
|
||||
last=emit_new(retry_me_op,nr,(unsigned long) cla2);
|
||||
if (first==NULL) first=last;
|
||||
nr++;
|
||||
}
|
||||
cla2=cla2->next;
|
||||
}
|
||||
prepare->new1=nr;
|
||||
if (first==last) {
|
||||
first->op=only_1_clause_op;
|
||||
} else {
|
||||
first->op=try_me_op;
|
||||
last->op=trust_me_op;
|
||||
}
|
||||
t->code=eam_assemble(StartCode);
|
||||
}
|
||||
}
|
||||
cla=cla->next;
|
||||
}
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Cell *gera_codigo_try_only_vars(struct Predicates *predi) /* gerar os try's de Vars para o predicado i */
|
||||
{
|
||||
struct Clauses *c;
|
||||
int nr=0,nr_preds;
|
||||
|
||||
StartCode=NULL;
|
||||
inter_code=NULL;
|
||||
nr_preds=predi->idx_var;
|
||||
c=predi->first;
|
||||
|
||||
emit_new(prepare_tries,nr_preds,predi->arity);
|
||||
if (nr_preds>=1) {
|
||||
while(c!=NULL) {
|
||||
if (c->predi==predi && c->idx==Variavel) {
|
||||
if (nr_preds==1) {
|
||||
emit_new(only_1_clause_op,0,(unsigned long) c);
|
||||
break;
|
||||
}
|
||||
if (nr+1==nr_preds) { emit_new(trust_me_op,nr,(unsigned long) c); break; }
|
||||
else if (nr==0) emit_new(try_me_op,nr_preds,(unsigned long) c);
|
||||
else emit_new(retry_me_op,nr,(unsigned long) c);
|
||||
nr++;
|
||||
}
|
||||
c=c->next;
|
||||
}
|
||||
} else {
|
||||
emit_new(fail_op,0,0);
|
||||
}
|
||||
|
||||
return(eam_assemble(StartCode));
|
||||
}
|
||||
|
||||
|
||||
void do_eam_indexing(struct Predicates *p)
|
||||
{
|
||||
p->code=gera_codigo_try(p);
|
||||
p->idx=-1;
|
||||
|
||||
if (p->arity && (p->idx_list || p->idx_atom || p->idx_functor)) {
|
||||
p->vars=gera_codigo_try_only_vars(p);
|
||||
p->list=gera_codigo_try_list(p);
|
||||
p->functor=gera_codigo_try_functor(p);
|
||||
p->atom=gera_codigo_try_atom(p);
|
||||
p->idx=1;
|
||||
}
|
||||
|
||||
if((Print_Code & 4) && (Print_Code & 8)) {
|
||||
printf("General Case :\n");
|
||||
eam_showcode(p->code);
|
||||
}
|
||||
|
||||
if (Print_Code & 1) ver_predicados(p);
|
||||
}
|
||||
|
||||
|
||||
void ver_predicados(struct Predicates *p)
|
||||
{
|
||||
struct Clauses *c; int i=0;
|
||||
|
||||
printf("Predicado %s:%d (ES=%d) tem %d clausulas do tipo V=%d L=%d A=%d F=%d \n",p->name,p->arity,p->eager_split,p->nr_alt,p->idx_var,p->idx_list,p->idx_atom,p->idx_functor);
|
||||
|
||||
c=p->first;
|
||||
while(c!=NULL) {
|
||||
printf("Clausula %d do tipo %d (%d locals %d args) (val=0x%X)\n",++i,c->idx,c->nr_vars,c->predi->arity, (unsigned )c->val);
|
||||
c=c->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* BEAM */
|
|
@ -0,0 +1,764 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* BEAM -> Basic Extended Andorra Model *
|
||||
* BEAM extends the YAP Prolog system to support the EAM *
|
||||
* *
|
||||
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
||||
* *
|
||||
**************************************************************************
|
||||
* comments: eam code compiler *
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef BEAM
|
||||
|
||||
#include "eam.h"
|
||||
#include "eamamasm.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int skip_while_var(void);
|
||||
extern int wait_while_var(void);
|
||||
extern int force_wait(void);
|
||||
extern int p_write(void);
|
||||
extern int p_is(void);
|
||||
extern int p_halt(void);
|
||||
extern int p_halt0(void);
|
||||
extern int commit(void);
|
||||
extern int eager_split(void);
|
||||
|
||||
extern void eam_showcode(Cell *);
|
||||
extern Cell *eam_assemble(CInstr *);
|
||||
extern void ShowCode_new2(int, int, CELL);
|
||||
extern Cell *gera_codigo_try(int);
|
||||
extern Cell *gera_codigo_try_list(int);
|
||||
extern Cell *gera_codigo_try_only_vars(int);
|
||||
extern struct HASH_TABLE **gera_codigo_try_atom(int);
|
||||
extern struct HASH_TABLE **gera_codigo_try_functor(int);
|
||||
|
||||
/* Novas Definicoes */
|
||||
compiler_struct *CGLOBS;
|
||||
int labelno;
|
||||
extern int nperm;
|
||||
CInstr *inter_code,*StartCode;
|
||||
|
||||
void convert_Yaam(struct Clauses *);
|
||||
void anota_predicados(struct Clauses *, PredEntry *,unsigned long ,int ,int ,int);
|
||||
void verifica_predicados(struct Clauses *);
|
||||
void ShowCode_new(int);
|
||||
void codigo_eam(compiler_struct *);
|
||||
void ver_predicados(void);
|
||||
void eam_instructions(struct Clauses *);
|
||||
void identify_calls(CInstr *);
|
||||
int needs_box(Cell);
|
||||
int is_skip(Cell);
|
||||
void delay_prepare_calls(void);
|
||||
int test_for_side_effects(void);
|
||||
CInstr *insert_inst(CInstr *, int,int,CELL);
|
||||
CInstr *emit_new(int, int, CELL);
|
||||
CInstr *new_inst(int, int, CELL);
|
||||
void *alloc_mem_temp(Cell);
|
||||
void *alloc_mem(Cell);
|
||||
|
||||
/***********************************************************************\
|
||||
* Aqui estao as novas partes do compilador *
|
||||
\***********************************************************************/
|
||||
|
||||
void anota_predicados(struct Clauses *clause, PredEntry *p, unsigned long a,int b,int info_type,int call)
|
||||
{
|
||||
struct Predicates *predi;
|
||||
|
||||
if (p->beamTable==NULL) { /*1 vez que aparece, inicializar uma nova estrutura */
|
||||
predi=(struct Predicates *) alloc_mem(sizeof(struct Predicates));
|
||||
p->beamTable=predi;
|
||||
|
||||
predi->id=a;
|
||||
predi->name=(char *) RepAtom(AtomOfTerm(MkAtomTerm((Atom) a)))->StrOfAE;
|
||||
predi->arity=b;
|
||||
predi->nr_alt=0;
|
||||
predi->calls=0;
|
||||
predi->idx_var=0;
|
||||
predi->idx_list=0;
|
||||
predi->idx_atom=0;
|
||||
predi->idx_functor=0;
|
||||
predi->first=NULL;
|
||||
predi->last=NULL;
|
||||
|
||||
} else predi=p->beamTable;
|
||||
|
||||
if (!call) { /* se nao foi chamado por um call, entao anota informacao */
|
||||
predi->id=a;
|
||||
predi->nr_alt++;
|
||||
if (info_type & Variavel ) predi->idx_var++; /* info_type=Lista+Estrutura+Constante; */
|
||||
if (info_type & Lista ) predi->idx_list++;
|
||||
if (info_type & Estrutura) predi->idx_functor++;
|
||||
if (info_type & Constante) predi->idx_atom++;
|
||||
if (predi->last==NULL) {
|
||||
predi->first=clause;
|
||||
predi->last=clause;
|
||||
clause->next=NULL;
|
||||
} else {
|
||||
predi->last->next=clause;
|
||||
predi->last=clause;
|
||||
clause->next=NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void identify_calls(CInstr *code) {
|
||||
PredEntry *p = RepPredProp((Prop) code->new4);
|
||||
Functor f = p->FunctorOfPred;
|
||||
int arity=p->ArityOfPE;
|
||||
char *name;
|
||||
|
||||
if ( arity == 0) name=((AtomEntry *) f)->StrOfAE;
|
||||
else name=((AtomEntry *) NameOfFunctor(f))->StrOfAE;
|
||||
|
||||
/*
|
||||
if (code->op==call_op) printf("call: ");
|
||||
else if (code->op==safe_call_op) printf("call: ");
|
||||
else if (code->op==execute_op) printf("execute: ");
|
||||
printf("->%s/%d...............\n",name,arity);
|
||||
*/
|
||||
|
||||
if (arity==0) {
|
||||
if (strcmp(name,"/")==0) { code->op=commit_op; return; }
|
||||
if (strcmp(name,":")==0) { code->op=force_wait_op; return; }
|
||||
if (strcmp(name,"nl")==0) { code->op=write_op; code->new1='\n'; return; }
|
||||
if (strcmp(name,"halt")==0) { code->op=exit_op; return; }
|
||||
|
||||
} else if (arity==1) {
|
||||
if (strcmp(name,"wait_while_var")==0) { code->op=wait_while_var_op; return; }
|
||||
if (strcmp(name,"skip_while_var")==0) { code->op=skip_while_var_op; return; }
|
||||
if (strcmp(name,"write")==0) { code->op=write_op; return; }
|
||||
|
||||
} else if (arity==2) {
|
||||
if (strcmp(name,"is")==0) { code->op=is_op; return; }
|
||||
}
|
||||
|
||||
/* não é nenhum call conhecido, deve ser um predicado em Prolog */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* no verifica_predicados, vou transformar os calls para */
|
||||
void verifica_predicados(struct Clauses *clause)
|
||||
{
|
||||
CELL Flags;
|
||||
|
||||
inter_code=StartCode;
|
||||
anota_predicados(clause,(CGLOBS->cint).CurrentPred, StartCode->new4,StartCode->new1,clause->idx,0);
|
||||
|
||||
while(inter_code!=NULL) {
|
||||
if (inter_code->op==safe_call_op) { /* new1 deve continuar igual */
|
||||
Flags = RepPredProp((Prop) (inter_code->new4))->PredFlags;
|
||||
if (Flags & AsmPredFlag) {
|
||||
inter_code->op=std_base_op;
|
||||
inter_code->new4=(Flags &0x7f);
|
||||
} else {
|
||||
PredEntry *p=RepPredProp((Prop) inter_code->new4);
|
||||
inter_code->op=safe_call_op;
|
||||
inter_code->new4= (unsigned long) p->cs.f_code;
|
||||
if (Flags & BinaryPredFlag) inter_code->new1=2;
|
||||
else inter_code->new1=0;
|
||||
}
|
||||
}
|
||||
else if (inter_code->op==call_op || inter_code->op==execute_op) {
|
||||
PredEntry *p = RepPredProp((Prop) inter_code->new4);
|
||||
Flags = p->PredFlags;
|
||||
Functor f = p->FunctorOfPred;
|
||||
|
||||
if (Flags & AsmPredFlag) {
|
||||
int op;
|
||||
switch (Flags & 0x7f) {
|
||||
case _equal:
|
||||
op = _p_equal;
|
||||
break;
|
||||
case _dif:
|
||||
op = _p_dif;
|
||||
break;
|
||||
case _eq:
|
||||
op = _p_eq;
|
||||
break;
|
||||
case _arg:
|
||||
op = _p_arg;
|
||||
break;
|
||||
case _functor:
|
||||
op = _p_functor;
|
||||
break;
|
||||
default:
|
||||
printf("Internal eam assembler error for built-in %d\n",((int) (Flags & 0x7f)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(Flags & CPredFlag)) {
|
||||
if (p->ArityOfPE == 0) f = Yap_MkFunctor((Atom) f, 0);
|
||||
inter_code->new4=(unsigned long) p;
|
||||
anota_predicados(clause, p, (unsigned long) NameOfFunctor(f),ArityOfFunctor(f),0,1);
|
||||
p->beamTable->calls++;
|
||||
|
||||
} else {/* safe_call */
|
||||
inter_code->op=safe_call_op;
|
||||
inter_code->new4= (unsigned long) p->cs.f_code;
|
||||
if (Flags & BinaryPredFlag) inter_code->new1=2;
|
||||
else inter_code->new1=0;
|
||||
}
|
||||
}
|
||||
inter_code=inter_code->nextInst;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ShowCode_new(int i)
|
||||
{
|
||||
/*
|
||||
struct intermediates c;
|
||||
c.CodeStart=StartCode;
|
||||
|
||||
Yap_ShowCode(&c);
|
||||
return;
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
|
||||
switch(i) {
|
||||
case 1: printf("\nVer Predicados \n");
|
||||
break;
|
||||
case 2: printf("\nVer yaam Original\n");
|
||||
break;
|
||||
case 4: printf("\nVer abs machine code\n");
|
||||
break;
|
||||
case 8: printf("\nVer o codigo dos trys\n");
|
||||
break;
|
||||
case 16: printf("\nVer o codigo yaam ja transformado\n");
|
||||
break;
|
||||
case 32: printf("\nver codigo EAM com direct calls\n");
|
||||
break;
|
||||
case 128: printf("\nVer codigo EAM final\n");
|
||||
break;
|
||||
}
|
||||
|
||||
inter_code = StartCode;
|
||||
while (inter_code) {
|
||||
ShowCode_new2(inter_code->op, inter_code->new1,inter_code->new4);
|
||||
inter_code = inter_code->nextInst;
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void codigo_eam(compiler_struct *cglobs)
|
||||
{
|
||||
struct Clauses *clause;
|
||||
|
||||
CGLOBS=cglobs;
|
||||
labelno=cglobs->labelno;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (Print_Code & 2 ) Yap_ShowCode(&CGLOBS->cint);
|
||||
#endif
|
||||
clause=(struct Clauses *) alloc_mem(sizeof(struct Clauses));
|
||||
convert_Yaam(clause); /* convert into an internal struct code and check IDX */
|
||||
verifica_predicados(clause); /* check predicates and convert calls */
|
||||
|
||||
clause->predi=(CGLOBS->cint).CurrentPred->beamTable;
|
||||
(CGLOBS->cint).CurrentPred->beamTable->idx=0; /* will need to go by indexing */
|
||||
|
||||
if (Print_Code & 4) ShowCode_new(2); /* codigo YAAM */
|
||||
|
||||
/* transf os safe_calls em instrucoes eam e verifica se existem side_effects */
|
||||
clause->side_effects=test_for_side_effects();
|
||||
|
||||
eam_instructions(clause);
|
||||
if (Print_Code & 16) ShowCode_new(16); /* codigo EAM */
|
||||
inter_code=NULL;
|
||||
delay_prepare_calls(); /* transforma alguns safe_calls em direct_calls */
|
||||
|
||||
if (Print_Code & 32) ShowCode_new(32); /* codigo com direct_callss */
|
||||
clause->code=eam_assemble(StartCode);
|
||||
clause->nr_vars=nperm;
|
||||
|
||||
if (Print_Code & 128) eam_showcode((Cell *)clause->code);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************\
|
||||
* Convert Code *
|
||||
\********************************************************/
|
||||
|
||||
|
||||
int is_skip(Cell op)
|
||||
{
|
||||
if (op==skip_while_var_op) return(1);
|
||||
if (op==wait_while_var_op) return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void eam_instructions(struct Clauses *clause)
|
||||
{
|
||||
int calls=0,nrcall=0;
|
||||
CInstr *b_code=NULL;
|
||||
|
||||
inter_code=StartCode;
|
||||
while(inter_code!=NULL){
|
||||
if (inter_code->op==body_op) calls=0;
|
||||
if (inter_code->op==procceed_op) inter_code->nextInst=NULL; /* CUIDADO */
|
||||
if (inter_code->op==allocate_op) inter_code->op=nop_op;
|
||||
if (inter_code->op==deallocate_op) inter_code->op=nop_op;
|
||||
if (inter_code->op==cutexit_op) {
|
||||
inter_code->op=cut_op;
|
||||
insert_inst(inter_code,procceed_op,0,0);
|
||||
}
|
||||
if (inter_code->op==fail_op) insert_inst(inter_code,procceed_op,0,0);
|
||||
|
||||
if (inter_code->op==execute_op) {
|
||||
inter_code->op=call_op;
|
||||
insert_inst(inter_code,procceed_op,0,0);
|
||||
}
|
||||
if (inter_code->op==safe_call_op) {
|
||||
if ((void *)inter_code->new4==(void *) eager_split) {
|
||||
inter_code->op=nop_op;
|
||||
clause->predi->eager_split=1;
|
||||
}
|
||||
}
|
||||
if (needs_box(inter_code->op)) calls++;
|
||||
|
||||
inter_code=inter_code->nextInst;
|
||||
}
|
||||
|
||||
if (calls) {
|
||||
inter_code=StartCode;
|
||||
while(inter_code!=NULL){
|
||||
if (inter_code->op==body_op) {
|
||||
inter_code->new4=calls;
|
||||
insert_inst(inter_code,create_first_box_op,calls,++labelno);
|
||||
inter_code=inter_code->nextInst;
|
||||
}
|
||||
if (needs_box(inter_code->op)) {
|
||||
insert_inst(inter_code,remove_box_op,nrcall,0);
|
||||
inter_code=inter_code->nextInst;
|
||||
b_code=inter_code;
|
||||
insert_inst(inter_code,label_op,nrcall,labelno);
|
||||
inter_code=inter_code->nextInst;
|
||||
insert_inst(inter_code,create_box_op,++nrcall,++labelno);
|
||||
}
|
||||
inter_code=inter_code->nextInst;
|
||||
}
|
||||
|
||||
b_code->op=remove_last_box_op;
|
||||
b_code->nextInst->nextInst->op=nop_op;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void delay_prepare_calls(void) {
|
||||
CInstr *b_code=NULL;
|
||||
|
||||
inter_code=StartCode;
|
||||
while(inter_code!=NULL){
|
||||
if (inter_code->op==body_op) b_code=inter_code;
|
||||
if (inter_code->op!=safe_call_op && inter_code->op!=cut_op && (needs_box(inter_code->op) || is_skip(inter_code->op))) break;
|
||||
|
||||
if (inter_code->op==safe_call_op) {
|
||||
inter_code->op=direct_safe_call_op;
|
||||
|
||||
b_code->nextInst->op=nop_op;
|
||||
inter_code->nextInst->op=nop_op;
|
||||
if (b_code->new4>1) {
|
||||
inter_code->nextInst->nextInst->op=body_op;
|
||||
inter_code->nextInst->nextInst->new1=0;
|
||||
inter_code->nextInst->nextInst->new4=b_code->new4-1;
|
||||
} else {
|
||||
inter_code->nextInst->nextInst->op=procceed_op;
|
||||
inter_code->nextInst->nextInst->new1=0;
|
||||
inter_code->nextInst->nextInst->new4=0;
|
||||
}
|
||||
b_code->op=nop_op;
|
||||
|
||||
}
|
||||
|
||||
inter_code=inter_code->nextInst;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int needs_box(Cell op)
|
||||
{
|
||||
if (op==safe_call_op) return(1);
|
||||
if (op==call_op) return(1);
|
||||
if (op==std_base_op) return(1);
|
||||
if (op==fail_op) return(1);
|
||||
if (op==force_wait_op) return(1);
|
||||
if (op==cut_op) return(1);
|
||||
if (op==commit_op) return(1);
|
||||
if (op==cutexit_op) return(1);
|
||||
if (op==write_op) return(1);
|
||||
if (op==is_op) return(1);
|
||||
if (op==equal_op) return(1);
|
||||
if (op==exit_op) return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int test_for_side_effects()
|
||||
{
|
||||
int side_effects=0;
|
||||
|
||||
inter_code=StartCode;
|
||||
while(inter_code!=NULL){
|
||||
switch (inter_code->op) {
|
||||
case write_op:
|
||||
side_effects+=WRITE;
|
||||
break;
|
||||
|
||||
case cutexit_op:
|
||||
case commit_op:
|
||||
case cut_op:
|
||||
side_effects+=CUT;
|
||||
break;
|
||||
case force_wait_op:
|
||||
side_effects+=SEQUENCIAL;
|
||||
break;
|
||||
}
|
||||
inter_code=inter_code->nextInst;
|
||||
}
|
||||
|
||||
return(side_effects);
|
||||
}
|
||||
|
||||
void convert_Yaam(struct Clauses *clause)
|
||||
{
|
||||
PInstr *CodeStart, *ppc;
|
||||
int calls=0;
|
||||
|
||||
clause->val=0;
|
||||
clause->idx=Variavel;
|
||||
|
||||
StartCode=NULL;
|
||||
inter_code=NULL;
|
||||
CodeStart=(&CGLOBS->cint)->CodeStart;
|
||||
ppc=CodeStart;
|
||||
while(ppc!=NULL){ /* copia o codigo YAAM para poder ser alterado e ve o tipo de indexacao*/
|
||||
if (ppc->op!=nop_op) {
|
||||
if (ppc->op==get_var_op && ppc->rnd2==1) { clause->idx=Variavel; clause->val=0; }
|
||||
if (ppc->op==get_list_op && ppc->rnd2==1) { clause->idx=Lista; clause->val=0; }
|
||||
if (ppc->op==get_struct_op && ppc->rnd2==1) { clause->idx=Estrutura; clause->val=ppc->rnd1; }
|
||||
if ((ppc->op==get_atom_op || ppc->op==get_num_op) && ppc->rnd2==1) { clause->idx=Constante; clause->val=ppc->rnd1; }
|
||||
|
||||
if (ppc->op==body_op || ppc->op==safe_call_op || ppc->op==call_op || ppc->op==execute_op) calls=1;
|
||||
|
||||
if (ppc->op==endgoal_op) {
|
||||
if (calls==0) emit_new(equal_op, 0, 0);
|
||||
calls=0;
|
||||
} else {
|
||||
emit_new(ppc->op, ppc->rnd2, ppc->rnd1);
|
||||
if (ppc->op==body_op) calls=1;
|
||||
if (ppc->op==safe_call_op || ppc->op==call_op || ppc->op==execute_op) {
|
||||
calls=1; identify_calls(inter_code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ppc=ppc->nextInst;
|
||||
}
|
||||
emit_new(nop_op, 0,0);
|
||||
emit_new(nop_op, 0,0);
|
||||
|
||||
/*
|
||||
CodeStart->nextInst=NULL;
|
||||
ppc=CodeStart;
|
||||
|
||||
(&CGLOBS->cint)->cpc=CodeStart;
|
||||
|
||||
Yap_emit(cut_op,Zero,Zero,&CGLOBS->cint);
|
||||
Yap_emit(run_op,Zero,(unsigned long) (CGLOBS->cint).CurrentPred,&CGLOBS->cint);
|
||||
Yap_emit(procceed_op, Zero, Zero, &CGLOBS->cint);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CInstr *insert_inst(CInstr *inst, int o,int r1,CELL r4)
|
||||
{
|
||||
CInstr *p;
|
||||
|
||||
p=new_inst(o,r1,r4);
|
||||
if (inst==NULL) inst=p;
|
||||
else {
|
||||
p->nextInst=inst->nextInst;
|
||||
inst->nextInst=p;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
CInstr *emit_new(int o, int r1,CELL r4)
|
||||
{
|
||||
CInstr *p;
|
||||
|
||||
p=new_inst(o,r1,r4);
|
||||
if (inter_code == NULL) {
|
||||
inter_code = StartCode = p;
|
||||
}
|
||||
else {
|
||||
inter_code->nextInst = p;
|
||||
inter_code = p;
|
||||
}
|
||||
return(inter_code);
|
||||
}
|
||||
|
||||
CInstr *new_inst(int o, int r1,CELL r4)
|
||||
{
|
||||
CInstr *p;
|
||||
|
||||
p = (CInstr *) alloc_mem_temp(sizeof(CInstr));
|
||||
p->op = o;
|
||||
p->new1 = r1;
|
||||
p->new4 = r4;
|
||||
p->nextInst = NULL;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
void *alloc_mem(Cell size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p=malloc(size);
|
||||
if (p==NULL) { printf(" Erro, falta de memoria \n"); exit(1); }
|
||||
// p=Yap_AllocCMem(size,&CGLOBS->cint);
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
void *alloc_mem_temp(Cell size) /* memory that will be discard after compiling */
|
||||
{
|
||||
void *p;
|
||||
|
||||
p=malloc(size);
|
||||
if (p==NULL) { printf(" Erro, falta de memoria \n"); exit(1); }
|
||||
// p=Yap_AllocCMem(size,&CGLOBS->cint);
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *opformat2[] =
|
||||
{
|
||||
"nop",
|
||||
"get_var %1,%4",
|
||||
"put_var %1,%4",
|
||||
"get_val %1,%4",
|
||||
"put_val %1,%4",
|
||||
"get_atom %1,%4",
|
||||
"put_atom %1,%4",
|
||||
"get_num %1,%4",
|
||||
"put_num %1,%4",
|
||||
"get_float %1,%4",
|
||||
"put_float %1,%4",
|
||||
"align_float %1,%4",
|
||||
"get_longint %1,%4",
|
||||
"put_longint %1,%4",
|
||||
"get_bigint %1,%4",
|
||||
"put_bigint %1,%4",
|
||||
"get_list %1,%4",
|
||||
"put_list %1,%4",
|
||||
"get_struct %1,%4",
|
||||
"put_struct %1,%4",
|
||||
"put_unsafe %1,%4",
|
||||
"unify_var %1,%4",
|
||||
"write_var %1,%4",
|
||||
"unify_val %1,%4",
|
||||
"write_val %1,%4",
|
||||
"unify_atom %1,%4",
|
||||
"write_atom %1,%4",
|
||||
"unify_num %1,%4",
|
||||
"write_num %1,%4",
|
||||
"unify_float %1,%4",
|
||||
"write_float %1,%4",
|
||||
"unify_longint %1,%4",
|
||||
"write_longint %1,%4",
|
||||
"unify_bigint %1,%4",
|
||||
"write_bigint %1,%4",
|
||||
"unify_list %1,%4",
|
||||
"write_list %1,%4",
|
||||
"unify_struct %1,%4",
|
||||
"write_struct %1,%4",
|
||||
"write_unsafe %1,%4",
|
||||
"fail %1,%4",
|
||||
"cut %1,%4",
|
||||
"cutexit %1,%4",
|
||||
"allocate %1,%4",
|
||||
"deallocate %1,%4",
|
||||
"try_me_else %1,%4",
|
||||
"jump %1,%4",
|
||||
"jump %1,%4",
|
||||
"proceed %1,%4",
|
||||
"call %1,%4",
|
||||
"execute %1,%4",
|
||||
"sys %1,%4",
|
||||
"%l: %1,%4",
|
||||
"name %1,%4",
|
||||
"pop %1,%4",
|
||||
"retry_me_else %1,%4",
|
||||
"trust_me_else_fail %1,%4",
|
||||
"either_me %1,%4",
|
||||
"or_else %1,%4",
|
||||
"or_last %1,%4",
|
||||
"push_or %1,%4",
|
||||
"pushpop_or %1,%4",
|
||||
"pop_or %1,%4",
|
||||
"save_by %1,%4",
|
||||
"commit_by %1,%4",
|
||||
"patch_by %1,%4",
|
||||
"try %1,%4",
|
||||
"retry %1,%4",
|
||||
"trust %1,%4",
|
||||
"try_in %1,%4",
|
||||
"jump_if_var %1,%4",
|
||||
"jump_if_nonvar %1,%4",
|
||||
"cache_arg %1,%4",
|
||||
"cache_sub_arg %1,%4",
|
||||
"switch_on_type %1,%4",
|
||||
"switch_on_constant %1,%4",
|
||||
"if_constant %1,%4",
|
||||
"switch_on_functor %1,%4",
|
||||
"if_functor %1,%4",
|
||||
"if_not_then %1,%4",
|
||||
"index_on_dbref %1,%4",
|
||||
"index_on_blob %1,%4",
|
||||
"check_var %1,%4",
|
||||
"save_pair %1,%4",
|
||||
"save_appl %1,%4",
|
||||
"fail_label %1,%4",
|
||||
"unify_local %1,%4",
|
||||
"write local %1,%4",
|
||||
"unify_last_list %1,%4",
|
||||
"write_last_list %1,%4",
|
||||
"unify_last_struct %1,%4",
|
||||
"write_last_struct %1,%4",
|
||||
"unify_last_var %1,%4",
|
||||
"unify_last_val %1,%4",
|
||||
"unify_last_local %1,%4",
|
||||
"unify_last_atom %1,%4",
|
||||
"unify_last_num %1,%4",
|
||||
"unify_last_float %1,%4",
|
||||
"unify_last_longint %1,%4",
|
||||
"unify_last_bigint %1,%4",
|
||||
"pvar_bitmap %1,%4",
|
||||
"pvar_live_regs %1,%4",
|
||||
"fetch_reg1_reg2 %1,%4",
|
||||
"fetch_constant_reg %1,%4",
|
||||
"fetch_reg_constant %1,%4",
|
||||
"function_to_var %1,%4",
|
||||
"function_to_al %1,%4",
|
||||
"enter_profiling %1,%4",
|
||||
"retry_profiled %1,%4",
|
||||
"count_call_op %1,%4",
|
||||
"count_retry_op %1,%4",
|
||||
"restore_temps %1,%4",
|
||||
"restore_temps_and_skip %1,%4",
|
||||
"enter_lu %1,%4",
|
||||
"empty_call %1,%4",
|
||||
#ifdef YAPOR
|
||||
"sync
|
||||
#endif /* YAPOR */
|
||||
#ifdef TABLING
|
||||
"table_new_answer %1,%4",
|
||||
"table_try_single %1,%4",
|
||||
#endif /* TABLING */
|
||||
#ifdef TABLING_INNER_CUTS
|
||||
"clause_with_cut %1,%4",
|
||||
#endif /* TABLING_INNER_CUTS */
|
||||
#ifdef BEAM
|
||||
"run_op %1,%4",
|
||||
"body_op %1",
|
||||
"endgoal_op",
|
||||
"try_me_op %1,%4",
|
||||
"retry_me_op %1,%4",
|
||||
"trust_me_op %1,%4",
|
||||
"only_1_clause_op %1,%4",
|
||||
"create_first_box_op %1,%4",
|
||||
"create_box_op %1,%4",
|
||||
"create_last_box_op %1,%4",
|
||||
"remove_box_op %1,%4",
|
||||
"remove_last_box_op %1,%4",
|
||||
"prepare_tries",
|
||||
"std_base_op %1,%4",
|
||||
"direct_safe_call",
|
||||
"commit_op",
|
||||
"skip_while_var_op",
|
||||
"wait_while_var_op",
|
||||
"force_wait_op",
|
||||
"write_op",
|
||||
"is_op",
|
||||
"exit",
|
||||
#endif
|
||||
"fetch_args_for_bccall %1,%4",
|
||||
"binary_cfunc %1,%4",
|
||||
"blob %1,%4",
|
||||
#ifdef SFUNC
|
||||
,
|
||||
"get_s_f_op %1,%4",
|
||||
"put_s_f_op %1,%4",
|
||||
"unify_s_f_op %1,%4",
|
||||
"write_s_f_op %1,%4",
|
||||
"unify_s_var %1,%4",
|
||||
"write_s_var %1,%4",
|
||||
"unify_s_val %1,%4",
|
||||
"write_s_val %1,%4",
|
||||
"unify_s_a %1,%4",
|
||||
"write_s_a %1,%4",
|
||||
"get_s_end",
|
||||
"put_s_end",
|
||||
"unify_s_end",
|
||||
"write_s_end"
|
||||
#endif
|
||||
};
|
||||
|
||||
void ShowCode_new2(int op, int new1,CELL new4);
|
||||
|
||||
void ShowCode_new2(int op, int new1,CELL new4)
|
||||
{
|
||||
char *f,ch;
|
||||
f=opformat2[op];
|
||||
|
||||
while ((ch = *f++) != 0)
|
||||
{
|
||||
if (ch == '%')
|
||||
switch (ch = *f++)
|
||||
{
|
||||
case '1':
|
||||
Yap_plwrite(MkIntTerm(new1), NULL, 30, 0, GLOBAL_MaxPriority);
|
||||
break;
|
||||
case '4':
|
||||
Yap_plwrite(MkIntTerm(new4), NULL, 20, 0, GLOBAL_MaxPriority);
|
||||
break;
|
||||
default:
|
||||
Yap_DebugPutc (LOCAL_c_error_stream,'%');
|
||||
Yap_DebugPutc (LOCAL_c_error_stream,ch);
|
||||
}
|
||||
else
|
||||
Yap_DebugPutc (LOCAL_c_error_stream,ch);
|
||||
}
|
||||
Yap_DebugPutc (LOCAL_c_error_stream,'\n');
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* BEAM */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,86 @@
|
|||
/*****************************************************************
|
||||
* INSTRUCTIONS *
|
||||
*****************************************************************/
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
|
||||
BOp(Ystop, l);
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
/* make sure ASP is initialized */
|
||||
saveregs();
|
||||
|
||||
#if PUSH_REGS
|
||||
restore_absmi_regs(old_regs);
|
||||
#endif
|
||||
#if BP_FREE
|
||||
P1REG = PCBACKUP;
|
||||
#endif
|
||||
return 1;
|
||||
ENDBOp();
|
||||
|
||||
BOp(Nstop, e);
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
saveregs();
|
||||
#if PUSH_REGS
|
||||
restore_absmi_regs(old_regs);
|
||||
#endif
|
||||
#if BP_FREE
|
||||
P1REG = PCBACKUP;
|
||||
#endif
|
||||
return 0;
|
||||
ENDBOp();
|
||||
|
||||
|
||||
|
||||
/************************************************************************\
|
||||
* Native Code Execution *
|
||||
\************************************************************************/
|
||||
|
||||
#if YAP_JIT
|
||||
static void *OpAddress_JIT[] =
|
||||
{
|
||||
#define OPCODE(OP,TYPE) && _##OP
|
||||
#include "YapOpcodes.h"
|
||||
#undef OPCODE
|
||||
};
|
||||
|
||||
/* native_me */
|
||||
BOp(jit_handler, J);
|
||||
if (!PREG->y_u.J.jh->fi.bcst.c) PREG->y_u.J.jh->mf.isground = IsGround(PREG);
|
||||
PREG->y_u.J.jh->fi.bcst.c++;
|
||||
|
||||
/* Did PREG reach threshold value to become critical? */
|
||||
if (PREG->y_u.J.jh->fi.bcst.c == (COUNT)(ExpEnv.config_struc.frequency_bound*(ExpEnv.config_struc.profiling_startp)) && !PREG->y_u.J.jh->mf.isground) {
|
||||
#if YAP_DBG_PREDS
|
||||
if (ExpEnv.debug_struc.pprint_me.criticals != 0 && ExpEnv.debug_struc.pprint_me.criticals != 0x1) {
|
||||
fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
|
||||
fprintf(stderr, "%s", (char*)ExpEnv.debug_struc.pprint_me.criticals);
|
||||
}
|
||||
#endif
|
||||
traced_absmi();
|
||||
|
||||
}
|
||||
#if YAP_DBG_PREDS
|
||||
print_main_when_head(PREG, ON_INTERPRETER);
|
||||
#endif
|
||||
PREG = NEXTOP(PREG, J);
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
#endif
|
||||
|
||||
#include "cp_absmi_insts.h"
|
||||
#include "lu_absmi_insts.h"
|
||||
#include "fail_absmi_insts.h"
|
||||
#include "control_absmi_insts.h"
|
||||
#include "unify_absmi_insts.h"
|
||||
#include "fli_absmi_insts.h"
|
||||
#include "or_absmi_insts.h"
|
||||
#include "index_absmi_insts.h"
|
||||
#include "type_absmi_insts.h"
|
||||
#include "prim_absmi_insts.h"
|
||||
#include "meta_absmi_insts.h"
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,574 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: agc.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: reclaim unused atoms and functors *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "@(#)agc.c 1.3 3/15/90";
|
||||
#endif
|
||||
|
||||
#include "absmi.h"
|
||||
#include "Foreign.h"
|
||||
#include "alloc.h"
|
||||
#include "yapio.h"
|
||||
#include "iopreds.h"
|
||||
#include "attvar.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
/* #define DEBUG_RESTORE1 1 */
|
||||
/* #define DEBUG_RESTORE2 1 */
|
||||
/* #define DEBUG_RESTORE3 1 */
|
||||
#define errout GLOBAL_stderr
|
||||
#endif
|
||||
|
||||
static void RestoreEntries(PropEntry *, int USES_REGS);
|
||||
static void CleanCode(PredEntry * USES_REGS);
|
||||
static void RestoreDBTerm(DBTerm *dbr, int attachments USES_REGS);
|
||||
|
||||
#define AtomMarkedBit 1
|
||||
|
||||
static inline void
|
||||
MarkAtomEntry(AtomEntry *ae)
|
||||
{
|
||||
CELL c = (CELL)(ae->NextOfAE);
|
||||
c |= AtomMarkedBit;
|
||||
ae->NextOfAE = (Atom)c;
|
||||
}
|
||||
|
||||
static inline int
|
||||
AtomResetMark(AtomEntry *ae)
|
||||
{
|
||||
CELL c = (CELL)(ae->NextOfAE);
|
||||
if (c & AtomMarkedBit) {
|
||||
c &= ~AtomMarkedBit;
|
||||
ae->NextOfAE = (Atom)c;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline Atom
|
||||
CleanAtomMarkedBit(Atom a)
|
||||
{
|
||||
CELL c = (CELL)a;
|
||||
c &= ~AtomMarkedBit;
|
||||
return (Atom)c;
|
||||
}
|
||||
|
||||
|
||||
static inline Functor
|
||||
FuncAdjust(Functor f)
|
||||
{
|
||||
if (!IsExtensionFunctor(f)) {
|
||||
AtomEntry *ae = RepAtom(NameOfFunctor(f));
|
||||
MarkAtomEntry(ae);
|
||||
}
|
||||
return(f);
|
||||
}
|
||||
|
||||
|
||||
static inline Term
|
||||
AtomTermAdjust(Term t)
|
||||
{
|
||||
AtomEntry *ae = RepAtom(AtomOfTerm(t));
|
||||
MarkAtomEntry(ae);
|
||||
return(t);
|
||||
}
|
||||
|
||||
static inline Term
|
||||
TermToGlobalOrAtomAdjust(Term t)
|
||||
{
|
||||
if (t && IsAtomTerm(t))
|
||||
return AtomTermAdjust(t);
|
||||
return(t);
|
||||
}
|
||||
|
||||
static inline Atom
|
||||
AtomAdjust(Atom a)
|
||||
{
|
||||
AtomEntry *ae;
|
||||
if (a == NIL) return(a);
|
||||
ae = RepAtom(a);
|
||||
MarkAtomEntry(ae);
|
||||
return(a);
|
||||
}
|
||||
|
||||
#define IsOldCode(P) FALSE
|
||||
#define IsOldCodeCellPtr(P) FALSE
|
||||
#define IsOldDelay(P) FALSE
|
||||
#define IsOldDelayPtr(P) FALSE
|
||||
#define IsOldLocalInTR(P) FALSE
|
||||
#define IsOldLocalInTRPtr(P) FALSE
|
||||
#define IsOldGlobal(P) FALSE
|
||||
#define IsOldGlobalPtr(P) FALSE
|
||||
#define IsOldTrail(P) FALSE
|
||||
#define IsOldTrailPtr(P) FALSE
|
||||
|
||||
#define CharP(X) ((char *)(X))
|
||||
|
||||
#define REINIT_LOCK(P)
|
||||
#define REINIT_RWLOCK(P)
|
||||
#define BlobTypeAdjust(P) (P)
|
||||
#define NoAGCAtomAdjust(P) (P)
|
||||
#define OrArgAdjust(P)
|
||||
#define TabEntryAdjust(P)
|
||||
#define IntegerAdjust(D) (D)
|
||||
#define AddrAdjust(P) (P)
|
||||
#define MFileAdjust(P) (P)
|
||||
#define CodeVarAdjust(P) (P)
|
||||
#define ConstantAdjust(P) (P)
|
||||
#define ArityAdjust(P) (P)
|
||||
#define DoubleInCodeAdjust(P)
|
||||
#define IntegerInCodeAdjust(P)
|
||||
#define OpcodeAdjust(P) (P)
|
||||
#define ModuleAdjust(P) (P)
|
||||
#define ExternalFunctionAdjust(P) (P)
|
||||
#define DBRecordAdjust(P) (P)
|
||||
#define PredEntryAdjust(P) (P)
|
||||
#define ModEntryPtrAdjust(P) (P)
|
||||
#define AtomEntryAdjust(P) (P)
|
||||
#define GlobalEntryAdjust(P) (P)
|
||||
#define BlobTermInCodeAdjust(P) (P)
|
||||
#define CellPtoHeapAdjust(P) (P)
|
||||
#define PtoAtomHashEntryAdjust(P) (P)
|
||||
#define CellPtoHeapCellAdjust(P) (P)
|
||||
#define CellPtoTRAdjust(P) (P)
|
||||
#define CodeAddrAdjust(P) (P)
|
||||
#define ConsultObjAdjust(P) (P)
|
||||
#define DelayAddrAdjust(P) (P)
|
||||
#define DelayAdjust(P) (P)
|
||||
#define GlobalAdjust(P) (P)
|
||||
#define DBRefAdjust(P,REF) (P)
|
||||
#define DBRefPAdjust(P) (P)
|
||||
#define DBTermAdjust(P) (P)
|
||||
#define LUIndexAdjust(P) (P)
|
||||
#define SIndexAdjust(P) (P)
|
||||
#define LocalAddrAdjust(P) (P)
|
||||
#define GlobalAddrAdjust(P) (P)
|
||||
#define OpListAdjust(P) (P)
|
||||
#define PtoLUCAdjust(P) (P)
|
||||
#define PtoStCAdjust(P) (P)
|
||||
#define PtoArrayEAdjust(P) (P)
|
||||
#define PtoArraySAdjust(P) (P)
|
||||
#define PtoGlobalEAdjust(P) (P)
|
||||
#define PtoDelayAdjust(P) (P)
|
||||
#define PtoGloAdjust(P) (P)
|
||||
#define PtoLocAdjust(P) (P)
|
||||
#define PtoHeapCellAdjust(P) (P)
|
||||
#define TermToGlobalAdjust(P) (P)
|
||||
#define PtoOpAdjust(P) (P)
|
||||
#define PtoLUClauseAdjust(P) (P)
|
||||
#define PtoLUIndexAdjust(P) (P)
|
||||
#define PtoDBTLAdjust(P) (P)
|
||||
#define PtoPredAdjust(P) (P)
|
||||
#define PtoPtoPredAdjust(P) (P)
|
||||
#define OpRTableAdjust(P) (P)
|
||||
#define OpEntryAdjust(P) (P)
|
||||
#define PropAdjust(P) (P)
|
||||
#define TrailAddrAdjust(P) (P)
|
||||
#define XAdjust(P) (P)
|
||||
#define YAdjust(P) (P)
|
||||
#define HoldEntryAdjust(P) (P)
|
||||
#define CodeCharPAdjust(P) (P)
|
||||
#define CodeConstCharPAdjust(P) (P)
|
||||
#define CodeVoidPAdjust(P) (P)
|
||||
#define HaltHookAdjust(P) (P)
|
||||
|
||||
#define recompute_mask(dbr)
|
||||
|
||||
#define rehash(oldcode, NOfE, KindOfEntries)
|
||||
|
||||
#define RestoreSWIHash()
|
||||
|
||||
static void
|
||||
AdjustTermFlag(flag_term *tarr, UInt i)
|
||||
{
|
||||
CACHE_REGS
|
||||
if (IsVarTerm(tarr[i].at)) {
|
||||
RestoreDBTerm( tarr[i].DBT, 0 PASS_REGS );
|
||||
} else if (IsAtomTerm( tarr[i].at ) )
|
||||
tarr[i].at = AtomTermAdjust(tarr[i].at);
|
||||
}
|
||||
|
||||
static void RestoreFlags( UInt NFlags )
|
||||
{
|
||||
CACHE_REGS
|
||||
size_t i;
|
||||
flag_term *tarr = GLOBAL_Flags;
|
||||
|
||||
if (worker_id == 0)
|
||||
for (i=0; i<GLOBAL_flagCount; i++) {
|
||||
AdjustTermFlag( tarr, i);
|
||||
}
|
||||
tarr = LOCAL_Flags;
|
||||
for (i=0; i<LOCAL_flagCount; i++) {
|
||||
AdjustTermFlag( tarr, i);
|
||||
}
|
||||
}
|
||||
|
||||
#include "rheap.h"
|
||||
|
||||
static void
|
||||
RestoreHashPreds( USES_REGS1 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void init_reg_copies(USES_REGS1)
|
||||
{
|
||||
LOCAL_OldASP = ASP;
|
||||
LOCAL_OldLCL0 = LCL0;
|
||||
LOCAL_OldTR = TR;
|
||||
LOCAL_OldGlobalBase = (CELL *)LOCAL_GlobalBase;
|
||||
LOCAL_OldH = HR;
|
||||
LOCAL_OldH0 = H0;
|
||||
LOCAL_OldTrailBase = LOCAL_TrailBase;
|
||||
LOCAL_OldTrailTop = LOCAL_TrailTop;
|
||||
LOCAL_OldHeapBase = Yap_HeapBase;
|
||||
LOCAL_OldHeapTop = HeapTop;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
RestoreAtomList(Atom atm USES_REGS)
|
||||
{
|
||||
AtomEntry *at;
|
||||
|
||||
at = RepAtom(atm);
|
||||
if (EndOfPAEntr(at))
|
||||
return;
|
||||
do {
|
||||
RestoreAtom(atm PASS_REGS);
|
||||
atm = CleanAtomMarkedBit(at->NextOfAE);
|
||||
at = RepAtom(atm);
|
||||
} while (!EndOfPAEntr(at));
|
||||
}
|
||||
|
||||
static void
|
||||
mark_trail(USES_REGS1)
|
||||
{
|
||||
register tr_fr_ptr pt;
|
||||
|
||||
pt = TR;
|
||||
/* moving the trail is simple */
|
||||
while (pt != (tr_fr_ptr)LOCAL_TrailBase) {
|
||||
CELL reg = TrailTerm(pt-1);
|
||||
|
||||
if (!IsVarTerm(reg)) {
|
||||
if (IsAtomTerm(reg)) {
|
||||
MarkAtomEntry(RepAtom(AtomOfTerm(reg)));
|
||||
}
|
||||
}
|
||||
|
||||
pt--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mark_registers(USES_REGS1)
|
||||
{
|
||||
CELL *pt;
|
||||
|
||||
pt = XREGS;
|
||||
/* moving the trail is simple */
|
||||
while (pt != XREGS+MaxTemps) {
|
||||
CELL reg = *pt++;
|
||||
|
||||
if (!IsVarTerm(reg)) {
|
||||
if (IsAtomTerm(reg)) {
|
||||
MarkAtomEntry(RepAtom(AtomOfTerm(reg)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mark_local(USES_REGS1)
|
||||
{
|
||||
CELL *pt;
|
||||
|
||||
/* Adjusting the local */
|
||||
pt = LCL0;
|
||||
/* moving the trail is simple */
|
||||
while (pt > ASP) {
|
||||
CELL reg = *--pt;
|
||||
|
||||
if (!IsVarTerm(reg)) {
|
||||
if (IsAtomTerm(reg)
|
||||
#ifdef TABLING
|
||||
/* assume we cannot have atoms on first page,
|
||||
so this must be an arity
|
||||
*/
|
||||
&& reg > Yap_page_size
|
||||
#endif
|
||||
) {
|
||||
MarkAtomEntry(RepAtom(AtomOfTerm(reg)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static CELL *
|
||||
mark_global_cell(CELL *pt)
|
||||
{
|
||||
CELL reg = *pt;
|
||||
|
||||
if (IsVarTerm(reg)) {
|
||||
/* skip bitmaps */
|
||||
switch(reg) {
|
||||
case (CELL)FunctorDouble:
|
||||
#if SIZEOF_DOUBLE == 2*SIZEOF_INT_P
|
||||
return pt + 4;
|
||||
#else
|
||||
return pt + 3;
|
||||
#endif
|
||||
case (CELL)FunctorString:
|
||||
return pt + 3 + pt[1];
|
||||
case (CELL)FunctorBigInt:
|
||||
{
|
||||
Int sz = 3 +
|
||||
(sizeof(MP_INT)+
|
||||
(((MP_INT *)(pt+2))->_mp_alloc*sizeof(mp_limb_t)))/sizeof(CELL);
|
||||
Opaque_CallOnGCMark f;
|
||||
Opaque_CallOnGCRelocate f2;
|
||||
Term t = AbsAppl(pt);
|
||||
|
||||
if ( (f = Yap_blob_gc_mark_handler(t)) ) {
|
||||
CELL ar[256];
|
||||
Int i,n = (f)(Yap_BlobTag(t), Yap_BlobInfo(t), ar, 256);
|
||||
if (n < 0) {
|
||||
Yap_Error(RESOURCE_ERROR_HEAP,TermNil,"not enough space for slot internal variables in agc");
|
||||
}
|
||||
for (i = 0; i< n; i++) {
|
||||
CELL *pt = ar+i;
|
||||
CELL reg = *pt;
|
||||
if (!IsVarTerm(reg) && IsAtomTerm(reg)) {
|
||||
*pt = AtomTermAdjust(reg);
|
||||
}
|
||||
}
|
||||
if ( (f2 = Yap_blob_gc_relocate_handler(t)) < 0 ) {
|
||||
int out = (f2)(Yap_BlobTag(t), Yap_BlobInfo(t), ar, n);
|
||||
if (out < 0)
|
||||
Yap_Error(RESOURCE_ERROR_HEAP,TermNil,"bad restore of slot internal variables in agc");
|
||||
}
|
||||
}
|
||||
|
||||
return pt + sz;
|
||||
}
|
||||
case (CELL)FunctorLongInt:
|
||||
return pt + 3;
|
||||
break;
|
||||
}
|
||||
} else if (IsAtomTerm(reg)) {
|
||||
MarkAtomEntry(RepAtom(AtomOfTerm(reg)));
|
||||
return pt+1;
|
||||
}
|
||||
return pt+1;
|
||||
}
|
||||
|
||||
static void
|
||||
mark_global(USES_REGS1)
|
||||
{
|
||||
CELL *pt;
|
||||
|
||||
/*
|
||||
* to clean the global now that functors are just variables pointing to
|
||||
* the code
|
||||
*/
|
||||
pt = H0;
|
||||
while (pt < HR) {
|
||||
pt = mark_global_cell(pt);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mark_stacks(USES_REGS1)
|
||||
{
|
||||
mark_registers(PASS_REGS1);
|
||||
mark_trail(PASS_REGS1);
|
||||
mark_local(PASS_REGS1);
|
||||
mark_global(PASS_REGS1);
|
||||
}
|
||||
|
||||
static void
|
||||
clean_atom_list(AtomHashEntry *HashPtr)
|
||||
{
|
||||
Atom atm = HashPtr->Entry;
|
||||
Atom *patm = &(HashPtr->Entry);
|
||||
while (atm != NIL) {
|
||||
AtomEntry *at = RepAtom(atm);
|
||||
if (AtomResetMark(at) ||
|
||||
( at->PropsOfAE != NIL && !IsBlob(at) ) ||
|
||||
(GLOBAL_AGCHook != NULL && !GLOBAL_AGCHook(atm))) {
|
||||
patm = &(at->NextOfAE);
|
||||
atm = at->NextOfAE;
|
||||
} else {
|
||||
NOfAtoms--;
|
||||
if (IsBlob(atm)) {
|
||||
YAP_BlobPropEntry *b = RepBlobProp(at->PropsOfAE);
|
||||
if (b->NextOfPE != NIL) {
|
||||
patm = &(at->NextOfAE);
|
||||
atm = at->NextOfAE;
|
||||
continue;
|
||||
}
|
||||
NOfAtoms++;
|
||||
NOfBlobs--;
|
||||
Yap_FreeCodeSpace((char *)b);
|
||||
GLOBAL_agc_collected += sizeof(YAP_BlobPropEntry);
|
||||
GLOBAL_agc_collected += sizeof(AtomEntry)+sizeof(size_t)+at->rep.blob->length;
|
||||
} else if (IsWideAtom(atm)) {
|
||||
#ifdef DEBUG_RESTORE3
|
||||
fprintf(stderr, "Purged %p:%S\n", at, at->WStrOfAE);
|
||||
#endif
|
||||
GLOBAL_agc_collected += sizeof(AtomEntry)+wcslen(at->WStrOfAE);
|
||||
} else {
|
||||
#ifdef DEBUG_RESTORE3
|
||||
fprintf(stderr, "Purged %p:%s patm=%p %p\n", at, at->StrOfAE, patm, at->NextOfAE);
|
||||
#endif
|
||||
GLOBAL_agc_collected += sizeof(AtomEntry)+strlen((const char *)at->StrOfAE);
|
||||
}
|
||||
*patm = atm = at->NextOfAE;
|
||||
Yap_FreeCodeSpace((char *)at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the really tough part, to restore the whole of the heap
|
||||
*/
|
||||
static void
|
||||
clean_atoms(void)
|
||||
{
|
||||
AtomHashEntry *HashPtr = HashChain;
|
||||
register int i;
|
||||
|
||||
AtomResetMark(AtomFoundVar);
|
||||
AtomResetMark(AtomFreeTerm);
|
||||
for (i = 0; i < AtomHashTableSize; ++i) {
|
||||
clean_atom_list(HashPtr);
|
||||
HashPtr++;
|
||||
}
|
||||
HashPtr = WideHashChain;
|
||||
for (i = 0; i < WideAtomHashTableSize; ++i) {
|
||||
clean_atom_list(HashPtr);
|
||||
HashPtr++;
|
||||
}
|
||||
clean_atom_list(&INVISIBLECHAIN);
|
||||
{
|
||||
AtomHashEntry list;
|
||||
list.Entry = Blobs;
|
||||
clean_atom_list(&list);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
atom_gc(USES_REGS1)
|
||||
{
|
||||
int gc_verbose = Yap_is_gc_verbose();
|
||||
int gc_trace = 0;
|
||||
|
||||
|
||||
UInt time_start, agc_time;
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
return;
|
||||
#endif
|
||||
if (Yap_GetValue(AtomGcTrace) != TermNil)
|
||||
gc_trace = 1;
|
||||
|
||||
GLOBAL_agc_calls++;
|
||||
GLOBAL_agc_collected = 0;
|
||||
|
||||
if (gc_trace) {
|
||||
fprintf(stderr, "%% agc:\n");
|
||||
} else if (gc_verbose) {
|
||||
fprintf(stderr, "%% Start of atom garbage collection %d:\n", GLOBAL_agc_calls);
|
||||
}
|
||||
time_start = Yap_cputime();
|
||||
/* get the number of active registers */
|
||||
YAPEnterCriticalSection();
|
||||
init_reg_copies(PASS_REGS1);
|
||||
mark_stacks(PASS_REGS1);
|
||||
restore_codes();
|
||||
clean_atoms();
|
||||
NOfBlobsMax = NOfBlobs+(NOfBlobs/2+256< 1024 ? NOfBlobs/2+256 : 1024);
|
||||
YAPLeaveCriticalSection();
|
||||
agc_time = Yap_cputime()-time_start;
|
||||
GLOBAL_tot_agc_time += agc_time;
|
||||
GLOBAL_tot_agc_recovered += GLOBAL_agc_collected;
|
||||
if (gc_verbose) {
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "%% Collected %I64d bytes.\n", GLOBAL_agc_collected);
|
||||
#else
|
||||
fprintf(stderr, "%% Collected %lld bytes.\n", GLOBAL_agc_collected);
|
||||
#endif
|
||||
fprintf(stderr, "%% GC %d took %g sec, total of %g sec doing GC so far.\n", GLOBAL_agc_calls, (double)agc_time/1000, (double)GLOBAL_tot_agc_time/1000);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_atom_gc(USES_REGS1)
|
||||
{
|
||||
atom_gc(PASS_REGS1);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_atom_gc(USES_REGS1)
|
||||
{
|
||||
#ifndef FIXED_STACKS
|
||||
atom_gc(PASS_REGS1);
|
||||
#endif /* FIXED_STACKS */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_inform_agc(USES_REGS1)
|
||||
{
|
||||
Term tn = MkIntegerTerm(GLOBAL_tot_agc_time);
|
||||
Term tt = MkIntegerTerm(GLOBAL_agc_calls);
|
||||
Term ts = MkIntegerTerm(GLOBAL_tot_agc_recovered);
|
||||
|
||||
return
|
||||
Yap_unify(tn, ARG2) &&
|
||||
Yap_unify(tt, ARG1) &&
|
||||
Yap_unify(ts, ARG3);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_agc_threshold(USES_REGS1)
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t)) {
|
||||
return Yap_unify(ARG1, MkIntegerTerm(GLOBAL_AGcThreshold));
|
||||
} else if (!IsIntegerTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER,t,"prolog_flag/2 agc_margin");
|
||||
return FALSE;
|
||||
} else {
|
||||
Int i = IntegerOfTerm(t);
|
||||
if (i<0) {
|
||||
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO,t,"prolog_flag/2 agc_margin");
|
||||
return FALSE;
|
||||
} else {
|
||||
GLOBAL_AGcThreshold = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_init_agc(void)
|
||||
{
|
||||
Yap_InitCPred("$atom_gc", 0, p_atom_gc, 0);
|
||||
Yap_InitCPred("$inform_agc", 3, p_inform_agc, 0);
|
||||
Yap_InitCPred("$agc_threshold", 1, p_agc_threshold, SafePredFlag);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,886 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: analyst.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: Tracing the abstract machine *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
|
||||
#endif
|
||||
|
||||
#include "Yap.h"
|
||||
|
||||
#ifdef ANALYST
|
||||
#include "Yatom.h"
|
||||
#include "yapio.h"
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
static Int p_reset_op_counters(void);
|
||||
static Int p_show_op_counters(void);
|
||||
static Int p_show_ops_by_group(void);
|
||||
|
||||
static Int
|
||||
p_reset_op_counters()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= _std_top; ++i)
|
||||
GLOBAL_opcount[i] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
print_instruction(int inst)
|
||||
{
|
||||
int j;
|
||||
|
||||
fprintf(GLOBAL_stderr, "%s", Yap_op_names[inst]);
|
||||
for (j = strlen(Yap_op_names[inst]); j < 25; j++)
|
||||
putc(' ', GLOBAL_stderr);
|
||||
j = GLOBAL_opcount[inst];
|
||||
if (j < 100000000) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 10000000) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 1000000) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 100000) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 10000) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 1000) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 100) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
if (j < 10) {
|
||||
putc(' ', GLOBAL_stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(GLOBAL_stderr, "%llu\n", GLOBAL_opcount[inst]);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_show_op_counters()
|
||||
{
|
||||
int i;
|
||||
Term t1 = Deref(ARG1);
|
||||
|
||||
if (IsVarTerm(t1) || !IsAtomTerm(t1)) {
|
||||
return FALSE;
|
||||
} else {
|
||||
Atom at1 = AtomOfTerm(t1);
|
||||
|
||||
if (IsWideAtom(at1)) {
|
||||
wchar_t *program;
|
||||
|
||||
program = RepAtom(at1)->WStrOfAE;
|
||||
fprintf(GLOBAL_stderr, "\n Instructions Executed in %S\n", program);
|
||||
} else {
|
||||
char *program;
|
||||
|
||||
program = RepAtom(at1)->StrOfAE;
|
||||
fprintf(GLOBAL_stderr, "\n Instructions Executed in %s\n", program);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= _std_top; ++i)
|
||||
print_instruction(i);
|
||||
fprintf(GLOBAL_stderr, "\n Control Instructions \n");
|
||||
print_instruction(_op_fail);
|
||||
print_instruction(_execute);
|
||||
print_instruction(_dexecute);
|
||||
print_instruction(_call);
|
||||
print_instruction(_fcall);
|
||||
print_instruction(_call_cpred);
|
||||
print_instruction(_call_c_wfail);
|
||||
print_instruction(_procceed);
|
||||
print_instruction(_allocate);
|
||||
print_instruction(_deallocate);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Choice Point Manipulation Instructions\n");
|
||||
print_instruction(_try_me);
|
||||
print_instruction(_retry_me);
|
||||
print_instruction(_trust_me);
|
||||
print_instruction(_try_clause);
|
||||
print_instruction(_try_in);
|
||||
print_instruction(_retry);
|
||||
print_instruction(_trust);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Disjunction Instructions\n");
|
||||
print_instruction(_either);
|
||||
print_instruction(_or_else);
|
||||
print_instruction(_or_last);
|
||||
print_instruction(_jump);
|
||||
print_instruction(_move_back);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Dynamic Predicates Choicepoint Instructions\n");
|
||||
print_instruction(_try_and_mark);
|
||||
print_instruction(_retry_and_mark);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n C Predicates Choicepoint Instructions\n");
|
||||
print_instruction(_try_c);
|
||||
print_instruction(_retry_c);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Indexing Instructions\n");
|
||||
fprintf(GLOBAL_stderr, "\n Switch on Type\n");
|
||||
print_instruction(_switch_on_type);
|
||||
print_instruction(_switch_list_nl);
|
||||
print_instruction(_switch_on_arg_type);
|
||||
print_instruction(_switch_on_sub_arg_type);
|
||||
fprintf(GLOBAL_stderr, "\n Switch on Value\n");
|
||||
print_instruction(_if_cons);
|
||||
print_instruction(_go_on_cons);
|
||||
print_instruction(_switch_on_cons);
|
||||
print_instruction(_if_func);
|
||||
print_instruction(_go_on_func);
|
||||
print_instruction(_switch_on_func);
|
||||
fprintf(GLOBAL_stderr, "\n Other Switches\n");
|
||||
print_instruction(_if_not_then);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Get Instructions\n");
|
||||
print_instruction(_get_x_var);
|
||||
print_instruction(_get_y_var);
|
||||
print_instruction(_get_x_val);
|
||||
print_instruction(_get_y_val);
|
||||
print_instruction(_get_atom);
|
||||
print_instruction(_get_2atoms);
|
||||
print_instruction(_get_3atoms);
|
||||
print_instruction(_get_4atoms);
|
||||
print_instruction(_get_5atoms);
|
||||
print_instruction(_get_6atoms);
|
||||
print_instruction(_get_list);
|
||||
print_instruction(_get_struct);
|
||||
fprintf(GLOBAL_stderr, "\n Optimised Get Instructions\n");
|
||||
print_instruction(_glist_valx);
|
||||
print_instruction(_glist_valy);
|
||||
print_instruction(_gl_void_varx);
|
||||
print_instruction(_gl_void_vary);
|
||||
print_instruction(_gl_void_valx);
|
||||
print_instruction(_gl_void_valy);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Unify Read Instructions\n");
|
||||
print_instruction(_unify_x_var);
|
||||
print_instruction(_unify_x_var2);
|
||||
print_instruction(_unify_y_var);
|
||||
print_instruction(_unify_x_val);
|
||||
print_instruction(_unify_y_val);
|
||||
print_instruction(_unify_x_loc);
|
||||
print_instruction(_unify_y_loc);
|
||||
print_instruction(_unify_atom);
|
||||
print_instruction(_unify_n_atoms);
|
||||
print_instruction(_unify_n_voids);
|
||||
print_instruction(_unify_list);
|
||||
print_instruction(_unify_struct);
|
||||
fprintf(GLOBAL_stderr, "\n Unify Last Read Instructions\n");
|
||||
print_instruction(_unify_l_x_var);
|
||||
print_instruction(_unify_l_x_var2);
|
||||
print_instruction(_unify_l_y_var);
|
||||
print_instruction(_unify_l_x_val);
|
||||
print_instruction(_unify_l_y_val);
|
||||
print_instruction(_unify_l_x_loc);
|
||||
print_instruction(_unify_l_y_loc);
|
||||
print_instruction(_unify_l_atom);
|
||||
print_instruction(_unify_l_n_voids);
|
||||
print_instruction(_unify_l_list);
|
||||
print_instruction(_unify_l_struc);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Unify Write Instructions\n");
|
||||
print_instruction(_unify_x_var_write);
|
||||
print_instruction(_unify_x_var2_write);
|
||||
print_instruction(_unify_y_var_write);
|
||||
print_instruction(_unify_x_val_write);
|
||||
print_instruction(_unify_y_val_write);
|
||||
print_instruction(_unify_x_loc_write);
|
||||
print_instruction(_unify_y_loc_write);
|
||||
print_instruction(_unify_atom_write);
|
||||
print_instruction(_unify_n_atoms_write);
|
||||
print_instruction(_unify_n_voids_write);
|
||||
print_instruction(_unify_list_write);
|
||||
print_instruction(_unify_struct_write);
|
||||
fprintf(GLOBAL_stderr, "\n Unify Last Read Instructions\n");
|
||||
print_instruction(_unify_l_x_var_write);
|
||||
print_instruction(_unify_l_x_var2_write);
|
||||
print_instruction(_unify_l_y_var_write);
|
||||
print_instruction(_unify_l_x_val_write);
|
||||
print_instruction(_unify_l_y_val_write);
|
||||
print_instruction(_unify_l_x_loc_write);
|
||||
print_instruction(_unify_l_y_loc_write);
|
||||
print_instruction(_unify_l_atom_write);
|
||||
print_instruction(_unify_l_n_voids_write);
|
||||
print_instruction(_unify_l_list_write);
|
||||
print_instruction(_unify_l_struc_write);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Put Instructions\n");
|
||||
print_instruction(_put_x_var);
|
||||
print_instruction(_put_y_var);
|
||||
print_instruction(_put_x_val);
|
||||
print_instruction(_put_xx_val);
|
||||
print_instruction(_put_y_val);
|
||||
print_instruction(_put_unsafe);
|
||||
print_instruction(_put_atom);
|
||||
print_instruction(_put_list);
|
||||
print_instruction(_put_struct);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Write Instructions\n");
|
||||
print_instruction(_write_x_var);
|
||||
print_instruction(_write_y_var);
|
||||
print_instruction(_write_x_val);
|
||||
print_instruction(_write_y_val);
|
||||
print_instruction(_write_x_loc);
|
||||
print_instruction(_write_y_loc);
|
||||
print_instruction(_write_atom);
|
||||
print_instruction(_write_n_atoms);
|
||||
print_instruction(_write_n_voids);
|
||||
print_instruction(_write_list);
|
||||
print_instruction(_write_struct);
|
||||
fprintf(GLOBAL_stderr, "\n Last Write Instructions\n");
|
||||
print_instruction(_write_l_list);
|
||||
print_instruction(_write_l_struc);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Miscellaneous Instructions\n");
|
||||
print_instruction(_cut);
|
||||
print_instruction(_cut_t);
|
||||
print_instruction(_cut_e);
|
||||
print_instruction(_skip);
|
||||
print_instruction(_pop);
|
||||
print_instruction(_pop_n);
|
||||
print_instruction(_trust_fail);
|
||||
print_instruction(_index_pred);
|
||||
print_instruction(_lock_pred);
|
||||
#if THREADS
|
||||
print_instruction(_thread_local);
|
||||
#endif
|
||||
print_instruction(_save_b_x);
|
||||
print_instruction(_save_b_y);
|
||||
print_instruction(_save_pair_x);
|
||||
print_instruction(_save_pair_y);
|
||||
print_instruction(_save_pair_x_write);
|
||||
print_instruction(_save_pair_y_write);
|
||||
print_instruction(_save_appl_x);
|
||||
print_instruction(_save_appl_y);
|
||||
print_instruction(_save_appl_x_write);
|
||||
print_instruction(_save_appl_y_write);
|
||||
print_instruction(_Ystop);
|
||||
print_instruction(_Nstop);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int nxvar, nxval, nyvar, nyval, ncons, nlist, nstru, nmisc;
|
||||
} uGLOBAL_opcount;
|
||||
|
||||
typedef struct {
|
||||
int ncalls, nexecs, nproceeds, ncallbips, ncuts, nallocs, ndeallocs;
|
||||
} cGLOBAL_opcount;
|
||||
|
||||
typedef struct {
|
||||
int ntries, nretries, ntrusts;
|
||||
} ccpcount;
|
||||
|
||||
static Int
|
||||
p_show_ops_by_group(void)
|
||||
{
|
||||
|
||||
uGLOBAL_opcount c_get, c_unify, c_put, c_write;
|
||||
cGLOBAL_opcount c_control;
|
||||
ccpcount c_cp;
|
||||
int gets, unifies, puts, writes, controls, choice_pts, indexes, misc,
|
||||
total;
|
||||
Term t1;
|
||||
Atom at1;
|
||||
|
||||
t1 = Deref(ARG1);
|
||||
if (IsVarTerm(t1) || !IsAtomTerm(t1))
|
||||
return (FALSE);
|
||||
at1 = AtomOfTerm(t1);
|
||||
if (IsWideAtom(at1)) {
|
||||
wchar_t *program;
|
||||
|
||||
program = RepAtom(at1)->WStrOfAE;
|
||||
fprintf(GLOBAL_stderr, "\n Instructions Executed in %S\n", program);
|
||||
} else {
|
||||
char *program;
|
||||
|
||||
program = RepAtom(at1)->StrOfAE;
|
||||
fprintf(GLOBAL_stderr, "\n Instructions Executed in %s\n", program);
|
||||
}
|
||||
|
||||
c_get.nxvar =
|
||||
GLOBAL_opcount[_get_x_var];
|
||||
c_get.nyvar =
|
||||
GLOBAL_opcount[_get_y_var];
|
||||
c_get.nxval =
|
||||
GLOBAL_opcount[_get_x_val];
|
||||
c_get.nyval =
|
||||
GLOBAL_opcount[_get_y_val];
|
||||
c_get.ncons =
|
||||
GLOBAL_opcount[_get_atom]+
|
||||
GLOBAL_opcount[_get_2atoms]+
|
||||
GLOBAL_opcount[_get_3atoms]+
|
||||
GLOBAL_opcount[_get_4atoms]+
|
||||
GLOBAL_opcount[_get_5atoms]+
|
||||
GLOBAL_opcount[_get_6atoms];
|
||||
c_get.nlist =
|
||||
GLOBAL_opcount[_get_list] +
|
||||
GLOBAL_opcount[_glist_valx] +
|
||||
GLOBAL_opcount[_glist_valy] +
|
||||
GLOBAL_opcount[_gl_void_varx] +
|
||||
GLOBAL_opcount[_gl_void_vary] +
|
||||
GLOBAL_opcount[_gl_void_valx] +
|
||||
GLOBAL_opcount[_gl_void_valy];
|
||||
c_get.nstru =
|
||||
GLOBAL_opcount[_get_struct];
|
||||
|
||||
gets = c_get.nxvar + c_get.nyvar + c_get.nxval + c_get.nyval +
|
||||
c_get.ncons + c_get.nlist + c_get.nstru;
|
||||
|
||||
c_unify.nxvar =
|
||||
GLOBAL_opcount[_unify_x_var] +
|
||||
GLOBAL_opcount[_unify_void] +
|
||||
GLOBAL_opcount[_unify_n_voids] +
|
||||
2 * GLOBAL_opcount[_unify_x_var2] +
|
||||
2 * GLOBAL_opcount[_gl_void_varx] +
|
||||
GLOBAL_opcount[_gl_void_vary] +
|
||||
GLOBAL_opcount[_gl_void_valx] +
|
||||
GLOBAL_opcount[_unify_l_x_var] +
|
||||
GLOBAL_opcount[_unify_l_void] +
|
||||
GLOBAL_opcount[_unify_l_n_voids] +
|
||||
2 * GLOBAL_opcount[_unify_l_x_var2] +
|
||||
GLOBAL_opcount[_unify_x_var_write] +
|
||||
GLOBAL_opcount[_unify_void_write] +
|
||||
GLOBAL_opcount[_unify_n_voids_write] +
|
||||
2 * GLOBAL_opcount[_unify_x_var2_write] +
|
||||
GLOBAL_opcount[_unify_l_x_var_write] +
|
||||
GLOBAL_opcount[_unify_l_void_write] +
|
||||
GLOBAL_opcount[_unify_l_n_voids_write] +
|
||||
2 * GLOBAL_opcount[_unify_l_x_var2_write];
|
||||
c_unify.nyvar =
|
||||
GLOBAL_opcount[_unify_y_var] +
|
||||
GLOBAL_opcount[_gl_void_vary] +
|
||||
GLOBAL_opcount[_unify_l_y_var] +
|
||||
GLOBAL_opcount[_unify_y_var_write] +
|
||||
GLOBAL_opcount[_unify_l_y_var_write];
|
||||
c_unify.nxval =
|
||||
GLOBAL_opcount[_unify_x_val] +
|
||||
GLOBAL_opcount[_unify_x_loc] +
|
||||
GLOBAL_opcount[_glist_valx] +
|
||||
GLOBAL_opcount[_gl_void_valx] +
|
||||
GLOBAL_opcount[_unify_l_x_val] +
|
||||
GLOBAL_opcount[_unify_l_x_loc] +
|
||||
GLOBAL_opcount[_unify_x_val_write] +
|
||||
GLOBAL_opcount[_unify_x_loc_write] +
|
||||
GLOBAL_opcount[_unify_l_x_val_write] +
|
||||
GLOBAL_opcount[_unify_l_x_loc_write];
|
||||
c_unify.nyval =
|
||||
GLOBAL_opcount[_unify_y_val] +
|
||||
GLOBAL_opcount[_unify_y_loc] +
|
||||
GLOBAL_opcount[_glist_valy] +
|
||||
GLOBAL_opcount[_gl_void_valy] +
|
||||
GLOBAL_opcount[_unify_l_y_val] +
|
||||
GLOBAL_opcount[_unify_l_y_loc] +
|
||||
GLOBAL_opcount[_unify_y_val_write] +
|
||||
GLOBAL_opcount[_unify_y_loc_write] +
|
||||
GLOBAL_opcount[_unify_l_y_val_write] +
|
||||
GLOBAL_opcount[_unify_l_y_loc_write];
|
||||
c_unify.ncons =
|
||||
GLOBAL_opcount[_unify_atom] +
|
||||
GLOBAL_opcount[_unify_n_atoms] +
|
||||
GLOBAL_opcount[_unify_l_atom] +
|
||||
GLOBAL_opcount[_unify_atom_write] +
|
||||
GLOBAL_opcount[_unify_n_atoms_write] +
|
||||
GLOBAL_opcount[_unify_l_atom_write];
|
||||
c_unify.nlist =
|
||||
GLOBAL_opcount[_unify_list] +
|
||||
GLOBAL_opcount[_unify_l_list] +
|
||||
GLOBAL_opcount[_unify_list_write] +
|
||||
GLOBAL_opcount[_unify_l_list_write];
|
||||
c_unify.nstru =
|
||||
GLOBAL_opcount[_unify_struct] +
|
||||
GLOBAL_opcount[_unify_l_struc] +
|
||||
GLOBAL_opcount[_unify_struct_write] +
|
||||
GLOBAL_opcount[_unify_l_struc_write];
|
||||
c_unify.nmisc =
|
||||
GLOBAL_opcount[_pop] +
|
||||
GLOBAL_opcount[_pop_n];
|
||||
|
||||
unifies = c_unify.nxvar + c_unify.nyvar + c_unify.nxval + c_unify.nyval +
|
||||
c_unify.ncons + c_unify.nlist + c_unify.nstru + c_unify.nmisc;
|
||||
|
||||
c_put.nxvar =
|
||||
GLOBAL_opcount[_put_x_var];
|
||||
c_put.nyvar =
|
||||
GLOBAL_opcount[_put_y_var];
|
||||
c_put.nxval =
|
||||
GLOBAL_opcount[_put_x_val]+
|
||||
2*GLOBAL_opcount[_put_xx_val];
|
||||
c_put.nyval =
|
||||
GLOBAL_opcount[_put_y_val];
|
||||
c_put.ncons =
|
||||
GLOBAL_opcount[_put_atom];
|
||||
c_put.nlist =
|
||||
GLOBAL_opcount[_put_list];
|
||||
c_put.nstru =
|
||||
GLOBAL_opcount[_put_struct];
|
||||
|
||||
puts = c_put.nxvar + c_put.nyvar + c_put.nxval + c_put.nyval +
|
||||
c_put.ncons + c_put.nlist + c_put.nstru;
|
||||
|
||||
c_write.nxvar =
|
||||
GLOBAL_opcount[_write_x_var] +
|
||||
GLOBAL_opcount[_write_void] +
|
||||
GLOBAL_opcount[_write_n_voids];
|
||||
c_write.nyvar =
|
||||
GLOBAL_opcount[_write_y_var];
|
||||
c_write.nxval =
|
||||
GLOBAL_opcount[_write_x_val];
|
||||
c_write.nyval =
|
||||
GLOBAL_opcount[_write_y_val];
|
||||
c_write.ncons =
|
||||
GLOBAL_opcount[_write_atom];
|
||||
c_write.nlist =
|
||||
GLOBAL_opcount[_write_list];
|
||||
c_write.nstru =
|
||||
GLOBAL_opcount[_write_struct];
|
||||
|
||||
writes = c_write.nxvar + c_write.nyvar + c_write.nxval + c_write.nyval +
|
||||
c_write.ncons + c_write.nlist + c_write.nstru;
|
||||
|
||||
c_control.nexecs =
|
||||
GLOBAL_opcount[_execute] +
|
||||
GLOBAL_opcount[_dexecute];
|
||||
|
||||
c_control.ncalls =
|
||||
GLOBAL_opcount[_call] +
|
||||
GLOBAL_opcount[_fcall];
|
||||
|
||||
c_control.nproceeds =
|
||||
GLOBAL_opcount[_procceed];
|
||||
|
||||
c_control.ncallbips =
|
||||
GLOBAL_opcount[_call_cpred] +
|
||||
GLOBAL_opcount[_call_c_wfail] +
|
||||
GLOBAL_opcount[_try_c] +
|
||||
GLOBAL_opcount[_retry_c] +
|
||||
GLOBAL_opcount[_op_fail] +
|
||||
GLOBAL_opcount[_trust_fail] +
|
||||
GLOBAL_opcount[_p_atom_x] +
|
||||
GLOBAL_opcount[_p_atom_y] +
|
||||
GLOBAL_opcount[_p_atomic_x] +
|
||||
GLOBAL_opcount[_p_atomic_y] +
|
||||
GLOBAL_opcount[_p_compound_x] +
|
||||
GLOBAL_opcount[_p_compound_y] +
|
||||
GLOBAL_opcount[_p_float_x] +
|
||||
GLOBAL_opcount[_p_float_y] +
|
||||
GLOBAL_opcount[_p_integer_x] +
|
||||
GLOBAL_opcount[_p_integer_y] +
|
||||
GLOBAL_opcount[_p_nonvar_x] +
|
||||
GLOBAL_opcount[_p_nonvar_y] +
|
||||
GLOBAL_opcount[_p_number_x] +
|
||||
GLOBAL_opcount[_p_number_y] +
|
||||
GLOBAL_opcount[_p_var_x] +
|
||||
GLOBAL_opcount[_p_var_y] +
|
||||
GLOBAL_opcount[_p_db_ref_x] +
|
||||
GLOBAL_opcount[_p_db_ref_y] +
|
||||
GLOBAL_opcount[_p_cut_by_x] +
|
||||
GLOBAL_opcount[_p_cut_by_y] +
|
||||
GLOBAL_opcount[_p_primitive_x] +
|
||||
GLOBAL_opcount[_p_primitive_y] +
|
||||
GLOBAL_opcount[_p_equal] +
|
||||
GLOBAL_opcount[_p_plus_vv] +
|
||||
GLOBAL_opcount[_p_plus_vc] +
|
||||
GLOBAL_opcount[_p_plus_y_vv] +
|
||||
GLOBAL_opcount[_p_plus_y_vc] +
|
||||
GLOBAL_opcount[_p_minus_vv] +
|
||||
GLOBAL_opcount[_p_minus_cv] +
|
||||
GLOBAL_opcount[_p_minus_y_vv] +
|
||||
GLOBAL_opcount[_p_minus_y_cv] +
|
||||
GLOBAL_opcount[_p_times_vv] +
|
||||
GLOBAL_opcount[_p_times_vc] +
|
||||
GLOBAL_opcount[_p_times_y_vv] +
|
||||
GLOBAL_opcount[_p_times_y_vc] +
|
||||
GLOBAL_opcount[_p_div_vv] +
|
||||
GLOBAL_opcount[_p_div_vc] +
|
||||
GLOBAL_opcount[_p_div_cv] +
|
||||
GLOBAL_opcount[_p_div_y_vv] +
|
||||
GLOBAL_opcount[_p_div_y_vc] +
|
||||
GLOBAL_opcount[_p_div_y_cv] +
|
||||
GLOBAL_opcount[_p_or_vv] +
|
||||
GLOBAL_opcount[_p_or_vc] +
|
||||
GLOBAL_opcount[_p_or_y_vv] +
|
||||
GLOBAL_opcount[_p_or_y_vc] +
|
||||
GLOBAL_opcount[_p_and_vv] +
|
||||
GLOBAL_opcount[_p_and_vc] +
|
||||
GLOBAL_opcount[_p_and_y_vv] +
|
||||
GLOBAL_opcount[_p_and_y_vc] +
|
||||
GLOBAL_opcount[_p_sll_vv] +
|
||||
GLOBAL_opcount[_p_sll_vc] +
|
||||
GLOBAL_opcount[_p_sll_y_vv] +
|
||||
GLOBAL_opcount[_p_sll_y_vc] +
|
||||
GLOBAL_opcount[_p_slr_vv] +
|
||||
GLOBAL_opcount[_p_slr_vc] +
|
||||
GLOBAL_opcount[_p_slr_y_vv] +
|
||||
GLOBAL_opcount[_p_slr_y_vc] +
|
||||
GLOBAL_opcount[_p_dif] +
|
||||
GLOBAL_opcount[_p_eq] +
|
||||
GLOBAL_opcount[_p_arg_vv] +
|
||||
GLOBAL_opcount[_p_arg_cv] +
|
||||
GLOBAL_opcount[_p_arg_y_vv] +
|
||||
GLOBAL_opcount[_p_arg_y_cv] +
|
||||
GLOBAL_opcount[_p_functor] +
|
||||
GLOBAL_opcount[_p_func2s_vv] +
|
||||
GLOBAL_opcount[_p_func2s_cv] +
|
||||
GLOBAL_opcount[_p_func2s_vc] +
|
||||
GLOBAL_opcount[_p_func2s_y_vv] +
|
||||
GLOBAL_opcount[_p_func2s_y_cv] +
|
||||
GLOBAL_opcount[_p_func2s_y_vc] +
|
||||
GLOBAL_opcount[_p_func2f_xx] +
|
||||
GLOBAL_opcount[_p_func2f_xy] +
|
||||
GLOBAL_opcount[_p_func2f_yx] +
|
||||
GLOBAL_opcount[_p_func2f_yy];
|
||||
|
||||
c_control.ncuts =
|
||||
GLOBAL_opcount[_cut] +
|
||||
GLOBAL_opcount[_cut_t] +
|
||||
GLOBAL_opcount[_cut_e] +
|
||||
GLOBAL_opcount[_commit_b_x] +
|
||||
GLOBAL_opcount[_commit_b_y];
|
||||
|
||||
c_control.nallocs =
|
||||
GLOBAL_opcount[_allocate] +
|
||||
GLOBAL_opcount[_fcall];
|
||||
|
||||
c_control.ndeallocs =
|
||||
GLOBAL_opcount[_dexecute] +
|
||||
GLOBAL_opcount[_deallocate];
|
||||
|
||||
controls =
|
||||
c_control.nexecs +
|
||||
c_control.ncalls +
|
||||
c_control.nproceeds +
|
||||
c_control.ncuts +
|
||||
c_control.nallocs +
|
||||
c_control.ndeallocs +
|
||||
GLOBAL_opcount[_jump] +
|
||||
GLOBAL_opcount[_move_back] +
|
||||
GLOBAL_opcount[_try_in];
|
||||
|
||||
|
||||
|
||||
c_cp.ntries =
|
||||
GLOBAL_opcount[_try_me] +
|
||||
GLOBAL_opcount[_try_and_mark] +
|
||||
GLOBAL_opcount[_try_c] +
|
||||
GLOBAL_opcount[_try_clause] +
|
||||
GLOBAL_opcount[_either];
|
||||
|
||||
c_cp.nretries =
|
||||
GLOBAL_opcount[_retry_me] +
|
||||
GLOBAL_opcount[_retry_and_mark] +
|
||||
GLOBAL_opcount[_retry_c] +
|
||||
GLOBAL_opcount[_retry] +
|
||||
GLOBAL_opcount[_or_else];
|
||||
|
||||
c_cp.ntrusts =
|
||||
GLOBAL_opcount[_trust_me] +
|
||||
GLOBAL_opcount[_trust] +
|
||||
GLOBAL_opcount[_or_last];
|
||||
|
||||
choice_pts =
|
||||
c_cp.ntries +
|
||||
c_cp.nretries +
|
||||
c_cp.ntrusts;
|
||||
|
||||
indexes =
|
||||
GLOBAL_opcount[_jump_if_var] +
|
||||
GLOBAL_opcount[_switch_on_type] +
|
||||
GLOBAL_opcount[_switch_list_nl] +
|
||||
GLOBAL_opcount[_switch_on_arg_type] +
|
||||
GLOBAL_opcount[_switch_on_sub_arg_type] +
|
||||
GLOBAL_opcount[_switch_on_cons] +
|
||||
GLOBAL_opcount[_go_on_cons] +
|
||||
GLOBAL_opcount[_if_cons] +
|
||||
GLOBAL_opcount[_switch_on_func] +
|
||||
GLOBAL_opcount[_go_on_func] +
|
||||
GLOBAL_opcount[_if_func] +
|
||||
GLOBAL_opcount[_if_not_then];
|
||||
misc =
|
||||
c_control.ncallbips +
|
||||
GLOBAL_opcount[_Ystop] +
|
||||
GLOBAL_opcount[_Nstop] +
|
||||
GLOBAL_opcount[_index_pred] +
|
||||
GLOBAL_opcount[_lock_pred] +
|
||||
#if THREADS
|
||||
GLOBAL_opcount[_thread_local] +
|
||||
#endif
|
||||
GLOBAL_opcount[_save_b_x] +
|
||||
GLOBAL_opcount[_save_b_y] +
|
||||
GLOBAL_opcount[_undef_p] +
|
||||
GLOBAL_opcount[_spy_pred] +
|
||||
GLOBAL_opcount[_spy_or_trymark] +
|
||||
GLOBAL_opcount[_save_pair_x] +
|
||||
GLOBAL_opcount[_save_pair_y] +
|
||||
GLOBAL_opcount[_save_pair_x_write] +
|
||||
GLOBAL_opcount[_save_pair_y_write] +
|
||||
GLOBAL_opcount[_save_appl_x] +
|
||||
GLOBAL_opcount[_save_appl_y] +
|
||||
GLOBAL_opcount[_save_appl_x_write] +
|
||||
GLOBAL_opcount[_save_appl_y_write];
|
||||
total = gets + unifies + puts + writes + controls + choice_pts + indexes + misc;
|
||||
|
||||
/* for (i = 0; i <= _std_top; ++i)
|
||||
* print_instruction(i);
|
||||
*/
|
||||
|
||||
fprintf(GLOBAL_stderr, "Groups are\n\n");
|
||||
fprintf(GLOBAL_stderr, " GET instructions: %8d (%3d%%)\n", gets,
|
||||
(gets * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " UNIFY instructions: %8d (%3d%%)\n", unifies,
|
||||
(unifies * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " PUT instructions: %8d (%3d%%)\n", puts,
|
||||
(puts * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " WRITE instructions: %8d (%3d%%)\n", writes,
|
||||
(writes * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " CONTROL instructions: %8d (%3d%%)\n", controls,
|
||||
(controls * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " CHOICE POINT instructions: %8d (%3d%%)\n", choice_pts,
|
||||
(choice_pts * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " INDEXING instructions: %8d (%3d%%)\n", indexes,
|
||||
(indexes * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " MISCELLANEOUS instructions: %8d (%3d%%)\n", misc,
|
||||
(misc * 100) / total);
|
||||
fprintf(GLOBAL_stderr, "_______________________________________________\n");
|
||||
fprintf(GLOBAL_stderr, " TOTAL instructions: %8d (%3d%%)\n\n", total,
|
||||
(total * 100) / total);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Analysis of Unification Instructions in %s \n", program);
|
||||
fprintf(GLOBAL_stderr, " XVAR, YVAR, XVAL, YVAL, CONS, LIST, STRUCT\n");
|
||||
fprintf(GLOBAL_stderr, " GET: %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
c_get.nxvar,
|
||||
c_get.nyvar,
|
||||
c_get.nxval,
|
||||
c_get.nyval,
|
||||
c_get.ncons,
|
||||
c_get.nlist,
|
||||
c_get.nstru);
|
||||
fprintf(GLOBAL_stderr, "UNIFY: %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
c_unify.nxvar,
|
||||
c_unify.nyvar,
|
||||
c_unify.nxval,
|
||||
c_unify.nyval,
|
||||
c_unify.ncons,
|
||||
c_unify.nlist,
|
||||
c_unify.nstru);
|
||||
fprintf(GLOBAL_stderr, " PUT: %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
c_put.nxvar,
|
||||
c_put.nyvar,
|
||||
c_put.nxval,
|
||||
c_put.nyval,
|
||||
c_put.ncons,
|
||||
c_put.nlist,
|
||||
c_put.nstru);
|
||||
fprintf(GLOBAL_stderr, "WRITE: %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
c_write.nxvar,
|
||||
c_write.nyvar,
|
||||
c_write.nxval,
|
||||
c_write.nyval,
|
||||
c_write.ncons,
|
||||
c_write.nlist,
|
||||
c_write.nstru);
|
||||
fprintf(GLOBAL_stderr, " ___________________________________________________\n");
|
||||
fprintf(GLOBAL_stderr, "TOTAL: %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
c_get.nxvar + c_unify.nxvar + c_put.nxvar + c_write.nxvar,
|
||||
c_get.nyvar + c_unify.nyvar + c_put.nyvar + c_write.nyvar,
|
||||
c_get.nxval + c_unify.nxval + c_put.nxval + c_write.nxval,
|
||||
c_get.nyval + c_unify.nyval + c_put.nyval + c_write.nyval,
|
||||
c_get.ncons + c_unify.ncons + c_put.ncons + c_write.ncons,
|
||||
c_get.nlist + c_unify.nlist + c_put.nlist + c_write.nlist,
|
||||
c_get.nstru + c_unify.nstru + c_put.nstru + c_write.nstru
|
||||
);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Analysis of Unification Instructions in %s \n", program);
|
||||
fprintf(GLOBAL_stderr, " XVAR, YVAR, XVAL, YVAL, CONS, LIST, STRUCT\n");
|
||||
fprintf(GLOBAL_stderr, " GET: %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%%\n",
|
||||
(((double) c_get.nxvar) * 100) / total,
|
||||
(((double) c_get.nyvar) * 100) / total,
|
||||
(((double) c_get.nxval) * 100) / total,
|
||||
(((double) c_get.nyval) * 100) / total,
|
||||
(((double) c_get.ncons) * 100) / total,
|
||||
(((double) c_get.nlist) * 100) / total,
|
||||
(((double) c_get.nstru) * 100) / total);
|
||||
fprintf(GLOBAL_stderr, "UNIFY: %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%%\n",
|
||||
(((double) c_unify.nxvar) * 100) / total,
|
||||
(((double) c_unify.nyvar) * 100) / total,
|
||||
(((double) c_unify.nxval) * 100) / total,
|
||||
(((double) c_unify.nyval) * 100) / total,
|
||||
(((double) c_unify.ncons) * 100) / total,
|
||||
(((double) c_unify.nlist) * 100) / total,
|
||||
(((double) c_unify.nstru) * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " PUT: %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%%\n",
|
||||
(((double) c_put.nxvar) * 100) / total,
|
||||
(((double) c_put.nyvar) * 100) / total,
|
||||
(((double) c_put.nxval) * 100) / total,
|
||||
(((double) c_put.nyval) * 100) / total,
|
||||
(((double) c_put.ncons) * 100) / total,
|
||||
(((double) c_put.nlist) * 100) / total,
|
||||
(((double) c_put.nstru) * 100) / total);
|
||||
fprintf(GLOBAL_stderr, "WRITE: %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%%\n",
|
||||
(((double) c_write.nxvar) * 100) / total,
|
||||
(((double) c_write.nyvar) * 100) / total,
|
||||
(((double) c_write.nxval) * 100) / total,
|
||||
(((double) c_write.nyval) * 100) / total,
|
||||
(((double) c_write.ncons) * 100) / total,
|
||||
(((double) c_write.nlist) * 100) / total,
|
||||
(((double) c_write.nstru) * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " ___________________________________________________\n");
|
||||
fprintf(GLOBAL_stderr, "TOTAL: %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%% %3.2f%%\n",
|
||||
(((double) c_get.nxvar + c_unify.nxvar + c_put.nxvar + c_write.nxvar) * 100) / total,
|
||||
(((double) c_get.nyvar + c_unify.nyvar + c_put.nyvar + c_write.nyvar) * 100) / total,
|
||||
(((double) c_get.nxval + c_unify.nxval + c_put.nxval + c_write.nxval) * 100) / total,
|
||||
(((double) c_get.nyval + c_unify.nyval + c_put.nyval + c_write.nyval) * 100) / total,
|
||||
(((double) c_get.ncons + c_unify.ncons + c_put.ncons + c_write.ncons) * 100) / total,
|
||||
(((double) c_get.nlist + c_unify.nlist + c_put.nlist + c_write.nlist) * 100) / total,
|
||||
(((double) c_get.nstru + c_unify.nstru + c_put.nstru + c_write.nstru) * 100) / total
|
||||
);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Control Instructions Executed in %s \n", program);
|
||||
fprintf(GLOBAL_stderr, "Grouped as\n\n");
|
||||
fprintf(GLOBAL_stderr, " CALL instructions: %8d (%3d%%)\n",
|
||||
c_control.ncalls, (c_control.ncalls * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " PROCEED instructions: %8d (%3d%%)\n",
|
||||
c_control.nproceeds, (c_control.nproceeds * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " EXECUTE instructions: %8d (%3d%%)\n",
|
||||
c_control.nexecs, (c_control.nexecs * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " CUT instructions: %8d (%3d%%)\n",
|
||||
c_control.ncuts, (c_control.ncuts * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " CALL_BIP instructions: %8d (%3d%%)\n",
|
||||
c_control.ncallbips, (c_control.ncallbips * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " ALLOCATE instructions: %8d (%3d%%)\n",
|
||||
c_control.nallocs, (c_control.nallocs * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " DEALLOCATE instructions: %8d (%3d%%)\n",
|
||||
c_control.ndeallocs, (c_control.ndeallocs * 100) / total);
|
||||
fprintf(GLOBAL_stderr, "_______________________________________________\n");
|
||||
fprintf(GLOBAL_stderr, " TOTAL instructions: %8d (%3d%%)\n\n", total,
|
||||
(total * 100) / total);
|
||||
|
||||
fprintf(GLOBAL_stderr, "\n Choice Point Manipulation Instructions Executed in %s \n", program);
|
||||
fprintf(GLOBAL_stderr, "Grouped as\n\n");
|
||||
fprintf(GLOBAL_stderr, " TRY instructions: %8d (%3d%%)\n",
|
||||
c_cp.ntries, (c_cp.ntries * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " RETRY instructions: %8d (%3d%%)\n",
|
||||
c_cp.nretries, (c_cp.nretries * 100) / total);
|
||||
fprintf(GLOBAL_stderr, " TRUST instructions: %8d (%3d%%)\n",
|
||||
c_cp.ntrusts, (c_cp.ntrusts * 100) / total);
|
||||
fprintf(GLOBAL_stderr, "_______________________________________________\n");
|
||||
fprintf(GLOBAL_stderr, " TOTAL instructions: %8d (%3d%%)\n\n", total,
|
||||
(total * 100) / total);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_show_sequences(void)
|
||||
{
|
||||
int i, j;
|
||||
YAP_ULONG_LONG min;
|
||||
YAP_ULONG_LONG sum = 0;
|
||||
Term t = Deref(ARG1);
|
||||
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t, "shows_sequences/1");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsIntegerTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, t, "shows_sequences/1");
|
||||
return FALSE;
|
||||
}
|
||||
min = (YAP_ULONG_LONG)IntegerOfTerm(t);
|
||||
if (min <= 0) {
|
||||
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t, "shows_sequences/1");
|
||||
return FALSE;
|
||||
}
|
||||
if (min <= 0) {
|
||||
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t, "shows_sequences/1");
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i <= _std_top; ++i) {
|
||||
sum += GLOBAL_opcount[i];
|
||||
}
|
||||
for (i = 0; i <= _std_top; ++i) {
|
||||
for (j = 0; j <= _std_top; ++j) {
|
||||
YAP_ULONG_LONG seqs = Yap_2opcount[i][j];
|
||||
if (seqs && sum/seqs <= min) {
|
||||
/*
|
||||
Term t[3], t0;
|
||||
Functor f =
|
||||
t[0] = Yap_MkFloatTerm(((double)seqs*100.0)/sum);
|
||||
t[1] = Yap_LookupAtom(Yap_op_names[i]);
|
||||
t[2] = Yap_LookupAtom(Yap_op_names[j]);
|
||||
t0 = MkApplTerm(
|
||||
Yap_MkPairTerm(Yap_op_names[i]
|
||||
*/
|
||||
fprintf(stderr,"%f -> %s,%s\n",((double)seqs*100.0)/sum,Yap_op_names[i],Yap_op_names[j]);
|
||||
/* we found one */
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitAnalystPreds(void)
|
||||
{
|
||||
Yap_InitCPred("wam_profiler_reset_op_counters", 0, p_reset_op_counters, SafePredFlag |SyncPredFlag);
|
||||
/** @pred wam_profiler_reset_op_counters
|
||||
|
||||
|
||||
Reinitialize all counters.
|
||||
|
||||
|
||||
*/
|
||||
Yap_InitCPred("wam_profiler_show_op_counters", 1, p_show_op_counters, SafePredFlag|SyncPredFlag);
|
||||
/** @pred wam_profiler_show_op_counters(+ _A_)
|
||||
|
||||
|
||||
Display the current value for the counters, using label _A_. The
|
||||
label must be an atom.
|
||||
|
||||
|
||||
*/
|
||||
Yap_InitCPred("wam_profiler_show_ops_by_group", 1, p_show_ops_by_group, SafePredFlag |SyncPredFlag);
|
||||
/** @pred wam_profiler_show_ops_by_group(+ _A_)
|
||||
|
||||
|
||||
Display the current value for the counters, organized by groups, using
|
||||
label _A_. The label must be an atom.
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
Yap_InitCPred("wam_profiler_show_sequences", 1, p_show_sequences, SafePredFlag |SyncPredFlag);
|
||||
}
|
||||
|
||||
#endif /* ANALYST */
|
|
@ -0,0 +1,228 @@
|
|||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Scan a list of arguments and output results to a pre-processed vector.
|
||||
*
|
||||
* @param listl: input list
|
||||
* @param def parameter definition
|
||||
*
|
||||
* @return all arguments, some of them set, some of them not.
|
||||
*/
|
||||
|
||||
static xarg *
|
||||
matchKey(Atom key, xarg *e0, int n, const param_t *def)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< n; i++) {
|
||||
if (!strcmp((char *)def->name, (char *)RepAtom(key)->StrOfAE)) {
|
||||
return e0;
|
||||
}
|
||||
def++;
|
||||
e0++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of an argument key, or -1 if not found.
|
||||
*
|
||||
*/
|
||||
int
|
||||
Yap_ArgKey(Atom key, const param_t *def, int n)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< n; i++) {
|
||||
if (!strcmp((char *)def->name, (char *)RepAtom(key)->StrOfAE)) {
|
||||
return i;
|
||||
}
|
||||
def++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static xarg *
|
||||
failed( yap_error_number e, Term t, xarg *a)
|
||||
{
|
||||
free( a );
|
||||
LOCAL_Error_TYPE = e;
|
||||
LOCAL_Error_Term = t;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
xarg *
|
||||
Yap_ArgListToVector (Term listl, const param_t *def, int n)
|
||||
{
|
||||
CACHE_REGS
|
||||
xarg *a = calloc( n , sizeof(xarg) );
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (IsApplTerm(listl) && FunctorOfTerm(listl) == FunctorModule)
|
||||
listl = ArgOfTerm(2,listl);
|
||||
if (!IsPairTerm(listl) && listl != TermNil) {
|
||||
if (IsVarTerm(listl) ) {
|
||||
return failed( INSTANTIATION_ERROR, listl, a);
|
||||
}
|
||||
if (IsAtomTerm(listl) ) {
|
||||
xarg *na = matchKey( AtomOfTerm(listl), a, n, def);
|
||||
if (!na) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
} else if (IsApplTerm(listl)) {
|
||||
Functor f = FunctorOfTerm( listl );
|
||||
if (IsExtensionFunctor(f)) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
arity_t arity = ArityOfFunctor( f );
|
||||
if (arity != 1) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
xarg *na = matchKey( NameOfFunctor( f ), a, n, def);
|
||||
if (!na) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
} else {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
listl = MkPairTerm( listl, TermNil );
|
||||
}
|
||||
while (IsPairTerm(listl)) {
|
||||
Term hd = HeadOfTerm( listl );
|
||||
listl = TailOfTerm( listl );
|
||||
if (IsVarTerm(hd) || IsVarTerm(listl)) {
|
||||
if (IsVarTerm(hd)) {
|
||||
return failed( INSTANTIATION_ERROR, hd, a);
|
||||
} else {
|
||||
return failed( INSTANTIATION_ERROR, listl, a);
|
||||
}
|
||||
}
|
||||
if (IsAtomTerm(hd)) {
|
||||
xarg *na = matchKey( AtomOfTerm( hd ), a, n, def);
|
||||
if (!na)
|
||||
return failed( DOMAIN_ERROR, hd, a);
|
||||
na->used = true;
|
||||
na->tvalue = TermNil;
|
||||
continue;
|
||||
} else if (IsApplTerm( hd )) {
|
||||
Functor f = FunctorOfTerm( hd );
|
||||
if (IsExtensionFunctor(f)) {
|
||||
return failed( TYPE_ERROR_PARAMETER, hd, a);
|
||||
}
|
||||
arity_t arity = ArityOfFunctor( f );
|
||||
if (arity != 1) {
|
||||
return failed( DOMAIN_ERROR_OUT_OF_RANGE, hd, a);
|
||||
}
|
||||
xarg *na = matchKey( NameOfFunctor( f ), a, n, def);
|
||||
if (!na) {
|
||||
return failed( DOMAIN_ERROR, hd, a);
|
||||
}
|
||||
na->used = 1;
|
||||
na->tvalue = ArgOfTerm(1, hd);
|
||||
} else {
|
||||
return failed( TYPE_ERROR_PARAMETER, hd, a);
|
||||
}
|
||||
}
|
||||
if (IsVarTerm(listl)) {
|
||||
return failed( INSTANTIATION_ERROR, listl, a);
|
||||
} else if (listl != TermNil) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static xarg *
|
||||
matchKey2(Atom key, xarg *e0, int n, const param2_t *def)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< n; i++) {
|
||||
if (!strcmp((char*)def->name, (char*)RepAtom(key)->StrOfAE)) {
|
||||
return e0;
|
||||
}
|
||||
def++;
|
||||
e0++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/// Yap_ArgList2ToVector is much the same as before,
|
||||
/// but assumes parameters also have something called a
|
||||
/// scope
|
||||
xarg *
|
||||
Yap_ArgList2ToVector (Term listl, const param2_t *def, int n)
|
||||
{
|
||||
CACHE_REGS
|
||||
xarg *a = calloc( n , sizeof(xarg) );
|
||||
if (!IsPairTerm(listl) && listl != TermNil) {
|
||||
if (IsVarTerm(listl) ) {
|
||||
return failed( INSTANTIATION_ERROR, listl, a);
|
||||
}
|
||||
if (IsAtomTerm(listl) ) {
|
||||
xarg *na = matchKey2( AtomOfTerm(listl), a, n, def);
|
||||
if (!na) {
|
||||
return failed( DOMAIN_ERROR, listl, a);
|
||||
}
|
||||
}
|
||||
if (IsApplTerm(listl)) {
|
||||
Functor f = FunctorOfTerm( listl );
|
||||
if (IsExtensionFunctor(f)) {
|
||||
return failed( TYPE_ERROR_PARAMETER, listl, a);
|
||||
}
|
||||
arity_t arity = ArityOfFunctor( f );
|
||||
if (arity != 1) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
xarg *na = matchKey2( NameOfFunctor( f ), a, n, def);
|
||||
if (!na) {
|
||||
return failed( DOMAIN_ERROR, listl, a);
|
||||
}
|
||||
} else {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
listl = MkPairTerm( listl, TermNil );
|
||||
}
|
||||
while (IsPairTerm(listl)) {
|
||||
Term hd = HeadOfTerm( listl );
|
||||
if (IsVarTerm(hd)) {
|
||||
return failed( INSTANTIATION_ERROR, hd, a);
|
||||
}
|
||||
if (IsAtomTerm(hd)) {
|
||||
xarg *na = matchKey2( AtomOfTerm( hd ), a, n, def);
|
||||
if (!na) {
|
||||
return failed( DOMAIN_ERROR, hd, a);
|
||||
}
|
||||
na->used = true;
|
||||
na->tvalue = TermNil;
|
||||
continue;
|
||||
} else if (IsApplTerm( hd )) {
|
||||
Functor f = FunctorOfTerm( hd );
|
||||
if (IsExtensionFunctor(f)) {
|
||||
return failed( TYPE_ERROR_PARAMETER, hd, a);
|
||||
}
|
||||
arity_t arity = ArityOfFunctor( f );
|
||||
if (arity != 1) {
|
||||
return failed( DOMAIN_ERROR, hd, a);
|
||||
}
|
||||
xarg *na = matchKey2( NameOfFunctor( f ), a, n, def);
|
||||
if (na) {
|
||||
na->used = 1;
|
||||
na->tvalue = ArgOfTerm(1, hd);
|
||||
} else {
|
||||
return failed( DOMAIN_ERROR, hd, a);
|
||||
}
|
||||
} else {
|
||||
return failed( INSTANTIATION_ERROR, hd, a);
|
||||
}
|
||||
listl = TailOfTerm(listl);
|
||||
}
|
||||
if (IsVarTerm(listl)) {
|
||||
return failed( INSTANTIATION_ERROR, listl, a);
|
||||
}
|
||||
if (TermNil != listl) {
|
||||
return failed( TYPE_ERROR_LIST, listl, a);
|
||||
}
|
||||
return a;
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: eval.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: arithmetical expression evaluation *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
/**
|
||||
@file arith0.c
|
||||
|
||||
*/
|
||||
|
||||
//! @{
|
||||
|
||||
/**
|
||||
@defgroup arithmetic_operators Arithmetic Functions
|
||||
@ingroup arithmetic
|
||||
|
||||
YAP implements several arithmetic functions, they are defined as
|
||||
fields in three enumerations, such that there is one enumeration
|
||||
per each different arity:
|
||||
|
||||
- #arith0_op defines constants and arity 0 arithmetic functions
|
||||
|
||||
@copydoc #arith0_op
|
||||
|
||||
- #arith1_op defines single argument arithmetic functions
|
||||
|
||||
@copydoc #arith1_op
|
||||
|
||||
- #arith2_op defines binary arithmetic functions
|
||||
|
||||
@copydoc #arith2_op
|
||||
|
||||
Arithmetic expressions
|
||||
in YAP may use the following operators:
|
||||
|
||||
- <b>pi [ISO]</b><p> @anchor pi_0
|
||||
|
||||
An approximation to the value of <em>pi</em>, that is, the ratio of a circle's circumference to its diameter.
|
||||
|
||||
- <b>e</b><p> @anchor e_0
|
||||
|
||||
Euler's number, the base of the natural logarithms.
|
||||
|
||||
- <b>epsilon</b><p> @anchor epsilon_0
|
||||
|
||||
The difference between the float `1.0` and the next largest floating point number.
|
||||
|
||||
- <b>inf</b><p> @anchor inf_0
|
||||
|
||||
Infinity according to the IEEE Floating-Point standard. Note that evaluating this term will generate a domain error in the `iso` language mode.
|
||||
|
||||
Note also that YAP supports `+inf` and `-inf`
|
||||
|
||||
- <b>nan (not a number)</b><p> @anchor nan_0
|
||||
|
||||
Not-a-number according to the IEEE Floating-Point standard. Note that evaluating this term will generate a domain error in the `iso` language mode.
|
||||
|
||||
- <b>random</b><p> @anchor random_0
|
||||
|
||||
A "random" floating point number between 0 and 1.
|
||||
|
||||
- <b>cputime</b><p> @anchor cputime_0
|
||||
|
||||
CPU time since YAP was invoked, in seconds.
|
||||
|
||||
- <b>heapused</b><p> @anchor heapused_0
|
||||
|
||||
Heap (data-base) space used, in bytes.
|
||||
|
||||
- <b>local</b><p> @anchor local_0
|
||||
|
||||
Local stack in use, in bytes
|
||||
|
||||
- <b>$b</b><p> @anchor b_0
|
||||
|
||||
current choicepoint
|
||||
|
||||
- <b>$env</b><p> @anchor env_0
|
||||
|
||||
Environment
|
||||
|
||||
- <b>$tr</b><p> @anchor tr_0
|
||||
|
||||
Trail in use
|
||||
|
||||
- <b>$free_stack</b><p> @anchor free_stack_0
|
||||
|
||||
Amount of free stack space, that is, free space between global and local stacks.
|
||||
|
||||
- <b>global</b><p> @anchor global_0
|
||||
|
||||
Global stack in use, in bytes.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "eval.h"
|
||||
|
||||
|
||||
|
||||
static Term
|
||||
eval0(Int fi) {
|
||||
CACHE_REGS
|
||||
arith0_op fop = fi;
|
||||
switch (fop) {
|
||||
case op_pi:
|
||||
{
|
||||
RFLOAT(PI);
|
||||
}
|
||||
case op_e:
|
||||
{
|
||||
RFLOAT(M_E);
|
||||
}
|
||||
case op_epsilon:
|
||||
{
|
||||
RFLOAT(DBL_EPSILON);
|
||||
}
|
||||
case op_inf:
|
||||
{
|
||||
#ifdef _MSC_VER /* Microsoft's Visual C++ Compiler */
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, TermNil, "evaluating infinity");
|
||||
P = (yamop *)FAILCODE;
|
||||
RERROR();
|
||||
#else
|
||||
if (isoLanguageFlag()) {/* iso */
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, TermNil, "evaluating infinity");
|
||||
P = (yamop *)FAILCODE;
|
||||
RERROR();
|
||||
} else {
|
||||
RFLOAT(INFINITY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case op_nan:
|
||||
{
|
||||
#ifdef _MSC_VER /* Microsoft's Visual C++ Compi<ler */
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, TermNil, "evaluating infinity");
|
||||
RERROR();
|
||||
#else
|
||||
if (isoLanguageFlag()) {/* iso */
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, TermNil, "evaluating not-a-number");
|
||||
RERROR();
|
||||
} else {
|
||||
RFLOAT(NAN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case op_random:
|
||||
{
|
||||
RFLOAT(Yap_random());
|
||||
}
|
||||
case op_cputime:
|
||||
{
|
||||
RFLOAT((Float)Yap_cputime()/1000.0);
|
||||
}
|
||||
case op_heapused:
|
||||
/// - heapused
|
||||
/// Heap (data-base) space used, in bytes.
|
||||
///
|
||||
RINT(HeapUsed);
|
||||
case op_localsp:
|
||||
/// - local
|
||||
/// Local stack in use, in bytes
|
||||
///
|
||||
#if YAPOR_SBA
|
||||
RINT((Int)ASP);
|
||||
#else
|
||||
RINT(LCL0 - ASP);
|
||||
#endif
|
||||
case op_b:
|
||||
/// - $b
|
||||
/// current choicepoint
|
||||
///
|
||||
#if YAPOR_SBA
|
||||
RINT((Int)B);
|
||||
#else
|
||||
RINT(LCL0 - (CELL *)B);
|
||||
#endif
|
||||
case op_env:
|
||||
/// - $env
|
||||
/// Environment
|
||||
///
|
||||
#if YAPOR_SBA
|
||||
RINT((Int)YENV);
|
||||
#else
|
||||
RINT(LCL0 - YENV);
|
||||
#endif
|
||||
case op_tr:
|
||||
/// - $tr
|
||||
/// Trail in use
|
||||
///
|
||||
#if YAPOR_SBA
|
||||
RINT(TR);
|
||||
#else
|
||||
RINT(((CELL *)TR)-LCL0);
|
||||
#endif
|
||||
case op_stackfree:
|
||||
/// - $free_stack
|
||||
///
|
||||
/// Not-a-number according to the IEEE Floating-Point standard. Note that evaluating this term will generate a domain error in the `iso` language mode.
|
||||
RINT(Unsigned(ASP) - Unsigned(HR));
|
||||
case op_globalsp:
|
||||
/// - global
|
||||
/// Global stack in use, in bytes.
|
||||
///
|
||||
#if YAPOR_SBA
|
||||
RINT((Int)HR);
|
||||
#else
|
||||
RINT(HR - H0);
|
||||
#endif
|
||||
}
|
||||
/// end of switch
|
||||
RERROR();
|
||||
}
|
||||
|
||||
Term Yap_eval_atom(Int f)
|
||||
{
|
||||
return eval0(f);
|
||||
}
|
||||
|
||||
typedef struct init_const_eval {
|
||||
char *OpName;
|
||||
arith0_op f;
|
||||
} InitConstEntry;
|
||||
|
||||
static InitConstEntry InitConstTab[] = {
|
||||
{"pi", op_pi},
|
||||
{"e", op_e},
|
||||
{"epsilon", op_epsilon},
|
||||
{"inf", op_inf},
|
||||
{"nan", op_nan},
|
||||
{"random", op_random},
|
||||
{"cputime", op_cputime},
|
||||
{"heapused", op_heapused},
|
||||
{"local_sp", op_localsp},
|
||||
{"global_sp", op_globalsp},
|
||||
{"$last_choice_pt", op_b},
|
||||
{"$env", op_env},
|
||||
{"$tr", op_tr},
|
||||
{"stackfree", op_stackfree},
|
||||
};
|
||||
|
||||
void
|
||||
Yap_InitConstExps(void)
|
||||
{
|
||||
unsigned int i;
|
||||
ExpEntry *p;
|
||||
|
||||
for (i = 0; i < sizeof(InitConstTab)/sizeof(InitConstEntry); ++i) {
|
||||
AtomEntry *ae = RepAtom(Yap_LookupAtom(InitConstTab[i].OpName));
|
||||
if (ae == NULL) {
|
||||
Yap_EvalError(RESOURCE_ERROR_HEAP,TermNil,"at InitConstExps");
|
||||
return;
|
||||
}
|
||||
WRITE_LOCK(ae->ARWLock);
|
||||
if (Yap_GetExpPropHavingLock(ae, 0)) {
|
||||
WRITE_UNLOCK(ae->ARWLock);
|
||||
break;
|
||||
}
|
||||
p = (ExpEntry *) Yap_AllocAtomSpace(sizeof(ExpEntry));
|
||||
p->KindOfPE = ExpProperty;
|
||||
p->ArityOfEE = 0;
|
||||
p->ENoOfEE = 0;
|
||||
p->FOfEE = InitConstTab[i].f;
|
||||
AddPropToAtom(ae, (PropEntry *)p);
|
||||
WRITE_UNLOCK(ae->ARWLock);
|
||||
}
|
||||
}
|
||||
|
||||
/* This routine is called from Restore to make sure we have the same arithmetic operators */
|
||||
int
|
||||
Yap_ReInitConstExps(void)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/// @}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,435 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: bb.c *
|
||||
* Last rev: 12/29/99 *
|
||||
* mods: *
|
||||
* comments: YAP's blackboard routines *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
|
||||
/** @defgroup BlackBoard The Blackboard
|
||||
@ingroup builtins
|
||||
@{
|
||||
|
||||
YAP implements a blackboard in the style of the SICStus Prolog
|
||||
blackboard. The blackboard uses the same underlying mechanism as the
|
||||
internal data-base but has several important differences:
|
||||
|
||||
+ It is module aware, in contrast to the internal data-base.
|
||||
+ Keys can only be atoms or integers, and not compound terms.
|
||||
+ A single term can be stored per key.
|
||||
+ An atomic update operation is provided; this is useful for
|
||||
parallelism.
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "clause.h"
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
static BBProp
|
||||
PutBBProp(AtomEntry *ae, Term mod USES_REGS) /* get BBentry for at; */
|
||||
{
|
||||
Prop p0;
|
||||
BBProp p;
|
||||
|
||||
WRITE_LOCK(ae->ARWLock);
|
||||
p = RepBBProp(p0 = ae->PropsOfAE);
|
||||
while (p0 != NIL && (!IsBBProperty(p->KindOfPE) ||
|
||||
(p->ModuleOfBB != mod))) {
|
||||
p = RepBBProp(p0 = p->NextOfPE);
|
||||
}
|
||||
if (p0 == NIL) {
|
||||
p = (BBProp)Yap_AllocAtomSpace(sizeof(*p));
|
||||
if (p == NULL) {
|
||||
WRITE_UNLOCK(ae->ARWLock);
|
||||
Yap_Error(RESOURCE_ERROR_HEAP,ARG1,"could not allocate space in bb_put/2");
|
||||
return(NULL);
|
||||
}
|
||||
AddPropToAtom(ae, (PropEntry *)p);
|
||||
p->ModuleOfBB = mod;
|
||||
p->Element = 0L;
|
||||
p->KeyOfBB = AbsAtom(ae);
|
||||
p->KindOfPE = BBProperty;
|
||||
INIT_RWLOCK(p->BBRWLock);
|
||||
}
|
||||
WRITE_UNLOCK(ae->ARWLock);
|
||||
return (p);
|
||||
}
|
||||
|
||||
static BBProp
|
||||
PutIntBBProp(Int key, Term mod USES_REGS) /* get BBentry for at; */
|
||||
{
|
||||
Prop p0;
|
||||
BBProp p;
|
||||
UInt hash_key;
|
||||
|
||||
if (INT_BB_KEYS == NULL) {
|
||||
INT_BB_KEYS = (Prop *)Yap_AllocCodeSpace(sizeof(Prop)*INT_BB_KEYS_SIZE);
|
||||
if (INT_BB_KEYS != NULL) {
|
||||
UInt i = 0;
|
||||
Prop *pp = INT_BB_KEYS;
|
||||
for (i = 0; i < INT_BB_KEYS_SIZE; i++) {
|
||||
pp[0] = NIL;
|
||||
pp++;
|
||||
}
|
||||
} else {
|
||||
Yap_Error(RESOURCE_ERROR_HEAP,ARG1,"could not allocate space in bb_put/2");
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
hash_key = (CELL)key % INT_BB_KEYS_SIZE;
|
||||
p0 = INT_BB_KEYS[hash_key];
|
||||
p = RepBBProp(p0);
|
||||
while (p0 != NIL && (!IsBBProperty(p->KindOfPE) ||
|
||||
key != (Int)(p->KeyOfBB) ||
|
||||
(p->ModuleOfBB != mod))) {
|
||||
p = RepBBProp(p0 = p->NextOfPE);
|
||||
}
|
||||
if (p0 == NIL) {
|
||||
YAPEnterCriticalSection();
|
||||
p = (BBProp)Yap_AllocAtomSpace(sizeof(*p));
|
||||
if (p == NULL) {
|
||||
YAPLeaveCriticalSection();
|
||||
Yap_Error(RESOURCE_ERROR_HEAP,ARG1,"could not allocate space in bb_put/2");
|
||||
return(NULL);
|
||||
}
|
||||
p->ModuleOfBB = mod;
|
||||
p->Element = 0L;
|
||||
p->KeyOfBB = (Atom)key;
|
||||
p->KindOfPE = BBProperty;
|
||||
p->NextOfPE = INT_BB_KEYS[hash_key];
|
||||
INT_BB_KEYS[hash_key] = AbsBBProp(p);
|
||||
YAPLeaveCriticalSection();
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
static BBProp
|
||||
GetBBProp(AtomEntry *ae, Term mod) /* get BBentry for at; */
|
||||
{
|
||||
Prop p0;
|
||||
BBProp p;
|
||||
|
||||
READ_LOCK(ae->ARWLock);
|
||||
p = RepBBProp(p0 = ae->PropsOfAE);
|
||||
while (p0 != NIL && (!IsBBProperty(p->KindOfPE) ||
|
||||
(p->ModuleOfBB != mod))) {
|
||||
p = RepBBProp(p0 = p->NextOfPE);
|
||||
}
|
||||
READ_UNLOCK(ae->ARWLock);
|
||||
if (p0 == NIL) {
|
||||
return(NULL);
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
static BBProp
|
||||
GetIntBBProp(Int key, Term mod) /* get BBentry for at; */
|
||||
{
|
||||
Prop p0;
|
||||
BBProp p;
|
||||
UInt hash_key;
|
||||
|
||||
if (INT_BB_KEYS == NULL)
|
||||
return(NULL);
|
||||
hash_key = (CELL)key % INT_BB_KEYS_SIZE;
|
||||
p0 = INT_BB_KEYS[hash_key];
|
||||
p = RepBBProp(p0);
|
||||
while (p0 != NIL && (!IsBBProperty(p->KindOfPE) ||
|
||||
key != (Int)(p->KeyOfBB) ||
|
||||
(p->ModuleOfBB != mod))) {
|
||||
p = RepBBProp(p0 = p->NextOfPE);
|
||||
}
|
||||
if (p0 == NIL) {
|
||||
return(NULL);
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
static int
|
||||
resize_bb_int_keys(UInt new_size) {
|
||||
CACHE_REGS
|
||||
Prop *new;
|
||||
UInt i;
|
||||
|
||||
YAPEnterCriticalSection();
|
||||
if (INT_BB_KEYS == NULL) {
|
||||
INT_BB_KEYS_SIZE = new_size;
|
||||
YAPLeaveCriticalSection();
|
||||
return(TRUE);
|
||||
}
|
||||
new = (Prop *)Yap_AllocCodeSpace(sizeof(Prop)*new_size);
|
||||
if (new == NULL) {
|
||||
YAPLeaveCriticalSection();
|
||||
Yap_Error(RESOURCE_ERROR_HEAP,ARG1,"could not allocate space");
|
||||
return(FALSE);
|
||||
}
|
||||
for (i = 0; i < new_size; i++) {
|
||||
new[i] = NIL;
|
||||
}
|
||||
for (i = 0; i < INT_BB_KEYS_SIZE; i++) {
|
||||
if (INT_BB_KEYS[i] != NIL) {
|
||||
Prop p0 = INT_BB_KEYS[i];
|
||||
while (p0 != NIL) {
|
||||
BBProp p = RepBBProp(p0);
|
||||
CELL key = (CELL)(p->KeyOfBB);
|
||||
UInt hash_key = (CELL)key % new_size;
|
||||
p0 = p->NextOfPE;
|
||||
p->NextOfPE = new[hash_key];
|
||||
new[hash_key] = AbsBBProp(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
Yap_FreeCodeSpace((char *)INT_BB_KEYS);
|
||||
INT_BB_KEYS = new;
|
||||
INT_BB_KEYS_SIZE = new_size;
|
||||
YAPLeaveCriticalSection();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static BBProp
|
||||
AddBBProp(Term t1, char *msg, Term mod USES_REGS)
|
||||
{
|
||||
BBProp p;
|
||||
|
||||
restart:
|
||||
if (IsVarTerm(t1)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t1, msg);
|
||||
return(NULL);
|
||||
} if (IsAtomTerm(t1)) {
|
||||
p = PutBBProp(RepAtom(AtomOfTerm(t1)), mod PASS_REGS);
|
||||
} else if (IsIntegerTerm(t1)) {
|
||||
p = PutIntBBProp(IntegerOfTerm(t1), mod PASS_REGS);
|
||||
} else if (IsApplTerm(t1) && FunctorOfTerm(t1) == FunctorModule) {
|
||||
Term tmod = ArgOfTerm(1, t1);
|
||||
if (!IsVarTerm(tmod) ) {
|
||||
t1 = ArgOfTerm(2, t1);
|
||||
mod = tmod;
|
||||
goto restart;
|
||||
} else {
|
||||
Yap_Error(INSTANTIATION_ERROR, t1, msg);
|
||||
return(NULL);
|
||||
}
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_ATOM, t1, msg);
|
||||
return(NULL);
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
static BBProp
|
||||
FetchBBProp(Term t1, char *msg, Term mod)
|
||||
{
|
||||
BBProp p;
|
||||
|
||||
restart:
|
||||
if (IsVarTerm(t1)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t1, msg);
|
||||
return(NULL);
|
||||
} if (IsAtomTerm(t1)) {
|
||||
p = GetBBProp(RepAtom(AtomOfTerm(t1)), mod);
|
||||
} else if (IsIntegerTerm(t1)) {
|
||||
p = GetIntBBProp(IntegerOfTerm(t1), mod);
|
||||
} else if (IsApplTerm(t1) && FunctorOfTerm(t1) == FunctorModule) {
|
||||
Term tmod = ArgOfTerm(1, t1);
|
||||
if (!IsVarTerm(tmod) ) {
|
||||
mod = tmod;
|
||||
t1 = ArgOfTerm(2, t1);
|
||||
goto restart;
|
||||
} else {
|
||||
Yap_Error(INSTANTIATION_ERROR, t1, msg);
|
||||
return(NULL);
|
||||
}
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_ATOM, t1, msg);
|
||||
return(NULL);
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
static Term
|
||||
BBPut(Term t0, Term t2)
|
||||
{
|
||||
if (!IsVarTerm(t0) && IsApplTerm(t0)) {
|
||||
Yap_ErLogUpdCl((LogUpdClause *)DBRefOfTerm(t0));
|
||||
}
|
||||
if (IsVarTerm(t2) || IsAtomOrIntTerm(t2)) {
|
||||
return t2;
|
||||
} else {
|
||||
LogUpdClause *cl = Yap_new_ludbe(t2, NULL, 0);
|
||||
|
||||
if (cl == NULL) {
|
||||
return 0L;
|
||||
}
|
||||
return MkDBRefTerm((DBRef)cl);
|
||||
}
|
||||
}
|
||||
|
||||
/** @pred bb_put(+ _Key_,? _Term_)
|
||||
|
||||
|
||||
Store term table _Term_ in the blackboard under key _Key_. If a
|
||||
previous term was stored under key _Key_ it is simply forgotten.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_bb_put( USES_REGS1 )
|
||||
{
|
||||
Term t1 = Deref(ARG1);
|
||||
BBProp p = AddBBProp(t1, "bb_put/2", CurrentModule PASS_REGS);
|
||||
|
||||
if (p == NULL) {
|
||||
return(FALSE);
|
||||
}
|
||||
WRITE_LOCK(p->BBRWLock);
|
||||
/*
|
||||
if (p->Element)
|
||||
fprintf(stderr,"putting %p, size %d\n", p, p->Element->NOfCells);
|
||||
*/
|
||||
p->Element = BBPut(p->Element, Deref(ARG2));
|
||||
WRITE_UNLOCK(p->BBRWLock);
|
||||
return (p->Element != 0L);
|
||||
}
|
||||
|
||||
static Term
|
||||
BBGet(Term t, UInt arity USES_REGS)
|
||||
{
|
||||
if (IsVarTerm(t)) {
|
||||
return MkVarTerm();
|
||||
} else if (IsAtomOrIntTerm(t)) {
|
||||
return t;
|
||||
} else {
|
||||
return Yap_LUInstance((LogUpdClause *)DBRefOfTerm(t), arity);
|
||||
}
|
||||
}
|
||||
|
||||
/** @pred bb_get(+ _Key_,? _Term_)
|
||||
|
||||
|
||||
Unify _Term_ with a term stored in the blackboard under key
|
||||
_Key_, or fail silently if no such term exists.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_bb_get( USES_REGS1 )
|
||||
{
|
||||
Term t1 = Deref(ARG1);
|
||||
BBProp p = FetchBBProp(t1, "bb_get/2", CurrentModule);
|
||||
Term out, t0;
|
||||
if (p == NULL || p->Element == 0L)
|
||||
return(FALSE);
|
||||
READ_LOCK(p->BBRWLock);
|
||||
/*
|
||||
if (p->Element)
|
||||
fprintf(stderr,"getting %p, size %d\n", p, p->Element->NOfCells);
|
||||
*/
|
||||
t0 = p->Element;
|
||||
READ_UNLOCK(p->BBRWLock);
|
||||
out = BBGet(t0, 2 PASS_REGS);
|
||||
return Yap_unify(ARG2,out);
|
||||
}
|
||||
|
||||
/** @pred bb_delete(+ _Key_,? _Term_)
|
||||
|
||||
|
||||
Delete any term stored in the blackboard under key _Key_ and unify
|
||||
it with _Term_. Fail silently if no such term exists.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_bb_delete( USES_REGS1 )
|
||||
{
|
||||
Term t1 = Deref(ARG1);
|
||||
BBProp p;
|
||||
Term out;
|
||||
|
||||
p = FetchBBProp(t1, "bb_delete/2", CurrentModule);
|
||||
if (p == NULL || p->Element == 0L)
|
||||
return(FALSE);
|
||||
WRITE_LOCK(p->BBRWLock);
|
||||
out = BBGet(p->Element, 2 PASS_REGS);
|
||||
if (!IsVarTerm(p->Element) && IsApplTerm(p->Element)) {
|
||||
Yap_ErLogUpdCl((LogUpdClause *)DBRefOfTerm(p->Element));
|
||||
}
|
||||
p->Element = 0L;
|
||||
WRITE_UNLOCK(p->BBRWLock);
|
||||
return Yap_unify(ARG2,out);
|
||||
}
|
||||
|
||||
/** @pred bb_update( +_Key_, ?_Term_, ?_New_)
|
||||
|
||||
|
||||
Atomically unify a term stored in the blackboard under key _Key_
|
||||
with _Term_, and if the unification succeeds replace it by
|
||||
_New_. Fail silently if no such term exists or if unification fails.
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_bb_update( USES_REGS1 )
|
||||
{
|
||||
Term t1 = Deref(ARG1);
|
||||
BBProp p;
|
||||
Term out;
|
||||
|
||||
p = FetchBBProp(t1, "bb_update/3", CurrentModule);
|
||||
if (p == NULL || p->Element == 0L)
|
||||
return FALSE;
|
||||
WRITE_LOCK(p->BBRWLock);
|
||||
out = BBGet(p->Element, 3 PASS_REGS);
|
||||
if (!Yap_unify(out,ARG2)) {
|
||||
WRITE_UNLOCK(p->BBRWLock);
|
||||
return FALSE;
|
||||
}
|
||||
p->Element = BBPut(p->Element, Deref(ARG3));
|
||||
WRITE_UNLOCK(p->BBRWLock);
|
||||
return (p->Element != 0L);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_resize_bb_int_keys( USES_REGS1 )
|
||||
{
|
||||
Term t1 = Deref(ARG1);
|
||||
if (IsVarTerm(t1)) {
|
||||
return(Yap_unify(ARG1,MkIntegerTerm((Int)INT_BB_KEYS_SIZE)));
|
||||
}
|
||||
if (!IsIntegerTerm(t1)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, t1, "yap_flag(resize_bb_int_keys,T)");
|
||||
return(FALSE);
|
||||
}
|
||||
return(resize_bb_int_keys(IntegerOfTerm(t1)));
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitBBPreds(void)
|
||||
{
|
||||
Yap_InitCPred("bb_put", 2, p_bb_put, 0);
|
||||
Yap_InitCPred("bb_get", 2, p_bb_get, 0);
|
||||
Yap_InitCPred("bb_delete", 2, p_bb_delete, 0);
|
||||
Yap_InitCPred("bb_update", 3, p_bb_update, 0);
|
||||
Yap_InitCPred("$resize_bb_int_keys", 1, p_resize_bb_int_keys, SafePredFlag|SyncPredFlag);
|
||||
}
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,571 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: arith1.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: bignum support through gmp *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "YapHeap.h"
|
||||
#include "YapText.h"
|
||||
|
||||
#ifdef USE_GMP
|
||||
|
||||
#include "eval.h"
|
||||
#include "alloc.h"
|
||||
|
||||
Term
|
||||
Yap_MkBigIntTerm(MP_INT *big)
|
||||
{
|
||||
CACHE_REGS
|
||||
Int nlimbs;
|
||||
MP_INT *dst = (MP_INT *)(HR+2);
|
||||
CELL *ret = HR;
|
||||
Int bytes;
|
||||
|
||||
if (mpz_fits_slong_p(big)) {
|
||||
long int out = mpz_get_si(big);
|
||||
return MkIntegerTerm((Int)out);
|
||||
}
|
||||
// bytes = big->_mp_alloc * sizeof(mp_limb_t);
|
||||
// nlimbs = ALIGN_YAPTYPE(bytes,CELL)/CellSize;
|
||||
// this works, but it shouldn't need to do this...
|
||||
nlimbs = big->_mp_alloc;
|
||||
bytes = nlimbs*sizeof(CELL);
|
||||
if (nlimbs > (ASP-ret)-1024) {
|
||||
return TermNil;
|
||||
}
|
||||
HR[0] = (CELL)FunctorBigInt;
|
||||
HR[1] = BIG_INT;
|
||||
|
||||
dst->_mp_size = big->_mp_size;
|
||||
dst->_mp_alloc = nlimbs*(CellSize/sizeof(mp_limb_t));
|
||||
memmove((void *)(dst+1), (const void *)(big->_mp_d), bytes);
|
||||
HR = (CELL *)(dst+1)+nlimbs;
|
||||
HR[0] = EndSpecials;
|
||||
HR++;
|
||||
return AbsAppl(ret);
|
||||
}
|
||||
|
||||
|
||||
MP_INT *
|
||||
Yap_BigIntOfTerm(Term t)
|
||||
{
|
||||
MP_INT *new = (MP_INT *)(RepAppl(t)+2);
|
||||
|
||||
new->_mp_d = (mp_limb_t *)(new+1);
|
||||
return(new);
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_MkBigRatTerm(MP_RAT *big)
|
||||
{
|
||||
CACHE_REGS
|
||||
Int nlimbs;
|
||||
MP_INT *dst = (MP_INT *)(HR+2);
|
||||
MP_INT *num = mpq_numref(big);
|
||||
MP_INT *den = mpq_denref(big);
|
||||
MP_RAT *rat;
|
||||
CELL *ret = HR;
|
||||
|
||||
if (mpz_cmp_si(den, 1) == 0)
|
||||
return Yap_MkBigIntTerm(num);
|
||||
if ((num->_mp_alloc+den->_mp_alloc)*(sizeof(mp_limb_t)/CellSize) > (ASP-ret)-1024) {
|
||||
return TermNil;
|
||||
}
|
||||
HR[0] = (CELL)FunctorBigInt;
|
||||
HR[1] = BIG_RATIONAL;
|
||||
dst->_mp_size = 0;
|
||||
rat = (MP_RAT *)(dst+1);
|
||||
rat->_mp_num._mp_size = num->_mp_size;
|
||||
rat->_mp_num._mp_alloc = num->_mp_alloc;
|
||||
nlimbs = (num->_mp_alloc)*(sizeof(mp_limb_t)/CellSize);
|
||||
memmove((void *)(rat+1), (const void *)(num->_mp_d), nlimbs*CellSize);
|
||||
rat->_mp_den._mp_size = den->_mp_size;
|
||||
rat->_mp_den._mp_alloc = den->_mp_alloc;
|
||||
HR = (CELL *)(rat+1)+nlimbs;
|
||||
nlimbs = (den->_mp_alloc)*(sizeof(mp_limb_t)/CellSize);
|
||||
memmove((void *)(HR), (const void *)(den->_mp_d), nlimbs*CellSize);
|
||||
HR += nlimbs;
|
||||
dst->_mp_alloc = (HR-(CELL *)(dst+1));
|
||||
HR[0] = EndSpecials;
|
||||
HR++;
|
||||
return AbsAppl(ret);
|
||||
}
|
||||
|
||||
MP_RAT *
|
||||
Yap_BigRatOfTerm(Term t)
|
||||
{
|
||||
MP_RAT *new = (MP_RAT *)(RepAppl(t)+2+sizeof(MP_INT)/sizeof(CELL));
|
||||
mp_limb_t *nt;
|
||||
|
||||
nt = new->_mp_num._mp_d = (mp_limb_t *)(new+1);
|
||||
nt += new->_mp_num._mp_alloc;
|
||||
new->_mp_den._mp_d = nt;
|
||||
return new;
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_RatTermToApplTerm(Term t)
|
||||
{
|
||||
Term ts[2];
|
||||
MP_RAT *rat = Yap_BigRatOfTerm(t);
|
||||
|
||||
ts[0] = Yap_MkBigIntTerm(mpq_numref(rat));
|
||||
ts[1] = Yap_MkBigIntTerm(mpq_denref(rat));
|
||||
return Yap_MkApplTerm(FunctorRDiv,2,ts);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Term
|
||||
Yap_AllocExternalDataInStack(CELL tag, size_t bytes)
|
||||
{
|
||||
CACHE_REGS
|
||||
Int nlimbs;
|
||||
MP_INT *dst = (MP_INT *)(HR+2);
|
||||
CELL *ret = HR;
|
||||
|
||||
nlimbs = ALIGN_BY_TYPE(bytes,CELL)/CellSize;
|
||||
if (nlimbs > (ASP-ret)-1024) {
|
||||
return TermNil;
|
||||
}
|
||||
HR[0] = (CELL)FunctorBigInt;
|
||||
HR[1] = tag;
|
||||
dst->_mp_size = 0;
|
||||
dst->_mp_alloc = nlimbs;
|
||||
HR = (CELL *)(dst+1)+nlimbs;
|
||||
HR[0] = EndSpecials;
|
||||
HR++;
|
||||
if (tag != EXTERNAL_BLOB) {
|
||||
TrailTerm(TR) = AbsPair(ret);
|
||||
TR++;
|
||||
}
|
||||
return AbsAppl(ret);
|
||||
}
|
||||
|
||||
int Yap_CleanOpaqueVariable(CELL *pt)
|
||||
{
|
||||
CELL blob_info, blob_tag;
|
||||
MP_INT *blobp;
|
||||
#ifdef DEBUG
|
||||
/* sanity checking */
|
||||
if (pt[0] != (CELL)FunctorBigInt) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "CleanOpaqueVariable bad call");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
blob_tag = pt[1];
|
||||
if (blob_tag < USER_BLOB_START ||
|
||||
blob_tag >= USER_BLOB_END) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, AbsAppl(pt), "clean opaque: bad blob with tag " UInt_FORMAT ,blob_tag);
|
||||
return FALSE;
|
||||
}
|
||||
blob_info = blob_tag - USER_BLOB_START;
|
||||
if (!GLOBAL_OpaqueHandlers)
|
||||
return FALSE;
|
||||
blobp = (MP_INT *)(pt+2);
|
||||
if (!GLOBAL_OpaqueHandlers[blob_info].fail_handler)
|
||||
return TRUE;
|
||||
return (GLOBAL_OpaqueHandlers[blob_info].fail_handler)((void *)(blobp+1));
|
||||
}
|
||||
|
||||
Opaque_CallOnWrite
|
||||
Yap_blob_write_handler(Term t)
|
||||
{
|
||||
CELL blob_info, blob_tag;
|
||||
CELL *pt = RepAppl(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* sanity checking */
|
||||
if (pt[0] != (CELL)FunctorBigInt) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "CleanOpaqueVariable bad call");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
blob_tag = pt[1];
|
||||
if (blob_tag < USER_BLOB_START ||
|
||||
blob_tag >= USER_BLOB_END) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, AbsAppl(pt), "clean opaque: bad blob with tag " UInt_FORMAT ,blob_tag);
|
||||
return FALSE;
|
||||
}
|
||||
blob_info = blob_tag - USER_BLOB_START;
|
||||
if (!GLOBAL_OpaqueHandlers) {
|
||||
return NULL;
|
||||
}
|
||||
return GLOBAL_OpaqueHandlers[blob_info].write_handler;
|
||||
}
|
||||
|
||||
Opaque_CallOnGCMark
|
||||
Yap_blob_gc_mark_handler(Term t)
|
||||
{
|
||||
CELL blob_info, blob_tag;
|
||||
CELL *pt = RepAppl(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* sanity checking */
|
||||
if (pt[0] != (CELL)FunctorBigInt) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "CleanOpaqueVariable bad call");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
blob_tag = pt[1];
|
||||
if (blob_tag < USER_BLOB_START ||
|
||||
blob_tag >= USER_BLOB_END) {
|
||||
return NULL;
|
||||
}
|
||||
blob_info = blob_tag - USER_BLOB_START;
|
||||
if (!GLOBAL_OpaqueHandlers)
|
||||
return NULL;
|
||||
return GLOBAL_OpaqueHandlers[blob_info].gc_mark_handler;
|
||||
}
|
||||
|
||||
Opaque_CallOnGCRelocate
|
||||
Yap_blob_gc_relocate_handler(Term t)
|
||||
{
|
||||
CELL blob_info, blob_tag;
|
||||
CELL *pt = RepAppl(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* sanity checking */
|
||||
if (pt[0] != (CELL)FunctorBigInt) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "CleanOpaqueVariable bad call");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
blob_tag = pt[1];
|
||||
if (blob_tag < USER_BLOB_START ||
|
||||
blob_tag >= USER_BLOB_END) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, AbsAppl(pt), "clean opaque: bad blob with tag " UInt_FORMAT ,blob_tag);
|
||||
return FALSE;
|
||||
}
|
||||
blob_info = blob_tag - USER_BLOB_START;
|
||||
if (!GLOBAL_OpaqueHandlers)
|
||||
return NULL;
|
||||
return GLOBAL_OpaqueHandlers[blob_info].gc_relocate_handler;
|
||||
}
|
||||
|
||||
extern Int Yap_blob_tag(Term t)
|
||||
{
|
||||
CELL *pt = RepAppl(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* sanity checking */
|
||||
if (pt[0] != (CELL)FunctorBigInt) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "CleanOpaqueVariable bad call");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return pt[1];
|
||||
}
|
||||
|
||||
void *
|
||||
Yap_blob_info(Term t)
|
||||
{
|
||||
MP_INT *blobp;
|
||||
CELL *pt = RepAppl(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* sanity checking */
|
||||
if (pt[0] != (CELL)FunctorBigInt) {
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "CleanOpaqueVariable bad call");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
if (!GLOBAL_OpaqueHandlers)
|
||||
return FALSE;
|
||||
blobp = (MP_INT *)(pt+2);
|
||||
return (void *)(blobp+1);
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_MkULLIntTerm(YAP_ULONG_LONG n)
|
||||
{
|
||||
#if __GNUC__ && USE_GMP
|
||||
mpz_t new;
|
||||
char tmp[256];
|
||||
Term t;
|
||||
|
||||
#ifdef _WIN32
|
||||
snprintf(tmp,256,"%I64u",n);
|
||||
#elif HAVE_SNPRINTF
|
||||
snprintf(tmp,256,"%llu",n);
|
||||
#else
|
||||
sprintf(tmp,"%llu",n);
|
||||
#endif
|
||||
/* try to scan it as a bignum */
|
||||
mpz_init_set_str (new, tmp, 10);
|
||||
if (mpz_fits_slong_p(new)) {
|
||||
CACHE_REGS
|
||||
return MkIntegerTerm(mpz_get_si(new));
|
||||
}
|
||||
t = Yap_MkBigIntTerm(new);
|
||||
mpz_clear(new);
|
||||
return t;
|
||||
#else
|
||||
CACHE_REGS
|
||||
return MkIntegerTerm(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
CELL *
|
||||
Yap_HeapStoreOpaqueTerm(Term t)
|
||||
{
|
||||
CELL *ptr = RepAppl(t);
|
||||
size_t sz;
|
||||
void *new;
|
||||
|
||||
if (ptr[0] == (CELL)FunctorBigInt) {
|
||||
sz = sizeof(MP_INT)+2*CellSize+
|
||||
((MP_INT *)(ptr+2))->_mp_alloc*sizeof(mp_limb_t);
|
||||
} else { /* string */
|
||||
sz = sizeof(CELL)*(2+ptr[1]);
|
||||
}
|
||||
new = Yap_AllocCodeSpace(sz);
|
||||
if (!new) {
|
||||
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, "subgoal_search_loop: no space for %s", StringOfTerm(t) );
|
||||
} else {
|
||||
if (ptr[0] == (CELL)FunctorBigInt) {
|
||||
MP_INT *new = (MP_INT *)(RepAppl(t)+2);
|
||||
|
||||
new->_mp_d = (mp_limb_t *)(new+1);
|
||||
}
|
||||
memmove(new, ptr, sz);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
Yap_OpaqueTermToString(Term t, char *str, size_t max)
|
||||
{
|
||||
size_t str_index = 0;
|
||||
CELL * li = RepAppl(t);
|
||||
unsigned char *ptr = (unsigned char *)StringOfTerm(AbsAppl(li));
|
||||
if (li[0] == (CELL)FunctorString) {
|
||||
str_index += sprintf(& str[str_index], "\"");
|
||||
do {
|
||||
utf8proc_int32_t chr;
|
||||
ptr += get_utf8(ptr, &chr);
|
||||
if (chr == '\0') break;
|
||||
str_index += sprintf(str+str_index, "%C", chr);
|
||||
} while (TRUE);
|
||||
str_index += sprintf(str+str_index, "\"");
|
||||
} else {
|
||||
CELL big_tag = li[1];
|
||||
|
||||
if (big_tag == ARRAY_INT || big_tag == ARRAY_FLOAT) {
|
||||
str_index += sprintf(& str[str_index], "{...}");
|
||||
#ifdef USE_GMP
|
||||
} else if (big_tag == BIG_INT) {
|
||||
MP_INT *big = Yap_BigIntOfTerm(AbsAppl(li));
|
||||
char *s = mpz_get_str(&str[str_index], 10, big);
|
||||
str_index += strlen(&s[str_index]);
|
||||
} else if (big_tag == BIG_RATIONAL) {
|
||||
MP_RAT *big = Yap_BigRatOfTerm(AbsAppl(li));
|
||||
char *s = mpq_get_str(&str[str_index], 10, big);
|
||||
str_index += strlen(&s[str_index]);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
else if (big_tag >= USER_BLOB_START && big_tag < USER_BLOB_END) {
|
||||
Opaque_CallOnWrite f;
|
||||
CELL blob_info;
|
||||
|
||||
blob_info = big_tag - USER_BLOB_START;
|
||||
if (GLOBAL_OpaqueHandlers &&
|
||||
(f= GLOBAL_OpaqueHandlers[blob_info].write_handler)) {
|
||||
(f)(wglb->stream, big_tag, ExternalBlobFromTerm(t), 0);
|
||||
return;
|
||||
}
|
||||
} */
|
||||
str_index += sprintf(& str[str_index], "0");
|
||||
}
|
||||
return str_index;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_is_bignum( USES_REGS1 )
|
||||
{
|
||||
#ifdef USE_GMP
|
||||
Term t = Deref(ARG1);
|
||||
return(
|
||||
IsNonVarTerm(t) &&
|
||||
IsApplTerm(t) &&
|
||||
FunctorOfTerm(t) == FunctorBigInt &&
|
||||
RepAppl(t)[1] == BIG_INT
|
||||
);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static Int
|
||||
p_is_string( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
return(
|
||||
IsNonVarTerm(t) &&
|
||||
IsApplTerm(t) &&
|
||||
FunctorOfTerm(t) == FunctorString
|
||||
);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_nb_set_bit( USES_REGS1 )
|
||||
{
|
||||
#ifdef USE_GMP
|
||||
Term t = Deref(ARG1);
|
||||
Term ti = Deref(ARG2);
|
||||
Int i;
|
||||
|
||||
if (!(
|
||||
IsNonVarTerm(t) &&
|
||||
IsApplTerm(t) &&
|
||||
FunctorOfTerm(t) == FunctorBigInt &&
|
||||
RepAppl(t)[1] == BIG_INT
|
||||
))
|
||||
return FALSE;
|
||||
if (!IsIntegerTerm(ti)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsIntegerTerm(ti)) {
|
||||
return FALSE;
|
||||
}
|
||||
i = IntegerOfTerm(ti);
|
||||
if (i < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
Yap_gmp_set_bit(i, t);
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static Int
|
||||
p_has_bignums( USES_REGS1 )
|
||||
{
|
||||
#ifdef USE_GMP
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static Int
|
||||
p_is_opaque( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t))
|
||||
return FALSE;
|
||||
if (IsApplTerm(t)) {
|
||||
Functor f = FunctorOfTerm(t);
|
||||
CELL *pt;
|
||||
|
||||
if (f != FunctorBigInt)
|
||||
return FALSE;
|
||||
pt = RepAppl(t);
|
||||
return ( pt[1] != BIG_RATIONAL || pt[1] != BIG_INT );
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_is_rational( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t))
|
||||
return FALSE;
|
||||
if (IsIntTerm(t))
|
||||
return TRUE;
|
||||
if (IsApplTerm(t)) {
|
||||
Functor f = FunctorOfTerm(t);
|
||||
CELL *pt;
|
||||
|
||||
if (f == FunctorLongInt)
|
||||
return TRUE;
|
||||
if (f != FunctorBigInt)
|
||||
return FALSE;
|
||||
pt = RepAppl(t);
|
||||
return ( pt[1] == BIG_RATIONAL || pt[1] == BIG_INT );
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_rational( USES_REGS1 )
|
||||
{
|
||||
#ifdef USE_GMP
|
||||
Term t = Deref(ARG1);
|
||||
Functor f;
|
||||
CELL *pt;
|
||||
MP_RAT *rat;
|
||||
Term t1, t2;
|
||||
|
||||
if (IsVarTerm(t))
|
||||
return FALSE;
|
||||
if (!IsApplTerm(t))
|
||||
return FALSE;
|
||||
f = FunctorOfTerm(t);
|
||||
if (f != FunctorBigInt)
|
||||
return FALSE;
|
||||
pt = RepAppl(t);
|
||||
if (pt[1] != BIG_RATIONAL)
|
||||
return FALSE;
|
||||
rat = Yap_BigRatOfTerm(t);
|
||||
while ((t1 = Yap_MkBigIntTerm(mpq_numref(rat))) == TermNil ||
|
||||
(t2 = Yap_MkBigIntTerm(mpq_denref(rat))) == TermNil) {
|
||||
UInt size =
|
||||
(mpq_numref(rat)->_mp_alloc)*(sizeof(mp_limb_t)/CellSize) +
|
||||
(mpq_denref(rat)->_mp_alloc)*(sizeof(mp_limb_t)/CellSize);
|
||||
if (!Yap_gcl(size, 3, ENV, P)) {
|
||||
Yap_Error(RESOURCE_ERROR_STACK, t, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return
|
||||
Yap_unify(ARG2, t1) &&
|
||||
Yap_unify(ARG3, t2);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitBigNums(void)
|
||||
{
|
||||
Yap_InitCPred("$has_bignums", 0, p_has_bignums, SafePredFlag);
|
||||
Yap_InitCPred("$bignum", 1, p_is_bignum, SafePredFlag);
|
||||
Yap_InitCPred("rational", 3, p_rational, 0);
|
||||
Yap_InitCPred("rational", 1, p_is_rational, SafePredFlag);
|
||||
/** @pred rational( _T_)
|
||||
|
||||
|
||||
Checks whether `T` is a rational number.
|
||||
|
||||
|
||||
*/
|
||||
Yap_InitCPred("string", 1, p_is_string, SafePredFlag);
|
||||
Yap_InitCPred("opaque", 1, p_is_opaque, SafePredFlag);
|
||||
Yap_InitCPred("nb_set_bit", 2, p_nb_set_bit, SafePredFlag);
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
//
|
||||
// blobs.c
|
||||
// yap
|
||||
//
|
||||
// Created by VITOR SANTOS COSTA on 09/05/15.
|
||||
// Copyright (c) 2015 VITOR SANTOS COSTA. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "iopreds.h"
|
||||
#include "yapio.h"
|
||||
|
||||
/* for freeBSD9.1 */
|
||||
#define _WITH_DPRINTF
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "fmemopen.h"
|
||||
#endif
|
||||
|
||||
#include "blobs.h"
|
||||
|
||||
static blob_type_t unregistered_blob_atom =
|
||||
{ YAP_BLOB_MAGIC_B,
|
||||
PL_BLOB_NOCOPY|PL_BLOB_TEXT,
|
||||
"unregistered"
|
||||
};
|
||||
|
||||
char * Yap_blob_to_string(AtomEntry *ref, const char *s0, size_t sz)
|
||||
{
|
||||
int rc;
|
||||
char *s = (char *)s0;
|
||||
|
||||
blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type;
|
||||
#if HAVE_FMEMOPEN
|
||||
if (type->write) {
|
||||
FILE *f = fmemopen( s, sz, "w");
|
||||
if (f == NULL){
|
||||
// could not find stream;
|
||||
return NULL;
|
||||
}
|
||||
Atom at = AbsAtom(ref);
|
||||
rc = type->write(f, at, 0);
|
||||
if (rc < 0) {
|
||||
Yap_Error( EVALUATION_ERROR_UNDEFINED, MkAtomTerm(at), "failure in user-defined blob to string code" );
|
||||
}
|
||||
fclose(f); // return the final result.
|
||||
return s;
|
||||
} else {
|
||||
#endif
|
||||
#if __APPLE__
|
||||
size_t sz0 = strlcpy( s, (char *)RepAtom( AtomSWIStream )->StrOfAE, sz);
|
||||
#else
|
||||
size_t sz0;
|
||||
char *f = (char *)memcpy(s, (char *)RepAtom( AtomSWIStream )->StrOfAE, sz);
|
||||
f[0]='\0';
|
||||
sz0 = f-s;
|
||||
#endif
|
||||
s = s+sz0;
|
||||
sz -= sz0;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
snprintf(s+strlen(s), sz0, "(%p)", ref);
|
||||
#else
|
||||
snprintf(s+strlen(s), sz0, "(0x%p)", ref);
|
||||
#endif
|
||||
return s;
|
||||
#if HAVE_FMEMOPEN
|
||||
}
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int Yap_write_blob(AtomEntry *ref, FILE *stream)
|
||||
{
|
||||
blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type;
|
||||
|
||||
if (type->write) {
|
||||
|
||||
Atom at = AbsAtom(ref);
|
||||
return type->write(stream, at, 0);
|
||||
} else {
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
return fprintf(stream, "\'%s\'(%p)", RepAtom(AtomSWIStream)->StrOfAE, ref);
|
||||
#else
|
||||
return fprintf(stream, "\'%s\'(0x%p)", RepAtom(AtomSWIStream)->StrOfAE, ref);
|
||||
#endif
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
YAP_is_blob(Term t, blob_type_t **type)
|
||||
{
|
||||
CACHE_REGS
|
||||
Term yt = Yap_GetFromSlot(t);
|
||||
Atom a;
|
||||
YAP_BlobPropEntry *b;
|
||||
|
||||
if (IsVarTerm(yt))
|
||||
return FALSE;
|
||||
if (!IsAtomTerm(yt))
|
||||
return FALSE;
|
||||
a = AtomOfTerm(yt);
|
||||
if (!IsBlob(a))
|
||||
return FALSE;
|
||||
b = RepBlobProp(a->PropsOfAE);
|
||||
*type = b->blob_type;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* void check_chain(void); */
|
||||
|
||||
/* void check_chain(void) { */
|
||||
/* AtomEntry *ae, *old; */
|
||||
/* ae = Blobs; */
|
||||
/* old = NULL; */
|
||||
/* while (ae) { */
|
||||
/* old = ae; */
|
||||
/* ae = RepAtom(ae->NextOfAE); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
AtomEntry *
|
||||
Yap_lookupBlob(void *blob, size_t len, void *type0, int *new)
|
||||
{
|
||||
YAP_BlobPropEntry *b;
|
||||
AtomEntry *ae;
|
||||
blob_type_t *type = type0;
|
||||
if (new)
|
||||
*new = FALSE;
|
||||
|
||||
LOCK(Blobs_Lock);
|
||||
if (type->flags & PL_BLOB_UNIQUE) {
|
||||
/* just keep a linked chain for now */
|
||||
ae = Blobs;
|
||||
while (ae) {
|
||||
if (ae->PropsOfAE &&
|
||||
RepBlobProp(ae->PropsOfAE)->blob_type == type &&
|
||||
ae->rep.blob->length == len &&
|
||||
!memcmp(ae->rep.blob->data, blob, len)) {
|
||||
UNLOCK(Blobs_Lock);
|
||||
return ae;
|
||||
}
|
||||
ae = RepAtom(ae->NextOfAE);
|
||||
}
|
||||
}
|
||||
if (new)
|
||||
*new = TRUE;
|
||||
b = (YAP_BlobPropEntry *)Yap_AllocCodeSpace(sizeof(YAP_BlobPropEntry));
|
||||
if (!b) {
|
||||
UNLOCK(Blobs_Lock);
|
||||
return NULL;
|
||||
}
|
||||
b->NextOfPE = NIL;
|
||||
b->KindOfPE = BlobProperty;
|
||||
b->blob_type = type;
|
||||
ae = (AtomEntry *)Yap_AllocCodeSpace(sizeof(AtomEntry)+len+sizeof(size_t));
|
||||
if (!ae) {
|
||||
UNLOCK(Blobs_Lock);
|
||||
return NULL;
|
||||
}
|
||||
NOfBlobs++;
|
||||
INIT_RWLOCK(ae->ARWLock);
|
||||
ae->PropsOfAE = AbsBlobProp(b);
|
||||
ae->NextOfAE = AbsAtom(Blobs);
|
||||
ae->rep.blob->length = len;
|
||||
memcpy(ae->rep.blob->data, blob, len);
|
||||
Blobs = ae;
|
||||
if (NOfBlobs > NOfBlobsMax) {
|
||||
Yap_signal(YAP_CDOVF_SIGNAL);
|
||||
}
|
||||
UNLOCK(Blobs_Lock);
|
||||
return ae;
|
||||
}
|
||||
|
||||
bool
|
||||
YAP_unify_blob(Term *t, void *blob, size_t len, blob_type_t *type)
|
||||
{
|
||||
AtomEntry *ae;
|
||||
|
||||
if (!blob)
|
||||
return FALSE;
|
||||
ae = Yap_lookupBlob(blob, len, type, NULL);
|
||||
if (!ae) {
|
||||
return FALSE;
|
||||
}
|
||||
if (type->acquire) {
|
||||
type->acquire(AbsAtom(ae));
|
||||
}
|
||||
*t = MkAtomTerm(AbsAtom(ae));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
YAP_get_blob(Term t, void **blob, size_t *len, blob_type_t **type)
|
||||
{
|
||||
CACHE_REGS
|
||||
Atom a;
|
||||
Term tt;
|
||||
AtomEntry *ae;
|
||||
|
||||
tt = Yap_GetFromSlot(t);
|
||||
if (IsVarTerm(tt))
|
||||
return FALSE;
|
||||
if (!IsAtomTerm(tt))
|
||||
return FALSE;
|
||||
a = AtomOfTerm(tt);
|
||||
if (!IsBlob(a))
|
||||
return FALSE;
|
||||
ae = RepAtom(a);
|
||||
if (type)
|
||||
*type = RepBlobProp(ae->PropsOfAE)->blob_type;
|
||||
if (len)
|
||||
*len = ae->rep.blob[0].length;
|
||||
if (blob)
|
||||
*blob = ae->rep.blob[0].data;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void *
|
||||
YAP_blob_data(Atom x, size_t *len, blob_type_t **type)
|
||||
{
|
||||
|
||||
if (!IsBlob(x)) {
|
||||
if (IsWideAtom(x)) {
|
||||
if ( len )
|
||||
*len = wcslen(x->WStrOfAE);
|
||||
if ( type )
|
||||
|
||||
|
||||
|
||||
*type = &unregistered_blob_atom;
|
||||
return x->WStrOfAE;
|
||||
}
|
||||
if ( len )
|
||||
*len = strlen((char *)x->StrOfAE);
|
||||
if ( type )
|
||||
*type = &unregistered_blob_atom;
|
||||
return x->StrOfAE;
|
||||
}
|
||||
if ( len )
|
||||
*len = x->rep.blob[0].length;
|
||||
if ( type )
|
||||
*type = RepBlobProp(x->PropsOfAE)->blob_type;
|
||||
return x->rep.blob[0].data;
|
||||
}
|
||||
|
||||
void
|
||||
YAP_register_blob_type(blob_type_t *type)
|
||||
{
|
||||
type->next = (void *)BlobTypes;
|
||||
BlobTypes = (void*)type;
|
||||
}
|
||||
|
||||
blob_type_t*
|
||||
YAP_find_blob_type(const char* name)
|
||||
{
|
||||
AtomEntry *a = RepAtom(Yap_LookupAtom(name));
|
||||
if (!IsBlob(a)) {
|
||||
return &unregistered_blob_atom;
|
||||
}
|
||||
return RepBlobProp(a->PropsOfAE)->blob_type;
|
||||
}
|
||||
|
||||
bool
|
||||
YAP_unregister_blob_type(blob_type_t *type)
|
||||
{
|
||||
fprintf(stderr,"YAP_unregister_blob_type not implemented yet\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
Yap_install_blobs(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,153 @@
|
|||
#include "Yap.h"
|
||||
#include "clause.h"
|
||||
#include "tracer.h"
|
||||
#ifdef YAPOR
|
||||
#include "or.macros.h"
|
||||
#endif /* YAPOR */
|
||||
#include "clause_list.h"
|
||||
|
||||
/* need to fix overflow handling */
|
||||
|
||||
static void mk_blob(int sz USES_REGS) {
|
||||
MP_INT *dst;
|
||||
|
||||
HR[0] = (CELL)FunctorBigInt;
|
||||
HR[1] = CLAUSE_LIST;
|
||||
dst = (MP_INT *)(HR + 2);
|
||||
dst->_mp_size = 0L;
|
||||
dst->_mp_alloc = sz;
|
||||
HR += (1 + sizeof(MP_INT) / sizeof(CELL));
|
||||
HR[sz] = EndSpecials;
|
||||
HR += sz + 1;
|
||||
}
|
||||
|
||||
static CELL *extend_blob(CELL *start, int sz USES_REGS) {
|
||||
UInt osize;
|
||||
MP_INT *dst;
|
||||
|
||||
if (HR + sz > ASP)
|
||||
return NULL;
|
||||
dst = (MP_INT *)(start + 2);
|
||||
osize = dst->_mp_alloc;
|
||||
start += (1 + sizeof(MP_INT) / sizeof(CELL));
|
||||
start[sz + osize] = EndSpecials;
|
||||
dst->_mp_alloc += sz;
|
||||
HR += sz;
|
||||
return start + osize;
|
||||
}
|
||||
|
||||
/*init of ClasuseList*/
|
||||
clause_list_t Yap_ClauseListInit(clause_list_t in) {
|
||||
CACHE_REGS in->n = 0;
|
||||
in->start = HR;
|
||||
mk_blob(0 PASS_REGS);
|
||||
in->end = HR;
|
||||
return in;
|
||||
}
|
||||
|
||||
/*add clause to ClauseList
|
||||
returns FALSE on error*/
|
||||
int Yap_ClauseListExtend(clause_list_t cl, void *clause, void *pred) {
|
||||
CACHE_REGS
|
||||
PredEntry *ap = (PredEntry *)pred;
|
||||
|
||||
/* fprintf(stderr,"cl=%p\n",clause); */
|
||||
if (cl->end != HR)
|
||||
return FALSE;
|
||||
if (cl->n == 0) {
|
||||
void **ptr;
|
||||
if (!(ptr = (void **)extend_blob(cl->start, 1 PASS_REGS)))
|
||||
return FALSE;
|
||||
ptr[0] = clause;
|
||||
} else if (cl->n == 1) {
|
||||
yamop **ptr;
|
||||
yamop *code_p, *fclause;
|
||||
|
||||
if (!(ptr = (yamop **)extend_blob(
|
||||
cl->start, 2 * (CELL)NEXTOP((yamop *)NULL, Otapl) / sizeof(CELL) -
|
||||
1 PASS_REGS)))
|
||||
return FALSE;
|
||||
fclause = ptr[-1];
|
||||
code_p = (yamop *)(ptr - 1);
|
||||
code_p->opc = Yap_opcode(_try_clause);
|
||||
code_p->y_u.Otapl.d = fclause;
|
||||
code_p->y_u.Otapl.s = ap->ArityOfPE;
|
||||
code_p->y_u.Otapl.p = ap;
|
||||
#ifdef TABLING
|
||||
code_p->y_u.Otapl.te = ap->TableOfPred;
|
||||
#endif
|
||||
#ifdef YAPOR
|
||||
INIT_YAMOP_LTT(code_p, 0);
|
||||
#endif /* YAPOR */
|
||||
code_p = NEXTOP(code_p, Otapl);
|
||||
code_p->opc = Yap_opcode(_trust);
|
||||
code_p->y_u.Otapl.d = clause;
|
||||
code_p->y_u.Otapl.s = ap->ArityOfPE;
|
||||
code_p->y_u.Otapl.p = ap;
|
||||
#ifdef TABLING
|
||||
code_p->y_u.Otapl.te = ap->TableOfPred;
|
||||
#endif
|
||||
#ifdef YAPOR
|
||||
INIT_YAMOP_LTT(code_p, 0);
|
||||
#endif /* YAPOR */
|
||||
} else {
|
||||
yamop *code_p;
|
||||
|
||||
if (!(code_p = (yamop *)extend_blob(cl->start,
|
||||
((CELL)NEXTOP((yamop *)NULL, Otapl)) /
|
||||
sizeof(CELL) PASS_REGS)))
|
||||
return FALSE;
|
||||
code_p->opc = Yap_opcode(_trust);
|
||||
code_p->y_u.Otapl.d = clause;
|
||||
code_p->y_u.Otapl.s = ap->ArityOfPE;
|
||||
code_p->y_u.Otapl.p = ap;
|
||||
#ifdef TABLING
|
||||
code_p->y_u.Otapl.te = ap->TableOfPred;
|
||||
#endif
|
||||
#ifdef YAPOR
|
||||
INIT_YAMOP_LTT(code_p, 0);
|
||||
#endif /* YAPOR */
|
||||
code_p = PREVOP(code_p, Otapl);
|
||||
code_p->opc = Yap_opcode(_retry);
|
||||
}
|
||||
cl->end = HR;
|
||||
cl->n++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*closes the clause list*/
|
||||
void Yap_ClauseListClose(clause_list_t cl) { /* no need to do nothing */
|
||||
}
|
||||
|
||||
/*destroys the clause list freeing memory*/
|
||||
int Yap_ClauseListDestroy(clause_list_t cl) {
|
||||
CACHE_REGS
|
||||
if (cl->end != HR)
|
||||
return FALSE;
|
||||
HR = cl->start;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*destroys clause list and returns only first clause*/
|
||||
void *Yap_ClauseListToClause(clause_list_t cl) {
|
||||
CACHE_REGS
|
||||
void **ptr;
|
||||
if (cl->end != HR)
|
||||
return NULL;
|
||||
if (cl->n != 1)
|
||||
return NULL;
|
||||
if (!(ptr = (void **)extend_blob(cl->start, 0 PASS_REGS)))
|
||||
return NULL;
|
||||
return ptr[-1];
|
||||
}
|
||||
|
||||
/*return pointer to start of try-retry-trust sequence*/
|
||||
void *Yap_ClauseListCode(clause_list_t cl) {
|
||||
CELL *ptr;
|
||||
ptr = (CELL *)cl->start;
|
||||
ptr += (1 + sizeof(MP_INT) / sizeof(CELL));
|
||||
return (void *)ptr;
|
||||
}
|
||||
|
||||
/* where to fail */
|
||||
void *Yap_FAILCODE(void) { return (void *)FAILCODE; }
|
|
@ -0,0 +1,954 @@
|
|||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: cmppreds.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: comparing two prolog terms *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
/// @file cmppreds.c
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@defgroup Comparing_Terms Comparing Terms
|
||||
@ingroup builtins
|
||||
|
||||
The following predicates are used to compare and order terms, using the
|
||||
standard ordering:
|
||||
|
||||
+
|
||||
variables come before numbers, numbers come before atoms which in turn
|
||||
come before compound terms, i.e.: variables @< numbers @< atoms @<
|
||||
compound terms.
|
||||
+ Variables are roughly ordered by "age" (the "oldest" variable is put
|
||||
first);
|
||||
+
|
||||
Floating point numbers are sorted in increasing order;
|
||||
+
|
||||
Rational numbers are sorted in increasing order;
|
||||
+
|
||||
Integers are sorted in increasing order;
|
||||
+
|
||||
Atoms are sorted in lexicographic order;
|
||||
+
|
||||
Compound terms are ordered first by arity of the main functor, then by
|
||||
the name of the main functor, and finally by their arguments in
|
||||
left-to-right order.
|
||||
|
||||
@{
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "eval.h"
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
|
||||
static Int compare(Term, Term);
|
||||
static Int p_compare( USES_REGS1 );
|
||||
static Int p_acomp( USES_REGS1 );
|
||||
static Int a_eq(Term,Term);
|
||||
static Int a_dif(Term,Term);
|
||||
static Int a_gt(Term, Term);
|
||||
static Int a_ge(Term,Term);
|
||||
static Int a_lt(Term,Term);
|
||||
static Int a_le(Term,Term);
|
||||
static Int a_noteq(Term,Term);
|
||||
static Int a_gen_lt(Term,Term);
|
||||
static Int a_gen_le(Term,Term);
|
||||
static Int a_gen_gt(Term,Term);
|
||||
static Int a_gen_ge(Term,Term);
|
||||
|
||||
#define rfloat(X) ( X > 0.0 ? 1 : ( X == 0.0 ? 0 : -1))
|
||||
|
||||
static int
|
||||
cmp_atoms(Atom a1, Atom a2)
|
||||
{
|
||||
if (IsWideAtom(a1)) {
|
||||
if (IsWideAtom(a2)) {
|
||||
return wcscmp((wchar_t *)RepAtom(a1)->StrOfAE,(wchar_t *)RepAtom(a2)->StrOfAE);
|
||||
} else {
|
||||
/* The standard does not seem to have nothing on this */
|
||||
unsigned char *s1 = (unsigned char *)RepAtom(a1)->StrOfAE;
|
||||
wchar_t *s2 = (wchar_t *)RepAtom(a2)->StrOfAE;
|
||||
|
||||
while (*s1 == *s2) {
|
||||
if (!*s1) return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *s1-*s2;
|
||||
}
|
||||
} else if (IsWideAtom(a2)) {
|
||||
/* The standard does not seem to have nothing on this */
|
||||
wchar_t *s1 = (wchar_t *)RepAtom(a1)->StrOfAE;
|
||||
unsigned char *s2 = (unsigned char *)RepAtom(a2)->StrOfAE;
|
||||
|
||||
while (*s1 == *s2) {
|
||||
if (!*s1) return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *s1-*s2;
|
||||
} else {
|
||||
return strcmp((char *)RepAtom(a1)->StrOfAE,(char *)RepAtom(a2)->StrOfAE);
|
||||
}
|
||||
}
|
||||
|
||||
static int compare_complex(register CELL *pt0, register CELL *pt0_end, register
|
||||
CELL *pt1)
|
||||
{
|
||||
CACHE_REGS
|
||||
register CELL **to_visit = (CELL **)HR;
|
||||
register int out = 0;
|
||||
|
||||
loop:
|
||||
while (pt0 < pt0_end) {
|
||||
register CELL d0, d1;
|
||||
++ pt0;
|
||||
++ pt1;
|
||||
d0 = Derefa(pt0);
|
||||
d1 = Derefa(pt1);
|
||||
if (IsVarTerm(d0)) {
|
||||
if (IsVarTerm(d1)) {
|
||||
out = Signed(d0) - Signed(d1);
|
||||
if (out) goto done;
|
||||
}
|
||||
else {
|
||||
out = -1;
|
||||
goto done;
|
||||
}
|
||||
} else if (IsVarTerm(d1)) {
|
||||
out = 1;
|
||||
goto done;
|
||||
} else {
|
||||
if (d0 == d1) continue;
|
||||
else if (IsAtomTerm(d0)) {
|
||||
if (IsAtomTerm(d1))
|
||||
out = cmp_atoms(AtomOfTerm(d0), AtomOfTerm(d1));
|
||||
else if (IsPrimitiveTerm(d1))
|
||||
out = 1;
|
||||
else out = -1;
|
||||
/* I know out must be != 0 */
|
||||
goto done;
|
||||
}
|
||||
else if (IsIntTerm(d0)) {
|
||||
if (IsIntTerm(d1))
|
||||
out = IntOfTerm(d0) - IntOfTerm(d1);
|
||||
else if (IsFloatTerm(d1)) {
|
||||
out = 1;
|
||||
} else if (IsLongIntTerm(d1)) {
|
||||
out = IntOfTerm(d0) - LongIntOfTerm(d1);
|
||||
#ifdef USE_GMP
|
||||
} else if (IsBigIntTerm(d1)) {
|
||||
out = Yap_gmp_tcmp_int_big(IntOfTerm(d0), d1);
|
||||
#endif
|
||||
} else if (IsRefTerm(d1))
|
||||
out = 1 ;
|
||||
else out = -1;
|
||||
if (out != 0)
|
||||
goto done;
|
||||
} else if (IsFloatTerm(d0)) {
|
||||
if (IsFloatTerm(d1)){
|
||||
out = rfloat(FloatOfTerm(d0) - FloatOfTerm(d1));
|
||||
} else if (IsRefTerm(d1)) {
|
||||
out = 1;
|
||||
} else {
|
||||
out = -1;
|
||||
}
|
||||
if (out != 0)
|
||||
goto done;
|
||||
} else if (IsStringTerm(d0)) {
|
||||
if (IsStringTerm(d1)){
|
||||
out = strcmp((char *)StringOfTerm(d0) , (char *)StringOfTerm(d1));
|
||||
} else if (IsIntTerm(d1))
|
||||
out = 1;
|
||||
else if (IsFloatTerm(d1)) {
|
||||
out = 1;
|
||||
} else if (IsLongIntTerm(d1)) {
|
||||
out = 1;
|
||||
#ifdef USE_GMP
|
||||
} else if (IsBigIntTerm(d1)) {
|
||||
out = 1;
|
||||
#endif
|
||||
} else if (IsRefTerm(d1)) {
|
||||
out = 1 ;
|
||||
} else {
|
||||
out = -1;
|
||||
}
|
||||
if (out != 0)
|
||||
goto done;
|
||||
} else if (IsLongIntTerm(d0)) {
|
||||
if (IsIntTerm(d1))
|
||||
out = LongIntOfTerm(d0) - IntOfTerm(d1);
|
||||
else if (IsFloatTerm(d1)) {
|
||||
out = 1;
|
||||
} else if (IsLongIntTerm(d1)) {
|
||||
out = LongIntOfTerm(d0) - LongIntOfTerm(d1);
|
||||
#ifdef USE_GMP
|
||||
} else if (IsBigIntTerm(d1)) {
|
||||
out = Yap_gmp_tcmp_int_big(LongIntOfTerm(d0), d1);
|
||||
#endif
|
||||
} else if (IsRefTerm(d1)) {
|
||||
out = 1 ;
|
||||
} else {
|
||||
out = -1;
|
||||
}
|
||||
if (out != 0)
|
||||
goto done;
|
||||
}
|
||||
#ifdef USE_GMP
|
||||
else if (IsBigIntTerm(d0)) {
|
||||
if (IsIntTerm(d1)) {
|
||||
out = Yap_gmp_tcmp_int_big(d0, IntOfTerm(d1));
|
||||
} else if (IsFloatTerm(d1)) {
|
||||
out = 1;
|
||||
} else if (IsLongIntTerm(d1)) {
|
||||
out = Yap_gmp_tcmp_int_big(d0, LongIntOfTerm(d1));
|
||||
} else if (IsBigIntTerm(d1)) {
|
||||
out = Yap_gmp_tcmp_big_big(d0, d1);
|
||||
} else if (IsRefTerm(d1))
|
||||
out = 1 ;
|
||||
else out = -1;
|
||||
if (out != 0)
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
else if (IsPairTerm(d0)) {
|
||||
if (!IsPairTerm(d1)) {
|
||||
if (IsApplTerm(d1)) {
|
||||
Functor f = FunctorOfTerm(d1);
|
||||
if (IsExtensionFunctor(f))
|
||||
out = 1;
|
||||
else if (!(out = 2-ArityOfFunctor(f)))
|
||||
out = strcmp(".",(char *)RepAtom(NameOfFunctor(f))->StrOfAE);
|
||||
} else out = 1;
|
||||
goto done;
|
||||
}
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit[3] = (CELL *)*pt0;
|
||||
to_visit += 4;
|
||||
*pt0 = d1;
|
||||
#else
|
||||
/* store the terms to visit */
|
||||
if (pt0 < pt0_end) {
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit += 3;
|
||||
}
|
||||
#endif
|
||||
pt0 = RepPair(d0) - 1;
|
||||
pt0_end = RepPair(d0) + 1;
|
||||
pt1 = RepPair(d1) - 1;
|
||||
continue;
|
||||
}
|
||||
else if (IsRefTerm(d0)) {
|
||||
if (IsRefTerm(d1))
|
||||
out = Unsigned(RefOfTerm(d1)) -
|
||||
Unsigned(RefOfTerm(d0));
|
||||
else out = -1;
|
||||
goto done;
|
||||
} else if (IsApplTerm(d0)) {
|
||||
register Functor f;
|
||||
register CELL *ap2, *ap3;
|
||||
if (!IsApplTerm(d1)) {
|
||||
out = 1 ;
|
||||
goto done;
|
||||
} else {
|
||||
/* store the terms to visit */
|
||||
Functor f2;
|
||||
ap2 = RepAppl(d0);
|
||||
ap3 = RepAppl(d1);
|
||||
f = (Functor)(*ap2);
|
||||
if (IsExtensionFunctor(f)) {
|
||||
out = 1;
|
||||
goto done;
|
||||
}
|
||||
f2 = (Functor)(*ap3);
|
||||
if (IsExtensionFunctor(f2)) {
|
||||
out = -1;
|
||||
goto done;
|
||||
}
|
||||
/* compare functors */
|
||||
if (f != (Functor)*ap3) {
|
||||
if (!(out = ArityOfFunctor(f)-ArityOfFunctor(f2)))
|
||||
out = cmp_atoms(NameOfFunctor(f), NameOfFunctor(f2));
|
||||
goto done;
|
||||
}
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit[3] = (CELL *)*pt0;
|
||||
to_visit += 4;
|
||||
*pt0 = d1;
|
||||
#else
|
||||
/* store the terms to visit */
|
||||
if (pt0 < pt0_end) {
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit += 3;
|
||||
}
|
||||
#endif
|
||||
d0 = ArityOfFunctor(f);
|
||||
pt0 = ap2;
|
||||
pt0_end = ap2 + d0;
|
||||
pt1 = ap3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/* Do we still have compound terms to visit */
|
||||
if (to_visit > (CELL **)HR) {
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit -= 4;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
pt1 = to_visit[2];
|
||||
*pt0 = (CELL)to_visit[3];
|
||||
#else
|
||||
to_visit -= 3;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
pt1 = to_visit[2];
|
||||
#endif
|
||||
goto loop;
|
||||
}
|
||||
|
||||
done:
|
||||
/* failure */
|
||||
#ifdef RATIONAL_TREES
|
||||
while (to_visit > (CELL **)HR) {
|
||||
to_visit -= 4;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
pt1 = to_visit[2];
|
||||
*pt0 = (CELL)to_visit[3];
|
||||
}
|
||||
#endif
|
||||
return(out);
|
||||
}
|
||||
|
||||
inline static Int
|
||||
compare(Term t1, Term t2) /* compare terms t1 and t2 */
|
||||
{
|
||||
|
||||
if (t1 == t2)
|
||||
return 0;
|
||||
if (IsVarTerm(t1)) {
|
||||
if (IsVarTerm(t2))
|
||||
return Signed(t1) - Signed(t2);
|
||||
return -1;
|
||||
} else if (IsVarTerm(t2)) {
|
||||
/* get rid of variables */
|
||||
return 1;
|
||||
}
|
||||
if (IsAtomOrIntTerm(t1)) {
|
||||
if (IsAtomTerm(t1)) {
|
||||
if (IsAtomTerm(t2))
|
||||
return cmp_atoms(AtomOfTerm(t1),AtomOfTerm(t2));
|
||||
if (IsPrimitiveTerm(t2))
|
||||
return 1;
|
||||
if (IsStringTerm(t2))
|
||||
return 1;
|
||||
return -1;
|
||||
} else {
|
||||
if (IsIntTerm(t2)) {
|
||||
return IntOfTerm(t1) - IntOfTerm(t2);
|
||||
}
|
||||
if (IsApplTerm(t2)) {
|
||||
Functor fun2 = FunctorOfTerm(t2);
|
||||
switch ((CELL)fun2) {
|
||||
case double_e:
|
||||
return 1;
|
||||
case long_int_e:
|
||||
return IntOfTerm(t1) - LongIntOfTerm(t2);
|
||||
#ifdef USE_GMP
|
||||
case big_int_e:
|
||||
return Yap_gmp_tcmp_int_big(IntOfTerm(t1), t2);
|
||||
#endif
|
||||
case db_ref_e:
|
||||
return 1;
|
||||
case string_e:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else if (IsPairTerm(t1)) {
|
||||
if (IsApplTerm(t2)) {
|
||||
Functor f = FunctorOfTerm(t2);
|
||||
if (IsExtensionFunctor(f))
|
||||
return 1;
|
||||
else {
|
||||
int out;
|
||||
if (!(out = 2-ArityOfFunctor(f)))
|
||||
out = strcmp(".",(char *)RepAtom(NameOfFunctor(f))->StrOfAE);
|
||||
return(out);
|
||||
}
|
||||
}
|
||||
if (IsPairTerm(t2)) {
|
||||
return(compare_complex(RepPair(t1)-1,
|
||||
RepPair(t1)+1,
|
||||
RepPair(t2)-1));
|
||||
}
|
||||
else return 1;
|
||||
} else {
|
||||
/* compound term */
|
||||
Functor fun1 = FunctorOfTerm(t1);
|
||||
|
||||
if (IsExtensionFunctor(fun1)) {
|
||||
/* float, long, big, dbref */
|
||||
switch ((CELL)fun1) {
|
||||
case double_e:
|
||||
{
|
||||
if (IsFloatTerm(t2))
|
||||
return(rfloat(FloatOfTerm(t1) - FloatOfTerm(t2)));
|
||||
if (IsRefTerm(t2))
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
case long_int_e:
|
||||
{
|
||||
if (IsIntTerm(t2))
|
||||
return LongIntOfTerm(t1) - IntOfTerm(t2);
|
||||
if (IsFloatTerm(t2)) {
|
||||
return 1;
|
||||
}
|
||||
if (IsLongIntTerm(t2))
|
||||
return LongIntOfTerm(t1) - LongIntOfTerm(t2);
|
||||
#ifdef USE_GMP
|
||||
if (IsBigIntTerm(t2)) {
|
||||
return Yap_gmp_tcmp_int_big(LongIntOfTerm(t1), t2);
|
||||
}
|
||||
#endif
|
||||
if (IsRefTerm(t2))
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
#ifdef USE_GMP
|
||||
case big_int_e:
|
||||
{
|
||||
if (IsIntTerm(t2))
|
||||
return Yap_gmp_tcmp_big_int(t1, IntOfTerm(t2));
|
||||
if (IsFloatTerm(t2)) {
|
||||
return 1;
|
||||
}
|
||||
if (IsLongIntTerm(t2))
|
||||
return Yap_gmp_tcmp_big_int(t1, LongIntOfTerm(t2));
|
||||
if (IsBigIntTerm(t2)) {
|
||||
return Yap_gmp_tcmp_big_big(t1, t2);
|
||||
}
|
||||
if (IsRefTerm(t2))
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
case string_e:
|
||||
{
|
||||
if (IsApplTerm(t2)) {
|
||||
Functor fun2 = FunctorOfTerm(t2);
|
||||
switch ((CELL)fun2) {
|
||||
case double_e:
|
||||
return 1;
|
||||
case long_int_e:
|
||||
return 1;
|
||||
#ifdef USE_GMP
|
||||
case big_int_e:
|
||||
return 1;
|
||||
#endif
|
||||
case db_ref_e:
|
||||
return 1;
|
||||
case string_e:
|
||||
return strcmp((char *)StringOfTerm(t1), (char *)StringOfTerm(t2));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
case db_ref_e:
|
||||
if (IsRefTerm(t2))
|
||||
return Unsigned(RefOfTerm(t2)) -
|
||||
Unsigned(RefOfTerm(t1));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!IsApplTerm(t2)) {
|
||||
if (IsPairTerm(t2)) {
|
||||
Int out;
|
||||
Functor f = FunctorOfTerm(t1);
|
||||
|
||||
if (!(out = ArityOfFunctor(f))-2)
|
||||
out = strcmp((char *)RepAtom(NameOfFunctor(f))->StrOfAE,".");
|
||||
return out;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
Functor fun2 = FunctorOfTerm(t2);
|
||||
Int r;
|
||||
|
||||
if (IsExtensionFunctor(fun2)) {
|
||||
return 1;
|
||||
}
|
||||
r = ArityOfFunctor(fun1) - ArityOfFunctor(fun2);
|
||||
if (r)
|
||||
return r;
|
||||
r = cmp_atoms(NameOfFunctor(fun1), NameOfFunctor(fun2));
|
||||
if (r)
|
||||
return r;
|
||||
else
|
||||
return(compare_complex(RepAppl(t1),
|
||||
RepAppl(t1)+ArityOfFunctor(fun1),
|
||||
RepAppl(t2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Int Yap_compare_terms(Term d0, Term d1)
|
||||
{
|
||||
return compare(Deref(d0),Deref(d1));
|
||||
}
|
||||
|
||||
/** @pred compare( _C_, _X_, _Y_) is iso
|
||||
|
||||
|
||||
As a result of comparing _X_ and _Y_, _C_ may take one of
|
||||
the following values:
|
||||
|
||||
+
|
||||
`=` if _X_ and _Y_ are identical;
|
||||
+
|
||||
`<` if _X_ precedes _Y_ in the defined order;
|
||||
+
|
||||
`>` if _Y_ precedes _X_ in the defined order;
|
||||
|
||||
*/
|
||||
Int
|
||||
p_compare( USES_REGS1 )
|
||||
{ /* compare(?Op,?T1,?T2) */
|
||||
Int r = compare(Deref(ARG2), Deref(ARG3));
|
||||
Atom p;
|
||||
Term t = Deref(ARG1);
|
||||
if (r < 0)
|
||||
p = AtomLT;
|
||||
else if (r > 0)
|
||||
p = AtomGT;
|
||||
else
|
||||
p = AtomEQ;
|
||||
if (!IsVarTerm(t)) {
|
||||
if (IsAtomTerm(t)) {
|
||||
Atom a = AtomOfTerm(t);
|
||||
if (a == p)
|
||||
return true;
|
||||
if (a != AtomLT &&
|
||||
a != AtomGT &&
|
||||
a != AtomEq)
|
||||
Yap_Error(DOMAIN_ERROR_ORDER, ARG1, NULL);
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_ATOM, ARG1, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return Yap_unify_constant(ARG1, MkAtomTerm(p));
|
||||
}
|
||||
|
||||
|
||||
/** @pred _X_ \== _Y_ is iso
|
||||
|
||||
Terms _X_ and _Y_ are not strictly identical.
|
||||
*/
|
||||
static Int
|
||||
a_noteq(Term t1, Term t2)
|
||||
{
|
||||
return (compare(t1, t2) != 0);
|
||||
}
|
||||
|
||||
static Int
|
||||
a_gen_lt(Term t1, Term t2)
|
||||
{
|
||||
return (compare(t1, t2) < 0);
|
||||
}
|
||||
|
||||
/** @pred _X_ @=< _Y_ is iso
|
||||
|
||||
|
||||
Term _X_ does not follow term _Y_ in the standard order.
|
||||
|
||||
*/
|
||||
static Int
|
||||
a_gen_le(Term t1, Term t2)
|
||||
{
|
||||
return (compare(t1, t2) <= 0);
|
||||
}
|
||||
|
||||
/** @pred _X_ @> _Y_ is iso
|
||||
|
||||
|
||||
Term _X_ does not follow term _Y_ in the standard order
|
||||
*/
|
||||
static Int
|
||||
a_gen_gt(Term t1, Term t2)
|
||||
{
|
||||
return compare(t1, t2) > 0;
|
||||
}
|
||||
|
||||
/** @pred _X_ @>= _Y_ is iso
|
||||
|
||||
Term _X_ does not precede term _Y_ in the standard order.
|
||||
*/
|
||||
static Int
|
||||
a_gen_ge(Term t1, Term t2)
|
||||
{
|
||||
return compare(t1, t2) >= 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@defgroup arithmetic_cmps Arithmetic Comparison Predicates
|
||||
@ingroup arithmetic
|
||||
|
||||
Comparison of Numeric Expressions. Both arguments must be valid ground expressions at time of call.
|
||||
|
||||
@{
|
||||
*/
|
||||
inline static Int
|
||||
int_cmp(Int dif)
|
||||
{
|
||||
return dif;
|
||||
}
|
||||
|
||||
inline static Int
|
||||
flt_cmp(Float dif)
|
||||
{
|
||||
if (dif < 0.0)
|
||||
return -1;
|
||||
if (dif > 0.0)
|
||||
return 1;
|
||||
return dif = 0.0;
|
||||
}
|
||||
|
||||
|
||||
static inline Int
|
||||
a_cmp(Term t1, Term t2 USES_REGS)
|
||||
{
|
||||
LOCAL_ArithError = FALSE;
|
||||
if (IsVarTerm(t1)) {
|
||||
LOCAL_ArithError = TRUE;
|
||||
Yap_Error(INSTANTIATION_ERROR, t1, "=:=/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (IsVarTerm(t2)) {
|
||||
LOCAL_ArithError = TRUE;
|
||||
Yap_Error(INSTANTIATION_ERROR, t2, "=:=/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (IsFloatTerm(t1) && IsFloatTerm(t2)) {
|
||||
return flt_cmp(FloatOfTerm(t1)-FloatOfTerm(t2));
|
||||
}
|
||||
if (IsIntegerTerm(t1) && IsIntegerTerm(t2)) {
|
||||
return int_cmp(IntegerOfTerm(t1)-IntegerOfTerm(t2));
|
||||
}
|
||||
t1 = Yap_Eval(t1);
|
||||
if (!t1) {
|
||||
return FALSE;
|
||||
}
|
||||
if (IsIntegerTerm(t1)) {
|
||||
Int i1 = IntegerOfTerm(t1);
|
||||
t2 = Yap_Eval(t2);
|
||||
|
||||
if (IsIntegerTerm(t2)) {
|
||||
Int i2 = IntegerOfTerm(t2);
|
||||
return int_cmp(i1-i2);
|
||||
} else if (IsFloatTerm(t2)) {
|
||||
Float f2 = FloatOfTerm(t2);
|
||||
#if HAVE_ISNAN
|
||||
if (isnan(f2)) {
|
||||
LOCAL_Error_TYPE = EVALUATION_ERROR_UNDEFINED;
|
||||
LOCAL_Error_Term = t2;
|
||||
LOCAL_ErrorMessage = "trying to evaluate nan";
|
||||
LOCAL_ArithError = TRUE;
|
||||
}
|
||||
#endif
|
||||
return flt_cmp(i1-f2);
|
||||
#ifdef USE_GMP
|
||||
} else if (IsBigIntTerm(t2)) {
|
||||
return Yap_gmp_cmp_int_big(i1,t2);
|
||||
#endif
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else if (IsFloatTerm(t1)) {
|
||||
Float f1 = FloatOfTerm(t1);
|
||||
#if HAVE_ISNAN
|
||||
if (isnan(f1)) {
|
||||
LOCAL_Error_TYPE = EVALUATION_ERROR_UNDEFINED;
|
||||
LOCAL_Error_Term = t1;
|
||||
LOCAL_ErrorMessage = "trying to evaluate nan";
|
||||
LOCAL_ArithError = TRUE;
|
||||
}
|
||||
#endif
|
||||
t2 = Yap_Eval(t2);
|
||||
#if HAVE_ISNAN
|
||||
if (isnan(f1))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (IsIntegerTerm(t2)) {
|
||||
Int i2 = IntegerOfTerm(t2);
|
||||
return flt_cmp(f1-i2);
|
||||
} else if (IsFloatTerm(t2)) {
|
||||
Float f2 = FloatOfTerm(t2);
|
||||
#if HAVE_ISNAN
|
||||
if (isnan(f2)) {
|
||||
LOCAL_Error_TYPE = EVALUATION_ERROR_UNDEFINED;
|
||||
LOCAL_Error_Term = t2;
|
||||
LOCAL_ErrorMessage = "trying to evaluate nan";
|
||||
LOCAL_ArithError = TRUE;
|
||||
}
|
||||
#endif
|
||||
return flt_cmp(f1-f2);
|
||||
#ifdef USE_GMP
|
||||
} else if (IsBigIntTerm(t2)) {
|
||||
return Yap_gmp_cmp_float_big(f1,t2);
|
||||
#endif
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#ifdef USE_GMP
|
||||
} else if (IsBigIntTerm(t1)) {
|
||||
{
|
||||
t2 = Yap_Eval(t2);
|
||||
|
||||
if (IsIntegerTerm(t2)) {
|
||||
return Yap_gmp_cmp_big_int(t1, IntegerOfTerm(t2));
|
||||
} else if (IsFloatTerm(t2)) {
|
||||
Float f2 = FloatOfTerm(t2);
|
||||
#if HAVE_ISNAN
|
||||
if (isnan(f2)) {
|
||||
LOCAL_Error_TYPE = EVALUATION_ERROR_UNDEFINED;
|
||||
LOCAL_Error_Term = t2;
|
||||
LOCAL_ErrorMessage = "trying to evaluate nan";
|
||||
LOCAL_ArithError = TRUE;
|
||||
}
|
||||
#endif
|
||||
return Yap_gmp_cmp_big_float(t1, f2);
|
||||
} else if (IsBigIntTerm(t2)) {
|
||||
return Yap_gmp_cmp_big_big(t1, t2);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_acmp(Term t1, Term t2 USES_REGS)
|
||||
{
|
||||
Int out = a_cmp(t1, t2 PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_acomp( USES_REGS1 )
|
||||
{ /* $a_compare(?R,+X,+Y) */
|
||||
Term t1 = Deref(ARG1);
|
||||
Term t2 = Deref(ARG2);
|
||||
Int out;
|
||||
|
||||
out = a_cmp(t1, t2 PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
@pred +_X_ =:= _Y_ is iso
|
||||
Equality of arithmetic expressions
|
||||
|
||||
The value of the expression _X_ is equal to the value of expression _Y_.
|
||||
*/
|
||||
/// @memberof =:=/2
|
||||
static Int
|
||||
a_eq(Term t1, Term t2)
|
||||
{
|
||||
CACHE_REGS
|
||||
/* A =:= B */
|
||||
Int out;
|
||||
t1 = Deref(t1);
|
||||
t2 = Deref(t2);
|
||||
|
||||
if (IsVarTerm(t1)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t1, "=:=/2");
|
||||
return(FALSE);
|
||||
}
|
||||
if (IsVarTerm(t2)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t2, "=:=/2");
|
||||
return(FALSE);
|
||||
}
|
||||
if (IsFloatTerm(t1)) {
|
||||
if (IsFloatTerm(t2))
|
||||
return (FloatOfTerm(t1) == FloatOfTerm(t2));
|
||||
else if (IsIntegerTerm(t2)) {
|
||||
return (FloatOfTerm(t1) == IntegerOfTerm(t2));
|
||||
}
|
||||
}
|
||||
if (IsIntegerTerm(t1)) {
|
||||
if (IsIntegerTerm(t2)) {
|
||||
return (IntegerOfTerm(t1) == IntegerOfTerm(t2));
|
||||
} else if (IsFloatTerm(t2)) {
|
||||
return (FloatOfTerm(t2) == IntegerOfTerm(t1));
|
||||
}
|
||||
}
|
||||
out = a_cmp(t1,t2 PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@pred +_X_ =\\= _Y_ is iso
|
||||
Difference of arithmetic expressions
|
||||
|
||||
The value of the expression _X_ is different from the value of expression _Y_.
|
||||
*/
|
||||
/// @memberof =\\=/2
|
||||
static Int
|
||||
a_dif(Term t1, Term t2)
|
||||
{
|
||||
CACHE_REGS
|
||||
Int out = a_cmp(Deref(t1),Deref(t2) PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@pred +_X_ \> +_Y_ is iso
|
||||
Greater than arithmetic expressions
|
||||
|
||||
The value of the expression _X_ is less than or equal to the value
|
||||
of expression _Y_.
|
||||
*/
|
||||
static Int
|
||||
a_gt(Term t1, Term t2)
|
||||
{ /* A > B */
|
||||
CACHE_REGS
|
||||
Int out = a_cmp(Deref(t1),Deref(t2) PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@pred +_X_ >= +_Y_ is iso
|
||||
Greater than or equal to arithmetic expressions
|
||||
|
||||
The value of the expression _X_ is greater than or equal to the
|
||||
value of expression _Y_.
|
||||
*/
|
||||
static Int
|
||||
a_ge(Term t1, Term t2)
|
||||
{ /* A >= B */
|
||||
CACHE_REGS
|
||||
Int out = a_cmp(Deref(t1),Deref(t2) PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@pred +_X_ \< +_Y_ is iso
|
||||
Lesser than arithmetic expressions
|
||||
|
||||
The value of the expression _X_ is less than the value of expression
|
||||
_Y_.
|
||||
*/
|
||||
/// @memberof </2
|
||||
static Int
|
||||
a_lt(Term t1, Term t2)
|
||||
{ /* A < B */
|
||||
CACHE_REGS
|
||||
Int out = a_cmp(Deref(t1),Deref(t2) PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@pred _X_ =< + _Y_
|
||||
Lesser than or equal to arithmetic expressions
|
||||
|
||||
|
||||
The value of the expression _X_ is less than or equal to the value
|
||||
of expression _Y_.
|
||||
*/
|
||||
/// @memberof =</2
|
||||
static Int
|
||||
a_le(Term t1, Term t2)
|
||||
{ /* A <= B */
|
||||
CACHE_REGS
|
||||
Int out = a_cmp(Deref(t1),Deref(t2) PASS_REGS);
|
||||
if (LOCAL_ArithError) { Yap_Error(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage); return FALSE; }
|
||||
return out <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
||||
|
||||
void
|
||||
Yap_InitCmpPreds(void)
|
||||
{
|
||||
Yap_InitCmpPred("=:=", 2, a_eq, SafePredFlag | BinaryPredFlag);
|
||||
Yap_InitCmpPred("=\\=", 2, a_dif, SafePredFlag | BinaryPredFlag);
|
||||
Yap_InitCmpPred(">", 2, a_gt, SafePredFlag | BinaryPredFlag);
|
||||
Yap_InitCmpPred("=<", 2, a_le, SafePredFlag | BinaryPredFlag);
|
||||
Yap_InitCmpPred("<", 2, a_lt, SafePredFlag | BinaryPredFlag);
|
||||
Yap_InitCmpPred(">=", 2, a_ge, SafePredFlag | BinaryPredFlag);
|
||||
Yap_InitCPred("$a_compare", 3, p_acomp, TestPredFlag | SafePredFlag);
|
||||
Yap_InitCmpPred("\\==", 2, a_noteq, BinaryPredFlag | SafePredFlag);
|
||||
Yap_InitCmpPred("@<", 2, a_gen_lt, BinaryPredFlag | SafePredFlag);
|
||||
Yap_InitCmpPred("@=<", 2, a_gen_le, BinaryPredFlag | SafePredFlag);
|
||||
Yap_InitCmpPred("@>", 2, a_gen_gt, BinaryPredFlag | SafePredFlag);
|
||||
Yap_InitCmpPred("@>=", 2, a_gen_ge, BinaryPredFlag | SafePredFlag);
|
||||
Yap_InitCPred("compare", 3, p_compare, TestPredFlag | SafePredFlag);
|
||||
}
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,798 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: computils.c *
|
||||
* comments: some useful routines for YAP's compiler *
|
||||
* *
|
||||
* Last rev: $Date: 2007-11-26 23:43:08 $ *
|
||||
* $Log: not supported by cvs2svn $
|
||||
* Revision 1.31 2007/11/06 17:02:12 vsc
|
||||
* compile ground terms away.
|
||||
*
|
||||
* Revision 1.30 2006/09/20 20:03:51 vsc
|
||||
* improve indexing on floats
|
||||
* fix sending large lists to DB
|
||||
*
|
||||
* Revision 1.29 2005/12/05 17:16:10 vsc
|
||||
* write_depth/3
|
||||
* overflow handlings and garbage collection
|
||||
* Several ipdates to CLPBN
|
||||
* dif/2 could be broken in the presence of attributed variables.
|
||||
*
|
||||
* Revision 1.28 2005/09/08 22:06:44 rslopes
|
||||
* BEAM for YAP update...
|
||||
*
|
||||
* Revision 1.27 2005/07/06 15:10:04 vsc
|
||||
* improvements to compiler: merged instructions and fixes for ->
|
||||
*
|
||||
* Revision 1.26 2005/01/04 02:50:21 vsc
|
||||
* - allow MegaClauses with blobs
|
||||
* - change Diffs to be thread specific
|
||||
* - include Christian's updates
|
||||
*
|
||||
* Revision 1.25 2004/11/19 17:14:13 vsc
|
||||
* a few fixes for 64 bit compiling.
|
||||
*
|
||||
* Revision 1.24 2004/04/16 19:27:31 vsc
|
||||
* more bug fixes
|
||||
*
|
||||
* Revision 1.23 2004/03/10 14:59:55 vsc
|
||||
* optimise -> for type tests
|
||||
* *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file includes a set of utilities, useful to the several compilation
|
||||
* modules
|
||||
*/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "compile.h"
|
||||
#include "yapio.h"
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The compiler creates an instruction chain which will be assembled after
|
||||
* afterwards
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct mem_blk {
|
||||
union {
|
||||
struct mem_blk *next;
|
||||
double fill;
|
||||
} ublock;
|
||||
char contents[1];
|
||||
} MemBlk;
|
||||
|
||||
#define CMEM_BLK_SIZE (4*4096)
|
||||
#define FIRST_CMEM_BLK_SIZE (16*4096)
|
||||
|
||||
static char *
|
||||
AllocCMem (UInt size, struct intermediates *cip)
|
||||
{
|
||||
#if SIZEOF_INT_P==8
|
||||
size = (size + 7) & ((UInt)-8);
|
||||
#else
|
||||
size = (size + 3) & ((UInt)0xfffffffc);
|
||||
#endif
|
||||
#if USE_SYSTEM_MALLOC
|
||||
if (!cip->blks || cip->blk_cur+size > cip->blk_top) {
|
||||
UInt blksz;
|
||||
struct mem_blk *p;
|
||||
|
||||
if (size > CMEM_BLK_SIZE)
|
||||
blksz = size+sizeof(struct mem_blk);
|
||||
else
|
||||
blksz = CMEM_BLK_SIZE;
|
||||
if (!cip->blks) {
|
||||
CACHE_REGS
|
||||
if (LOCAL_CMemFirstBlock) {
|
||||
p = LOCAL_CMemFirstBlock;
|
||||
blksz = LOCAL_CMemFirstBlockSz;
|
||||
p->ublock.next = NULL;
|
||||
} else {
|
||||
if (blksz < FIRST_CMEM_BLK_SIZE)
|
||||
blksz = FIRST_CMEM_BLK_SIZE;
|
||||
p = (struct mem_blk *)Yap_AllocCodeSpace(blksz);
|
||||
if (!p) {
|
||||
LOCAL_Error_Size = size;
|
||||
save_machine_regs();
|
||||
siglongjmp(cip->CompilerBotch, OUT_OF_HEAP_BOTCH);
|
||||
}
|
||||
LOCAL_CMemFirstBlock = p;
|
||||
LOCAL_CMemFirstBlockSz = blksz;
|
||||
}
|
||||
} else {
|
||||
p = (struct mem_blk *)Yap_AllocCodeSpace(blksz);
|
||||
if (!p) {
|
||||
CACHE_REGS
|
||||
LOCAL_Error_Size = size;
|
||||
save_machine_regs();
|
||||
siglongjmp(cip->CompilerBotch, OUT_OF_HEAP_BOTCH);
|
||||
}
|
||||
}
|
||||
p->ublock.next = cip->blks;
|
||||
cip->blks = p;
|
||||
cip->blk_cur = p->contents;
|
||||
cip->blk_top = (char *)p+blksz;
|
||||
}
|
||||
{
|
||||
char *out = cip->blk_cur;
|
||||
cip->blk_cur += size;
|
||||
return out;
|
||||
}
|
||||
#else
|
||||
char *p;
|
||||
if (ASP <= CellPtr (cip->freep) + 256) {
|
||||
CACHE_REGS
|
||||
LOCAL_Error_Size = 256+((char *)cip->freep - (char *)HR);
|
||||
save_machine_regs();
|
||||
siglongjmp(cip->CompilerBotch, OUT_OF_STACK_BOTCH);
|
||||
}
|
||||
p = cip->freep;
|
||||
cip->freep += size;
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ReleaseCMem (struct intermediates *cip)
|
||||
{
|
||||
#if USE_SYSTEM_MALLOC
|
||||
CACHE_REGS
|
||||
struct mem_blk *p = cip->blks;
|
||||
while (p) {
|
||||
struct mem_blk *nextp = p->ublock.next;
|
||||
if (p != LOCAL_CMemFirstBlock)
|
||||
Yap_FreeCodeSpace((ADDR)p);
|
||||
p = nextp;
|
||||
}
|
||||
cip->blks = NULL;
|
||||
if (cip->label_offset &&
|
||||
cip->label_offset != LOCAL_LabelFirstArray) {
|
||||
Yap_FreeCodeSpace((ADDR)cip->label_offset);
|
||||
}
|
||||
#endif
|
||||
cip->label_offset = NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
Yap_AllocCMem (UInt size, struct intermediates *cip)
|
||||
{
|
||||
return AllocCMem(size, cip);
|
||||
}
|
||||
|
||||
static int
|
||||
is_a_test(Term arg, Term mod)
|
||||
{
|
||||
if (IsVarTerm (arg)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (IsVarTerm (arg) || !IsAtomTerm(mod)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (IsAtomTerm (arg)) {
|
||||
Atom At = AtomOfTerm (arg);
|
||||
PredEntry *pe = RepPredProp(PredPropByAtom(At, mod));
|
||||
if (EndOfPAEntr(pe))
|
||||
return FALSE;
|
||||
return pe->PredFlags & TestPredFlag;
|
||||
}
|
||||
if (IsApplTerm (arg)) {
|
||||
Functor f = FunctorOfTerm (arg);
|
||||
|
||||
if (f == FunctorModule) {
|
||||
return is_a_test(ArgOfTerm(2,arg), ArgOfTerm(1,arg));
|
||||
} else if (f == FunctorComma) {
|
||||
return
|
||||
is_a_test(ArgOfTerm(1,arg), mod) &&
|
||||
is_a_test(ArgOfTerm(2,arg), mod);
|
||||
} else {
|
||||
PredEntry *pe = RepPredProp(PredPropByFunc(f, mod));
|
||||
|
||||
if (EndOfPAEntr(pe))
|
||||
return FALSE;
|
||||
if (pe->PredFlags & AsmPredFlag) {
|
||||
int op = pe->PredFlags & 0x7f;
|
||||
if (op >= _atom && op <= _eq) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
return pe->PredFlags & (TestPredFlag|BinaryPredFlag);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_is_a_test_pred (Term arg, Term mod)
|
||||
{
|
||||
return is_a_test(arg, mod);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_emit (compiler_vm_op o, Int r1, CELL r2, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p), cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->rnd2 = r2;
|
||||
p->nextInst = NULL;
|
||||
if (cip->cpc == NIL) {
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
} else {
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_emit_3ops (compiler_vm_op o, CELL r1, CELL r2, CELL r3, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p)+sizeof(CELL), cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->rnd2 = r2;
|
||||
p->rnd3 = r3;
|
||||
p->nextInst = NIL;
|
||||
if (cip->cpc == NIL)
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
else
|
||||
{
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_emit_4ops (compiler_vm_op o, CELL r1, CELL r2, CELL r3, CELL r4, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p)+2*sizeof(CELL), cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->rnd2 = r2;
|
||||
p->rnd3 = r3;
|
||||
p->rnd4 = r4;
|
||||
p->nextInst = NIL;
|
||||
if (cip->cpc == NIL)
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
else
|
||||
{
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_emit_5ops (compiler_vm_op o, CELL r1, CELL r2, CELL r3, CELL r4, CELL r5, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p)+3*sizeof(CELL), cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->rnd2 = r2;
|
||||
p->rnd3 = r3;
|
||||
p->rnd4 = r4;
|
||||
p->rnd5 = r5;
|
||||
p->nextInst = NIL;
|
||||
if (cip->cpc == NIL)
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
else
|
||||
{
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_emit_6ops (compiler_vm_op o, CELL r1, CELL r2, CELL r3, CELL r4, CELL r5, CELL r6, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p)+4*sizeof(CELL), cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->rnd2 = r2;
|
||||
p->rnd3 = r3;
|
||||
p->rnd4 = r4;
|
||||
p->rnd5 = r5;
|
||||
p->rnd6 = r6;
|
||||
p->nextInst = NIL;
|
||||
if (cip->cpc == NIL)
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
else
|
||||
{
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_emit_7ops (compiler_vm_op o, CELL r1, CELL r2, CELL r3, CELL r4, CELL r5, CELL r6, CELL r7, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p)+5*sizeof(CELL), cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->rnd2 = r2;
|
||||
p->rnd3 = r3;
|
||||
p->rnd4 = r4;
|
||||
p->rnd5 = r5;
|
||||
p->rnd6 = r6;
|
||||
p->rnd7 = r7;
|
||||
p->nextInst = NIL;
|
||||
if (cip->cpc == NIL)
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
else
|
||||
{
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
}
|
||||
|
||||
CELL *
|
||||
Yap_emit_extra_size (compiler_vm_op o, CELL r1, int size, struct intermediates *cip)
|
||||
{
|
||||
PInstr *p;
|
||||
p = (PInstr *) AllocCMem (sizeof (*p) + size - CellSize, cip);
|
||||
p->op = o;
|
||||
p->rnd1 = r1;
|
||||
p->nextInst = NIL;
|
||||
if (cip->cpc == NIL)
|
||||
cip->cpc = cip->CodeStart = p;
|
||||
else
|
||||
{
|
||||
cip->cpc->nextInst = p;
|
||||
cip->cpc = p;
|
||||
}
|
||||
return p->arnds;
|
||||
}
|
||||
|
||||
static void
|
||||
bip_name(Int op, char *s)
|
||||
{
|
||||
switch (op) {
|
||||
case _atom:
|
||||
strcpy(s,"atom");
|
||||
break;
|
||||
case _atomic:
|
||||
strcpy(s,"atomic");
|
||||
break;
|
||||
case _integer:
|
||||
strcpy(s,"integer");
|
||||
break;
|
||||
case _nonvar:
|
||||
strcpy(s,"nonvar");
|
||||
break;
|
||||
case _number:
|
||||
strcpy(s,"number");
|
||||
break;
|
||||
case _var:
|
||||
strcpy(s,"var");
|
||||
break;
|
||||
case _cut_by:
|
||||
strcpy(s,"cut_by");
|
||||
break;
|
||||
case _save_by:
|
||||
strcpy(s,"save_by");
|
||||
break;
|
||||
case _db_ref:
|
||||
strcpy(s,"db_ref");
|
||||
break;
|
||||
case _compound:
|
||||
strcpy(s,"compound");
|
||||
break;
|
||||
case _float:
|
||||
strcpy(s,"float");
|
||||
break;
|
||||
case _primitive:
|
||||
strcpy(s,"primitive");
|
||||
break;
|
||||
case _equal:
|
||||
strcpy(s,"equal");
|
||||
break;
|
||||
case _dif:
|
||||
strcpy(s,"dif");
|
||||
break;
|
||||
case _eq:
|
||||
strcpy(s,"eq");
|
||||
break;
|
||||
case _functor:
|
||||
strcpy(s,"functor");
|
||||
break;
|
||||
case _plus:
|
||||
strcpy(s,"plus");
|
||||
break;
|
||||
case _minus:
|
||||
strcpy(s,"minus");
|
||||
break;
|
||||
case _times:
|
||||
strcpy(s,"times");
|
||||
break;
|
||||
case _div:
|
||||
strcpy(s,"div");
|
||||
break;
|
||||
case _and:
|
||||
strcpy(s,"and");
|
||||
break;
|
||||
case _or:
|
||||
strcpy(s,"or");
|
||||
break;
|
||||
case _sll:
|
||||
strcpy(s,"sll");
|
||||
break;
|
||||
case _slr:
|
||||
strcpy(s,"slr");
|
||||
break;
|
||||
case _arg:
|
||||
strcpy(s,"arg");
|
||||
break;
|
||||
default:
|
||||
strcpy(s,"");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Yap_bip_name(Int op, char *s) {
|
||||
bip_name(op,s);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static void
|
||||
write_address(CELL address)
|
||||
{
|
||||
if (address < (CELL)AtomBase) {
|
||||
Yap_DebugErrorPutc('L');
|
||||
Yap_DebugPlWrite(MkIntTerm (address));
|
||||
} else if (address == (CELL) FAILCODE) {
|
||||
Yap_DebugPlWrite (MkAtomTerm (AtomFail));
|
||||
} else {
|
||||
char buf[32], *p = buf;
|
||||
|
||||
#if HAVE_SNPRINTF
|
||||
snprintf(buf,32,"%p",(void *)address);
|
||||
#else
|
||||
sprintf(buf,"%p",(void *)address);
|
||||
#endif
|
||||
p[31] = '\0'; /* so that I don't have to worry */
|
||||
//Yap_DebugErrorPutc('0');
|
||||
//Yap_DebugErrorPutc('x');
|
||||
while (*p != '\0') {
|
||||
Yap_DebugErrorPutc(*p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_special_label(special_label_op arg, special_label_id rn, UInt lab)
|
||||
{
|
||||
switch (arg) {
|
||||
case SPECIAL_LABEL_INIT:
|
||||
Yap_DebugErrorPuts("init,");
|
||||
switch (rn) {
|
||||
case SPECIAL_LABEL_EXCEPTION:
|
||||
Yap_DebugErrorPuts("exception,");
|
||||
break;
|
||||
case SPECIAL_LABEL_SUCCESS:
|
||||
Yap_DebugErrorPuts("success,");
|
||||
break;
|
||||
case SPECIAL_LABEL_FAILURE:
|
||||
Yap_DebugErrorPuts("fail,");
|
||||
break;
|
||||
}
|
||||
write_address(lab);
|
||||
case SPECIAL_LABEL_SET:
|
||||
Yap_DebugErrorPuts("set,");
|
||||
break;
|
||||
case SPECIAL_LABEL_CLEAR:
|
||||
Yap_DebugErrorPuts("clear,");
|
||||
switch (rn) {
|
||||
case SPECIAL_LABEL_EXCEPTION:
|
||||
Yap_DebugErrorPuts("exception");
|
||||
break;
|
||||
case SPECIAL_LABEL_SUCCESS:
|
||||
Yap_DebugErrorPuts("success");
|
||||
break;
|
||||
case SPECIAL_LABEL_FAILURE:
|
||||
Yap_DebugErrorPuts("fail");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_functor(Functor f)
|
||||
{
|
||||
if (IsExtensionFunctor(f)) {
|
||||
if (f == FunctorDBRef) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomDBREF));
|
||||
} else if (f == FunctorLongInt) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomLONGINT));
|
||||
} else if (f == FunctorBigInt) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomLONGINT));
|
||||
} else if (f == FunctorDouble) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomDOUBLE));
|
||||
} else if (f == FunctorString) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomSTRING));
|
||||
}
|
||||
} else {
|
||||
Yap_DebugPlWrite(MkAtomTerm(NameOfFunctor (f)));
|
||||
Yap_DebugErrorPutc ('/');
|
||||
Yap_DebugPlWrite(MkIntTerm(ArityOfFunctor (f)));
|
||||
}
|
||||
}
|
||||
|
||||
char *opDesc[] = { mklist(f_arr) };
|
||||
|
||||
static void send_pred(PredEntry *p)
|
||||
{
|
||||
Functor f = p->FunctorOfPred;
|
||||
UInt arity = p->ArityOfPE;
|
||||
Term mod = TermProlog;
|
||||
|
||||
if (p->ModuleOfPred) mod = p->ModuleOfPred;
|
||||
Yap_DebugPlWrite (mod);
|
||||
Yap_DebugErrorPutc (':');
|
||||
if (arity == 0)
|
||||
Yap_DebugPlWrite (MkAtomTerm ((Atom)f));
|
||||
else
|
||||
Yap_DebugPlWrite (MkAtomTerm (NameOfFunctor (f)));
|
||||
Yap_DebugErrorPutc ('/');
|
||||
Yap_DebugPlWrite (MkIntTerm (arity));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ShowOp (compiler_vm_op ic, const char *f, struct PSEUDO *cpc)
|
||||
{
|
||||
CACHE_REGS
|
||||
char ch;
|
||||
Int arg = cpc->rnd1;
|
||||
Int rn = cpc->rnd2;
|
||||
CELL *cptr = cpc->arnds;
|
||||
|
||||
if (ic != label_op && ic != label_ctl_op && ic != name_op) {
|
||||
Yap_DebugErrorPutc ('\t');
|
||||
}
|
||||
while ((ch = *f++) != 0)
|
||||
{
|
||||
if (ch == '%')
|
||||
switch (ch = *f++)
|
||||
{
|
||||
#ifdef BEAM
|
||||
case '1':
|
||||
Yap_DebugPlWrite(MkIntTerm(rn));
|
||||
break;
|
||||
case '4':
|
||||
Yap_DebugPlWrite(MkIntTerm(arg));
|
||||
break;
|
||||
#endif
|
||||
case '2':
|
||||
{
|
||||
Ventry *v = (Ventry *) cpc->rnd3;
|
||||
Yap_DebugErrorPutc (v->KindOfVE == PermVar ? 'Y' : 'X');
|
||||
Yap_DebugPlWrite (MkIntTerm ((v->NoOfVE) & MaskVarAdrs));
|
||||
Yap_DebugErrorPutc (',');
|
||||
Yap_DebugErrorPutc ('A');
|
||||
Yap_DebugPlWrite (MkIntegerTerm (cpc->rnd4));
|
||||
Yap_DebugErrorPutc (',');
|
||||
send_pred( RepPredProp((Prop)(cpc->rnd5)) );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'n':
|
||||
Yap_DebugPlWrite ((Term) arg);
|
||||
break;
|
||||
case 'b':
|
||||
/* write a variable bitmap for a call */
|
||||
{
|
||||
int max = arg/(8*sizeof(CELL)), i;
|
||||
CELL *ptr = cptr;
|
||||
for (i = 0; i <= max; i++) {
|
||||
Yap_DebugPlWrite(MkIntegerTerm((Int)(*ptr++)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
write_address (arg);
|
||||
break;
|
||||
case 'L':
|
||||
write_special_label (arg, rn, cpc->rnd3);
|
||||
break;
|
||||
case 'B':
|
||||
{
|
||||
char s[32];
|
||||
|
||||
bip_name(rn,s);
|
||||
Yap_DebugPlWrite (MkAtomTerm(Yap_LookupAtom(s)));
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
Yap_DebugPlWrite (MkIntegerTerm (arg));
|
||||
break;
|
||||
case 'z':
|
||||
Yap_DebugPlWrite (MkIntTerm (cpc->rnd3));
|
||||
break;
|
||||
case 'v':
|
||||
{
|
||||
Ventry *v = (Ventry *) arg;
|
||||
if (v) {
|
||||
Yap_DebugErrorPutc (v->KindOfVE == PermVar ? 'Y' : 'X');
|
||||
Yap_DebugPlWrite (MkIntTerm ((v->NoOfVE) & MaskVarAdrs));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
{
|
||||
Ventry *v;
|
||||
|
||||
cpc = cpc->nextInst;
|
||||
arg = cpc->rnd1;
|
||||
v = (Ventry *) arg;
|
||||
Yap_DebugErrorPutc (v->KindOfVE == PermVar ? 'Y' : 'X');
|
||||
Yap_DebugPlWrite (MkIntTerm ((v->NoOfVE) & MaskVarAdrs));
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
Yap_DebugPlWrite (MkAtomTerm ((Atom) arg));
|
||||
Yap_DebugErrorPutc ('/');
|
||||
Yap_DebugPlWrite (MkIntTerm (rn));
|
||||
break;
|
||||
case 'p':
|
||||
send_pred( RepPredProp((Prop)(arg) ));
|
||||
break;
|
||||
case 'P':
|
||||
send_pred( RepPredProp((Prop)(rn) ));
|
||||
break;
|
||||
case 'f':
|
||||
write_functor((Functor)arg);
|
||||
break;
|
||||
case 'r':
|
||||
Yap_DebugErrorPutc ('A');
|
||||
Yap_DebugPlWrite (MkIntTerm (rn));
|
||||
break;
|
||||
case 'S':
|
||||
Yap_DebugErrorPutc ('S');
|
||||
Yap_DebugPlWrite (MkIntTerm (rn));
|
||||
break;
|
||||
case 'h':
|
||||
{
|
||||
CELL my_arg = *cptr++;
|
||||
write_address(my_arg);
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
write_address(arg);
|
||||
break;
|
||||
case 'i':
|
||||
write_address (arg);
|
||||
break;
|
||||
case 'j':
|
||||
{
|
||||
Functor fun = (Functor)*cptr++;
|
||||
if (IsExtensionFunctor(fun)) {
|
||||
if (fun == FunctorDBRef) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomDBREF));
|
||||
} else if (fun == FunctorLongInt) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomLONGINT));
|
||||
} else if (fun == FunctorDouble) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomDOUBLE));
|
||||
} else if (fun == FunctorString) {
|
||||
Yap_DebugPlWrite(MkAtomTerm(AtomSTRING));
|
||||
}
|
||||
} else {
|
||||
Yap_DebugPlWrite (MkAtomTerm(NameOfFunctor(fun)));
|
||||
Yap_DebugErrorPutc ('/');
|
||||
Yap_DebugPlWrite (MkIntTerm(ArityOfFunctor(fun)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
Yap_DebugPlWrite(AbsAppl(cptr));
|
||||
break;
|
||||
case 'x':
|
||||
Yap_DebugPlWrite (MkIntTerm (rn >> 1));
|
||||
Yap_DebugErrorPutc ('\t');
|
||||
Yap_DebugPlWrite (MkIntTerm (rn & 1));
|
||||
break;
|
||||
case 'w':
|
||||
Yap_DebugPlWrite (arg);
|
||||
break;
|
||||
case 'o':
|
||||
Yap_DebugPlWrite ((Term) * cptr++);
|
||||
case 'c':
|
||||
{
|
||||
int i;
|
||||
CELL *ptr = (CELL *)cptr[0];
|
||||
for (i = 0; i < arg; ++i) {
|
||||
CELL my_arg;
|
||||
Yap_DebugErrorPutc('\t');
|
||||
if (*ptr) {
|
||||
Yap_DebugPlWrite ((Term) *ptr++);
|
||||
} else {
|
||||
Yap_DebugPlWrite (MkIntTerm (0));
|
||||
ptr++;
|
||||
}
|
||||
Yap_DebugErrorPutc ('\t');
|
||||
my_arg = *ptr++;
|
||||
write_address (my_arg);
|
||||
if (i+1 < arg)
|
||||
Yap_DebugErrorPutc ('\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
{
|
||||
int i;
|
||||
CELL *ptr = (CELL *)cptr[0];
|
||||
for (i = 0; i < arg; ++i) {
|
||||
CELL my_arg = ptr[0], lbl = ptr[1];
|
||||
Yap_DebugErrorPutc('\t');
|
||||
if (my_arg) {
|
||||
write_functor((Functor)my_arg);
|
||||
} else {
|
||||
Yap_DebugPlWrite(MkIntTerm (0));
|
||||
}
|
||||
Yap_DebugErrorPutc('\t');
|
||||
write_address(lbl);
|
||||
ptr += 2;
|
||||
if (i+1 < arg)
|
||||
Yap_DebugErrorPutc('\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Yap_DebugErrorPutc ('%');
|
||||
Yap_DebugErrorPutc (ch);
|
||||
}
|
||||
else
|
||||
Yap_DebugErrorPutc (ch);
|
||||
}
|
||||
Yap_DebugErrorPutc ('\n');
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShowCode (struct intermediates *cint)
|
||||
{
|
||||
CACHE_REGS
|
||||
struct PSEUDO *cpc;
|
||||
|
||||
cpc = cint->CodeStart;
|
||||
/* MkIntTerm and friends may build terms in the global stack */
|
||||
HR = (CELL *)cint->freep;
|
||||
while (cpc) {
|
||||
compiler_vm_op ic = cpc->op;
|
||||
if (ic != nop_op) {
|
||||
ShowOp (ic, opDesc[ic], cpc);
|
||||
}
|
||||
cpc = cpc->nextInst;
|
||||
}
|
||||
Yap_DebugErrorPutc ('\n');
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
|
@ -0,0 +1,558 @@
|
|||
/************************************************************************\
|
||||
* Cut & Commit Instructions *
|
||||
\************************************************************************/
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
/* cut */
|
||||
Op(cut, s);
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackCut, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
do_cut:
|
||||
#endif
|
||||
SET_ASP(YREG, PREG->y_u.s.s);
|
||||
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, s),Osbpp),l);
|
||||
/* assume cut is always in stack */
|
||||
saveregs();
|
||||
prune((choiceptr)YREG[E_CB] PASS_REGS);
|
||||
setregs();
|
||||
GONext();
|
||||
|
||||
#ifdef COROUTINING
|
||||
NoStackCut:
|
||||
PROCESS_INT(interrupt_cut, do_cut);
|
||||
#endif
|
||||
|
||||
ENDOp();
|
||||
|
||||
/* cut_t */
|
||||
/* cut_t does the same as cut */
|
||||
Op(cut_t, s);
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackCutT, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
do_cut_t:
|
||||
#endif
|
||||
SET_ASP(YREG, PREG->y_u.s.s);
|
||||
/* assume cut is always in stack */
|
||||
saveregs();
|
||||
prune((choiceptr)YREG[E_CB] PASS_REGS);
|
||||
setregs();
|
||||
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, s),Osbpp),l);
|
||||
GONext();
|
||||
|
||||
#ifdef COROUTINING
|
||||
NoStackCutT:
|
||||
PROCESS_INT(interrupt_cut_t, do_cut_t);
|
||||
#endif
|
||||
|
||||
ENDOp();
|
||||
|
||||
/* cut_e */
|
||||
Op(cut_e, s);
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackCutE, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
do_cut_e:
|
||||
#endif
|
||||
SET_ASP(YREG, PREG->y_u.s.s);
|
||||
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, s),Osbpp),l);
|
||||
saveregs();
|
||||
prune((choiceptr)SREG[E_CB] PASS_REGS);
|
||||
setregs();
|
||||
GONext();
|
||||
|
||||
#ifdef COROUTINING
|
||||
NoStackCutE:
|
||||
PROCESS_INT(interrupt_cut_e, do_cut_e);
|
||||
#endif
|
||||
|
||||
ENDOp();
|
||||
|
||||
/* save_b_x Xi */
|
||||
Op(save_b_x, x);
|
||||
BEGD(d0);
|
||||
d0 = PREG->y_u.x.x;
|
||||
#if defined(YAPOR_SBA) && defined(FROZEN_STACKS)
|
||||
XREG(d0) = MkIntegerTerm((Int)B);
|
||||
#else
|
||||
XREG(d0) = MkIntegerTerm(LCL0-(CELL *) (B));
|
||||
#endif /* YAPOR_SBA && FROZEN_STACKS */
|
||||
PREG = NEXTOP(PREG, x);
|
||||
ENDD(d0);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
/* save_b_y Yi */
|
||||
Op(save_b_y, y);
|
||||
#if defined(YAPOR_SBA)
|
||||
INITIALIZE_PERMVAR(YREG+PREG->y_u.y.y,MkIntegerTerm((Int)B));
|
||||
#else
|
||||
INITIALIZE_PERMVAR(YREG+PREG->y_u.y.y,MkIntegerTerm(LCL0-(CELL *)(B)));
|
||||
#endif /* YAPOR_SBA*/
|
||||
PREG = NEXTOP(PREG, y);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
/* commit_b_x Xi */
|
||||
Op(commit_b_x, xps);
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackCommitX, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
do_commit_b_x:
|
||||
#endif
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xps.x);
|
||||
deref_head(d0, commit_b_x_unk);
|
||||
commit_b_x_nvar:
|
||||
/* skip a void call and a label */
|
||||
SET_ASP(YREG, PREG->y_u.xps.s);
|
||||
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, xps),Osbpp),l);
|
||||
{
|
||||
choiceptr pt0;
|
||||
#if defined(YAPOR_SBA) && defined(FROZEN_STACKS)
|
||||
pt0 = (choiceptr)IntegerOfTerm(d0);
|
||||
#else
|
||||
pt0 = (choiceptr)(LCL0-IntegerOfTerm(d0));
|
||||
#endif /* YAPOR_SBA && FROZEN_STACKS */
|
||||
saveregs();
|
||||
prune(pt0 PASS_REGS);
|
||||
setregs();
|
||||
}
|
||||
GONext();
|
||||
|
||||
BEGP(pt1);
|
||||
deref_body(d0, pt1, commit_b_x_unk, commit_b_x_nvar);
|
||||
ENDP(pt1);
|
||||
/* never cut to a variable */
|
||||
/* Abort */
|
||||
FAIL();
|
||||
ENDD(d0);
|
||||
|
||||
#ifdef COROUTINING
|
||||
/* Problem: have I got an environment or not? */
|
||||
NoStackCommitX:
|
||||
PROCESS_INT(interrupt_commit_x, do_commit_b_x);
|
||||
#endif
|
||||
ENDOp();
|
||||
|
||||
/* commit_b_y Yi */
|
||||
Op(commit_b_y, yps);
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackCommitY, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
do_commit_b_y:
|
||||
#endif
|
||||
BEGD(d0);
|
||||
d0 = YREG[PREG->y_u.yps.y];
|
||||
deref_head(d0, commit_b_y_unk);
|
||||
commit_b_y_nvar:
|
||||
SET_ASP(YREG, PREG->y_u.yps.s);
|
||||
PREG = NEXTOP(NEXTOP(NEXTOP(PREG, yps),Osbpp),l);
|
||||
{
|
||||
choiceptr pt0;
|
||||
#if defined(YAPOR_SBA) && defined(FROZEN_STACKS)
|
||||
pt0 = (choiceptr)IntegerOfTerm(d0);
|
||||
#else
|
||||
pt0 = (choiceptr)(LCL0-IntegerOfTerm(d0));
|
||||
#endif
|
||||
saveregs();
|
||||
prune(pt0 PASS_REGS);
|
||||
setregs();
|
||||
}
|
||||
GONext();
|
||||
|
||||
BEGP(pt1);
|
||||
deref_body(d0, pt1, commit_b_y_unk, commit_b_y_nvar);
|
||||
ENDP(pt1);
|
||||
/* never cut to a variable */
|
||||
/* Abort */
|
||||
FAIL();
|
||||
ENDD(d0);
|
||||
|
||||
#ifdef COROUTINING
|
||||
/* This is easier: I know there is an environment so I cannot do allocate */
|
||||
NoStackCommitY:
|
||||
PROCESS_INT(interrupt_commit_y, do_commit_b_y);
|
||||
#endif
|
||||
ENDOp();
|
||||
|
||||
/*************************************************************************
|
||||
* Call / Proceed instructions *
|
||||
*************************************************************************/
|
||||
|
||||
/* Macros for stack trimming */
|
||||
|
||||
/* execute Label */
|
||||
BOp(execute, pp);
|
||||
{
|
||||
PredEntry *pt0;
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
pt0 = PREG->y_u.pp.p;
|
||||
#ifndef NO_CHECKING
|
||||
check_stack(NoStackExecute, HR);
|
||||
goto skip_do_execute;
|
||||
#endif
|
||||
do_execute:
|
||||
FETCH_Y_FROM_ENV(YREG);
|
||||
pt0 = PREG->y_u.pp.p;
|
||||
skip_do_execute:
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
low_level_trace(enter_pred,pt0,XREGS+1);
|
||||
}
|
||||
#endif /* LOW_LEVEL_TRACE */
|
||||
CACHE_A1();
|
||||
ALWAYS_LOOKAHEAD(pt0->OpcodeOfPred);
|
||||
BEGD(d0);
|
||||
d0 = (CELL)B;
|
||||
PREG = pt0->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
ENV_YREG[E_CB] = d0;
|
||||
ENDD(d0);
|
||||
#ifdef DEPTH_LIMIT
|
||||
if (DEPTH <= MkIntTerm(1)) {/* I assume Module==0 is prolog */
|
||||
if (pt0->ModuleOfPred) {
|
||||
if (DEPTH == MkIntTerm(0)) {
|
||||
FAIL();
|
||||
} else { DEPTH = RESET_DEPTH(); }
|
||||
}
|
||||
} else if (pt0->ModuleOfPred)
|
||||
DEPTH -= MkIntConstant(2);
|
||||
#endif /* DEPTH_LIMIT */
|
||||
/* this is the equivalent to setting up the stack */
|
||||
ALWAYS_GONext();
|
||||
ALWAYS_END_PREFETCH();
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
}
|
||||
|
||||
NoStackExecute:
|
||||
PROCESS_INT(interrupt_execute, do_execute);
|
||||
|
||||
ENDBOp();
|
||||
|
||||
/* dexecute Label */
|
||||
/* joint deallocate and execute */
|
||||
BOp(dexecute, pp);
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace)
|
||||
low_level_trace(enter_pred,PREG->y_u.pp.p,XREGS+1);
|
||||
#endif /* LOW_LEVEL_TRACER */
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
{
|
||||
PredEntry *pt0;
|
||||
|
||||
CACHE_A1();
|
||||
pt0 = PREG->y_u.pp.p;
|
||||
#ifndef NO_CHECKING
|
||||
/* check stacks */
|
||||
check_stack(NoStackDExecute, HR);
|
||||
goto skip_dexecute;
|
||||
#endif
|
||||
continue_dexecute:
|
||||
FETCH_Y_FROM_ENV(YREG);
|
||||
pt0 = PREG->y_u.pp.p;
|
||||
skip_dexecute:
|
||||
#ifdef DEPTH_LIMIT
|
||||
if (DEPTH <= MkIntTerm(1)) {/* I assume Module==0 is primitives */
|
||||
if (pt0->ModuleOfPred) {
|
||||
if (DEPTH == MkIntTerm(0)) {
|
||||
FAIL();
|
||||
} else {
|
||||
DEPTH = RESET_DEPTH();
|
||||
}
|
||||
}
|
||||
} else if (pt0->ModuleOfPred)
|
||||
DEPTH -= MkIntConstant(2);
|
||||
#endif /* DEPTH_LIMIT */
|
||||
PREG = pt0->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
ALWAYS_LOOKAHEAD(pt0->OpcodeOfPred);
|
||||
/* do deallocate */
|
||||
CPREG = (yamop *) ENV_YREG[E_CP];
|
||||
ENV_YREG = ENV = (CELL *) ENV_YREG[E_E];
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (ENV_YREG > (CELL *) top_b || ENV_YREG < HR) ENV_YREG = (CELL *) top_b;
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) top_b) ENV_YREG = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
else ENV_YREG = (CELL *)((CELL)ENV_YREG + ENV_Size(CPREG));
|
||||
}
|
||||
#else
|
||||
if (ENV_YREG > (CELL *)B) {
|
||||
ENV_YREG = (CELL *)B;
|
||||
}
|
||||
else {
|
||||
ENV_YREG = (CELL *) ((CELL) ENV_YREG + ENV_Size(CPREG));
|
||||
}
|
||||
#endif /* FROZEN_STACKS */
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
/* setup GB */
|
||||
ENV_YREG[E_CB] = (CELL) B;
|
||||
ALWAYS_GONext();
|
||||
ALWAYS_END_PREFETCH();
|
||||
}
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
|
||||
NoStackDExecute:
|
||||
PROCESS_INT(interrupt_dexecute, continue_dexecute);
|
||||
|
||||
ENDBOp();
|
||||
|
||||
BOp(fcall, Osbpp);
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
ENV_YREG[E_CP] = (CELL) CPREG;
|
||||
ENV_YREG[E_E] = (CELL) ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
ENV_YREG[E_DEPTH] = DEPTH;
|
||||
#endif /* DEPTH_LIMIT */
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
ENDBOp();
|
||||
|
||||
BOp(call, Osbpp);
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
low_level_trace(enter_pred,PREG->y_u.Osbpp.p,XREGS+1);
|
||||
}
|
||||
#endif /* LOW_LEVEL_TRACER */
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
{
|
||||
PredEntry *pt;
|
||||
CACHE_A1();
|
||||
pt = PREG->y_u.Osbpp.p;
|
||||
#ifndef NO_CHECKING
|
||||
check_stack(NoStackCall, HR);
|
||||
goto skip_call;
|
||||
#endif
|
||||
call_body:
|
||||
/* external jump if we don;t want to creep */
|
||||
FETCH_Y_FROM_ENV(YREG);
|
||||
pt = PREG->y_u.Osbpp.p;
|
||||
skip_call:
|
||||
ENV = ENV_YREG;
|
||||
/* Try to preserve the environment */
|
||||
ENV_YREG = (CELL *) (((char *) ENV_YREG) + PREG->y_u.Osbpp.s);
|
||||
CPREG = NEXTOP(PREG, Osbpp);
|
||||
ALWAYS_LOOKAHEAD(pt->OpcodeOfPred);
|
||||
PREG = pt->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
#ifdef DEPTH_LIMIT
|
||||
if (DEPTH <= MkIntTerm(1)) {/* I assume Module==0 is primitives */
|
||||
if (pt->ModuleOfPred) {
|
||||
if (DEPTH == MkIntTerm(0)) {
|
||||
FAIL();
|
||||
} else {
|
||||
DEPTH = RESET_DEPTH();
|
||||
}
|
||||
}
|
||||
} else if (pt->ModuleOfPred)
|
||||
DEPTH -= MkIntConstant(2);
|
||||
#endif /* DEPTH_LIMIT */
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (ENV_YREG > (CELL *) top_b || ENV_YREG < HR) ENV_YREG = (CELL *) top_b;
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) top_b) ENV_YREG = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
}
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) B) {
|
||||
ENV_YREG = (CELL *) B;
|
||||
}
|
||||
#endif /* FROZEN_STACKS */
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
/* setup GB */
|
||||
ENV_YREG[E_CB] = (CELL) B;
|
||||
#ifdef YAPOR
|
||||
SCH_check_requests();
|
||||
#endif /* YAPOR */
|
||||
ALWAYS_GONext();
|
||||
ALWAYS_END_PREFETCH();
|
||||
}
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
ENDBOp();
|
||||
|
||||
BOp(procceed, p);
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
ALWAYS_LOOKAHEAD(CPREG->opc);
|
||||
PREG = CPREG;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
ENV_YREG = ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = ENV_YREG[E_DEPTH];
|
||||
#endif
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
ALWAYS_GONext();
|
||||
ALWAYS_END_PREFETCH();
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
|
||||
NoStackCall:
|
||||
PROCESS_INT(interrupt_call, call_body);
|
||||
|
||||
ENDBOp();
|
||||
|
||||
Op(allocate, e);
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
PREG = NEXTOP(PREG, e);
|
||||
ENV_YREG[E_CP] = (CELL) CPREG;
|
||||
ENV_YREG[E_E] = (CELL) ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
ENV_YREG[E_DEPTH] = DEPTH;
|
||||
#endif /* DEPTH_LIMIT */
|
||||
ENV = ENV_YREG;
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
Op(deallocate, p);
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_trail(TR);
|
||||
#ifndef NO_CHECKING
|
||||
/* check stacks */
|
||||
check_stack(NoStackDeallocate, HR);
|
||||
#endif
|
||||
PREG = NEXTOP(PREG, p);
|
||||
/* other instructions do depend on S being set by deallocate
|
||||
:-( */
|
||||
SREG = YREG;
|
||||
CPREG = (yamop *) ENV_YREG[E_CP];
|
||||
ENV = ENV_YREG = (CELL *) ENV_YREG[E_E];
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = ENV_YREG[E_DEPTH];
|
||||
#endif /* DEPTH_LIMIT */
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (ENV_YREG > (CELL *) top_b || ENV_YREG < HR) ENV_YREG = (CELL *) top_b;
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) top_b) ENV_YREG = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
else ENV_YREG = (CELL *)((CELL) ENV_YREG + ENV_Size(CPREG));
|
||||
}
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) B)
|
||||
ENV_YREG = (CELL *) B;
|
||||
else
|
||||
ENV_YREG = (CELL *) ((CELL) ENV_YREG + ENV_Size(CPREG));
|
||||
#endif /* FROZEN_STACKS */
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
GONext();
|
||||
|
||||
NoStackDeallocate:
|
||||
BEGD(d0);
|
||||
#ifdef SHADOW_S
|
||||
Yap_REGS.S_ = YREG;
|
||||
#endif
|
||||
PREG = NEXTOP(PREG,p);
|
||||
saveregs();
|
||||
d0 = interrupt_deallocate( PASS_REGS1 );
|
||||
setregs();
|
||||
PREG = PREVOP(PREG,p);
|
||||
#ifdef SHADOW_S
|
||||
SREG = Yap_REGS.S_;
|
||||
#endif
|
||||
// return to original deallocate
|
||||
if (!d0) FAIL();
|
||||
JMPNext();
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
/**********************************************
|
||||
* OPTYap instructions *
|
||||
**********************************************/
|
||||
|
||||
#ifdef YAPOR
|
||||
#include "or.insts.h"
|
||||
#endif /* YAPOR */
|
||||
#ifdef TABLING
|
||||
#include "tab.insts.h"
|
||||
#include "tab.tries.insts.h"
|
||||
#endif /* TABLING */
|
||||
|
||||
|
||||
|
||||
#ifdef BEAM
|
||||
extern int eam_am(PredEntry *);
|
||||
|
||||
Op(retry_eam, e);
|
||||
printf("Aqui estou eu..................\n");
|
||||
if (!eam_am(2)) {
|
||||
abort_eam("Falhei\n");
|
||||
FAIL();
|
||||
}
|
||||
|
||||
goto procceed;
|
||||
PREG = NEXTOP(PREG, e);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
Op(run_eam, os);
|
||||
if (inp==-9000) { /* use indexing to find out valid alternatives */
|
||||
extern CELL *beam_ALTERNATIVES;
|
||||
*beam_ALTERNATIVES= (CELL *) PREG->y_u.os.opcw;
|
||||
beam_ALTERNATIVES++;
|
||||
if (OLD_B!=B) goto fail;
|
||||
#if PUSH_REGS
|
||||
Yap_regp=old_regs;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
saveregs();
|
||||
if (!eam_am((PredEntry *) PREG->y_u.os.s)) FAIL();
|
||||
setregs();
|
||||
|
||||
/* cut */
|
||||
BACKUP_B();
|
||||
while (POP_CHOICE_POINT(B->cp_b)) {
|
||||
POP_EXECUTE();
|
||||
}
|
||||
B = B->cp_b; /* cut_fail */
|
||||
HB = B->cp_h; /* cut_fail */
|
||||
RECOVER_B();
|
||||
|
||||
if (0) { register choiceptr ccp;
|
||||
/* initialize ccp */
|
||||
#define NORM_CP(CP) ((choiceptr)(CP))
|
||||
|
||||
YREG = (CELL *) (NORM_CP(YREG) - 1);
|
||||
ccp = NORM_CP(YREG);
|
||||
store_yaam_reg_cpdepth(ccp);
|
||||
ccp->cp_tr = TR;
|
||||
ccp->cp_ap = BEAM_RETRY_CODE;
|
||||
ccp->cp_h = HR;
|
||||
ccp->cp_b = B;
|
||||
ccp->cp_env= ENV;
|
||||
ccp->cp_cp = CPREG;
|
||||
B = ccp;
|
||||
SET_BB(B);
|
||||
}
|
||||
goto procceed;
|
||||
PREG = NEXTOP(PREG, os);
|
||||
GONext();
|
||||
ENDOp();
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,572 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: corout.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: Co-routining from within YAP *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "heapgc.h"
|
||||
#include "attvar.h"
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
#ifdef COROUTINING
|
||||
|
||||
/* check if variable was there */
|
||||
static Term AddVarIfNotThere(Term var, Term dest USES_REGS) {
|
||||
Term test = dest;
|
||||
while (test != TermNil) {
|
||||
if ((RepPair(test))[0] == var)
|
||||
return (dest);
|
||||
else
|
||||
test = (RepPair(test))[1];
|
||||
}
|
||||
return (MkPairTerm(var, dest));
|
||||
}
|
||||
|
||||
/* This routine verifies whether two complex structures can unify. */
|
||||
static int can_unify_complex(register CELL *pt0, register CELL *pt0_end,
|
||||
register CELL *pt1, Term *Vars USES_REGS) {
|
||||
|
||||
/* This is really just unification, folks */
|
||||
tr_fr_ptr saved_TR;
|
||||
CELL *saved_HB;
|
||||
choiceptr saved_B;
|
||||
|
||||
register CELL **to_visit = (CELL **)Yap_PreAllocCodeSpace();
|
||||
CELL **to_visit_base = to_visit;
|
||||
|
||||
/* make sure to trail all bindings */
|
||||
saved_TR = TR;
|
||||
saved_B = B;
|
||||
saved_HB = HB;
|
||||
HB = HR;
|
||||
|
||||
loop:
|
||||
while (pt0 < pt0_end) {
|
||||
register CELL d0, d1;
|
||||
++pt0;
|
||||
++pt1;
|
||||
d0 = Derefa(pt0);
|
||||
d1 = Derefa(pt1);
|
||||
if (IsVarTerm(d0)) {
|
||||
if (IsVarTerm(d1)) {
|
||||
if (d0 != d1) {
|
||||
/* we need to suspend on both variables ! */
|
||||
*Vars = AddVarIfNotThere(d0, AddVarIfNotThere(d1, *Vars PASS_REGS)
|
||||
PASS_REGS);
|
||||
/* bind the two variables, we would have to do that to unify
|
||||
them */
|
||||
if (d1 > d0) { /* youngest */
|
||||
/* we don't want to wake up goals */
|
||||
Bind_Global_NonAtt((CELL *)d1, d0);
|
||||
} else {
|
||||
Bind_Global_NonAtt((CELL *)d0, d1);
|
||||
}
|
||||
}
|
||||
/* continue the loop */
|
||||
continue;
|
||||
} else {
|
||||
/* oh no, some more variables! */
|
||||
*Vars = AddVarIfNotThere(d0, *Vars PASS_REGS);
|
||||
}
|
||||
/* now bind it */
|
||||
Bind_Global_NonAtt((CELL *)d0, d1);
|
||||
/* continue the loop */
|
||||
} else if (IsVarTerm(d1)) {
|
||||
*Vars = AddVarIfNotThere(d1, *Vars PASS_REGS);
|
||||
/* and bind it */
|
||||
Bind_Global_NonAtt((CELL *)d1, d0);
|
||||
/* continue the loop */
|
||||
} else {
|
||||
if (d0 == d1)
|
||||
continue;
|
||||
if (IsAtomOrIntTerm(d0) || IsAtomOrIntTerm(d1)) {
|
||||
if (d0 != d1)
|
||||
goto comparison_failed;
|
||||
/* else continue the loop */
|
||||
} else if (IsPairTerm(d0)) {
|
||||
if (!IsPairTerm(d1))
|
||||
goto comparison_failed;
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit[3] = (CELL *)*pt0;
|
||||
to_visit += 4;
|
||||
*pt0 = d1;
|
||||
#else
|
||||
/* store the terms to visit */
|
||||
if (pt0 < pt0_end) {
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit += 3;
|
||||
}
|
||||
#endif
|
||||
pt0 = RepPair(d0) - 1;
|
||||
pt0_end = RepPair(d0) + 1;
|
||||
pt1 = RepPair(d1) - 1;
|
||||
continue;
|
||||
} else if (IsApplTerm(d0)) {
|
||||
register Functor f;
|
||||
register CELL *ap2, *ap3;
|
||||
if (!IsApplTerm(d1)) {
|
||||
goto comparison_failed;
|
||||
} else {
|
||||
/* store the terms to visit */
|
||||
ap2 = RepAppl(d0);
|
||||
ap3 = RepAppl(d1);
|
||||
f = (Functor)(*ap2);
|
||||
/* compare functors */
|
||||
if (f != (Functor)*ap3) {
|
||||
goto comparison_failed;
|
||||
}
|
||||
if (IsExtensionFunctor(f)) {
|
||||
switch ((CELL)f) {
|
||||
case (CELL) FunctorDBRef:
|
||||
if (d0 == d1)
|
||||
continue;
|
||||
goto comparison_failed;
|
||||
case (CELL) FunctorLongInt:
|
||||
if (ap2[1] == ap3[1])
|
||||
continue;
|
||||
goto comparison_failed;
|
||||
case (CELL) FunctorDouble:
|
||||
if (FloatOfTerm(d0) == FloatOfTerm(d1))
|
||||
continue;
|
||||
goto comparison_failed;
|
||||
case (CELL) FunctorString:
|
||||
if (strcmp((char *)StringOfTerm(d0), (char *)StringOfTerm(d1)) ==
|
||||
0)
|
||||
continue;
|
||||
goto comparison_failed;
|
||||
#ifdef USE_GMP
|
||||
case (CELL) FunctorBigInt:
|
||||
if (Yap_gmp_tcmp_big_big(d0, d1) == 0)
|
||||
continue;
|
||||
goto comparison_failed;
|
||||
#endif /* USE_GMP */
|
||||
default:
|
||||
goto comparison_failed;
|
||||
}
|
||||
}
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit[3] = (CELL *)*pt0;
|
||||
to_visit += 4;
|
||||
*pt0 = d1;
|
||||
#else
|
||||
/* store the terms to visit */
|
||||
if (pt0 < pt0_end) {
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = pt1;
|
||||
to_visit += 3;
|
||||
}
|
||||
#endif
|
||||
d0 = ArityOfFunctor(f);
|
||||
pt0 = ap2;
|
||||
pt0_end = ap2 + d0;
|
||||
pt1 = ap3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Do we still have compound terms to visit */
|
||||
if (to_visit > (CELL **)to_visit_base) {
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit -= 4;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
pt1 = to_visit[2];
|
||||
*pt0 = (CELL)to_visit[3];
|
||||
#else
|
||||
to_visit -= 3;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
pt1 = to_visit[2];
|
||||
#endif
|
||||
goto loop;
|
||||
}
|
||||
/* success */
|
||||
Yap_ReleasePreAllocCodeSpace((ADDR)to_visit);
|
||||
/* restore B, and later HB */
|
||||
B = saved_B;
|
||||
HB = saved_HB;
|
||||
/* untrail all bindings made by IUnify */
|
||||
while (TR != saved_TR) {
|
||||
pt1 = (CELL *)(TrailTerm(--TR));
|
||||
RESET_VARIABLE(pt1);
|
||||
}
|
||||
return (TRUE);
|
||||
|
||||
comparison_failed:
|
||||
/* failure */
|
||||
Yap_ReleasePreAllocCodeSpace((ADDR)to_visit);
|
||||
#ifdef RATIONAL_TREES
|
||||
while (to_visit > (CELL **)to_visit_base) {
|
||||
to_visit -= 4;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
pt1 = to_visit[2];
|
||||
*pt0 = (CELL)to_visit[3];
|
||||
}
|
||||
#endif
|
||||
/* restore B, and later HB */
|
||||
B = saved_B;
|
||||
HB = saved_HB;
|
||||
/* untrail all bindings made by IUnify */
|
||||
while (TR != saved_TR) {
|
||||
pt1 = (CELL *)(TrailTerm(--TR));
|
||||
RESET_VARIABLE(pt1);
|
||||
}
|
||||
/* the system will take care of TR for me, no need to worry here! */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static int can_unify(Term t1, Term t2, Term *Vars USES_REGS) {
|
||||
t1 = Deref(t1);
|
||||
t2 = Deref(t2);
|
||||
if (t1 == t2) {
|
||||
*Vars = TermNil;
|
||||
return TRUE;
|
||||
}
|
||||
if (IsVarTerm(t1)) {
|
||||
/* we know for sure they can't be different */
|
||||
if (IsVarTerm(t2)) {
|
||||
/* we need to suspend on both variables because otherwise
|
||||
Y = susp(_) would not wakeup susp ! */
|
||||
*Vars = MkPairTerm(t1, MkPairTerm(t2, TermNil));
|
||||
return TRUE;
|
||||
} else {
|
||||
*Vars = MkPairTerm(t1, TermNil);
|
||||
return TRUE;
|
||||
}
|
||||
} else if (IsVarTerm(t2)) {
|
||||
/* wait until t2 is bound */
|
||||
*Vars = MkPairTerm(t2, TermNil);
|
||||
return TRUE;
|
||||
}
|
||||
/* Two standard terms at last! */
|
||||
if (IsAtomOrIntTerm(t1) || IsAtomOrIntTerm(t2)) {
|
||||
/* Two primitive terms can only be equal if they are
|
||||
the same. If they are, $eq succeeds without further ado.
|
||||
*/
|
||||
if (t1 != t2)
|
||||
return FALSE;
|
||||
else {
|
||||
*Vars = TermNil;
|
||||
return TRUE;
|
||||
}
|
||||
} else if (IsPairTerm(t1)) {
|
||||
if (IsPairTerm(t2)) {
|
||||
return (can_unify_complex(RepPair(t1) - 1, RepPair(t1) + 1,
|
||||
RepPair(t2) - 1, Vars PASS_REGS));
|
||||
} else
|
||||
return FALSE;
|
||||
} else {
|
||||
Functor f = FunctorOfTerm(t1);
|
||||
if (f != FunctorOfTerm(t2))
|
||||
return FALSE;
|
||||
if (IsExtensionFunctor(f)) {
|
||||
switch ((CELL)f) {
|
||||
case (CELL) FunctorDBRef:
|
||||
if (t1 == t2)
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
case (CELL) FunctorLongInt:
|
||||
if (RepAppl(t1)[1] == RepAppl(t2)[1])
|
||||
return (TRUE);
|
||||
return FALSE;
|
||||
case (CELL) FunctorString:
|
||||
if (strcmp((char *)StringOfTerm(t1), (char *)StringOfTerm(t2)) == 0)
|
||||
return (TRUE);
|
||||
return FALSE;
|
||||
case (CELL) FunctorDouble:
|
||||
if (FloatOfTerm(t1) == FloatOfTerm(t2))
|
||||
return (TRUE);
|
||||
return FALSE;
|
||||
#ifdef USE_GMP
|
||||
case (CELL) FunctorBigInt:
|
||||
if (Yap_gmp_tcmp_big_big(t1, t2) == 0)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
#endif /* USE_GMP */
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/* Two complex terms with the same functor */
|
||||
return can_unify_complex(RepAppl(t1), RepAppl(t1) + ArityOfFunctor(f),
|
||||
RepAppl(t2), Vars PASS_REGS);
|
||||
}
|
||||
}
|
||||
|
||||
/* This routine verifies whether a complex has variables. */
|
||||
static int non_ground_complex(register CELL *pt0, register CELL *pt0_end,
|
||||
Term *Var USES_REGS) {
|
||||
|
||||
register CELL **to_visit = (CELL **)Yap_PreAllocCodeSpace();
|
||||
CELL **to_visit_base = to_visit;
|
||||
|
||||
loop:
|
||||
while (pt0 < pt0_end) {
|
||||
register CELL d0;
|
||||
++pt0;
|
||||
d0 = Derefa(pt0);
|
||||
if (IsVarTerm(d0)) {
|
||||
*Var = d0;
|
||||
goto var_found;
|
||||
}
|
||||
if (IsPairTerm(d0)) {
|
||||
if (to_visit + 1024 >= (CELL **)AuxSp) {
|
||||
goto aux_overflow;
|
||||
}
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = (CELL *)*pt0;
|
||||
to_visit += 3;
|
||||
*pt0 = TermNil;
|
||||
#else
|
||||
/* store the terms to visit */
|
||||
if (pt0 < pt0_end) {
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit += 2;
|
||||
}
|
||||
#endif
|
||||
pt0 = RepPair(d0) - 1;
|
||||
pt0_end = RepPair(d0) + 1;
|
||||
} else if (IsApplTerm(d0)) {
|
||||
register Functor f;
|
||||
register CELL *ap2;
|
||||
|
||||
/* store the terms to visit */
|
||||
ap2 = RepAppl(d0);
|
||||
f = (Functor)(*ap2);
|
||||
|
||||
if (IsExtensionFunctor(f)) {
|
||||
continue;
|
||||
}
|
||||
if (to_visit + 1024 >= (CELL **)AuxSp) {
|
||||
goto aux_overflow;
|
||||
}
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit[2] = (CELL *)*pt0;
|
||||
to_visit += 3;
|
||||
*pt0 = TermNil;
|
||||
#else
|
||||
/* store the terms to visit */
|
||||
if (pt0 < pt0_end) {
|
||||
to_visit[0] = pt0;
|
||||
to_visit[1] = pt0_end;
|
||||
to_visit += 2;
|
||||
}
|
||||
#endif
|
||||
d0 = ArityOfFunctor(f);
|
||||
pt0 = ap2;
|
||||
pt0_end = ap2 + d0;
|
||||
}
|
||||
/* just continue the loop */
|
||||
}
|
||||
|
||||
/* Do we still have compound terms to visit */
|
||||
if (to_visit > (CELL **)to_visit_base) {
|
||||
#ifdef RATIONAL_TREES
|
||||
to_visit -= 3;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
*pt0 = (CELL)to_visit[2];
|
||||
#else
|
||||
to_visit -= 2;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
#endif
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* the term is ground */
|
||||
Yap_ReleasePreAllocCodeSpace((ADDR)to_visit);
|
||||
return FALSE;
|
||||
|
||||
var_found:
|
||||
/* the term is non-ground */
|
||||
Yap_ReleasePreAllocCodeSpace((ADDR)to_visit);
|
||||
#ifdef RATIONAL_TREES
|
||||
while (to_visit > (CELL **)to_visit_base) {
|
||||
to_visit -= 3;
|
||||
pt0 = to_visit[0];
|
||||
pt0_end = to_visit[1];
|
||||
*pt0 = (CELL)to_visit[2];
|
||||
}
|
||||
#endif
|
||||
/* the system will take care of TR for me, no need to worry here! */
|
||||
return TRUE;
|
||||
|
||||
aux_overflow:
|
||||
/* unwind stack */
|
||||
Yap_ReleasePreAllocCodeSpace((ADDR)to_visit);
|
||||
#ifdef RATIONAL_TREES
|
||||
while (to_visit > (CELL **)to_visit_base) {
|
||||
to_visit -= 3;
|
||||
pt0 = to_visit[0];
|
||||
*pt0 = (CELL)to_visit[2];
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int non_ground(Term t, Term *Var USES_REGS) {
|
||||
int out = -1;
|
||||
while (out < 0) {
|
||||
t = Deref(t);
|
||||
if (IsVarTerm(t)) {
|
||||
/* we found a variable */
|
||||
*Var = t;
|
||||
return TRUE;
|
||||
}
|
||||
if (IsPrimitiveTerm(t)) {
|
||||
return FALSE;
|
||||
} else if (IsPairTerm(t)) {
|
||||
out = non_ground_complex(RepPair(t) - 1, RepPair(t) + 1, Var PASS_REGS);
|
||||
if (out >= 0)
|
||||
return out;
|
||||
} else {
|
||||
Functor f = FunctorOfTerm(t);
|
||||
if (IsExtensionFunctor(f)) {
|
||||
return FALSE;
|
||||
}
|
||||
out = non_ground_complex(RepAppl(t),
|
||||
RepAppl(t) + ArityOfFunctor(FunctorOfTerm(t)),
|
||||
Var PASS_REGS);
|
||||
if (out >= 0)
|
||||
return out;
|
||||
}
|
||||
if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
|
||||
Yap_Error(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, "overflow in ground");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* check whether the two terms unify and return what variables should
|
||||
be bound before the terms are exactly equal */
|
||||
static Int p_can_unify(USES_REGS1) {
|
||||
#ifdef COROUTINING
|
||||
Term r = TermNil;
|
||||
if (!can_unify(ARG1, ARG2, &r PASS_REGS))
|
||||
return FALSE;
|
||||
return Yap_unify(ARG3, r);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* if the term is not ground return a variable in the term */
|
||||
static Int p_non_ground(USES_REGS1) {
|
||||
#ifdef COROUTINING
|
||||
Term r = TermNil;
|
||||
if (!non_ground(ARG1, &r PASS_REGS))
|
||||
return (FALSE);
|
||||
return (Yap_unify(ARG2, r));
|
||||
#else
|
||||
return (FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* if the term is not ground return a variable in the term */
|
||||
static Int p_coroutining(USES_REGS1) {
|
||||
#ifdef COROUTINING
|
||||
return (TRUE);
|
||||
#else
|
||||
return (FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if COROUTINING
|
||||
static Term ListOfWokenGoals(USES_REGS1) {
|
||||
return Yap_ReadTimedVar(LOCAL_WokenGoals);
|
||||
}
|
||||
|
||||
Term Yap_ListOfWokenGoals(void) {
|
||||
CACHE_REGS
|
||||
return ListOfWokenGoals(PASS_REGS1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return a list of awoken goals */
|
||||
static Int p_awoken_goals(USES_REGS1) {
|
||||
#ifdef COROUTINING
|
||||
Term WGs = Yap_ReadTimedVar(LOCAL_WokenGoals);
|
||||
if (WGs == TermNil) {
|
||||
return (FALSE);
|
||||
}
|
||||
WGs = ListOfWokenGoals(PASS_REGS1);
|
||||
Yap_UpdateTimedVar(LOCAL_WokenGoals, TermNil);
|
||||
return (Yap_unify(ARG1, WGs));
|
||||
#else
|
||||
return (FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Int p_yap_has_rational_trees(USES_REGS1) {
|
||||
#if RATIONAL_TREES
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static Int p_yap_has_coroutining(USES_REGS1) {
|
||||
#if COROUTINING
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Yap_InitCoroutPreds(void) {
|
||||
#ifdef COROUTINING
|
||||
Atom at;
|
||||
PredEntry *pred;
|
||||
|
||||
at = AtomWakeUpGoal;
|
||||
pred = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, 2), 0));
|
||||
WakeUpCode = pred;
|
||||
#endif
|
||||
Yap_InitAttVarPreds();
|
||||
Yap_InitCPred("$yap_has_rational_trees", 0, p_yap_has_rational_trees,
|
||||
SafePredFlag);
|
||||
Yap_InitCPred("$yap_has_coroutining", 0, p_yap_has_coroutining, SafePredFlag);
|
||||
Yap_InitCPred("$can_unify", 3, p_can_unify, SafePredFlag);
|
||||
Yap_InitCPred("$non_ground", 2, p_non_ground, SafePredFlag);
|
||||
Yap_InitCPred("$coroutining", 0, p_coroutining, SafePredFlag);
|
||||
Yap_InitCPred("$awoken_goals", 1, p_awoken_goals, SafePredFlag);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
|||
#include "Yap.h"
|
||||
#include "cut_c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void cut_c_initialize(int wid){
|
||||
CACHE_REGS
|
||||
Yap_REGS.CUT_C_TOP=(cut_c_str_ptr)REMOTE_LocalBase(wid);
|
||||
}
|
||||
|
||||
/*Removes a choice_point from the stack*/
|
||||
void cut_c_pop(void){
|
||||
CACHE_REGS
|
||||
cut_c_str_ptr to_delete = NULL;
|
||||
if (((CELL *)Yap_REGS.CUT_C_TOP) == ((CELL *)LOCAL_LocalBase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{ /* removes the top element
|
||||
from the stack */
|
||||
to_delete = Yap_REGS.CUT_C_TOP;
|
||||
Yap_REGS.CUT_C_TOP = to_delete->before;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*Insert a choice_point in the stack*/
|
||||
void cut_c_push(cut_c_str_ptr new_top){
|
||||
CACHE_REGS
|
||||
new_top->before = Yap_REGS.CUT_C_TOP;
|
||||
Yap_REGS.CUT_C_TOP=new_top;
|
||||
return;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,94 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: it_deep.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: Support for Iterative Deepening *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif /* SCCS */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "eval.h"
|
||||
|
||||
#ifdef DEPTH_LIMIT
|
||||
|
||||
#include "Yatom.h"
|
||||
|
||||
static Int p_get_depth_limit( USES_REGS1 );
|
||||
static Int p_set_depth_limit( USES_REGS1 );
|
||||
|
||||
static Int p_get_depth_limit( USES_REGS1 )
|
||||
{
|
||||
Int d = IntOfTerm(DEPTH);
|
||||
if (d % 2 == 1)
|
||||
return(Yap_unify(ARG1, MkFloatTerm(INFINITY)));
|
||||
return(Yap_unify_constant(ARG1, MkIntTerm(d/2)));
|
||||
}
|
||||
|
||||
static Int p_set_depth_limit( USES_REGS1 )
|
||||
{
|
||||
Term d = Deref(ARG1);
|
||||
|
||||
if (IsVarTerm(d)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, d, "set-depth_limit");
|
||||
return(FALSE);
|
||||
} else if (!IsIntegerTerm(d)) {
|
||||
if (IsFloatTerm(d) && isinf(FloatOfTerm(d))) {
|
||||
d = RESET_DEPTH();
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, d, "set-depth_limit");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
d = MkIntTerm(IntegerOfTerm(d)*2);
|
||||
|
||||
YENV[E_DEPTH] = d;
|
||||
DEPTH = d;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static Int p_set_depth_limit_for_next_call( USES_REGS1 )
|
||||
{
|
||||
Term d = Deref(ARG1);
|
||||
|
||||
if (IsVarTerm(d)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, d, "set-depth_limit");
|
||||
return(FALSE);
|
||||
} else if (!IsIntegerTerm(d)) {
|
||||
if (IsFloatTerm(d) && isinf(FloatOfTerm(d))) {
|
||||
DEPTH = RESET_DEPTH();
|
||||
return TRUE;
|
||||
}
|
||||
Yap_Error(TYPE_ERROR_INTEGER, d, "set-depth_limit");
|
||||
return(FALSE);
|
||||
}
|
||||
d = MkIntTerm(IntegerOfTerm(d)*2);
|
||||
|
||||
DEPTH = d;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
void Yap_InitItDeepenPreds(void)
|
||||
{
|
||||
Yap_InitCPred("get_depth_limit", 1, p_get_depth_limit, SafePredFlag);
|
||||
Yap_InitCPred("$set_depth_limit", 1, p_set_depth_limit, 0);
|
||||
Yap_InitCPred("$set_depth_limit_for_next_call", 1, p_set_depth_limit_for_next_call, 0);
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,720 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* Yap Prolog *
|
||||
* *
|
||||
* Yap Prolog Was Developed At Nccup - Universidade Do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa And Universidade Do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: errors.c *
|
||||
* Last Rev: *
|
||||
* Mods: *
|
||||
* Comments: Yap'S error handlers *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "absmi.h"
|
||||
#include "yapio.h"
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include "Foreign.h"
|
||||
|
||||
#if DEBUG
|
||||
void Yap_PrintPredName(PredEntry *ap) {
|
||||
CACHE_REGS
|
||||
Term tmod = ap->ModuleOfPred;
|
||||
if (!tmod)
|
||||
tmod = TermProlog;
|
||||
#if THREADS
|
||||
Yap_DebugPlWrite(MkIntegerTerm(worker_id));
|
||||
Yap_DebugPutc(stderr, ' ');
|
||||
#endif
|
||||
Yap_DebugPutc(stderr, '>');
|
||||
Yap_DebugPutc(stderr, '\t');
|
||||
Yap_DebugPlWrite(tmod);
|
||||
Yap_DebugPutc(stderr, ':');
|
||||
if (ap->ModuleOfPred == IDB_MODULE) {
|
||||
Term t = Deref(ARG1);
|
||||
if (IsAtomTerm(t)) {
|
||||
Yap_DebugPlWrite(t);
|
||||
} else if (IsIntegerTerm(t)) {
|
||||
Yap_DebugPlWrite(t);
|
||||
} else {
|
||||
Functor f = FunctorOfTerm(t);
|
||||
Atom At = NameOfFunctor(f);
|
||||
Yap_DebugPlWrite(MkAtomTerm(At));
|
||||
Yap_DebugPutc(stderr, '/');
|
||||
Yap_DebugPlWrite(MkIntegerTerm(ArityOfFunctor(f)));
|
||||
}
|
||||
} else {
|
||||
if (ap->ArityOfPE == 0) {
|
||||
Atom At = (Atom)ap->FunctorOfPred;
|
||||
Yap_DebugPlWrite(MkAtomTerm(At));
|
||||
} else {
|
||||
Functor f = ap->FunctorOfPred;
|
||||
Atom At = NameOfFunctor(f);
|
||||
Yap_DebugPlWrite(MkAtomTerm(At));
|
||||
Yap_DebugPutc(stderr, '/');
|
||||
Yap_DebugPlWrite(MkIntegerTerm(ArityOfFunctor(f)));
|
||||
}
|
||||
}
|
||||
char s[1024];
|
||||
if (ap->PredFlags & StandardPredFlag)
|
||||
fprintf(stderr, "S");
|
||||
if (ap->PredFlags & CPredFlag)
|
||||
fprintf(stderr, "C");
|
||||
if (ap->PredFlags & UserCPredFlag)
|
||||
fprintf(stderr, "U");
|
||||
if (ap->PredFlags & SyncPredFlag)
|
||||
fprintf(stderr, "Y");
|
||||
if (ap->PredFlags & LogUpdatePredFlag)
|
||||
fprintf(stderr, "Y");
|
||||
if (ap->PredFlags & HiddenPredFlag)
|
||||
fprintf(stderr, "H");
|
||||
sprintf(s, " %llx\n", ap->PredFlags);
|
||||
Yap_DebugPuts(stderr, s);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Yap_Warning(const char *s, ...) {
|
||||
CACHE_REGS
|
||||
va_list ap;
|
||||
PredEntry *pred;
|
||||
bool rc;
|
||||
Term ts[2];
|
||||
const char *format;
|
||||
char tmpbuf[MAXPATHLEN];
|
||||
|
||||
if (LOCAL_within_print_message) {
|
||||
/* error within error */
|
||||
fprintf(stderr, "%% WARNING WITHIN WARNING\n");
|
||||
Yap_RestartYap(1);
|
||||
}
|
||||
LOCAL_DoingUndefp = true;
|
||||
LOCAL_within_print_message = true;
|
||||
pred = RepPredProp(PredPropByFunc(FunctorPrintMessage,
|
||||
PROLOG_MODULE)); // PROCEDURE_print_message2
|
||||
va_start(ap, s);
|
||||
format = va_arg(ap, char *);
|
||||
if (format != NULL) {
|
||||
#if HAVE_VSNPRINTF
|
||||
vsnprintf(tmpbuf, MAXPATHLEN - 1, format, ap);
|
||||
#else
|
||||
(void)vsprintf(tmpbuf, format, ap);
|
||||
#endif
|
||||
} else
|
||||
return false;
|
||||
va_end(ap);
|
||||
if (pred->OpcodeOfPred == UNDEF_OPCODE||
|
||||
pred->OpcodeOfPred == FAIL_OPCODE) {
|
||||
fprintf(stderr, "warning message: %s\n", tmpbuf);
|
||||
LOCAL_DoingUndefp = false;
|
||||
LOCAL_within_print_message = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
ts[1] = MkAtomTerm(AtomWarning);
|
||||
ts[0] = MkAtomTerm(Yap_LookupAtom(tmpbuf));
|
||||
rc = Yap_execute_pred(pred, ts, true PASS_REGS);
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool Yap_PrintWarning(Term twarning) {
|
||||
CACHE_REGS
|
||||
PredEntry *pred = RepPredProp(PredPropByFunc(
|
||||
FunctorPrintMessage, PROLOG_MODULE)); // PROCEDURE_print_message2;
|
||||
Term cmod = ( CurrentModule == PROLOG_MODULE ? TermProlog : CurrentModule );
|
||||
bool rc;
|
||||
Term ts[2];
|
||||
|
||||
if (LOCAL_within_print_message) {
|
||||
/* error within error */
|
||||
fprintf(stderr, "%% WARNING WITHIN WARNING\n");
|
||||
Yap_RestartYap(1);
|
||||
}
|
||||
LOCAL_DoingUndefp = true;
|
||||
LOCAL_within_print_message = true;
|
||||
if (pred->OpcodeOfPred == UNDEF_OPCODE ||
|
||||
pred->OpcodeOfPred == FAIL_OPCODE
|
||||
) {
|
||||
fprintf(stderr, "warning message:\n");
|
||||
Yap_DebugPlWrite(twarning);
|
||||
fprintf(stderr, "\n");
|
||||
LOCAL_DoingUndefp = false;
|
||||
LOCAL_within_print_message = false;
|
||||
CurrentModule = cmod;
|
||||
return false;
|
||||
}
|
||||
ts[1] = twarning;
|
||||
ts[0] = MkAtomTerm(AtomWarning);
|
||||
HB = B->cp_h = HR;
|
||||
B->cp_tr = TR;
|
||||
rc = Yap_execute_pred(pred, ts, true PASS_REGS);
|
||||
LOCAL_within_print_message = false;
|
||||
LOCAL_DoingUndefp = false;
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool Yap_HandleError__(const char *file, const char *function, int lineno, const char *s, ...) {
|
||||
CACHE_REGS
|
||||
yap_error_number err = LOCAL_Error_TYPE;
|
||||
const char *serr;
|
||||
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (LOCAL_ErrorMessage) {
|
||||
serr = LOCAL_ErrorMessage;
|
||||
} else {
|
||||
serr = s;
|
||||
}
|
||||
switch (err) {
|
||||
case RESOURCE_ERROR_STACK:
|
||||
if (!Yap_gc(2, ENV, gc_P(P, CP))) {
|
||||
Yap_Error__(file, function, lineno, RESOURCE_ERROR_STACK, ARG1, serr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case RESOURCE_ERROR_AUXILIARY_STACK:
|
||||
if (LOCAL_MAX_SIZE < (char *)AuxSp - AuxBase) {
|
||||
LOCAL_MAX_SIZE += 1024;
|
||||
}
|
||||
if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
|
||||
/* crash in flames */
|
||||
Yap_Error__(file, function, lineno, RESOURCE_ERROR_AUXILIARY_STACK, ARG1, serr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case RESOURCE_ERROR_HEAP:
|
||||
if (!Yap_growheap(FALSE, 0, NULL)) {
|
||||
Yap_Error__(file, function, lineno, RESOURCE_ERROR_HEAP, ARG2, serr);
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
Yap_Error__(file, function, lineno, err, LOCAL_Error_Term, serr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int Yap_SWIHandleError(const char *s, ...) {
|
||||
CACHE_REGS
|
||||
yap_error_number err = LOCAL_Error_TYPE;
|
||||
char *serr;
|
||||
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (LOCAL_ErrorMessage) {
|
||||
serr = LOCAL_ErrorMessage;
|
||||
} else {
|
||||
serr = (char *)s;
|
||||
}
|
||||
switch (err) {
|
||||
case RESOURCE_ERROR_STACK:
|
||||
if (!Yap_gc(2, ENV, gc_P(P, CP))) {
|
||||
Yap_Error(RESOURCE_ERROR_STACK, TermNil, serr);
|
||||
return (FALSE);
|
||||
}
|
||||
return TRUE;
|
||||
case RESOURCE_ERROR_AUXILIARY_STACK:
|
||||
if (LOCAL_MAX_SIZE < (char *)AuxSp - AuxBase) {
|
||||
LOCAL_MAX_SIZE += 1024;
|
||||
}
|
||||
if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
|
||||
/* crash in flames */
|
||||
Yap_Error(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, serr);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
case RESOURCE_ERROR_HEAP:
|
||||
if (!Yap_growheap(FALSE, 0, NULL)) {
|
||||
Yap_Error(RESOURCE_ERROR_HEAP, ARG2, serr);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
Yap_Error(err, LOCAL_Error_Term, serr);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Yap_RestartYap(int flag) {
|
||||
CACHE_REGS
|
||||
#if PUSH_REGS
|
||||
restore_absmi_regs(&Yap_standard_regs);
|
||||
#endif
|
||||
siglongjmp(LOCAL_RestartEnv, 1);
|
||||
}
|
||||
|
||||
static void error_exit_yap(int value) {
|
||||
CACHE_REGS
|
||||
if (!(LOCAL_PrologMode & BootMode)) {
|
||||
|
||||
#if DEBUG
|
||||
#endif
|
||||
}
|
||||
fprintf(stderr, "\n Exiting ....\n");
|
||||
Yap_exit(value);
|
||||
}
|
||||
|
||||
/* This needs to be a static because I can't trust the stack (WIN32), and
|
||||
I can't trust the Yap stacks (error) */
|
||||
#define YAP_BUF_SIZE 512
|
||||
|
||||
static char tmpbuf[YAP_BUF_SIZE];
|
||||
|
||||
// error classes: based on OSI errors.
|
||||
//
|
||||
// - The extra argument says whether there different instances
|
||||
//
|
||||
// - Events are treated within the same pipeline as errors.
|
||||
//
|
||||
|
||||
#undef BEGIN_ERROR_CLASSES
|
||||
#undef ECLASS
|
||||
#undef END_ERROR_CLASSES
|
||||
#undef BEGIN_ERRORS
|
||||
#undef E0
|
||||
#undef E
|
||||
#undef E2
|
||||
#undef END_ERRORS
|
||||
|
||||
#define BEGIN_ERROR_CLASSES() \
|
||||
static Term mkerrorct(yap_error_class_number c, Term *ts) { \
|
||||
switch (c) {
|
||||
|
||||
#define ECLASS(CL, A, B) \
|
||||
case CL: \
|
||||
if (A == 0) \
|
||||
return MkAtomTerm(Yap_LookupAtom(A)); \
|
||||
else { \
|
||||
return Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom(A), B), B, ts); \
|
||||
}
|
||||
|
||||
#define END_ERROR_CLASSES() \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BEGIN_ERRORS() \
|
||||
static Term mkerrort(yap_error_number e, Term *ts) { \
|
||||
switch (e) {
|
||||
|
||||
#define E0(A, B) \
|
||||
case A: \
|
||||
return mkerrorct(B, ts);
|
||||
|
||||
#define E(A, B, C) \
|
||||
case A: \
|
||||
ts -= 1; \
|
||||
ts[0] = MkAtomTerm(Yap_LookupAtom(C)); \
|
||||
return mkerrorct(B, ts);
|
||||
|
||||
#define E2(A, B, C, D) \
|
||||
case A: \
|
||||
ts -= 2; \
|
||||
ts[0] = MkAtomTerm(Yap_LookupAtom(C)); \
|
||||
ts[1] = MkAtomTerm(Yap_LookupAtom(D)); \
|
||||
return mkerrorct(B, ts);
|
||||
|
||||
#define END_ERRORS() \
|
||||
} \
|
||||
}
|
||||
|
||||
#include "YapErrors.h"
|
||||
|
||||
/**
|
||||
* @brief Yap_Error
|
||||
* This function handles errors in the C code. Check errors.yap for the
|
||||
*corresponding Prolog code.
|
||||
*
|
||||
* @param file C source
|
||||
* @param function C function
|
||||
* @param lineno C exact line
|
||||
* @param type the error ID (in YAP this is a single integer)
|
||||
* @param where the culprit
|
||||
* @return usually FAILCODE
|
||||
*
|
||||
* In a good day, the error handler's job is to generate a throw. This includes:
|
||||
* - constructing an ISO style error term;
|
||||
* - constructing a list with all available info on the bug
|
||||
* - generating the throw
|
||||
* - forcing backtracking in order to restart.
|
||||
*
|
||||
* In a bad day, it has to deal with OOM, abort, and errors within errorts.
|
||||
*
|
||||
* The list includes the following options:
|
||||
* + c=c(file, line, function): where the bug was detected;
|
||||
*
|
||||
* + e=p(mod, name, arity, cl, file, lin): where the code was entered;
|
||||
*
|
||||
* + p=p(mod, name, arity, cl, file, line): the prolog procedure that caused
|
||||
*the bug,
|
||||
*and optionally,
|
||||
*
|
||||
* + g=g(Goal): the goal that created this mess
|
||||
*
|
||||
* + i=i(Comment): an user-written comment on this bug.
|
||||
*/
|
||||
yamop *Yap_Error__(const char *file, const char *function, int lineno,
|
||||
yap_error_number type, Term where, ...) {
|
||||
CACHE_REGS
|
||||
va_list ap;
|
||||
CELL nt[3];
|
||||
Functor fun;
|
||||
bool serious;
|
||||
Term tf, error_t, comment, culprit = TermNil;
|
||||
char *format;
|
||||
char s[MAXPATHLEN];
|
||||
|
||||
/* disallow recursive error handling */
|
||||
if (LOCAL_PrologMode & InErrorMode) {
|
||||
fprintf(stderr, "%% ERROR WITHIN ERROR %d: %s\n", LOCAL_CurrentError,
|
||||
tmpbuf);
|
||||
Yap_RestartYap(1);
|
||||
}
|
||||
LOCAL_PrologMode |= InErrorMode;
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
Yap_ClearExs();
|
||||
if (where == 0L) {
|
||||
where = TermNil;
|
||||
}
|
||||
// first, obtain current location
|
||||
sprintf(LOCAL_FileNameBuf, "%s:%d in C-function %s ", file, lineno, function);
|
||||
tf = MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf));
|
||||
#if DEBUG_STRICT
|
||||
if (Yap_heap_regs && !(LOCAL_PrologMode & BootMode))
|
||||
fprintf(stderr, "***** Processing Error %d (%lx,%x) %s***\n", type,
|
||||
(unsigned long int)LOCAL_Signals, LOCAL_PrologMode, format);
|
||||
else
|
||||
fprintf(stderr, "***** Processing Error %d (%x) %s***\n", type,
|
||||
LOCAL_PrologMode, format);
|
||||
#endif
|
||||
if (type == INTERRUPT_EVENT) {
|
||||
fprintf(stderr, "%% YAP exiting: cannot handle signal %d\n",
|
||||
(int)IntOfTerm(where));
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
Yap_exit(1);
|
||||
}
|
||||
if (LOCAL_within_print_message) {
|
||||
/* error within error */
|
||||
fprintf(stderr, "%% ERROR WITHIN WARNING %d: %s\n", LOCAL_CurrentError,
|
||||
tmpbuf);
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
Yap_exit(1);
|
||||
}
|
||||
va_start(ap, where);
|
||||
format = va_arg(ap, char *);
|
||||
if (format != NULL) {
|
||||
#if HAVE_VSNPRINTF
|
||||
(void)vsnprintf(s, MAXPATHLEN - 1, format, ap);
|
||||
#else
|
||||
(void)vsprintf(s, format, ap);
|
||||
#endif
|
||||
// fprintf(stderr, "warning: ");
|
||||
comment = MkAtomTerm(Yap_LookupAtom(s));
|
||||
} else if (LOCAL_ErrorSay && LOCAL_ErrorSay[0]) {
|
||||
comment = MkAtomTerm(Yap_LookupAtom(LOCAL_ErrorSay));
|
||||
} else {
|
||||
comment = TermNil;
|
||||
}
|
||||
va_end(ap);
|
||||
if (P == (yamop *)(FAILCODE)) {
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
return P;
|
||||
}
|
||||
/* PURE_ABORT may not have set where correctly, BootMode may not have the data
|
||||
* terms ready */
|
||||
if (type == ABORT_EVENT || LOCAL_PrologMode & BootMode) {
|
||||
where = TermNil;
|
||||
LOCAL_PrologMode &= ~AbortMode;
|
||||
LOCAL_CurrentError = type;
|
||||
LOCAL_PrologMode |= InErrorMode;
|
||||
/* make sure failure will be seen at next port */
|
||||
// no need to lock & unlock
|
||||
if (LOCAL_PrologMode & AsyncIntMode)
|
||||
Yap_signal(YAP_FAIL_SIGNAL);
|
||||
P = FAILCODE;
|
||||
} else {
|
||||
if (IsVarTerm(where)) {
|
||||
/* we must be careful someone gave us a copy to a local variable */
|
||||
Term t = MkVarTerm();
|
||||
Yap_unify(t, where);
|
||||
where = Deref(where);
|
||||
}
|
||||
/* Exit Abort Mode, if we were there */
|
||||
LOCAL_PrologMode &= ~AbortMode;
|
||||
LOCAL_CurrentError = type;
|
||||
LOCAL_PrologMode |= InErrorMode;
|
||||
if (!(where = Yap_CopyTerm(where))) {
|
||||
where = TermNil;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOCAL_PrologMode & BootMode) {
|
||||
/* crash in flames! */
|
||||
fprintf(stderr, "%s:%d:0 YAP Fatal Error %d in function %s:\n %s exiting....\n", file, lineno, type, function, s);
|
||||
error_exit_yap(1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
// DumpActiveGoals( USES_REGS1 );
|
||||
#endif /* DEBUG */
|
||||
if (!IsVarTerm(where) &&
|
||||
IsApplTerm(where) &&
|
||||
FunctorOfTerm(where) == FunctorError) {
|
||||
error_t = where;
|
||||
Yap_JumpToEnv(error_t);
|
||||
P = (yamop *)FAILCODE;
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
return P;
|
||||
}
|
||||
switch (type) {
|
||||
case SYSTEM_ERROR_INTERNAL: {
|
||||
fprintf(stderr, "%% Internal YAP Error: %s exiting....\n", tmpbuf);
|
||||
serious = TRUE;
|
||||
if (LOCAL_PrologMode & BootMode) {
|
||||
fprintf(stderr, "%% YAP crashed while booting %s\n", tmpbuf);
|
||||
} else {
|
||||
Yap_detect_bug_location(P, FIND_PRED_FROM_ANYWHERE, YAP_BUF_SIZE);
|
||||
fprintf(stderr, "%% Bug found while executing %s\n", tmpbuf);
|
||||
}
|
||||
error_exit_yap(1);
|
||||
}
|
||||
case SYSTEM_ERROR_FATAL: {
|
||||
fprintf(stderr, "%% Fatal YAP Error: %s exiting....\n", tmpbuf);
|
||||
error_exit_yap(1);
|
||||
}
|
||||
case INTERRUPT_EVENT: {
|
||||
error_exit_yap(1);
|
||||
}
|
||||
case ABORT_EVENT:
|
||||
nt[0] = MkAtomTerm(AtomDAbort);
|
||||
fun = FunctorDollarVar;
|
||||
serious = TRUE;
|
||||
break;
|
||||
case CALL_COUNTER_UNDERFLOW_EVENT:
|
||||
/* Do a long jump */
|
||||
LOCAL_ReductionsCounterOn = FALSE;
|
||||
LOCAL_PredEntriesCounterOn = FALSE;
|
||||
LOCAL_RetriesCounterOn = FALSE;
|
||||
Yap_JumpToEnv(MkAtomTerm(AtomCallCounter));
|
||||
P = (yamop *)FAILCODE;
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
return (P);
|
||||
case PRED_ENTRY_COUNTER_UNDERFLOW_EVENT:
|
||||
/* Do a long jump */
|
||||
LOCAL_ReductionsCounterOn = FALSE;
|
||||
LOCAL_PredEntriesCounterOn = FALSE;
|
||||
LOCAL_RetriesCounterOn = FALSE;
|
||||
Yap_JumpToEnv(MkAtomTerm(AtomCallAndRetryCounter));
|
||||
P = (yamop *)FAILCODE;
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
return (P);
|
||||
case RETRY_COUNTER_UNDERFLOW_EVENT:
|
||||
/* Do a long jump */
|
||||
LOCAL_ReductionsCounterOn = FALSE;
|
||||
LOCAL_PredEntriesCounterOn = FALSE;
|
||||
LOCAL_RetriesCounterOn = FALSE;
|
||||
Yap_JumpToEnv(MkAtomTerm(AtomRetryCounter));
|
||||
P = (yamop *)FAILCODE;
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
return (P);
|
||||
default: {
|
||||
Term ts[3];
|
||||
ts[2] = where;
|
||||
nt[0] = mkerrort(type, ts + 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
if (type != ABORT_EVENT) {
|
||||
Term location;
|
||||
|
||||
/* This is used by some complex procedures to detect there was an error */
|
||||
if (IsAtomTerm(nt[0])) {
|
||||
strncpy(LOCAL_ErrorSay, (char *) RepAtom(AtomOfTerm(nt[0]))->StrOfAE,
|
||||
MAX_ERROR_MSG_SIZE);
|
||||
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
||||
} else {
|
||||
strncpy(LOCAL_ErrorSay,
|
||||
(char *) RepAtom(NameOfFunctor(FunctorOfTerm(nt[0])))->StrOfAE,
|
||||
MAX_ERROR_MSG_SIZE);
|
||||
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
||||
}
|
||||
nt[1] = TermNil;
|
||||
switch (type) {
|
||||
case RESOURCE_ERROR_HEAP:
|
||||
case RESOURCE_ERROR_STACK:
|
||||
case RESOURCE_ERROR_TRAIL:
|
||||
comment = MkAtomTerm(Yap_LookupAtom(tmpbuf));
|
||||
default:
|
||||
if (comment != TermNil)
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("i")), comment),
|
||||
nt[1]);
|
||||
if (file && function) {
|
||||
Term ts[3], t3;
|
||||
ts[0] = MkAtomTerm(Yap_LookupAtom(file));
|
||||
ts[1] = MkIntegerTerm(lineno);
|
||||
ts[2] = MkAtomTerm(Yap_LookupAtom(function));
|
||||
t3 = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("c"), 3), 3, ts);
|
||||
nt[1] =
|
||||
MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("c")), t3), nt[1]);
|
||||
}
|
||||
if ((location = Yap_pc_location(P, B, ENV)) != TermNil) {
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("p")), location),
|
||||
nt[1]);
|
||||
}
|
||||
if ((location = Yap_env_location(CP, B, ENV, 0)) != TermNil) {
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("e")), location),
|
||||
nt[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* disable active signals at this point */
|
||||
LOCAL_Signals = 0;
|
||||
CalculateStackGap(PASS_REGS1);
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
/* we might be in the middle of a critical region */
|
||||
if (LOCAL_InterruptsDisabled) {
|
||||
LOCAL_InterruptsDisabled = 0;
|
||||
LOCAL_UncaughtThrow = TRUE;
|
||||
Yap_RestartYap(1);
|
||||
}
|
||||
#if DEBUG
|
||||
// DumpActiveGoals( PASS_REGS1 );
|
||||
#endif
|
||||
/* wait if we we are in user code,
|
||||
it's up to her to decide */
|
||||
fun = FunctorError;
|
||||
if (LOCAL_PrologMode & UserCCallMode) {
|
||||
error_t = Yap_MkApplTerm(fun, 2, nt);
|
||||
if (!(EX = Yap_StoreTermInDB(error_t, 2))) {
|
||||
/* fat chance */
|
||||
Yap_RestartYap(1);
|
||||
}
|
||||
} else {
|
||||
if (type == ABORT_EVENT) {
|
||||
error_t = MkAtomTerm(AtomDAbort);
|
||||
} else {
|
||||
error_t = Yap_MkApplTerm(fun, 2, nt);
|
||||
}
|
||||
Yap_JumpToEnv(error_t);
|
||||
P = (yamop *)FAILCODE;
|
||||
}
|
||||
|
||||
LOCAL_PrologMode &= ~InErrorMode;
|
||||
return P;
|
||||
}
|
||||
|
||||
static Int
|
||||
is_boolean( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
//Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t, NULL);
|
||||
return false;
|
||||
}
|
||||
return t == TermTrue || t == TermFalse;
|
||||
}
|
||||
|
||||
static Int
|
||||
is_atom( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
//Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t, NULL);
|
||||
return false;
|
||||
}
|
||||
return IsAtomTerm( t );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Int
|
||||
is_callable( USES_REGS1 )
|
||||
{
|
||||
Term G = Deref(ARG1);
|
||||
//Term Context = Deref(ARG2);
|
||||
while (true) {
|
||||
if (IsVarTerm(G)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, G, NULL);
|
||||
return false;
|
||||
}
|
||||
if (IsApplTerm(G)) {
|
||||
Functor f = FunctorOfTerm(G);
|
||||
if (IsExtensionFunctor(f)) {
|
||||
Yap_Error(TYPE_ERROR_CALLABLE, G, NULL);
|
||||
}
|
||||
if (f == FunctorModule) {
|
||||
Term tm = ArgOfTerm( 1, G);
|
||||
if (IsVarTerm(tm)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, G, NULL);
|
||||
return false;
|
||||
}
|
||||
if (!IsAtomTerm(tm)) {
|
||||
Yap_Error(TYPE_ERROR_CALLABLE, G, NULL);
|
||||
return false;
|
||||
}
|
||||
G = ArgOfTerm( 2, G );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if (IsPairTerm(G) || IsAtomTerm(G)) {
|
||||
return true;
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_CALLABLE, G, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Int
|
||||
is_predicate_indicator( USES_REGS1 )
|
||||
{
|
||||
Term G = Deref(ARG1);
|
||||
//Term Context = Deref(ARG2);
|
||||
Term mod = CurrentModule;
|
||||
|
||||
G = Yap_YapStripModule(G, &mod);
|
||||
if (IsVarTerm(G)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, G, NULL);
|
||||
return false;
|
||||
}
|
||||
if (!IsVarTerm(mod) && !IsAtomTerm(mod)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM, G, NULL);
|
||||
return false;
|
||||
}
|
||||
if (IsApplTerm(G)) {
|
||||
Functor f = FunctorOfTerm(G);
|
||||
if (IsExtensionFunctor(f)) {
|
||||
Yap_Error(TYPE_ERROR_PREDICATE_INDICATOR, G, NULL);
|
||||
}
|
||||
if (f == FunctorSlash || f == FunctorDoubleSlash) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Yap_Error(TYPE_ERROR_PREDICATE_INDICATOR, G, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Yap_InitErrorPreds( void )
|
||||
{
|
||||
CACHE_REGS
|
||||
Term cm = CurrentModule;
|
||||
CurrentModule = ERROR_MODULE;
|
||||
Yap_InitCPred("is_boolean", 2, is_boolean, TestPredFlag);
|
||||
Yap_InitCPred("is_callable", 2, is_callable, TestPredFlag);
|
||||
Yap_InitCPred("is_atom", 2, is_atom, TestPredFlag);
|
||||
Yap_InitCPred("is_predicate_indicator", 2, is_predicate_indicator, TestPredFlag);
|
||||
CurrentModule = cm;
|
||||
}
|
|
@ -0,0 +1,611 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: eval.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: arithmetical expression evaluation *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
//! @file eval.c
|
||||
|
||||
//! @{
|
||||
|
||||
/**
|
||||
@defgroup arithmetic_preds Arithmetic Predicates
|
||||
@ingroup arithmetic
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "eval.h"
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_FENV_H
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
|
||||
static Term Eval(Term t1 USES_REGS);
|
||||
|
||||
static Term
|
||||
get_matrix_element(Term t1, Term t2 USES_REGS)
|
||||
{
|
||||
if (!IsPairTerm(t2)) {
|
||||
if (t2 == MkAtomTerm(AtomLength)) {
|
||||
Int sz = 1;
|
||||
while (IsApplTerm(t1)) {
|
||||
Functor f = FunctorOfTerm(t1);
|
||||
if (NameOfFunctor(f) != AtomNil) {
|
||||
return MkIntegerTerm(sz);
|
||||
}
|
||||
sz *= ArityOfFunctor(f);
|
||||
t1 = ArgOfTerm(1, t1);
|
||||
}
|
||||
return MkIntegerTerm(sz);
|
||||
}
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, t2, "X is Y^[A]");
|
||||
return FALSE;
|
||||
}
|
||||
while (IsPairTerm(t2)) {
|
||||
Int indx;
|
||||
Term indxt = Eval(HeadOfTerm(t2) PASS_REGS);
|
||||
if (!IsIntegerTerm(indxt)) {
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, t2, "X is Y^[A]");
|
||||
return FALSE;
|
||||
}
|
||||
indx = IntegerOfTerm(indxt);
|
||||
if (!IsApplTerm(t1)) {
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, t1, "X is Y^[A]");
|
||||
return FALSE;
|
||||
} else {
|
||||
Functor f = FunctorOfTerm(t1);
|
||||
if (ArityOfFunctor(f) < indx) {
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, t1, "X is Y^[A]");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
t1 = ArgOfTerm(indx, t1);
|
||||
t2 = TailOfTerm(t2);
|
||||
}
|
||||
if (t2 != TermNil) {
|
||||
Yap_ArithError(TYPE_ERROR_EVALUABLE, t2, "X is Y^[A]");
|
||||
return FALSE;
|
||||
}
|
||||
return Eval(t1 PASS_REGS);
|
||||
}
|
||||
|
||||
static Term
|
||||
Eval(Term t USES_REGS)
|
||||
{
|
||||
|
||||
if (IsVarTerm(t)) {
|
||||
return Yap_ArithError(INSTANTIATION_ERROR,t,"in arithmetic");
|
||||
} else if (IsNumTerm(t)) {
|
||||
return t;
|
||||
} else if (IsAtomTerm(t)) {
|
||||
ExpEntry *p;
|
||||
Atom name = AtomOfTerm(t);
|
||||
|
||||
if (EndOfPAEntr(p = RepExpProp(Yap_GetExpProp(name, 0)))) {
|
||||
return Yap_ArithError(TYPE_ERROR_EVALUABLE, takeIndicator(t),
|
||||
"atom %s in arithmetic expression",
|
||||
RepAtom(name)->StrOfAE);
|
||||
}
|
||||
return Yap_eval_atom(p->FOfEE);
|
||||
} else if (IsApplTerm(t)) {
|
||||
Functor fun = FunctorOfTerm(t);
|
||||
if (fun == FunctorString) {
|
||||
const char *s = (const char*)StringOfTerm(t);
|
||||
if (s[1] == '\0')
|
||||
return MkIntegerTerm(s[0]);
|
||||
return Yap_ArithError(TYPE_ERROR_EVALUABLE, t,
|
||||
"string in arithmetic expression");
|
||||
} else if ((Atom)fun == AtomFoundVar) {
|
||||
return Yap_ArithError(TYPE_ERROR_EVALUABLE, TermNil,
|
||||
"cyclic term in arithmetic expression");
|
||||
} else {
|
||||
Int n = ArityOfFunctor(fun);
|
||||
Atom name = NameOfFunctor(fun);
|
||||
ExpEntry *p;
|
||||
Term t1, t2;
|
||||
|
||||
if (EndOfPAEntr(p = RepExpProp(Yap_GetExpProp(name, n)))) {
|
||||
return Yap_ArithError(TYPE_ERROR_EVALUABLE, takeIndicator(t),
|
||||
"functor %s/%d for arithmetic expression",
|
||||
RepAtom(name)->StrOfAE,n);
|
||||
}
|
||||
if (p->FOfEE == op_power && p->ArityOfEE == 2) {
|
||||
t2 = ArgOfTerm(2, t);
|
||||
if (IsPairTerm(t2)) {
|
||||
return get_matrix_element(ArgOfTerm(1, t), t2 PASS_REGS);
|
||||
}
|
||||
}
|
||||
*RepAppl(t) = (CELL)AtomFoundVar;
|
||||
t1 = Eval(ArgOfTerm(1,t) PASS_REGS);
|
||||
if (t1 == 0L) {
|
||||
*RepAppl(t) = (CELL)fun;
|
||||
return FALSE;
|
||||
}
|
||||
if (n == 1) {
|
||||
*RepAppl(t) = (CELL)fun;
|
||||
return Yap_eval_unary(p->FOfEE, t1);
|
||||
}
|
||||
t2 = Eval(ArgOfTerm(2,t) PASS_REGS);
|
||||
*RepAppl(t) = (CELL)fun;
|
||||
if (t2 == 0L)
|
||||
return FALSE;
|
||||
return Yap_eval_binary(p->FOfEE,t1,t2);
|
||||
}
|
||||
} /* else if (IsPairTerm(t)) */ {
|
||||
if (TailOfTerm(t) != TermNil) {
|
||||
return Yap_ArithError(TYPE_ERROR_EVALUABLE, t,
|
||||
"string must contain a single character to be evaluated as an arithmetic expression");
|
||||
}
|
||||
return Eval(HeadOfTerm(t) PASS_REGS);
|
||||
}
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_InnerEval__(Term t USES_REGS)
|
||||
{
|
||||
return Eval(t PASS_REGS);
|
||||
}
|
||||
|
||||
#ifdef BEAM
|
||||
Int BEAM_is(void);
|
||||
|
||||
Int
|
||||
BEAM_is(void)
|
||||
{ /* X is Y */
|
||||
union arith_ret res;
|
||||
blob_type bt;
|
||||
|
||||
bt = Eval(Deref(XREGS[2]), &res);
|
||||
if (bt==db_ref_e) return (NULL);
|
||||
return (EvalToTerm(bt,&res));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@pred is( X:number, + Y:ground) is det
|
||||
|
||||
This predicate succeeds iff the result of evaluating the expression
|
||||
_Y_ unifies with _X_. This is the predicate normally used to
|
||||
perform evaluation of arithmetic expressions:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
X is 2+3*4
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
succeeds with `X = 14`.
|
||||
|
||||
Consult @ref arithmetic_operators for the complete list of arithmetic_operators
|
||||
|
||||
*/
|
||||
|
||||
/// @memberof is/2
|
||||
static Int
|
||||
p_is( USES_REGS1 )
|
||||
{ /* X is Y */
|
||||
Term out;
|
||||
yap_error_number err;
|
||||
|
||||
Term t = Deref(ARG2);
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_EvalError(INSTANTIATION_ERROR,t, "X is Y");
|
||||
return(FALSE);
|
||||
}
|
||||
Yap_ClearExs();
|
||||
do {
|
||||
out = Yap_InnerEval(Deref(ARG2));
|
||||
if ((err = Yap_FoundArithError()) == YAP_NO_ERROR)
|
||||
break;
|
||||
if (err == RESOURCE_ERROR_STACK) {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_gcl(LOCAL_Error_Size, 2, ENV, CP)) {
|
||||
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
Yap_EvalError(err, takeIndicator( ARG2 ), "X is Exp");
|
||||
return FALSE;
|
||||
}
|
||||
} while (TRUE);
|
||||
return Yap_unify_constant(ARG1,out);
|
||||
}
|
||||
|
||||
/**
|
||||
@pred isnan(? X:float) is det
|
||||
|
||||
Interface to the IEE754 `isnan` test.
|
||||
*/
|
||||
|
||||
/// @memberof isnan/1
|
||||
static Int
|
||||
p_isnan( USES_REGS1 )
|
||||
{ /* X isnan Y */
|
||||
Term out = 0L;
|
||||
|
||||
while (!(out = Eval(Deref(ARG1) PASS_REGS))) {
|
||||
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_gcl(LOCAL_Error_Size, 1, ENV, CP)) {
|
||||
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (IsVarTerm(out)) {
|
||||
Yap_EvalError(INSTANTIATION_ERROR, out, "isnan/1");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsFloatTerm(out)) {
|
||||
Yap_EvalError(TYPE_ERROR_FLOAT, out, "isnan/1");
|
||||
return FALSE;
|
||||
}
|
||||
return isnan(FloatOfTerm(out));
|
||||
}
|
||||
|
||||
/**
|
||||
@pred isinf(? X:float) is det</b>
|
||||
|
||||
Interface to the IEE754 `isinf` test.
|
||||
*/
|
||||
|
||||
/// @memberof isnan/1
|
||||
static Int
|
||||
p_isinf( USES_REGS1 )
|
||||
{ /* X is Y */
|
||||
Term out = 0L;
|
||||
|
||||
while (!(out = Eval(Deref(ARG1) PASS_REGS))) {
|
||||
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_gcl(LOCAL_Error_Size, 1, ENV, CP)) {
|
||||
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (IsVarTerm(out)) {
|
||||
Yap_EvalError(INSTANTIATION_ERROR, out, "isinf/1");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsFloatTerm(out)) {
|
||||
Yap_EvalError(TYPE_ERROR_FLOAT, out, "isinf/1");
|
||||
return FALSE;
|
||||
}
|
||||
return isinf(FloatOfTerm(out));
|
||||
}
|
||||
|
||||
/**
|
||||
@pred logsum(+ Log1:float, + Log2:float, - Out:float ) is det
|
||||
|
||||
True if _Log1_ is the logarithm of the positive number _A1_,
|
||||
_Log2_ is the logarithm of the positive number _A2_, and
|
||||
_Out_ is the logarithm of the sum of the numbers _A1_ and
|
||||
_A2_. Useful in probability computation.
|
||||
*/
|
||||
|
||||
/// @memberof logsum/3
|
||||
static Int
|
||||
p_logsum( USES_REGS1 )
|
||||
{ /* X is Y */
|
||||
Term t1 = Deref(ARG1);
|
||||
Term t2 = Deref(ARG2);
|
||||
int done = FALSE;
|
||||
Float f1, f2;
|
||||
|
||||
while (!done) {
|
||||
if (IsFloatTerm(t1)) {
|
||||
f1 = FloatOfTerm(t1);
|
||||
done = TRUE;
|
||||
} else if (IsIntegerTerm(t1)) {
|
||||
f1 = IntegerOfTerm(t1);
|
||||
done = TRUE;
|
||||
#if USE_GMP
|
||||
} else if (IsBigIntTerm(t1)) {
|
||||
f1 = Yap_gmp_to_float(t1);
|
||||
done = TRUE;
|
||||
#endif
|
||||
} else {
|
||||
while (!(t1 = Eval(t1 PASS_REGS))) {
|
||||
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_gcl(LOCAL_Error_Size, 1, ENV, CP)) {
|
||||
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done = FALSE;
|
||||
while (!done) {
|
||||
if (IsFloatTerm(t2)) {
|
||||
f2 = FloatOfTerm(t2);
|
||||
done = TRUE;
|
||||
} else if (IsIntegerTerm(t2)) {
|
||||
f2 = IntegerOfTerm(t2);
|
||||
done = TRUE;
|
||||
#if USE_GMP
|
||||
} else if (IsBigIntTerm(t2)) {
|
||||
f2 = Yap_gmp_to_float(t2);
|
||||
done = TRUE;
|
||||
#endif
|
||||
} else {
|
||||
while (!(t2 = Eval(t2 PASS_REGS))) {
|
||||
if (LOCAL_Error_TYPE == RESOURCE_ERROR_STACK) {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_gcl(LOCAL_Error_Size, 2, ENV, CP)) {
|
||||
Yap_EvalError(RESOURCE_ERROR_STACK, ARG2, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
Yap_EvalError(LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f1 >= f2) {
|
||||
Float fi = exp(f2-f1);
|
||||
return Yap_unify(ARG3,MkFloatTerm(f1+log(1+fi)));
|
||||
} else {
|
||||
Float fi = exp(f1-f2);
|
||||
return Yap_unify(ARG3,MkFloatTerm(f2+log(1+fi)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Int
|
||||
Yap_ArithError__(const char *file, const char *function, int lineno, yap_error_number type, Term where,...)
|
||||
{
|
||||
CACHE_REGS
|
||||
va_list ap;
|
||||
char *format;
|
||||
|
||||
if (LOCAL_ArithError)
|
||||
return 0L;
|
||||
LOCAL_ArithError = TRUE;
|
||||
LOCAL_Error_TYPE = type;
|
||||
LOCAL_Error_File = file;
|
||||
LOCAL_Error_Function = function;
|
||||
LOCAL_Error_Lineno = lineno;
|
||||
LOCAL_Error_Term = where;
|
||||
if (!LOCAL_ErrorMessage)
|
||||
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
||||
va_start (ap, where);
|
||||
format = va_arg( ap, char *);
|
||||
if (format != NULL) {
|
||||
#if HAVE_VSNPRINTF
|
||||
(void) vsnprintf(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, format, ap);
|
||||
#else
|
||||
(void) vsprintf(LOCAL_ErrorMessage, format, ap);
|
||||
#endif
|
||||
} else {
|
||||
LOCAL_ErrorMessage[0] = '\0';
|
||||
}
|
||||
va_end (ap);
|
||||
return 0L;
|
||||
}
|
||||
|
||||
yamop *
|
||||
Yap_EvalError__(const char *file, const char *function, int lineno,yap_error_number type, Term where,...)
|
||||
{
|
||||
CACHE_REGS
|
||||
va_list ap;
|
||||
char *format;
|
||||
|
||||
if (LOCAL_ArithError) {
|
||||
LOCAL_ArithError = YAP_NO_ERROR;
|
||||
return Yap_Error__(file, function, lineno, LOCAL_Error_TYPE, LOCAL_Error_Term, LOCAL_ErrorMessage);
|
||||
}
|
||||
|
||||
if (!LOCAL_ErrorMessage)
|
||||
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
||||
va_start (ap, where);
|
||||
format = va_arg(ap, char *);
|
||||
if (format != NULL) {
|
||||
#if HAVE_VSNPRINTF
|
||||
(void) vsnprintf(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, format, ap);
|
||||
#else
|
||||
(void) vsprintf(LOCAL_ErrorMessage, format, ap);
|
||||
#endif
|
||||
} else {
|
||||
LOCAL_ErrorMessage[0] = '\0';
|
||||
}
|
||||
va_end (ap);
|
||||
return Yap_Error__(file, function, lineno, type, where, LOCAL_ErrorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@pred between(+ Low:int, + High:int, ? Value:int) is nondet
|
||||
|
||||
_Low_ and _High_ are integers, _High_ \>= _Low_. If
|
||||
_Value_ is an integer, _Low_ =\< _Value_
|
||||
=\< _High_. When _Value_ is a variable it is successively
|
||||
bound to all integers between _Low_ and _High_. If
|
||||
_High_ is inf or infinite between/3 is true iff
|
||||
_Value_ \>= _Low_, a feature that is particularly interesting
|
||||
for generating integers from a certain value.
|
||||
|
||||
*/
|
||||
|
||||
/// @memberof between/3
|
||||
static Int cont_between( USES_REGS1 )
|
||||
{
|
||||
Term t1 = EXTRA_CBACK_ARG(3,1);
|
||||
Term t2 = EXTRA_CBACK_ARG(3,2);
|
||||
|
||||
Yap_unify(ARG3, t1);
|
||||
if (IsIntegerTerm(t1)) {
|
||||
Int i1;
|
||||
Term tn;
|
||||
|
||||
if (t1 == t2)
|
||||
cut_succeed();
|
||||
i1 = IntegerOfTerm(t1);
|
||||
tn = add_int(i1, 1 PASS_REGS);
|
||||
EXTRA_CBACK_ARG(3,1) = tn;
|
||||
HB = B->cp_h = HR;
|
||||
return TRUE;
|
||||
} else {
|
||||
Term t[2];
|
||||
Term tn;
|
||||
Int cmp;
|
||||
|
||||
cmp = Yap_acmp(t1, t2 PASS_REGS);
|
||||
if (cmp == 0)
|
||||
cut_succeed();
|
||||
t[0] = t1;
|
||||
t[1] = MkIntTerm(1);
|
||||
tn = Eval(Yap_MkApplTerm(FunctorPlus, 2, t) PASS_REGS);
|
||||
EXTRA_CBACK_ARG(3,1) = tn;
|
||||
HB = B->cp_h = HR;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/// @memberof between/3
|
||||
static Int
|
||||
init_between( USES_REGS1 )
|
||||
{
|
||||
Term t1 = Deref(ARG1);
|
||||
Term t2 = Deref(ARG2);
|
||||
|
||||
if (IsVarTerm(t1)) {
|
||||
Yap_EvalError(INSTANTIATION_ERROR, t1, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (IsVarTerm(t2)) {
|
||||
Yap_EvalError(INSTANTIATION_ERROR, t1, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsIntegerTerm(t1) &&
|
||||
!IsBigIntTerm(t1)) {
|
||||
Yap_EvalError(TYPE_ERROR_INTEGER, t1, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsIntegerTerm(t2) &&
|
||||
!IsBigIntTerm(t2) &&
|
||||
t2 != MkAtomTerm(AtomInf) &&
|
||||
t2 != MkAtomTerm(AtomInfinity)) {
|
||||
Yap_EvalError(TYPE_ERROR_INTEGER, t2, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (IsIntegerTerm(t1) && IsIntegerTerm(t2)) {
|
||||
Int i1 = IntegerOfTerm(t1);
|
||||
Int i2 = IntegerOfTerm(t2);
|
||||
Term t3;
|
||||
|
||||
t3 = Deref(ARG3);
|
||||
if (!IsVarTerm(t3)) {
|
||||
if (!IsIntegerTerm(t3)) {
|
||||
if (!IsBigIntTerm(t3)) {
|
||||
Yap_EvalError(TYPE_ERROR_INTEGER, t3, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
cut_fail();
|
||||
} else {
|
||||
Int i3 = IntegerOfTerm(t3);
|
||||
if (i3 >= i1 && i3 <= i2)
|
||||
cut_succeed();
|
||||
cut_fail();
|
||||
}
|
||||
}
|
||||
if (i1 > i2) cut_fail();
|
||||
if (i1 == i2) {
|
||||
Yap_unify(ARG3, t1);
|
||||
cut_succeed();
|
||||
}
|
||||
} else if (IsIntegerTerm(t1) && IsAtomTerm(t2)) {
|
||||
Int i1 = IntegerOfTerm(t1);
|
||||
Term t3;
|
||||
|
||||
t3 = Deref(ARG3);
|
||||
if (!IsVarTerm(t3)) {
|
||||
if (!IsIntegerTerm(t3)) {
|
||||
if (!IsBigIntTerm(t3)) {
|
||||
Yap_EvalError(TYPE_ERROR_INTEGER, t3, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
cut_fail();
|
||||
} else {
|
||||
Int i3 = IntegerOfTerm(t3);
|
||||
if (i3 >= i1)
|
||||
cut_succeed();
|
||||
cut_fail();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Term t3 = Deref(ARG3);
|
||||
Int cmp;
|
||||
|
||||
if (!IsVarTerm(t3)) {
|
||||
if (!IsIntegerTerm(t3) && !IsBigIntTerm(t3)) {
|
||||
Yap_EvalError(TYPE_ERROR_INTEGER, t3, "between/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (Yap_acmp(t3, t1 PASS_REGS) >= 0 && Yap_acmp(t2,t3 PASS_REGS) >= 0 && P != FAILCODE)
|
||||
cut_succeed();
|
||||
cut_fail();
|
||||
}
|
||||
cmp = Yap_acmp(t1, t2 PASS_REGS);
|
||||
if (cmp > 0) cut_fail();
|
||||
if (cmp == 0) {
|
||||
Yap_unify(ARG3, t1);
|
||||
cut_succeed();
|
||||
}
|
||||
}
|
||||
EXTRA_CBACK_ARG(3,1) = t1;
|
||||
EXTRA_CBACK_ARG(3,2) = t2;
|
||||
return cont_between( PASS_REGS1 );
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitEval(void)
|
||||
{
|
||||
/* here are the arithmetical predicates */
|
||||
Yap_InitConstExps();
|
||||
Yap_InitUnaryExps();
|
||||
Yap_InitBinaryExps();
|
||||
Yap_InitCPred("is", 2, p_is, 0L);
|
||||
Yap_InitCPred("isnan", 1, p_isnan, TestPredFlag);
|
||||
Yap_InitCPred("isinf", 1, p_isinf, TestPredFlag);
|
||||
Yap_InitCPred("logsum", 3, p_logsum, TestPredFlag);
|
||||
Yap_InitCPredBack("between", 3, 2, init_between, cont_between, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @}
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,787 @@
|
|||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: exo.c *
|
||||
* comments: Exo compilation *
|
||||
* *
|
||||
* Last rev: $Date: 2008-07-22 23:34:44 $,$Author: vsc $ * *
|
||||
* $Log: not supported by cvs2svn $ *
|
||||
* *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "clause.h"
|
||||
#include "yapio.h"
|
||||
#include "eval.h"
|
||||
#include "tracer.h"
|
||||
#ifdef YAPOR
|
||||
#include "or.macros.h"
|
||||
#endif /* YAPOR */
|
||||
#ifdef TABLING
|
||||
#include "tab.macros.h"
|
||||
#endif /* TABLING */
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
bool YAP_NewExo( PredEntry *ap, size_t data, struct udi_info *udi);
|
||||
bool YAP_AssertTuples( PredEntry *pe, const Term *ts, size_t offset, size_t m);
|
||||
|
||||
//static int exo_write=FALSE;
|
||||
|
||||
//void do_write(void) { exo_write=TRUE;}
|
||||
|
||||
#define MAX_ARITY 256
|
||||
|
||||
#if SIZEOF_INT_P==4
|
||||
#define FNV32_PRIME (16777619UL)
|
||||
#define FNV32_OFFSET (0x811c9dc5UL)
|
||||
#define FNV_PRIME FNV32_PRIME
|
||||
#define FNV_OFFSET FNV32_OFFSET
|
||||
#elif SIZEOF_INT_P==8
|
||||
#define FNV64_PRIME (1099511628211)
|
||||
#if SIZEOF_LONG_INT==4
|
||||
#define FNV64_OFFSET (14695981039346656037ULL)
|
||||
#else
|
||||
#define FNV64_OFFSET (14695981039346656037UL)
|
||||
#endif
|
||||
#define FNV_PRIME FNV64_PRIME
|
||||
#define FNV_OFFSET FNV64_OFFSET
|
||||
#endif
|
||||
|
||||
/*MurmurHash3 from: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
|
||||
BITS32 rotl32 ( BITS32, int8_t);
|
||||
|
||||
inline BITS32 rotl32 ( BITS32 x, int8_t r )
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
#define ROTL32(x,y) rotl32(x,y)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finalization mix - force all bits of a hash block to avalanche
|
||||
|
||||
BITS32 fmix32 ( BITS32 );
|
||||
inline BITS32 fmix32 ( BITS32 h )
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_MURMUR3_32 (UInt arity, CELL *cl, UInt bnds[], UInt sz);
|
||||
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_MURMUR3_32 (UInt arity, CELL *cl, UInt bnds[], UInt sz)
|
||||
{
|
||||
UInt hash;
|
||||
UInt j=0;
|
||||
int len = 0;
|
||||
const BITS32 c1 = 0xcc9e2d51;
|
||||
const BITS32 c2 = 0x1b873593;
|
||||
|
||||
hash = FNV_OFFSET; /*did not find what seed to use yet*/
|
||||
|
||||
while (j < arity) {
|
||||
if (bnds[j]) {
|
||||
unsigned char *i=(unsigned char*)(cl+j);
|
||||
unsigned char *m=(unsigned char*)(cl+(j+1));
|
||||
|
||||
while (i < m) {
|
||||
BITS32 k1 = i[0];
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
hash ^= k1;
|
||||
hash = ROTL32(hash,13);
|
||||
hash = hash*5+0xe6546b64;
|
||||
i++;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail not used becouse len is block multiple
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
hash ^= len;
|
||||
|
||||
hash = fmix32(hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*DJB2*/
|
||||
#define DJB2_OFFSET 5381
|
||||
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_DJB2(UInt arity, CELL *cl, UInt bnds[], UInt sz);
|
||||
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_DJB2(UInt arity, CELL *cl, UInt bnds[], UInt sz)
|
||||
{
|
||||
BITS32 hash;
|
||||
UInt j=0;
|
||||
|
||||
hash = DJB2_OFFSET;
|
||||
while (j < arity) {
|
||||
if (bnds[j]) {
|
||||
unsigned char *i=(unsigned char*)(cl+j);
|
||||
unsigned char *m=(unsigned char*)(cl+(j+1));
|
||||
|
||||
while (i < m) {
|
||||
BITS32 h5 = hash << 5;
|
||||
hash += h5 + i[0]; /* hash * 33 + i[0] */
|
||||
i++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_RS(UInt arity, CELL *cl, UInt bnds[], UInt sz);
|
||||
|
||||
/* RS Hash Function */
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_RS(UInt arity, CELL *cl, UInt bnds[], UInt sz)
|
||||
{
|
||||
UInt hash=0;
|
||||
UInt j=0;
|
||||
|
||||
UInt b = 378551;
|
||||
UInt a = 63689;
|
||||
|
||||
while (j < arity) {
|
||||
if (bnds[j]) {
|
||||
unsigned char *i=(unsigned char*)(cl+j);
|
||||
unsigned char *m=(unsigned char*)(cl+(j+1));
|
||||
|
||||
while (i < m) {
|
||||
hash = hash * a + i[0];
|
||||
a = a * b;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_FVN_1A(UInt arity, CELL *cl, UInt bnds[], UInt sz);
|
||||
|
||||
/* Simple hash function:
|
||||
FVN-1A
|
||||
first component is the base key.
|
||||
hash0 spreads extensions coming from different elements.
|
||||
spread over j quadrants.
|
||||
*/
|
||||
INLINE_ONLY inline BITS32
|
||||
HASH_FVN_1A(UInt arity, CELL *cl, UInt bnds[], UInt sz)
|
||||
{
|
||||
UInt hash;
|
||||
UInt j=0;
|
||||
|
||||
hash = FNV_OFFSET;
|
||||
while (j < arity) {
|
||||
if (bnds[j]) {
|
||||
unsigned char *i=(unsigned char*)(cl+j);
|
||||
unsigned char *m=(unsigned char*)(cl+(j+1));
|
||||
|
||||
while (i < m) {
|
||||
hash = hash ^ i[0];
|
||||
hash = hash * FNV_PRIME;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
//#define TEST_HASH_DJB 1
|
||||
|
||||
#if defined TEST_HASH_MURMUR
|
||||
# define HASH(...) HASH_MURMUR3_32(__VA_ARGS__)
|
||||
#elif defined TEST_HASH_DJB
|
||||
# define HASH(...) HASH_DJB2(__VA_ARGS__)
|
||||
#elif defined TEST_HASH_RS
|
||||
# define HASH(...) HASH_RS(__VA_ARGS__)
|
||||
#else
|
||||
/* Default: TEST_HASH_FVN */
|
||||
# define HASH(...) HASH_FVN_1A(__VA_ARGS__)
|
||||
# define HASH1(...) HASH_MURMUR3_32(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
static BITS32
|
||||
NEXT(UInt arity, CELL *cl, UInt bnds[], UInt sz, BITS32 hash)
|
||||
{
|
||||
int i = 0;
|
||||
BITS32 hash1;
|
||||
|
||||
while (bnds[i]==0) i++;
|
||||
hash1 = HASH1(arity, cl, bnds, sz);
|
||||
return (hash + hash1 +cl[i]);
|
||||
}
|
||||
|
||||
/* search for matching elements */
|
||||
static int
|
||||
MATCH(CELL *clp, CELL *kvp, UInt arity, UInt bnds[])
|
||||
{
|
||||
UInt j = 0;
|
||||
while (j< arity) {
|
||||
if ( bnds[j] && clp[j] != kvp[j])
|
||||
return FALSE;
|
||||
j++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ADD_TO_TRY_CHAIN(CELL *kvp, CELL *cl, struct index_t *it)
|
||||
{
|
||||
BITS32 old = EXO_ADDRESS_TO_OFFSET(it, kvp);
|
||||
BITS32 new = EXO_ADDRESS_TO_OFFSET(it, cl);
|
||||
BITS32 *links = it->links;
|
||||
BITS32 tmp = links[old]; /* points to the end of the chain */
|
||||
|
||||
if (!tmp) {
|
||||
links[old] = links[new] = new;
|
||||
} else {
|
||||
links[new] = links[tmp];
|
||||
links[tmp] = new;
|
||||
links[old] = new;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the critical routine, it builds the hash table *
|
||||
* each HT field stores a key pointer which is actually
|
||||
* a pointer to the point in the clause where one can find the element.
|
||||
*
|
||||
* The cls table indexes all elements that can be reached using that key.
|
||||
*
|
||||
* Insert:
|
||||
* j = first
|
||||
* not match cij -> insert, open new chain
|
||||
* match ci..j ck..j -> find j = minarg(cij \= c2j),
|
||||
* else j = +inf -> c2+ci
|
||||
* Lookup:
|
||||
* j= first
|
||||
* not match cij -> fail
|
||||
* match ci..j ck..j -> find j = minarg(cij \= c2j)
|
||||
* else
|
||||
*/
|
||||
static int
|
||||
INSERT(CELL *cl, struct index_t *it, UInt arity, UInt base, UInt bnds[])
|
||||
{
|
||||
CELL *kvp;
|
||||
BITS32 hash;
|
||||
int coll_count = 0;
|
||||
|
||||
|
||||
hash = HASH(arity, cl, bnds, it->hsize);
|
||||
next:
|
||||
kvp = EXO_OFFSET_TO_ADDRESS(it, it->key [hash % it->hsize]);
|
||||
if (kvp == NULL) {
|
||||
/* simple case, new entry */
|
||||
it->nentries++;
|
||||
it->key[hash % it->hsize ] = EXO_ADDRESS_TO_OFFSET(it, cl);
|
||||
if (coll_count > it -> max_col_count)
|
||||
it->max_col_count = coll_count;
|
||||
return TRUE;
|
||||
} else if (MATCH(kvp, cl, arity, bnds)) {
|
||||
it->ntrys++;
|
||||
ADD_TO_TRY_CHAIN(kvp, cl, it);
|
||||
return TRUE;
|
||||
} else {
|
||||
coll_count++;
|
||||
it->ncollisions++;
|
||||
// printf("#");
|
||||
hash = NEXT(arity, cl, bnds, it->hsize, hash);
|
||||
//if (exo_write) printf("N=%ld\n", hash);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
static yamop *
|
||||
LOOKUP(struct index_t *it, UInt arity, UInt j, UInt bnds[])
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL *kvp;
|
||||
BITS32 hash;
|
||||
|
||||
/* j is the firs bound element */
|
||||
/* check if we match */
|
||||
hash = HASH(arity, XREGS+1, bnds, it->hsize);
|
||||
next:
|
||||
/* loop to insert element */
|
||||
kvp = EXO_OFFSET_TO_ADDRESS(it, it->key[hash % it->hsize]);
|
||||
if (kvp == NULL) {
|
||||
/* simple case, no element */
|
||||
return FAILCODE;
|
||||
} else if (MATCH(kvp, XREGS+1, arity, bnds)) {
|
||||
S = kvp;
|
||||
if (!it->is_key && it->links[EXO_ADDRESS_TO_OFFSET(it, S)])
|
||||
return it->code;
|
||||
else
|
||||
return NEXTOP(NEXTOP(it->code,lp),lp);
|
||||
} else {
|
||||
/* collision */
|
||||
hash = NEXT(arity, XREGS+1, bnds, it->hsize, hash);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fill_hash(UInt bmap, struct index_t *it, UInt bnds[])
|
||||
{
|
||||
UInt i;
|
||||
UInt arity = it->arity;
|
||||
CELL *cl = it->cls;
|
||||
|
||||
for (i=0; i < it->nels; i++) {
|
||||
if (!INSERT(cl, it, arity, 0, bnds))
|
||||
return FALSE;
|
||||
cl += arity;
|
||||
}
|
||||
for (i=0; i < it->hsize; i++) {
|
||||
if (it->key[i]) {
|
||||
BITS32 offset = it->key[i];
|
||||
BITS32 last = it->links[offset];
|
||||
if (last) {
|
||||
/* the chain used to point straight to the last, and the last back to the original first */
|
||||
it->links[offset] = it->links[last];
|
||||
it->links[last] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static struct index_t *
|
||||
add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count)
|
||||
{
|
||||
CACHE_REGS
|
||||
UInt ncls = ap->cs.p_code.NOfClauses, j;
|
||||
CELL *base = NULL;
|
||||
struct index_t *i;
|
||||
size_t sz, dsz;
|
||||
yamop *ptr;
|
||||
UInt *bnds = LOCAL_ibnds;
|
||||
|
||||
sz = (CELL)NEXTOP(NEXTOP((yamop*)NULL,lp),lp)+ap->ArityOfPE*(CELL)NEXTOP((yamop *)NULL,x) +(CELL)NEXTOP(NEXTOP((yamop *)NULL,p),l);
|
||||
if (!(i = (struct index_t *)Yap_AllocCodeSpace(sizeof(struct index_t)+sz))) {
|
||||
CACHE_REGS
|
||||
save_machine_regs();
|
||||
LOCAL_Error_Size = 3*ncls*sizeof(CELL);
|
||||
LOCAL_ErrorMessage = "not enough space to index";
|
||||
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
|
||||
return NULL;
|
||||
}
|
||||
i->is_key = FALSE;
|
||||
i->next = *ip;
|
||||
i->prev = NULL;
|
||||
i->nels = ncls;
|
||||
i->arity = ap->ArityOfPE;
|
||||
i->ap = ap;
|
||||
i->bmap = bmap;
|
||||
i->is_key = FALSE;
|
||||
i->hsize = 2*ncls;
|
||||
dsz = sizeof(BITS32)*(ncls+1+i->hsize);
|
||||
if (count) {
|
||||
if (!(base = (CELL *)Yap_AllocCodeSpace(dsz))) {
|
||||
CACHE_REGS
|
||||
save_machine_regs();
|
||||
LOCAL_Error_Size = dsz;
|
||||
LOCAL_ErrorMessage = "not enough space to generate indices";
|
||||
Yap_FreeCodeSpace((void *)i);
|
||||
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
|
||||
return NULL;
|
||||
}
|
||||
memset(base, 0, dsz);
|
||||
}
|
||||
i->size = sz+dsz+sizeof(struct index_t);
|
||||
i->key = (BITS32 *)base;
|
||||
i->links = (BITS32 *)base+i->hsize;
|
||||
i->ncollisions = i->nentries = i->ntrys = 0;
|
||||
i->cls = (CELL *)((ADDR)ap->cs.p_code.FirstClause+2*sizeof(struct index_t *));
|
||||
i->bcls= i->cls-i->arity;
|
||||
i->udi_free_args = 0;
|
||||
i->is_udi = FALSE;
|
||||
i->udi_arg = 0;
|
||||
*ip = i;
|
||||
while (count) {
|
||||
if (!fill_hash(bmap, i, bnds)) {
|
||||
size_t sz;
|
||||
i->hsize += ncls;
|
||||
if (i->is_key) {
|
||||
sz = i->hsize*sizeof(BITS32);
|
||||
} else {
|
||||
sz = (ncls+1+i->hsize)*sizeof(BITS32);
|
||||
}
|
||||
if (base != (CELL *)Yap_ReallocCodeSpace((char *)base, sz))
|
||||
return FALSE;
|
||||
memset(base, 0, sz);
|
||||
i->key = (BITS32 *)base;
|
||||
i->links = (BITS32 *)(base+i->hsize);
|
||||
i->ncollisions = i->nentries = i->ntrys = 0;
|
||||
continue;
|
||||
}
|
||||
#if DEBUG
|
||||
fprintf(stderr, "entries=" UInt_FORMAT " collisions=" UInt_FORMAT" (max=" UInt_FORMAT ") trys=" UInt_FORMAT "\n", i->nentries, i->ncollisions, i->max_col_count, i->ntrys);
|
||||
#endif
|
||||
if (!i->ntrys && !i->is_key) {
|
||||
i->is_key = TRUE;
|
||||
if (base != (CELL *)Yap_ReallocCodeSpace((char *)base, i->hsize*sizeof(BITS32)))
|
||||
return FALSE;
|
||||
}
|
||||
/* our hash table is just too large */
|
||||
if (( i->nentries+i->ncollisions )*10 < i->hsize) {
|
||||
size_t sz;
|
||||
i->hsize = ( i->nentries+i->ncollisions )*10;
|
||||
if (i->is_key) {
|
||||
sz = i->hsize*sizeof(BITS32);
|
||||
} else {
|
||||
sz = (ncls+1+i->hsize)*sizeof(BITS32);
|
||||
}
|
||||
if (base != (CELL *)Yap_ReallocCodeSpace((char *)base, sz))
|
||||
return FALSE;
|
||||
memset(base, 0, sz);
|
||||
i->key = (BITS32 *)base;
|
||||
i->links = (BITS32 *)base+i->hsize;
|
||||
i->ncollisions = i->nentries = i->ntrys = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr = (yamop *)(i+1);
|
||||
i->code = ptr;
|
||||
if (count)
|
||||
ptr->opc = Yap_opcode(_try_exo);
|
||||
else
|
||||
ptr->opc = Yap_opcode(_try_all_exo);
|
||||
ptr->y_u.lp.l = (yamop *)i;
|
||||
ptr->y_u.lp.p = ap;
|
||||
ptr = NEXTOP(ptr, lp);
|
||||
if (count)
|
||||
ptr->opc = Yap_opcode(_retry_exo);
|
||||
else
|
||||
ptr->opc = Yap_opcode(_retry_all_exo);
|
||||
ptr->y_u.lp.p = ap;
|
||||
ptr->y_u.lp.l = (yamop *)i;
|
||||
ptr = NEXTOP(ptr, lp);
|
||||
for (j = 0; j < i->arity; j++) {
|
||||
ptr->opc = Yap_opcode(_get_atom_exo);
|
||||
#if PRECOMPUTE_REGADDRESS
|
||||
ptr->y_u.x.x = (CELL) (XREGS + (j+1));
|
||||
#else
|
||||
ptr->y_u.x.x = j+1;
|
||||
#endif
|
||||
ptr = NEXTOP(ptr, x);
|
||||
}
|
||||
ptr->opc = Yap_opcode(_procceed);
|
||||
ptr->y_u.p.p = ap;
|
||||
ptr = NEXTOP(ptr, p);
|
||||
ptr->opc = Yap_opcode(_Ystop);
|
||||
ptr->y_u.l.l = i->code;
|
||||
Yap_inform_profiler_of_clause((char *)(i->code), (char *)NEXTOP(ptr,l), ap, GPROF_INDEX);
|
||||
if (ap->PredFlags & UDIPredFlag) {
|
||||
Yap_new_udi_clause( ap, NULL, (Term)ip);
|
||||
} else {
|
||||
i->is_udi = FALSE;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
yamop *
|
||||
Yap_ExoLookup(PredEntry *ap USES_REGS)
|
||||
{
|
||||
UInt arity = ap->ArityOfPE;
|
||||
UInt bmap = 0L, bit = 1, count = 0, j, j0 = 0;
|
||||
struct index_t **ip = (struct index_t **)(ap->cs.p_code.FirstClause);
|
||||
struct index_t *i = *ip;
|
||||
|
||||
for (j=0; j< arity; j++, bit<<=1) {
|
||||
Term t = Deref(XREGS[j+1]);
|
||||
if (!IsVarTerm(t)) {
|
||||
bmap += bit;
|
||||
LOCAL_ibnds[j] = TRUE;
|
||||
if (!count) j0= j;
|
||||
count++;
|
||||
} else {
|
||||
LOCAL_ibnds[j] = FALSE;
|
||||
}
|
||||
XREGS[j+1] = t;
|
||||
}
|
||||
|
||||
while (i) {
|
||||
// if (i->is_key && (i->bmap & bmap) == i->bmap) {
|
||||
// break;
|
||||
// }
|
||||
if (i->bmap == bmap) {
|
||||
break;
|
||||
}
|
||||
ip = &i->next;
|
||||
i = i->next;
|
||||
}
|
||||
if (!i) {
|
||||
i = add_index(ip, bmap, ap, count);
|
||||
}
|
||||
if (count) {
|
||||
yamop *code = LOOKUP(i, arity, j0, LOCAL_ibnds);
|
||||
if (code == FAILCODE)
|
||||
return code;
|
||||
if (i->is_udi)
|
||||
return ((CEnterExoIndex)i->udi_first)(i PASS_REGS);
|
||||
else
|
||||
return code;
|
||||
} else if(i->is_udi) {
|
||||
return ((CEnterExoIndex)i->udi_first)(i PASS_REGS);
|
||||
} else {
|
||||
return i->code;
|
||||
}
|
||||
}
|
||||
|
||||
CELL
|
||||
Yap_NextExo(choiceptr cptr, struct index_t *it)
|
||||
{
|
||||
CACHE_REGS
|
||||
BITS32 offset = ADDRESS_TO_LINK(it,(BITS32 *)((CELL *)(B+1))[it->arity]);
|
||||
BITS32 next = it->links[offset];
|
||||
((CELL *)(B+1))[it->arity] = (CELL)LINK_TO_ADDRESS(it, next);
|
||||
S = it->cls+it->arity*offset;
|
||||
return next;
|
||||
}
|
||||
|
||||
static MegaClause *
|
||||
exodb_get_space( Term t, Term mod, Term tn )
|
||||
{
|
||||
UInt arity;
|
||||
Prop pe;
|
||||
PredEntry *ap;
|
||||
MegaClause *mcl;
|
||||
UInt ncls;
|
||||
UInt required;
|
||||
struct index_t **li;
|
||||
|
||||
|
||||
if (IsVarTerm(mod) || !IsAtomTerm(mod)) {
|
||||
return NULL;
|
||||
}
|
||||
if (IsAtomTerm(t)) {
|
||||
Atom a = AtomOfTerm(t);
|
||||
arity = 0;
|
||||
pe = PredPropByAtom(a, mod);
|
||||
} else if (IsApplTerm(t)) {
|
||||
register Functor f = FunctorOfTerm(t);
|
||||
arity = ArityOfFunctor(f);
|
||||
pe = PredPropByFunc(f, mod);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
if (EndOfPAEntr(pe))
|
||||
return NULL;
|
||||
ap = RepPredProp(pe);
|
||||
if (ap->PredFlags & (DynamicPredFlag|LogUpdatePredFlag
|
||||
#ifdef TABLING
|
||||
|TabledPredFlag
|
||||
#endif /* TABLING */
|
||||
)) {
|
||||
Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE,t,"dbload_get_space/4");
|
||||
return NULL;
|
||||
}
|
||||
if (IsVarTerm(tn) || !IsIntegerTerm(tn)) {
|
||||
return NULL;
|
||||
}
|
||||
ncls = IntegerOfTerm(tn);
|
||||
if (ncls <= 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
required = ncls*arity*sizeof(CELL)+sizeof(MegaClause)+2*sizeof(struct index_t *);
|
||||
while (!(mcl = (MegaClause *)Yap_AllocCodeSpace(required))) {
|
||||
if (!Yap_growheap(FALSE, required, NULL)) {
|
||||
/* just fail, the system will keep on going */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
Yap_ClauseSpace += required;
|
||||
/* cool, it's our turn to do the conversion */
|
||||
mcl->ClFlags = MegaMask|ExoMask;
|
||||
mcl->ClSize = required;
|
||||
mcl->ClPred = ap;
|
||||
mcl->ClItemSize = arity*sizeof(CELL);
|
||||
mcl->ClNext = NULL;
|
||||
li = (struct index_t **)(mcl->ClCode);
|
||||
li[0] = li[1] = NULL;
|
||||
ap->cs.p_code.FirstClause =
|
||||
ap->cs.p_code.LastClause =
|
||||
mcl->ClCode;
|
||||
ap->PredFlags |= MegaClausePredFlag;
|
||||
ap->cs.p_code.NOfClauses = ncls;
|
||||
if (ap->PredFlags & (SpiedPredFlag|CountPredFlag|ProfiledPredFlag)) {
|
||||
ap->OpcodeOfPred = Yap_opcode(_spy_pred);
|
||||
} else {
|
||||
ap->OpcodeOfPred = Yap_opcode(_enter_exo);
|
||||
}
|
||||
ap->CodeOfPred = ap->cs.p_code.TrueCodeOfPred = (yamop *)(&(ap->OpcodeOfPred));
|
||||
return mcl;
|
||||
}
|
||||
|
||||
bool
|
||||
YAP_NewExo( PredEntry *ap, size_t data, struct udi_info *udi)
|
||||
{
|
||||
MegaClause *mcl;
|
||||
size_t required;
|
||||
struct index_t **li;
|
||||
|
||||
if (data <= ap->ArityOfPE*sizeof(CELL)) {
|
||||
return false;
|
||||
}
|
||||
// data = ncls*arity*sizeof(CELL);
|
||||
required = data+sizeof(MegaClause)+2*sizeof(struct index_t *);
|
||||
while (!(mcl = (MegaClause *)Yap_AllocCodeSpace(required))) {
|
||||
if (!Yap_growheap(FALSE, required, NULL)) {
|
||||
/* just fail, the system will keep on going */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Yap_ClauseSpace += required;
|
||||
/* cool, it's our turn to do the conversion */
|
||||
mcl->ClFlags = MegaMask|ExoMask;
|
||||
mcl->ClSize = required;
|
||||
mcl->ClPred = ap;
|
||||
mcl->ClItemSize = ap->ArityOfPE*sizeof(CELL);
|
||||
mcl->ClNext = NULL;
|
||||
li = (struct index_t **)(mcl->ClCode);
|
||||
li[0] = li[1] = NULL;
|
||||
ap->cs.p_code.FirstClause =
|
||||
ap->cs.p_code.LastClause =
|
||||
mcl->ClCode;
|
||||
ap->PredFlags |= MegaClausePredFlag;
|
||||
ap->cs.p_code.NOfClauses = 0;
|
||||
if (ap->PredFlags & (SpiedPredFlag|CountPredFlag|ProfiledPredFlag)) {
|
||||
ap->OpcodeOfPred = Yap_opcode(_spy_pred);
|
||||
} else {
|
||||
ap->OpcodeOfPred = Yap_opcode(_enter_exo);
|
||||
}
|
||||
ap->CodeOfPred = ap->cs.p_code.TrueCodeOfPred = (yamop *)(&(ap->OpcodeOfPred));
|
||||
return true;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_exodb_get_space( USES_REGS1 )
|
||||
{ /* '$number_of_clauses'(Predicate,M,N) */
|
||||
void *mcl;
|
||||
|
||||
if ((mcl = exodb_get_space(Deref(ARG1), Deref(ARG2), Deref(ARG3))) == NULL)
|
||||
return FALSE;
|
||||
|
||||
return Yap_unify(ARG4, MkIntegerTerm((Int)mcl));
|
||||
}
|
||||
|
||||
#define DerefAndCheck(t, V) \
|
||||
t = Deref(V); if(IsVarTerm(t) || !(IsAtomOrIntTerm(t))) Yap_Error(TYPE_ERROR_ATOMIC, t0, "load_db");
|
||||
|
||||
static Int
|
||||
store_exo(yamop *pc, UInt arity, Term t0)
|
||||
{
|
||||
Term t;
|
||||
CELL *tp = RepAppl(t0)+1,
|
||||
*cpc = (CELL *)pc;
|
||||
UInt i;
|
||||
for (i = 0; i< arity; i++) {
|
||||
DerefAndCheck(t, tp[0]);
|
||||
*cpc = t;
|
||||
// Yap_DebugPlWrite(t); fprintf(stderr,"\n");
|
||||
tp++;
|
||||
cpc++;
|
||||
}
|
||||
//fprintf(stderr,"\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
YAP_AssertTuples( PredEntry *pe, const Term *ts, size_t offset, size_t m)
|
||||
{
|
||||
MegaClause *mcl = ClauseCodeToMegaClause(pe->cs.p_code.FirstClause);
|
||||
size_t i;
|
||||
ADDR base = (ADDR)mcl->ClCode+2*sizeof(struct index_t *);
|
||||
for (i=0; i<m; i++) {
|
||||
yamop *ptr = (yamop *)(base+offset*(mcl->ClItemSize));
|
||||
store_exo( ptr, pe->ArityOfPE, ts[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
exoassert( void *handle, Int n, Term term )
|
||||
{ /* '$number_of_clauses'(Predicate,M,N) */
|
||||
PredEntry *pe;
|
||||
MegaClause *mcl;
|
||||
|
||||
|
||||
mcl = (MegaClause *) handle;
|
||||
pe = mcl->ClPred;
|
||||
store_exo((yamop *)((ADDR)mcl->ClCode+2*sizeof(struct index_t *)+n*(mcl->ClItemSize)),pe->ArityOfPE, term);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_exoassert( USES_REGS1 )
|
||||
{ /* '$number_of_clauses'(Predicate,M,N) */
|
||||
Term thandle = Deref(ARG2);
|
||||
Term tn = Deref(ARG3);
|
||||
MegaClause *mcl;
|
||||
Int n;
|
||||
|
||||
|
||||
if (IsVarTerm(thandle) || !IsIntegerTerm(thandle)) {
|
||||
return FALSE;
|
||||
}
|
||||
mcl = (MegaClause *)IntegerOfTerm(thandle);
|
||||
if (IsVarTerm(tn) || !IsIntegerTerm(tn)) {
|
||||
return FALSE;
|
||||
}
|
||||
n = IntegerOfTerm(tn);
|
||||
exoassert(mcl,n,Deref(ARG1));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitExoPreds(void)
|
||||
{
|
||||
CACHE_REGS
|
||||
Term cm = CurrentModule;
|
||||
|
||||
CurrentModule = DBLOAD_MODULE;
|
||||
Yap_InitCPred("exo_db_get_space", 4, p_exodb_get_space, 0L);
|
||||
Yap_InitCPred("exoassert", 3, p_exoassert, 0L);
|
||||
CurrentModule = cm;
|
||||
}
|
|
@ -0,0 +1,588 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: exo.c *
|
||||
* comments: Exo compilation *
|
||||
* *
|
||||
* Last rev: $Date: 2008-07-22 23:34:44 $,$Author: vsc $ * *
|
||||
* $Log: not supported by cvs2svn $ *
|
||||
* *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "clause.h"
|
||||
#include "yapio.h"
|
||||
#include "eval.h"
|
||||
#include "tracer.h"
|
||||
#include "attvar.h"
|
||||
#ifdef YAPOR
|
||||
#include "or.macros.h"
|
||||
#endif /* YAPOR */
|
||||
#ifdef TABLING
|
||||
#include "tab.macros.h"
|
||||
#endif /* TABLING */
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include <udi.h>
|
||||
|
||||
|
||||
static int
|
||||
compar(const void *ip0, const void *jp0) {
|
||||
CACHE_REGS
|
||||
BITS32 *ip = (BITS32 *)ip0, *jp = (BITS32 *)jp0;
|
||||
Term i = EXO_OFFSET_TO_ADDRESS(LOCAL_exo_it, *ip)[LOCAL_exo_arg];
|
||||
Term j = EXO_OFFSET_TO_ADDRESS(LOCAL_exo_it, *jp)[LOCAL_exo_arg];
|
||||
//fprintf(stderr, "%ld-%ld\n", IntOfTerm(i), IntOfTerm(j));
|
||||
return IntOfTerm(i)-IntOfTerm(j);
|
||||
}
|
||||
|
||||
static Int
|
||||
cmp_extra_args(CELL *si, CELL *sj, struct index_t *it)
|
||||
{
|
||||
UInt m = it->udi_free_args;
|
||||
UInt m0 = 1, x;
|
||||
|
||||
for (x=0; x< it->arity; x++) {
|
||||
if (m0 & m) {
|
||||
if (si[x] != sj[x]) {
|
||||
if (IsIntTerm(si[x]))
|
||||
return IntOfTerm(si[x])-IntOfTerm(sj[x]);
|
||||
return AtomOfTerm(si[x])-AtomOfTerm(sj[x]);
|
||||
}
|
||||
m -= m0;
|
||||
if (m == 0)
|
||||
return 0;
|
||||
}
|
||||
m0 <<= 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compar2(const void *ip0, const void *jp0) {
|
||||
CACHE_REGS
|
||||
BITS32 *ip = (BITS32 *)ip0, *jp = (BITS32 *)jp0;
|
||||
struct index_t *it = LOCAL_exo_it;
|
||||
Term* si = EXO_OFFSET_TO_ADDRESS(it, *ip);
|
||||
Term* sj = EXO_OFFSET_TO_ADDRESS(it, *jp);
|
||||
int cmp = cmp_extra_args(si, sj, it);
|
||||
if (cmp)
|
||||
return cmp;
|
||||
return IntOfTerm(si[LOCAL_exo_arg])-IntOfTerm(sj[LOCAL_exo_arg]);
|
||||
}
|
||||
|
||||
static int
|
||||
compare(const BITS32 *ip, Int j USES_REGS) {
|
||||
Term i = EXO_OFFSET_TO_ADDRESS(LOCAL_exo_it, *ip)[LOCAL_exo_arg];
|
||||
//fprintf(stderr, "%ld-%ld\n", IntOfTerm(i), j);
|
||||
return IntOfTerm(i)-j;
|
||||
}
|
||||
|
||||
static UInt free_args(UInt b[], UInt arity, UInt i) {
|
||||
UInt j;
|
||||
UInt rc = 0;
|
||||
|
||||
for (j=0; j<arity; j++) {
|
||||
if (i !=j && b[j] == 0)
|
||||
rc |= 1<<j;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BITS32*
|
||||
NEXT_DIFFERENT(BITS32 *pt0, BITS32 *pte, struct index_t *it)
|
||||
{
|
||||
Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
|
||||
Term* sj;
|
||||
|
||||
do {
|
||||
pt0++;
|
||||
if (pt0 == pte)
|
||||
return NULL;
|
||||
sj = EXO_OFFSET_TO_ADDRESS(it, *pt0);
|
||||
} while (!cmp_extra_args(si, sj, it));
|
||||
return pt0;
|
||||
}
|
||||
|
||||
static BITS32*
|
||||
PREV_DIFFERENT(BITS32 *pt0, BITS32 *pte, struct index_t *it)
|
||||
{
|
||||
Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
|
||||
Term* sj;
|
||||
|
||||
do {
|
||||
pt0--;
|
||||
if (pt0 == pte)
|
||||
return NULL;
|
||||
sj = EXO_OFFSET_TO_ADDRESS(it, *pt0);
|
||||
} while (!cmp_extra_args(si, sj, it));
|
||||
return pt0;
|
||||
}
|
||||
|
||||
static BITS32*
|
||||
NEXT_MIN(BITS32 *pt0, BITS32 *pte, Term tmin, Term tmax, struct index_t *it)
|
||||
{
|
||||
Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
|
||||
int do_min, do_max;
|
||||
Int min = 0, max = 0;
|
||||
|
||||
if (IsVarTerm(tmin)) {
|
||||
do_min = FALSE;
|
||||
} else {
|
||||
do_min = TRUE;
|
||||
min = IntOfTerm(tmin);
|
||||
}
|
||||
if (IsVarTerm(tmax)) {
|
||||
do_max = FALSE;
|
||||
} else {
|
||||
do_max = TRUE;
|
||||
max = IntOfTerm(tmax);
|
||||
}
|
||||
|
||||
while ((do_min && IntOfTerm(si[it->udi_arg]) < min) ||
|
||||
(do_max && IntOfTerm(si[it->udi_arg]) > max)) {
|
||||
pt0++;
|
||||
if (pt0 == pte)
|
||||
return NULL;
|
||||
si = EXO_OFFSET_TO_ADDRESS(it, *pt0);
|
||||
}
|
||||
return pt0;
|
||||
}
|
||||
|
||||
static BITS32*
|
||||
NEXT_MAX(BITS32 *pt0, BITS32 *pte, Term tmin, Term tmax, struct index_t *it)
|
||||
{
|
||||
Term* si = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
|
||||
int do_min, do_max;
|
||||
Int min = 0, max = 0;
|
||||
|
||||
if (IsVarTerm(tmin)) {
|
||||
do_min = FALSE;
|
||||
} else {
|
||||
do_min = TRUE;
|
||||
min = IntOfTerm(tmin);
|
||||
}
|
||||
if (IsVarTerm(tmax)) {
|
||||
do_max = FALSE;
|
||||
} else {
|
||||
do_max = TRUE;
|
||||
max = IntOfTerm(tmax);
|
||||
}
|
||||
|
||||
while ((do_min && IntOfTerm(si[it->udi_arg]) < min) ||
|
||||
(do_max && IntOfTerm(si[it->udi_arg]) > max)) {
|
||||
pt0--;
|
||||
if (pt0 == pte)
|
||||
return NULL;
|
||||
si = EXO_OFFSET_TO_ADDRESS(it, *pt0);
|
||||
}
|
||||
return pt0;
|
||||
}
|
||||
|
||||
static void
|
||||
IntervalUDIRefitIndex(struct index_t **ip, UInt b[] USES_REGS)
|
||||
{
|
||||
size_t sz;
|
||||
struct index_t *it = *ip;
|
||||
yamop *code;
|
||||
|
||||
/* hard-wired implementation for the Interval case */
|
||||
Int i = it->udi_arg;
|
||||
/* it is bound, use hash */
|
||||
if (it->bmap & b[i]) return;
|
||||
/* no constraints, nothing to gain */
|
||||
//if (!IsAttVar(VarOfTerm(Deref(XREGS[i+1])))) return;
|
||||
LOCAL_exo_it = it;
|
||||
LOCAL_exo_base = it->bcls;
|
||||
LOCAL_exo_arity = it->arity;
|
||||
LOCAL_exo_arg = i;
|
||||
it->udi_free_args = free_args(b, it->arity, i);
|
||||
if (!it->key) {
|
||||
UInt ncls = it->ap->cs.p_code.NOfClauses, i;
|
||||
BITS32 *sorted;
|
||||
/* handle ll variables */
|
||||
sz = sizeof(BITS32)*(ncls);
|
||||
/* allocate space */
|
||||
if (!(it->udi_data = (BITS32*)Yap_AllocCodeSpace(sz)))
|
||||
return;
|
||||
sorted = (BITS32*)it->udi_data;
|
||||
for (i=0; i< ncls; i++)
|
||||
sorted[i] = i;
|
||||
qsort(sorted, (size_t)ncls, sizeof(BITS32), compar);
|
||||
it->links = NULL;
|
||||
} else {
|
||||
BITS32 *sorted0, *sorted;
|
||||
|
||||
/* be conservative */
|
||||
if (it->udi_free_args)
|
||||
sz = sizeof(BITS32)*(2*it->ntrys+3*it->nentries);
|
||||
else
|
||||
sz = sizeof(BITS32)*(it->ntrys+2*it->nentries);
|
||||
/* allocate space */
|
||||
if (!(it->udi_data = (BITS32*)malloc(sz)))
|
||||
return;
|
||||
sorted0 = sorted = (BITS32 *)it->udi_data;
|
||||
sorted++; /* leave an initial hole */
|
||||
for (i=0; i < it->hsize; i++) {
|
||||
if (it->key[i]) {
|
||||
BITS32 *s0 = sorted;
|
||||
BITS32 offset = it->key[i], offset0 = offset;
|
||||
|
||||
*sorted++ = 0;
|
||||
do {
|
||||
*sorted++ = offset;
|
||||
offset = it->links[offset];
|
||||
} while (offset);
|
||||
// S = EXO_OFFSET_TO_ADDRESS(it, offset0); Yap_DebugPlWrite(S[0]);
|
||||
// fprintf(stderr, " key[i]=%d offset=%d %d\n", it->key[i], offset0, (sorted-s0)-1);
|
||||
if (sorted-s0 == 2) {
|
||||
it->links[offset0] = 0;
|
||||
sorted = s0;
|
||||
} else {
|
||||
/* number of elements comes first */
|
||||
*s0 = sorted - (s0+1);
|
||||
qsort(s0+1, (size_t)*s0, sizeof(BITS32), compar);
|
||||
it->links[offset0] = s0-sorted0;
|
||||
if (it->udi_free_args) {
|
||||
memcpy(sorted, s0+1, sizeof(BITS32)*(*s0));
|
||||
qsort(sorted, (size_t)*s0, sizeof(BITS32), compar2);
|
||||
sorted += *s0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sz = sizeof(BITS32)*(sorted-sorted0);
|
||||
it->udi_data = (BITS32 *)realloc((char *)it->udi_data, sz);
|
||||
}
|
||||
it->is_udi = i+1;
|
||||
code = it->code;
|
||||
code->opc = Yap_opcode(_try_exo_udi);
|
||||
code = NEXTOP(code, lp);
|
||||
code->opc = Yap_opcode(_retry_exo_udi);
|
||||
}
|
||||
|
||||
static BITS32 *
|
||||
binary_search(BITS32 *start, BITS32 *end, Int x USES_REGS)
|
||||
{
|
||||
BITS32 *mid;
|
||||
while (start < end) {
|
||||
int cmp;
|
||||
mid = start + (end-start)/2;
|
||||
cmp = compare(mid, x PASS_REGS);
|
||||
if (!cmp)
|
||||
return mid;
|
||||
if (cmp > 0) {
|
||||
end = mid-1;
|
||||
} else
|
||||
start = mid+1;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
static yamop *
|
||||
Interval(struct index_t *it, Term min, Term max, Term op, BITS32 off USES_REGS)
|
||||
{
|
||||
BITS32 *c;
|
||||
BITS32 n;
|
||||
BITS32 *pt;
|
||||
BITS32 *end;
|
||||
Atom at;
|
||||
|
||||
LOCAL_exo_it = it;
|
||||
LOCAL_exo_base = it->bcls;
|
||||
LOCAL_exo_arity = it->arity;
|
||||
LOCAL_exo_arg = it->udi_arg;
|
||||
if (!it->links) {
|
||||
c = (BITS32 *)it->udi_data;
|
||||
n = it->nels;
|
||||
pt = c;
|
||||
end = c+(n-1);
|
||||
} else if (it->links[off]) {
|
||||
c = (BITS32 *)it->udi_data;
|
||||
n = c[it->links[off]];
|
||||
pt = c;
|
||||
end = c+(it->links[off]+n);
|
||||
// fprintf(stderr," %d links %d=%d \n", off, it->links[off], n);
|
||||
} else {
|
||||
if (!IsVarTerm(min)) {
|
||||
Int x;
|
||||
if (!IsIntegerTerm(min)) {
|
||||
min = Yap_Eval(min);
|
||||
if (!IsIntegerTerm(min)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, min, "data-base constraint");
|
||||
return FAILCODE;
|
||||
}
|
||||
}
|
||||
x = IntegerOfTerm(min);
|
||||
if (x >= IntegerOfTerm(S[LOCAL_exo_arg])) {
|
||||
return FAILCODE;
|
||||
}
|
||||
}
|
||||
if (!IsVarTerm(max)) {
|
||||
Int x;
|
||||
if (!IsIntegerTerm(max)) {
|
||||
max = Yap_Eval(max);
|
||||
if (!IsIntegerTerm(max)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, max, "data-base constraint");
|
||||
return FAILCODE;
|
||||
}
|
||||
}
|
||||
x = IntegerOfTerm(max);
|
||||
if (x <= IntegerOfTerm(S[LOCAL_exo_arg])) {
|
||||
return FAILCODE;
|
||||
}
|
||||
}
|
||||
return NEXTOP(NEXTOP(it->code,lp),lp);
|
||||
}
|
||||
|
||||
if (!IsVarTerm(min)) {
|
||||
Int x;
|
||||
if (!IsIntegerTerm(min)) {
|
||||
min = Yap_Eval(min);
|
||||
if (!IsIntegerTerm(min)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, min, "data-base constraint");
|
||||
return FAILCODE;
|
||||
}
|
||||
}
|
||||
x = IntegerOfTerm(min);
|
||||
if (n > 8) {
|
||||
int cmp;
|
||||
pt = binary_search(pt, end, x PASS_REGS);
|
||||
while ( pt < end+1 && (cmp = compare(pt, x PASS_REGS)) <= 0 ) {
|
||||
if (cmp > 0) break;
|
||||
pt++;
|
||||
}
|
||||
} else {
|
||||
while ( pt < end+1 && compare(pt, x PASS_REGS) <= 0 ) {
|
||||
pt++;
|
||||
}
|
||||
}
|
||||
if (pt > end)
|
||||
return FAILCODE;
|
||||
}
|
||||
if (!IsVarTerm(max)) {
|
||||
Int x;
|
||||
BITS32 *pt1;
|
||||
Int n = end-pt;
|
||||
|
||||
if (!IsIntegerTerm(max)) {
|
||||
max = Yap_Eval(max);
|
||||
if (!IsIntegerTerm(max)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER, max, "data-base constraint");
|
||||
return FAILCODE;
|
||||
}
|
||||
}
|
||||
x = IntegerOfTerm(max);
|
||||
if (n > 8) {
|
||||
int cmp;
|
||||
pt1 = binary_search(pt, end, x PASS_REGS);
|
||||
while ( pt1 >= pt && (cmp = compare(pt1, x PASS_REGS)) >= 0 ) {
|
||||
if (cmp < 0) break;
|
||||
pt1--;
|
||||
}
|
||||
} else {
|
||||
pt1 = end;
|
||||
while ( pt1 >= pt && compare(pt1, x PASS_REGS) >= 0 ) {
|
||||
pt1--;
|
||||
}
|
||||
}
|
||||
if (pt1 < pt)
|
||||
return FAILCODE;
|
||||
end = pt1;
|
||||
}
|
||||
if (IsVarTerm(op)) {
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
if (pt < end ) {
|
||||
YENV[-1] = (CELL)( end );
|
||||
YENV[-2] = (CELL)( pt+1 );
|
||||
YENV -= 2;
|
||||
return it->code;
|
||||
}
|
||||
return NEXTOP(NEXTOP(it->code,lp),lp);
|
||||
}
|
||||
at = AtomOfTerm(op);
|
||||
if (at == AtomAny || at == AtomMinimum) {
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
} else if (at == AtomMaximum) {
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, end[0]);
|
||||
} else if (at == AtomUnique) {
|
||||
if (end-2 > pt)
|
||||
return FAILCODE;
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
} else if (at == AtomMin) {
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
if (it->udi_free_args) {
|
||||
BITS32 *ptn;
|
||||
pt = c+(it->links[off]+n+1);
|
||||
end = pt+n;
|
||||
pt = NEXT_MIN(pt, end, min, max, it);
|
||||
if (!pt)
|
||||
return FAILCODE;
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
ptn = NEXT_DIFFERENT(pt, end, it);
|
||||
if (ptn)
|
||||
ptn = NEXT_MIN(ptn, end, min, max, it);
|
||||
if ( ptn ) {
|
||||
YENV[-1] = min; // what we are doing
|
||||
YENV[-2] = max; // what we are doing
|
||||
YENV[-3] = (CELL) end; // what we are doing
|
||||
YENV[-4] = MkAtomTerm(AtomMin); // what we are doing
|
||||
YENV[-5] = (CELL)( ptn ); // where we are in pt0 array
|
||||
YENV -= 5;
|
||||
return it->code;
|
||||
}
|
||||
}
|
||||
return NEXTOP(NEXTOP(it->code,lp),lp);
|
||||
} else if (at == AtomMax) {
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
if (it->udi_free_args) {
|
||||
BITS32 *ptn;
|
||||
end = c+(it->links[off]+n);
|
||||
pt = end+n;
|
||||
pt = NEXT_MAX(pt, end, min, max, it);
|
||||
if (!pt)
|
||||
return FAILCODE;
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt[0]);
|
||||
ptn = PREV_DIFFERENT(pt, end, it);
|
||||
if (ptn)
|
||||
ptn = NEXT_MAX(ptn, end, min, max, it);
|
||||
if ( ptn ) {
|
||||
YENV[-1] = min; // what we are doing
|
||||
YENV[-2] = max; // what we are doing
|
||||
YENV[-3] = (CELL) end; // what we are doing
|
||||
YENV[-4] = MkAtomTerm(AtomMax); // what we are doing
|
||||
YENV[-5] = (CELL)( ptn ); // where we are in pt0 array
|
||||
YENV -= 5;
|
||||
return it->code;
|
||||
}
|
||||
}
|
||||
return NEXTOP(NEXTOP(it->code,lp),lp);
|
||||
}
|
||||
return NEXTOP(NEXTOP(it->code,lp),lp);
|
||||
}
|
||||
|
||||
static yamop *
|
||||
IntervalEnterUDIIndex(struct index_t *it USES_REGS)
|
||||
{
|
||||
Int i = it->udi_arg;
|
||||
Term t = XREGS[i+1], a1;
|
||||
BITS32 off = EXO_ADDRESS_TO_OFFSET(it, S);
|
||||
// printf("off=%d it=%p %p---%p\n", off, it, it->cls, S);
|
||||
attvar_record *attv;
|
||||
|
||||
t = Deref(t);
|
||||
if (!IsVarTerm(t))
|
||||
return FALSE;
|
||||
if(!IsAttVar(VarOfTerm(t)))
|
||||
return Interval(it, MkVarTerm(), MkVarTerm(), MkVarTerm(), off PASS_REGS);
|
||||
attv = RepAttVar(VarOfTerm(t));
|
||||
t = attv->Atts;
|
||||
a1 = ArgOfTerm(2,t);
|
||||
if (IsVarTerm(a1)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t, "executing exo_interval constraints");
|
||||
return FAILCODE;
|
||||
} else if (!IsApplTerm(a1)) {
|
||||
Yap_Error(TYPE_ERROR_COMPOUND, a1, "executing exo_interval constraints");
|
||||
return FAILCODE;
|
||||
} else {
|
||||
return Interval(it, ArgOfTerm(1,a1), ArgOfTerm(2,a1), ArgOfTerm(3,a1), off PASS_REGS);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
IntervalRetryUDIIndex(struct index_t *it USES_REGS)
|
||||
{
|
||||
CELL *w = (CELL*)(B+1)+it->arity;
|
||||
if (IsVarTerm(w[2])) {
|
||||
BITS32 *end = (BITS32 *) w[2],
|
||||
*pt = (BITS32 *) w[1];
|
||||
BITS32 f = *pt;
|
||||
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, f);
|
||||
if (pt++ == end) return FALSE;
|
||||
w[1] = (CELL)pt;
|
||||
} else {
|
||||
BITS32 *pt0 = (BITS32 *)w[1];
|
||||
BITS32 *pte = (BITS32 *)w[3];
|
||||
Atom what = AtomOfTerm(w[2]);
|
||||
Term min = w[5];
|
||||
Term max = w[4];
|
||||
|
||||
S = EXO_OFFSET_TO_ADDRESS(it, pt0[0]);
|
||||
if ( what == AtomMin ) {
|
||||
pt0 = NEXT_DIFFERENT(pt0, pte, it);
|
||||
if (pt0)
|
||||
pt0 = NEXT_MIN(pt0, pte, min, max, it);
|
||||
} else {
|
||||
pt0 = PREV_DIFFERENT(pt0, pte, it);
|
||||
if (pt0)
|
||||
pt0 = NEXT_MAX(pt0, pte, min, max, it);
|
||||
}
|
||||
if (!pt0) {
|
||||
return FALSE;
|
||||
}
|
||||
w[1] = (CELL)pt0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static struct udi_control_block IntervalCB;
|
||||
|
||||
typedef struct exo_udi_access_t {
|
||||
CRefitExoIndex refit;
|
||||
} exo_udi_encaps_t;
|
||||
|
||||
static struct exo_udi_access_t ExoCB;
|
||||
|
||||
static void *
|
||||
IntervalUdiInit (Term spec, int arg, int arity) {
|
||||
ExoCB.refit = IntervalUDIRefitIndex;
|
||||
return (void *)&ExoCB;
|
||||
}
|
||||
|
||||
static void *
|
||||
IntervalUdiInsert (void *control,
|
||||
Term term, int arg, void *data)
|
||||
{
|
||||
CACHE_REGS
|
||||
|
||||
struct index_t **ip = (struct index_t **)term;
|
||||
(*ip)->udi_arg = arg-1;
|
||||
(ExoCB.refit)(ip, LOCAL_ibnds PASS_REGS);
|
||||
(*ip)->udi_first = (void *)IntervalEnterUDIIndex;
|
||||
(*ip)->udi_next = (void *)IntervalRetryUDIIndex;
|
||||
return control;
|
||||
}
|
||||
|
||||
static int IntervalUdiDestroy(void *control)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Yap_udi_Interval_init(void) {
|
||||
UdiControlBlock cb = &IntervalCB;
|
||||
Atom name = Yap_LookupAtom("exo_interval");
|
||||
memset((void *) cb,0, sizeof(*cb));
|
||||
|
||||
/*TODO: ask vitor why this gives a warning*/
|
||||
cb->decl= (YAP_Atom)name;
|
||||
Yap_MkEmptyWakeUp(name);
|
||||
cb->init= IntervalUdiInit;
|
||||
cb->insert=IntervalUdiInsert;
|
||||
cb->search=NULL;
|
||||
cb->destroy=IntervalUdiDestroy;
|
||||
|
||||
Yap_UdiRegister(cb);
|
||||
}
|
|
@ -0,0 +1,414 @@
|
|||
/*****************************************************************
|
||||
* Failure *
|
||||
*****************************************************************/
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
/* trust_fail */
|
||||
BOp(trust_fail, e);
|
||||
{
|
||||
while (POP_CHOICE_POINT(B->cp_b))
|
||||
{
|
||||
POP_EXECUTE();
|
||||
}
|
||||
}
|
||||
#ifdef YAPOR
|
||||
{
|
||||
choiceptr cut_pt;
|
||||
cut_pt = B->cp_b;
|
||||
CUT_prune_to(cut_pt);
|
||||
B = cut_pt;
|
||||
}
|
||||
#else
|
||||
B = B->cp_b;
|
||||
#endif /* YAPOR */
|
||||
goto fail;
|
||||
ENDBOp();
|
||||
|
||||
#ifdef YAPOR
|
||||
shared_fail:
|
||||
B = Get_LOCAL_top_cp();
|
||||
SET_BB(PROTECT_FROZEN_B(B));
|
||||
goto fail;
|
||||
#endif /* YAPOR */
|
||||
|
||||
/* fail */
|
||||
PBOp(op_fail, e);
|
||||
|
||||
if (PP) {
|
||||
UNLOCK(PP->PELock);
|
||||
PP = NULL;
|
||||
}
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackFail, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
#endif
|
||||
|
||||
fail:
|
||||
{
|
||||
register tr_fr_ptr pt0 = TR;
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP) {
|
||||
UNLOCK(PP->PELock);
|
||||
PP = NULL;
|
||||
}
|
||||
#endif
|
||||
PREG = B->cp_ap;
|
||||
save_pc();
|
||||
CACHE_TR(B->cp_tr);
|
||||
PREFETCH_OP(PREG);
|
||||
failloop:
|
||||
if (pt0 == S_TR) {
|
||||
SP = SP0;
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
int go_on = true;
|
||||
yamop *ipc = PREG;
|
||||
|
||||
while (go_on) {
|
||||
op_numbers opnum = Yap_op_from_opcode(ipc->opc);
|
||||
|
||||
go_on = false;
|
||||
switch (opnum) {
|
||||
#ifdef TABLING
|
||||
case _table_load_answer:
|
||||
low_level_trace(retry_table_loader, LOAD_CP(B)->cp_pred_entry, NULL);
|
||||
break;
|
||||
case _table_try_answer:
|
||||
case _table_retry_me:
|
||||
case _table_trust_me:
|
||||
case _table_retry:
|
||||
case _table_trust:
|
||||
case _table_completion:
|
||||
#ifdef THREADS_CONSUMER_SHARING
|
||||
case _table_answer_resolution_completion:
|
||||
#endif /* THREADS_CONSUMER_SHARING */
|
||||
#ifdef DETERMINISTIC_TABLING
|
||||
if (IS_DET_GEN_CP(B))
|
||||
low_level_trace(retry_table_generator, DET_GEN_CP(B)->cp_pred_entry, NULL);
|
||||
else
|
||||
#endif /* DETERMINISTIC_TABLING */
|
||||
low_level_trace(retry_table_generator, GEN_CP(B)->cp_pred_entry, (CELL *)(GEN_CP(B) + 1));
|
||||
break;
|
||||
case _table_answer_resolution:
|
||||
low_level_trace(retry_table_consumer, CONS_CP(B)->cp_pred_entry, NULL);
|
||||
break;
|
||||
case _trie_trust_var:
|
||||
case _trie_retry_var:
|
||||
case _trie_trust_var_in_pair:
|
||||
case _trie_retry_var_in_pair:
|
||||
case _trie_trust_val:
|
||||
case _trie_retry_val:
|
||||
case _trie_trust_val_in_pair:
|
||||
case _trie_retry_val_in_pair:
|
||||
case _trie_trust_atom:
|
||||
case _trie_retry_atom:
|
||||
case _trie_trust_atom_in_pair:
|
||||
case _trie_retry_atom_in_pair:
|
||||
case _trie_trust_null:
|
||||
case _trie_retry_null:
|
||||
case _trie_trust_null_in_pair:
|
||||
case _trie_retry_null_in_pair:
|
||||
case _trie_trust_pair:
|
||||
case _trie_retry_pair:
|
||||
case _trie_trust_appl:
|
||||
case _trie_retry_appl:
|
||||
case _trie_trust_appl_in_pair:
|
||||
case _trie_retry_appl_in_pair:
|
||||
case _trie_trust_extension:
|
||||
case _trie_retry_extension:
|
||||
case _trie_trust_double:
|
||||
case _trie_retry_double:
|
||||
case _trie_trust_longint:
|
||||
case _trie_retry_longint:
|
||||
case _trie_trust_gterm:
|
||||
case _trie_retry_gterm:
|
||||
low_level_trace(retry_table_loader, UndefCode, NULL);
|
||||
break;
|
||||
#endif /* TABLING */
|
||||
case _or_else:
|
||||
case _or_last:
|
||||
low_level_trace(retry_or, NULL, NULL);
|
||||
break;
|
||||
case _retry2:
|
||||
case _retry3:
|
||||
case _retry4:
|
||||
ipc = NEXTOP(ipc,l);
|
||||
go_on = true;
|
||||
break;
|
||||
case _jump:
|
||||
ipc = ipc->y_u.l.l;
|
||||
go_on = true;
|
||||
break;
|
||||
case _retry_c:
|
||||
case _retry_userc:
|
||||
low_level_trace(retry_pred, ipc->y_u.OtapFs.p, B->cp_args);
|
||||
break;
|
||||
case _retry_profiled:
|
||||
case _count_retry:
|
||||
ipc = NEXTOP(ipc,p);
|
||||
go_on = true;
|
||||
break;
|
||||
case _retry_me:
|
||||
case _trust_me:
|
||||
case _count_retry_me:
|
||||
case _count_trust_me:
|
||||
case _profiled_retry_me:
|
||||
case _profiled_trust_me:
|
||||
case _retry_and_mark:
|
||||
case _profiled_retry_and_mark:
|
||||
case _retry:
|
||||
case _trust:
|
||||
low_level_trace(retry_pred, ipc->y_u.Otapl.p, B->cp_args);
|
||||
break;
|
||||
case _try_logical:
|
||||
case _retry_logical:
|
||||
case _profiled_retry_logical:
|
||||
case _count_retry_logical:
|
||||
case _trust_logical:
|
||||
case _profiled_trust_logical:
|
||||
case _count_trust_logical:
|
||||
low_level_trace(retry_pred, ipc->y_u.OtILl.d->ClPred, B->cp_args);
|
||||
break;
|
||||
case _Nstop:
|
||||
case _Ystop:
|
||||
low_level_trace(retry_pred, NULL, B->cp_args);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LOW_LEVEL_TRACER */
|
||||
#ifdef FROZEN_STACKS
|
||||
#ifdef YAPOR_SBA
|
||||
if (pt0 < TR_FZ || pt0 > (ADDR)CurrentTrailTop+MinTrailGap)
|
||||
#else
|
||||
if (pt0 < TR_FZ)
|
||||
#endif /* YAPOR_SBA */
|
||||
{
|
||||
TR = TR_FZ;
|
||||
TRAIL_LINK(pt0);
|
||||
} else
|
||||
#endif /* FROZEN_STACKS */
|
||||
RESTORE_TR();
|
||||
GONext();
|
||||
}
|
||||
BEGD(d1);
|
||||
d1 = TrailTerm(pt0-1);
|
||||
pt0--;
|
||||
if (IsVarTerm(d1)) {
|
||||
#if defined(YAPOR_SBA) && defined(YAPOR)
|
||||
/* clean up the trail when we backtrack */
|
||||
if (Unsigned((Int)(d1)-(Int)(H_FZ)) >
|
||||
Unsigned((Int)(B_FZ)-(Int)(H_FZ))) {
|
||||
RESET_VARIABLE(STACK_TO_SBA(d1));
|
||||
} else
|
||||
#endif
|
||||
/* normal variable */
|
||||
RESET_VARIABLE(d1);
|
||||
goto failloop;
|
||||
}
|
||||
/* pointer to code space */
|
||||
/* or updatable variable */
|
||||
#if defined(TERM_EXTENSIONS) || defined(FROZEN_STACKS) || defined(MULTI_ASSIGNMENT_VARIABLES)
|
||||
if (IsPairTerm(d1))
|
||||
#endif /* TERM_EXTENSIONS || FROZEN_STACKS || MULTI_ASSIGNMENT_VARIABLES */
|
||||
{
|
||||
register CELL flags;
|
||||
CELL *pt1 = RepPair(d1);
|
||||
#ifdef LIMIT_TABLING
|
||||
if ((ADDR) pt1 == LOCAL_TrailBase) {
|
||||
sg_fr_ptr sg_fr = (sg_fr_ptr) TrailVal(pt0);
|
||||
TrailTerm(pt0) = AbsPair((CELL *)(pt0 - 1));
|
||||
SgFr_state(sg_fr)--; /* complete_in_use --> complete : compiled_in_use --> compiled */
|
||||
insert_into_global_sg_fr_list(sg_fr);
|
||||
goto failloop;
|
||||
}
|
||||
#endif /* LIMIT_TABLING */
|
||||
#ifdef FROZEN_STACKS /* TRAIL */
|
||||
/* avoid frozen segments */
|
||||
if (
|
||||
#ifdef YAPOR_SBA
|
||||
(ADDR) pt1 >= HeapTop
|
||||
#else
|
||||
IN_BETWEEN(LOCAL_TrailBase, pt1, (ADDR)CurrentTrailTop+MinTrailGap)
|
||||
#endif /* YAPOR_SBA */
|
||||
)
|
||||
{
|
||||
pt0 = (tr_fr_ptr) pt1;
|
||||
goto failloop;
|
||||
} else
|
||||
#endif /* FROZEN_STACKS */
|
||||
if (IN_BETWEEN(H0,pt1,HR)) {
|
||||
if (IsAttVar(pt1)) {
|
||||
goto failloop;
|
||||
} else if (*pt1 == (CELL)FunctorBigInt) {
|
||||
Yap_CleanOpaqueVariable(pt1);
|
||||
goto failloop;
|
||||
}
|
||||
}
|
||||
#ifdef FROZEN_STACKS /* TRAIL */
|
||||
/* don't reset frozen variables */
|
||||
if (pt0 < TR_FZ)
|
||||
goto failloop;
|
||||
#endif
|
||||
flags = *pt1;
|
||||
#if MULTIPLE_STACKS
|
||||
if (FlagOn(DBClMask, flags)) {
|
||||
DBRef dbr = DBStructFlagsToDBStruct(pt1);
|
||||
int erase;
|
||||
|
||||
LOCK(dbr->lock);
|
||||
DEC_DBREF_COUNT(dbr);
|
||||
erase = (dbr->Flags & ErasedMask) && (dbr->ref_count == 0);
|
||||
UNLOCK(dbr->lock);
|
||||
if (erase) {
|
||||
saveregs();
|
||||
Yap_ErDBE(dbr);
|
||||
setregs();
|
||||
}
|
||||
} else {
|
||||
if (flags & LogUpdMask) {
|
||||
if (flags & IndexMask) {
|
||||
LogUpdIndex *cl = ClauseFlagsToLogUpdIndex(pt1);
|
||||
int erase;
|
||||
#if PARALLEL_YAP
|
||||
PredEntry *ap = cl->ClPred;
|
||||
#endif
|
||||
|
||||
PELOCK(8,ap);
|
||||
DEC_CLREF_COUNT(cl);
|
||||
erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
|
||||
if (erase) {
|
||||
saveregs();
|
||||
/* at this point,
|
||||
we are the only ones accessing the clause,
|
||||
hence we don't need to have a lock it */
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else if (cl->ClFlags & DirtyMask) {
|
||||
saveregs();
|
||||
/* at this point,
|
||||
we are the only ones accessing the clause,
|
||||
hence we don't need to have a lock it */
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
UNLOCK(ap->PELock);
|
||||
} else {
|
||||
LogUpdClause *cl = ClauseFlagsToLogUpdClause(pt1);
|
||||
int erase;
|
||||
#if PARALLEL_YAP
|
||||
PredEntry *ap = cl->ClPred;
|
||||
#endif
|
||||
/* BB support */
|
||||
if (ap) {
|
||||
|
||||
PELOCK(9,ap);
|
||||
DEC_CLREF_COUNT(cl);
|
||||
erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
|
||||
if (erase) {
|
||||
saveregs();
|
||||
/* at this point,
|
||||
we are the only ones accessing the clause,
|
||||
hence we don't need to have a lock it */
|
||||
Yap_ErLogUpdCl(cl);
|
||||
setregs();
|
||||
}
|
||||
UNLOCK(ap->PELock);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DynamicClause *cl = ClauseFlagsToDynamicClause(pt1);
|
||||
int erase;
|
||||
|
||||
LOCK(cl->ClLock);
|
||||
DEC_CLREF_COUNT(cl);
|
||||
erase = (cl->ClFlags & ErasedMask) && !(cl->ClRefCount);
|
||||
UNLOCK(cl->ClLock);
|
||||
if (erase) {
|
||||
saveregs();
|
||||
/* at this point,
|
||||
we are the only ones accessing the clause,
|
||||
hence we don't need to have a lock it */
|
||||
Yap_ErCl(cl);
|
||||
setregs();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
ResetFlag(InUseMask, flags);
|
||||
*pt1 = flags;
|
||||
if (FlagOn((ErasedMask|DirtyMask), flags)) {
|
||||
if (FlagOn(DBClMask, flags)) {
|
||||
saveregs();
|
||||
Yap_ErDBE(DBStructFlagsToDBStruct(pt1));
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
if (flags & LogUpdMask) {
|
||||
if (flags & IndexMask) {
|
||||
if (FlagOn(ErasedMask, flags)) {
|
||||
Yap_ErLogUpdIndex(ClauseFlagsToLogUpdIndex(pt1));
|
||||
} else {
|
||||
Yap_CleanUpIndex(ClauseFlagsToLogUpdIndex(pt1));
|
||||
}
|
||||
} else {
|
||||
Yap_ErLogUpdCl(ClauseFlagsToLogUpdClause(pt1));
|
||||
}
|
||||
} else {
|
||||
Yap_ErCl(ClauseFlagsToDynamicClause(pt1));
|
||||
}
|
||||
setregs();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
goto failloop;
|
||||
}
|
||||
#ifdef MULTI_ASSIGNMENT_VARIABLES
|
||||
else /* if (IsApplTerm(d1)) */ {
|
||||
CELL *pt = RepAppl(d1);
|
||||
/* AbsAppl means */
|
||||
/* multi-assignment variable */
|
||||
/* so the next cell is the old value */
|
||||
#ifdef FROZEN_STACKS
|
||||
--pt0;
|
||||
pt[0] = TrailVal(pt0);
|
||||
#else
|
||||
pt[0] = TrailTerm(pt0-1);
|
||||
pt0 -= 2;
|
||||
#endif /* FROZEN_STACKS */
|
||||
goto failloop;
|
||||
}
|
||||
#endif
|
||||
ENDD(d1);
|
||||
ENDCACHE_TR();
|
||||
}
|
||||
|
||||
#ifdef COROUTINING
|
||||
NoStackFail:
|
||||
BEGD(d0);
|
||||
#ifdef SHADOW_S
|
||||
Yap_REGS.S_ = SREG;
|
||||
#endif
|
||||
saveregs();
|
||||
d0 = interrupt_fail( PASS_REGS1 );
|
||||
setregs();
|
||||
#ifdef SHADOW_S
|
||||
SREG = Yap_REGS.S_;
|
||||
#endif
|
||||
if (!d0) FAIL();
|
||||
JMPNext();
|
||||
ENDD(d0);
|
||||
|
||||
#endif /* COROUTINING */
|
||||
ENDPBOp();
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,628 @@
|
|||
/************************************************************************\
|
||||
* Call C predicates instructions *
|
||||
\************************************************************************/
|
||||
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
BOp(call_cpred, Osbpp);
|
||||
#if __ANDROID__ && STRONG_DEBUG
|
||||
char *s; Atom name;
|
||||
if (PREG->y_u.Osbpp.p->ArityOfPE) {
|
||||
Functor f = PREG->y_u.Osbpp.p->FunctorOfPred;
|
||||
name = f->NameOfFE;
|
||||
} else {
|
||||
name = (Atom)(PREG->y_u.Osbpp.p->FunctorOfPred);
|
||||
}
|
||||
s = name->StrOfAE;
|
||||
|
||||
LOG( " %s ", s);
|
||||
#endif
|
||||
check_trail(TR);
|
||||
if (!(PREG->y_u.Osbpp.p->PredFlags & (SafePredFlag|NoTracePredFlag|HiddenPredFlag))) {
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackCCall, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
}
|
||||
do_c_call:
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
|
||||
#ifdef YAPOR_SBA
|
||||
if (YREG > (CELL *) top_b || YREG < HR) ASP = (CELL *)top_b;
|
||||
#else
|
||||
if (YREG > (CELL *) top_b) ASP = (CELL *)top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
else ASP = (CELL *)(((char *)YREG) + PREG->y_u.Osbpp.s);
|
||||
}
|
||||
#else
|
||||
SET_ASP(YREG, PREG->y_u.Osbpp.s);
|
||||
/* for slots to work */
|
||||
#endif /* FROZEN_STACKS */
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace)
|
||||
low_level_trace(enter_pred,PREG->y_u.Osbpp.p,XREGS+1);
|
||||
#endif /* LOW_LEVEL_TRACE */
|
||||
BEGD(d0);
|
||||
CPredicate f = PREG->y_u.Osbpp.p->cs.f_code;
|
||||
PREG = NEXTOP(PREG, Osbpp);
|
||||
saveregs();
|
||||
d0 = (f)(PASS_REGS1);
|
||||
setregs();
|
||||
#ifdef SHADOW_S
|
||||
SREG = Yap_REGS.S_;
|
||||
#endif
|
||||
if (!d0) {
|
||||
FAIL();
|
||||
}
|
||||
CACHE_A1();
|
||||
ENDD(d0);
|
||||
JMPNext();
|
||||
|
||||
NoStackCCall:
|
||||
PROCESS_INT(interrupt_call, do_c_call);
|
||||
|
||||
ENDBOp();
|
||||
|
||||
/* execute Label */
|
||||
BOp(execute_cpred, pp);
|
||||
check_trail(TR);
|
||||
{
|
||||
PredEntry *pt0;
|
||||
|
||||
BEGD(d0);
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
#ifndef NO_CHECKING
|
||||
check_stack(NoStackExecuteC, HR);
|
||||
do_executec:
|
||||
#endif
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
|
||||
#ifdef YAPOR_SBA
|
||||
if (YREG > (CELL *) top_b || YREG < HR) ASP = (CELL *)top_b;
|
||||
#else
|
||||
if (YREG > (CELL *) top_b) ASP = (CELL *)top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
else ASP = YREG+E_CB;
|
||||
}
|
||||
#else
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
/* for slots to work */
|
||||
#endif /* FROZEN_STACKS */
|
||||
pt0 = PREG->y_u.pp.p;
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
low_level_trace(enter_pred,pt0,XREGS+1);
|
||||
}
|
||||
#endif /* LOW_LEVEL_TRACE */
|
||||
CACHE_A1();
|
||||
BEGD(d0);
|
||||
d0 = (CELL)B;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
ENV_YREG[E_CB] = d0;
|
||||
ENDD(d0);
|
||||
#ifdef DEPTH_LIMIT
|
||||
if (DEPTH <= MkIntTerm(1)) {/* I assume Module==0 is prolog */
|
||||
if (pt0->ModuleOfPred) {
|
||||
if (DEPTH == MkIntTerm(0)) {
|
||||
FAIL();
|
||||
} else{
|
||||
DEPTH = RESET_DEPTH();
|
||||
}
|
||||
}
|
||||
} else if (pt0->ModuleOfPred) {
|
||||
DEPTH -= MkIntConstant(2);
|
||||
}
|
||||
#endif /* DEPTH_LIMIT */
|
||||
/* now call C-Code */
|
||||
{
|
||||
CPredicate f = PREG->y_u.pp.p->cs.f_code;
|
||||
yamop *oldPREG = PREG;
|
||||
saveregs();
|
||||
d0 = (f)(PASS_REGS1);
|
||||
setregs();
|
||||
#ifdef SHADOW_S
|
||||
SREG = Yap_REGS.S_;
|
||||
#endif
|
||||
if (!d0) {
|
||||
FAIL();
|
||||
}
|
||||
if (oldPREG == PREG) {
|
||||
/* we did not update PREG */
|
||||
/* we can proceed */
|
||||
PREG = CPREG;
|
||||
ENV_YREG = ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = ENV_YREG[E_DEPTH];
|
||||
#endif
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
} else {
|
||||
/* call the new code */
|
||||
CACHE_A1();
|
||||
}
|
||||
}
|
||||
JMPNext();
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
ENDD(d0);
|
||||
}
|
||||
|
||||
NoStackExecuteC:
|
||||
PROCESS_INT(interrupt_execute, do_executec);
|
||||
ENDBOp();
|
||||
|
||||
/* Like previous, the only difference is that we do not */
|
||||
/* trust the C-function we are calling and hence we must */
|
||||
/* guarantee that *all* machine registers are saved and */
|
||||
/* restored */
|
||||
BOp(call_usercpred, Osbpp);
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackUserCall, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
do_user_call:
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
low_level_trace(enter_pred,PREG->y_u.Osbpp.p,XREGS+1);
|
||||
}
|
||||
#endif /* LOW_LEVEL_TRACE */
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (YREG > (CELL *) top_b || YREG < HR) ASP = (CELL *) top_b;
|
||||
#else
|
||||
if (YREG > (CELL *) top_b) ASP = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
else ASP = (CELL *)(((char *)YREG) + PREG->y_u.Osbpp.s);
|
||||
}
|
||||
#else
|
||||
SET_ASP(YREG, PREG->y_u.Osbpp.s);
|
||||
/* for slots to work */
|
||||
#endif /* FROZEN_STACKS */
|
||||
{
|
||||
/* make sure that we can still have access to our old PREG after calling user defined goals and backtracking or failing */
|
||||
yamop *savedP;
|
||||
|
||||
LOCAL_PrologMode |= UserCCallMode;
|
||||
{
|
||||
PredEntry *p = PREG->y_u.Osbpp.p;
|
||||
|
||||
PREG = NEXTOP(PREG, Osbpp);
|
||||
savedP = PREG;
|
||||
saveregs();
|
||||
save_machine_regs();
|
||||
|
||||
SREG = (CELL *) YAP_Execute(p, p->cs.f_code);
|
||||
}
|
||||
setregs();
|
||||
LOCAL_PrologMode &= ~UserCCallMode;
|
||||
restore_machine_regs();
|
||||
PREG = savedP;
|
||||
}
|
||||
if (EX) {
|
||||
struct DB_TERM *exp = EX;
|
||||
EX = NULL;
|
||||
Yap_JumpToEnv(Yap_PopTermFromDB(exp));
|
||||
SREG = NULL;
|
||||
}
|
||||
if (!SREG) {
|
||||
FAIL();
|
||||
}
|
||||
/* in case we call Execute */
|
||||
YENV = ENV;
|
||||
YREG = ENV;
|
||||
JMPNext();
|
||||
|
||||
NoStackUserCall:
|
||||
PROCESS_INT(interrupt_call, do_user_call);
|
||||
|
||||
ENDBOp();
|
||||
|
||||
BOp(call_c_wfail, slpp);
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
low_level_trace(enter_pred,PREG->y_u.slpp.p,XREGS+1);
|
||||
}
|
||||
#endif /* LOW_LEVEL_TRACE */
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (YREG > (CELL *) top_b || YREG < HR) ASP = (CELL *) top_b;
|
||||
#else
|
||||
if (YREG > (CELL *) top_b) ASP = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
else {
|
||||
BEGD(d0);
|
||||
d0 = PREG->y_u.slpp.s;
|
||||
ASP = ((CELL *)YREG) + d0;
|
||||
ENDD(d0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (YREG > (CELL *) B)
|
||||
ASP = (CELL *) B;
|
||||
else {
|
||||
BEGD(d0);
|
||||
d0 = PREG->y_u.slpp.s;
|
||||
ASP = ((CELL *) YREG) + d0;
|
||||
ENDD(d0);
|
||||
}
|
||||
#endif /* FROZEN_STACKS */
|
||||
{
|
||||
CPredicate f = PREG->y_u.slpp.p->cs.f_code;
|
||||
saveregs();
|
||||
SREG = (CELL *)((f)(PASS_REGS1));
|
||||
setregs();
|
||||
}
|
||||
if (!SREG) {
|
||||
/* be careful about error handling */
|
||||
if (PREG != FAILCODE)
|
||||
PREG = PREG->y_u.slpp.l;
|
||||
} else {
|
||||
PREG = NEXTOP(PREG, slpp);
|
||||
}
|
||||
CACHE_A1();
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(try_c, OtapFs);
|
||||
#ifdef YAPOR
|
||||
CUT_wait_leftmost();
|
||||
#endif /* YAPOR */
|
||||
CACHE_Y(YREG);
|
||||
/* Alocate space for the cut_c structure*/
|
||||
CUT_C_PUSH(NEXTOP(NEXTOP(PREG,OtapFs),OtapFs),S_YREG);
|
||||
S_YREG = S_YREG - PREG->y_u.OtapFs.extra;
|
||||
store_args(PREG->y_u.OtapFs.s);
|
||||
store_yaam_regs(NEXTOP(PREG, OtapFs), 0);
|
||||
B = B_YREG;
|
||||
#ifdef YAPOR
|
||||
SCH_set_load(B_YREG);
|
||||
#endif /* YAPOR */
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
|
||||
TRYCC:
|
||||
ASP = (CELL *)B;
|
||||
{
|
||||
CPredicate f = (CPredicate)(PREG->y_u.OtapFs.f);
|
||||
saveregs();
|
||||
SREG = (CELL *) ((f) (PASS_REGS1));
|
||||
/* This last instruction changes B B*/
|
||||
while (POP_CHOICE_POINT(B)){
|
||||
cut_c_pop();
|
||||
}
|
||||
setregs();
|
||||
}
|
||||
if (!SREG) {
|
||||
/* Removes the cut functions from the stack
|
||||
without executing them because we have fail
|
||||
and not cuted the predicate*/
|
||||
while(POP_CHOICE_POINT(B))
|
||||
cut_c_pop();
|
||||
FAIL();
|
||||
}
|
||||
if ((CELL *) B == YREG && ASP != (CELL *) B) {
|
||||
/* as Luis says, the predicate that did the try C might
|
||||
* have left some data on the stack. We should preserve
|
||||
* it, unless the builtin also did cut */
|
||||
YREG = ASP;
|
||||
HBREG = PROTECT_FROZEN_H(B);
|
||||
SET_BB(B);
|
||||
}
|
||||
PREG = CPREG;
|
||||
YREG = ENV;
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(retry_c, OtapFs);
|
||||
#ifdef YAPOR
|
||||
CUT_wait_leftmost();
|
||||
#endif /* YAPOR */
|
||||
CACHE_Y(B);
|
||||
CPREG = B_YREG->cp_cp;
|
||||
ENV = B_YREG->cp_env;
|
||||
HR = PROTECT_FROZEN_H(B);
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH =B->cp_depth;
|
||||
#endif
|
||||
HBREG = HR;
|
||||
restore_args(PREG->y_u.OtapFs.s);
|
||||
ENDCACHE_Y();
|
||||
goto TRYCC;
|
||||
ENDBOp();
|
||||
|
||||
BOp(cut_c, OtapFs);
|
||||
/*This is a phantom instruction. This is not executed by the WAM*/
|
||||
#ifdef DEBUG
|
||||
/*If WAM executes this instruction, probably there's an error
|
||||
when we put this instruction, cut_c, after retry_c*/
|
||||
printf ("ERROR: Should not print this message FILE: absmi.c %d\n",__LINE__);
|
||||
#endif /*DEBUG*/
|
||||
ENDBOp();
|
||||
|
||||
BOp(try_userc, OtapFs);
|
||||
#ifdef YAPOR
|
||||
CUT_wait_leftmost();
|
||||
#endif /* YAPOR */
|
||||
CACHE_Y(YREG);
|
||||
/* Alocate space for the cut_c structure*/
|
||||
CUT_C_PUSH(NEXTOP(NEXTOP(PREG,OtapFs),OtapFs),S_YREG);
|
||||
S_YREG = S_YREG - PREG->y_u.OtapFs.extra;
|
||||
store_args(PREG->y_u.OtapFs.s);
|
||||
store_yaam_regs(NEXTOP(PREG, OtapFs), 0);
|
||||
B = B_YREG;
|
||||
#ifdef YAPOR
|
||||
SCH_set_load(B_YREG);
|
||||
#endif
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
LOCAL_PrologMode = UserCCallMode;
|
||||
ASP = YREG;
|
||||
saveregs();
|
||||
save_machine_regs();
|
||||
SREG = (CELL *) YAP_ExecuteFirst(PREG->y_u.OtapFs.p, (CPredicate)(PREG->y_u.OtapFs.f));
|
||||
EX = NULL;
|
||||
restore_machine_regs();
|
||||
setregs();
|
||||
LOCAL_PrologMode &= UserMode;
|
||||
if (!SREG) {
|
||||
FAIL();
|
||||
}
|
||||
if ((CELL *) B == YREG && ASP != (CELL *) B) {
|
||||
/* as Luis says, the predicate that did the try C might
|
||||
* have left some data on the stack. We should preserve
|
||||
* it, unless the builtin also did cut */
|
||||
YREG = ASP;
|
||||
HBREG = PROTECT_FROZEN_H(B);
|
||||
}
|
||||
PREG = CPREG;
|
||||
YREG = ENV;
|
||||
CACHE_A1();
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(retry_userc, OtapFs);
|
||||
#ifdef YAPOR
|
||||
CUT_wait_leftmost();
|
||||
#endif /* YAPOR */
|
||||
CACHE_Y(B);
|
||||
CPREG = B_YREG->cp_cp;
|
||||
ENV = B_YREG->cp_env;
|
||||
HR = PROTECT_FROZEN_H(B);
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH =B->cp_depth;
|
||||
#endif
|
||||
HBREG = HR;
|
||||
restore_args(PREG->y_u.OtapFs.s);
|
||||
ENDCACHE_Y();
|
||||
|
||||
LOCAL_PrologMode |= UserCCallMode;
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
saveregs();
|
||||
save_machine_regs();
|
||||
SREG = (CELL *) YAP_ExecuteNext(PREG->y_u.OtapFs.p, (CPredicate)(PREG->y_u.OtapFs.f));
|
||||
EX = NULL;
|
||||
restore_machine_regs();
|
||||
setregs();
|
||||
LOCAL_PrologMode &= ~UserCCallMode;
|
||||
if (!SREG) {
|
||||
/* Removes the cut functions from the stack
|
||||
without executing them because we have fail
|
||||
and not cuted the predicate*/
|
||||
while(POP_CHOICE_POINT(B))
|
||||
cut_c_pop();
|
||||
FAIL();
|
||||
}
|
||||
if ((CELL *) B == YREG && ASP != (CELL *) B) {
|
||||
/* as Luis says, the predicate that did the try C might
|
||||
* have left some data on the stack. We should preserve
|
||||
* it, unless the builtin also did cut */
|
||||
YREG = ASP;
|
||||
HBREG = PROTECT_FROZEN_H(B);
|
||||
}
|
||||
PREG = CPREG;
|
||||
YREG = ENV;
|
||||
CACHE_A1();
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(cut_userc, OtapFs);
|
||||
/*This is a phantom instruction. This is not executed by the WAM*/
|
||||
#ifdef DEBUG
|
||||
/*If WAM executes this instruction, probably there's an error
|
||||
when we put this instruction, cut_userc, after retry_userc*/
|
||||
printf ("ERROR: Should not print this message FILE: absmi.c %d\n",__LINE__);
|
||||
#endif /*DEBUG*/
|
||||
CACHE_A1();
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
|
||||
/************************************************************************\
|
||||
* support instructions *
|
||||
\************************************************************************/
|
||||
|
||||
BOp(lock_pred, e);
|
||||
{
|
||||
PredEntry *ap = PredFromDefCode(PREG);
|
||||
PELOCK(10,ap);
|
||||
PP = ap;
|
||||
if (!ap->cs.p_code.NOfClauses) {
|
||||
UNLOCKPE(11,ap);
|
||||
FAIL();
|
||||
}
|
||||
/*
|
||||
we do not lock access to the predicate,
|
||||
we must take extra care here
|
||||
*/
|
||||
if (ap->cs.p_code.NOfClauses > 1 &&
|
||||
!(ap->PredFlags & IndexedPredFlag)) {
|
||||
/* update ASP before calling IPred */
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
saveregs();
|
||||
Yap_IPred(ap, 0, CP);
|
||||
/* IPred can generate errors, it thus must get rid of the lock itself */
|
||||
setregs();
|
||||
CACHE_A1();
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
}
|
||||
PREG = ap->cs.p_code.TrueCodeOfPred;
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(index_pred, e);
|
||||
{
|
||||
PredEntry *ap = PredFromDefCode(PREG);
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
/*
|
||||
we do not lock access to the predicate,
|
||||
we must take extra care here
|
||||
*/
|
||||
if (!PP) {
|
||||
PELOCK(11,ap);
|
||||
}
|
||||
if (ap->OpcodeOfPred != INDEX_OPCODE) {
|
||||
/* someone was here before we were */
|
||||
if (!PP) {
|
||||
UNLOCKPE(11,ap);
|
||||
}
|
||||
PREG = ap->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
JMPNext();
|
||||
}
|
||||
#endif
|
||||
/* update ASP before calling IPred */
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
saveregs();
|
||||
Yap_IPred(ap, 0, CP);
|
||||
/* IPred can generate errors, it thus must get rid of the lock itself */
|
||||
setregs();
|
||||
CACHE_A1();
|
||||
PREG = ap->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (!PP)
|
||||
#endif
|
||||
UNLOCKPE(14,ap);
|
||||
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
#if THREADS
|
||||
BOp(thread_local, e);
|
||||
{
|
||||
PredEntry *ap = PredFromDefCode(PREG);
|
||||
ap = Yap_GetThreadPred(ap PASS_REGS);
|
||||
PREG = ap->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
#endif
|
||||
|
||||
BOp(expand_index, e);
|
||||
{
|
||||
PredEntry *pe = PredFromExpandCode(PREG);
|
||||
yamop *pt0;
|
||||
|
||||
/* update ASP before calling IPred */
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (!PP) {
|
||||
PELOCK(12,pe);
|
||||
}
|
||||
if (!same_lu_block(PREG_ADDR, PREG)) {
|
||||
PREG = *PREG_ADDR;
|
||||
if (!PP) {
|
||||
UNLOCKPE(15,pe);
|
||||
}
|
||||
JMPNext();
|
||||
}
|
||||
#endif
|
||||
#ifdef SHADOW_S
|
||||
S = SREG;
|
||||
#endif /* SHADOW_S */
|
||||
saveregs();
|
||||
pt0 = Yap_ExpandIndex(pe, 0);
|
||||
/* restart index */
|
||||
setregs();
|
||||
#ifdef SHADOW_S
|
||||
SREG = S;
|
||||
#endif /* SHADOW_S */
|
||||
PREG = pt0;
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (!PP) {
|
||||
UNLOCKPE(12,pe);
|
||||
}
|
||||
#endif
|
||||
JMPNext();
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
BOp(expand_clauses, sssllp);
|
||||
{
|
||||
PredEntry *pe = PREG->y_u.sssllp.p;
|
||||
yamop *pt0;
|
||||
|
||||
/* update ASP before calling IPred */
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP == NULL) {
|
||||
PELOCK(13,pe);
|
||||
}
|
||||
if (!same_lu_block(PREG_ADDR, PREG)) {
|
||||
PREG = *PREG_ADDR;
|
||||
if (!PP) {
|
||||
UNLOCKPE(16,pe);
|
||||
}
|
||||
JMPNext();
|
||||
}
|
||||
#endif
|
||||
saveregs();
|
||||
pt0 = Yap_ExpandIndex(pe, 0);
|
||||
/* restart index */
|
||||
setregs();
|
||||
PREG = pt0;
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (!PP) {
|
||||
UNLOCKPE(18,pe);
|
||||
}
|
||||
#endif
|
||||
JMPNext();
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
BOp(undef_p, e);
|
||||
/* save S for module name */
|
||||
saveregs();
|
||||
undef_goal( PASS_REGS1 );
|
||||
setregs();
|
||||
/* for profiler */
|
||||
CACHE_A1();
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(spy_pred, e);
|
||||
saveregs();
|
||||
spy_goal( PASS_REGS1 );
|
||||
setregs();
|
||||
CACHE_A1();
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,458 @@
|
|||
/************************************************************************\
|
||||
* Indexing in ARG1 *
|
||||
\************************************************************************/
|
||||
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
BOp(user_switch, lp);
|
||||
{
|
||||
yamop *new = Yap_udi_search(PREG->y_u.lp.p);
|
||||
if (!new) {
|
||||
PREG = PREG->y_u.lp.l;
|
||||
JMPNext();
|
||||
}
|
||||
PREG = new;
|
||||
JMPNext();
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
BOp(switch_on_type, llll);
|
||||
BEGD(d0);
|
||||
d0 = CACHED_A1();
|
||||
deref_head(d0, swt_unk);
|
||||
/* nonvar */
|
||||
swt_nvar:
|
||||
if (IsPairTerm(d0)) {
|
||||
/* pair */
|
||||
SREG = RepPair(d0);
|
||||
copy_jmp_address(PREG->y_u.llll.l1);
|
||||
PREG = PREG->y_u.llll.l1;
|
||||
JMPNext();
|
||||
}
|
||||
else if (!IsApplTerm(d0)) {
|
||||
/* constant */
|
||||
copy_jmp_address(PREG->y_u.llll.l2);
|
||||
PREG = PREG->y_u.llll.l2;
|
||||
I_R = d0;
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* appl */
|
||||
copy_jmp_address(PREG->y_u.llll.l3);
|
||||
PREG = PREG->y_u.llll.l3;
|
||||
SREG = RepAppl(d0);
|
||||
JMPNext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, swt_unk, swt_nvar);
|
||||
/* variable */
|
||||
copy_jmp_address(PREG->y_u.llll.l4);
|
||||
PREG = PREG->y_u.llll.l4;
|
||||
JMPNext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
/* specialised case where the arguments may be:
|
||||
* a list;
|
||||
* the empty list;
|
||||
* some other atom;
|
||||
* a variable;
|
||||
*
|
||||
*/
|
||||
BOp(switch_list_nl, ollll);
|
||||
ALWAYS_LOOKAHEAD(PREG->y_u.ollll.pop);
|
||||
BEGD(d0);
|
||||
d0 = CACHED_A1();
|
||||
#if UNIQUE_TAG_FOR_PAIRS
|
||||
deref_list_head(d0, swlnl_unk_p);
|
||||
swlnl_list_p:
|
||||
{
|
||||
#else
|
||||
deref_head(d0, swlnl_unk_p);
|
||||
/* non variable */
|
||||
swlnl_nvar_p:
|
||||
if (__builtin_expect(IsPairTerm(d0),1)) {
|
||||
/* pair */
|
||||
#endif
|
||||
copy_jmp_address(PREG->y_u.ollll.l1);
|
||||
PREG = PREG->y_u.ollll.l1;
|
||||
SREG = RepPair(d0);
|
||||
ALWAYS_GONext();
|
||||
}
|
||||
#if UNIQUE_TAG_FOR_PAIRS
|
||||
swlnl_nlist_p:
|
||||
#endif
|
||||
if (d0 == TermNil) {
|
||||
/* empty list */
|
||||
PREG = PREG->y_u.ollll.l2;
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* appl or constant */
|
||||
if (IsApplTerm(d0)) {
|
||||
copy_jmp_address(PREG->y_u.ollll.l3);
|
||||
PREG = PREG->y_u.ollll.l3;
|
||||
SREG = RepAppl(d0);
|
||||
JMPNext();
|
||||
} else {
|
||||
copy_jmp_address(PREG->y_u.ollll.l3);
|
||||
PREG = PREG->y_u.ollll.l3;
|
||||
I_R = d0;
|
||||
JMPNext();
|
||||
}
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
#if UNIQUE_TAG_FOR_PAIRS
|
||||
swlnl_unk_p:
|
||||
deref_list_body(d0, pt0, swlnl_list_p, swlnl_nlist_p);
|
||||
#else
|
||||
deref_body(d0, pt0, swlnl_unk_p, swlnl_nvar_p);
|
||||
#endif
|
||||
ENDP(pt0);
|
||||
/* variable */
|
||||
copy_jmp_address(PREG->y_u.ollll.l4);
|
||||
PREG = PREG->y_u.ollll.l4;
|
||||
JMPNext();
|
||||
ENDD(d0);
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
BOp(switch_on_arg_type, xllll);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xllll.x);
|
||||
deref_head(d0, arg_swt_unk);
|
||||
/* nonvar */
|
||||
arg_swt_nvar:
|
||||
if (IsPairTerm(d0)) {
|
||||
/* pair */
|
||||
copy_jmp_address(PREG->y_u.xllll.l1);
|
||||
PREG = PREG->y_u.xllll.l1;
|
||||
SREG = RepPair(d0);
|
||||
JMPNext();
|
||||
}
|
||||
else if (!IsApplTerm(d0)) {
|
||||
/* constant */
|
||||
copy_jmp_address(PREG->y_u.xllll.l2);
|
||||
PREG = PREG->y_u.xllll.l2;
|
||||
I_R = d0;
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* appl */
|
||||
copy_jmp_address(PREG->y_u.xllll.l3);
|
||||
PREG = PREG->y_u.xllll.l3;
|
||||
SREG = RepAppl(d0);
|
||||
JMPNext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, arg_swt_unk, arg_swt_nvar);
|
||||
/* variable */
|
||||
copy_jmp_address(PREG->y_u.xllll.l4);
|
||||
PREG = PREG->y_u.xllll.l4;
|
||||
JMPNext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
BOp(switch_on_sub_arg_type, sllll);
|
||||
BEGD(d0);
|
||||
d0 = SREG[PREG->y_u.sllll.s];
|
||||
deref_head(d0, sub_arg_swt_unk);
|
||||
/* nonvar */
|
||||
sub_arg_swt_nvar:
|
||||
if (IsPairTerm(d0)) {
|
||||
/* pair */
|
||||
copy_jmp_address(PREG->y_u.sllll.l1);
|
||||
PREG = PREG->y_u.sllll.l1;
|
||||
SREG = RepPair(d0);
|
||||
JMPNext();
|
||||
}
|
||||
else if (!IsApplTerm(d0)) {
|
||||
/* constant */
|
||||
copy_jmp_address(PREG->y_u.sllll.l2);
|
||||
PREG = PREG->y_u.sllll.l2;
|
||||
I_R = d0;
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* appl */
|
||||
copy_jmp_address(PREG->y_u.sllll.l3);
|
||||
PREG = PREG->y_u.sllll.l3;
|
||||
SREG = RepAppl(d0);
|
||||
JMPNext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, sub_arg_swt_unk, sub_arg_swt_nvar);
|
||||
/* variable */
|
||||
copy_jmp_address(PREG->y_u.sllll.l4);
|
||||
PREG = PREG->y_u.sllll.l4;
|
||||
JMPNext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
BOp(jump_if_var, l);
|
||||
BEGD(d0);
|
||||
d0 = CACHED_A1();
|
||||
deref_head(d0, jump_if_unk);
|
||||
/* non var */
|
||||
jump0_if_nonvar:
|
||||
PREG = NEXTOP(PREG, l);
|
||||
JMPNext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, jump_if_unk, jump0_if_nonvar);
|
||||
/* variable */
|
||||
copy_jmp_address(PREG->y_u.l.l);
|
||||
PREG = PREG->y_u.l.l;
|
||||
ENDP(pt0);
|
||||
JMPNext();
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
BOp(jump_if_nonvar, xll);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xll.x);
|
||||
deref_head(d0, jump2_if_unk);
|
||||
/* non var */
|
||||
jump2_if_nonvar:
|
||||
copy_jmp_address(PREG->y_u.xll.l1);
|
||||
PREG = PREG->y_u.xll.l1;
|
||||
JMPNext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, jump2_if_unk, jump2_if_nonvar);
|
||||
/* variable */
|
||||
PREG = NEXTOP(PREG, xll);
|
||||
ENDP(pt0);
|
||||
JMPNext();
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
BOp(if_not_then, clll);
|
||||
BEGD(d0);
|
||||
d0 = CACHED_A1();
|
||||
deref_head(d0, if_n_unk);
|
||||
if_n_nvar:
|
||||
/* not variable */
|
||||
if (d0 == PREG->y_u.clll.c) {
|
||||
/* equal to test value */
|
||||
copy_jmp_address(PREG->y_u.clll.l2);
|
||||
PREG = PREG->y_u.clll.l2;
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* different from test value */
|
||||
/* the case to optimise */
|
||||
copy_jmp_address(PREG->y_u.clll.l1);
|
||||
PREG = PREG->y_u.clll.l1;
|
||||
JMPNext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, if_n_unk, if_n_nvar);
|
||||
ENDP(pt0);
|
||||
/* variable */
|
||||
copy_jmp_address(PREG->y_u.clll.l3);
|
||||
PREG = PREG->y_u.clll.l3;
|
||||
JMPNext();
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
/************************************************************************\
|
||||
* Indexing on ARG1 *
|
||||
\************************************************************************/
|
||||
|
||||
#define HASH_SHIFT 6
|
||||
|
||||
BOp(switch_on_func, sssl);
|
||||
BEGD(d1);
|
||||
d1 = *SREG++;
|
||||
/* we use a very simple hash function to find elements in a
|
||||
* switch table */
|
||||
{
|
||||
CELL
|
||||
/* first, calculate the mask */
|
||||
Mask = (PREG->y_u.sssl.s - 1) << 1, /* next, calculate the hash function */
|
||||
hash = d1 >> (HASH_SHIFT - 1) & Mask;
|
||||
CELL *base;
|
||||
|
||||
base = (CELL *)PREG->y_u.sssl.l;
|
||||
/* PREG now points at the beginning of the hash table */
|
||||
BEGP(pt0);
|
||||
/* pt0 will always point at the item */
|
||||
pt0 = base + hash;
|
||||
BEGD(d0);
|
||||
d0 = pt0[0];
|
||||
/* a match happens either if we found the value, or if we
|
||||
* found an empty slot */
|
||||
if (d0 == d1 || d0 == 0) {
|
||||
copy_jmp_addressa(pt0+1);
|
||||
PREG = (yamop *) (pt0[1]);
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* ooops, collision, look for other items */
|
||||
register CELL d = ((d1 | 1) << 1) & Mask;
|
||||
|
||||
while (1) {
|
||||
hash = (hash + d) & Mask;
|
||||
pt0 = base + hash;
|
||||
d0 = pt0[0];
|
||||
if (d0 == d1 || d0 == 0) {
|
||||
copy_jmp_addressa(pt0+1);
|
||||
PREG = (yamop *) pt0[1];
|
||||
JMPNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
ENDD(d0);
|
||||
ENDP(pt0);
|
||||
}
|
||||
ENDD(d1);
|
||||
ENDBOp();
|
||||
|
||||
BOp(switch_on_cons, sssl);
|
||||
BEGD(d1);
|
||||
d1 = I_R;
|
||||
/* we use a very simple hash function to find elements in a
|
||||
* switch table */
|
||||
{
|
||||
CELL
|
||||
/* first, calculate the mask */
|
||||
Mask = (PREG->y_u.sssl.s - 1) << 1, /* next, calculate the hash function */
|
||||
hash = d1 >> (HASH_SHIFT - 1) & Mask;
|
||||
CELL *base;
|
||||
|
||||
base = (CELL *)PREG->y_u.sssl.l;
|
||||
/* PREG now points at the beginning of the hash table */
|
||||
BEGP(pt0);
|
||||
/* pt0 will always point at the item */
|
||||
pt0 = base + hash;
|
||||
BEGD(d0);
|
||||
d0 = pt0[0];
|
||||
/* a match happens either if we found the value, or if we
|
||||
* found an empty slot */
|
||||
if (d0 == d1 || d0 == 0) {
|
||||
copy_jmp_addressa(pt0+1);
|
||||
PREG = (yamop *) (pt0[1]);
|
||||
JMPNext();
|
||||
}
|
||||
else {
|
||||
/* ooops, collision, look for other items */
|
||||
register CELL d = ((d1 | 1) << 1) & Mask;
|
||||
|
||||
while (1) {
|
||||
hash = (hash + d) & Mask;
|
||||
pt0 = base + hash;
|
||||
d0 = pt0[0];
|
||||
if (d0 == d1 || d0 == 0) {
|
||||
copy_jmp_addressa(pt0+1);
|
||||
PREG = (yamop *) pt0[1];
|
||||
JMPNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
ENDD(d0);
|
||||
ENDP(pt0);
|
||||
}
|
||||
ENDD(d1);
|
||||
ENDBOp();
|
||||
|
||||
BOp(go_on_func, sssl);
|
||||
BEGD(d0);
|
||||
{
|
||||
CELL *pt = (CELL *)(PREG->y_u.sssl.l);
|
||||
|
||||
d0 = *SREG++;
|
||||
if (d0 == pt[0]) {
|
||||
copy_jmp_addressa(pt+1);
|
||||
PREG = (yamop *) pt[1];
|
||||
JMPNext();
|
||||
} else {
|
||||
copy_jmp_addressa(pt+3);
|
||||
PREG = (yamop *) pt[3];
|
||||
JMPNext();
|
||||
}
|
||||
}
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
BOp(go_on_cons, sssl);
|
||||
BEGD(d0);
|
||||
{
|
||||
CELL *pt = (CELL *)(PREG->y_u.sssl.l);
|
||||
|
||||
d0 = I_R;
|
||||
if (d0 == pt[0]) {
|
||||
copy_jmp_addressa(pt+1);
|
||||
PREG = (yamop *) pt[1];
|
||||
JMPNext();
|
||||
} else {
|
||||
copy_jmp_addressa(pt+3);
|
||||
PREG = (yamop *) pt[3];
|
||||
JMPNext();
|
||||
}
|
||||
}
|
||||
ENDD(d0);
|
||||
ENDBOp();
|
||||
|
||||
BOp(if_func, sssl);
|
||||
BEGD(d1);
|
||||
BEGP(pt0);
|
||||
pt0 = (CELL *) PREG->y_u.sssl.l;
|
||||
d1 = *SREG++;
|
||||
while (pt0[0] != d1 && pt0[0] != (CELL)NULL ) {
|
||||
pt0 += 2;
|
||||
}
|
||||
copy_jmp_addressa(pt0+1);
|
||||
PREG = (yamop *) (pt0[1]);
|
||||
JMPNext();
|
||||
ENDP(pt0);
|
||||
ENDD(d1);
|
||||
ENDBOp();
|
||||
|
||||
BOp(if_cons, sssl);
|
||||
BEGD(d1);
|
||||
BEGP(pt0);
|
||||
pt0 = (CELL *) PREG->y_u.sssl.l;
|
||||
d1 = I_R;
|
||||
while (pt0[0] != d1 && pt0[0] != 0L ) {
|
||||
pt0 += 2;
|
||||
}
|
||||
copy_jmp_addressa(pt0+1);
|
||||
PREG = (yamop *) (pt0[1]);
|
||||
JMPNext();
|
||||
ENDP(pt0);
|
||||
ENDD(d1);
|
||||
ENDBOp();
|
||||
|
||||
Op(index_dbref, e);
|
||||
PREG = NEXTOP(PREG, e);
|
||||
I_R = AbsAppl(SREG-1);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
Op(index_blob, e);
|
||||
PREG = NEXTOP(PREG, e);
|
||||
I_R = Yap_DoubleP_key(SREG);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
Op(index_long, e);
|
||||
PREG = NEXTOP(PREG, e);
|
||||
I_R = Yap_IntP_key(SREG);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,107 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_dl.c *
|
||||
* comments: dl based dynamic loaderr of external routines *
|
||||
* tested on i486-linuxelf *
|
||||
*************************************************************************/
|
||||
|
||||
#ifdef _AIX
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "yapio.h"
|
||||
#include "Foreign.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
/* not implemented */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static Int
|
||||
LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
|
||||
extern char *sys_errlist[ ];
|
||||
|
||||
/* load wants to follow the LIBRARY_PATH */
|
||||
if (ofiles->next != NULL || libs != NULL) {
|
||||
strcpy(LOCAL_ErrorSay," Load Failed: in AIX you must load a single object file");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if (!Yap_AbsoluteFileInBuffer(AtomName(ofiles->name), LOCAL_FileNameBuf, YAP_FILENAME_MAX, true)) {
|
||||
strcpy(LOCAL_ErrorSay, " Trying to open unexisting file in LoadForeign ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* In AIX, just call load and everything will go in */
|
||||
if ((*init_proc=((YapInitProc *)load(LOCAL_FileNameBuf,0,NULL))) == NULL) {
|
||||
strcpy(LOCAL_ErrorSay,sys_errlist[errno]);
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
#endif /* _AIX */
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_aout.c *
|
||||
* comments: aout based dynamic loader of external routines *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "yapio.h"
|
||||
#include "Foreign.h"
|
||||
|
||||
#ifdef A_OUT
|
||||
this code is no being maintained anymore
|
||||
#include <stdio.h>
|
||||
#if STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_FILE_H
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <a.out.h>
|
||||
|
||||
|
||||
|
||||
#define oktox(n) \
|
||||
(0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFREG&&0==access(n,X_OK))
|
||||
#define oktow(n) \
|
||||
(0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFDIR&&0==access(n,W_OK))
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
register char *cp, *cp2;
|
||||
struct stat stbuf;
|
||||
|
||||
|
||||
cp = (char *)getenv("PATH");
|
||||
if (cp == NULL)
|
||||
cp = ".:/usr/ucb:/bin:/usr/bin:/usr/local/bin";
|
||||
if (*GLOBAL_argv[0] == '/') {
|
||||
if (oktox(GLOBAL_argv[0])) {
|
||||
strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
|
||||
Yap_AbsoluteFileInBuffer(LOCAL_FileNameBuf, true);
|
||||
strncpy( GLOBAL_Executable, LOCAL_FileNameBuf, YAP_MAXPATHLEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (*cp == ':')
|
||||
cp++;
|
||||
for (; *cp;) {
|
||||
/*
|
||||
* copy over current directory and then append
|
||||
* argv[0]
|
||||
*/
|
||||
|
||||
for (cp2 = LOCAL_FileNameBuf; (*cp) != 0 && (*cp) != ':';)
|
||||
*cp2++ = *cp++;
|
||||
*cp2++ = '/';
|
||||
strcpy(cp2, GLOBAL_argv[0]);
|
||||
if (*cp)
|
||||
cp++;
|
||||
if (!oktox(LOCAL_FileNameBuf))
|
||||
continue;
|
||||
Yap_AbsoluteFileInBuffer(Yap_AbsoluteFileInBuffer(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
|
||||
return;
|
||||
}
|
||||
/* one last try for dual systems */
|
||||
strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
|
||||
Yap_AbsoluteFileInBuffer(Yap_AbsoluteFileInBuffer(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
|
||||
if (oktox(GLOBAL_Executable))
|
||||
return GLOBAL_Executable;
|
||||
else
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL,MkAtomTerm(Yap_LookupAtom(GLOBAL_Executable)),
|
||||
"cannot find file being executed");
|
||||
}
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
/* not implemented */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static int
|
||||
LoadForeign(StringList ofiles,
|
||||
StringList libs,
|
||||
char *proc_name,
|
||||
YapInitProc *init_proc)
|
||||
{
|
||||
char command[2*MAXPATHLEN];
|
||||
char o_files[1024]; /* list of objects we want to load
|
||||
*/
|
||||
char l_files[1024]; /* list of libraries we want to
|
||||
load */
|
||||
char tmp_buff[32] = "/tmp/YAP_TMP_XXXXXX"; /* used for
|
||||
mktemp */
|
||||
char *tfile; /* name of temporary file */
|
||||
int fildes; /* temp file descriptor */
|
||||
struct exec header; /* header for loaded file */
|
||||
unsigned long loadImageSize, firstloadImSz; /* size of image we will load */
|
||||
char *FCodeBase; /* where we load foreign code */
|
||||
|
||||
/*
|
||||
* put in a string the names of the files you want to load and of any
|
||||
* libraries you want to use
|
||||
*/
|
||||
/* files first */
|
||||
*o_files = '\0';
|
||||
{
|
||||
StringList tmp = ofiles;
|
||||
|
||||
while(tmp != NULL) {
|
||||
strcat(o_files," ");
|
||||
strcat(o_files,AtomName(tmp->name));
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
/* same_trick for libraries */
|
||||
*l_files = '\0';
|
||||
{
|
||||
StringList tmp = libs;
|
||||
|
||||
while(tmp != NULL) {
|
||||
strcat(l_files," ");
|
||||
strcat(l_files,AtomName(tmp->name));
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
/* next, create a temp file to serve as loader output */
|
||||
tfile = mktemp(tmp_buff);
|
||||
|
||||
/* prepare the magic */
|
||||
if (strlen(o_files) + strlen(l_files) + strlen(proc_name) +
|
||||
strlen(GLOBAL_Executable) > 2*MAXPATHLEN) {
|
||||
strcpy(LOCAL_ErrorSay, " too many parameters in load_foreign/3 ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
sprintf(command, "/usr/bin/ld -N -A %s -o %s -u _%s %s %s -lc",
|
||||
GLOBAL_Executable,
|
||||
tfile, proc_name, o_files, l_files);
|
||||
/* now, do the magic */
|
||||
if (system(command) != 0) {
|
||||
unlink(tfile);
|
||||
strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* now check the music has played */
|
||||
if ((fildes = open(tfile, O_RDONLY)) < 0) {
|
||||
strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* it did, get the mice */
|
||||
/* first, get the header */
|
||||
read(fildes, (char *) &header, sizeof(header));
|
||||
close(fildes);
|
||||
/* get the full size of what we need to load */
|
||||
loadImageSize = header.a_text + header.a_data + header.a_bss;
|
||||
/* add 16 just to play it safe */
|
||||
loadImageSize += 16;
|
||||
/* keep this copy */
|
||||
firstloadImSz = loadImageSize;
|
||||
/* now fetch the space we need */
|
||||
if (!(FCodeBase = Yap_AllocCodeSpace((int) loadImageSize))) {
|
||||
strcpy(LOCAL_ErrorSay," unable to allocate space for external code ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* now, a new incantation to load the new foreign code */
|
||||
sprintf(command, "/usr/bin/ld -N -A %s -T %lx -o %s -u _%s %s %s -lc",
|
||||
GLOBAL_Executable,
|
||||
(unsigned long) FCodeBase,
|
||||
tfile, proc_name, o_files, l_files);
|
||||
/* and do it */
|
||||
if (system(command) != 0) {
|
||||
unlink(tfile);
|
||||
strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if ((fildes = open(tfile, O_RDONLY)) < 0) {
|
||||
strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
read(fildes, (char *) &header, sizeof(header));
|
||||
loadImageSize = header.a_text + header.a_data + header.a_bss;
|
||||
if (firstloadImSz < loadImageSize) {
|
||||
strcpy(LOCAL_ErrorSay," miscalculation in load_foreign/3 ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* now search for our init function */
|
||||
{
|
||||
char entry_fun[256];
|
||||
struct nlist func_info[2];
|
||||
sprintf(entry_fun, "_%s", proc_name);
|
||||
func_info[0].n_un.n_name = entry_fun;
|
||||
func_info[1].n_un.n_name = NULL;
|
||||
if (nlist(tfile, func_info) == -1) {
|
||||
strcpy(LOCAL_ErrorSay," in nlist(3) ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if (func_info[0].n_type == 0) {
|
||||
strcpy(LOCAL_ErrorSay," in nlist(3) ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
*init_proc = (YapInitProc)(func_info[0].n_value);
|
||||
}
|
||||
/* ok, we got our init point */
|
||||
/* now read our text */
|
||||
lseek(fildes, (long)(N_TXTOFF(header)), 0);
|
||||
{
|
||||
unsigned int u1 = header.a_text + header.a_data;
|
||||
read(fildes, (char *) FCodeBase, u1);
|
||||
/* zero the BSS segment */
|
||||
while (u1 < loadImageSize)
|
||||
FCodeBase[u1++] = 0;
|
||||
}
|
||||
close(fildes);
|
||||
unlink(tfile);
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_coff.c *
|
||||
* comments: coff based dynamic loader of external routines *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "Foreign.h"
|
||||
|
||||
#ifdef COFF
|
||||
this code is no being maintained anymore
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <a.out.h>
|
||||
|
||||
#define oktox(n) \
|
||||
(0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFREG&&0==access(n,X_OK))
|
||||
#define oktow(n) \
|
||||
(0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFDIR&&0==access(n,W_OK))
|
||||
|
||||
#ifdef mips
|
||||
#define MAXSECTIONS 100
|
||||
#else
|
||||
#define MAXSECTIONS 20
|
||||
#endif /* mips */
|
||||
|
||||
#ifdef sgi
|
||||
#include <symbol.h>
|
||||
#endif /* sgi */
|
||||
|
||||
#define N_TXTOFF(x) (sizeof(struct filehdr)+(x).f_opthdr+(x).f_nscns*sizeof(struct scnhdr))
|
||||
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
register char *cp, *cp2;
|
||||
struct stat stbuf;
|
||||
|
||||
|
||||
cp = (char *)getenv("PATH");
|
||||
if (cp == NULL)
|
||||
cp = ".:/usr/ucb:/bin:/usr/bin:/usr/local/bin";
|
||||
if (*GLOBAL_argv[0] == '/') {
|
||||
if (oktox(GLOBAL_argv[0])) {
|
||||
strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
|
||||
Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (*cp == ':')
|
||||
cp++;
|
||||
for (; *cp;) {
|
||||
/*
|
||||
* copy over current directory and then append
|
||||
* argv[0]
|
||||
*/
|
||||
|
||||
for (cp2 = LOCAL_FileNameBuf; (*cp) != 0 && (*cp) != ':';)
|
||||
*cp2++ = *cp++;
|
||||
*cp2++ = '/';
|
||||
strcpy(cp2, GLOBAL_argv[0]);
|
||||
if (*cp)
|
||||
cp++;
|
||||
if (!oktox(LOCAL_FileNameBuf))
|
||||
continue;
|
||||
Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
|
||||
return GLOBAL_Executable;
|
||||
}
|
||||
/* one last try for dual systems */
|
||||
strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
|
||||
Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
|
||||
if (oktox(GLOBAL_Executable))
|
||||
return GLOBAL_Executable;
|
||||
else
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL,MkAtomTerm(Yap_LookupAtom(GLOBAL_Executable)),
|
||||
"cannot find file being executed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
/* not implemented */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static Int
|
||||
LoadForeign(StringList ofiles,
|
||||
StringList libs,
|
||||
char *proc_name,
|
||||
YapInitProc *init_proc)
|
||||
{
|
||||
char command[2*MAXPATHLEN];
|
||||
char o_files[1024]; /* list of objects we want to load
|
||||
*/
|
||||
char l_files[1024]; /* list of libraries we want to
|
||||
load */
|
||||
char tmp_buff[32] = "/tmp/YAP_TMP_XXXXXX"; /* used for
|
||||
mktemp */
|
||||
char *tfile; /* name of temporary file */
|
||||
int fildes; /* temp file descriptor */
|
||||
struct aouthdr sysHeader;
|
||||
struct filehdr fileHeader;
|
||||
struct scnhdr sectionHeader[MAXSECTIONS];
|
||||
struct exec header; /* header for loaded file */
|
||||
unsigned long loadImageSize, firstloadImSz; /* size of image we will load */
|
||||
char *FCodeBase; /* where we load foreign code */
|
||||
|
||||
/*
|
||||
* put in a string the names of the files you want to load and of any
|
||||
* libraries you want to use
|
||||
*/
|
||||
/* files first */
|
||||
*o_files = '\0';
|
||||
{
|
||||
StringList tmp = ofiles;
|
||||
|
||||
while(tmp != NULL) {
|
||||
strcat(o_files," ");
|
||||
strcat(o_files,AtomName(tmp->name));
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
/* same_trick for libraries */
|
||||
*l_files = '\0';
|
||||
{
|
||||
StringList tmp = libs;
|
||||
|
||||
while(tmp != NULL) {
|
||||
strcat(l_files," ");
|
||||
strcat(l_files,AtomName(tmp->name));
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
/* next, create a temp file to serve as loader output */
|
||||
tfile = mktemp(tmp_buff);
|
||||
|
||||
/* prepare the magic */
|
||||
if (strlen(o_files) + strlen(l_files) + strlen(proc_name) +
|
||||
strlen(GLOBAL_Executable) > 2*MAXPATHLEN) {
|
||||
strcpy(LOCAL_ErrorSay, " too many parameters in load_foreign/3 ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
sprintf(command, "/usr/bin/ld -N -A %s -o %s %s %s -lc",
|
||||
GLOBAL_Executable,
|
||||
tfile, o_files, l_files);
|
||||
/* now, do the magic */
|
||||
if (system(command) != 0) {
|
||||
unlink(tfile);
|
||||
strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* now check the music has played */
|
||||
if ((fildes = open(tfile, O_RDONLY)) < 0) {
|
||||
strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* it did, get the mice */
|
||||
/* first, get the header */
|
||||
read(fildes, (char *) &fileHeader, sizeof(fileHeader));
|
||||
read(fildes, (char *) &sysHeader, sizeof(sysHeader));
|
||||
{ int i;
|
||||
for (i = 0; i < fileHeader.f_nscns; i++)
|
||||
read(fildes, (char *) §ionHeader[i],
|
||||
sizeof(*sectionHeader));
|
||||
}
|
||||
close(fildes);
|
||||
/* get the full size of what we need to load */
|
||||
loadImageSize = sysHeader.tsize + sysHeader.dsize + sysHeader.bsize;
|
||||
#ifdef mips
|
||||
/* add an extra page in mips machines */
|
||||
loadImageSize += 4095 + 16;
|
||||
#else
|
||||
/* add 16 just to play it safe */
|
||||
loadImageSize += 16;
|
||||
#endif
|
||||
/* keep this copy */
|
||||
firstloadImSz = loadImageSize;
|
||||
/* now fetch the space we need */
|
||||
if (!(FCodeBase = Yap_AllocCodeSpace((int) loadImageSize))
|
||||
#ifdef pyr
|
||||
|| activate_code(ForeignCodeBase, u1)
|
||||
#endif /* pyr */
|
||||
) {
|
||||
strcpy(LOCAL_ErrorSay," unable to allocate space for external code ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
#ifdef mips
|
||||
FCodeBase = (char *) (Unsigned(FCodeBase + PAGESIZE - 1) & ~(PAGESIZE - 1));
|
||||
#endif
|
||||
|
||||
/* now, a new incantation to load the new foreign code */
|
||||
#ifdef convex
|
||||
/* No -N flag in the Convex loader */
|
||||
/* -T option does not want MallocBase bit set */
|
||||
sprintf(command, "ld -x -A %s -T %lx -o %s -u %s %s %s -lc",
|
||||
ostabf,
|
||||
((unsigned long) (((unsigned long) (ForeignCodeBase)) &
|
||||
((unsigned long) (~Yap_HeapBase))
|
||||
)
|
||||
), tfile, entry_point, o_files, l_files);
|
||||
#else
|
||||
#ifdef mips
|
||||
sprintf(command, "ld -systype bsd43 -N -A %s -T %lx -o %s -u %s %s %s -lc",
|
||||
ostabf,
|
||||
(unsigned long) ForeignCodeBase,
|
||||
tfile, entry_point, o_files, l_files);
|
||||
#else
|
||||
sprintf(command, "ld -N -A %s -T %lx -o %s -e %s -u _%s %s -lc",
|
||||
ostabf,
|
||||
(unsigned long) ForeignCodeBase,
|
||||
tfile, entry_point, o_files, l_files);
|
||||
#endif /* mips */
|
||||
#endif /* convex */
|
||||
/* and do it */
|
||||
if (system(command) != 0) {
|
||||
unlink(tfile);
|
||||
strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if ((fildes = open(tfile, O_RDONLY)) < 0) {
|
||||
strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
read(fildes, (char *) &fileHeader, sizeof(fileHeader));
|
||||
read(fildes, (char *) &sysHeader, sizeof(sysHeader));
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fileHeader.f_nscns; i++)
|
||||
read(fildes, (char *) §ionHeader[i], sizeof(*sectionHeader));
|
||||
}
|
||||
loadImageSize = sysHeader.tsize + sysHeader.dsize + sysHeader.bsize;
|
||||
if (firstloadImSz < loadImageSize) {
|
||||
strcpy(LOCAL_ErrorSay," miscalculation in load_foreign/3 ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
/* now search for our init function */
|
||||
{
|
||||
char entry_fun[256];
|
||||
struct nlist func_info[2];
|
||||
#if defined(mips) || defined(I386)
|
||||
char NAME1[128], NAME2[128];
|
||||
func_info[0].n_name = NAME1;
|
||||
func_info[1].n_name = NAME2;
|
||||
#endif /* COFF */
|
||||
sprintf(entry_fun, "_%s", proc_name);
|
||||
func_info[0].n_name = entry_fun;
|
||||
func_info[1].n_name = NULL;
|
||||
if (nlist(tfile, func_info) == -1) {
|
||||
strcpy(LOCAL_ErrorSay," in nlist(3) ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if (func_info[0].n_type == 0) {
|
||||
strcpy(LOCAL_ErrorSay," in nlist(3) ");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
*init_proc = (YapInitProc)(func_info[0].n_value);
|
||||
}
|
||||
/* ok, we got our init point */
|
||||
/* now read our text */
|
||||
lseek(fildes, (long)(N_TXTOFF(header)), 0);
|
||||
{
|
||||
unsigned int u1 = header.a_text + header.a_data;
|
||||
read(fildes, (char *) FCodeBase, u1);
|
||||
/* zero the BSS segment */
|
||||
while (u1 < loadImageSize)
|
||||
FCodeBase[u1++] = 0;
|
||||
}
|
||||
close(fildes);
|
||||
unlink(tfile);
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_dl.c *
|
||||
* comments: dl based dynamic loaderr of external routines *
|
||||
* tested on i486-linuxelf *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "yapio.h"
|
||||
#include "Foreign.h"
|
||||
|
||||
#if LOAD_DL
|
||||
|
||||
// use SWI-Prolog code if all else fails
|
||||
char *
|
||||
findExecutable(const char *av0, char *buffer);
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#if defined(__APPLE__)
|
||||
#include <mach-o/dyld.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef void (*prismf)(void);
|
||||
|
||||
/* only works for dlls */
|
||||
int
|
||||
Yap_CallFunctionByName(const char *thing_string);
|
||||
|
||||
int
|
||||
Yap_CallFunctionByName(const char *thing_string)
|
||||
{
|
||||
void * handle = dlopen(NULL, RTLD_LAZY
|
||||
#ifndef __CYGWIN__
|
||||
#ifdef RTLD_NOLOAD
|
||||
| RTLD_NOLOAD
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
// you could do RTLD_NOW as well. shouldn't matter
|
||||
if (!handle) {
|
||||
CACHE_REGS
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, ARG1, "Dynamic linking on main module : %s\n", dlerror());
|
||||
}
|
||||
prismf * addr = (prismf *)dlsym(handle, thing_string);
|
||||
if (addr)
|
||||
(*addr)();
|
||||
dlclose(handle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
#if HAVE_GETEXECNAME
|
||||
// Solaris
|
||||
return getexecname();
|
||||
#elif __APPLE__
|
||||
char path[1024];
|
||||
char *buf;
|
||||
|
||||
uint32_t size = sizeof(path);
|
||||
if (!_NSGetExecutablePath(path, &size)) {
|
||||
size_t sz = strlen(path);
|
||||
buf = malloc(sz+1);
|
||||
strncpy(buf, path, sz);
|
||||
return buf;
|
||||
} else {
|
||||
char *rc = malloc(size+1);
|
||||
if (_NSGetExecutablePath(rc, &size) == 0)
|
||||
return "yap";
|
||||
return rc;
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
enum { BUFFERSIZE = 1024 };
|
||||
char *buf = malloc(BUFFERSIZE);
|
||||
ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)-1);
|
||||
|
||||
if (len != -1) {
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
// follow through to standard method
|
||||
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
enum { BUFFERSIZE = 1024 };
|
||||
char *buf = malloc(BUFFERSIZE);
|
||||
ssize_t len = readlink("/proc/curproc/file", buf, sizeof(buf)-1);
|
||||
|
||||
if (len != -1) {
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
int mib[4];
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PATHNAME;
|
||||
mib[3] = -1; // current process
|
||||
size_t cb = BUFFERSIZE;
|
||||
sysctl(mib, 4, buf, &cb, NULL, 0);
|
||||
// follow through to standard method
|
||||
#endif
|
||||
return
|
||||
NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
CACHE_REGS
|
||||
int dlflag;
|
||||
void *out;
|
||||
|
||||
|
||||
if (flags & EAGER_LOADING)
|
||||
dlflag = RTLD_NOW;
|
||||
else
|
||||
dlflag = RTLD_LAZY;
|
||||
if (flags & GLOBAL_LOADING)
|
||||
dlflag |= RTLD_GLOBAL;
|
||||
#ifndef __CYGWIN__
|
||||
else
|
||||
dlflag |= RTLD_LOCAL;
|
||||
#endif
|
||||
if (!Yap_TrueFileName(file, LOCAL_FileNameBuf, true)){
|
||||
/* use LD_LIBRARY_PATH */
|
||||
strncpy(LOCAL_FileNameBuf,file, YAP_FILENAME_MAX-1);
|
||||
strncat(LOCAL_FileNameBuf,".", YAP_FILENAME_MAX-1);
|
||||
strncat(LOCAL_FileNameBuf, "SO_EXT", YAP_FILENAME_MAX-1);
|
||||
}
|
||||
out = (void *)dlopen(LOCAL_FileNameBuf, flags);
|
||||
if (out == NULL) {
|
||||
char *m_os = dlerror();
|
||||
if (m_os) {
|
||||
LOCAL_ErrorMessage = dlerror();
|
||||
} else {
|
||||
LOCAL_ErrorMessage = "dlopen failed";
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
YapInitProc proc = (YapInitProc) dlsym(handle, f);
|
||||
if (!proc) {
|
||||
/* Yap_Error(SYSTEM_ERROR_INTERNAL, ARG1, "dlsym error %s\n", dlerror());*/
|
||||
return FALSE;
|
||||
}
|
||||
(*proc) ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
if ( dlclose(handle) < 0) {
|
||||
CACHE_REGS
|
||||
Yap_Error(SYSTEM_ERROR_INTERNAL, ARG1, "dlclose error %s\n", dlerror());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static Int
|
||||
LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
CACHE_REGS
|
||||
|
||||
while (libs) {
|
||||
if (!Yap_TrueFileName((char *)AtomName(libs->name), LOCAL_FileNameBuf, true)) {
|
||||
/* use LD_LIBRARY_PATH */
|
||||
strncpy(LOCAL_FileNameBuf, (char *)AtomName(libs->name), YAP_FILENAME_MAX);
|
||||
}
|
||||
|
||||
#ifdef __osf__
|
||||
if((libs->handle=dlopen(LOCAL_FileNameBuf,RTLD_LAZY)) == NULL)
|
||||
#else
|
||||
if((libs->handle=dlopen(LOCAL_FileNameBuf,RTLD_LAZY|RTLD_GLOBAL)) == NULL)
|
||||
#endif
|
||||
{
|
||||
strcpy(LOCAL_ErrorSay,dlerror());
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
libs = libs->next;
|
||||
}
|
||||
|
||||
while (ofiles) {
|
||||
void *handle;
|
||||
|
||||
/* load libraries first so that their symbols are available to
|
||||
other routines */
|
||||
|
||||
/* dlopen wants to follow the LD_CONFIG_PATH */
|
||||
if (!Yap_TrueFileName((char *)AtomName(ofiles->name), LOCAL_FileNameBuf, TRUE)) {
|
||||
strcpy(LOCAL_ErrorSay, "%% Trying to open unexisting file in LoadForeign");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
#ifdef __osf__
|
||||
if((handle=dlopen(LOCAL_FileNameBuf,RTLD_LAZY)) == 0)
|
||||
#else
|
||||
if((handle=dlopen(LOCAL_FileNameBuf,RTLD_LAZY|RTLD_GLOBAL)) == 0)
|
||||
#endif
|
||||
{
|
||||
fprintf(stderr,"dlopen of image %s failed: %s\n", LOCAL_FileNameBuf, dlerror());
|
||||
/* strcpy(LOCAL_ErrorSay,dlerror());*/
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
ofiles->handle = handle;
|
||||
|
||||
if (proc_name && !*init_proc)
|
||||
*init_proc = (YapInitProc) dlsym(handle,proc_name);
|
||||
|
||||
ofiles = ofiles->next;
|
||||
}
|
||||
|
||||
if(! *init_proc) {
|
||||
strcpy(LOCAL_ErrorSay,"Could not locate initialization routine");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
ForeignObj *f_code;
|
||||
|
||||
f_code = ForeignCodeLoaded;
|
||||
while (f_code != NULL) {
|
||||
StringList objs, libs, old;
|
||||
ForeignObj *of_code = f_code;
|
||||
|
||||
objs = f_code->objs;
|
||||
while (objs != NULL) {
|
||||
old = objs;
|
||||
if (dlclose(objs->handle) != 0)
|
||||
return; /* ERROR */
|
||||
objs = objs->next;
|
||||
Yap_FreeCodeSpace((ADDR)old);
|
||||
}
|
||||
libs = f_code->libs;
|
||||
while (libs != NULL) {
|
||||
old = libs;
|
||||
if (dlclose(libs->handle) != 0)
|
||||
return; /* ERROR */
|
||||
libs = libs->next;
|
||||
Yap_FreeCodeSpace((ADDR)old);
|
||||
}
|
||||
f_code = f_code->next;
|
||||
Yap_FreeCodeSpace((ADDR)of_code);
|
||||
}
|
||||
/*
|
||||
make sure that we don't try to close foreign code several times, eg,
|
||||
from within an error handler
|
||||
*/
|
||||
ForeignCodeLoaded = NULL;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if SIMICS
|
||||
|
||||
void dlopen(void)
|
||||
{
|
||||
}
|
||||
|
||||
void dlclose(void)
|
||||
{
|
||||
}
|
||||
|
||||
void dlsym(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_dld.c *
|
||||
* comments: dld based dynamic loaderr of external routines *
|
||||
* tested on i486-linuxaout *
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(linux) && !defined(__ELF__) && !defined(__LCC__)
|
||||
|
||||
#include "Foreign.h"
|
||||
#include <dld.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
this code is no being maintained anymore
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
/* use dld_find_executable */
|
||||
char *res;
|
||||
if(name != NULL && (res=dld_find_executable(name))) {
|
||||
return GLOBAL_Executable;
|
||||
} else {
|
||||
return "yap";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
/* not implemented */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static int
|
||||
LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
int error;
|
||||
|
||||
if(firstTime) {
|
||||
error = dld_init(GLOBAL_Executable);
|
||||
if(error) {
|
||||
strcpy(LOCAL_ErrorSay,dld_strerror(error));
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
firstTime=0;
|
||||
}
|
||||
|
||||
while (ofiles) {
|
||||
if((error=dld_link(AtomName(ofiles->name))) !=0) {
|
||||
strcpy(LOCAL_ErrorSay,dld_strerror(error));
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
ofiles = ofiles->next;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: handle libs */
|
||||
*init_proc = (YapInitProc) dld_get_func(proc_name);
|
||||
if(! *init_proc) {
|
||||
strcpy(LOCAL_ErrorSay,"Could not locate initialization routine");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if(!dld_function_executable_p(proc_name)) {
|
||||
char **undefs = dld_list_undefined_sym();
|
||||
char **p = undefs;
|
||||
int k = dld_undefined_sym_count;
|
||||
strcpy(LOCAL_ErrorSay,"Could not resolve all symbols");
|
||||
while(k) {
|
||||
YP_printf("[undefined symbol %s]\n",*p++);
|
||||
--k;
|
||||
}
|
||||
free(undefs);
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,153 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_dl.c *
|
||||
* comments: dl based dynamic loader of external routines *
|
||||
* tested on i486-linuxelf *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "yapio.h"
|
||||
#include "Foreign.h"
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
enum { BUFFERSIZE = 1024 };
|
||||
char *buf = malloc(BUFFERSIZE);
|
||||
|
||||
if (!GetModuleFileName(NULL, buf, BUFFERSIZE-1))
|
||||
return NULL;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
void *ptr= (void *)LoadLibrary(file);
|
||||
if (!ptr) {
|
||||
CACHE_REGS
|
||||
LOCAL_ErrorSay[0]='\0';
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LOCAL_ErrorSay, 256,
|
||||
NULL);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
YapInitProc proc = (YapInitProc)GetProcAddress((HMODULE)handle, f);
|
||||
if (!proc)
|
||||
return FALSE;
|
||||
(*proc)();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return FreeLibrary((HMODULE)handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static Int
|
||||
LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
CACHE_REGS
|
||||
while (ofiles) {
|
||||
HINSTANCE handle;
|
||||
|
||||
if (Yap_TrueFileName(AtomName(ofiles->name), LOCAL_FileNameBuf, TRUE) &&
|
||||
(handle=LoadLibrary(LOCAL_FileNameBuf)) != 0)
|
||||
{
|
||||
LOCAL_ErrorSay[0]=~'\0';
|
||||
if (*init_proc == NULL)
|
||||
*init_proc = (YapInitProc)GetProcAddress((HMODULE)handle, proc_name);
|
||||
} else {
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LOCAL_ErrorSay, 256,
|
||||
NULL);
|
||||
//fprintf(stderr,"WinError: %s\n", LOCAL_ErrorSay);
|
||||
}
|
||||
ofiles = ofiles->next;
|
||||
}
|
||||
/* load libraries first so that their symbols are available to
|
||||
other routines */
|
||||
while (libs) {
|
||||
HINSTANCE handle;
|
||||
const char * s = AtomName(libs->name);
|
||||
|
||||
if (s[0] == '-') {
|
||||
strcat(LOCAL_FileNameBuf,s+2);
|
||||
strcat(LOCAL_FileNameBuf,".dll");
|
||||
} else {
|
||||
strcpy(LOCAL_FileNameBuf,s);
|
||||
}
|
||||
|
||||
if((handle=LoadLibrary(LOCAL_FileNameBuf)) == 0)
|
||||
{
|
||||
/* strcpy(LOCAL_ErrorSay,dlerror());*/
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
if (*init_proc == NULL)
|
||||
*init_proc = (YapInitProc)GetProcAddress((HMODULE)handle, proc_name);
|
||||
|
||||
libs = libs->next;
|
||||
}
|
||||
|
||||
if(*init_proc == NULL) {
|
||||
strcpy(LOCAL_ErrorSay,"Could not locate initialization routine");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_dyld.c *
|
||||
* comments: dyld based dynamic loaderr of external routines *
|
||||
* tested on MacOS *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "yapio.h"
|
||||
#include "Foreign.h"
|
||||
|
||||
#if LOAD_DYLD
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Code originally from Rex A. Dieter's posting in comp.sys.next.programmer
|
||||
and from dynload_next.c in the Python sources
|
||||
*/
|
||||
#import <mach-o/dyld.h>
|
||||
|
||||
|
||||
|
||||
static char *
|
||||
mydlerror(void)
|
||||
{
|
||||
char *errString;
|
||||
switch(LOCAL_dl_errno) {
|
||||
default:
|
||||
case NSObjectFileImageFailure:
|
||||
case NSObjectFileImageFormat:
|
||||
/* for these a message is printed on stderr by dyld */
|
||||
errString = "Can't create object file image";
|
||||
break;
|
||||
case NSObjectFileImageSuccess:
|
||||
errString = NULL;
|
||||
break;
|
||||
case NSObjectFileImageInappropriateFile:
|
||||
errString = "Inappropriate file type for dynamic loading";
|
||||
break;
|
||||
case NSObjectFileImageArch:
|
||||
errString = "Wrong CPU type in object file";
|
||||
break;
|
||||
case NSObjectFileImageAccess:
|
||||
errString = "Can't read object file (no access)";
|
||||
break;
|
||||
}
|
||||
return(errString);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
char path[1024];
|
||||
uint32_t size = sizeof(path);
|
||||
if (_NSGetExecutablePath(path, &size) == 0) {
|
||||
char *rc = malloc(size+1);
|
||||
strncpy(rc, path, size);
|
||||
return rc;
|
||||
} else {
|
||||
char *rc = malloc(size+1);
|
||||
if (_NSGetExecutablePath(rc, &size) == 0)
|
||||
return "yap";
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
mydlopen(char *path)
|
||||
{
|
||||
int dyld_result;
|
||||
NSObjectFileImage ofile;
|
||||
NSModule handle = NULL;
|
||||
dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
|
||||
if (dyld_result != NSObjectFileImageSuccess) {
|
||||
LOCAL_dl_errno = dyld_result;
|
||||
} else {
|
||||
/* NSLinkModule will cause the run to abort on any link error's */
|
||||
/* not very friendly but the error recovery functionality is limited */
|
||||
handle = NSLinkModule(ofile, path, TRUE);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void *
|
||||
mydlsym(char *symbol)
|
||||
{
|
||||
void *addr;
|
||||
char funcname[256];
|
||||
|
||||
#if HAVE_SNPRINTF
|
||||
snprintf(funcname, sizeof(funcname), "_%.200s", symbol);
|
||||
#else
|
||||
sprintf(funcname, "_%.200s", symbol);
|
||||
#endif
|
||||
if (NSIsSymbolNameDefined(funcname))
|
||||
addr = NSAddressOfSymbol(NSLookupAndBindSymbol(funcname));
|
||||
else
|
||||
addr = NULL;
|
||||
return addr;
|
||||
}
|
||||
|
||||
static int
|
||||
mydlclose(void *handle)
|
||||
{
|
||||
NSUnLinkModule(handle, NSUNLINKMODULE_OPTION_NONE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
return (void *)mydlopen(file);
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
YapInitProc proc = (YapInitProc) mydlsym(f);
|
||||
if (!proc)
|
||||
return FALSE;
|
||||
(*proc)();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return mydlclose(handle);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
static Int
|
||||
LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
|
||||
while (ofiles) {
|
||||
void *handle;
|
||||
|
||||
/* mydlopen wants to follow the LD_CONFIG_PATH */
|
||||
if (!Yap_TrueFileName(AtomName(ofiles->name), LOCAL_FileNameBuf, TRUE)) {
|
||||
strcpy(LOCAL_ErrorSay, "%% Trying to open unexisting file in LoadForeign");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
if((handle=mydlopen(LOCAL_FileNameBuf)) == 0)
|
||||
{
|
||||
fprintf(stderr,"calling dlopen with error %s\n", mydlerror());
|
||||
/* strcpy(LOCAL_ErrorSay,dlerror());*/
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
ofiles->handle = handle;
|
||||
|
||||
ofiles = ofiles->next;
|
||||
}
|
||||
/* load libraries first so that their symbols are available to
|
||||
other routines */
|
||||
while (libs) {
|
||||
char *s = AtomName(lib->name);
|
||||
|
||||
if (ls[0] == '-') {
|
||||
strcpy(LOCAL_FileNameBuf,"lib");
|
||||
strcat(LOCAL_FileNameBuf,s+2);
|
||||
strcat(LOCAL_FileNameBuf,".so");
|
||||
} else {
|
||||
strcpy(LOCAL_FileNameBuf,s);
|
||||
}
|
||||
|
||||
if((libs->handle=mydlopen(LOCAL_FileNameBuf)) == NULL)
|
||||
{
|
||||
strcpy(LOCAL_ErrorSay,mydlerror());
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
libs = libs->next;
|
||||
}
|
||||
|
||||
*init_proc = (YapInitProc) mydlsym(proc_name);
|
||||
|
||||
if(! *init_proc) {
|
||||
strcpy(LOCAL_ErrorSay,"Could not locate initialization routine");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
ForeignObj *f_code;
|
||||
|
||||
f_code = ForeignCodeLoaded;
|
||||
while (f_code != NULL) {
|
||||
StringList objs, libs;
|
||||
|
||||
objs = f_code->objs;
|
||||
while (objs != NULL) {
|
||||
if (mydlclose(objs->handle) != 0)
|
||||
return; /* ERROR */
|
||||
objs = objs->next;
|
||||
}
|
||||
libs = f_code->libs;
|
||||
while (libs != NULL) {
|
||||
if (mydlclose(libs->handle) != 0)
|
||||
return; /* ERROR */
|
||||
objs = libs->next;
|
||||
}
|
||||
f_code = f_code->next;
|
||||
}
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,274 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_foreign.c *
|
||||
* comments: dynamic loader of external routines *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%.2";
|
||||
#endif
|
||||
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "yapio.h"
|
||||
#include "YapText.h"
|
||||
#include <stdlib.h>
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "Foreign.h"
|
||||
|
||||
#if _WIN32 || defined(__CYGWIN__)
|
||||
#ifndef SO_EXT
|
||||
#define SO_EXT "dll"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Int p_load_foreign( USES_REGS1 );
|
||||
|
||||
Int
|
||||
p_load_foreign( USES_REGS1 )
|
||||
{
|
||||
StringList ofiles = NULL;
|
||||
StringList libs = NULL;
|
||||
char *InitProcName;
|
||||
YapInitProc InitProc = NULL;
|
||||
Term t, t1;
|
||||
StringList new;
|
||||
Int returncode = FALSE;
|
||||
yhandle_t CurSlot = Yap_StartSlots();
|
||||
|
||||
strcpy(LOCAL_ErrorSay,"Invalid arguments");
|
||||
// Yap_DebugPlWrite(ARG1); printf("%s\n", " \n");
|
||||
//Yap_DebugPlWrite(ARG2); printf("%s\n", " \n");
|
||||
//ap_DebugPlWrite(ARG3); printf("%s\n", " \n");
|
||||
|
||||
/* collect the list of object files */
|
||||
t = Deref(ARG1);
|
||||
while(1) {
|
||||
if (t == TermNil) break;
|
||||
t1 = HeadOfTerm(t);
|
||||
t = TailOfTerm(t);
|
||||
new = (StringList) Yap_AllocCodeSpace(sizeof(StringListItem));
|
||||
new->next = ofiles;
|
||||
new->name = AtomOfTerm(t1);
|
||||
ofiles = new;
|
||||
}
|
||||
|
||||
/* collect the list of library files */
|
||||
t = Deref(ARG2);
|
||||
while(1) {
|
||||
if (t == TermNil) break;
|
||||
t1 = HeadOfTerm(t);
|
||||
t = TailOfTerm(t);
|
||||
new = (StringList) Yap_AllocCodeSpace(sizeof(StringListItem));
|
||||
new->next = libs;
|
||||
new->name = AtomOfTerm(t1);
|
||||
libs = new;
|
||||
}
|
||||
|
||||
/* get the initialization function name */
|
||||
t1 = Deref(ARG3);
|
||||
InitProcName = (char *)RepAtom(AtomOfTerm(t1))->StrOfAE;
|
||||
|
||||
/* call the OS specific function for dynamic loading */
|
||||
if(Yap_LoadForeign(ofiles,libs,InitProcName,&InitProc)==LOAD_SUCCEEDED) {
|
||||
Yap_StartSlots( );
|
||||
(*InitProc)();
|
||||
Yap_CloseSlots(CurSlot);
|
||||
returncode = TRUE;
|
||||
}
|
||||
|
||||
/* I should recover space if load foreign fails */
|
||||
if (returncode == TRUE) {
|
||||
ForeignObj *f_code = (ForeignObj *)Yap_AllocCodeSpace(sizeof(ForeignObj));
|
||||
f_code->objs = ofiles;
|
||||
f_code->libs = libs;
|
||||
f_code->f = AtomOfTerm(t1);
|
||||
f_code->next = ForeignCodeLoaded;
|
||||
f_code->module = CurrentModule;
|
||||
ForeignCodeLoaded = f_code;
|
||||
} else {
|
||||
while (ofiles) {
|
||||
new = ofiles->next;
|
||||
Yap_FreeCodeSpace((ADDR)ofiles);
|
||||
ofiles = new;
|
||||
}
|
||||
while (libs) {
|
||||
new = libs->next;
|
||||
Yap_FreeCodeSpace((ADDR)libs);
|
||||
libs = new;
|
||||
}
|
||||
}
|
||||
return returncode;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_open_shared_object( USES_REGS1 ) {
|
||||
Term t = Deref(ARG1);
|
||||
Term tflags = Deref(ARG2);
|
||||
char *s;
|
||||
void *handle;
|
||||
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,t,"open_shared_object/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM,t,"open_shared_object/3");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (IsVarTerm(tflags)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,tflags,"open_shared_object/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsIntegerTerm(tflags)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER,tflags,"open_shared_object/3");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s = (char *)RepAtom(AtomOfTerm(t))->StrOfAE;
|
||||
if ((handle = Yap_LoadForeignFile(s, IntegerOfTerm(tflags)))==NULL) {
|
||||
Yap_Error(EXISTENCE_ERROR_SOURCE_SINK,t,"open_shared_object_failed for %s with %s\n", s, LOCAL_ErrorSay);
|
||||
return FALSE;
|
||||
} else {
|
||||
return Yap_unify(MkIntegerTerm((Int)handle),ARG3);
|
||||
}
|
||||
}
|
||||
|
||||
static Int
|
||||
p_close_shared_object( USES_REGS1 ) {
|
||||
Term t = Deref(ARG1);
|
||||
void *handle;
|
||||
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,t,"close_shared_object/1");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsIntegerTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER,t,"close_shared_object/1");
|
||||
return FALSE;
|
||||
}
|
||||
handle = (char *)IntegerOfTerm(t);
|
||||
|
||||
return Yap_CloseForeignFile(handle);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_call_shared_object_function( USES_REGS1 ) {
|
||||
Term t = Deref(ARG1);
|
||||
Term tfunc = Deref(ARG2);
|
||||
Term tmod;
|
||||
void *handle;
|
||||
Term OldCurrentModule = CurrentModule;
|
||||
Int res;
|
||||
|
||||
tmod = CurrentModule;
|
||||
restart:
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,t,"call_shared_object_function/2");
|
||||
return FALSE;
|
||||
} else if (IsApplTerm(t)) {
|
||||
Functor fun = FunctorOfTerm(t);
|
||||
if (fun == FunctorModule) {
|
||||
tmod = ArgOfTerm(1, t);
|
||||
if (IsVarTerm(tmod) ) {
|
||||
Yap_Error(INSTANTIATION_ERROR,t,"call_shared_object_function/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(tmod) ) {
|
||||
Yap_Error(TYPE_ERROR_ATOM,ARG1,"call_shared_object_function/2");
|
||||
return FALSE;
|
||||
}
|
||||
t = ArgOfTerm(2, t);
|
||||
goto restart;
|
||||
}
|
||||
} else if (!IsIntegerTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_INTEGER,t,"call_shared_object_function/2");
|
||||
return FALSE;
|
||||
}
|
||||
handle = (void *)IntegerOfTerm(t);
|
||||
if (IsVarTerm(tfunc)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,t,"call_shared_object_function/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(tfunc)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM,t,"call_shared_object_function/2/3");
|
||||
return FALSE;
|
||||
}
|
||||
CurrentModule = tmod;
|
||||
res = Yap_CallForeignFile(handle, (char *)RepAtom(AtomOfTerm(tfunc))->StrOfAE);
|
||||
CurrentModule = OldCurrentModule;
|
||||
return res;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_obj_suffix( USES_REGS1 ) {
|
||||
return Yap_unify(Yap_CharsToListOfCodes(SO_EXT, ENC_ISO_LATIN1 PASS_REGS),ARG1);
|
||||
}
|
||||
|
||||
static Int
|
||||
p_open_shared_objects( USES_REGS1 ) {
|
||||
#ifdef SO_EXT
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitLoadForeign( void )
|
||||
{
|
||||
Yap_InitCPred("$load_foreign_files", 3, p_load_foreign, SafePredFlag|SyncPredFlag);
|
||||
Yap_InitCPred("$open_shared_objects", 0, p_open_shared_objects, SafePredFlag);
|
||||
Yap_InitCPred("$open_shared_object", 3, p_open_shared_object, SyncPredFlag);
|
||||
Yap_InitCPred("close_shared_object", 1, p_close_shared_object, SyncPredFlag|SafePredFlag);
|
||||
/** @pred close_shared_object(+ _Handle_)
|
||||
|
||||
Detach the shared object identified by _Handle_.
|
||||
|
||||
|
||||
*/
|
||||
Yap_InitCPred("$call_shared_object_function", 2, p_call_shared_object_function, SyncPredFlag);
|
||||
Yap_InitCPred("$obj_suffix", 1, p_obj_suffix, SafePredFlag);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ReOpenLoadForeign(void)
|
||||
{
|
||||
CACHE_REGS
|
||||
ForeignObj *f_code = ForeignCodeLoaded;
|
||||
Term OldModule = CurrentModule;
|
||||
|
||||
while (f_code != NULL) {
|
||||
YapInitProc InitProc = NULL;
|
||||
|
||||
CurrentModule = f_code->module;
|
||||
if(Yap_ReLoadForeign(f_code->objs,f_code->libs,(char *)RepAtom(f_code->f)->StrOfAE,&InitProc)==LOAD_SUCCEEDED) {
|
||||
if (InitProc)
|
||||
(*InitProc)();
|
||||
}
|
||||
f_code = f_code->next;
|
||||
}
|
||||
CurrentModule = OldModule;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: load_none.c *
|
||||
* comments: dummy dynamic loaderr of external routines *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Foreign.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef NO_DYN
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
char *
|
||||
Yap_FindExecutable(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LoadForeign(file_name,proc_name,init_proc) dynamically loads a foreign
|
||||
* code file and locates an initialization routine
|
||||
*/
|
||||
static Int
|
||||
LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
strcpy(LOCAL_ErrorSay,"load_foreign not supported in this version of Yap");
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
/* not implemented */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign(void)
|
||||
{
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return(LoadForeign(ofiles,libs, proc_name, init_proc));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "yapio.h"
|
||||
#include "Foreign.h"
|
||||
|
||||
#if LOAD_SHL
|
||||
|
||||
#include <dl.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* YAP_FindExecutable(argv[0]) should be called on yap initialization to
|
||||
* locate the executable of Yap
|
||||
*/
|
||||
|
||||
char * Yap_FindExecutable(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
Yap_LoadForeignFile(char *file, int flags)
|
||||
{
|
||||
/* not implemented */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CallForeignFile(void *handle, char *f)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
Yap_CloseForeignFile(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
|
||||
* code files and libraries and locates an initialization routine
|
||||
*/
|
||||
|
||||
static Int
|
||||
LoadForeign( StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc )
|
||||
{
|
||||
|
||||
/* *init_proc is initialized to NULL in load_foreign.c */
|
||||
int init_missing = -1;
|
||||
|
||||
int n, i;
|
||||
struct shl_symbol *p;
|
||||
|
||||
while( ofiles ) {
|
||||
int valid_fname;
|
||||
|
||||
/* shl_load wants to follow the LD_CONFIG_PATH */
|
||||
valid_fname = Yap_TrueFileName( AtomName(ofiles->name), LOCAL_FileNameBuf, TRUE );
|
||||
|
||||
if( !valid_fname ) {
|
||||
strcpy( LOCAL_ErrorSay, "%% Trying to open non-existing file in LoadForeign" );
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
ofiles->handle = Yap_AllocCodeSpace( sizeof(shl_t) );
|
||||
*(shl_t *)ofiles->handle = shl_load( LOCAL_FileNameBuf, BIND_DEFERRED, 0 );
|
||||
if( *(shl_t *)ofiles->handle == NULL ) {
|
||||
strncpy( LOCAL_ErrorSay, strerror(errno), MAX_ERROR_MSG_SIZE );
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
if( init_missing ) {
|
||||
init_missing = shl_findsym( ofiles->handle, proc_name,
|
||||
TYPE_PROCEDURE, init_proc );
|
||||
}
|
||||
|
||||
ofiles = ofiles->next;
|
||||
}
|
||||
|
||||
if( init_missing ) {
|
||||
strcpy( LOCAL_ErrorSay, "Could not locate initialization routine" );
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
while( libs ) {
|
||||
char *s = AtomName(lib->s);
|
||||
|
||||
if( s[0] == '-' ) {
|
||||
strcpy( LOCAL_FileNameBuf, "lib" );
|
||||
strcat( LOCAL_FileNameBuf, s+2 );
|
||||
strcat( LOCAL_FileNameBuf, ".sl" );
|
||||
}
|
||||
else {
|
||||
strcpy( LOCAL_FileNameBuf, s );
|
||||
}
|
||||
|
||||
*(shl_t *)libs->handle = shl_load( LOCAL_FileNameBuf, BIND_DEFERRED, 0 );
|
||||
if( *(shl_t *)libs->handle == NULL ) {
|
||||
strncpy( LOCAL_ErrorSay, strerror(errno), MAX_ERROR_MSG_SIZE );
|
||||
return LOAD_FAILLED;
|
||||
}
|
||||
|
||||
libs = libs->next;
|
||||
}
|
||||
|
||||
return LOAD_SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
Int
|
||||
Yap_LoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
return LoadForeign(ofiles, libs, proc_name, init_proc);
|
||||
}
|
||||
|
||||
void
|
||||
Yap_ShutdownLoadForeign( void )
|
||||
{
|
||||
ForeignObj *f_code;
|
||||
int err;
|
||||
|
||||
f_code = ForeignCodeLoaded;
|
||||
while( f_code != NULL ) {
|
||||
StringList objs, libs;
|
||||
|
||||
objs = f_code->objs;
|
||||
while( objs ) {
|
||||
err = shl_unload( *(shl_t *)objs->handle );
|
||||
if( err ) {
|
||||
/* dunno how to properly report an error here */
|
||||
perror( NULL );
|
||||
return;
|
||||
}
|
||||
Yap_FreeCodeSpace( objs->handle );
|
||||
objs = objs->next;
|
||||
}
|
||||
|
||||
libs = f_code->libs;
|
||||
while( libs ) {
|
||||
err = shl_unload( *(shl_t *)libs->handle );
|
||||
if( err ) {
|
||||
/* dunno how to properly report an error here */
|
||||
perror( NULL );
|
||||
return;
|
||||
}
|
||||
Yap_FreeCodeSpace( libs->handle );
|
||||
libs = libs->next;
|
||||
}
|
||||
f_code = f_code->next;
|
||||
}
|
||||
}
|
||||
|
||||
Int
|
||||
Yap_ReLoadForeign(StringList ofiles, StringList libs,
|
||||
char *proc_name, YapInitProc *init_proc)
|
||||
{
|
||||
ShutdownLoadForeign();
|
||||
return( LoadForeign( ofiles, libs, proc_name, init_proc ) );
|
||||
}
|
||||
|
||||
/*
|
||||
dunno what this one is supposed to do, no load_* defines it
|
||||
void ReOpenLoadForeign(void);
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,771 @@
|
|||
/************************************************************************\
|
||||
* Logical Updates *
|
||||
\************************************************************************/
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
/************************************************************************\
|
||||
* Logical Updates *
|
||||
\************************************************************************/
|
||||
|
||||
/* enter logical pred */
|
||||
BOp(enter_lu_pred, Illss);
|
||||
check_trail(TR);
|
||||
/* mark the indexing code */
|
||||
{
|
||||
LogUpdIndex *cl = PREG->y_u.Illss.I;
|
||||
PredEntry *ap = cl->ClPred;
|
||||
|
||||
if (!cl) { FAIL(); } /* in case the index is empty */
|
||||
if (ap->LastCallOfPred != LUCALL_EXEC) {
|
||||
/*
|
||||
only increment time stamp if we are working on current time
|
||||
stamp
|
||||
*/
|
||||
if (ap->TimeStampOfPred >= TIMESTAMP_RESET)
|
||||
Yap_UpdateTimestamps(ap);
|
||||
ap->TimeStampOfPred++;
|
||||
ap->LastCallOfPred = LUCALL_EXEC;
|
||||
/* fprintf(stderr,"R %x--%d--%ul\n",ap,ap->TimeStampOfPred,ap->ArityOfPE);*/
|
||||
}
|
||||
*--YREG = MkIntegerTerm(ap->TimeStampOfPred);
|
||||
/* fprintf(stderr,"> %p/%p %d %d\n",cl,ap,ap->TimeStampOfPred,PREG->y_u.Illss.s);*/
|
||||
PREG = PREG->y_u.Illss.l1;
|
||||
/* indicate the indexing code is being used */
|
||||
#if MULTIPLE_STACKS
|
||||
/* just store a reference */
|
||||
INC_CLREF_COUNT(cl);
|
||||
TRAIL_CLREF(cl);
|
||||
#else
|
||||
if (!(cl->ClFlags & InUseMask)) {
|
||||
cl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(cl);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(profiled_retry_logical, OtaLl);
|
||||
check_trail(TR);
|
||||
{
|
||||
UInt timestamp;
|
||||
CACHE_Y(B);
|
||||
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP != PREG->y_u.OtaLl.d->ClPred) {
|
||||
if (PP) UNLOCKPE(15,PP);
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
PELOCK(15,PP);
|
||||
}
|
||||
#endif
|
||||
timestamp = IntegerOfTerm(((CELL *)(B_YREG+1))[PREG->y_u.OtaLl.s]);
|
||||
if (!VALID_TIMESTAMP(timestamp, PREG->y_u.OtaLl.d)) {
|
||||
/* jump to next instruction */
|
||||
PREG=PREG->y_u.OtaLl.n;
|
||||
JMPNext();
|
||||
}
|
||||
restore_yaam_regs(PREG->y_u.OtaLl.n);
|
||||
restore_args(PREG->y_u.OtaLl.s);
|
||||
LOCK(PREG->y_u.OtaLl.d->ClPred->StatisticsForPred->lock);
|
||||
PREG->y_u.OtaLl.d->ClPred->StatisticsForPred->NOfRetries++;
|
||||
UNLOCK(PREG->y_u.OtaLl.d->ClPred->StatisticsForPred->lock);
|
||||
#ifdef THREADS
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
#endif
|
||||
PREG = PREG->y_u.OtaLl.d->ClCode;
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
set_cut(S_YREG, B->cp_b);
|
||||
#else
|
||||
set_cut(S_YREG, B_YREG->cp_b);
|
||||
#endif /* FROZEN_STACKS */
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(profiled_trust_logical, OtILl);
|
||||
CACHE_Y(B);
|
||||
{
|
||||
LogUpdIndex *cl = PREG->y_u.OtILl.block;
|
||||
PredEntry *ap = cl->ClPred;
|
||||
LogUpdClause *lcl = PREG->y_u.OtILl.d;
|
||||
UInt timestamp = IntegerOfTerm(((CELL *)(B_YREG+1))[ap->ArityOfPE]);
|
||||
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP != ap) {
|
||||
if (PP) UNLOCKPE(16,PP);
|
||||
PP = ap;
|
||||
PELOCK(16,PP);
|
||||
}
|
||||
#endif
|
||||
if (!VALID_TIMESTAMP(timestamp, lcl)) {
|
||||
/* jump to next alternative */
|
||||
PREG = FAILCODE;
|
||||
} else {
|
||||
LOCK(ap->StatisticsForPred->lock);
|
||||
ap->StatisticsForPred->NOfRetries++;
|
||||
UNLOCK(ap->StatisticsForPred->lock);
|
||||
PREG = lcl->ClCode;
|
||||
}
|
||||
/* HEY, leave indexing block alone!! */
|
||||
/* check if we are the ones using this code */
|
||||
#if MULTIPLE_STACKS
|
||||
DEC_CLREF_COUNT(cl);
|
||||
/* clear the entry from the trail */
|
||||
B->cp_tr--;
|
||||
TR = B->cp_tr;
|
||||
/* actually get rid of the code */
|
||||
if (cl->ClRefCount == 0 && (cl->ClFlags & (ErasedMask|DirtyMask))) {
|
||||
if (PREG != FAILCODE) {
|
||||
/* I am the last one using this clause, hence I don't need a lock
|
||||
to dispose of it
|
||||
*/
|
||||
if (lcl->ClRefCount == 1) {
|
||||
/* make sure the clause isn't destroyed */
|
||||
/* always add an extra reference */
|
||||
INC_CLREF_COUNT(lcl);
|
||||
TRAIL_CLREF(lcl);
|
||||
}
|
||||
}
|
||||
if (cl->ClFlags & ErasedMask) {
|
||||
saveregs();
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
save_pc();
|
||||
}
|
||||
#else
|
||||
if (TrailTerm(B->cp_tr-1) == CLREF_TO_TRENTRY(cl) &&
|
||||
B->cp_tr != B->cp_b->cp_tr) {
|
||||
cl->ClFlags &= ~InUseMask;
|
||||
--B->cp_tr;
|
||||
#if FROZEN_STACKS
|
||||
if (B->cp_tr > TR_FZ)
|
||||
#endif
|
||||
{
|
||||
TR = B->cp_tr;
|
||||
}
|
||||
/* next, recover space for the indexing code if it was erased */
|
||||
if (cl->ClFlags & (ErasedMask|DirtyMask)) {
|
||||
if (PREG != FAILCODE) {
|
||||
/* make sure we don't erase the clause we are jumping to,
|
||||
notice that we can erase a number of refs in one go. */
|
||||
if (!(lcl->ClFlags & InUseMask)) {
|
||||
lcl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(lcl);
|
||||
}
|
||||
}
|
||||
if (cl->ClFlags & ErasedMask) {
|
||||
saveregs();
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
save_pc();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef YAPOR
|
||||
if (SCH_top_shared_cp(B)) {
|
||||
SCH_last_alternative(PREG, B_YREG);
|
||||
restore_args(ap->ArityOfPE);
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
#else
|
||||
S_YREG++;
|
||||
#endif /* FROZEN_STACKS */
|
||||
set_cut(S_YREG, B->cp_b);
|
||||
} else
|
||||
#endif /* YAPOR */
|
||||
{
|
||||
pop_yaam_regs();
|
||||
pop_args(ap->ArityOfPE);
|
||||
S_YREG--;
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
#endif /* FROZEN_STACKS */
|
||||
set_cut(S_YREG, B);
|
||||
}
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
JMPNext();
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
BOp(try_logical, OtaLl);
|
||||
check_trail(TR);
|
||||
{
|
||||
UInt timestamp;
|
||||
|
||||
CACHE_Y(YREG);
|
||||
timestamp = IntegerOfTerm(S_YREG[0]);
|
||||
/* fprintf(stderr,"+ %p/%p %d %d %d--%u\n",PREG,PREG->y_u.OtaLl.d->ClPred,timestamp,PREG->y_u.OtaLl.d->ClPred->TimeStampOfPred,PREG->y_u.OtaLl.d->ClTimeStart,PREG->y_u.OtaLl.d->ClTimeEnd);*/
|
||||
/* Point AP to the code that follows this instruction */
|
||||
/* always do this, even if we are not going to use it */
|
||||
store_args(PREG->y_u.OtaLl.s);
|
||||
store_yaam_regs(PREG->y_u.OtaLl.n, 0);
|
||||
set_cut(S_YREG, B);
|
||||
B = B_YREG;
|
||||
#ifdef YAPOR
|
||||
SCH_set_load(B_YREG);
|
||||
#endif /* YAPOR */
|
||||
#ifdef YAPOR
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
#endif /* YAPOR */
|
||||
if (!VALID_TIMESTAMP(timestamp, PREG->y_u.OtaLl.d)) {
|
||||
/* jump to next alternative */
|
||||
PREG=PREG->y_u.OtaLl.n;
|
||||
} else {
|
||||
PREG = PREG->y_u.OtaLl.d->ClCode;
|
||||
}
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(count_retry_logical, OtaLl);
|
||||
check_trail(TR);
|
||||
{
|
||||
UInt timestamp;
|
||||
CACHE_Y(B);
|
||||
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP != PREG->y_u.OtaLl.d->ClPred) {
|
||||
if (PP) UNLOCKPE(15,PP);
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
PELOCK(15,PP);
|
||||
}
|
||||
#endif
|
||||
timestamp = IntegerOfTerm(((CELL *)(B_YREG+1))[PREG->y_u.OtaLl.s]);
|
||||
if (!VALID_TIMESTAMP(timestamp, PREG->y_u.OtaLl.d)) {
|
||||
/* jump to next instruction */
|
||||
PREG=PREG->y_u.OtaLl.n;
|
||||
JMPNext();
|
||||
}
|
||||
restore_yaam_regs(PREG->y_u.OtaLl.n);
|
||||
restore_args(PREG->y_u.OtaLl.s);
|
||||
LOCAL_RetriesCounter--;
|
||||
if (LOCAL_RetriesCounter == 0) {
|
||||
saveregs();
|
||||
Yap_NilError(RETRY_COUNTER_UNDERFLOW_EVENT,"");
|
||||
setregs();
|
||||
JMPNext();
|
||||
}
|
||||
LOCAL_PredEntriesCounter--;
|
||||
if (LOCAL_PredEntriesCounter == 0) {
|
||||
saveregs();
|
||||
Yap_NilError(PRED_ENTRY_COUNTER_UNDERFLOW_EVENT,"");
|
||||
setregs();
|
||||
JMPNext();
|
||||
}
|
||||
LOCK(PREG->y_u.OtaLl.d->ClPred->StatisticsForPred->lock);
|
||||
PREG->y_u.OtaLl.d->ClPred->StatisticsForPred->NOfRetries++;
|
||||
UNLOCK(PREG->y_u.OtaLl.d->ClPred->StatisticsForPred->lock);
|
||||
#ifdef THREADS
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
#endif
|
||||
PREG = PREG->y_u.OtaLl.d->ClCode;
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
set_cut(S_YREG, B->cp_b);
|
||||
#else
|
||||
set_cut(S_YREG, B_YREG->cp_b);
|
||||
#endif /* FROZEN_STACKS */
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(count_trust_logical, OtILl);
|
||||
CACHE_Y(B);
|
||||
{
|
||||
LogUpdIndex *cl = PREG->y_u.OtILl.block;
|
||||
PredEntry *ap = cl->ClPred;
|
||||
LogUpdClause *lcl = PREG->y_u.OtILl.d;
|
||||
UInt timestamp = IntegerOfTerm(((CELL *)(B_YREG+1))[ap->ArityOfPE]);
|
||||
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP != ap) {
|
||||
if (PP) UNLOCKPE(16,PP);
|
||||
PP = ap;
|
||||
PELOCK(16,PP);
|
||||
}
|
||||
#endif
|
||||
if (!VALID_TIMESTAMP(timestamp, lcl)) {
|
||||
/* jump to next alternative */
|
||||
PREG = FAILCODE;
|
||||
} else {
|
||||
LOCAL_RetriesCounter--;
|
||||
if (LOCAL_RetriesCounter == 0) {
|
||||
saveregs();
|
||||
Yap_NilError(RETRY_COUNTER_UNDERFLOW_EVENT,"");
|
||||
setregs();
|
||||
JMPNext();
|
||||
}
|
||||
LOCAL_PredEntriesCounter--;
|
||||
if (LOCAL_PredEntriesCounter == 0) {
|
||||
saveregs();
|
||||
Yap_NilError(PRED_ENTRY_COUNTER_UNDERFLOW_EVENT,"");
|
||||
setregs();
|
||||
JMPNext();
|
||||
}
|
||||
LOCK(ap->StatisticsForPred->lock);
|
||||
ap->StatisticsForPred->NOfRetries++;
|
||||
UNLOCK(ap->StatisticsForPred->lock);
|
||||
PREG = lcl->ClCode;
|
||||
}
|
||||
/* HEY, leave indexing block alone!! */
|
||||
/* check if we are the ones using this code */
|
||||
#if MULTIPLE_STACKS
|
||||
PELOCK(2, ap);
|
||||
PP = ap;
|
||||
DEC_CLREF_COUNT(cl);
|
||||
/* clear the entry from the trail */
|
||||
--B->cp_tr;
|
||||
TR = B->cp_tr;
|
||||
/* actually get rid of the code */
|
||||
if (cl->ClRefCount == 0 && (cl->ClFlags & (ErasedMask|DirtyMask))) {
|
||||
if (PREG != FAILCODE) {
|
||||
/* I am the last one using this clause, hence I don't need a lock
|
||||
to dispose of it
|
||||
*/
|
||||
if (lcl->ClRefCount == 1) {
|
||||
/* make sure the clause isn't destroyed */
|
||||
/* always add an extra reference */
|
||||
INC_CLREF_COUNT(lcl);
|
||||
TRAIL_CLREF(lcl);
|
||||
}
|
||||
}
|
||||
if (cl->ClFlags & ErasedMask) {
|
||||
saveregs();
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
save_pc();
|
||||
}
|
||||
#else
|
||||
if (TrailTerm(B->cp_tr-1) == CLREF_TO_TRENTRY(cl) &&
|
||||
B->cp_tr != B->cp_b->cp_tr) {
|
||||
cl->ClFlags &= ~InUseMask;
|
||||
--B->cp_tr;
|
||||
#if FROZEN_STACKS
|
||||
if (B->cp_tr > TR_FZ)
|
||||
#endif
|
||||
{
|
||||
TR = B->cp_tr;
|
||||
}
|
||||
/* next, recover space for the indexing code if it was erased */
|
||||
if (cl->ClFlags & (ErasedMask|DirtyMask)) {
|
||||
if (PREG != FAILCODE) {
|
||||
/* make sure we don't erase the clause we are jumping too */
|
||||
if (!(lcl->ClFlags & InUseMask)) {
|
||||
lcl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(lcl);
|
||||
}
|
||||
}
|
||||
if (cl->ClFlags & ErasedMask) {
|
||||
saveregs();
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
save_pc();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef YAPOR
|
||||
if (SCH_top_shared_cp(B)) {
|
||||
SCH_last_alternative(PREG, B_YREG);
|
||||
restore_args(ap->ArityOfPE);
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
#else
|
||||
S_YREG++;
|
||||
#endif /* FROZEN_STACKS */
|
||||
set_cut(S_YREG, B->cp_b);
|
||||
} else
|
||||
#endif /* YAPOR */
|
||||
{
|
||||
pop_yaam_regs();
|
||||
pop_args(ap->ArityOfPE);
|
||||
S_YREG--;
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
#endif /* FROZEN_STACKS */
|
||||
set_cut(S_YREG, B);
|
||||
}
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
JMPNext();
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
|
||||
|
||||
BOp(retry_logical, OtaLl);
|
||||
check_trail(TR);
|
||||
{
|
||||
UInt timestamp;
|
||||
CACHE_Y(B);
|
||||
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP != PREG->y_u.OtaLl.d->ClPred) {
|
||||
if (PP) UNLOCKPE(15,PP);
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
PELOCK(15,PP);
|
||||
}
|
||||
#endif
|
||||
timestamp = IntegerOfTerm(((CELL *)(B_YREG+1))[PREG->y_u.OtaLl.s]);
|
||||
/* fprintf(stderr,"^ %p/%p %d %d %d--%u\n",PREG,PREG->y_u.OtaLl.d->ClPred,timestamp,PREG->y_u.OtaLl.d->ClPred->TimeStampOfPred,PREG->y_u.OtaLl.d->ClTimeStart,PREG->y_u.OtaLl.d->ClTimeEnd);*/
|
||||
if (!VALID_TIMESTAMP(timestamp, PREG->y_u.OtaLl.d)) {
|
||||
/* jump to next instruction */
|
||||
PREG=PREG->y_u.OtaLl.n;
|
||||
JMPNext();
|
||||
}
|
||||
restore_yaam_regs(PREG->y_u.OtaLl.n);
|
||||
restore_at_least_one_arg(PREG->y_u.OtaLl.s);
|
||||
#ifdef THREADS
|
||||
PP = PREG->y_u.OtaLl.d->ClPred;
|
||||
#endif
|
||||
PREG = PREG->y_u.OtaLl.d->ClCode;
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
set_cut(S_YREG, B->cp_b);
|
||||
#else
|
||||
set_cut(S_YREG, B_YREG->cp_b);
|
||||
#endif /* FROZEN_STACKS */
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
}
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
BOp(trust_logical, OtILl);
|
||||
CACHE_Y(B);
|
||||
{
|
||||
LogUpdIndex *cl = PREG->y_u.OtILl.block;
|
||||
PredEntry *ap = cl->ClPred;
|
||||
LogUpdClause *lcl = PREG->y_u.OtILl.d;
|
||||
UInt timestamp = IntegerOfTerm(((CELL *)(B_YREG+1))[ap->ArityOfPE]);
|
||||
|
||||
/* fprintf(stderr,"- %p/%p %d %d %p\n",PREG,ap,timestamp,ap->TimeStampOfPred,PREG->y_u.OtILl.d->ClCode);*/
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP != ap) {
|
||||
if (PP) UNLOCKPE(16,PP);
|
||||
PP = ap;
|
||||
PELOCK(16,PP);
|
||||
}
|
||||
#endif
|
||||
if (!VALID_TIMESTAMP(timestamp, lcl)) {
|
||||
/* jump to next alternative */
|
||||
PREG = FAILCODE;
|
||||
} else {
|
||||
PREG = lcl->ClCode;
|
||||
}
|
||||
/* HEY, leave indexing block alone!! */
|
||||
/* check if we are the ones using this code */
|
||||
#if MULTIPLE_STACKS
|
||||
DEC_CLREF_COUNT(cl);
|
||||
/* clear the entry from the trail */
|
||||
B->cp_tr--;
|
||||
TR = B->cp_tr;
|
||||
/* actually get rid of the code */
|
||||
if (cl->ClRefCount == 0 && (cl->ClFlags & (ErasedMask|DirtyMask))) {
|
||||
if (PREG != FAILCODE) {
|
||||
if (lcl->ClRefCount == 1) {
|
||||
/* make sure the clause isn't destroyed */
|
||||
/* always add an extra reference */
|
||||
INC_CLREF_COUNT(lcl);
|
||||
TRAIL_CLREF(lcl);
|
||||
B->cp_tr = TR;
|
||||
}
|
||||
}
|
||||
if (cl->ClFlags & ErasedMask) {
|
||||
saveregs();
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
save_pc();
|
||||
}
|
||||
#else
|
||||
if (TrailTerm(B->cp_tr-1) == CLREF_TO_TRENTRY(cl) &&
|
||||
B->cp_tr != B->cp_b->cp_tr) {
|
||||
cl->ClFlags &= ~InUseMask;
|
||||
B->cp_tr--;
|
||||
#if FROZEN_STACKS
|
||||
if (B->cp_tr > TR_FZ)
|
||||
#endif
|
||||
{
|
||||
TR = B->cp_tr;
|
||||
}
|
||||
/* next, recover space for the indexing code if it was erased */
|
||||
if (cl->ClFlags & (ErasedMask|DirtyMask)) {
|
||||
if (PREG != FAILCODE) {
|
||||
/* make sure we don't erase the clause we are jumping too */
|
||||
if (!(lcl->ClFlags & InUseMask)) {
|
||||
lcl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(lcl);
|
||||
B->cp_tr = TR;
|
||||
}
|
||||
}
|
||||
if (cl->ClFlags & ErasedMask) {
|
||||
saveregs();
|
||||
Yap_ErLogUpdIndex(cl);
|
||||
setregs();
|
||||
} else {
|
||||
saveregs();
|
||||
Yap_CleanUpIndex(cl);
|
||||
setregs();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef YAPOR
|
||||
if (SCH_top_shared_cp(B)) {
|
||||
SCH_last_alternative(PREG, B_YREG);
|
||||
restore_args(ap->ArityOfPE);
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
#else
|
||||
S_YREG++;
|
||||
#endif /* FROZEN_STACKS */
|
||||
set_cut(S_YREG, B->cp_b);
|
||||
} else
|
||||
#endif /* YAPOR */
|
||||
{
|
||||
pop_yaam_regs();
|
||||
pop_args(ap->ArityOfPE);
|
||||
S_YREG--;
|
||||
#ifdef FROZEN_STACKS
|
||||
S_YREG = (CELL *) PROTECT_FROZEN_B(B_YREG);
|
||||
#endif /* FROZEN_STACKS */
|
||||
set_cut(S_YREG, B);
|
||||
}
|
||||
SET_BB(B_YREG);
|
||||
ENDCACHE_Y();
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PREG == FAILCODE) {
|
||||
UNLOCKPE(26,PP);
|
||||
PP = NULL;
|
||||
}
|
||||
#endif
|
||||
JMPNext();
|
||||
}
|
||||
ENDBOp();
|
||||
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* enter a logical semantics dynamic predicate *
|
||||
*****************************************************************/
|
||||
|
||||
/* only meaningful with THREADS on! */
|
||||
/* lock logical updates predicate. */
|
||||
Op(lock_lu, p);
|
||||
#if PARALLEL_YAP
|
||||
if (PP) {
|
||||
GONext();
|
||||
}
|
||||
PP = PREG->y_u.p.p;
|
||||
PELOCK(3, PP);
|
||||
#endif
|
||||
PREG = NEXTOP(PREG, p);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
/* only meaningful with THREADS on! */
|
||||
/* lock logical updates predicate. */
|
||||
Op(unlock_lu, e);
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP) {
|
||||
UNLOCKPE(1,PP);
|
||||
PP = NULL;
|
||||
}
|
||||
#endif
|
||||
PREG = NEXTOP(PREG, e);
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
|
||||
/* enter logical pred */
|
||||
BOp(alloc_for_logical_pred, L);
|
||||
check_trail(TR);
|
||||
/* say that an environment is using this clause */
|
||||
/* we have our own copy for the clause */
|
||||
#if MULTIPLE_STACKS
|
||||
{
|
||||
LogUpdClause *cl = PREG->y_u.L.ClBase;
|
||||
#if PARALLEL_YAP
|
||||
PredEntry *ap = cl->ClPred;
|
||||
#endif
|
||||
|
||||
/* always add an extra reference */
|
||||
INC_CLREF_COUNT(cl);
|
||||
TRAIL_CLREF(cl);
|
||||
UNLOCKPE(2,ap);
|
||||
PP = NULL;
|
||||
}
|
||||
#else
|
||||
{
|
||||
LogUpdClause *cl = (LogUpdClause *)PREG->y_u.L.ClBase;
|
||||
if (!(cl->ClFlags & InUseMask)) {
|
||||
cl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(cl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
PREG = NEXTOP(PREG, L);
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
/* copy database term */
|
||||
BOp(copy_idb_term, e);
|
||||
{
|
||||
LogUpdClause *cl = ClauseCodeToLogUpdClause(PREG);
|
||||
Term t;
|
||||
|
||||
SET_ASP(YREG, E_CB*sizeof(CELL));
|
||||
saveregs();
|
||||
while ((t = Yap_FetchTermFromDB(cl->lusl.ClSource)) == 0L) {
|
||||
if (PP) UNLOCKPE(3,PP);
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
PP = NULL;
|
||||
#endif
|
||||
if (LOCAL_Error_TYPE == RESOURCE_ERROR_ATTRIBUTED_VARIABLES) {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_growglobal(NULL)) {
|
||||
Yap_NilError(RESOURCE_ERROR_ATTRIBUTED_VARIABLES, LOCAL_ErrorMessage);
|
||||
FAIL();
|
||||
}
|
||||
} else {
|
||||
LOCAL_Error_TYPE = YAP_NO_ERROR;
|
||||
if (!Yap_gc(3, ENV, CP)) {
|
||||
Yap_NilError(RESOURCE_ERROR_STACK, LOCAL_ErrorMessage);
|
||||
FAIL();
|
||||
}
|
||||
}
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
PELOCK(5,ClauseCodeToLogUpdClause(PREG)->ClPred);
|
||||
PP = ClauseCodeToLogUpdClause(PREG)->ClPred;
|
||||
#endif
|
||||
}
|
||||
if (!Yap_IUnify(ARG2, t)) {
|
||||
setregs();
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP) UNLOCKPE(6,PP);
|
||||
PP = NULL;
|
||||
#endif
|
||||
FAIL();
|
||||
}
|
||||
if (!Yap_IUnify(ARG3, MkDBRefTerm((DBRef)cl))) {
|
||||
setregs();
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
if (PP) UNLOCKPE(5,PP);
|
||||
PP = NULL;
|
||||
#endif
|
||||
FAIL();
|
||||
}
|
||||
setregs();
|
||||
|
||||
#if MULTIPLE_STACKS
|
||||
/* always add an extra reference */
|
||||
INC_CLREF_COUNT(cl);
|
||||
TRAIL_CLREF(cl);
|
||||
if (PP) UNLOCKPE(7,PP);
|
||||
PP = NULL;
|
||||
#else
|
||||
if (!(cl->ClFlags & InUseMask)) {
|
||||
/* Clause *cl = (Clause *)PREG->y_u.EC.ClBase;
|
||||
|
||||
PREG->y_u.EC.ClTrail = TR-(tr_fr_ptr)LOCAL_TrailBase;
|
||||
PREG->y_u.EC.ClENV = LCL0-YREG;*/
|
||||
cl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(cl);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
PREG = CPREG;
|
||||
YREG = ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = YREG[E_DEPTH];
|
||||
#endif
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
|
||||
/* unify with database term */
|
||||
BOp(unify_idb_term, e);
|
||||
{
|
||||
LogUpdClause *cl = ClauseCodeToLogUpdClause(PREG);
|
||||
|
||||
saveregs();
|
||||
if (!Yap_IUnify(ARG2, cl->lusl.ClSource->Entry)) {
|
||||
setregs();
|
||||
UNLOCKPE(8,PP);
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
PP = NULL;
|
||||
#endif
|
||||
FAIL();
|
||||
}
|
||||
if (!Yap_IUnify(ARG3, MkDBRefTerm((DBRef)cl))) {
|
||||
setregs();
|
||||
UNLOCKPE(9,PP);
|
||||
#if defined(YAPOR) || defined(THREADS)
|
||||
PP = NULL;
|
||||
#endif
|
||||
FAIL();
|
||||
}
|
||||
setregs();
|
||||
|
||||
/* say that an environment is using this clause */
|
||||
/* we have our own copy for the clause */
|
||||
#if MULTIPLE_STACKS
|
||||
/* always add an extra reference */
|
||||
INC_CLREF_COUNT(cl);
|
||||
TRAIL_CLREF(cl);
|
||||
UNLOCKPE(10,PP);
|
||||
PP = NULL;
|
||||
#else
|
||||
if (!(cl->ClFlags & InUseMask)) {
|
||||
/* Clause *cl = (Clause *)PREG->y_u.EC.ClBase;
|
||||
|
||||
PREG->y_u.EC.ClTrail = TR-(tr_fr_ptr)LOCAL_TrailBase;
|
||||
PREG->y_u.EC.ClENV = LCL0-YREG;*/
|
||||
cl->ClFlags |= InUseMask;
|
||||
TRAIL_CLREF(cl);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
PREG = CPREG;
|
||||
YREG = ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = YREG[E_DEPTH];
|
||||
#endif
|
||||
JMPNext();
|
||||
ENDBOp();
|
|
@ -0,0 +1,361 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: mavar.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: support from multiple assignment variables in YAP *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@file mavar.c
|
||||
|
||||
@defgroup Term_Modification Term Modification
|
||||
@ingroup builtins
|
||||
|
||||
|
||||
It is sometimes useful to change the value of instantiated
|
||||
variables. Although, this is against the spirit of logic programming, it
|
||||
is sometimes useful. As in other Prolog systems, YAP has
|
||||
several primitives that allow updating Prolog terms. Note that these
|
||||
primitives are also backtrackable.
|
||||
|
||||
The setarg/3 primitive allows updating any argument of a Prolog
|
||||
compound terms. The _mutable_ family of predicates provides
|
||||
<em>mutable variables</em>. They should be used instead of setarg/3,
|
||||
as they allow the encapsulation of accesses to updatable
|
||||
variables. Their implementation can also be more efficient for long
|
||||
deterministic computations.
|
||||
|
||||
@{
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "Yap.h"
|
||||
|
||||
#ifdef MULTI_ASSIGNMENT_VARIABLES
|
||||
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "eval.h"
|
||||
|
||||
static Int p_setarg( USES_REGS1 );
|
||||
static Int p_create_mutable( USES_REGS1 );
|
||||
static Int p_get_mutable( USES_REGS1 );
|
||||
static Int p_update_mutable( USES_REGS1 );
|
||||
static Int p_is_mutable( USES_REGS1 );
|
||||
|
||||
/** @pred setarg(+ _I_,+ _S_,? _T_)
|
||||
|
||||
|
||||
Set the value of the _I_th argument of term _S_ to term _T_.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_setarg( USES_REGS1 )
|
||||
{
|
||||
CELL ti = Deref(ARG1), ts = Deref(ARG2), t3 = Deref(ARG3);
|
||||
Int i;
|
||||
|
||||
if (IsVarTerm(t3) &&
|
||||
VarOfTerm(t3) > HR &&VarOfTerm(t3) < ASP) {
|
||||
/* local variable */
|
||||
Term tn = MkVarTerm();
|
||||
Bind_Local(VarOfTerm(t3), tn);
|
||||
t3 = tn;
|
||||
}
|
||||
if (IsVarTerm(ti)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,ti,"setarg/3");
|
||||
return FALSE;
|
||||
} else {
|
||||
if (IsIntTerm(ti))
|
||||
i = IntOfTerm(ti);
|
||||
else {
|
||||
Term te = Yap_Eval(ti);
|
||||
if (IsIntegerTerm(te)) {
|
||||
i = IntegerOfTerm(te);
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_INTEGER,ti,"setarg/3");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IsVarTerm(ts)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,ts,"setarg/3");
|
||||
} else if(IsApplTerm(ts)) {
|
||||
CELL *pt;
|
||||
if (IsExtensionFunctor(FunctorOfTerm(ts))) {
|
||||
Yap_Error(TYPE_ERROR_COMPOUND,ts,"setarg/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (i < 1 || i > (Int)ArityOfFunctor(FunctorOfTerm(ts))) {
|
||||
if (i<0)
|
||||
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO,ts,"setarg/3");
|
||||
return FALSE;
|
||||
if (i==0)
|
||||
Yap_Error(DOMAIN_ERROR_NOT_ZERO,ts,"setarg/3");
|
||||
return FALSE;
|
||||
}
|
||||
pt = RepAppl(ts)+i;
|
||||
/* the evil deed is to be done now */
|
||||
MaBind(pt, t3);
|
||||
} else if(IsPairTerm(ts)) {
|
||||
CELL *pt;
|
||||
if (i < 1 || i > 2) {
|
||||
if (i<0)
|
||||
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO,ts,"setarg/3");
|
||||
return FALSE;
|
||||
}
|
||||
pt = RepPair(ts)+i-1;
|
||||
/* the evil deed is to be done now */
|
||||
MaBind(pt, t3);
|
||||
} else {
|
||||
Yap_Error(TYPE_ERROR_COMPOUND,ts,"setarg/3");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* One problem with MAVars is that they you always trail on
|
||||
non-determinate bindings. This is not cool if you have a long
|
||||
determinate computation. One alternative could be to use
|
||||
timestamps.
|
||||
|
||||
Because of !, the only timestamp one can trust is the trailpointer
|
||||
(ouch..). The trail is not reclaimed after cuts. Also, if there was
|
||||
a conditional binding, the trail is sure to have been increased
|
||||
since the last choicepoint. For maximum effect, we can actually
|
||||
store the current value of TR in the timestamp field, giving a way
|
||||
to actually follow a link of all trailings for these variables.
|
||||
|
||||
*/
|
||||
|
||||
/* create and initialize a new timed var. The problem is: how to set
|
||||
the clock?
|
||||
|
||||
If I give it the current value of B->TR, we may have trouble if no
|
||||
non-determinate bindings are made before the next
|
||||
choice-point. Just to make sure this doesn't cause trouble, if (TR
|
||||
== B->TR) we will add a little something ;-).
|
||||
*/
|
||||
|
||||
static Term
|
||||
NewTimedVar(CELL val USES_REGS)
|
||||
{
|
||||
Term out;
|
||||
timed_var *tv;
|
||||
if (IsVarTerm(val) &&
|
||||
VarOfTerm(val) > HR) {
|
||||
Term nval = MkVarTerm();
|
||||
Bind_Local(VarOfTerm(val), nval);
|
||||
val = nval;
|
||||
}
|
||||
out = AbsAppl(HR);
|
||||
*HR++ = (CELL)FunctorMutable;
|
||||
tv = (timed_var *)HR;
|
||||
RESET_VARIABLE(&(tv->clock));
|
||||
tv->value = val;
|
||||
HR += sizeof(timed_var)/sizeof(CELL);
|
||||
return(out);
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_NewTimedVar(CELL val)
|
||||
{
|
||||
CACHE_REGS
|
||||
return NewTimedVar(val PASS_REGS);
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_NewEmptyTimedVar( void )
|
||||
{
|
||||
CACHE_REGS
|
||||
Term out = AbsAppl(HR);
|
||||
timed_var *tv;
|
||||
*HR++ = (CELL)FunctorMutable;
|
||||
tv = (timed_var *)HR;
|
||||
RESET_VARIABLE(&(tv->clock));
|
||||
RESET_VARIABLE(&(tv->value));
|
||||
HR += sizeof(timed_var)/sizeof(CELL);
|
||||
return(out);
|
||||
}
|
||||
|
||||
static Term
|
||||
ReadTimedVar(Term inv)
|
||||
{
|
||||
timed_var *tv = (timed_var *)(RepAppl(inv)+1);
|
||||
return(tv->value);
|
||||
}
|
||||
|
||||
Term
|
||||
Yap_ReadTimedVar(Term inv)
|
||||
{
|
||||
return ReadTimedVar(inv);
|
||||
}
|
||||
|
||||
|
||||
/* update a timed var with a new value */
|
||||
static Term
|
||||
UpdateTimedVar(Term inv, Term new USES_REGS)
|
||||
{
|
||||
timed_var *tv = (timed_var *)(RepAppl(inv)+1);
|
||||
CELL t = tv->value;
|
||||
CELL* timestmp = (CELL *)(tv->clock);
|
||||
if (IsVarTerm(new) &&
|
||||
VarOfTerm(new) > HR) {
|
||||
Term nnew = MkVarTerm();
|
||||
Bind_Local(VarOfTerm(new), nnew);
|
||||
new = nnew;
|
||||
}
|
||||
if (timestmp > B->cp_h
|
||||
#if FROZEN_STACKS
|
||||
&& timestmp > H_FZ
|
||||
#endif
|
||||
) {
|
||||
/* last assignment more recent than last B */
|
||||
#if YAPOR_SBA
|
||||
if (Unsigned((Int)(tv)-(Int)(H_FZ)) >
|
||||
Unsigned((Int)(B_FZ)-(Int)(H_FZ)))
|
||||
*STACK_TO_SBA(&(tv->value)) = new;
|
||||
else
|
||||
#endif
|
||||
tv->value = new;
|
||||
} else {
|
||||
Term nclock = (Term)HR;
|
||||
MaBind(&(tv->value), new);
|
||||
*HR++ = TermFoundVar;
|
||||
MaBind(&(tv->clock), nclock);
|
||||
}
|
||||
return(t);
|
||||
}
|
||||
|
||||
/* update a timed var with a new value */
|
||||
Term
|
||||
Yap_UpdateTimedVar(Term inv, Term new)
|
||||
{
|
||||
CACHE_REGS
|
||||
return UpdateTimedVar(inv, new PASS_REGS);
|
||||
}
|
||||
|
||||
/** @pred create_mutable(+ _D_,- _M_)
|
||||
|
||||
|
||||
Create new mutable variable _M_ with initial value _D_.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_create_mutable( USES_REGS1 )
|
||||
{
|
||||
Term t = NewTimedVar(Deref(ARG1) PASS_REGS);
|
||||
return(Yap_unify(ARG2,t));
|
||||
}
|
||||
|
||||
/** @pred get_mutable(? _D_,+ _M_)
|
||||
|
||||
|
||||
Unify the current value of mutable term _M_ with term _D_.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_get_mutable( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG2);
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t, "get_mutable/3");
|
||||
return(FALSE);
|
||||
}
|
||||
if (!IsApplTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_COMPOUND,t,"get_mutable/3");
|
||||
return(FALSE);
|
||||
}
|
||||
if (FunctorOfTerm(t) != FunctorMutable) {
|
||||
Yap_Error(DOMAIN_ERROR_MUTABLE,t,"get_mutable/3");
|
||||
return(FALSE);
|
||||
}
|
||||
t = ReadTimedVar(t);
|
||||
return(Yap_unify(ARG1, t));
|
||||
}
|
||||
|
||||
/** @pred update_mutable(+ _D_,+ _M_)
|
||||
|
||||
|
||||
Set the current value of mutable term _M_ to term _D_.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_update_mutable( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG2);
|
||||
if (IsVarTerm(t)) {
|
||||
Yap_Error(INSTANTIATION_ERROR, t, "update_mutable/3");
|
||||
return(FALSE);
|
||||
}
|
||||
if (!IsApplTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_COMPOUND,t,"update_mutable/3");
|
||||
return(FALSE);
|
||||
}
|
||||
if (FunctorOfTerm(t) != FunctorMutable) {
|
||||
Yap_Error(DOMAIN_ERROR_MUTABLE,t,"update_mutable/3");
|
||||
return(FALSE);
|
||||
}
|
||||
UpdateTimedVar(t, Deref(ARG1) PASS_REGS);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/** @pred is_mutable(? _D_)
|
||||
|
||||
|
||||
Holds if _D_ is a mutable term.
|
||||
|
||||
|
||||
*/
|
||||
static Int
|
||||
p_is_mutable( USES_REGS1 )
|
||||
{
|
||||
Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t)) {
|
||||
return(FALSE);
|
||||
}
|
||||
if (!IsApplTerm(t)) {
|
||||
return(FALSE);
|
||||
}
|
||||
if (FunctorOfTerm(t) != FunctorMutable) {
|
||||
return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
Yap_InitMaVarCPreds(void)
|
||||
{
|
||||
#ifdef MULTI_ASSIGNMENT_VARIABLES
|
||||
Yap_InitCPred("setarg", 3, p_setarg, SafePredFlag);
|
||||
Yap_InitCPred("create_mutable", 2, p_create_mutable, SafePredFlag);
|
||||
Yap_InitCPred("get_mutable", 2, p_get_mutable, SafePredFlag);
|
||||
Yap_InitCPred("update_mutable", 2, p_update_mutable, SafePredFlag);
|
||||
Yap_InitCPred("is_mutable", 1, p_is_mutable, SafePredFlag);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,300 @@
|
|||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
/* join all the meta-call code into a single procedure with three entry points */
|
||||
{
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
BEGD(d0); /* term to be meta-called */
|
||||
Term mod; /* module to be used */
|
||||
PredEntry *pen; /* predicate */
|
||||
choiceptr b_ptr; /* cut point */
|
||||
Functor f;
|
||||
|
||||
/* we are doing the rhs of a , */
|
||||
BOp(p_execute_tail, Osbmp);
|
||||
|
||||
FETCH_Y_FROM_ENV(YREG);
|
||||
/* place to cut to */
|
||||
b_ptr = (choiceptr)ENV_YREG[E_CB];
|
||||
/* original goal */
|
||||
d0 = ENV_YREG[-EnvSizeInCells-1];
|
||||
/* predicate we had used */
|
||||
pen = RepPredProp((Prop)IntegerOfTerm(ENV_YREG[-EnvSizeInCells-2]));
|
||||
/* current module at the time */
|
||||
mod = ENV_YREG[-EnvSizeInCells-3];
|
||||
/* set YREG */
|
||||
/* Try to preserve the environment */
|
||||
ENV_YREG = (CELL *) (((char *) YREG) + PREG->y_u.Osbmp.s);
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (ENV_YREG > (CELL *) top_b || ENV_YREG < HR) ENV_YREG = (CELL *) top_b;
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) top_b) ENV_YREG = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
}
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) B) {
|
||||
ENV_YREG = (CELL *) B;
|
||||
}
|
||||
#endif /* FROZEN_STACKS */
|
||||
/* now, jump to actual execution */
|
||||
if (pen->ArityOfPE) {
|
||||
f = pen->FunctorOfPred;
|
||||
/* reuse environment if we are continuining a comma, ie, (g1,g2,g3) */
|
||||
/* can only do it deterministically */
|
||||
/* broken
|
||||
if (f == FunctorComma && (CELL *)B >= ENV) {
|
||||
ENV_YREG = ENV;
|
||||
ENV = (CELL *)ENV[E_E];
|
||||
}
|
||||
*/
|
||||
goto execute_pred_f;
|
||||
} else
|
||||
goto execute_pred_a;
|
||||
ENDBOp();
|
||||
|
||||
/* fetch the module from ARG2 */
|
||||
BOp(p_execute2, Osbpp);
|
||||
|
||||
mod = ARG2;
|
||||
deref_head(mod, execute2_unk0);
|
||||
execute2_nvar0:
|
||||
if (!IsAtomTerm(mod)) {
|
||||
saveregs();
|
||||
Yap_Error(TYPE_ERROR_ATOM, mod, "call/2");
|
||||
setregs();
|
||||
}
|
||||
goto start_execute;
|
||||
|
||||
BEGP(pt1);
|
||||
deref_body(mod, pt1, execute2_unk0, execute2_nvar0);
|
||||
saveregs();
|
||||
Yap_Error(INSTANTIATION_ERROR, mod, "call/2");
|
||||
setregs();
|
||||
ENDP(pt1);
|
||||
/* Oops, second argument was unbound too */
|
||||
FAIL();
|
||||
ENDBOp();
|
||||
|
||||
BOp(p_execute, Osbmp);
|
||||
/* fetch the module from PREG */
|
||||
mod = PREG->y_u.Osbmp.mod;
|
||||
start_execute:
|
||||
/* place to cut to */
|
||||
b_ptr = B;
|
||||
/* we have mod, and ARG1 has the goal, let us roll */
|
||||
/* Try to preserve the environment */
|
||||
ENV_YREG = (CELL *) (((char *) YREG) + PREG->y_u.Osbmp.s);
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (ENV_YREG > (CELL *) top_b || ENV_YREG < HR) ENV_YREG = (CELL *) top_b;
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) top_b) ENV_YREG = (CELL *) top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
}
|
||||
#else
|
||||
if (ENV_YREG > (CELL *) B) {
|
||||
ENV_YREG = (CELL *) B;
|
||||
}
|
||||
#endif /* FROZEN_STACKS */
|
||||
d0 = ARG1;
|
||||
restart_execute:
|
||||
deref_head(d0, execute_unk);
|
||||
execute_nvar:
|
||||
if (IsApplTerm(d0)) {
|
||||
f = FunctorOfTerm(d0);
|
||||
if (IsExtensionFunctor(f)) {
|
||||
goto execute_metacall;
|
||||
}
|
||||
pen = RepPredProp(PredPropByFunc(f, mod));
|
||||
execute_pred_f:
|
||||
if (pen->PredFlags & MetaPredFlag) {
|
||||
/* just strip all of M:G */
|
||||
if (f == FunctorModule) {
|
||||
Term tmod = ArgOfTerm(1,d0);
|
||||
/* loop on modules */
|
||||
if (!IsVarTerm(tmod) && IsAtomTerm(tmod)) {
|
||||
d0 = ArgOfTerm(2,d0);
|
||||
mod = tmod;
|
||||
goto execute_nvar;
|
||||
}
|
||||
goto execute_metacall;
|
||||
}
|
||||
if (f == FunctorComma) {
|
||||
Term nmod = mod;
|
||||
|
||||
/* optimise conj */
|
||||
SREG = RepAppl(d0);
|
||||
BEGD(d1);
|
||||
d1 = SREG[2];
|
||||
/* create an environment to execute the call */
|
||||
deref_head(d1, execute_comma_unk);
|
||||
execute_comma_nvar:
|
||||
if (IsAtomTerm(d1)) {
|
||||
/* atomic goal is simpler */
|
||||
ENV_YREG[-EnvSizeInCells-2] = MkIntegerTerm((Int)PredPropByAtom(AtomOfTerm(d1),nmod));
|
||||
} else if (IsApplTerm(d1)) {
|
||||
Functor f1 = FunctorOfTerm(d1);
|
||||
if (IsExtensionFunctor(f1)) {
|
||||
goto execute_metacall;
|
||||
} else {
|
||||
/* check for modules when looking up */
|
||||
if (f1 == FunctorModule) {
|
||||
Term tmod = ArgOfTerm(1,d1);
|
||||
/* loop on modules */
|
||||
if (!IsVarTerm(tmod) && IsAtomTerm(tmod)) {
|
||||
d1 = ArgOfTerm(2,d1);
|
||||
nmod = tmod;
|
||||
goto execute_comma_nvar;
|
||||
}
|
||||
goto execute_metacall;
|
||||
}
|
||||
ENV_YREG[-EnvSizeInCells-2] = MkIntegerTerm((Int)PredPropByFunc(f1,nmod));
|
||||
}
|
||||
} else {
|
||||
goto execute_metacall;
|
||||
}
|
||||
ENV_YREG[-EnvSizeInCells-3] = mod;
|
||||
/* now, we can create the new environment for the meta-call */
|
||||
/* notice that we are at a call, so we should ignore CP */
|
||||
ENV_YREG[E_CP] = (CELL)NEXTOP(PREG,Osbmp);
|
||||
ENV_YREG[E_CB] = (CELL)b_ptr;
|
||||
ENV_YREG[E_E] = (CELL)ENV;
|
||||
#ifdef DEPTH_LIMIT
|
||||
ENV_YREG[E_DEPTH] = DEPTH;
|
||||
#endif /* DEPTH_LIMIT */
|
||||
ENV_YREG[-EnvSizeInCells-1] = d1;
|
||||
ENV = ENV_YREG;
|
||||
ENV_YREG -= EnvSizeInCells+3;
|
||||
CPREG = NEXTOP(PREG, Osbmp);
|
||||
PREG = COMMA_CODE;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
d0 = SREG[1];
|
||||
goto restart_execute;
|
||||
|
||||
BEGP(pt1);
|
||||
deref_body(d1, pt1, execute_comma_unk, execute_comma_nvar);
|
||||
goto execute_metacall;
|
||||
ENDP(pt1);
|
||||
ENDD(d1);
|
||||
} else if (mod != CurrentModule) {
|
||||
goto execute_metacall;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy arguments of meta-call to XREGS */
|
||||
BEGP(pt1);
|
||||
pt1 = RepAppl(d0);
|
||||
BEGD(d2);
|
||||
for (d2 = ArityOfFunctor(f); d2; d2--) {
|
||||
#ifdef YAPOR_SBA
|
||||
BEGD(d1);
|
||||
d1 = pt1[d2];
|
||||
if (d1 == 0) {
|
||||
XREGS[d2] = (CELL)(pt1+d2);
|
||||
} else {
|
||||
XREGS[d2] = d1;
|
||||
}
|
||||
#else
|
||||
XREGS[d2] = pt1[d2];
|
||||
#endif
|
||||
}
|
||||
ENDD(d2);
|
||||
ENDP(pt1);
|
||||
CACHE_A1();
|
||||
} else if (IsAtomTerm(d0)) {
|
||||
pen = RepPredProp(PredPropByAtom(AtomOfTerm(d0), mod));
|
||||
execute_pred_a:
|
||||
/* handle extra pruning */
|
||||
if (pen->FunctorOfPred == (Functor)AtomCut) {
|
||||
if (b_ptr != B) {
|
||||
saveregs();
|
||||
prune(b_ptr PASS_REGS);
|
||||
setregs();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
goto execute_metacall;
|
||||
}
|
||||
|
||||
/* execute, but test first for interrupts */
|
||||
execute_end:
|
||||
/* code copied from call */
|
||||
#ifndef NO_CHECKING
|
||||
check_stack(NoStackPExecute, HR);
|
||||
#endif
|
||||
execute_stack_checked:
|
||||
CPREG = NEXTOP(PREG, Osbmp);
|
||||
ALWAYS_LOOKAHEAD(pen->OpcodeOfPred);
|
||||
PREG = pen->CodeOfPred;
|
||||
/* for profiler */
|
||||
save_pc();
|
||||
#ifdef DEPTH_LIMIT
|
||||
if (DEPTH <= MkIntTerm(1)) {/* I assume Module==0 is primitives */
|
||||
if (pen->ModuleOfPred) {
|
||||
if (DEPTH == MkIntTerm(0)) {
|
||||
FAIL();
|
||||
} else {
|
||||
DEPTH = RESET_DEPTH();
|
||||
}
|
||||
}
|
||||
} else if (pen->ModuleOfPred)
|
||||
DEPTH -= MkIntConstant(2);
|
||||
#endif /* DEPTH_LIMIT */
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace)
|
||||
low_level_trace(enter_pred,pen,XREGS+1);
|
||||
#endif /* LOW_LEVEL_TRACER */
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
/* setup GB */
|
||||
ENV_YREG[E_CB] = (CELL) B;
|
||||
#ifdef YAPOR
|
||||
SCH_check_requests();
|
||||
#endif /* YAPOR */
|
||||
CACHE_A1();
|
||||
ALWAYS_GONext();
|
||||
ALWAYS_END_PREFETCH();
|
||||
|
||||
/* meta-call: Prolog to the rescue */
|
||||
BEGP(pt1);
|
||||
deref_body(d0, pt1, execute_unk, execute_nvar);
|
||||
execute_metacall:
|
||||
ARG1 = ARG3 = d0;
|
||||
pen = PredMetaCall;
|
||||
ARG2 = Yap_cp_as_integer(b_ptr);
|
||||
if (mod)
|
||||
ARG4 = mod;
|
||||
else
|
||||
ARG4 = TermProlog;
|
||||
goto execute_end;
|
||||
ENDP(pt1);
|
||||
|
||||
/* at this point, we have the arguments all set in the argument registers, pen says who is the current predicate. don't remove. */
|
||||
NoStackPExecute:
|
||||
WRITEBACK_Y_AS_ENV();
|
||||
#ifdef SHADOW_S
|
||||
Yap_REGS.S_ = SREG;
|
||||
#endif
|
||||
saveregs_and_ycache();
|
||||
d0 = interrupt_pexecute( pen PASS_REGS );
|
||||
setregs_and_ycache();
|
||||
#ifdef SHADOW_S
|
||||
SREG = Yap_REGS.S_;
|
||||
#endif
|
||||
if (!d0) FAIL();
|
||||
if (d0 == 2) goto execute_stack_checked;
|
||||
goto execute_end;
|
||||
ENDBOp();
|
||||
|
||||
ENDD(d0);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
}
|
|
@ -0,0 +1,552 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
File: modules.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: module support *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCSLookupSystemModule
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
|
||||
static Int current_module(USES_REGS1);
|
||||
static Int current_module1(USES_REGS1);
|
||||
static ModEntry *LookupModule(Term a);
|
||||
static ModEntry *LookupSystemModule(Term a);
|
||||
static ModEntry *GetModuleEntry(Atom at);
|
||||
static ModEntry *FetchModuleEntry(Atom at);
|
||||
|
||||
/**
|
||||
* initialize module data-structure
|
||||
*
|
||||
* @param to parent module (CurrentModule)
|
||||
* @param ae module name.
|
||||
*
|
||||
* @return a new module structure
|
||||
*//** */
|
||||
static ModEntry *
|
||||
initMod( AtomEntry *toname, AtomEntry *ae) {
|
||||
CACHE_REGS
|
||||
ModEntry *n, *parent;
|
||||
|
||||
if (toname == NULL)
|
||||
parent = NULL;
|
||||
else {
|
||||
parent = FetchModuleEntry( toname );
|
||||
}
|
||||
n = (ModEntry *)Yap_AllocAtomSpace(sizeof(*n));
|
||||
INIT_RWLOCK(n->ModRWLock);
|
||||
n->KindOfPE = ModProperty;
|
||||
n->PredForME = NULL;
|
||||
n->NextME = CurrentModules;
|
||||
CurrentModules = n;
|
||||
n->AtomOfME = ae;
|
||||
n->OwnerFile = Yap_ConsultingFile( PASS_REGS1);
|
||||
AddPropToAtom(ae, (PropEntry *)n);
|
||||
Yap_setModuleFlags(n, parent);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* get predicate entry for ap/arity; create it if neccessary
|
||||
*
|
||||
* @param[in] at
|
||||
*
|
||||
* @return module descriptorxs
|
||||
*/
|
||||
static ModEntry *GetModuleEntry(Atom at)
|
||||
{
|
||||
Prop p0;
|
||||
AtomEntry *ae = RepAtom(at);
|
||||
|
||||
READ_LOCK(ae->ARWLock);
|
||||
p0 = ae->PropsOfAE;
|
||||
while (p0) {
|
||||
ModEntry *me = RepModProp(p0);
|
||||
if (me->KindOfPE == ModProperty) {
|
||||
READ_UNLOCK(ae->ARWLock);
|
||||
return me;
|
||||
}
|
||||
p0 = me->NextOfPE;
|
||||
}
|
||||
READ_UNLOCK(ae->ARWLock);
|
||||
|
||||
return initMod( ( CurrentModule == PROLOG_MODULE ? NULL : AtomOfTerm( CurrentModule ) ), at );
|
||||
}
|
||||
|
||||
/** get entry for ap/arity; assumes one is there. */
|
||||
static ModEntry *FetchModuleEntry(Atom at)
|
||||
{
|
||||
Prop p0;
|
||||
AtomEntry *ae = RepAtom(at);
|
||||
|
||||
READ_LOCK(ae->ARWLock);
|
||||
p0 = ae->PropsOfAE;
|
||||
while (p0) {
|
||||
ModEntry *me = RepModProp(p0);
|
||||
if (me->KindOfPE == ModProperty) {
|
||||
READ_UNLOCK(ae->ARWLock);
|
||||
return me;
|
||||
}
|
||||
p0 = me->NextOfPE;
|
||||
}
|
||||
READ_UNLOCK(ae->ARWLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Term Yap_getUnknownModule(ModEntry *m) {
|
||||
if (m && m->flags & UNKNOWN_ERROR) {
|
||||
return TermError;
|
||||
} else if (m && m->flags & UNKNOWN_WARNING) {
|
||||
return TermWarning;
|
||||
} else if (m && m->flags & UNKNOWN_FAST_FAIL) {
|
||||
return TermFastFail;
|
||||
} else {
|
||||
return TermFail;
|
||||
}
|
||||
}
|
||||
|
||||
bool Yap_getUnknown ( Term mod) {
|
||||
ModEntry *m = LookupModule( mod );
|
||||
return Yap_getUnknownModule( m );
|
||||
}
|
||||
|
||||
|
||||
bool Yap_CharacterEscapes(Term mt) {
|
||||
if (mt == PROLOG_MODULE) mt = TermProlog;
|
||||
return GetModuleEntry(AtomOfTerm(mt))->flags & M_CHARESCAPE;
|
||||
}
|
||||
|
||||
|
||||
#define ByteAdr(X) ((char *)&(X))
|
||||
Term Yap_Module_Name(PredEntry *ap) {
|
||||
CACHE_REGS
|
||||
Term mod;
|
||||
if (!ap)
|
||||
return TermUser;
|
||||
if (!ap->ModuleOfPred)
|
||||
/* If the system predicate is a meta-call I should return the
|
||||
module for the metacall, which I will suppose has to be
|
||||
reachable from the current module anyway.
|
||||
|
||||
So I will return the current module in case the system
|
||||
predicate is a meta-call. Otherwise it will still work.
|
||||
*/
|
||||
return TermProlog;
|
||||
else {
|
||||
return ap->ModuleOfPred;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static ModEntry *LookupSystemModule(Term a) {
|
||||
CACHE_REGS
|
||||
Atom at;
|
||||
ModEntry *me;
|
||||
|
||||
|
||||
/* prolog module */
|
||||
if (a == 0) {
|
||||
a = TermProlog;
|
||||
}
|
||||
at = AtomOfTerm(a);
|
||||
me = GetModuleEntry(at);
|
||||
if (!me)
|
||||
return NULL;
|
||||
me->flags |= M_SYSTEM;
|
||||
me->OwnerFile = Yap_ConsultingFile( PASS_REGS1 );
|
||||
return me;
|
||||
}
|
||||
|
||||
|
||||
static ModEntry *LookupModule(Term a) {
|
||||
Atom at;
|
||||
ModEntry *me;
|
||||
|
||||
/* prolog module */
|
||||
if (a == 0) {
|
||||
return GetModuleEntry(AtomProlog);
|
||||
}
|
||||
at = AtomOfTerm(a);
|
||||
me = GetModuleEntry(at);
|
||||
return me;
|
||||
}
|
||||
|
||||
bool Yap_isSystemModule(Term a) {
|
||||
ModEntry *me = LookupModule(a);
|
||||
return
|
||||
me != NULL &&
|
||||
me->flags & M_SYSTEM;
|
||||
}
|
||||
|
||||
Term Yap_Module(Term tmod) {
|
||||
LookupModule(tmod);
|
||||
return tmod;
|
||||
}
|
||||
|
||||
ModEntry *Yap_GetModuleEntry(Term mod) {
|
||||
ModEntry *me;
|
||||
if (!(me = LookupModule(mod)))
|
||||
return NULL;
|
||||
return me;
|
||||
|
||||
}
|
||||
|
||||
Term Yap_GetModuleFromEntry(ModEntry *me) {
|
||||
return MkAtomTerm(me->AtomOfME);
|
||||
;
|
||||
}
|
||||
|
||||
struct pred_entry *Yap_ModulePred(Term mod) {
|
||||
ModEntry *me;
|
||||
if (!(me = LookupModule(mod)))
|
||||
return NULL;
|
||||
return me->PredForME;
|
||||
}
|
||||
|
||||
void Yap_NewModulePred(Term mod, struct pred_entry *ap) {
|
||||
ModEntry *me;
|
||||
|
||||
if (!(me = LookupModule(mod)))
|
||||
return;
|
||||
WRITE_LOCK(me->ModRWLock);
|
||||
ap->NextPredOfModule = me->PredForME;
|
||||
me->PredForME = ap;
|
||||
WRITE_UNLOCK(me->ModRWLock);
|
||||
}
|
||||
|
||||
static Int
|
||||
current_module(USES_REGS1) { /* $current_module(Old,N) */
|
||||
Term t;
|
||||
|
||||
if (CurrentModule) {
|
||||
if (!Yap_unify_constant(ARG1, CurrentModule))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!Yap_unify_constant(ARG1, TermProlog))
|
||||
return FALSE;
|
||||
}
|
||||
t = Deref(ARG2);
|
||||
if (IsVarTerm(t) || !IsAtomTerm(t))
|
||||
return FALSE;
|
||||
if (t == TermProlog) {
|
||||
CurrentModule = PROLOG_MODULE;
|
||||
} else {
|
||||
// make it very clear that t inherits from cm.
|
||||
LookupModule(t);
|
||||
CurrentModule = t;
|
||||
}
|
||||
LOCAL_SourceModule = CurrentModule;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int change_module(USES_REGS1) { /* $change_module(N) */
|
||||
Term mod = Deref(ARG1);
|
||||
LookupModule(mod);
|
||||
CurrentModule = mod;
|
||||
LOCAL_SourceModule = mod;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int current_module1(USES_REGS1) { /* $current_module(Old)
|
||||
*/
|
||||
if (CurrentModule)
|
||||
return Yap_unify_constant(ARG1, CurrentModule);
|
||||
return Yap_unify_constant(ARG1, TermProlog);
|
||||
}
|
||||
|
||||
|
||||
static Int cont_current_module(USES_REGS1) {
|
||||
ModEntry *imod = AddressOfTerm(EXTRA_CBACK_ARG(1, 1)), *next;
|
||||
Term t = MkAtomTerm(imod->AtomOfME);
|
||||
next = imod->NextME;
|
||||
|
||||
/* ARG1 is unbound */
|
||||
Yap_unify(ARG1, t);
|
||||
if (!next)
|
||||
cut_succeed();
|
||||
EXTRA_CBACK_ARG(1, 1) = MkAddressTerm(next);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int init_current_module(
|
||||
USES_REGS1) { /* current_module(?ModuleName) */
|
||||
Term t = Deref(ARG1);
|
||||
if (!IsVarTerm(t)) {
|
||||
if (!IsAtomTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM, t, "module name must be an atom");
|
||||
return FALSE;
|
||||
}
|
||||
if (FetchModuleEntry(AtomOfTerm(t)) != NULL)
|
||||
cut_succeed();
|
||||
cut_fail();
|
||||
}
|
||||
EXTRA_CBACK_ARG(1, 1) = MkIntegerTerm((Int)CurrentModules);
|
||||
return cont_current_module(PASS_REGS1);
|
||||
}
|
||||
|
||||
static Int cont_ground_module(USES_REGS1) {
|
||||
ModEntry *imod = AddressOfTerm(EXTRA_CBACK_ARG(3, 1)), *next;
|
||||
Term t2 = MkAtomTerm(imod->AtomOfME);
|
||||
next = imod->NextME;
|
||||
|
||||
/* ARG2 is unbound */
|
||||
if (!next)
|
||||
cut_succeed();
|
||||
EXTRA_CBACK_ARG(3, 1) = MkAddressTerm(next);
|
||||
return Yap_unify(ARG2, t2);
|
||||
}
|
||||
|
||||
static Int init_ground_module(USES_REGS1) {
|
||||
/* current_module(?ModuleName) */
|
||||
Term t1 = Deref(ARG1), tmod = CurrentModule, t3;
|
||||
if (tmod == PROLOG_MODULE) {
|
||||
tmod = TermProlog;
|
||||
}
|
||||
t3 = Yap_YapStripModule(t1, &tmod);
|
||||
if (!t3) {
|
||||
Yap_Error(TYPE_ERROR_CALLABLE, t3, "trying to obtain module");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsVarTerm(tmod)) {
|
||||
if (!IsAtomTerm(tmod)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM, tmod, "module name must be an atom");
|
||||
cut_fail();
|
||||
}
|
||||
if (FetchModuleEntry(AtomOfTerm(tmod)) != NULL && Yap_unify(tmod, ARG2) &&
|
||||
Yap_unify(t3, ARG3)) {
|
||||
cut_succeed();
|
||||
}
|
||||
cut_fail();
|
||||
}
|
||||
if (!Yap_unify(ARG2, tmod) ||
|
||||
!Yap_unify(ARG3, t3) ) {
|
||||
cut_fail();
|
||||
}
|
||||
// make sure we keep the binding
|
||||
B->cp_tr = TR;
|
||||
B->cp_h = HR;
|
||||
EXTRA_CBACK_ARG(3, 1) = MkAddressTerm(CurrentModules);
|
||||
return cont_ground_module(PASS_REGS1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pred system_module( + _Mod_)
|
||||
*
|
||||
* @param module
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static Int is_system_module( USES_REGS1 )
|
||||
{
|
||||
Term t;
|
||||
if (IsVarTerm(t = Deref (ARG1))) {
|
||||
return false;
|
||||
}
|
||||
if (!IsAtomTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM, t, "load_files/2");
|
||||
return false;
|
||||
}
|
||||
return Yap_isSystemModule( t );
|
||||
}
|
||||
|
||||
static Int new_system_module( USES_REGS1 )
|
||||
{
|
||||
ModEntry *me;
|
||||
Term t;
|
||||
if (IsVarTerm(t = Deref (ARG1))) {
|
||||
Yap_Error( INSTANTIATION_ERROR, t, NULL);
|
||||
return false;
|
||||
}
|
||||
if (!IsAtomTerm(t)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM, t, NULL);
|
||||
return false;
|
||||
}
|
||||
if ((me = LookupSystemModule( t ) ))
|
||||
me->OwnerFile = Yap_ConsultingFile( PASS_REGS1);
|
||||
return me != NULL;
|
||||
}
|
||||
|
||||
static Int strip_module(USES_REGS1) {
|
||||
Term t1 = Deref(ARG1), tmod = CurrentModule;
|
||||
if (tmod == PROLOG_MODULE) {
|
||||
tmod = TermProlog;
|
||||
}
|
||||
t1 = Yap_StripModule(t1, &tmod);
|
||||
if (!t1) {
|
||||
Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
|
||||
return FALSE;
|
||||
}
|
||||
return Yap_unify(ARG3, t1) && Yap_unify(ARG2, tmod);
|
||||
}
|
||||
|
||||
Term Yap_YapStripModule(Term t, Term *modp) {
|
||||
CACHE_REGS
|
||||
Term tmod;
|
||||
|
||||
if (modp)
|
||||
tmod = *modp;
|
||||
else {
|
||||
tmod = CurrentModule;
|
||||
if (tmod == PROLOG_MODULE) {
|
||||
tmod = TermProlog;
|
||||
}
|
||||
}
|
||||
restart:
|
||||
if (IsVarTerm(t) || !IsApplTerm(t)) {
|
||||
if (modp)
|
||||
*modp = tmod;
|
||||
return t;
|
||||
} else {
|
||||
Functor fun = FunctorOfTerm(t);
|
||||
if (fun == FunctorModule) {
|
||||
Term t1 = ArgOfTerm(1, t);
|
||||
tmod = t1;
|
||||
if (!IsVarTerm(tmod) && !IsAtomTerm(tmod)) {
|
||||
return 0L;
|
||||
}
|
||||
t = ArgOfTerm(2, t);
|
||||
goto restart;
|
||||
}
|
||||
if (modp)
|
||||
*modp = tmod;
|
||||
return t;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
static Int yap_strip_module(USES_REGS1) {
|
||||
Term t1 = Deref(ARG1), tmod = CurrentModule;
|
||||
if (tmod == PROLOG_MODULE) {
|
||||
tmod = TermProlog;
|
||||
}
|
||||
t1 = Yap_YapStripModule(t1, &tmod);
|
||||
if (!t1) {
|
||||
Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
|
||||
return FALSE;
|
||||
}
|
||||
return Yap_unify(ARG3, t1) && Yap_unify(ARG2, tmod);
|
||||
}
|
||||
|
||||
static Int context_module(USES_REGS1) {
|
||||
yamop *parentcp = P;
|
||||
CELL *yenv;
|
||||
PredEntry *ap = EnvPreg(parentcp);
|
||||
if (ap->ModuleOfPred && !(ap->PredFlags & MetaPredFlag))
|
||||
return Yap_unify(ARG1, ap->ModuleOfPred);
|
||||
parentcp = CP;
|
||||
yenv = ENV;
|
||||
do {
|
||||
ap = EnvPreg(parentcp);
|
||||
if (ap->ModuleOfPred && !(ap->PredFlags & MetaPredFlag))
|
||||
return Yap_unify(ARG1, ap->ModuleOfPred);
|
||||
parentcp = (yamop *)yenv[E_CP];
|
||||
yenv = (CELL *)yenv[E_E];
|
||||
} while (yenv);
|
||||
return Yap_unify(ARG1, CurrentModule);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pred source_module(-Mod)
|
||||
*
|
||||
* @param Mod is the current text source module.
|
||||
*
|
||||
* : _Mod_ is the current read-in or source module.
|
||||
*/
|
||||
static Int source_module(USES_REGS1) {
|
||||
if (LOCAL_SourceModule == PROLOG_MODULE) {
|
||||
return Yap_unify(ARG1, TermProlog);
|
||||
}
|
||||
return Yap_unify(ARG1, LOCAL_SourceModule);
|
||||
}
|
||||
|
||||
Term Yap_StripModule(Term t, Term *modp) {
|
||||
CACHE_REGS
|
||||
Term tmod;
|
||||
|
||||
if (modp)
|
||||
tmod = *modp;
|
||||
else {
|
||||
tmod = CurrentModule;
|
||||
if (tmod == PROLOG_MODULE) {
|
||||
tmod = TermProlog;
|
||||
}
|
||||
}
|
||||
restart:
|
||||
if (IsVarTerm(t) || !IsApplTerm(t)) {
|
||||
if (modp)
|
||||
*modp = tmod;
|
||||
return t;
|
||||
} else {
|
||||
Functor fun = FunctorOfTerm(t);
|
||||
if (fun == FunctorModule) {
|
||||
Term t1 = ArgOfTerm(1, t);
|
||||
if (IsVarTerm(t1)) {
|
||||
*modp = tmod;
|
||||
return t;
|
||||
}
|
||||
tmod = t1;
|
||||
if (!IsVarTerm(tmod) && !IsAtomTerm(tmod)) {
|
||||
return 0L;
|
||||
}
|
||||
t = ArgOfTerm(2, t);
|
||||
goto restart;
|
||||
}
|
||||
if (modp)
|
||||
*modp = tmod;
|
||||
return t;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
void Yap_InitModulesC(void) {
|
||||
Yap_InitCPred("$current_module", 2, current_module,
|
||||
SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("$current_module", 1, current_module1,
|
||||
SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("$change_module", 1, change_module,
|
||||
SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("strip_module", 3, strip_module, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("source_module", 1, source_module, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("$yap_strip_module", 3, yap_strip_module,
|
||||
SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("context_module", 1, context_module, 0);
|
||||
Yap_InitCPred("$is_system_module", 1, is_system_module, SafePredFlag);
|
||||
Yap_InitCPred("new_system_module", 1, new_system_module, SafePredFlag);
|
||||
Yap_InitCPredBack("$all_current_modules", 1, 1, init_current_module,
|
||||
cont_current_module, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPredBack("$ground_module", 3, 1, init_ground_module,
|
||||
cont_ground_module, SafePredFlag | SyncPredFlag);
|
||||
}
|
||||
|
||||
void Yap_InitModules(void) {
|
||||
CACHE_REGS
|
||||
LookupSystemModule(MkAtomTerm(AtomProlog));
|
||||
LOCAL_SourceModule = MkAtomTerm(AtomProlog);
|
||||
LookupModule(USER_MODULE);
|
||||
LookupModule(IDB_MODULE);
|
||||
LookupModule(ATTRIBUTES_MODULE);
|
||||
LookupSystemModule(CHARSIO_MODULE);
|
||||
LookupSystemModule(TERMS_MODULE);
|
||||
LookupSystemModule(SYSTEM_MODULE);
|
||||
LookupSystemModule(READUTIL_MODULE);
|
||||
LookupSystemModule(HACKS_MODULE);
|
||||
LookupModule(ARG_MODULE);
|
||||
LookupSystemModule(GLOBALS_MODULE);
|
||||
LookupSystemModule(DBLOAD_MODULE);
|
||||
LookupSystemModule(RANGE_MODULE);
|
||||
CurrentModule = PROLOG_MODULE;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/************************************************************************ \
|
||||
* Instructions for implemeting 'or;' *
|
||||
\************************************************************************/
|
||||
|
||||
#ifdef INDENT_CODE
|
||||
{
|
||||
{
|
||||
{
|
||||
#endif /* INDENT_CODE */
|
||||
|
||||
BOp(jump, l);
|
||||
PREG = PREG->y_u.l.l;
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
/* This instruction is called when the previous goal
|
||||
was interrupted when waking up goals
|
||||
*/
|
||||
BOp(move_back, l);
|
||||
PREG = (yamop *)(((char *)PREG)-(Int)(NEXTOP((yamop *)NULL,Osbpp)));
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
/* This instruction is called when the previous goal
|
||||
was interrupted when waking up goals
|
||||
*/
|
||||
BOp(skip, l);
|
||||
PREG = NEXTOP(PREG,l);
|
||||
JMPNext();
|
||||
ENDBOp();
|
||||
|
||||
Op(either, Osblp);
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
if (Yap_do_low_level_trace) {
|
||||
low_level_trace(try_or, PREG->y_u.Osblp.p0, NULL);
|
||||
}
|
||||
#endif
|
||||
#ifdef COROUTINING
|
||||
CACHE_Y_AS_ENV(YREG);
|
||||
check_stack(NoStackEither, HR);
|
||||
ENDCACHE_Y_AS_ENV();
|
||||
either_notest:
|
||||
#endif
|
||||
BEGD(d0);
|
||||
/* Try to preserve the environment */
|
||||
d0 = PREG->y_u.Osblp.s;
|
||||
BEGCHO(pt1);
|
||||
pt1 = (choiceptr) ((char *) YREG + (yslot) d0);
|
||||
#ifdef FROZEN_STACKS
|
||||
{
|
||||
choiceptr top_b = PROTECT_FROZEN_B(B);
|
||||
#ifdef YAPOR_SBA
|
||||
if (pt1 > top_b || pt1 < (choiceptr)HR) pt1 = top_b;
|
||||
#else
|
||||
if (pt1 > top_b) pt1 = top_b;
|
||||
#endif /* YAPOR_SBA */
|
||||
}
|
||||
#else
|
||||
if (pt1 > B) {
|
||||
pt1 = B;
|
||||
}
|
||||
#endif /* FROZEN_STACKS */
|
||||
pt1 = (choiceptr)(((CELL *) pt1)-1);
|
||||
*(CELL **) pt1 = YREG;
|
||||
store_yaam_regs_for_either(PREG->y_u.Osblp.l, PREG);
|
||||
SREG = (CELL *) (B = pt1);
|
||||
#ifdef YAPOR
|
||||
SCH_set_load(pt1);
|
||||
#endif /* YAPOR */
|
||||
SET_BB(pt1);
|
||||
ENDCHO(pt1);
|
||||
/* skip the current instruction plus the next one */
|
||||
PREG = NEXTOP(NEXTOP(PREG, Osblp),l);
|
||||
GONext();
|
||||
ENDD(d0);
|
||||
|
||||
#ifdef COROUTINING
|
||||
NoStackEither:
|
||||
PROCESS_INT(interrupt_either, either_notest);
|
||||
#endif
|
||||
|
||||
ENDOp();
|
||||
|
||||
Op(or_else, Osblp);
|
||||
HR = HBREG = PROTECT_FROZEN_H(B);
|
||||
ENV = B->cp_env;
|
||||
B->cp_cp = PREG;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = B->cp_depth;
|
||||
#endif /* DEPTH_LIMIT */
|
||||
SET_BB(PROTECT_FROZEN_B(B));
|
||||
#ifdef YAPOR
|
||||
if (SCH_top_shared_cp(B)) {
|
||||
SCH_new_alternative(PREG, PREG->y_u.Osblp.l);
|
||||
} else
|
||||
#endif /* YAPOR */
|
||||
B->cp_ap = PREG->y_u.Osblp.l;
|
||||
PREG = NEXTOP(PREG, Osblp);
|
||||
YREG = (CELL *) B->cp_a1;
|
||||
GONext();
|
||||
ENDOp();
|
||||
|
||||
#ifdef YAPOR
|
||||
Op(or_last, Osblp);
|
||||
#else
|
||||
Op(or_last, p);
|
||||
#endif /* YAPOR */
|
||||
BEGCHO(pt0);
|
||||
pt0 = B;
|
||||
#ifdef YAPOR
|
||||
if (SCH_top_shared_cp(B)) {
|
||||
HR = HBREG = PROTECT_FROZEN_H(pt0);
|
||||
YREG = (CELL *) pt0->cp_a1;
|
||||
ENV = pt0->cp_env;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = pt0->cp_depth;
|
||||
#endif /* DEPTH_LIMIT */
|
||||
SCH_new_alternative(PREG, NULL);
|
||||
}
|
||||
else
|
||||
#endif /* YAPOR */
|
||||
{
|
||||
B = pt0->cp_b;
|
||||
HR = PROTECT_FROZEN_H(pt0);
|
||||
YREG = (CELL *) pt0->cp_a1;
|
||||
ENV = pt0->cp_env;
|
||||
#ifdef DEPTH_LIMIT
|
||||
DEPTH = pt0->cp_depth;
|
||||
#endif /* DEPTH_LIMIT */
|
||||
HBREG = PROTECT_FROZEN_H(B);
|
||||
}
|
||||
#ifdef YAPOR
|
||||
PREG = NEXTOP(PREG, Osblp);
|
||||
#else
|
||||
PREG = NEXTOP(PREG, p);
|
||||
#endif /* YAPOR */
|
||||
SET_BB(PROTECT_FROZEN_B(B));
|
||||
GONext();
|
||||
ENDCHO(pt0);
|
||||
ENDOp();
|
||||
|
||||
/************************************************************************\
|
||||
* Pop operations *
|
||||
\************************************************************************/
|
||||
|
||||
OpRW(pop_n, s);
|
||||
/* write mode might have been called from read mode */
|
||||
BEGD(d0);
|
||||
d0 = PREG->y_u.os.s;
|
||||
SP = (CELL *) (((char *) SP) + d0);
|
||||
ENDD(d0);
|
||||
BEGD(d0);
|
||||
d0 = SP[0];
|
||||
if (d0) {
|
||||
START_PREFETCH(s);
|
||||
SREG = (CELL *) (SP[1]);
|
||||
SP += 2;
|
||||
PREG = NEXTOP(PREG, s);
|
||||
GONext();
|
||||
END_PREFETCH();
|
||||
}
|
||||
else {
|
||||
START_PREFETCH_W(s);
|
||||
SREG = (CELL *) (SP[1]);
|
||||
SP += 2;
|
||||
PREG = NEXTOP(PREG, s);
|
||||
GONextW();
|
||||
END_PREFETCH_W();
|
||||
}
|
||||
ENDD(d0);
|
||||
ENDOpRW();
|
||||
|
||||
OpRW(pop, e);
|
||||
BEGD(d0);
|
||||
d0 = SP[0];
|
||||
SREG = (CELL *) (SP[1]);
|
||||
SP += 2;
|
||||
if (d0) {
|
||||
START_PREFETCH(e);
|
||||
PREG = NEXTOP(PREG, e);
|
||||
GONext();
|
||||
END_PREFETCH();
|
||||
}
|
||||
else {
|
||||
START_PREFETCH_W(e);
|
||||
PREG = NEXTOP(PREG, e);
|
||||
GONextW();
|
||||
END_PREFETCH_W();
|
||||
}
|
||||
ENDD(d0);
|
||||
ENDOpRW();
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: other.c *
|
||||
* Last rev: Dec/90 *
|
||||
* mods: *
|
||||
* comments: extra routines *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* exile Yap_standard_regs here, otherwise WIN32 linkers may complain */
|
||||
REGSTORE Yap_standard_regs;
|
||||
|
||||
#if PUSH_REGS
|
||||
|
||||
#ifdef THREADS
|
||||
/* PushRegs always on */
|
||||
|
||||
pthread_key_t Yap_yaamregs_key;
|
||||
|
||||
#else
|
||||
|
||||
REGSTORE *Yap_regp;
|
||||
|
||||
#endif
|
||||
|
||||
#else /* !PUSH_REGS */
|
||||
|
||||
REGSTORE Yap_REGS;
|
||||
|
||||
#endif
|
||||
|
||||
Term
|
||||
Yap_MkNewPairTerm(void)
|
||||
{
|
||||
CACHE_REGS
|
||||
register CELL *p = HR;
|
||||
|
||||
RESET_VARIABLE(HR);
|
||||
RESET_VARIABLE(HR+1);
|
||||
HR+=2;
|
||||
return (AbsPair(p));
|
||||
}
|
||||
|
||||
/** compound term constructor, builds a compound term with functor f and n
|
||||
* args.
|
||||
*
|
||||
*
|
||||
* Room for the new term is allocated from the heap: the functor and arguments are copied there.
|
||||
*
|
||||
*/
|
||||
Term
|
||||
Yap_MkApplTerm(Functor f, arity_t n, const Term *a)
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL *t = HR;
|
||||
|
||||
if (n == 0)
|
||||
return (MkAtomTerm(NameOfFunctor(f)));
|
||||
if (f == FunctorList)
|
||||
return MkPairTerm(a[0], a[1]);
|
||||
*HR++ = (CELL) f;
|
||||
while (n--)
|
||||
*HR++ = * a++;
|
||||
return (AbsAppl(t));
|
||||
}
|
||||
|
||||
Term
|
||||
|
||||
Yap_MkNewApplTerm(Functor f, arity_t n)
|
||||
/* build compound term with functor f and n
|
||||
* args a */
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL *t = HR;
|
||||
|
||||
if (n == 0)
|
||||
return (MkAtomTerm(NameOfFunctor(f)));
|
||||
if (f == FunctorList) {
|
||||
RESET_VARIABLE(HR);
|
||||
RESET_VARIABLE(HR+1);
|
||||
HR+=2;
|
||||
return (AbsPair(t));
|
||||
}
|
||||
*HR++ = (CELL) f;
|
||||
while (n--) {
|
||||
RESET_VARIABLE(HR);
|
||||
HR++;
|
||||
}
|
||||
return (AbsAppl(t));
|
||||
}
|
||||
|
||||
|
||||
Term
|
||||
Yap_Globalise(Term t)
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL *vt;
|
||||
Term tn;
|
||||
|
||||
if (!IsVarTerm(t))
|
||||
return t;
|
||||
vt = VarOfTerm(t);
|
||||
if (vt <= HR && vt > H0)
|
||||
return t;
|
||||
tn = MkVarTerm();
|
||||
Yap_unify(t, tn);
|
||||
return tn;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,981 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V. Santos Costa and Universidade do Porto 1985-- *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: qlyw.c *
|
||||
* comments: quick saver/loader *
|
||||
* *
|
||||
* Last rev: $Date: 2011-08-29$,$Author: vsc $ *
|
||||
* $Log: not supported by cvs2svn $ *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "absmi.h"
|
||||
#include "Foreign.h"
|
||||
#include "alloc.h"
|
||||
#include "yapio.h"
|
||||
#include "iopreds.h"
|
||||
#include "attvar.h"
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "qly.h"
|
||||
|
||||
static void RestoreEntries(PropEntry *, int USES_REGS);
|
||||
static void CleanCode(PredEntry * USES_REGS);
|
||||
|
||||
static void
|
||||
GrowAtomTable(void) {
|
||||
CACHE_REGS
|
||||
UInt size = LOCAL_ExportAtomHashTableSize;
|
||||
export_atom_hash_entry_t *p, *newt, *oldt = LOCAL_ExportAtomHashChain;
|
||||
UInt new_size = size + (size > 1024 ? size : 1024);
|
||||
UInt i;
|
||||
|
||||
newt = (export_atom_hash_entry_t *)calloc(new_size,sizeof(export_atom_hash_entry_t));
|
||||
if (!newt) {
|
||||
return;
|
||||
}
|
||||
p = oldt;
|
||||
for (i = 0 ; i < size ; p++,i++) {
|
||||
Atom a = p->val;
|
||||
export_atom_hash_entry_t *newp;
|
||||
CELL hash;
|
||||
const unsigned char *apt;
|
||||
|
||||
|
||||
if (!a) continue;
|
||||
apt = RepAtom(a)->UStrOfAE;
|
||||
hash = HashFunction(apt)/(2*sizeof(CELL)) % new_size;
|
||||
newp = newt+hash;
|
||||
while (newp->val) {
|
||||
newp++;
|
||||
if (newp == newt+new_size)
|
||||
newp = newt;
|
||||
}
|
||||
newp->val = a;
|
||||
}
|
||||
LOCAL_ExportAtomHashChain = newt;
|
||||
LOCAL_ExportAtomHashTableSize = new_size;
|
||||
free(oldt);
|
||||
}
|
||||
|
||||
static void
|
||||
LookupAtom(Atom at)
|
||||
{
|
||||
CACHE_REGS
|
||||
const unsigned char *p = RepAtom(at)->UStrOfAE;
|
||||
CELL hash = HashFunction(p) % LOCAL_ExportAtomHashTableSize;
|
||||
export_atom_hash_entry_t *a;
|
||||
|
||||
a = LOCAL_ExportAtomHashChain+hash;
|
||||
while (a->val) {
|
||||
if (a->val == at) {
|
||||
return;
|
||||
}
|
||||
a++;
|
||||
if (a == LOCAL_ExportAtomHashChain+LOCAL_ExportAtomHashTableSize)
|
||||
a = LOCAL_ExportAtomHashChain;
|
||||
|
||||
}
|
||||
a->val = at;
|
||||
LOCAL_ExportAtomHashTableNum++;
|
||||
if (LOCAL_ExportAtomHashTableNum >
|
||||
LOCAL_ExportAtomHashTableSize/2
|
||||
) {
|
||||
GrowAtomTable();
|
||||
if (!LOCAL_ExportAtomHashChain) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GrowFunctorTable(void) {
|
||||
CACHE_REGS
|
||||
UInt size = LOCAL_ExportFunctorHashTableSize;
|
||||
export_functor_hash_entry_t *p, *newt, *oldt = LOCAL_ExportFunctorHashChain;
|
||||
UInt new_size = size + (size > 1024 ? size : 1024);
|
||||
UInt i;
|
||||
|
||||
newt = (export_functor_hash_entry_t *)calloc(new_size,sizeof(export_functor_hash_entry_t));
|
||||
if (!newt) {
|
||||
return;
|
||||
}
|
||||
p = oldt;
|
||||
for (i = 0 ; i < size ; p++,i++) {
|
||||
Functor f = p->val;
|
||||
export_functor_hash_entry_t *newp;
|
||||
CELL hash;
|
||||
|
||||
if (!f) continue;
|
||||
hash = ((CELL)(f))/(2*sizeof(CELL)) % new_size;
|
||||
newp = newt+hash;
|
||||
while (newp->val) {
|
||||
newp++;
|
||||
if (newp == newt+new_size)
|
||||
newp = newt;
|
||||
}
|
||||
newp->val = p->val;
|
||||
newp->arity = p->arity;
|
||||
newp->name = p->name;
|
||||
}
|
||||
LOCAL_ExportFunctorHashChain = newt;
|
||||
LOCAL_ExportFunctorHashTableSize = new_size;
|
||||
free(oldt);
|
||||
}
|
||||
|
||||
static void
|
||||
LookupFunctor(Functor fun)
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL hash = ((CELL)(fun))/(2*sizeof(CELL)) % LOCAL_ExportFunctorHashTableSize;
|
||||
export_functor_hash_entry_t *f;
|
||||
Atom name = NameOfFunctor(fun);
|
||||
UInt arity = ArityOfFunctor(fun);
|
||||
|
||||
f = LOCAL_ExportFunctorHashChain+hash;
|
||||
while (f->val) {
|
||||
if (f->val == fun) {
|
||||
return;
|
||||
}
|
||||
f++;
|
||||
if (f == LOCAL_ExportFunctorHashChain+LOCAL_ExportFunctorHashTableSize)
|
||||
f = LOCAL_ExportFunctorHashChain;
|
||||
}
|
||||
LookupAtom(name);
|
||||
f->val = fun;
|
||||
f->name = name;
|
||||
f->arity = arity;
|
||||
LOCAL_ExportFunctorHashTableNum++;
|
||||
if (LOCAL_ExportFunctorHashTableNum >
|
||||
LOCAL_ExportFunctorHashTableSize/2
|
||||
) {
|
||||
GrowFunctorTable();
|
||||
if (!LOCAL_ExportFunctorHashChain) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GrowPredTable(void) {
|
||||
CACHE_REGS
|
||||
UInt size = LOCAL_ExportPredEntryHashTableSize;
|
||||
export_pred_entry_hash_entry_t *p, *newt, *oldt = LOCAL_ExportPredEntryHashChain;
|
||||
UInt new_size = size + (size > 1024 ? size : 1024);
|
||||
UInt i;
|
||||
|
||||
newt = (export_pred_entry_hash_entry_t *)calloc(new_size,sizeof(export_pred_entry_hash_entry_t));
|
||||
if (!newt) {
|
||||
return;
|
||||
}
|
||||
p = oldt;
|
||||
for (i = 0 ; i < size ; p++,i++) {
|
||||
PredEntry *pe = p->val;
|
||||
export_pred_entry_hash_entry_t *newp;
|
||||
CELL hash;
|
||||
|
||||
if (!pe) continue;
|
||||
hash = ((CELL)(pe))/(2*sizeof(CELL)) % new_size;
|
||||
newp = newt+hash;
|
||||
while (newp->val) {
|
||||
newp++;
|
||||
if (newp == newt+new_size)
|
||||
newp = newt;
|
||||
}
|
||||
newp->val = p->val;
|
||||
newp->arity = p->arity;
|
||||
newp->u_af.f = p->u_af.f;
|
||||
newp->module = p->module;
|
||||
}
|
||||
LOCAL_ExportPredEntryHashChain = newt;
|
||||
LOCAL_ExportPredEntryHashTableSize = new_size;
|
||||
free(oldt);
|
||||
}
|
||||
|
||||
static void
|
||||
LookupPredEntry(PredEntry *pe)
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL hash = (((CELL)(pe))/(2*sizeof(CELL))) % LOCAL_ExportPredEntryHashTableSize;
|
||||
export_pred_entry_hash_entry_t *p;
|
||||
UInt arity = pe->ArityOfPE;
|
||||
|
||||
p = LOCAL_ExportPredEntryHashChain+hash;
|
||||
while (p->val) {
|
||||
if (p->val == pe) {
|
||||
return;
|
||||
}
|
||||
p++;
|
||||
if (p == LOCAL_ExportPredEntryHashChain+LOCAL_ExportPredEntryHashTableSize)
|
||||
p = LOCAL_ExportPredEntryHashChain;
|
||||
}
|
||||
p->arity = arity;
|
||||
p->val = pe;
|
||||
if (pe->ModuleOfPred != IDB_MODULE) {
|
||||
if (arity) {
|
||||
p->u_af.f = pe->FunctorOfPred;
|
||||
LookupFunctor(pe->FunctorOfPred);
|
||||
} else {
|
||||
p->u_af.a = (Atom)(pe->FunctorOfPred);
|
||||
LookupAtom((Atom)(pe->FunctorOfPred));
|
||||
}
|
||||
} else {
|
||||
if (pe->PredFlags & AtomDBPredFlag) {
|
||||
p->u_af.a = (Atom)(pe->FunctorOfPred);
|
||||
p->arity = (CELL)(-2);
|
||||
LookupAtom((Atom)(pe->FunctorOfPred));
|
||||
} else if (!(pe->PredFlags & NumberDBPredFlag)) {
|
||||
p->u_af.f = pe->FunctorOfPred;
|
||||
p->arity = (CELL)(-1);
|
||||
LookupFunctor(pe->FunctorOfPred);
|
||||
} else {
|
||||
p->u_af.f = pe->FunctorOfPred;
|
||||
}
|
||||
}
|
||||
if (pe->ModuleOfPred) {
|
||||
p->module = AtomOfTerm(pe->ModuleOfPred);
|
||||
} else {
|
||||
p->module = AtomProlog;
|
||||
}
|
||||
LookupAtom(p->module);
|
||||
LOCAL_ExportPredEntryHashTableNum++;
|
||||
if (LOCAL_ExportPredEntryHashTableNum >
|
||||
LOCAL_ExportPredEntryHashTableSize/2
|
||||
) {
|
||||
GrowPredTable();
|
||||
if (!LOCAL_ExportPredEntryHashChain) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
GrowDBRefTable(void) {
|
||||
CACHE_REGS
|
||||
UInt size = LOCAL_ExportDBRefHashTableSize;
|
||||
export_dbref_hash_entry_t *p, *newt, *oldt = LOCAL_ExportDBRefHashChain;
|
||||
UInt new_size = size + (size > 1024 ? size : 1024);
|
||||
UInt i;
|
||||
|
||||
newt = (export_dbref_hash_entry_t *)calloc(new_size,sizeof(export_dbref_hash_entry_t));
|
||||
if (!newt) {
|
||||
return;
|
||||
}
|
||||
p = oldt;
|
||||
for (i = 0 ; i < size ; p++,i++) {
|
||||
DBRef dbr = p->val;
|
||||
export_dbref_hash_entry_t *newp;
|
||||
CELL hash;
|
||||
|
||||
if (!dbr) continue;
|
||||
hash = ((CELL)(dbr))/(2*sizeof(CELL)) % new_size;
|
||||
newp = newt+hash;
|
||||
while (newp->val) {
|
||||
newp++;
|
||||
if (newp == newt+new_size)
|
||||
newp = newt;
|
||||
}
|
||||
newp->val = p->val;
|
||||
newp->sz = p->sz;
|
||||
newp->refs = p->refs;
|
||||
}
|
||||
LOCAL_ExportDBRefHashChain = newt;
|
||||
LOCAL_ExportDBRefHashTableSize = new_size;
|
||||
free(oldt);
|
||||
}
|
||||
|
||||
static void
|
||||
LookupDBRef(DBRef ref)
|
||||
{
|
||||
CACHE_REGS
|
||||
CELL hash = ((CELL)(ref))/(2*sizeof(CELL)) % LOCAL_ExportDBRefHashTableSize;
|
||||
export_dbref_hash_entry_t *a;
|
||||
|
||||
a = LOCAL_ExportDBRefHashChain+hash;
|
||||
while (a->val) {
|
||||
if (a->val == ref) {
|
||||
a->refs++;
|
||||
return;
|
||||
}
|
||||
a++;
|
||||
if (a == LOCAL_ExportDBRefHashChain+LOCAL_ExportDBRefHashTableSize)
|
||||
a = LOCAL_ExportDBRefHashChain;
|
||||
}
|
||||
a->val = ref;
|
||||
a->sz = ((LogUpdClause *)ref)->ClSize;
|
||||
a->refs = 1;
|
||||
LOCAL_ExportDBRefHashTableNum++;
|
||||
if (LOCAL_ExportDBRefHashTableNum >
|
||||
LOCAL_ExportDBRefHashTableSize/2
|
||||
) {
|
||||
GrowDBRefTable();
|
||||
if (!LOCAL_ExportDBRefHashChain) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InitHash(void)
|
||||
{
|
||||
CACHE_REGS
|
||||
LOCAL_ExportFunctorHashTableNum = 0;
|
||||
LOCAL_ExportFunctorHashTableSize = EXPORT_FUNCTOR_TABLE_SIZE;
|
||||
LOCAL_ExportFunctorHashChain = (export_functor_hash_entry_t *)calloc(LOCAL_ExportFunctorHashTableSize, sizeof(export_functor_hash_entry_t ));
|
||||
LOCAL_ExportAtomHashTableNum = 0;
|
||||
LOCAL_ExportAtomHashTableSize = EXPORT_ATOM_TABLE_SIZE;
|
||||
LOCAL_ExportAtomHashChain = (export_atom_hash_entry_t *)calloc( LOCAL_ExportAtomHashTableSize, sizeof(export_atom_hash_entry_t));
|
||||
LOCAL_ExportPredEntryHashTableNum = 0;
|
||||
LOCAL_ExportPredEntryHashTableSize = EXPORT_PRED_ENTRY_TABLE_SIZE;
|
||||
LOCAL_ExportPredEntryHashChain = (export_pred_entry_hash_entry_t *)calloc(LOCAL_ExportPredEntryHashTableSize, sizeof(export_pred_entry_hash_entry_t));
|
||||
LOCAL_ExportDBRefHashTableNum = 0;
|
||||
LOCAL_ExportDBRefHashTableSize = EXPORT_DBREF_TABLE_SIZE;
|
||||
LOCAL_ExportDBRefHashChain = (export_dbref_hash_entry_t *)calloc(EXPORT_DBREF_TABLE_SIZE, sizeof(export_dbref_hash_entry_t));
|
||||
}
|
||||
|
||||
static void
|
||||
CloseHash(void)
|
||||
{
|
||||
CACHE_REGS
|
||||
LOCAL_ExportFunctorHashTableNum = 0;
|
||||
LOCAL_ExportFunctorHashTableSize = 0L;
|
||||
free(LOCAL_ExportFunctorHashChain);
|
||||
LOCAL_ExportAtomHashTableNum = 0;
|
||||
LOCAL_ExportAtomHashTableSize = 0L;
|
||||
free(LOCAL_ExportAtomHashChain);
|
||||
LOCAL_ExportPredEntryHashTableNum = 0;
|
||||
LOCAL_ExportPredEntryHashTableSize = 0L;
|
||||
free(LOCAL_ExportPredEntryHashChain);
|
||||
LOCAL_ExportDBRefHashTableNum = 0;
|
||||
LOCAL_ExportDBRefHashTableSize = 0L;
|
||||
free(LOCAL_ExportDBRefHashChain);
|
||||
}
|
||||
|
||||
static inline Atom
|
||||
AtomAdjust(Atom a)
|
||||
{
|
||||
LookupAtom(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline Functor
|
||||
FuncAdjust(Functor f)
|
||||
{
|
||||
LookupFunctor(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static inline Term
|
||||
AtomTermAdjust(Term t)
|
||||
{
|
||||
LookupAtom(AtomOfTerm(t));
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline Term
|
||||
TermToGlobalOrAtomAdjust(Term t)
|
||||
{
|
||||
if (t && IsAtomTerm(t))
|
||||
return AtomTermAdjust(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
#define IsOldCode(P) FALSE
|
||||
#define IsOldCodeCellPtr(P) FALSE
|
||||
#define IsOldDelay(P) FALSE
|
||||
#define IsOldDelayPtr(P) FALSE
|
||||
#define IsOldLocalInTR(P) FALSE
|
||||
#define IsOldLocalInTRPtr(P) FALSE
|
||||
#define IsOldGlobal(P) FALSE
|
||||
#define IsOldGlobalPtr(P) FALSE
|
||||
#define IsOldTrail(P) FALSE
|
||||
#define IsOldTrailPtr(P) FALSE
|
||||
|
||||
#define CharP(X) ((char *)(X))
|
||||
|
||||
#define REINIT_LOCK(P)
|
||||
#define REINIT_RWLOCK(P)
|
||||
#define BlobTypeAdjust(P) (P)
|
||||
#define NoAGCAtomAdjust(P) (P)
|
||||
#define OrArgAdjust(P)
|
||||
#define TabEntryAdjust(P)
|
||||
#define IntegerAdjust(D) (D)
|
||||
#define AddrAdjust(P) (P)
|
||||
#define MFileAdjust(P) (P)
|
||||
#define CodeVarAdjust(P) (P)
|
||||
#define ConstantAdjust(P) (P)
|
||||
#define ArityAdjust(P) (P)
|
||||
#define DoubleInCodeAdjust(P)
|
||||
#define IntegerInCodeAdjust(P)
|
||||
#define OpcodeAdjust(P) (P)
|
||||
|
||||
static inline Term
|
||||
ModuleAdjust(Term t)
|
||||
{
|
||||
if (!t) return t;
|
||||
return AtomTermAdjust(t);
|
||||
}
|
||||
|
||||
static inline PredEntry *
|
||||
PredEntryAdjust(PredEntry *pe)
|
||||
{
|
||||
LookupPredEntry(pe);
|
||||
return pe;
|
||||
}
|
||||
|
||||
static inline PredEntry *
|
||||
PtoPredAdjust(PredEntry *pe)
|
||||
{
|
||||
LookupPredEntry(pe);
|
||||
return pe;
|
||||
}
|
||||
|
||||
|
||||
#define ExternalFunctionAdjust(P) (P)
|
||||
#define DBRecordAdjust(P) (P)
|
||||
#define ModEntryPtrAdjust(P) (P)
|
||||
#define AtomEntryAdjust(P) (P)
|
||||
#define GlobalEntryAdjust(P) (P)
|
||||
#define BlobTermInCodeAdjust(P) (P)
|
||||
#define CellPtoHeapAdjust(P) (P)
|
||||
#define PtoAtomHashEntryAdjust(P) (P)
|
||||
#define CellPtoHeapCellAdjust(P) (P)
|
||||
#define CellPtoTRAdjust(P) (P)
|
||||
#define CodeAddrAdjust(P) (P)
|
||||
#define ConsultObjAdjust(P) (P)
|
||||
#define DelayAddrAdjust(P) (P)
|
||||
#define DelayAdjust(P) (P)
|
||||
#define GlobalAdjust(P) (P)
|
||||
|
||||
#define DBRefAdjust(P,DoRef) DBRefAdjust__(P PASS_REGS)
|
||||
static inline DBRef
|
||||
DBRefAdjust__ (DBRef dbt USES_REGS)
|
||||
{
|
||||
LookupDBRef(dbt);
|
||||
return dbt;
|
||||
}
|
||||
|
||||
#define DBRefPAdjust(P) (P)
|
||||
#define DBTermAdjust(P) (P)
|
||||
#define LUIndexAdjust(P) (P)
|
||||
#define SIndexAdjust(P) (P)
|
||||
#define LocalAddrAdjust(P) (P)
|
||||
#define GlobalAddrAdjust(P) (P)
|
||||
#define OpListAdjust(P) (P)
|
||||
#define PtoLUCAdjust(P) (P)
|
||||
#define PtoStCAdjust(P) (P)
|
||||
#define PtoArrayEAdjust(P) (P)
|
||||
#define PtoArraySAdjust(P) (P)
|
||||
#define PtoGlobalEAdjust(P) (P)
|
||||
#define PtoDelayAdjust(P) (P)
|
||||
#define PtoGloAdjust(P) (P)
|
||||
#define PtoLocAdjust(P) (P)
|
||||
#define PtoHeapCellAdjust(P) (P)
|
||||
#define TermToGlobalAdjust(P) (P)
|
||||
#define PtoOpAdjust(P) (P)
|
||||
#define PtoLUClauseAdjust(P) (P)
|
||||
#define PtoLUIndexAdjust(P) (P)
|
||||
#define PtoDBTLAdjust(P) (P)
|
||||
#define PtoPtoPredAdjust(P) (P)
|
||||
#define OpRTableAdjust(P) (P)
|
||||
#define OpEntryAdjust(P) (P)
|
||||
#define PropAdjust(P) (P)
|
||||
#define TrailAddrAdjust(P) (P)
|
||||
#define XAdjust(P) (P)
|
||||
#define YAdjust(P) (P)
|
||||
#define HoldEntryAdjust(P) (P)
|
||||
#define CodeCharPAdjust(P) (P)
|
||||
#define CodeConstCharPAdjust(P) (P)
|
||||
#define CodeVoidPAdjust(P) (P)
|
||||
#define HaltHookAdjust(P) (P)
|
||||
|
||||
#define recompute_mask(dbr)
|
||||
|
||||
#define rehash(oldcode, NOfE, KindOfEntries)
|
||||
|
||||
#define RestoreSWIHash()
|
||||
|
||||
static void RestoreFlags( UInt NFlags )
|
||||
{
|
||||
}
|
||||
|
||||
#include "rheap.h"
|
||||
|
||||
static void
|
||||
RestoreHashPreds( USES_REGS1 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
RestoreAtomList(Atom atm USES_REGS)
|
||||
{
|
||||
}
|
||||
|
||||
static size_t save_bytes(FILE *stream, void *ptr, size_t sz)
|
||||
{
|
||||
return fwrite(ptr, sz, 1, stream);
|
||||
}
|
||||
|
||||
static size_t save_byte(FILE *stream, int byte)
|
||||
{
|
||||
fputc(byte, stream);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t save_bits16(FILE *stream, BITS16 val)
|
||||
{
|
||||
BITS16 v = val;
|
||||
return save_bytes(stream, &v, sizeof(BITS16));
|
||||
}
|
||||
|
||||
static size_t save_UInt(FILE *stream, UInt val)
|
||||
{
|
||||
UInt v = val;
|
||||
return save_bytes(stream, &v, sizeof(UInt));
|
||||
}
|
||||
|
||||
static size_t save_Int(FILE *stream, Int val)
|
||||
{
|
||||
Int v = val;
|
||||
return save_bytes(stream, &v, sizeof(Int));
|
||||
}
|
||||
|
||||
static size_t save_tag(FILE *stream, qlf_tag_t tag)
|
||||
{
|
||||
return save_byte(stream, tag);
|
||||
}
|
||||
|
||||
static size_t save_predFlags(FILE *stream, pred_flags_t predFlags)
|
||||
{
|
||||
pred_flags_t v = predFlags;
|
||||
return save_bytes(stream, &v, sizeof(pred_flags_t));
|
||||
}
|
||||
|
||||
static int
|
||||
SaveHash(FILE *stream)
|
||||
{
|
||||
CACHE_REGS
|
||||
UInt i;
|
||||
/* first, current opcodes */
|
||||
CHECK(save_tag(stream, QLY_START_X));
|
||||
save_UInt(stream, (UInt)&ARG1);
|
||||
CHECK(save_tag(stream, QLY_START_OPCODES));
|
||||
save_Int(stream, _std_top);
|
||||
for (i= 0; i <= _std_top; i++) {
|
||||
save_UInt(stream, (UInt)Yap_opcode(i));
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_START_ATOMS));
|
||||
CHECK(save_UInt(stream, LOCAL_ExportAtomHashTableNum));
|
||||
for (i = 0; i < LOCAL_ExportAtomHashTableSize; i++) {
|
||||
export_atom_hash_entry_t *a = LOCAL_ExportAtomHashChain+i;
|
||||
if (a->val) {
|
||||
Atom at = a->val;
|
||||
CHECK(save_UInt(stream, (UInt)at));
|
||||
if (IsWideAtom(at)) {
|
||||
CHECK(save_tag(stream, QLY_ATOM_WIDE));
|
||||
CHECK(save_UInt(stream, wcslen(RepAtom(at)->WStrOfAE)));
|
||||
CHECK(save_bytes(stream, at->WStrOfAE, (wcslen(at->WStrOfAE)+1)*sizeof(wchar_t)));
|
||||
} else {
|
||||
CHECK(save_tag(stream, QLY_ATOM));
|
||||
CHECK(save_UInt(stream, strlen((char *)RepAtom(at)->StrOfAE)));
|
||||
CHECK(save_bytes(stream, (char *)at->StrOfAE, (strlen((char *)at->StrOfAE)+1)*sizeof(char)));
|
||||
}
|
||||
}
|
||||
}
|
||||
save_tag(stream, QLY_START_FUNCTORS);
|
||||
save_UInt(stream, LOCAL_ExportFunctorHashTableNum);
|
||||
for (i = 0; i < LOCAL_ExportFunctorHashTableSize; i++) {
|
||||
export_functor_hash_entry_t *f = LOCAL_ExportFunctorHashChain+i;
|
||||
if (!(f->val))
|
||||
continue;
|
||||
CHECK(save_UInt(stream, (UInt)(f->val)));
|
||||
CHECK(save_UInt(stream, f->arity));
|
||||
CHECK(save_UInt(stream, (CELL)(f->name)));
|
||||
}
|
||||
save_tag(stream, QLY_START_PRED_ENTRIES);
|
||||
save_UInt(stream, LOCAL_ExportPredEntryHashTableNum);
|
||||
for (i = 0; i < LOCAL_ExportPredEntryHashTableSize; i++) {
|
||||
export_pred_entry_hash_entry_t *p = LOCAL_ExportPredEntryHashChain+i;
|
||||
if (!(p->val))
|
||||
continue;
|
||||
CHECK(save_UInt(stream, (UInt)(p->val)));
|
||||
CHECK(save_UInt(stream, p->arity));
|
||||
CHECK(save_UInt(stream, (UInt)p->module));
|
||||
CHECK(save_UInt(stream, (UInt)p->u_af.f));
|
||||
}
|
||||
save_tag(stream, QLY_START_DBREFS);
|
||||
save_UInt(stream, LOCAL_ExportDBRefHashTableNum);
|
||||
for (i = 0; i < LOCAL_ExportDBRefHashTableSize; i++) {
|
||||
export_dbref_hash_entry_t *p = LOCAL_ExportDBRefHashChain+i;
|
||||
if (p->val) {
|
||||
CHECK(save_UInt(stream, (UInt)(p->val)));
|
||||
CHECK(save_UInt(stream, p->sz));
|
||||
CHECK(save_UInt(stream, p->refs));
|
||||
}
|
||||
}
|
||||
save_tag(stream, QLY_FAILCODE);
|
||||
save_UInt(stream, (UInt)FAILCODE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
save_clauses(FILE *stream, PredEntry *pp) {
|
||||
yamop *FirstC, *LastC;
|
||||
|
||||
FirstC = pp->cs.p_code.FirstClause;
|
||||
LastC = pp->cs.p_code.LastClause;
|
||||
if (FirstC == NULL && LastC == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if (pp->PredFlags & LogUpdatePredFlag) {
|
||||
LogUpdClause *cl = ClauseCodeToLogUpdClause(FirstC);
|
||||
|
||||
while (cl != NULL) {
|
||||
if (IN_BETWEEN(cl->ClTimeStart, pp->TimeStampOfPred, cl->ClTimeEnd)) {
|
||||
UInt size = cl->ClSize;
|
||||
CHECK(save_tag(stream, QLY_START_LU_CLAUSE));
|
||||
CHECK(save_UInt(stream, (UInt)cl));
|
||||
CHECK(save_UInt(stream, size));
|
||||
CHECK(save_bytes(stream, cl, size));
|
||||
}
|
||||
cl = cl->ClNext;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_LU_CLAUSES));
|
||||
} else if (pp->PredFlags & MegaClausePredFlag) {
|
||||
MegaClause *cl = ClauseCodeToMegaClause(FirstC);
|
||||
UInt size = cl->ClSize;
|
||||
|
||||
CHECK(save_UInt(stream, (UInt)cl));
|
||||
CHECK(save_UInt(stream, (UInt)(cl->ClFlags)));
|
||||
CHECK(save_UInt(stream, size));
|
||||
CHECK(save_bytes(stream, cl, size));
|
||||
} else if (pp->PredFlags & DynamicPredFlag) {
|
||||
yamop *cl = FirstC;
|
||||
|
||||
do {
|
||||
DynamicClause *dcl = ClauseCodeToDynamicClause(cl);
|
||||
UInt size = dcl->ClSize;
|
||||
|
||||
CHECK(save_UInt(stream, (UInt)cl));
|
||||
CHECK(save_UInt(stream, size));
|
||||
CHECK(save_bytes(stream, dcl, size));
|
||||
if (cl == LastC) return 1;
|
||||
cl = NextDynamicClause(cl);
|
||||
} while (TRUE);
|
||||
} else {
|
||||
StaticClause *cl = ClauseCodeToStaticClause(FirstC);
|
||||
|
||||
if (pp->PredFlags & SYSTEM_PRED_FLAGS) {
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
UInt size = cl->ClSize;
|
||||
|
||||
CHECK(save_UInt(stream, (UInt)cl));
|
||||
CHECK(save_UInt(stream, size));
|
||||
CHECK(save_bytes(stream, cl, size));
|
||||
if (cl->ClCode == LastC) return 1;
|
||||
cl = cl->ClNext;
|
||||
} while (TRUE);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
save_pred(FILE *stream, PredEntry *ap) {
|
||||
CHECK(save_UInt(stream, (UInt)ap));
|
||||
CHECK(save_predFlags(stream, ap->PredFlags));
|
||||
if (ap->PredFlags & ForeignPredFlags)
|
||||
return 1;
|
||||
CHECK(save_UInt(stream, ap->cs.p_code.NOfClauses));
|
||||
CHECK(save_UInt(stream, ap->src.IndxId));
|
||||
CHECK(save_UInt(stream, ap->TimeStampOfPred));
|
||||
return save_clauses(stream, ap);
|
||||
}
|
||||
|
||||
static int
|
||||
clean_pred(PredEntry *pp USES_REGS) {
|
||||
if (pp->PredFlags & ForeignPredFlags) {
|
||||
return true;
|
||||
} else {
|
||||
CleanClauses(pp->cs.p_code.FirstClause, pp->cs.p_code.LastClause, pp PASS_REGS);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static size_t
|
||||
mark_pred(PredEntry *ap)
|
||||
{
|
||||
CACHE_REGS
|
||||
if (ap->ModuleOfPred != IDB_MODULE) {
|
||||
if (ap->ArityOfPE) {
|
||||
FuncAdjust(ap->FunctorOfPred);
|
||||
} else {
|
||||
AtomAdjust((Atom)(ap->FunctorOfPred));
|
||||
}
|
||||
} else {
|
||||
if (ap->PredFlags & AtomDBPredFlag) {
|
||||
AtomAdjust((Atom)(ap->FunctorOfPred));
|
||||
} else if (!(ap->PredFlags & NumberDBPredFlag)) {
|
||||
FuncAdjust(ap->FunctorOfPred);
|
||||
}
|
||||
}
|
||||
if (!(ap->PredFlags & (MultiFileFlag|NumberDBPredFlag)) &&
|
||||
ap->src.OwnerFile) {
|
||||
AtomAdjust(ap->src.OwnerFile);
|
||||
}
|
||||
CHECK(clean_pred(ap PASS_REGS));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
mark_ops(FILE *stream, Term mod) {
|
||||
OpEntry *op = OpList;
|
||||
while (op) {
|
||||
if (!mod || op->OpModule == mod) {
|
||||
AtomAdjust(op->OpName);
|
||||
if (op->OpModule)
|
||||
AtomTermAdjust(op->OpModule);
|
||||
}
|
||||
op = op->OpNext;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
save_ops(FILE *stream, Term mod) {
|
||||
OpEntry *op = OpList;
|
||||
while (op) {
|
||||
if (!mod || op->OpModule == mod) {
|
||||
CHECK(save_tag(stream, QLY_NEW_OP));
|
||||
save_UInt(stream, (UInt)op->OpName);
|
||||
save_UInt(stream, (UInt)op->OpModule);
|
||||
save_bits16(stream, op->Prefix);
|
||||
save_bits16(stream, op->Infix);
|
||||
save_bits16(stream, op->Posfix);
|
||||
}
|
||||
op = op->OpNext;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_OPS));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
save_header(FILE *stream, char type[])
|
||||
{
|
||||
char msg[256];
|
||||
|
||||
sprintf(msg, "#!/bin/sh\nexec_dir=${YAPBINDIR:-%s}\nexec $exec_dir/yap $0 \"$@\"\n%s %s\n", YAP_BINDIR, type, YAP_FULL_VERSION);
|
||||
return save_bytes(stream, msg, strlen(msg)+1);
|
||||
}
|
||||
|
||||
static size_t
|
||||
save_module(FILE *stream, Term mod) {
|
||||
PredEntry *ap = Yap_ModulePred(mod);
|
||||
save_header( stream, "saved module," );
|
||||
InitHash();
|
||||
ModuleAdjust(mod);
|
||||
while (ap) {
|
||||
ap = PredEntryAdjust(ap);
|
||||
CHECK(mark_pred(ap));
|
||||
ap = ap->NextPredOfModule;
|
||||
}
|
||||
/* just to make sure */
|
||||
mark_ops(stream, mod);
|
||||
SaveHash(stream);
|
||||
CHECK(save_tag(stream, QLY_START_MODULE));
|
||||
CHECK(save_UInt(stream, (UInt)mod));
|
||||
ap = Yap_ModulePred(mod);
|
||||
while (ap) {
|
||||
CHECK(save_tag(stream, QLY_START_PREDICATE));
|
||||
CHECK(save_pred(stream, ap));
|
||||
ap = ap->NextPredOfModule;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_PREDICATES));
|
||||
CHECK(save_tag(stream, QLY_END_MODULES));
|
||||
save_ops(stream, mod);
|
||||
CloseHash();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
save_program(FILE *stream) {
|
||||
ModEntry *me = CurrentModules;
|
||||
|
||||
InitHash();
|
||||
save_header( stream, "saved state," );
|
||||
/* should we allow the user to see hidden predicates? */
|
||||
while (me) {
|
||||
PredEntry *pp;
|
||||
pp = me->PredForME;
|
||||
AtomAdjust(me->AtomOfME);
|
||||
while (pp != NULL) {
|
||||
#if DEBUG
|
||||
// Yap_PrintPredName( pp );
|
||||
#endif
|
||||
pp = PredEntryAdjust(pp);
|
||||
CHECK(mark_pred(pp));
|
||||
pp = pp->NextPredOfModule;
|
||||
}
|
||||
me = me->NextME;
|
||||
}
|
||||
|
||||
/* just to make sure */
|
||||
mark_ops(stream, 0);
|
||||
SaveHash(stream);
|
||||
me = CurrentModules;
|
||||
while (me) {
|
||||
PredEntry *pp;
|
||||
pp = me->PredForME;
|
||||
CHECK(save_tag(stream, QLY_START_MODULE));
|
||||
CHECK(save_UInt(stream, (UInt)MkAtomTerm(me->AtomOfME)));
|
||||
while (pp != NULL) {
|
||||
CHECK(save_tag(stream, QLY_START_PREDICATE));
|
||||
CHECK(save_pred(stream, pp));
|
||||
pp = pp->NextPredOfModule;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_PREDICATES));
|
||||
me = me->NextME;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_MODULES));
|
||||
save_ops(stream, 0);
|
||||
CloseHash();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
save_file(FILE *stream, Atom FileName) {
|
||||
ModEntry *me = CurrentModules;
|
||||
|
||||
InitHash();
|
||||
save_header( stream, "saved file," );
|
||||
/* should we allow the user to see hidden predicates? */
|
||||
while (me) {
|
||||
PredEntry *pp;
|
||||
pp = me->PredForME;
|
||||
AtomAdjust(me->AtomOfME);
|
||||
while (pp != NULL) {
|
||||
pp = PredEntryAdjust(pp);
|
||||
if (pp &&
|
||||
!(pp->PredFlags & (MultiFileFlag|NumberDBPredFlag|AtomDBPredFlag|CPredFlag|AsmPredFlag|UserCPredFlag)) &&
|
||||
pp->ModuleOfPred != IDB_MODULE &&
|
||||
pp->src.OwnerFile == FileName) {
|
||||
CHECK(mark_pred(pp));
|
||||
}
|
||||
pp = pp->NextPredOfModule;
|
||||
}
|
||||
me = me->NextME;
|
||||
}
|
||||
|
||||
/* just to make sure */
|
||||
mark_ops(stream, 0);
|
||||
SaveHash(stream);
|
||||
me = CurrentModules;
|
||||
while (me) {
|
||||
PredEntry *pp;
|
||||
pp = me->PredForME;
|
||||
CHECK(save_tag(stream, QLY_START_MODULE));
|
||||
CHECK(save_UInt(stream, (UInt)MkAtomTerm(me->AtomOfME)));
|
||||
while (pp != NULL) {
|
||||
if (pp &&
|
||||
!(pp->PredFlags & (MultiFileFlag|NumberDBPredFlag|AtomDBPredFlag|CPredFlag|AsmPredFlag|UserCPredFlag)) &&
|
||||
pp->src.OwnerFile == FileName) {
|
||||
CHECK(save_tag(stream, QLY_START_PREDICATE));
|
||||
CHECK(save_pred(stream, pp));
|
||||
}
|
||||
pp = pp->NextPredOfModule;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_PREDICATES));
|
||||
me = me->NextME;
|
||||
}
|
||||
CHECK(save_tag(stream, QLY_END_MODULES));
|
||||
save_ops(stream, 0);
|
||||
CloseHash();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Int
|
||||
qsave_module_preds( USES_REGS1 )
|
||||
{
|
||||
FILE *stream;
|
||||
Term tmod = Deref(ARG2);
|
||||
Term t1 = Deref(ARG1);
|
||||
|
||||
if (IsVarTerm(t1)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,t1,"save_module/3");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(t1)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM,t1,"save_module/3");
|
||||
return(FALSE);
|
||||
}
|
||||
if (!(stream = Yap_GetOutputStream(t1, "save_module") )){
|
||||
return FALSE;
|
||||
}
|
||||
if (IsVarTerm(tmod)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,tmod,"save_module/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(tmod)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM,tmod,"save_module/2");
|
||||
return FALSE;
|
||||
}
|
||||
return save_module(stream, tmod) != 0;
|
||||
}
|
||||
|
||||
static Int
|
||||
qsave_program( USES_REGS1 )
|
||||
{
|
||||
FILE *stream;
|
||||
Term t1 = Deref(ARG1);
|
||||
|
||||
if (!(stream = Yap_GetOutputStream(t1,"save_program")) ) {
|
||||
return FALSE;
|
||||
}
|
||||
return save_program(stream) != 0;
|
||||
}
|
||||
|
||||
static Int
|
||||
qsave_file( USES_REGS1 )
|
||||
{
|
||||
FILE *stream;
|
||||
Term t1 = Deref(ARG1);
|
||||
Term tfile = Deref(ARG2);
|
||||
|
||||
if (!(stream = Yap_GetOutputStream(t1, "save_file/2") ) ) {
|
||||
return FALSE;
|
||||
}
|
||||
if (IsVarTerm(tfile)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,tfile,"save_file/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(tfile)) {
|
||||
Yap_Error(TYPE_ERROR_ATOM,tfile,"save_file/2");
|
||||
return FALSE;
|
||||
}
|
||||
return save_file(stream, AtomOfTerm(tfile) ) != 0;
|
||||
}
|
||||
|
||||
void Yap_InitQLY(void)
|
||||
{
|
||||
Yap_InitCPred("$qsave_module_preds", 2, qsave_module_preds, SyncPredFlag|UserCPredFlag);
|
||||
Yap_InitCPred("$qsave_program", 1, qsave_program, SyncPredFlag|UserCPredFlag);
|
||||
Yap_InitCPred("$qsave_file_preds", 2, qsave_file, SyncPredFlag|UserCPredFlag);
|
||||
if (FALSE) {
|
||||
restore_codes();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V. Santos Costa and Universidade do Porto 1985-- *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: range.c *
|
||||
* comments: Arithmetic interval computation *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "eval.h"
|
||||
|
||||
static Int
|
||||
p_in_range( USES_REGS1 ) {
|
||||
Term t;
|
||||
double i,j;
|
||||
double d1;
|
||||
double d2;
|
||||
double d3;
|
||||
|
||||
t = Deref(ARG1);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(ARG4);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
d1 = i-j;
|
||||
t = Deref(ARG2);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(ARG5);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
d2 = i-j;
|
||||
t = Deref(ARG3);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(ARG6);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
d3 = i-j;
|
||||
t = Deref(ARG7);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(ARG8);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
|
||||
return fabs(sqrt(d1*d1 + d2*d2 + d3*d3)-i) <= j;
|
||||
|
||||
}
|
||||
|
||||
static Int
|
||||
p_in_range2( USES_REGS1 ) {
|
||||
CELL *p1, *p2;
|
||||
Term t;
|
||||
double i,j;
|
||||
double d1;
|
||||
double d2;
|
||||
double d3;
|
||||
UInt arity;
|
||||
p1 = RepAppl(Deref(ARG1));
|
||||
arity = ArityOfFunctor((Functor)*p1);
|
||||
p1 += arity-2;
|
||||
p2 = RepAppl(Deref(ARG2))+(arity-2);;
|
||||
|
||||
t = Deref(p1[0]);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(p2[0]);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
d1 = i-j;
|
||||
t = Deref(p1[1]);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(p2[1]);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
d2 = i-j;
|
||||
t = Deref(p1[2]);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(p2[2]);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
d3 = i-j;
|
||||
t = Deref(ARG3);
|
||||
if (IsFloatTerm(t)) i = FloatOfTerm(t); else i = IntegerOfTerm(t);
|
||||
t = Deref(ARG4);
|
||||
if (IsFloatTerm(t)) j = FloatOfTerm(t); else j = IntegerOfTerm(t);
|
||||
|
||||
return fabs(sqrt(d1*d1 + d2*d2 + d3*d3)-i) <= j;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_euc_dist( USES_REGS1 ) {
|
||||
Term t1 = Deref(ARG1);
|
||||
Term t2 = Deref(ARG2);
|
||||
double d1 = (double)(IntegerOfTerm(ArgOfTerm(1,t1))-IntegerOfTerm(ArgOfTerm(1,t2)));
|
||||
double d2 = (double)(IntegerOfTerm(ArgOfTerm(2,t1))-IntegerOfTerm(ArgOfTerm(2,t2)));
|
||||
double d3 = (double)(IntegerOfTerm(ArgOfTerm(3,t1))-IntegerOfTerm(ArgOfTerm(3,t2)));
|
||||
Int result = (Int)sqrt(d1*d1+d2*d2+d3*d3);
|
||||
return(Yap_unify(ARG3,MkIntegerTerm(result)));
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
volatile int loop_counter = 0;
|
||||
|
||||
static Int
|
||||
p_loop( USES_REGS1 ) {
|
||||
while (loop_counter == 0);
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Yap_InitRange(void)
|
||||
{
|
||||
CACHE_REGS
|
||||
Term cm = CurrentModule;
|
||||
CurrentModule = RANGE_MODULE;
|
||||
Yap_InitCPred("euclidean_distance", 3, p_euc_dist, SafePredFlag);
|
||||
#ifdef DEBUG
|
||||
Yap_InitCPred("loop", 0, p_loop, SafePredFlag);
|
||||
#endif
|
||||
Yap_InitCPred("in_range", 8, p_in_range, TestPredFlag|SafePredFlag);
|
||||
Yap_InitCPred("in_range", 4, p_in_range2, TestPredFlag|SafePredFlag);
|
||||
CurrentModule = cm;
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>/var/www/vhosts/netmite.com/android/mydroid/bionic/libc/bionic/realpath.c</title>
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000">
|
||||
<pre>
|
||||
<font color="#444444">/*
|
||||
* Copyright (c) 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/</font>
|
||||
|
||||
<font color="0000ff"><strong>#if defined(LIBC_SCCS) && !defined(lint)</strong></font>
|
||||
<strong>static</strong> <strong>char</strong> <font color="#2040a0">sccsid</font><font color="4444FF">[</font><font color="4444FF">]</font> <font color="4444FF">=</font> <font color="#008000">"@(#)realpath.c 8.1 (Berkeley) 2/16/94"</font><font color="4444FF">;</font>
|
||||
<strong>static</strong> <strong>char</strong> <font color="#2040a0">rcsid</font><font color="4444FF">[</font><font color="4444FF">]</font> <font color="4444FF">=</font>
|
||||
<font color="#008000">"$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/realpath.c,v 1.6.2.1 2003/08/03 23:47:39 nectar Exp $"</font><font color="4444FF">;</font>
|
||||
<font color="0000ff"><strong>#endif<font color="#444444"> /* LIBC_SCCS and not lint */</font></strong></font>
|
||||
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><sys/param.h></font></strong></font>
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><sys/stat.h></font></strong></font>
|
||||
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><errno.h></font></strong></font>
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><fcntl.h></font></strong></font>
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><stdlib.h></font></strong></font>
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><string.h></font></strong></font>
|
||||
<font color="0000ff"><strong>#include <font color="#008000"><unistd.h></font></strong></font>
|
||||
|
||||
<font color="#444444">/*
|
||||
* char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
|
||||
*
|
||||
* Find the real name of path, by removing all ".", ".." and symlink
|
||||
* components. Returns (resolved) on success, or (NULL) on failure,
|
||||
* in which case the path which caused trouble is left in (resolved).
|
||||
*/</font>
|
||||
<strong>char</strong> <font color="4444FF">*</font>
|
||||
<font color="#2040a0">realpath</font><font color="4444FF">(</font><font color="#2040a0">path</font>, <font color="#2040a0">resolved</font><font color="4444FF">)</font>
|
||||
<strong>const</strong> <strong>char</strong> <font color="4444FF">*</font><font color="#2040a0">path</font><font color="4444FF">;</font>
|
||||
<strong>char</strong> <font color="4444FF">*</font><font color="#2040a0">resolved</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>{</strong></font>
|
||||
<strong>struct</strong> <font color="#2040a0">stat</font> <font color="#2040a0">sb</font><font color="4444FF">;</font>
|
||||
<strong>int</strong> <font color="#2040a0">fd</font>, <font color="#2040a0">n</font>, <font color="#2040a0">rootd</font>, <font color="#2040a0">serrno</font><font color="4444FF">;</font>
|
||||
<strong>char</strong> <font color="4444FF">*</font><font color="#2040a0">p</font>, <font color="4444FF">*</font><font color="#2040a0">q</font>, <font color="#2040a0">wbuf</font><font color="4444FF">[</font><font color="#2040a0">MAXPATHLEN</font><font color="4444FF">]</font><font color="4444FF">;</font>
|
||||
<strong>int</strong> <font color="#2040a0">symlinks</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
|
||||
|
||||
<font color="#444444">/* Save the starting point. */</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="4444FF">(</font><font color="#2040a0">fd</font> <font color="4444FF">=</font> <font color="#2040a0">open</font><font color="4444FF">(</font><font color="#008000">"."</font>, <font color="#2040a0">O_RDONLY</font><font color="4444FF">)</font><font color="4444FF">)</font> <font color="4444FF"><</font> <font color="#FF0000">0</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">strcpy</font><font color="4444FF">(</font><font color="#2040a0">resolved</font>, <font color="#008000">"."</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<strong>return</strong> <font color="4444FF">(</font><font color="#2040a0">NULL</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
|
||||
<font color="#444444">/*
|
||||
* Find the dirname and basename from the path to be resolved.
|
||||
* Change directory to the dirname component.
|
||||
* lstat the basename part.
|
||||
* if it is a symlink, read in the value and loop.
|
||||
* if it is a directory, then change to that directory.
|
||||
* get the current directory name and append the basename.
|
||||
*/</font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">strncpy</font><font color="4444FF">(</font><font color="#2040a0">resolved</font>, <font color="#2040a0">path</font>, <font color="#2040a0">MAXPATHLEN</font> <font color="4444FF">-</font> <font color="#FF0000">1</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">resolved</font><font color="4444FF">[</font><font color="#2040a0">MAXPATHLEN</font> <font color="4444FF">-</font> <font color="#FF0000">1</font><font color="4444FF">]</font> <font color="4444FF">=</font> <font color="#008000">'<font color="#77dd77">\0</font>'</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">loop</font><font color="4444FF">:</font>
|
||||
<font color="#2040a0">q</font> <font color="4444FF">=</font> <font color="#2040a0">strrchr</font><font color="4444FF">(</font><font color="#2040a0">resolved</font>, <font color="#008000">'/'</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">q</font> <font color="4444FF">!</font><font color="4444FF">=</font> <font color="#2040a0">NULL</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<font color="#2040a0">p</font> <font color="4444FF">=</font> <font color="#2040a0">q</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">;</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">q</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#2040a0">resolved</font><font color="4444FF">)</font>
|
||||
<font color="#2040a0">q</font> <font color="4444FF">=</font> <font color="#008000">"/"</font><font color="4444FF">;</font>
|
||||
<strong>else</strong> <font color="4444FF"><strong>{</strong></font>
|
||||
<strong>do</strong> <font color="4444FF"><strong>{</strong></font>
|
||||
<font color="4444FF">-</font><font color="4444FF">-</font><font color="#2040a0">q</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font> <strong>while</strong> <font color="4444FF">(</font><font color="#2040a0">q</font> <font color="4444FF">></font> <font color="#2040a0">resolved</font> <font color="4444FF">&</font><font color="4444FF">&</font> <font color="4444FF">*</font><font color="#2040a0">q</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#008000">'/'</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">q</font><font color="4444FF">[</font><font color="#FF0000">1</font><font color="4444FF">]</font> <font color="4444FF">=</font> <font color="#008000">'<font color="#77dd77">\0</font>'</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">q</font> <font color="4444FF">=</font> <font color="#2040a0">resolved</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">chdir</font><font color="4444FF">(</font><font color="#2040a0">q</font><font color="4444FF">)</font> <font color="4444FF"><</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err1</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font> <strong>else</strong>
|
||||
<font color="#2040a0">p</font> <font color="4444FF">=</font> <font color="#2040a0">resolved</font><font color="4444FF">;</font>
|
||||
|
||||
<font color="#444444">/* Deal with the last component. */</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="4444FF">*</font><font color="#2040a0">p</font> <font color="4444FF">!</font><font color="4444FF">=</font> <font color="#008000">'<font color="#77dd77">\0</font>'</font> <font color="4444FF">&</font><font color="4444FF">&</font> <font color="#2040a0">lstat</font><font color="4444FF">(</font><font color="#2040a0">p</font>, <font color="4444FF">&</font><font color="#2040a0">sb</font><font color="4444FF">)</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">S_ISLNK</font><font color="4444FF">(</font><font color="#2040a0">sb</font>.<font color="#2040a0">st_mode</font><font color="4444FF">)</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="4444FF">+</font><font color="4444FF">+</font><font color="#2040a0">symlinks</font> <font color="4444FF">></font> <font color="#2040a0">MAXSYMLINKS</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<font color="#2040a0">errno</font> <font color="4444FF">=</font> <font color="#2040a0">ELOOP</font><font color="4444FF">;</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err1</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
<font color="#2040a0">n</font> <font color="4444FF">=</font> <font color="#2040a0">readlink</font><font color="4444FF">(</font><font color="#2040a0">p</font>, <font color="#2040a0">resolved</font>, <font color="#2040a0">MAXPATHLEN</font> <font color="4444FF">-</font> <font color="#FF0000">1</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">n</font> <font color="4444FF"><</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err1</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">resolved</font><font color="4444FF">[</font><font color="#2040a0">n</font><font color="4444FF">]</font> <font color="4444FF">=</font> <font color="#008000">'<font color="#77dd77">\0</font>'</font><font color="4444FF">;</font>
|
||||
<strong>goto</strong> <font color="#2040a0">loop</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">S_ISDIR</font><font color="4444FF">(</font><font color="#2040a0">sb</font>.<font color="#2040a0">st_mode</font><font color="4444FF">)</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">chdir</font><font color="4444FF">(</font><font color="#2040a0">p</font><font color="4444FF">)</font> <font color="4444FF"><</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err1</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">p</font> <font color="4444FF">=</font> <font color="#008000">""</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
|
||||
<font color="#444444">/*
|
||||
* Save the last component name and get the full pathname of
|
||||
* the current directory.
|
||||
*/</font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">strcpy</font><font color="4444FF">(</font><font color="#2040a0">wbuf</font>, <font color="#2040a0">p</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">getcwd</font><font color="4444FF">(</font><font color="#2040a0">resolved</font>, <font color="#2040a0">MAXPATHLEN</font><font color="4444FF">)</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err1</font><font color="4444FF">;</font>
|
||||
|
||||
<font color="#444444">/*
|
||||
* Join the two strings together, ensuring that the right thing
|
||||
* happens if the last component is empty, or the dirname is root.
|
||||
*/</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">resolved</font><font color="4444FF">[</font><font color="#FF0000">0</font><font color="4444FF">]</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#008000">'/'</font> <font color="4444FF">&</font><font color="4444FF">&</font> <font color="#2040a0">resolved</font><font color="4444FF">[</font><font color="#FF0000">1</font><font color="4444FF">]</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#008000">'<font color="#77dd77">\0</font>'</font><font color="4444FF">)</font>
|
||||
<font color="#2040a0">rootd</font> <font color="4444FF">=</font> <font color="#FF0000">1</font><font color="4444FF">;</font>
|
||||
<strong>else</strong>
|
||||
<font color="#2040a0">rootd</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
|
||||
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="4444FF">*</font><font color="#2040a0">wbuf</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">strlen</font><font color="4444FF">(</font><font color="#2040a0">resolved</font><font color="4444FF">)</font> <font color="4444FF">+</font> <font color="#2040a0">strlen</font><font color="4444FF">(</font><font color="#2040a0">wbuf</font><font color="4444FF">)</font> <font color="4444FF">+</font> <font color="4444FF">(</font><font color="#FF0000">1</font><font color="4444FF">-</font><font color="#2040a0">rootd</font><font color="4444FF">)</font> <font color="4444FF">+</font> <font color="#FF0000">1</font> <font color="4444FF">></font>
|
||||
<font color="#2040a0">MAXPATHLEN</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<font color="#2040a0">errno</font> <font color="4444FF">=</font> <font color="#2040a0">ENAMETOOLONG</font><font color="4444FF">;</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err1</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">rootd</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">strcat</font><font color="4444FF">(</font><font color="#2040a0">resolved</font>, <font color="#008000">"/"</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">strcat</font><font color="4444FF">(</font><font color="#2040a0">resolved</font>, <font color="#2040a0">wbuf</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
|
||||
<font color="#444444">/* Go back to where we came from. */</font>
|
||||
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">fchdir</font><font color="4444FF">(</font><font color="#2040a0">fd</font><font color="4444FF">)</font> <font color="4444FF"><</font> <font color="#FF0000">0</font><font color="4444FF">)</font> <font color="4444FF"><strong>{</strong></font>
|
||||
<font color="#2040a0">serrno</font> <font color="4444FF">=</font> <font color="#2040a0">errno</font><font color="4444FF">;</font>
|
||||
<strong>goto</strong> <font color="#2040a0">err2</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
|
||||
<font color="#444444">/* It's okay if the close fails, what's an fd more or less? */</font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">close</font><font color="4444FF">(</font><font color="#2040a0">fd</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<strong>return</strong> <font color="4444FF">(</font><font color="#2040a0">resolved</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
|
||||
<font color="#2040a0">err1</font><font color="4444FF">:</font> <font color="#2040a0">serrno</font> <font color="4444FF">=</font> <font color="#2040a0">errno</font><font color="4444FF">;</font>
|
||||
<font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">fchdir</font><font color="4444FF">(</font><font color="#2040a0">fd</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">err2</font><font color="4444FF">:</font> <font color="4444FF">(</font><strong>void</strong><font color="4444FF">)</font><font color="#2040a0">close</font><font color="4444FF">(</font><font color="#2040a0">fd</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="#2040a0">errno</font> <font color="4444FF">=</font> <font color="#2040a0">serrno</font><font color="4444FF">;</font>
|
||||
<strong>return</strong> <font color="4444FF">(</font><font color="#2040a0">NULL</font><font color="4444FF">)</font><font color="4444FF">;</font>
|
||||
<font color="4444FF"><strong>}</strong></font>
|
||||
|
||||
</pre>
|
||||
<hr>
|
||||
syntax highlighted by <a href="http://www.palfrader.org/code2html">Code2HTML</a>, v. 0.9.1
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,434 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V. Santos Costa and Universidade do Porto 1985-- *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: signal.c *
|
||||
* comments: Signal Handling & Debugger Support *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
#define HAS_CACHE_REGS 1
|
||||
|
||||
#include "Yap.h"
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if _WIN32
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "eval.h"
|
||||
#include "yapio.h"
|
||||
#ifdef TABLING
|
||||
#include "tab.macros.h"
|
||||
#endif /* TABLING */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#if HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
#include <tracer.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The InteractSIGINT function is called after a normal interrupt had been
|
||||
* caught.
|
||||
* It allows 6 possibilities: abort, continue, trace, debug, help, exit.
|
||||
*/
|
||||
static yap_signals InteractSIGINT(int ch) {
|
||||
#ifdef HAVE_SETBUF
|
||||
/* make sure we are not waiting for the end of line */
|
||||
setbuf(stdin, NULL);
|
||||
#endif
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
/* abort computation */
|
||||
return YAP_ABORT_SIGNAL;
|
||||
case 'b':
|
||||
/* continue */
|
||||
return YAP_BREAK_SIGNAL;
|
||||
case 'c':
|
||||
/* continue */
|
||||
return YAP_NO_SIGNAL;
|
||||
case 'd':
|
||||
/* enter debug mode */
|
||||
return YAP_DEBUG_SIGNAL;
|
||||
case 'e':
|
||||
/* exit */
|
||||
Yap_exit(1);
|
||||
return YAP_EXIT_SIGNAL;
|
||||
case 'g':
|
||||
/* stack dump */
|
||||
return YAP_STACK_DUMP_SIGNAL;
|
||||
case 't':
|
||||
/* start tracing */
|
||||
return YAP_TRACE_SIGNAL;
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
case 'T':
|
||||
toggle_low_level_trace();
|
||||
return YAP_NO_SIGNAL;
|
||||
#endif
|
||||
case 's':
|
||||
/* show some statistics */
|
||||
return YAP_STATISTICS_SIGNAL;
|
||||
case EOF:
|
||||
return YAP_NO_SIGNAL;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
/* show an helpful message */
|
||||
fprintf(stderr, "Please press one of:\n");
|
||||
fprintf(stderr, " a for abort\n c for continue\n d for debug\n");
|
||||
fprintf(stderr, " e for exit\n g for stack dump\n s for statistics\n t "
|
||||
"for trace\n");
|
||||
fprintf(stderr, " b for break\n");
|
||||
return YAP_NO_SIGNAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This function talks to the user about a signal. We assume we are in
|
||||
the context of the main Prolog thread (trivial in Unix, but hard in WIN32)
|
||||
*/
|
||||
static yap_signals ProcessSIGINT(void) {
|
||||
CACHE_REGS
|
||||
int ch, out;
|
||||
#if _WIN32
|
||||
if (!_isatty(0)) {
|
||||
return YAP_INT_SIGNAL;
|
||||
}
|
||||
#elif HAVE_ISATTY
|
||||
if (!isatty(0)) {
|
||||
return YAP_INT_SIGNAL;
|
||||
}
|
||||
#endif
|
||||
LOCAL_PrologMode |= AsyncIntMode;
|
||||
do {
|
||||
ch = Yap_GetCharForSIGINT();
|
||||
} while (!(out = InteractSIGINT(ch)));
|
||||
LOCAL_PrologMode &= ~AsyncIntMode;
|
||||
return (out);
|
||||
}
|
||||
|
||||
inline static void do_signal(int wid, yap_signals sig USES_REGS) {
|
||||
#if THREADS
|
||||
__sync_fetch_and_or(&REMOTE(wid)->Signals_, SIGNAL_TO_BIT(sig));
|
||||
if (!REMOTE_InterruptsDisabled(wid)) {
|
||||
REMOTE_ThreadHandle(wid).current_yaam_regs->CreepFlag_ =
|
||||
Unsigned(REMOTE_ThreadHandle(wid).current_yaam_regs->LCL0_);
|
||||
}
|
||||
#else
|
||||
LOCAL_Signals |= SIGNAL_TO_BIT(sig);
|
||||
if (!LOCAL_InterruptsDisabled) {
|
||||
CreepFlag = Unsigned(LCL0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static bool get_signal(yap_signals sig USES_REGS) {
|
||||
#if THREADS
|
||||
uint64_t old;
|
||||
|
||||
// first, clear the Creep Flag, now if someone sets it it is their problem
|
||||
CalculateStackGap(PASS_REGS1);
|
||||
// reset the flag
|
||||
if ((old = __sync_fetch_and_and(&LOCAL_Signals, ~SIGNAL_TO_BIT(sig))) !=
|
||||
SIGNAL_TO_BIT(sig)) {
|
||||
if (!LOCAL_InterruptsDisabled && LOCAL_Signals != 0) {
|
||||
CreepFlag = (CELL)LCL0;
|
||||
}
|
||||
if (!(old & SIGNAL_TO_BIT(sig))) {
|
||||
// not there?
|
||||
return FALSE;
|
||||
}
|
||||
// more likely case, we have other interrupts.
|
||||
return TRUE;
|
||||
}
|
||||
// success, we are good
|
||||
return TRUE;
|
||||
// should we set the flag?
|
||||
#else
|
||||
if (LOCAL_Signals & SIGNAL_TO_BIT(sig)) {
|
||||
LOCAL_Signals &= ~SIGNAL_TO_BIT(sig);
|
||||
if (!LOCAL_InterruptsDisabled && LOCAL_Signals != 0) {
|
||||
CreepFlag = (CELL)LCL0;
|
||||
} else {
|
||||
CalculateStackGap(PASS_REGS1);
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Function called to handle delayed interrupts.
|
||||
*/
|
||||
int Yap_HandleInterrupts(void) {
|
||||
CACHE_REGS
|
||||
yap_signals sig;
|
||||
|
||||
if (get_signal(YAP_INT_SIGNAL PASS_REGS)) {
|
||||
if ((sig = ProcessSIGINT()) != YAP_NO_SIGNAL)
|
||||
do_signal(worker_id, sig PASS_REGS);
|
||||
LOCAL_PrologMode &= ~InterruptMode;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Int p_creep(USES_REGS1) {
|
||||
Atom at;
|
||||
PredEntry *pred;
|
||||
|
||||
at = AtomCreep;
|
||||
pred = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, 1), 0));
|
||||
CreepCode = pred;
|
||||
do_signal(worker_id, YAP_CREEP_SIGNAL PASS_REGS);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int p_creep_fail(USES_REGS1) {
|
||||
Atom at;
|
||||
PredEntry *pred;
|
||||
|
||||
at = AtomCreep;
|
||||
pred = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, 1), 0));
|
||||
CreepCode = pred;
|
||||
do_signal(worker_id, YAP_CREEP_SIGNAL PASS_REGS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Int stop_creeping(USES_REGS1) {
|
||||
if (get_signal(YAP_CREEP_SIGNAL PASS_REGS)) {
|
||||
return Yap_unify(ARG1, TermTrue);
|
||||
}
|
||||
return Yap_unify(ARG1, TermFalse);
|
||||
}
|
||||
|
||||
static Int disable_debugging(USES_REGS1) {
|
||||
get_signal(YAP_CREEP_SIGNAL PASS_REGS);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Int creep_allowed(USES_REGS1) {
|
||||
if (PP != NULL) {
|
||||
get_signal(YAP_CREEP_SIGNAL PASS_REGS);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Yap_signal(yap_signals sig) {
|
||||
CACHE_REGS
|
||||
do_signal(worker_id, sig PASS_REGS);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static Int p_debug(USES_REGS1);
|
||||
#endif
|
||||
|
||||
void Yap_external_signal(int wid, yap_signals sig) {
|
||||
#if THREADS
|
||||
REGSTORE *regcache = REMOTE_ThreadHandle(wid).current_yaam_regs;
|
||||
#endif
|
||||
do_signal(wid, sig PASS_REGS);
|
||||
LOCAL_PrologMode &= ~InterruptMode;
|
||||
}
|
||||
|
||||
int Yap_get_signal__(yap_signals sig USES_REGS) {
|
||||
return get_signal(sig PASS_REGS);
|
||||
}
|
||||
|
||||
// the caller holds the lock.
|
||||
int Yap_has_signals__(yap_signals sig1, yap_signals sig2 USES_REGS) {
|
||||
return LOCAL_Signals & (SIGNAL_TO_BIT(sig1) | SIGNAL_TO_BIT(sig2));
|
||||
}
|
||||
|
||||
int Yap_only_has_signals__(yap_signals sig1, yap_signals sig2 USES_REGS) {
|
||||
uint64_t sigs = LOCAL_Signals;
|
||||
return sigs & (SIGNAL_TO_BIT(sig1) | SIGNAL_TO_BIT(sig2)) &&
|
||||
!(sigs & ~(SIGNAL_TO_BIT(sig1) | SIGNAL_TO_BIT(sig2)));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
volatile int volat = 0;
|
||||
|
||||
static Int p_debug(USES_REGS1) { /* $debug(+Flag) */
|
||||
int i = IntOfTerm(Deref(ARG1));
|
||||
while (volat == 0) {
|
||||
}
|
||||
if (i >= 'a' && i <= 'z')
|
||||
GLOBAL_Option[i - 96] = !GLOBAL_Option[i - 96];
|
||||
return 1;
|
||||
}
|
||||
void Yap_loop(void);
|
||||
void Yap_debug_end_loop(void);
|
||||
|
||||
void Yap_loop(void) {
|
||||
while (volat == 0)
|
||||
;
|
||||
}
|
||||
|
||||
void Yap_debug_end_loop(void) { volat = 1; }
|
||||
#endif
|
||||
|
||||
static Int first_signal(USES_REGS1) {
|
||||
Atom at;
|
||||
yap_signals sig;
|
||||
|
||||
while (TRUE) {
|
||||
uint64_t mask = LOCAL_Signals;
|
||||
if (mask == 0)
|
||||
return FALSE;
|
||||
#if HAVE___BUILTIN_FFSLL
|
||||
sig = __builtin_ffsll(mask);
|
||||
#elif HAVE_FFSLL
|
||||
sig = ffsll(mask);
|
||||
#else
|
||||
sig = Yap_msb(mask PASS_REGS) + 1;
|
||||
#endif
|
||||
if (get_signal(sig PASS_REGS)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
loop:
|
||||
switch (sig) {
|
||||
case YAP_INT_SIGNAL:
|
||||
sig = ProcessSIGINT();
|
||||
if (sig == YAP_INT_SIGNAL) {
|
||||
at = AtomSigInt;
|
||||
break;
|
||||
}
|
||||
if (sig != YAP_NO_SIGNAL)
|
||||
goto loop;
|
||||
return FALSE;
|
||||
case YAP_ABORT_SIGNAL:
|
||||
/* abort computation */
|
||||
LOCAL_PrologMode &= ~AsyncIntMode;
|
||||
if (LOCAL_PrologMode & (GCMode | ConsoleGetcMode | CritMode)) {
|
||||
LOCAL_PrologMode |= AbortMode;
|
||||
return -1;
|
||||
} else {
|
||||
Yap_Error(ABORT_EVENT, TermNil, "abort from console");
|
||||
}
|
||||
Yap_RestartYap(1);
|
||||
return FALSE;
|
||||
case YAP_CREEP_SIGNAL:
|
||||
at = AtomSigCreep;
|
||||
break;
|
||||
case YAP_TRACE_SIGNAL:
|
||||
at = AtomSigTrace;
|
||||
break;
|
||||
case YAP_DEBUG_SIGNAL:
|
||||
at = AtomSigDebug;
|
||||
break;
|
||||
case YAP_BREAK_SIGNAL:
|
||||
at = AtomSigBreak;
|
||||
break;
|
||||
case YAP_FAIL_SIGNAL:
|
||||
at = AtomFail;
|
||||
break;
|
||||
case YAP_STACK_DUMP_SIGNAL:
|
||||
at = AtomSigStackDump;
|
||||
break;
|
||||
case YAP_STATISTICS_SIGNAL:
|
||||
at = AtomSigStatistics;
|
||||
break;
|
||||
#ifdef SIGALRM
|
||||
case YAP_ALARM_SIGNAL:
|
||||
#endif
|
||||
case YAP_WINTIMER_SIGNAL:
|
||||
at = AtomSigAlarm;
|
||||
break;
|
||||
#ifdef SIGVTALRM
|
||||
case YAP_VTALARM_SIGNAL:
|
||||
at = AtomSigVTAlarm;
|
||||
break;
|
||||
#endif
|
||||
case YAP_EXIT_SIGNAL:
|
||||
Yap_exit(1);
|
||||
return FALSE;
|
||||
case YAP_WAKEUP_SIGNAL:
|
||||
at = AtomSigWakeUp;
|
||||
break;
|
||||
case YAP_ITI_SIGNAL:
|
||||
at = AtomSigIti;
|
||||
break;
|
||||
#ifdef SIGPIPE
|
||||
case YAP_PIPE_SIGNAL:
|
||||
at = AtomSigPipe;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
case YAP_HUP_SIGNAL:
|
||||
at = AtomSigHup;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
case YAP_USR1_SIGNAL:
|
||||
at = AtomSigUsr1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
case YAP_USR2_SIGNAL:
|
||||
at = AtomSigUsr2;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
case YAP_FPE_SIGNAL:
|
||||
at = AtomSigFPE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return Yap_unify(ARG1, MkAtomTerm(at));
|
||||
}
|
||||
|
||||
static Int continue_signals(USES_REGS1) { return first_signal(PASS_REGS1); }
|
||||
|
||||
void Yap_InitSignalCPreds(void) {
|
||||
/* Basic predicates for the debugger */
|
||||
Yap_InitCPred("$creep", 0, p_creep, SafePredFlag);
|
||||
Yap_InitCPred("$creep_fail", 0, p_creep_fail, SafePredFlag);
|
||||
Yap_InitCPred("$stop_creeping", 1, stop_creeping,
|
||||
NoTracePredFlag | HiddenPredFlag | SafePredFlag);
|
||||
Yap_InitCPred("$disable_debugging", 0, disable_debugging,
|
||||
NoTracePredFlag | HiddenPredFlag | SafePredFlag);
|
||||
Yap_InitCPred("$first_signal", 1, first_signal, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("$continue_signals", 0, continue_signals,
|
||||
SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("creep_allowed", 0, creep_allowed, 0);
|
||||
#ifdef DEBUG
|
||||
Yap_InitCPred("sys_debug", 1, p_debug, SafePredFlag | SyncPredFlag);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *Yap_InitSignals(int wid) {
|
||||
void *ptr = (void *)malloc(sizeof(UInt) * REMOTE_MaxActiveSignals(wid));
|
||||
return ptr;
|
||||
}
|
|
@ -0,0 +1,421 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: sort.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: sorting in Prolog *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
/* for the moment, follow Prolog's traditional mergesort */
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
/* fill in the even or the odd elements */
|
||||
#define M_EVEN 0
|
||||
#define M_ODD 1
|
||||
|
||||
static Int build_new_list(CELL *, Term CACHE_TYPE);
|
||||
static void simple_mergesort(CELL *, Int, int);
|
||||
static Int compact_mergesort(CELL *, Int, int);
|
||||
static int key_mergesort(CELL *, Int, int, Functor);
|
||||
static void adjust_vector(CELL *, Int);
|
||||
static Int p_sort( USES_REGS1 );
|
||||
static Int p_msort( USES_REGS1 );
|
||||
static Int p_ksort( USES_REGS1 );
|
||||
|
||||
/* copy to a new list of terms */
|
||||
static Int
|
||||
build_new_list(CELL *pt, Term t USES_REGS)
|
||||
{
|
||||
Int out = 0;
|
||||
if (IsVarTerm(t))
|
||||
return(-1);
|
||||
if (t == TermNil)
|
||||
return(0);
|
||||
restart:
|
||||
while (IsPairTerm(t)) {
|
||||
out++;
|
||||
pt[0] = HeadOfTerm(t);
|
||||
t = TailOfTerm(t);
|
||||
if (IsVarTerm(t))
|
||||
return(-1);
|
||||
if (t == TermNil) {
|
||||
return(out);
|
||||
}
|
||||
pt += 2;
|
||||
if (pt > ASP - 4096) {
|
||||
if (!Yap_gcl((ASP-HR)*sizeof(CELL), 2, ENV, gc_P(P,CP))) {
|
||||
Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
|
||||
return(FALSE);
|
||||
}
|
||||
t = Deref(ARG1);
|
||||
pt = HR;
|
||||
out = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* copy to a new list of terms */
|
||||
static
|
||||
void simple_mergesort(CELL *pt, Int size, int my_p)
|
||||
{
|
||||
|
||||
if (size > 2) {
|
||||
Int half_size = size / 2;
|
||||
CELL *pt_left, *pt_right, *end_pt, *end_pt_left;
|
||||
int left_p, right_p;
|
||||
|
||||
pt_right = pt + half_size*2;
|
||||
left_p = my_p^1;
|
||||
right_p = my_p;
|
||||
simple_mergesort(pt, half_size, left_p);
|
||||
simple_mergesort(pt_right, size-half_size, right_p);
|
||||
/* now implement a simple merge routine */
|
||||
|
||||
/* pointer to after the end of the list */
|
||||
end_pt = pt + 2*size;
|
||||
/* pointer to the element after the last element to the left */
|
||||
end_pt_left = pt+half_size*2;
|
||||
/* where is left list */
|
||||
pt_left = pt+left_p;
|
||||
/* where is right list */
|
||||
pt_right += right_p;
|
||||
/* where is new list */
|
||||
pt += my_p;
|
||||
/* while there are elements in the left or right vector do compares */
|
||||
while (pt_left < end_pt_left && pt_right < end_pt) {
|
||||
/* if the element to the left is larger than the one to the right */
|
||||
if (Yap_compare_terms(pt_left[0], pt_right[0]) <= 0) {
|
||||
/* copy the one to the left */
|
||||
pt[0] = pt_left[0];
|
||||
/* and avance the two pointers */
|
||||
pt += 2;
|
||||
pt_left += 2;
|
||||
} else {
|
||||
/* otherwise, copy the one to the right */
|
||||
pt[0] = pt_right[0];
|
||||
pt += 2;
|
||||
pt_right += 2;
|
||||
}
|
||||
}
|
||||
/* if any elements were left in the left vector just copy them */
|
||||
while (pt_left < end_pt_left) {
|
||||
pt[0] = pt_left[0];
|
||||
pt += 2;
|
||||
pt_left += 2;
|
||||
}
|
||||
/* if any elements were left in the right vector
|
||||
and they are in the wrong place, just copy them */
|
||||
if (my_p != right_p) {
|
||||
while(pt_right < end_pt) {
|
||||
pt[0] = pt_right[0];
|
||||
pt += 2;
|
||||
pt_right += 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (size > 1 && (Yap_compare_terms(pt[0],pt[2]) > 0)) {
|
||||
CELL t = pt[2];
|
||||
pt[2+my_p] = pt[0];
|
||||
pt[my_p] = t;
|
||||
} else if (my_p) {
|
||||
pt[1] = pt[0];
|
||||
if (size > 1)
|
||||
pt[3] = pt[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* copy to a new list of terms */
|
||||
static
|
||||
int key_mergesort(CELL *pt, Int size, int my_p, Functor FuncDMinus)
|
||||
{
|
||||
|
||||
if (size > 2) {
|
||||
Int half_size = size / 2;
|
||||
CELL *pt_left, *pt_right, *end_pt, *end_pt_left;
|
||||
int left_p, right_p;
|
||||
|
||||
pt_right = pt + half_size*2;
|
||||
left_p = my_p^1;
|
||||
right_p = my_p;
|
||||
if (!key_mergesort(pt, half_size, left_p, FuncDMinus))
|
||||
return(FALSE);
|
||||
if (!key_mergesort(pt_right, size-half_size, right_p, FuncDMinus))
|
||||
return(FALSE);
|
||||
/* now implement a simple merge routine */
|
||||
|
||||
/* pointer to after the end of the list */
|
||||
end_pt = pt + 2*size;
|
||||
/* pointer to the element after the last element to the left */
|
||||
end_pt_left = pt+half_size*2;
|
||||
/* where is left list */
|
||||
pt_left = pt+left_p;
|
||||
/* where is right list */
|
||||
pt_right += right_p;
|
||||
/* where is new list */
|
||||
pt += my_p;
|
||||
/* while there are elements in the left or right vector do compares */
|
||||
while (pt_left < end_pt_left && pt_right < end_pt) {
|
||||
/* if the element to the left is larger than the one to the right */
|
||||
Term t0 = pt_left[0] , t1 = pt_right[0];
|
||||
if (IsVarTerm(t0) || !IsApplTerm(t0) || FunctorOfTerm(t0) != FuncDMinus)
|
||||
return(FALSE);
|
||||
t0 = ArgOfTerm(1,t0);
|
||||
if (IsVarTerm(t1) || !IsApplTerm(t1) || FunctorOfTerm(t1) != FuncDMinus)
|
||||
return(FALSE);
|
||||
t1 = ArgOfTerm(1,t1);
|
||||
if (Yap_compare_terms(t0, t1) <= 0) {
|
||||
/* copy the one to the left */
|
||||
pt[0] = pt_left[0];
|
||||
/* and avance the two pointers */
|
||||
pt += 2;
|
||||
pt_left += 2;
|
||||
} else {
|
||||
/* otherwise, copy the one to the right */
|
||||
pt[0] = pt_right[0];
|
||||
pt += 2;
|
||||
pt_right += 2;
|
||||
}
|
||||
}
|
||||
/* if any elements were left in the left vector just copy them */
|
||||
while (pt_left < end_pt_left) {
|
||||
pt[0] = pt_left[0];
|
||||
pt += 2;
|
||||
pt_left += 2;
|
||||
}
|
||||
/* if any elements were left in the right vector
|
||||
and they are in the wrong place, just copy them */
|
||||
if (my_p != right_p) {
|
||||
while(pt_right < end_pt) {
|
||||
pt[0] = pt_right[0];
|
||||
pt += 2;
|
||||
pt_right += 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (size > 1) {
|
||||
Term t0 = pt[0], t1 = pt[2];
|
||||
if (IsVarTerm(t0) || !IsApplTerm(t0) || FunctorOfTerm(t0) != FuncDMinus)
|
||||
return(FALSE);
|
||||
t0 = ArgOfTerm(1,t0);
|
||||
if (IsVarTerm(t1) || !IsApplTerm(t1) || FunctorOfTerm(t1) != FuncDMinus)
|
||||
return(FALSE);
|
||||
t1 = ArgOfTerm(1,t1);
|
||||
if (Yap_compare_terms(t0,t1) > 0) {
|
||||
CELL t = pt[2];
|
||||
pt[2+my_p] = pt[0];
|
||||
pt[my_p] = t;
|
||||
} else if (my_p) {
|
||||
pt[1] = pt[0];
|
||||
pt[3] = pt[2];
|
||||
}
|
||||
} else {
|
||||
if (my_p)
|
||||
pt[1] = pt[0];
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* copy to a new list of terms and compress duplicates */
|
||||
static
|
||||
Int compact_mergesort(CELL *pt, Int size, int my_p)
|
||||
{
|
||||
|
||||
if (size > 2) {
|
||||
Int half_size = size / 2;
|
||||
CELL *pt_left, *pt_right, *end_pt_right, *end_pt_left;
|
||||
int left_p, right_p;
|
||||
Int lsize, rsize;
|
||||
|
||||
pt_right = pt + half_size*2;
|
||||
left_p = my_p^1;
|
||||
right_p = my_p;
|
||||
lsize = compact_mergesort(pt, half_size, left_p);
|
||||
rsize = compact_mergesort(pt_right, size-half_size, right_p);
|
||||
/* now implement a simple merge routine */
|
||||
|
||||
/* where is left list */
|
||||
pt_left = pt+left_p;
|
||||
/* pointer to the element after the last element to the left */
|
||||
end_pt_left = pt+2*lsize;
|
||||
/* where is right list */
|
||||
pt_right += right_p;
|
||||
/* pointer to after the end of the list */
|
||||
end_pt_right = pt_right + 2*rsize;
|
||||
/* where is new list */
|
||||
pt += my_p;
|
||||
size = 0;
|
||||
/* while there are elements in the left or right vector do compares */
|
||||
while (pt_left < end_pt_left && pt_right < end_pt_right) {
|
||||
/* if the element to the left is larger than the one to the right */
|
||||
Int cmp = Yap_compare_terms(pt_left[0], pt_right[0]);
|
||||
if (cmp < (Int)0) {
|
||||
/* copy the one to the left */
|
||||
pt[0] = pt_left[0];
|
||||
/* and avance the two pointers */
|
||||
pt += 2;
|
||||
size ++;
|
||||
pt_left += 2;
|
||||
} else if (cmp == (Int)0) {
|
||||
/* otherwise, just skip one of them, anyone */
|
||||
pt_left += 2;
|
||||
} else {
|
||||
/* otherwise, copy the one to the right */
|
||||
pt[0] = pt_right[0];
|
||||
pt += 2;
|
||||
pt_right += 2;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
/* if any elements were left in the left vector just copy them */
|
||||
while (pt_left < end_pt_left) {
|
||||
pt[0] = pt_left[0];
|
||||
pt += 2;
|
||||
pt_left += 2;
|
||||
size++;
|
||||
}
|
||||
/* if any elements were left in the right vector
|
||||
and they are in the wrong place, just copy them */
|
||||
while(pt_right < end_pt_right) {
|
||||
pt[0] = pt_right[0];
|
||||
pt += 2;
|
||||
pt_right += 2;
|
||||
size++;
|
||||
}
|
||||
return(size);
|
||||
} else if (size == 2) {
|
||||
Int cmp = Yap_compare_terms(pt[0],pt[2]);
|
||||
if (cmp > 0) {
|
||||
/* swap */
|
||||
CELL t = pt[2];
|
||||
pt[2+my_p] = pt[0];
|
||||
pt[my_p] = t;
|
||||
return(2);
|
||||
} else if (cmp == 0) {
|
||||
if (my_p)
|
||||
pt[1] = pt[0];
|
||||
return(1);
|
||||
} else {
|
||||
if (my_p) {
|
||||
pt[1] = pt[0];
|
||||
pt[3] = pt[2];
|
||||
}
|
||||
return(2);
|
||||
}
|
||||
} else {
|
||||
/* size = 1 */
|
||||
if (my_p)
|
||||
pt[1] = pt[0];
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
adjust_vector(CELL *pt, Int size)
|
||||
{
|
||||
/* the elements are where they should be */
|
||||
CELL *ptf = pt + 2*(size-1);
|
||||
pt ++;
|
||||
while (pt < ptf) {
|
||||
pt[0] = AbsPair(pt+1);
|
||||
pt += 2;
|
||||
}
|
||||
/* close the list */
|
||||
pt[0] = TermNil;
|
||||
}
|
||||
|
||||
static Int
|
||||
p_sort( USES_REGS1 )
|
||||
{
|
||||
/* use the heap to build a new list */
|
||||
CELL *pt = HR;
|
||||
Term out;
|
||||
/* list size */
|
||||
Int size;
|
||||
size = build_new_list(pt, Deref(ARG1) PASS_REGS);
|
||||
if (size < 0)
|
||||
return(FALSE);
|
||||
if (size < 2)
|
||||
return(Yap_unify(ARG1, ARG2));
|
||||
pt = HR; /* because of possible garbage collection */
|
||||
/* make sure no one writes on our temp data structure */
|
||||
HR += size*2;
|
||||
/* reserve the necessary space */
|
||||
size = compact_mergesort(pt, size, M_EVEN);
|
||||
/* reajust space */
|
||||
HR = pt+size*2;
|
||||
adjust_vector(pt, size);
|
||||
out = AbsPair(pt);
|
||||
return(Yap_unify(out, ARG2));
|
||||
}
|
||||
|
||||
static Int
|
||||
p_msort( USES_REGS1 )
|
||||
{
|
||||
/* use the heap to build a new list */
|
||||
CELL *pt = HR;
|
||||
Term out;
|
||||
/* list size */
|
||||
Int size;
|
||||
size = build_new_list(pt, Deref(ARG1) PASS_REGS);
|
||||
if (size < 0)
|
||||
return(FALSE);
|
||||
if (size < 2)
|
||||
return(Yap_unify(ARG1, ARG2));
|
||||
pt = HR; /* because of possible garbage collection */
|
||||
/* reserve the necessary space */
|
||||
HR += size*2;
|
||||
simple_mergesort(pt, size, M_EVEN);
|
||||
adjust_vector(pt, size);
|
||||
out = AbsPair(pt);
|
||||
return(Yap_unify(out, ARG2));
|
||||
}
|
||||
|
||||
static Int
|
||||
p_ksort( USES_REGS1 )
|
||||
{
|
||||
/* use the heap to build a new list */
|
||||
CELL *pt = HR;
|
||||
Term out;
|
||||
/* list size */
|
||||
Int size;
|
||||
size = build_new_list(pt, Deref(ARG1) PASS_REGS);
|
||||
if (size < 0)
|
||||
return(FALSE);
|
||||
if (size < 2)
|
||||
return(Yap_unify(ARG1, ARG2));
|
||||
/* reserve the necessary space */
|
||||
pt = HR; /* because of possible garbage collection */
|
||||
HR += size*2;
|
||||
if (!key_mergesort(pt, size, M_EVEN, FunctorMinus))
|
||||
return(FALSE);
|
||||
adjust_vector(pt, size);
|
||||
out = AbsPair(pt);
|
||||
return(Yap_unify(out, ARG2));
|
||||
}
|
||||
|
||||
void
|
||||
Yap_InitSortPreds(void)
|
||||
{
|
||||
Yap_InitCPred("$sort", 2, p_sort, 0);
|
||||
Yap_InitCPred("$msort", 2, p_msort, 0);
|
||||
Yap_InitCPred("$keysort", 2, p_ksort, 0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,517 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog @(#)amidefs.h 1.3 3/15/90
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: tracer.h *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: definitions for low level tracer *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
#include "Yap.h"
|
||||
|
||||
#ifdef LOW_LEVEL_TRACER
|
||||
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#include "attvar.h"
|
||||
#include "yapio.h"
|
||||
#include "clause.h"
|
||||
#include "tracer.h"
|
||||
|
||||
static void send_tracer_message(char *start, char *name, Int arity, char *mname,
|
||||
CELL *args) {
|
||||
if (name == NULL) {
|
||||
#ifdef YAPOR
|
||||
fprintf(stderr, "(%d)%s", worker_id, start);
|
||||
#else
|
||||
fprintf(stderr, "%s", start);
|
||||
#endif
|
||||
} else {
|
||||
int i;
|
||||
|
||||
if (arity) {
|
||||
if (args)
|
||||
fprintf(stderr, "%s %s:%s(", start, mname, name);
|
||||
else
|
||||
fprintf(stderr, "%s %s:%s/%lu", start, mname, name,
|
||||
(unsigned long int)arity);
|
||||
} else {
|
||||
fprintf(stderr, "%s %s:%s", start, mname, name);
|
||||
}
|
||||
if (args) {
|
||||
for (i = 0; i < arity; i++) {
|
||||
if (i > 0)
|
||||
fprintf(stderr, ",");
|
||||
Yap_plwrite(args[i], NULL, 15, Handle_vars_f | AttVar_Portray_f,
|
||||
GLOBAL_MaxPriority);
|
||||
}
|
||||
if (arity) {
|
||||
fprintf(stderr, ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
unsigned long long vsc_count;
|
||||
#else
|
||||
unsigned long vsc_count;
|
||||
#endif
|
||||
|
||||
#if THREADS
|
||||
static int thread_trace;
|
||||
#endif
|
||||
|
||||
/*
|
||||
static int
|
||||
check_trail_consistency(void) {
|
||||
tr_fr_ptr ptr = TR;
|
||||
while (ptr > (CELL *)LOCAL_TrailBase) {
|
||||
ptr = --ptr;
|
||||
if (!IsVarTerm(TrailTerm(ptr))) {
|
||||
if (IsApplTerm(TrailTerm(ptr))) {
|
||||
CELL *cptr = (CELL *)ptr;
|
||||
ptr = (tr_fr_ptr)(cptr-1);
|
||||
} else {
|
||||
if (IsPairTerm(TrailTerm(ptr))) {
|
||||
CELL *p = RepPair(TrailTerm(ptr));
|
||||
if IsAttVar(p) continue;
|
||||
}
|
||||
printf("Oops at call %ld, B->cp(%p) TR(%p) pt(%p)\n",
|
||||
vsc_count,B->cp_tr, TR, ptr);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
*/
|
||||
|
||||
volatile int v;
|
||||
|
||||
CELL old_value = 0L, old_value2 = 0L;
|
||||
|
||||
void jmp_deb(int), jmp_deb2(void);
|
||||
|
||||
void jmp_deb2(void) { fprintf(stderr, "Here\n"); }
|
||||
|
||||
void jmp_deb(int i) {
|
||||
if (i)
|
||||
printf("Here we go %ld\n", old_value++);
|
||||
if (old_value == 716)
|
||||
jmp_deb2();
|
||||
}
|
||||
|
||||
struct various_codes *sc;
|
||||
|
||||
/*
|
||||
CELL array[332];
|
||||
|
||||
int found = FALSE;
|
||||
|
||||
static void
|
||||
check_area(void)
|
||||
{
|
||||
int i, first = -1;
|
||||
for (i= 0; i < 332; i++) {
|
||||
if (array[i] !=((CELL *)0x187a800)[i]) {
|
||||
if (first != -1) {
|
||||
first = i;
|
||||
found = TRUE;
|
||||
}
|
||||
fprintf(stderr,"%lld changed %d\n",vsc_count,i);
|
||||
}
|
||||
array[i] = ((CELL *)0x187a800)[i];
|
||||
}
|
||||
if (first != -1)
|
||||
jmp_deb(i);
|
||||
}
|
||||
*/
|
||||
|
||||
//PredEntry *old_p[10000];
|
||||
//Term old_x1[10000], old_x2[10000], old_x3[10000];
|
||||
|
||||
// static CELL oldv;
|
||||
|
||||
void low_level_trace(yap_low_level_port port, PredEntry *pred, CELL *args) {
|
||||
CACHE_REGS
|
||||
char *s;
|
||||
char *mname;
|
||||
Int arity;
|
||||
/* extern int gc_calls; */
|
||||
vsc_count++;
|
||||
// if (HR < ASP ) return;
|
||||
// fif (vsc_count == 12534) jmp_deb( 2 );
|
||||
#if __ANDROID__ && 0
|
||||
PredEntry *ap = pred;
|
||||
if (pred && port == enter_pred) {
|
||||
UInt flags = ap->PredFlags;
|
||||
if (ap->ArityOfPE && ap->ModuleOfPred != IDB_MODULE)
|
||||
__android_log_print(ANDROID_LOG_INFO, "YAP ", " %s/%ld %lx\n",
|
||||
NameOfFunctor(ap->FunctorOfPred)->StrOfAE,
|
||||
ap->ArityOfPE, flags);
|
||||
/* printf(" %s/%ld %lx\n", NameOfFunctor(ap->FunctorOfPred)->StrOfAE,
|
||||
* ap->ArityOfPE, flags); */
|
||||
else if (ap->ModuleOfPred != IDB_MODULE)
|
||||
__android_log_print(ANDROID_LOG_INFO, "YAP ", " %s/%ld %lx\n",
|
||||
((Atom)(ap->FunctorOfPred))->StrOfAE, ap->ArityOfPE,
|
||||
flags);
|
||||
/* printf(" %s/%ld %lx\n", ((Atom)(ap->FunctorOfPred))->StrOfAE,
|
||||
* ap->ArityOfPE, flags); */
|
||||
__android_log_print(ANDROID_LOG_INFO, "YAP ", " %x ", ap->src.OwnerFile);
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
|
||||
// if (!worker_id) return;
|
||||
LOCK(Yap_low_level_trace_lock);
|
||||
sc = Yap_heap_regs;
|
||||
// if (vsc_count == 161862) jmp_deb(1);
|
||||
#ifdef THREADS
|
||||
LOCAL_ThreadHandle.thread_inst_count++;
|
||||
#endif
|
||||
#ifdef COMMENTED
|
||||
fprintf(stderr, "in %p\n");
|
||||
CELL *gc_ENV = ENV;
|
||||
while (gc_ENV != NULL) { /* no more environments */
|
||||
fprintf(stderr, "%ld\n", LCL0 - gc_ENV);
|
||||
gc_ENV = (CELL *)gc_ENV[E_E]; /* link to prev
|
||||
* environment */
|
||||
}
|
||||
return;
|
||||
{
|
||||
choiceptr b_p = B;
|
||||
while (b_p) {
|
||||
fprintf(stderr, "%p %ld\n", b_p, Yap_op_from_opcode(b_p->cp_ap->opc));
|
||||
b_p = b_p->cp_b;
|
||||
}
|
||||
}
|
||||
{
|
||||
choiceptr myB = B;
|
||||
while (myB)
|
||||
myB = myB->cp_b;
|
||||
}
|
||||
//*(H0+(0xb65f2850-0xb64b2008)/sizeof(CELL))==0xc ||
|
||||
// 0x4fd4d
|
||||
if (vsc_count > 1388060LL && vsc_count < 1388070LL) {
|
||||
if (vsc_count == 1388061LL)
|
||||
jmp_deb(1);
|
||||
if (vsc_count % 1LL == 0) {
|
||||
UInt sz = Yap_regp->H0_[17];
|
||||
UInt end = sizeof(MP_INT) / sizeof(CELL) + sz + 1;
|
||||
fprintf(stderr, "VAL %lld %d %x/%x\n", vsc_count, sz, H0[16],
|
||||
H0[16 + end]);
|
||||
}
|
||||
} else
|
||||
return;
|
||||
{
|
||||
tr_fr_ptr pt = (tr_fr_ptr)LOCAL_TrailBase;
|
||||
if (pt[140].term == 0 && pt[140].value != 0)
|
||||
jmp_deb(1);
|
||||
}
|
||||
if (worker_id != 04 || worker_id != 03)
|
||||
return;
|
||||
// if (vsc_count == 218280)
|
||||
// vsc_xstop = 1;
|
||||
if (vsc_count < 1468068888) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (port != enter_pred || !pred || pred->ArityOfPE != 4 ||
|
||||
strcmp(RepAtom(NameOfFunctor(pred->FunctorOfPred))->StrOfAE,
|
||||
"in_between_target_phrases")) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (vsc_count < 1246949400LL) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (vsc_count == 1246949493LL)
|
||||
vsc_xstop = TRUE;
|
||||
if (vsc_count < 5646100000LL) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (vsc_count == 5646100441LL)
|
||||
vsc_xstop = TRUE;
|
||||
if (vsc_count < 2923351500LL) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (vsc_count == 123536441LL)
|
||||
vsc_xstop = 1;
|
||||
if (vsc_count < 5530257LL) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (vsc_count == 9414280LL) {
|
||||
vsc_xstop = TRUE;
|
||||
}
|
||||
if (vsc_count < 3399741LL) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (TR_FZ > TR)
|
||||
jmp_deb(1);
|
||||
{
|
||||
tr_fr_ptr pt = (tr_fr_ptr)LOCAL_TrailBase;
|
||||
if (pt[153].term == 0 && pt[153].value == 0 && pt[154].term != 0 &&
|
||||
pt[154].value != 0 && (TR > pt + 154 || TR_FZ > pt + 154))
|
||||
jmp_deb(2);
|
||||
if (pt[635].term == 0 && pt[635].value == 0 && pt[636].term != 0 &&
|
||||
pt[636].value != 0 && (TR > pt + 636 || TR_FZ > pt + 636))
|
||||
jmp_deb(3);
|
||||
if (pt[138].term == 0 && pt[138].value == 0 && pt[139].term != 0 &&
|
||||
pt[139].value != 0 && (TR > pt + 138 || TR_FZ > pt + 138))
|
||||
jmp_deb(4);
|
||||
}
|
||||
if (vsc_count == 287939LL)
|
||||
jmp_deb(1);
|
||||
if (vsc_count == 173118LL)
|
||||
jmp_deb(1);
|
||||
if (!(vsc_count >= 287934LL && vsc_count <= 287939LL) &&
|
||||
!(vsc_count >= 173100LL && vsc_count <= 173239LL) && vsc_count != -1)
|
||||
return;
|
||||
if (vsc_count == 51021) {
|
||||
printf("Here I go\n");
|
||||
}
|
||||
if (vsc_count < 52000) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (vsc_count > 52000)
|
||||
exit(0);
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
if (vsc_count == 837074) {
|
||||
printf("Here I go\n");
|
||||
}
|
||||
if (gc_calls < 1) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
{
|
||||
CELL *env_ptr = ENV;
|
||||
PredEntry *p;
|
||||
|
||||
while (env_ptr) {
|
||||
PredEntry *pe = EnvPreg(env_ptr[E_CP]);
|
||||
|
||||
printf("%p->", env_ptr, pe);
|
||||
if (vsc_count == 52LL)
|
||||
printf("\n");
|
||||
if (p == pe) {
|
||||
UNLOCK(Yap_heap_regs->low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (env_ptr != NULL)
|
||||
env_ptr = (CELL *)(env_ptr[E_E]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
fprintf(stderr, "%lld %ld ", vsc_count, LCL0 - (CELL *)B);
|
||||
#if defined(THREADS) || defined(YAPOR)
|
||||
fprintf(stderr, "(%d)", worker_id);
|
||||
#endif
|
||||
/* check_trail_consistency(); */
|
||||
if (pred == NULL) {
|
||||
UNLOCK(Yap_low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
if (pred->ModuleOfPred == PROLOG_MODULE) {
|
||||
if (!LOCAL_do_trace_primitives) {
|
||||
UNLOCK(Yap_low_level_trace_lock);
|
||||
return;
|
||||
}
|
||||
mname = "prolog";
|
||||
} else {
|
||||
mname = RepAtom(AtomOfTerm(Yap_Module_Name(pred)))->StrOfAE;
|
||||
}
|
||||
switch (port) {
|
||||
case enter_pred:
|
||||
arity = pred->ArityOfPE;
|
||||
if (arity == 0) {
|
||||
s = (char *)RepAtom((Atom)pred->FunctorOfPred)->StrOfAE;
|
||||
} else {
|
||||
s = (char *)RepAtom(NameOfFunctor((pred->FunctorOfPred)))->StrOfAE;
|
||||
}
|
||||
/* if ((pred->ModuleOfPred == 0) && (s[0] == '$'))
|
||||
return; */
|
||||
send_tracer_message("CALL: ", s, arity, mname, args);
|
||||
break;
|
||||
case try_or:
|
||||
send_tracer_message("TRY_OR ", NULL, 0, NULL, args);
|
||||
break;
|
||||
case retry_or:
|
||||
send_tracer_message("FAIL ", NULL, 0, NULL, args);
|
||||
send_tracer_message("RETRY_OR ", NULL, 0, NULL, args);
|
||||
break;
|
||||
case retry_table_generator:
|
||||
send_tracer_message("FAIL ", NULL, 0, NULL, args);
|
||||
mname = (char *)RepAtom(AtomOfTerm(Yap_Module_Name(pred)))->StrOfAE;
|
||||
arity = pred->ArityOfPE;
|
||||
if (arity == 0)
|
||||
s = (char *)RepAtom((Atom)pred->FunctorOfPred)->StrOfAE;
|
||||
else
|
||||
s = (char *)RepAtom(NameOfFunctor((pred->FunctorOfPred)))->StrOfAE;
|
||||
send_tracer_message("RETRY GENERATOR: ", s, arity, mname, args);
|
||||
break;
|
||||
case retry_table_consumer:
|
||||
send_tracer_message("FAIL ", NULL, 0, NULL, args);
|
||||
mname = (char *)RepAtom(AtomOfTerm(Yap_Module_Name(pred)))->StrOfAE;
|
||||
arity = pred->ArityOfPE;
|
||||
if (arity == 0) {
|
||||
s = (char *)RepAtom((Atom)pred->FunctorOfPred)->StrOfAE;
|
||||
send_tracer_message("RETRY CONSUMER: ", s, 0, mname, NULL);
|
||||
} else {
|
||||
s = (char *)RepAtom(NameOfFunctor((pred->FunctorOfPred)))->StrOfAE;
|
||||
send_tracer_message("RETRY CONSUMER: ", s, pred->ArityOfPE, mname, NULL);
|
||||
}
|
||||
break;
|
||||
case retry_table_loader:
|
||||
send_tracer_message("FAIL ", NULL, 0, NULL, args);
|
||||
if (pred == UndefCode) {
|
||||
send_tracer_message("RETRY LOADER ", NULL, 0, NULL, NULL);
|
||||
} else {
|
||||
mname = (char *)RepAtom(AtomOfTerm(Yap_Module_Name(pred)))->StrOfAE;
|
||||
arity = pred->ArityOfPE;
|
||||
if (arity == 0)
|
||||
s = (char *)RepAtom((Atom)pred->FunctorOfPred)->StrOfAE;
|
||||
else
|
||||
s = (char *)RepAtom(NameOfFunctor((pred->FunctorOfPred)))->StrOfAE;
|
||||
send_tracer_message("RETRY LOADER: ", s, 0, mname, NULL);
|
||||
}
|
||||
break;
|
||||
case retry_pred:
|
||||
send_tracer_message("FAIL ", NULL, 0, NULL, args);
|
||||
if (pred != NULL) {
|
||||
mname = (char *)RepAtom(AtomOfTerm(Yap_Module_Name(pred)))->StrOfAE;
|
||||
arity = pred->ArityOfPE;
|
||||
if (pred->ModuleOfPred == IDB_MODULE) {
|
||||
s = "recorded";
|
||||
arity = 3;
|
||||
} else if (arity == 0) {
|
||||
s = (char *)RepAtom((Atom)pred->FunctorOfPred)->StrOfAE;
|
||||
} else {
|
||||
s = (char *)RepAtom(NameOfFunctor((pred->FunctorOfPred)))->StrOfAE;
|
||||
}
|
||||
send_tracer_message("RETRY: ", s, arity, mname, args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
fflush(NULL);
|
||||
UNLOCK(Yap_low_level_trace_lock);
|
||||
}
|
||||
|
||||
void toggle_low_level_trace(void) {
|
||||
Yap_do_low_level_trace = !Yap_do_low_level_trace;
|
||||
}
|
||||
|
||||
static Int start_low_level_trace(USES_REGS1) {
|
||||
Yap_do_low_level_trace = TRUE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static Int total_choicepoints(USES_REGS1) {
|
||||
return Yap_unify(MkIntegerTerm(LOCAL_total_choicepoints), ARG1);
|
||||
}
|
||||
|
||||
static Int reset_total_choicepoints(USES_REGS1) {
|
||||
LOCAL_total_choicepoints = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Int show_low_level_trace(USES_REGS1) {
|
||||
fprintf(stderr, "Call counter=%lld\n", vsc_count);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#ifdef THREADS
|
||||
static Int start_low_level_trace2(USES_REGS1) {
|
||||
thread_trace = IntegerOfTerm(Deref(ARG1)) + 1;
|
||||
Yap_do_low_level_trace = TRUE;
|
||||
return (TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/** @pred stop_low_level_trace
|
||||
|
||||
Stop displaying messages at procedure entry and retry.
|
||||
|
||||
Note that using this compile-time option will slow down execution, even if
|
||||
messages are
|
||||
not being output.
|
||||
|
||||
*/
|
||||
static Int stop_low_level_trace(USES_REGS1) {
|
||||
Yap_do_low_level_trace = FALSE;
|
||||
LOCAL_do_trace_primitives = TRUE;
|
||||
#if DEBUG_LOCKS
|
||||
debug_locks = TRUE;
|
||||
#endif
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
volatile int v_wait;
|
||||
|
||||
static Int vsc_wait(USES_REGS1) {
|
||||
while (!v_wait)
|
||||
;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Int vsc_go(USES_REGS1) {
|
||||
v_wait = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Yap_InitLowLevelTrace(void) {
|
||||
Yap_InitCPred("start_low_level_trace", 0, start_low_level_trace,
|
||||
SafePredFlag);
|
||||
Yap_InitCPred("$start_low_level_trace", 0, start_low_level_trace,
|
||||
SafePredFlag);
|
||||
/** @pred start_low_level_trace
|
||||
|
||||
|
||||
Begin display of messages at procedure entry and retry.
|
||||
|
||||
|
||||
*/
|
||||
#if THREADS
|
||||
Yap_InitCPred("start_low_level_trace", 1, start_low_level_trace2,
|
||||
SafePredFlag);
|
||||
#endif
|
||||
Yap_InitCPred("stop_low_level_trace", 0, stop_low_level_trace, SafePredFlag);
|
||||
Yap_InitCPred("show_low_level_trace", 0, show_low_level_trace, SafePredFlag);
|
||||
Yap_InitCPred("$stop_low_level_trace", 0, stop_low_level_trace, SafePredFlag);
|
||||
Yap_InitCPred("total_choicepoints", 1, total_choicepoints, SafePredFlag);
|
||||
Yap_InitCPred("reset_total_choicepoints", 0, reset_total_choicepoints,
|
||||
SafePredFlag);
|
||||
Yap_InitCPred("vsc_wait", 0, vsc_wait, SafePredFlag);
|
||||
Yap_InitCPred("vsc_go", 0, vsc_go, SafePredFlag);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static null(USES_REGS1) { return true; }
|
||||
|
||||
void Yap_InitLowLevelTrace(void) {
|
||||
Yap_InitCPred("$start_low_level_trace", 0, null,
|
||||
SafePredFlag | HiddenPredFlag);
|
||||
Yap_InitCPred("$stop_low_level_trace", 0, null,
|
||||
SafePredFlag | HiddenPredFlag);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,551 @@
|
|||
#if 0
|
||||
{
|
||||
{
|
||||
#endif
|
||||
/************************************************************************ \
|
||||
* Basic Primitive Predicates *
|
||||
\************************************************************************/
|
||||
|
||||
Op(p_atom_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, atom_x_unk);
|
||||
atom_x_nvar:
|
||||
if (IsAtomTerm(d0) && !IsBlob(AtomOfTerm(d0))) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, atom_x_unk, atom_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_atom_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, atom_y_unk);
|
||||
atom_y_nvar:
|
||||
if (IsAtomTerm(d0) && !IsBlob(AtomOfTerm(d0))) {
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
derefa_body(d0, pt0, atom_y_unk, atom_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_atomic_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, atomic_x_unk);
|
||||
atomic_x_nvar:
|
||||
/* non variable */
|
||||
if (IsAtomicTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, atomic_x_unk, atomic_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_atomic_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, atomic_y_unk);
|
||||
atomic_y_nvar:
|
||||
/* non variable */
|
||||
if (IsAtomicTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
derefa_body(d0, pt0, atomic_y_unk, atomic_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_integer_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, integer_x_unk);
|
||||
integer_x_nvar:
|
||||
/* non variable */
|
||||
if (IsIntTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
if (IsApplTerm(d0)) {
|
||||
Functor f0 = FunctorOfTerm(d0);
|
||||
if (IsExtensionFunctor(f0)) {
|
||||
switch ((CELL)f0) {
|
||||
case (CELL)FunctorBigInt:
|
||||
{ CELL *pt = RepAppl(d0);
|
||||
if ( pt[1] != BIG_INT ) {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
break;
|
||||
case (CELL)FunctorLongInt:
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
break;
|
||||
default:
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
}
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, integer_x_unk, integer_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_integer_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, integer_y_unk);
|
||||
integer_y_nvar:
|
||||
/* non variable */
|
||||
if (IsIntTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
if (IsApplTerm(d0)) {
|
||||
Functor f0 = FunctorOfTerm(d0);
|
||||
if (IsExtensionFunctor(f0)) {
|
||||
switch ((CELL)f0) {
|
||||
case (CELL)FunctorBigInt:
|
||||
{ CELL *pt = RepAppl(d0);
|
||||
if ( pt[1] != BIG_INT ) {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
break;
|
||||
case (CELL)FunctorLongInt:
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
break;
|
||||
default:
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
}
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
|
||||
derefa_body(d0, pt0, integer_y_unk, integer_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_nonvar_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, nonvar_x_unk);
|
||||
nonvar_x_nvar:
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, nonvar_x_unk, nonvar_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_nonvar_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, nonvar_y_unk);
|
||||
nonvar_y_nvar:
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
|
||||
derefa_body(d0, pt0, nonvar_y_unk, nonvar_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_number_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, number_x_unk);
|
||||
number_x_nvar:
|
||||
/* non variable */
|
||||
if (IsIntTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
if (IsApplTerm(d0)) {
|
||||
Functor f0 = FunctorOfTerm(d0);
|
||||
if (IsExtensionFunctor(f0)) {
|
||||
switch ((CELL)f0) {
|
||||
case (CELL)FunctorBigInt:
|
||||
{ CELL *pt = RepAppl(d0);
|
||||
if ( pt[1] != BIG_RATIONAL || pt[1] != BIG_INT ) {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
case (CELL)FunctorLongInt:
|
||||
case (CELL)FunctorDouble:
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
break;
|
||||
default:
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
}
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, number_x_unk, number_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_number_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, number_y_unk);
|
||||
number_y_nvar:
|
||||
/* non variable */
|
||||
/* non variable */
|
||||
if (IsIntTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
if (IsApplTerm(d0)) {
|
||||
Functor f0 = FunctorOfTerm(d0);
|
||||
if (IsExtensionFunctor(f0)) {
|
||||
switch ((CELL)f0) {
|
||||
case (CELL)FunctorBigInt:
|
||||
{ CELL *pt = RepAppl(d0);
|
||||
if ( pt[1] != BIG_RATIONAL || pt[1] != BIG_INT ) {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (CELL)FunctorLongInt:
|
||||
case (CELL)FunctorDouble:
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
break;
|
||||
default:
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
}
|
||||
}
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
|
||||
derefa_body(d0, pt0, number_y_unk, number_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_var_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, var_x_unk);
|
||||
var_x_nvar:
|
||||
/* non variable */
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, var_x_unk, var_x_nvar);
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_var_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, var_y_unk);
|
||||
var_y_nvar:
|
||||
/* non variable */
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
|
||||
derefa_body(d0, pt0, var_y_unk, var_y_nvar);
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_db_ref_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, dbref_x_unk);
|
||||
dbref_x_nvar:
|
||||
/* non variable */
|
||||
if (IsDBRefTerm(d0)) {
|
||||
/* only allow references to the database, not general references
|
||||
* to go through. */
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, dbref_x_unk, dbref_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_db_ref_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, dbref_y_unk);
|
||||
dbref_y_nvar:
|
||||
/* non variable */
|
||||
if (IsDBRefTerm(d0)) {
|
||||
/* only allow references to the database, not general references
|
||||
* to go through. */
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
derefa_body(d0, pt0, dbref_y_unk, dbref_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_primitive_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, primi_x_unk);
|
||||
primi_x_nvar:
|
||||
/* non variable */
|
||||
if (IsPrimitiveTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, primi_x_unk, primi_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_primitive_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, primi_y_unk);
|
||||
primi_y_nvar:
|
||||
/* non variable */
|
||||
if (IsPrimitiveTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
derefa_body(d0, pt0, primi_y_unk, primi_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_compound_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, compound_x_unk);
|
||||
compound_x_nvar:
|
||||
/* non variable */
|
||||
if (IsPairTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
else if (IsApplTerm(d0)) {
|
||||
if (IsExtensionFunctor(FunctorOfTerm(d0))) {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, compound_x_unk, compound_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_compound_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, compound_y_unk);
|
||||
compound_y_nvar:
|
||||
/* non variable */
|
||||
if (IsPairTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
else if (IsApplTerm(d0)) {
|
||||
if (IsExtensionFunctor(FunctorOfTerm(d0))) {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
else {
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
}
|
||||
|
||||
derefa_body(d0, pt0, compound_y_unk, compound_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_float_x, xl);
|
||||
BEGD(d0);
|
||||
d0 = XREG(PREG->y_u.xl.x);
|
||||
deref_head(d0, float_x_unk);
|
||||
float_x_nvar:
|
||||
/* non variable */
|
||||
if (IsFloatTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, xl);
|
||||
GONext();
|
||||
}
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
|
||||
BEGP(pt0);
|
||||
deref_body(d0, pt0, float_x_unk, float_x_nvar);
|
||||
PREG = PREG->y_u.xl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
||||
|
||||
Op(p_float_y, yl);
|
||||
BEGD(d0);
|
||||
BEGP(pt0);
|
||||
pt0 = YREG + PREG->y_u.yl.y;
|
||||
d0 = *pt0;
|
||||
deref_head(d0, float_y_unk);
|
||||
float_y_nvar:
|
||||
/* non variable */
|
||||
if (IsFloatTerm(d0)) {
|
||||
PREG = NEXTOP(PREG, yl);
|
||||
GONext();
|
||||
}
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
|
||||
derefa_body(d0, pt0, float_y_unk, float_y_nvar);
|
||||
PREG = PREG->y_u.yl.F;
|
||||
GONext();
|
||||
ENDP(pt0);
|
||||
ENDD(d0);
|
||||
ENDOp();
|
|
@ -0,0 +1,255 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "Yap.h"
|
||||
#include "YapInterface.h"
|
||||
#include "clause.h"
|
||||
#include "udi_private.h"
|
||||
|
||||
/* to keep an array with the registered udi indexers */
|
||||
UT_icd udicb_icd = {sizeof(UdiControlBlock), NULL, NULL, NULL};
|
||||
UT_array *indexing_structures;
|
||||
|
||||
/*
|
||||
* Register a new user indexer
|
||||
*/
|
||||
void
|
||||
Yap_UdiRegister(UdiControlBlock cb){
|
||||
/*TODO: check structure integrity and duplicates */
|
||||
utarray_push_back(indexing_structures, &cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* New user indexed predicate:
|
||||
* the first argument is the term.
|
||||
*/
|
||||
static YAP_Int
|
||||
p_new_udi( USES_REGS1 )
|
||||
{
|
||||
Term spec = Deref(ARG1);
|
||||
|
||||
PredEntry *p;
|
||||
UdiInfo blk;
|
||||
int info;
|
||||
|
||||
/* get the predicate from the spec, copied from cdmgr.c */
|
||||
if (IsVarTerm(spec)) {
|
||||
Yap_Error(INSTANTIATION_ERROR,spec,"new user index/1");
|
||||
return FALSE;
|
||||
} else if (!IsApplTerm(spec)) {
|
||||
Yap_Error(TYPE_ERROR_COMPOUND,spec,"new user index/1");
|
||||
return FALSE;
|
||||
} else {
|
||||
Functor fun = FunctorOfTerm(spec);
|
||||
Term tmod = CurrentModule;
|
||||
|
||||
while (fun == FunctorModule) {
|
||||
tmod = ArgOfTerm(1,spec);
|
||||
if (IsVarTerm(tmod) ) {
|
||||
Yap_Error(INSTANTIATION_ERROR, spec, "new user index/1");
|
||||
return FALSE;
|
||||
}
|
||||
if (!IsAtomTerm(tmod) ) {
|
||||
Yap_Error(TYPE_ERROR_ATOM, spec, "new user index/1");
|
||||
return FALSE;
|
||||
}
|
||||
spec = ArgOfTerm(2, spec);
|
||||
fun = FunctorOfTerm(spec);
|
||||
}
|
||||
p = RepPredProp(PredPropByFunc(fun, tmod));
|
||||
}
|
||||
if (!p)
|
||||
return FALSE;
|
||||
/* boring, boring, boring! */
|
||||
if ((p->PredFlags
|
||||
& (DynamicPredFlag|LogUpdatePredFlag|UserCPredFlag|CArgsPredFlag|NumberDBPredFlag|AtomDBPredFlag|TestPredFlag|AsmPredFlag|CPredFlag|BinaryPredFlag))
|
||||
|| (p->ModuleOfPred == PROLOG_MODULE)) {
|
||||
Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE, spec, "udi/2");
|
||||
return FALSE;
|
||||
}
|
||||
if (p->PredFlags & (DynamicPredFlag|LogUpdatePredFlag|TabledPredFlag)) {
|
||||
Yap_Error(PERMISSION_ERROR_ACCESS_PRIVATE_PROCEDURE, spec, "udi/2");
|
||||
return FALSE;
|
||||
}
|
||||
/* TODO: remove AtomRTree from atom list */
|
||||
|
||||
/* this is the real work */
|
||||
blk = (UdiInfo) Yap_AllocCodeSpace(sizeof(struct udi_info));
|
||||
memset((void *) blk,0, sizeof(struct udi_info));
|
||||
if (!blk) {
|
||||
Yap_Error(RESOURCE_ERROR_HEAP, spec, "new user index/1");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*Init UdiInfo */
|
||||
utarray_new(blk->args, &arg_icd);
|
||||
utarray_new(blk->clauselist, &cl_icd);
|
||||
blk->p = p;
|
||||
|
||||
/*Now Init args list*/
|
||||
info = p_udi_args_init(spec, p->ArityOfPE, blk);
|
||||
if (!info)
|
||||
{
|
||||
utarray_free(blk->args);
|
||||
utarray_free(blk->clauselist);
|
||||
Yap_FreeCodeSpace((char *) blk);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*Push into the hash*/
|
||||
HASH_ADD_UdiInfo(UdiControlBlocks, p, blk);
|
||||
|
||||
p->PredFlags |= UDIPredFlag;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we initialize the arguments indexing
|
||||
*/
|
||||
YAP_Int
|
||||
p_udi_args_init(Term spec, int arity, UdiInfo blk)
|
||||
{
|
||||
int i;
|
||||
Term arg;
|
||||
Atom idxtype;
|
||||
UdiControlBlock *cb;
|
||||
struct udi_p_args p_arg;
|
||||
|
||||
for (i = 1; i <= arity; i++) {
|
||||
arg = ArgOfTerm(i,spec);
|
||||
if (IsAtomTerm(arg)) {
|
||||
idxtype = AtomOfTerm(arg);
|
||||
if (idxtype == AtomMinus) //skip this argument
|
||||
continue;
|
||||
p_arg.control = NULL;
|
||||
cb = NULL;
|
||||
while ((cb = (UdiControlBlock *) utarray_next(indexing_structures, cb))) {
|
||||
if (idxtype == (*cb)->decl){
|
||||
p_arg.arg = i;
|
||||
p_arg.control = *cb;
|
||||
p_arg.idxstr = (*cb)->init(spec, i, arity);
|
||||
utarray_push_back(blk->args, &p_arg);
|
||||
}
|
||||
}
|
||||
if (p_arg.control == NULL){ /* not "-" and not found */
|
||||
fprintf(stderr, "Invalid Spec (%s)\n", AtomName(idxtype));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* From now on this is called in several places of yap
|
||||
* when the predicate has the UDIPredFlag
|
||||
* and is what actually triggers the insert/search/abolish of indexing structures
|
||||
*/
|
||||
|
||||
/*
|
||||
* Init Yap udi interface
|
||||
*/
|
||||
void
|
||||
Yap_udi_init(void)
|
||||
{
|
||||
UdiControlBlocks = NULL;
|
||||
|
||||
/*init indexing structures array*/
|
||||
utarray_new(indexing_structures, &udicb_icd);
|
||||
|
||||
Yap_InitCPred("$udi_init", 1, p_new_udi, 0);
|
||||
/* TODO: decide if udi.yap should be loaded automaticaly in init.yap */
|
||||
}
|
||||
|
||||
/* called from cdmgr.c
|
||||
*
|
||||
* for each assert of a udipredicate
|
||||
* to pass info to user structure
|
||||
*/
|
||||
int
|
||||
Yap_new_udi_clause(PredEntry *p, yamop *cl, Term t)
|
||||
{
|
||||
int i;
|
||||
UdiPArg parg;
|
||||
UdiInfo info;
|
||||
YAP_Int index;
|
||||
|
||||
/* try to find our structure */
|
||||
HASH_FIND_UdiInfo(UdiControlBlocks,p,info);
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
/* insert into clauselist */
|
||||
utarray_push_back(info->clauselist, &cl);
|
||||
|
||||
for (i = 0; i < utarray_len(info->args) ; i++) {
|
||||
parg = (UdiPArg) utarray_eltptr(info->args,i);
|
||||
index = (YAP_Int) utarray_len(info->clauselist);
|
||||
parg->idxstr = parg->control->insert(parg->idxstr, t,
|
||||
parg->arg,
|
||||
(void *) index);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* index, called from absmi.c
|
||||
*
|
||||
* Returns:
|
||||
* NULL (yap fallback) No usable indexing available
|
||||
*
|
||||
* Yap_FAILCODE() (fail) No result found
|
||||
* Yap_CauseListToClause(cl) 1 solution found
|
||||
* Yap_ClauseListCode(cl) 2+ solutions found
|
||||
*/
|
||||
yamop *
|
||||
Yap_udi_search(PredEntry *p)
|
||||
{
|
||||
int r;
|
||||
struct ClauseList clauselist;
|
||||
UdiPArg parg;
|
||||
UdiInfo info;
|
||||
|
||||
/* find our structure*/
|
||||
HASH_FIND_UdiInfo(UdiControlBlocks,p,info);
|
||||
if (!info || utarray_len(info->args) == 0)
|
||||
return NULL;
|
||||
|
||||
if (utarray_len(info->args) == 1){ //simple case no intersection needed
|
||||
struct si_callback_h c;
|
||||
|
||||
c.cl = Yap_ClauseListInit(&clauselist);
|
||||
c.clauselist = info->clauselist;
|
||||
c.pred = info->p;
|
||||
if (!c.cl)
|
||||
return NULL;
|
||||
|
||||
parg = (UdiPArg) utarray_eltptr(info->args,0);
|
||||
r = parg->control->search(parg->idxstr, parg->arg, si_callback, (void *) &c);
|
||||
Yap_ClauseListClose(c.cl);
|
||||
|
||||
if (r == -1) {
|
||||
Yap_ClauseListDestroy(c.cl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Yap_ClauseListCount(c.cl) == 0) {
|
||||
Yap_ClauseListDestroy(c.cl);
|
||||
return Yap_FAILCODE();
|
||||
}
|
||||
#if 0
|
||||
} else {//intersection needed using Judy
|
||||
Yap_udi_join( &clauselist, parg, info );
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Yap_ClauseListCount(&clauselist) == 1)
|
||||
return Yap_ClauseListToClause(&clauselist);
|
||||
return Yap_ClauseListCode(&clauselist);
|
||||
}
|
||||
|
||||
/* index, called from absmi.c */
|
||||
void
|
||||
Yap_udi_abolish(PredEntry *p)
|
||||
{
|
||||
/* tell the predicate destroy */
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,698 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* YAP Prolog *
|
||||
* *
|
||||
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: userpreds.c *
|
||||
* Last rev: *
|
||||
* mods: *
|
||||
* comments: an entry for user defined predicates *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#ifdef SCCS
|
||||
static char SccsId[] = "%W% %G%";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file is an entry for user defined C-predicates.
|
||||
*
|
||||
* There are two sorts of C-Predicates: deterministic - which should be defined
|
||||
* in the function InitUserCPreds().
|
||||
*
|
||||
* backtrackable - they include a start and a continuation function, the first
|
||||
* one called by the first invocation, the last one called after a fail. This
|
||||
* can be seen as: pred :- init ; repeat, cont. These predicates should be
|
||||
* defined in the function InitUserBacks()
|
||||
*
|
||||
* These two functions are called after any "restore" operation.
|
||||
*
|
||||
* The function InitUserExtensions() is called once, when starting the execution
|
||||
* of the program, and should be used to initialize any user-defined
|
||||
* extensions (like the execution environment or interfaces to other
|
||||
* programs).
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Yap.h"
|
||||
#include "Yatom.h"
|
||||
#include "YapHeap.h"
|
||||
#if EUROTRA
|
||||
#include "yapio.h"
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* You should include here the prototypes for all static functions */
|
||||
|
||||
#ifdef EUROTRA
|
||||
static int p_clean(void);
|
||||
static int p_namelength(void);
|
||||
static int p_getpid(void);
|
||||
static int p_exit(void);
|
||||
static int p_incrcounter(void);
|
||||
static int p_setcounter(void);
|
||||
static int p_trapsignal(void);
|
||||
static int subsumes(Term, Term);
|
||||
static int p_subsumes(void);
|
||||
static int p_grab_tokens(void);
|
||||
#endif
|
||||
#ifdef MACYAP
|
||||
static typedef int (*SignalProc)();
|
||||
static SignalProc skel_signal(int, SignalProc);
|
||||
static int chdir(char *);
|
||||
#endif
|
||||
|
||||
#ifdef SFUNC
|
||||
static int p_softfunctor(void);
|
||||
#endif /* SFUNC */
|
||||
|
||||
#ifdef USERPREDS
|
||||
/* These are some examples of user-defined functions */
|
||||
|
||||
/*
|
||||
* unify(A,B) --> unification with occurs-check it uses the functions
|
||||
* full_unification and occurs_in
|
||||
*
|
||||
* occurs_check(V,S) :- var(S), !, S \== V. occurs_check(V,S) :- primitive(S),
|
||||
* !. occurs_check(V,[H|T]) :- !, occurs_check(V,H), occurs_check(V,T).
|
||||
* occurs_check(V,St) :- functor(T,_,N), occurs_check_struct(N,V,St).
|
||||
*
|
||||
* occurs_check_struct(1,V,T) :- !, arg(1,T,A), occurs_check(V,A).
|
||||
* occurs_check_struct(N,V,T) :- N1 is N-1, occurs_check_structure(N1,V,T),
|
||||
* arg(N,T,A), occurs_check(V,A).
|
||||
*
|
||||
* unify(X,Y) :- var(X), var(Y), !, X = Y. unify(X,Y) :- var(X), !,
|
||||
* occurs_check(X,Y), X = Y. unify(X,Y) :- var(Y), !, occurs_check(Y,X), X =
|
||||
* Y. unify([H0|T0],[H1|T1]) :- !, unify(H0,H1), unify(T0,T1). unify(X,Y) :-
|
||||
* functor(X,A,N), functor(Y,A,N), unify_structs(N,X,Y).
|
||||
*
|
||||
* unify_structs(1,X,Y) :- !, arg(1,X,A), arg(1,Y,B), unify(A,B).
|
||||
* unify_structs(N,Y,Z) :- N1 is N-1, unify_structs(N1,X,Y), arg(N,X,A),
|
||||
* arg(N,Y,B), unify(A,B).
|
||||
*/
|
||||
|
||||
/* occurs-in --> checks if the variable V occurs in term S */
|
||||
|
||||
static int occurs_check(V, T) Term V, T;
|
||||
{
|
||||
/* V and S are always derefed */
|
||||
if (IsVarTerm(T)) {
|
||||
return (V != T);
|
||||
} else if (IsPrimitiveTerm(T)) {
|
||||
return (TRUE);
|
||||
} else if (IsPairTerm(T)) {
|
||||
return (occurs_check(V, HeadOfTerm(T)) && occurs_check(V, TailOfTerm(T)));
|
||||
} else if (IsApplTerm(T)) {
|
||||
unsigned int i;
|
||||
unsigned int arity = ArityOfFunctor(FunctorOfTerm(T));
|
||||
|
||||
for (i = 1; i <= arity; ++i)
|
||||
if (!occurs_check(V, ArgOfTerm(i, T)))
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
If you worry about coroutining the routine must receive the
|
||||
arguments before dereferencing, otherwise unify() won't be
|
||||
to wake possible bound variables
|
||||
*/
|
||||
static int full_unification(T1, T2) Term T1, T2;
|
||||
{
|
||||
Term t1 = Deref(T1);
|
||||
Term t2 = Deref(T2);
|
||||
if (IsVarTerm(t1)) {/* Testing for variables should be done first */
|
||||
if (IsVarTerm(t2) || IsPrimitiveTerm(t2))
|
||||
return (Yap_unify(T1, t2));
|
||||
if (occurs_check(t1, t2))
|
||||
return (Yap_unify(T1, t2));
|
||||
return (FALSE);
|
||||
}
|
||||
if (IsVarTerm(t2)) {
|
||||
if (occurs_check(t2, t1))
|
||||
return (Yap_unify(T2, t1));
|
||||
return (FALSE);
|
||||
}
|
||||
if (IsPrimitiveTerm(t1)) {
|
||||
if (IsFloatTerm(t1))
|
||||
return (IsFloatTerm(t2) && FloatOfTerm(t1) == FloatOfTerm(t2));
|
||||
else if (IsRefTerm(t1))
|
||||
return (IsRefTerm(t2) && RefOfTerm(t1) == RefOfTerm(t2));
|
||||
if (IsLongIntTerm(t1))
|
||||
return (IsLongIntTerm(t2) && LongIntOfTerm(t1) == LongIntOfTerm(t2));
|
||||
else
|
||||
return (t1 == t2);
|
||||
}
|
||||
if (IsPairTerm(t1)) {
|
||||
if (!IsPairTerm(t2))
|
||||
return (FALSE);
|
||||
return (full_unification(HeadOfTermCell(t1), HeadOfTermCell(t2)) &&
|
||||
full_unification(TailOfTermCell(t1), TailOfTermCell(t2)));
|
||||
}
|
||||
if (IsApplTerm(t1)) {
|
||||
unsigned int i, arity;
|
||||
if (!IsApplTerm(t2))
|
||||
return (FALSE);
|
||||
if (FunctorOfTerm(t1) != FunctorOfTerm(t2))
|
||||
return (FALSE);
|
||||
arity = ArityOfFunctor(FunctorOfTerm(t1));
|
||||
for (i = 1; i <= arity; ++i)
|
||||
if (!full_unification(ArgOfTermCell(i, t1), ArgOfTerm(i, t2)))
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
#ifdef lint
|
||||
return (FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int p_occurs_check() { /* occurs_check(?,?) */
|
||||
return (occurs_check(Deref(ARG1), Deref(DARG2)));
|
||||
}
|
||||
|
||||
/* Out of date, use unify_with_occurs_check instead*/
|
||||
static int p_unify() { /* unify(?,?) */
|
||||
/* routines that perform unification must receive the original arguments */
|
||||
return (full_unification(ARG1, ARG2));
|
||||
}
|
||||
|
||||
/*
|
||||
* One example of a counter using the atom value functions counter(Atom,M,N)
|
||||
*
|
||||
* If the second argument is uninstantiated, then it will be unified with the
|
||||
* current value of the counter, otherwyse the counter will be set to its
|
||||
* value. The third argument then be unified with the next integer, which
|
||||
* will become the current counter value.
|
||||
*/
|
||||
static int p_counter() { /* counter(+Atom,?Number,?Next) */
|
||||
Term TCount, TNext, T1, T2;
|
||||
Atom a;
|
||||
/* Int -> an YAP integer */
|
||||
Int val;
|
||||
T1 = Deref(ARG1);
|
||||
ARG2 = Deref(ARG2);
|
||||
|
||||
/* No need to deref ARG3, we don't want to know what's in there */
|
||||
if (IsVarTerm(T1) || !IsAtomTerm(T1))
|
||||
return (FALSE);
|
||||
a = AtomOfTerm(T1);
|
||||
if (IsVarTerm(T2)) {
|
||||
TCount = Yap_GetValue(a);
|
||||
if (!IsIntTerm(TCount))
|
||||
return (FALSE);
|
||||
Yap_unify_constant(ARG2, TCount); /* always succeeds */
|
||||
val = IntOfTerm(TCount);
|
||||
} else {
|
||||
if (!IsIntTerm(T2))
|
||||
return (FALSE);
|
||||
val = IntOfTerm(T2);
|
||||
}
|
||||
val++;
|
||||
/* The atom will now take the incremented value */
|
||||
Yap_PutValue(a, TNext = MkIntTerm(val));
|
||||
return (Yap_unify_constant(ARG3, TNext));
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenate an instantiated list to another list, and unify with third
|
||||
* argument
|
||||
*/
|
||||
|
||||
/*
|
||||
* In order to be more efficient, iconcat instead of unifying the terms in
|
||||
* the old structure with the ones in the new one just copies them. This is a
|
||||
* dangerous behaviour, though acceptable in this case, and you should try to
|
||||
* avoid it whenever possible
|
||||
*/
|
||||
#ifdef COMMENT
|
||||
static int p_iconcat() { /* iconcat(+L1,+L2,-L) */
|
||||
Term Tkeep[1025]; /* Will do it just for lists less
|
||||
* than 1024 elements long */
|
||||
register Term *Tkp = Tkeep;
|
||||
register Term L0, L1;
|
||||
Term T2;
|
||||
|
||||
L0 = Deref(ARG1);
|
||||
*Tkp++ = Unsigned(0);
|
||||
L1 = TermNil;
|
||||
while (L0 != L1) {
|
||||
/*
|
||||
* Usually you should test if L1 a var, if (!IsPairTerm(L0))
|
||||
* return(FALSE);
|
||||
*/
|
||||
*Tkp++ = HeadOfTerm(L0);
|
||||
L0 = TailOfTerm(L0);
|
||||
}
|
||||
L1 = Deref(ARG2);
|
||||
while (L0 = *--Tkp)
|
||||
L1 = MkPairTerm(L0, L1);
|
||||
T2 = L1;
|
||||
return (Yap_unify(T2, ARG3));
|
||||
}
|
||||
#endif /* COMMENT */
|
||||
|
||||
static int p_iconcat() { /* iconcat(+L1,+L2,-L) */
|
||||
register Term *Tkp = H, *tp;
|
||||
register Term L0, L1;
|
||||
Term T2;
|
||||
|
||||
L0 = Deref(ARG1);
|
||||
L1 = TermNil;
|
||||
while (L0 != L1) {
|
||||
/* if (!IsPairTerm(L0)) return(FALSE); */
|
||||
tp = Tkp;
|
||||
*tp = AbsPair(++Tkp);
|
||||
*Tkp++ = HeadOfTerm(L0);
|
||||
L0 = TailOfTerm(L0);
|
||||
}
|
||||
*Tkp++ = Deref(ARG2);
|
||||
T2 = *H;
|
||||
H = Tkp;
|
||||
return (Yap_unify(T2, ARG3));
|
||||
}
|
||||
|
||||
#endif /* USERPREDS */
|
||||
|
||||
#ifdef EUROTRA
|
||||
|
||||
static int p_clean() /* predicate clean for ets */
|
||||
/*
|
||||
* clean(FB,CFB) :- FB =.. [fb|L],!, clean1(L,CL), CFB =.. [fb|CL].
|
||||
* clean(FB,CFB) :- var(FB).
|
||||
*
|
||||
* clean1([],[]) :- !. clean1([H|T],[CH|CT]) :- H==$u,!, clean1(T,CT).
|
||||
* clean1([H|T],[H|CT]) :- clean1(T,CT).
|
||||
*/
|
||||
{
|
||||
unsigned int arity, i;
|
||||
Term t, Args[255];
|
||||
Term t1 = Deref(ARG1);
|
||||
|
||||
if (IsVarTerm(t1))
|
||||
return (TRUE);
|
||||
if (!(IsApplTerm(t1) && NameOfFunctor(FunctorOfTerm(t1)) == AtomFB))
|
||||
return (FALSE);
|
||||
arity = ArityOfFunctor(FunctorOfTerm(t1));
|
||||
#ifdef SFUNC
|
||||
if (arity == SFArity) {
|
||||
CELL *pt = H, *ntp = ArgsOfSFTerm(t1);
|
||||
Term tn = AbsAppl(H);
|
||||
*pt++ = FunctorOfTerm(t1);
|
||||
RESET_VARIABLE(pt);
|
||||
pt++;
|
||||
while (*pt++ = *ntp++)
|
||||
if ((*pt++ = *ntp++) == MkAtomTerm(AtomDollarUndef))
|
||||
pt -= 2;
|
||||
H = pt;
|
||||
return (Yap_unify(tn, ARG2));
|
||||
}
|
||||
#endif
|
||||
for (i = 1; i <= arity; ++i) {
|
||||
if ((t = ArgOfTerm(i, t1)) == TermDollarU)
|
||||
t = MkVarTerm();
|
||||
Args[i - 1] = t;
|
||||
}
|
||||
t = Yap_MkApplTerm(FunctorOfTerm(t1), arity, Args);
|
||||
return (Yap_unify(ARG2, t));
|
||||
}
|
||||
|
||||
static Term *subs_table;
|
||||
static int subs_entries;
|
||||
#define SUBS_TABLE_SIZE 500
|
||||
|
||||
static int subsumes(T1, T2) Term T1, T2;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (IsVarTerm(T1)) {
|
||||
if (!IsVarTerm(T2))
|
||||
return (FALSE);
|
||||
if (T1 == T2)
|
||||
return (TRUE);
|
||||
for (i = 0; i < subs_entries; ++i)
|
||||
if (subs_table[i] == T2)
|
||||
return (FALSE);
|
||||
if (T2 < T1) {/* T1 gets instantiated with T2 */
|
||||
Yap_unify(T1, T2);
|
||||
for (i = 0; i < subs_entries; ++i)
|
||||
if (subs_table[i] == T1) {
|
||||
subs_table[i] = T2;
|
||||
return (TRUE);
|
||||
}
|
||||
subs_table[subs_entries++] = T2;
|
||||
return (TRUE);
|
||||
}
|
||||
/* T2 gets instantiated with T1 */
|
||||
Yap_unify(T1, T2);
|
||||
for (i = 0; i < subs_entries; ++i)
|
||||
if (subs_table[i] == T1)
|
||||
return (TRUE);
|
||||
subs_table[subs_entries++] = T1;
|
||||
return (TRUE);
|
||||
}
|
||||
if (IsVarTerm(T2)) {
|
||||
for (i = 0; i < subs_entries; ++i)
|
||||
if (subs_table[i] == T2)
|
||||
return (FALSE);
|
||||
return (Yap_unify(T1, T2));
|
||||
}
|
||||
if (IsPrimitiveTerm(T1)) {
|
||||
if (IsFloatTerm(T1))
|
||||
return (IsFloatTerm(T2) && FloatOfTerm(T1) == FloatOfTerm(T2));
|
||||
else if (IsRefTerm(T1))
|
||||
return (IsRefTerm(T2) && RefOfTerm(T1) == RefOfTerm(T2));
|
||||
else if (IsLongIntTerm(T1))
|
||||
return (IsLongIntTerm(T2) && LongIntOfTerm(T1) == LongIntOfTerm(T2));
|
||||
else
|
||||
return (T1 == T2);
|
||||
}
|
||||
if (IsPairTerm(T1)) {
|
||||
if (!IsPairTerm(T2))
|
||||
return (FALSE);
|
||||
return (subsumes(HeadOfTerm(T1), HeadOfTerm(T2)) &&
|
||||
subsumes(TailOfTerm(T1), TailOfTerm(T2)));
|
||||
}
|
||||
if (IsApplTerm(T1)) {
|
||||
int arity;
|
||||
if (!IsApplTerm(T2))
|
||||
return (FALSE);
|
||||
if (FunctorOfTerm(T1) != FunctorOfTerm(T2))
|
||||
return (FALSE);
|
||||
arity = ArityOfFunctor(FunctorOfTerm(T1));
|
||||
#ifdef SFUNC
|
||||
if (arity == SFArity) {
|
||||
CELL *a1a = ArgsOfSFTerm(T1), *a2a = ArgsOfSFTerm(T2);
|
||||
CELL *a1p = a1a - 1, *a2p = a2a - 1;
|
||||
CELL *pt = H;
|
||||
int flags = 0;
|
||||
Term t1, t2;
|
||||
*pt++ = FunctorOfTerm(T1);
|
||||
RESET_VARIABLE(pt);
|
||||
pt++;
|
||||
while (1) {
|
||||
if (*a2a < *a1a || *a1a == 0) {
|
||||
if (*a2a) {
|
||||
*pt++ = *a2a++;
|
||||
t2 = Derefa(a2a);
|
||||
++a2a;
|
||||
if (!IsVarTerm(t2))
|
||||
return (FALSE);
|
||||
for (i = 0; i < subs_entries; ++i)
|
||||
if (subs_table[i] == t2)
|
||||
return (FALSE);
|
||||
subs_table[subs_entries++] = t2;
|
||||
*pt++ = t2;
|
||||
flags |= 1;
|
||||
} else { /* T2 is finished */
|
||||
if ((flags & 1) == 0) {/* containned in first */
|
||||
*a2p = Unsigned(a1p - 1);
|
||||
if (a2p < HB)
|
||||
*TR++ = Unsigned(a2p);
|
||||
return (TRUE);
|
||||
}
|
||||
while ((*pt++ = *a1a++))
|
||||
;
|
||||
*a1p = Unsigned(H);
|
||||
if (a1p < HB)
|
||||
*TR++ = Unsigned(a1p);
|
||||
*a2p = Unsigned(H);
|
||||
if (a2p < HB)
|
||||
*TR++ = Unsigned(a2p);
|
||||
H = pt;
|
||||
return (TRUE);
|
||||
}
|
||||
} else if (*a2a > *a1a || *a2a == 0) {
|
||||
*pt++ = *a1a++;
|
||||
t1 = Derefa(a1a);
|
||||
++a1a;
|
||||
if (IsVarTerm(t1)) {
|
||||
for (i = 0; i < subs_entries; ++i)
|
||||
if (subs_table[i] == t1)
|
||||
break;
|
||||
if (i >= subs_entries)
|
||||
subs_table[subs_entries++] = t1;
|
||||
}
|
||||
*pt++ = t1;
|
||||
flags |= 2;
|
||||
} else if (*a1a == *a2a) {
|
||||
*pt++ = *a1a++;
|
||||
++a2a;
|
||||
t1 = Derefa(a1a);
|
||||
++a1a;
|
||||
t2 = Derefa(a2a);
|
||||
++a2a;
|
||||
*pt++ = t1;
|
||||
if (!subsumes(t1, t2))
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (i = 1; i <= arity; ++i)
|
||||
if (!subsumes(ArgOfTerm(i, T1), ArgOfTerm(i, T2)))
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static int p_subsumes() {
|
||||
Term work_space[SUBS_TABLE_SIZE];
|
||||
subs_table = work_space;
|
||||
subs_entries = 0;
|
||||
return (subsumes(Deref(ARG1), Deref(ARG2)));
|
||||
}
|
||||
|
||||
static int p_namelength() {
|
||||
register Term t = Deref(ARG1);
|
||||
Term tf;
|
||||
|
||||
if (IsVarTerm(t)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (IsAtomTerm(t)) {
|
||||
Term tf = MkIntTerm(strlen(RepAtom(AtomOfTerm(t))->StrOfAE));
|
||||
return (Yap_unify_constant(ARG2, tf));
|
||||
} else if (IsIntTerm(t)) {
|
||||
register int i = 1, k = IntOfTerm(t);
|
||||
if (k < 0)
|
||||
++i, k = -k;
|
||||
while (k > 10)
|
||||
++i, k /= 10;
|
||||
tf = MkIntTerm(i);
|
||||
return (Yap_unify_constant(ARG2, tf));
|
||||
} else
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static int p_getpid() {
|
||||
#ifndef MPW
|
||||
Term t = MkIntTerm(getpid());
|
||||
#else
|
||||
Term t = MkIntTerm(1);
|
||||
#endif
|
||||
return (Yap_unify_constant(ARG1, t));
|
||||
}
|
||||
|
||||
static int p_exit() {
|
||||
register Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t) || !IsIntTerm(t))
|
||||
return (FALSE);
|
||||
Yap_exit((int)IntOfTerm(t));
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static int current_pos;
|
||||
|
||||
static int p_incrcounter() {
|
||||
register Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t) || !IsIntTerm(t))
|
||||
return (FALSE);
|
||||
current_pos += IntOfTerm(t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static int p_setcounter() {
|
||||
register Term t = Deref(ARG1);
|
||||
if (IsVarTerm(t) || !IsIntTerm(t)) {
|
||||
return (Yap_unify_constant(ARG1, MkIntTerm(current_pos)));
|
||||
} else {
|
||||
current_pos = IntOfTerm(t);
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#include <signal.h>
|
||||
#ifdef MACYAP
|
||||
#define signal(A, B) skel_signal(A, B)
|
||||
#endif
|
||||
|
||||
#ifndef EOF
|
||||
#define EOF -1
|
||||
#endif
|
||||
|
||||
static int p_trapsignal(void) {
|
||||
#ifndef MPW
|
||||
signal(SIGINT, SIG_IGN);
|
||||
#endif
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#define varstarter(ch) ((ch >= 'A' && ch <= 'Z') || ch == '_')
|
||||
#define idstarter(ch) (ch >= 'a' && ch <= 'z')
|
||||
#define idchar(ch) \
|
||||
((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || \
|
||||
(ch >= 'a' && ch <= 'z') || ch == '_')
|
||||
|
||||
static int p_grab_tokens() {
|
||||
Term *p = ASP - 20, *p0, t;
|
||||
Functor IdFunctor, VarFunctor;
|
||||
char ch, IdChars[256], *chp;
|
||||
|
||||
IdFunctor = FunctorId;
|
||||
VarFunctor = FunctorDollarVar;
|
||||
p0 = p;
|
||||
ch = Yap_PlGetchar();
|
||||
while (1) {
|
||||
while (ch <= ' ' && ch != EOF)
|
||||
ch = Yap_PlGetchar();
|
||||
if (ch == '.' || ch == EOF)
|
||||
break;
|
||||
if (ch == '%') {
|
||||
while ((ch = Yap_PlGetchar()) != 10)
|
||||
;
|
||||
ch = Yap_PlGetchar();
|
||||
continue;
|
||||
}
|
||||
if (ch == '\'') {
|
||||
chp = IdChars;
|
||||
while (1) {
|
||||
ch = Yap_PlGetchar();
|
||||
if (ch == '\'')
|
||||
break;
|
||||
*chp++ = ch;
|
||||
}
|
||||
*chp = 0;
|
||||
t = MkAtomTerm(Yap_LookupAtom(IdChars));
|
||||
*p-- = Yap_MkApplTerm(IdFunctor, 1, &t);
|
||||
ch = Yap_PlGetchar();
|
||||
continue;
|
||||
}
|
||||
if (varstarter(ch)) {
|
||||
chp = IdChars;
|
||||
*chp++ = ch;
|
||||
while (1) {
|
||||
ch = Yap_PlGetchar();
|
||||
if (!idchar(ch))
|
||||
break;
|
||||
*chp++ = ch;
|
||||
}
|
||||
*chp = 0;
|
||||
t = MkAtomTerm(Yap_LookupAtom(IdChars));
|
||||
*p-- = Yap_MkApplTerm(VarFunctor, 1, &t);
|
||||
continue;
|
||||
}
|
||||
if (idstarter(ch)) {
|
||||
chp = IdChars;
|
||||
*chp++ = ch;
|
||||
while (1) {
|
||||
ch = Yap_PlGetchar();
|
||||
if (!idchar(ch))
|
||||
break;
|
||||
*chp++ = ch;
|
||||
}
|
||||
*chp = 0;
|
||||
t = MkAtomTerm(Yap_LookupAtom(IdChars));
|
||||
*p-- = Yap_MkApplTerm(IdFunctor, 1, &t);
|
||||
continue;
|
||||
}
|
||||
IdChars[0] = ch;
|
||||
IdChars[1] = 0;
|
||||
*p-- = MkAtomTerm(Yap_LookupAtom(IdChars));
|
||||
ch = Yap_PlGetchar();
|
||||
}
|
||||
t = MkAtomTerm(AtomNil);
|
||||
while (p != p0) {
|
||||
t = MkPairTerm(*++p, t);
|
||||
}
|
||||
return (Yap_unify(ARG1, t));
|
||||
}
|
||||
|
||||
#endif /* EUROTRA */
|
||||
|
||||
#ifdef SFUNC
|
||||
|
||||
static p_softfunctor() {
|
||||
Term nilvalue = 0;
|
||||
SFEntry *pe;
|
||||
Prop p0;
|
||||
Atom a;
|
||||
Term t1 = Deref(ARG1);
|
||||
Term t2 = Deref(ARG2);
|
||||
|
||||
if (IsAtomTerm(t2))
|
||||
nilvalue = t2;
|
||||
if (!IsAtomTerm(t1))
|
||||
return (FALSE);
|
||||
a = AtomOfTerm(t1);
|
||||
WRITE_LOCK(RepAtom(a)->ARWLock);
|
||||
if ((p0 = Yap_GetAProp(a, SFProperty)) == NIL) {
|
||||
pe = (SFEntry *)Yap_AllocAtomSpace(sizeof(*pe));
|
||||
pe->KindOfPE = SFProperty;
|
||||
AddPropToAtom(RepAtom(a), (PropEntry *)pe);
|
||||
} else
|
||||
pe = RepSFProp(p0);
|
||||
WRITE_UNLOCK(RepAtom(a)->ARWLock);
|
||||
pe->NilValue = nilvalue;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#endif /* SFUNC */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
static Int
|
||||
p_matching_distances(void)
|
||||
{
|
||||
return(fabs(FloatOfTerm(Deref(ARG1))-FloatOfTerm(Deref(ARG2))) <=
|
||||
FloatOfTerm(Deref(ARG3)));
|
||||
}
|
||||
*/
|
||||
|
||||
void Yap_InitUserCPreds(void) {
|
||||
#ifdef XINTERFACE
|
||||
Yap_InitXPreds();
|
||||
#endif
|
||||
#ifdef EUROTRA
|
||||
Yap_InitCPred("clean", 2, p_clean, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("name_length", 2, p_namelength, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("get_pid", 1, p_getpid, SafePredFlag);
|
||||
Yap_InitCPred("exit", 1, p_exit, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("incr_counter", 1, p_incrcounter, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("set_counter", 1, p_setcounter, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("trap_signal", 0, p_trapsignal, SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("mark2_grab_tokens", 1, p_grab_tokens,
|
||||
SafePredFlag | SyncPredFlag);
|
||||
Yap_InitCPred("subsumes", 2, p_subsumes, SafePredFlag);
|
||||
#endif
|
||||
#ifdef SFUNC
|
||||
Yap_InitCPred("sparse_functor", 2, p_softfunctor, SafePredFlag);
|
||||
#endif /* SFUNC */
|
||||
/* Yap_InitCPred("match_distances", 3, p_matching_distances, SafePredFlag);
|
||||
*/
|
||||
/* Yap_InitCPred("unify",2,p_unify,SafePredFlag); */
|
||||
/* Yap_InitCPred("occurs_check",2,p_occurs_check,SafePredFlag); */
|
||||
/* Yap_InitCPred("counter",3,p_counter,SafePredFlag); */
|
||||
/* Yap_InitCPred("iconcat",3,p_iconcat,SafePredFlag); */
|
||||
}
|
||||
|
||||
void Yap_InitUserBacks(void) {}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,562 @@
|
|||
/*************************************************************************
|
||||
* *
|
||||
* Yap Prolog *
|
||||
* *
|
||||
* Yap Prolog Was Developed At Nccup - Universidade Do Porto *
|
||||
* *
|
||||
* Copyright L.Damas, V.S.Costa And Universidade Do Porto 1985-1997 *
|
||||
* *
|
||||
**************************************************************************
|
||||
* *
|
||||
* File: Yap.C *
|
||||
* Last Rev: *
|
||||
* Mods: *
|
||||
* Comments: Yap's Main File: parse arguments *
|
||||
* *
|
||||
*************************************************************************/
|
||||
/* static char SccsId[] = "X 4.3.3"; */
|
||||
|
||||
#include "config.h"
|
||||
#include "Yap.h"
|
||||
#include "YapHeap.h"
|
||||
#include "YapInterface.h"
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#ifdef _MSC_VER /* Microsoft's Visual C++ Compiler */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#undef HAVE_UNISTD_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_DIRECT_H
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#if (DefTrailSpace < MinTrailSpace)
|
||||
#undef DefTrailSpace
|
||||
#define DefTrailSpace MinTrailSpace
|
||||
#endif
|
||||
|
||||
#if (DefStackSpace < MinStackSpace)
|
||||
#undef DefStackSpace
|
||||
#define DefStackSpace MinStackSpace
|
||||
#endif
|
||||
|
||||
#if (DefHeapSpace < MinHeapSpace)
|
||||
#undef DefHeapSpace
|
||||
#define DefHeapSpace MinHeapSpace
|
||||
#endif
|
||||
|
||||
#define DEFAULT_NUMBERWORKERS 1
|
||||
#define DEFAULT_SCHEDULERLOOP 10
|
||||
#define DEFAULT_DELAYEDRELEASELOAD 3
|
||||
|
||||
static void print_usage(void) {
|
||||
fprintf(stderr, "\n[ Valid switches for command line arguments: ]\n");
|
||||
fprintf(stderr, " -? Shows this screen\n");
|
||||
fprintf(stderr, " -b Boot file \n");
|
||||
fprintf(stderr, " -dump-runtime-variables\n");
|
||||
fprintf(stderr, " -f initialization file or \"none\"\n");
|
||||
fprintf(stderr, " -g Run Goal Before Top-Level \n");
|
||||
fprintf(stderr, " -z Run Goal Before Top-Level \n");
|
||||
fprintf(stderr, " -q start with informational messages off\n");
|
||||
fprintf(stderr, " -l load Prolog file\n");
|
||||
fprintf(stderr, " -L run Prolog file and exit\n");
|
||||
fprintf(stderr, " -p extra path for file-search-path\n");
|
||||
fprintf(stderr, " -hSize Heap area in Kbytes (default: %d, minimum: %d)\n",
|
||||
DefHeapSpace, MinHeapSpace);
|
||||
fprintf(stderr,
|
||||
" -sSize Stack area in Kbytes (default: %d, minimum: %d)\n",
|
||||
DefStackSpace, MinStackSpace);
|
||||
fprintf(stderr,
|
||||
" -tSize Trail area in Kbytes (default: %d, minimum: %d)\n",
|
||||
DefTrailSpace, MinTrailSpace);
|
||||
fprintf(stderr, " -GSize Max Area for Global Stack\n");
|
||||
fprintf(stderr,
|
||||
" -LSize Max Area for Local Stack (number must follow L)\n");
|
||||
fprintf(stderr, " -TSize Max Area for Trail (number must follow L)\n");
|
||||
fprintf(stderr, " -nosignals disable signal handling from Prolog\n");
|
||||
fprintf(stderr, "\n[Execution Modes]\n");
|
||||
fprintf(stderr, " -J0 Interpreted mode (default)\n");
|
||||
fprintf(stderr, " -J1 Mixed mode only for user predicates\n");
|
||||
fprintf(stderr, " -J2 Mixed mode for all predicates\n");
|
||||
fprintf(stderr, " -J3 Compile all user predicates\n");
|
||||
fprintf(stderr, " -J4 Compile all predicates\n");
|
||||
|
||||
#ifdef TABLING
|
||||
fprintf(stderr,
|
||||
" -ts Maximum table space area in Mbytes (default: unlimited)\n");
|
||||
#endif /* TABLING */
|
||||
#if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) || \
|
||||
defined(YAPOR_THREADS)
|
||||
fprintf(stderr, " -w Number of workers (default: %d)\n",
|
||||
DEFAULT_NUMBERWORKERS);
|
||||
fprintf(stderr, " -sl Loop scheduler executions before look for hiden "
|
||||
"shared work (default: %d)\n",
|
||||
DEFAULT_SCHEDULERLOOP);
|
||||
fprintf(stderr, " -d Value of delayed release of load (default: %d)\n",
|
||||
DEFAULT_DELAYEDRELEASELOAD);
|
||||
#endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA || YAPOR_THREADS */
|
||||
/* nf: Preprocessor */
|
||||
/* fprintf(stderr," -DVar=Name Persistent definition\n"); */
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static int myisblank(int c) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static char *add_end_dot(char arg[]) {
|
||||
int sz = strlen(arg), i;
|
||||
i = sz;
|
||||
while (i && myisblank(arg[--i]))
|
||||
;
|
||||
if (i && arg[i] != ',') {
|
||||
char *p = (char *)malloc(sz + 2);
|
||||
if (!p)
|
||||
return NULL;
|
||||
strncpy(p, arg, sz);
|
||||
p[sz] = '.';
|
||||
p[sz + 1] = '\0';
|
||||
return p;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
static int dump_runtime_variables(void) {
|
||||
fprintf(stdout, "CC=\"%s\"\n", C_CC);
|
||||
fprintf(stdout, "YAP_ROOTDIR=\"%s\"\n", YAP_ROOTDIR);
|
||||
fprintf(stdout, "YAP_LIBS=\"%s\"\n", C_LIBS);
|
||||
fprintf(stdout, "YAP_SHLIB_SUFFIX=\"%s\"\n", SO_EXT);
|
||||
fprintf(stdout, "YAP_VERSION=%s\n", YAP_NUMERIC_VERSION);
|
||||
exit(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
X_API int YAP_parse_yap_arguments(int argc, char *argv[], YAP_init_args *iap) {
|
||||
char *p;
|
||||
int BootMode = YAP_BOOT_FROM_SAVED_CODE;
|
||||
unsigned long int *ssize;
|
||||
|
||||
iap->SavedState = NULL;
|
||||
iap->HeapSize = 0;
|
||||
iap->StackSize = 0;
|
||||
iap->TrailSize = 0;
|
||||
iap->AttsSize = 0;
|
||||
iap->MaxAttsSize = 0;
|
||||
iap->MaxHeapSize = 0;
|
||||
iap->MaxStackSize = 0;
|
||||
iap->MaxGlobalSize = 0;
|
||||
iap->MaxTrailSize = 0;
|
||||
iap->YapLibDir = NULL;
|
||||
iap->YapPrologBootFile = NULL;
|
||||
iap->YapPrologInitFile = NULL;
|
||||
iap->YapPrologRCFile = NULL;
|
||||
iap->YapPrologGoal = NULL;
|
||||
iap->YapPrologTopLevelGoal = NULL;
|
||||
iap->YapPrologAddPath = NULL;
|
||||
iap->HaltAfterConsult = FALSE;
|
||||
iap->FastBoot = FALSE;
|
||||
iap->MaxTableSpaceSize = 0;
|
||||
iap->NumberWorkers = DEFAULT_NUMBERWORKERS;
|
||||
iap->SchedulerLoop = DEFAULT_SCHEDULERLOOP;
|
||||
iap->DelayedReleaseLoad = DEFAULT_DELAYEDRELEASELOAD;
|
||||
iap->PrologShouldHandleInterrupts = TRUE;
|
||||
iap->ExecutionMode = YAPC_INTERPRETED;
|
||||
iap->Argc = argc;
|
||||
iap->Argv = argv;
|
||||
iap->def_c = 0;
|
||||
iap->ErrorNo = 0;
|
||||
iap->ErrorCause = NULL;
|
||||
iap->QuietMode = FALSE;
|
||||
|
||||
while (--argc > 0) {
|
||||
p = *++argv;
|
||||
if (*p == '-')
|
||||
switch (*++p) {
|
||||
case 'b':
|
||||
BootMode = YAP_BOOT_FROM_PROLOG;
|
||||
iap->YapPrologBootFile = *++argv;
|
||||
argc--;
|
||||
break;
|
||||
case '?':
|
||||
print_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'q':
|
||||
iap->QuietMode = TRUE;
|
||||
break;
|
||||
#if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) || \
|
||||
defined(YAPOR_THREADS)
|
||||
case 'w':
|
||||
ssize = &(iap->NumberWorkers);
|
||||
goto GetSize;
|
||||
case 'd':
|
||||
if (!strcmp("dump-runtime-variables", p))
|
||||
return dump_runtime_variables();
|
||||
ssize = &(iap->DelayedReleaseLoad);
|
||||
goto GetSize;
|
||||
#else
|
||||
case 'd':
|
||||
if (!strcmp("dump-runtime-variables", p))
|
||||
return dump_runtime_variables();
|
||||
#endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA || YAPOR_THREADS */
|
||||
case 'F':
|
||||
/* just ignore for now */
|
||||
argc--;
|
||||
argv++;
|
||||
break;
|
||||
case 'f':
|
||||
iap->FastBoot = TRUE;
|
||||
if (argc > 1 && argv[1][0] != '-') {
|
||||
argc--;
|
||||
argv++;
|
||||
if (strcmp(*argv, "none")) {
|
||||
iap->YapPrologRCFile = *argv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// execution mode
|
||||
case 'J':
|
||||
switch (p[1]) {
|
||||
case '0':
|
||||
iap->ExecutionMode = YAPC_INTERPRETED;
|
||||
break;
|
||||
case '1':
|
||||
iap->ExecutionMode = YAPC_MIXED_MODE_USER;
|
||||
break;
|
||||
case '2':
|
||||
iap->ExecutionMode = YAPC_MIXED_MODE_ALL;
|
||||
break;
|
||||
case '3':
|
||||
iap->ExecutionMode = YAPC_COMPILE_USER;
|
||||
break;
|
||||
case '4':
|
||||
iap->ExecutionMode = YAPC_COMPILE_ALL;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "[ YAP unrecoverable error: unknown switch -%c%c ]\n",
|
||||
*p, p[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
case 'G':
|
||||
ssize = &(iap->MaxGlobalSize);
|
||||
goto GetSize;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
ssize = &(iap->StackSize);
|
||||
#if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) || \
|
||||
defined(YAPOR_THREADS)
|
||||
if (p[1] == 'l') {
|
||||
p++;
|
||||
ssize = &(iap->SchedulerLoop);
|
||||
}
|
||||
#endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA || YAPOR_THREADS */
|
||||
goto GetSize;
|
||||
case 'a':
|
||||
case 'A':
|
||||
ssize = &(iap->AttsSize);
|
||||
goto GetSize;
|
||||
case 'T':
|
||||
ssize = &(iap->MaxTrailSize);
|
||||
goto get_trail_size;
|
||||
case 't':
|
||||
ssize = &(iap->TrailSize);
|
||||
#ifdef TABLING
|
||||
if (p[1] == 's') {
|
||||
p++;
|
||||
ssize = &(iap->MaxTableSpaceSize);
|
||||
}
|
||||
#endif /* TABLING */
|
||||
get_trail_size:
|
||||
if (*++p == '\0') {
|
||||
if (argc > 1)
|
||||
--argc, p = *++argv;
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"[ YAP unrecoverable error: missing size in flag %s ]",
|
||||
argv[0]);
|
||||
print_usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned long int i = 0, ch;
|
||||
while ((ch = *p++) >= '0' && ch <= '9')
|
||||
i = i * 10 + ch - '0';
|
||||
switch (ch) {
|
||||
case 'M':
|
||||
case 'm':
|
||||
i *= 1024;
|
||||
ch = *p++;
|
||||
break;
|
||||
case 'g':
|
||||
i *= 1024 * 1024;
|
||||
ch = *p++;
|
||||
break;
|
||||
case 'k':
|
||||
case 'K':
|
||||
ch = *p++;
|
||||
break;
|
||||
}
|
||||
if (ch) {
|
||||
iap->YapPrologTopLevelGoal = add_end_dot(*argv);
|
||||
} else {
|
||||
*ssize = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
ssize = &(iap->HeapSize);
|
||||
GetSize:
|
||||
if (*++p == '\0') {
|
||||
if (argc > 1)
|
||||
--argc, p = *++argv;
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"[ YAP unrecoverable error: missing size in flag %s ]",
|
||||
argv[0]);
|
||||
print_usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned long int i = 0, ch;
|
||||
while ((ch = *p++) >= '0' && ch <= '9')
|
||||
i = i * 10 + ch - '0';
|
||||
switch (ch) {
|
||||
case 'M':
|
||||
case 'm':
|
||||
i *= 1024;
|
||||
ch = *p++;
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
i *= 1024 * 1024;
|
||||
ch = *p++;
|
||||
break;
|
||||
case 'k':
|
||||
case 'K':
|
||||
ch = *p++;
|
||||
break;
|
||||
}
|
||||
if (ch) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"[ YAP unrecoverable error: illegal size specification %s ]",
|
||||
argv[-1]);
|
||||
Yap_exit(1);
|
||||
}
|
||||
*ssize = i;
|
||||
}
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case 'P':
|
||||
YAP_SetOutputMessage();
|
||||
if (p[1] != '\0') {
|
||||
while (p[1] != '\0') {
|
||||
int ch = p[1];
|
||||
if (ch >= 'A' && ch <= 'Z')
|
||||
ch += ('a' - 'A');
|
||||
if (ch >= 'a' && ch <= 'z')
|
||||
GLOBAL_Option[ch - 96] = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'L':
|
||||
if (p[1] && p[1] >= '0' &&
|
||||
p[1] <= '9') /* hack to emulate SWI's L local option */
|
||||
{
|
||||
ssize = &(iap->MaxStackSize);
|
||||
goto GetSize;
|
||||
}
|
||||
iap->QuietMode = TRUE;
|
||||
iap->HaltAfterConsult = TRUE;
|
||||
case 'l':
|
||||
p++;
|
||||
if (!*++argv) {
|
||||
fprintf(stderr,
|
||||
"%% YAP unrecoverable error: missing load file name\n");
|
||||
exit(1);
|
||||
} else if (!strcmp("--", *argv)) {
|
||||
/* shell script, the next entry should be the file itself */
|
||||
iap->YapPrologRCFile = argv[1];
|
||||
argc = 1;
|
||||
break;
|
||||
} else {
|
||||
iap->YapPrologRCFile = *argv;
|
||||
argc--;
|
||||
}
|
||||
if (*p) {
|
||||
/* we have something, usually, of the form:
|
||||
-L --
|
||||
FileName
|
||||
ExtraArgs
|
||||
*/
|
||||
/* being called from a script */
|
||||
while (*p && (*p == ' ' || *p == '\t'))
|
||||
p++;
|
||||
if (p[0] == '-' && p[1] == '-') {
|
||||
/* ignore what is next */
|
||||
argc = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* run goal before top-level */
|
||||
case 'g':
|
||||
if ((*argv)[0] == '\0')
|
||||
iap->YapPrologGoal = *argv;
|
||||
else {
|
||||
argc--;
|
||||
if (argc == 0) {
|
||||
fprintf(stderr, " [ YAP unrecoverable error: missing "
|
||||
"initialization goal for option 'g' ]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
argv++;
|
||||
iap->YapPrologGoal = *argv;
|
||||
}
|
||||
break;
|
||||
/* run goal as top-level */
|
||||
case 'z':
|
||||
if ((*argv)[0] == '\0')
|
||||
iap->YapPrologTopLevelGoal = *argv;
|
||||
else {
|
||||
argc--;
|
||||
if (argc == 0) {
|
||||
fprintf(
|
||||
stderr,
|
||||
" [ YAP unrecoverable error: missing goal for option 'z' ]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
argv++;
|
||||
iap->YapPrologTopLevelGoal = add_end_dot(*argv);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (!strcmp("nosignals", p)) {
|
||||
iap->PrologShouldHandleInterrupts = FALSE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if (!strcmp("-nosignals", p)) {
|
||||
iap->PrologShouldHandleInterrupts = FALSE;
|
||||
break;
|
||||
} else if (!strncmp("-home=", p, strlen("-home="))) {
|
||||
GLOBAL_Home = p + strlen("-home=");
|
||||
} else if (!strncmp("-cwd=", p, strlen("-cwd="))) {
|
||||
#if __WINDOWS__
|
||||
if (_chdir(p + strlen("-cwd=")) < 0) {
|
||||
#else
|
||||
if (chdir(p + strlen("-cwd=")) < 0) {
|
||||
#endif
|
||||
fprintf(stderr, " [ YAP unrecoverable error in setting cwd: %s ]\n",
|
||||
strerror(errno));
|
||||
}
|
||||
} else if (!strncmp("-stack=", p, strlen("-stack="))) {
|
||||
ssize = &(iap->StackSize);
|
||||
p += strlen("-stack=");
|
||||
goto GetSize;
|
||||
} else if (!strncmp("-trail=", p, strlen("-trail="))) {
|
||||
ssize = &(iap->TrailSize);
|
||||
p += strlen("-trail=");
|
||||
goto GetSize;
|
||||
} else if (!strncmp("-heap=", p, strlen("-heap="))) {
|
||||
ssize = &(iap->HeapSize);
|
||||
p += strlen("-heap=");
|
||||
goto GetSize;
|
||||
} else if (!strncmp("-goal=", p, strlen("-goal="))) {
|
||||
iap->YapPrologGoal = p + strlen("-goal=");
|
||||
} else if (!strncmp("-top-level=", p, strlen("-top-level="))) {
|
||||
iap->YapPrologTopLevelGoal = p + strlen("-top-level=");
|
||||
} else if (!strncmp("-table=", p, strlen("-table="))) {
|
||||
ssize = &(iap->MaxTableSpaceSize);
|
||||
p += strlen("-table=");
|
||||
goto GetSize;
|
||||
} else if (!strncmp("-", p, strlen("-="))) {
|
||||
ssize = &(iap->MaxTableSpaceSize);
|
||||
p += strlen("-table=");
|
||||
/* skip remaining arguments */
|
||||
argc = 1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if ((*argv)[0] == '\0')
|
||||
iap->YapPrologAddPath = *argv;
|
||||
else {
|
||||
argc--;
|
||||
if (argc == 0) {
|
||||
fprintf(
|
||||
stderr,
|
||||
" [ YAP unrecoverable error: missing paths for option 'p' ]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
argv++;
|
||||
iap->YapPrologAddPath = *argv;
|
||||
}
|
||||
break;
|
||||
/* nf: Begin preprocessor code */
|
||||
case 'D': {
|
||||
char *var, *value;
|
||||
++p;
|
||||
var = p;
|
||||
if (var == NULL || *var == '\0')
|
||||
break;
|
||||
while (*p != '=' && *p != '\0')
|
||||
++p;
|
||||
if (*p == '\0')
|
||||
break;
|
||||
*p = '\0';
|
||||
++p;
|
||||
value = p;
|
||||
if (*value == '\0')
|
||||
break;
|
||||
if (iap->def_c == YAP_MAX_YPP_DEFS)
|
||||
break;
|
||||
iap->def_var[iap->def_c] = var;
|
||||
iap->def_value[iap->def_c] = value;
|
||||
++(iap->def_c);
|
||||
break;
|
||||
}
|
||||
/* End preprocessor code */
|
||||
default: {
|
||||
fprintf(stderr, "[ YAP unrecoverable error: unknown switch -%c ]\n",
|
||||
*p);
|
||||
print_usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
iap->SavedState = p;
|
||||
}
|
||||
}
|
||||
//___androidlog_print(ANDROID_LOG_INFO, "YAP ", "boot mode %d", BootMode);
|
||||
return BootMode;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue