[m-dev.] Tabling [2/3]
Fergus Henderson
fjh at cs.mu.OZ.AU
Tue Mar 31 00:21:37 AEST 1998
On 23-Mar-1998, Oliver Hutchison <ohutch at students.cs.mu.oz.au> wrote:
> Index: library/mercury_builtin.m
> +% 2) Predicates to test and set the status of the tables. These predicates
> +% expect ether a subgoal or answer table node depending there
> +% functionality.
s/ether/either/
s/there/on their/
> +% 3) Predicates to save answers into the tables. Answers are saved in
> +% an answer block which is a vector n elements where n is the number
> +% of output arguments of the predicate it belongs to. For det and
> +% semidet tabling the answer block is connected directly to subgoal
> +% table nodes. In the case of nondet tabling answer blocks are connected
> +% to answered slots which are strung together to form a list.
s/block which/block, which/
s/vector n elements/vector of n elements/
> + % This type is used as a generic table it can in fact represent two
> + % types ether a subgoal_table or an answer_table. The subgoal_table
> + % and answer_table types are differentiated by what they have at the
> + % table nodes but not by the actual underling trie structure.
s/table it can/table: it can/
s/types ether/types, either/
By the way, the use of different types for the different sorts of tables
makes the code *much* easier to read. Thanks.
> + % This is a dummy predicate, its pred_proc_id, but not its code,
> + % is used. See the comment in compiler/table_gen.m for more
> + % information.
> +:- impure pred get_table(table).
s/predicate, its/predicate: its/
> + % Create a new slot in the answer list.
> +:- impure pred table_new_ans_slot(subgoal_table_node, answer_slot).
> +:- mode table_new_ans_slot(in, out) is det.
> +
> + % Return true if the subgoal represented by the given table is
> +
> + % Save an integer answer in the given answer block at the given
> + % offset.
> +:- impure pred table_save_int_ans(answer_block, int, int).
> +:- mode table_save_int_ans(in, in, in) is det.
The unfinished comment in the middle looks like it is not meant to
be there.
> +/* Used to save the state of a subgoal */
> +typedef struct {
> + Word *last_ret_ans; /* Pointer to the last answer return
> + to the node */
Should that be "returned" instead of "return"?
> +/* Used to save info about a single subgoal in the table */
> +typedef struct {
> + TableStatus status; /* Status of subgoal */
> + Word answer_table; /* Table of answers returnd by the
> + subgoal */
> + Word num_ans; /* Number of answers returnd by the
> + subgoal */
> + Word answer_list; /* List of answers returnd by the
> + subgoal */
> + Word *ans_list_tail; /* Pointer to the tail of the ans
> + list. This is used to update the
> + tail rather than the head of the
> + ans list. */
> + Word suspend_list; /* List of suspended calls to the
> + subgoal */
> + Word *suspend_list_tail; /* Dito for ans_list_tail */
> + Word *non_stack_bottom; /* Pointer to the bottom point of
> + the nondet stack from whicj to
> + copy */
> + Word *det_stack_bottom; /* Pointer to the bottom point of
> + the det stack from which to copy */
s/returnd/returned/g
s/whicj/which/
s/Dito/Ditto/
s/ans/answer/
> +:- pragma c_code(table_suspend(T::in, A::out), will_not_call_mercury, "
> + Word *non_stack_top = MR_maxfr;
> + Word *det_stack_top = MR_sp;
> + Word *non_stack_bottom = NON_TABLE(T)->non_stack_bottom;
> + Word *det_stack_bottom = NON_TABLE(T)->det_stack_bottom;
> + Word non_stack_delta = non_stack_top - non_stack_bottom;
> + Word det_stack_delta = det_stack_top - det_stack_bottom;
> + Word ListNode;
> + SuspendListNode *Node = table_allocate(sizeof(SuspendListNode));
> +
> + Node->last_ret_ans = &(NON_TABLE(T)->answer_list);
> +
> + Node->non_stack_block_size = non_stack_delta;
> + Node->non_stack_block = table_allocate(non_stack_delta);
> + table_copy_mem((void *)Node->non_stack_block, (void *)non_stack_bottom,
> + non_stack_delta);
> +
> + Node->det_stack_block_size = det_stack_delta;
> + Node->det_stack_block = table_allocate(det_stack_delta);
> + table_copy_mem((void *)Node->det_stack_block, (void *)det_stack_bottom,
> + det_stack_delta);
> +
> + Node->succ_ip = MR_succip;
> + Node->s_p = MR_sp;
> + Node->cur_fr = MR_curfr;
> + Node->max_fr = MR_maxfr;
> +
> + ListNode = list_cons(Node, *NON_TABLE(T)->suspend_list_tail);
> + *NON_TABLE(T)->suspend_list_tail = ListNode;
> + NON_TABLE(T)->suspend_list_tail = &list_tail(ListNode);
> +
> + A = 0;
> + fail();
> +").
Some comments here would be nice.
Why do you set A = 0?
I think the call to fail() should instead be a call to FAIL().
Deja vu, I said the same thing last time ;-)
| Some more documentation about the code for this predicate
| would be helpful.
|
| Why is it declared as `nondet'?
|
| Why assign to A if you're only going to immediately fail anyway?
|
| According to the nonexistant documentation for nondet pragma C ;-),
| the `fail()' here should be `FAIL()'.
> +:- external(table_resume/1).
> +
> +:- pragma c_code("
> +
> +typedef struct {
> + NondetTable *table;
> + Word non_stack_block_size;
> + Word *non_stack_block;
> + Word det_stack_block_size;
> + Word *det_stack_block;
> +
> + Code *succ_ip;
> + Word *s_p;
> + Word *cur_fr;
> + Word *max_fr;
> +
> + Word changed;
> + Word num_ans, new_num_ans;
> + Word suspend_list;
> + SuspendListNode *suspend_node;
> + Word ans_list;
> + AnswerListNode *ansNode;
> +} ResumeStackNode;
> +
> +Integer ML_resumption_sp = -1;
> +Word ML_resumption_stack_size = 256; /* Half the initial size of
> + the stack */
> +ResumeStackNode** ML_resumption_stack = NULL;
Please see my comments from last time.
> #define HASH_STRING_FUNC_BODY \
> - int hash; \
> - do_hash_string(hash, s); \
> - return hash;
> + int _hash; \
> + do_hash_string(_hash, s); \
> + return _hash;
Ditto.
> +++ mercury_type_info.h 1998/03/20 05:21:09
> @@ -779,5 +779,26 @@
>
> +Word * MR_create_type_info(Word *, Word *);
> +int MR_compare_type_info(Word, Word);
> +Word MR_collapse_equivalences(Word);
Ditto.
> +/*
> +** definitions for creating type infos from pseudo_type_info's
> +*/
> +
> +/* for make_type_info(), we keep a list of allocated memory cells */
> +struct MemoryCellNode {
> + void *data;
> + struct MemoryCellNode *next;
> +};
> +typedef struct MemoryCellNode *MemoryList;
> +
> +Word * make_type_info(Word *term_type_info, Word *arg_pseudo_type_info,
> + MemoryList *allocated);
> +void deallocate(MemoryList allocated_memory_cells);
MemoryCellNode, MemoryList, make_type_info, and deallocate
should all get an `MR_' prefix, since they're now in the
runtime header files and hence globally visible.
I'd like to see more documentation for table_resume/1 and
table_suspend/1.
That's it for part 2.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list