Files
mercury/compiler/prog_data.m
Oliver Hutchison bcf7dbf9f8 Add support for tabling.
Estimated hours taken: 250

Add support for tabling.

This change allows for model_det, model_semidet and model_non memoing,
minimal model and loop detection tabling.

compiler/base_type_layout.m:
	Update comments to reflect new runtime naming standard.

compiler/det_analysis.m:
	Allow tabling to change the result of det analysis. This is
	necessary in the case of minimal model tabling which can
	turn a det procedure into a semidet one.

compiler/det_report.m:
compiler/hlds_data.m:
	Add code to report error messages for various non compatible
	tabling methods and determinism.

compiler/hlds_out.m:
compiler/modules.m:
	Remove reference to the old memo marker.

compiler/hlds_pred.m:
	Create new type (eval_method) to define which of the available
	evaluation methods should be used each procedure.
	Add new field to the proc_info structure.
	Add several new predicates relating to the new eval_method type.

compiler/inlining.m:
compiler/intermod.m:
	Make sure only procedures with normal evaluation are inlined.

compiler/make_hlds.m:
	Add code to process new tabling pragmas.

compiler/mercury_compile.m:
	Call the tabling transformation code.

compiler/modes.m:
	Make sure that all procedures with non normal evaluation have
	no unique/partially instantiated modes. Produce error messages
	if they do. Support for partially instantiated modes is currently
	missing as it represents a large amount of work for a case that
	is currently not used.

compiler/module_qual.m:
compile/prog_data.m:
compiler/prog_io_pragma.m:
	Add three new pragma types:
		`memo'
		`loop_check'
		`minimal_model'
	and code to support them.

compiler/simplify.m:
	Don't report infinite recursion warning if a procedure has
	minimal model evaluation.

compiler/stratify.m:
	Change the stratification analyser so that it reports cases of
	definite non-stratification. Rather than reporting warnings for
	any code that is not definitely stratified.
	Remove reference to the old memo marker.

compiler/switch_detection.m:
	Fix a small bug where goal were being placed in reverse order.
	Call list__reverse on the list of goals.

compiler/table_gen.m:
	New module to do the actual tabling transformation.

compiler/notes/compiler_design.html:
	Document addition of new tabling pass to the compiler.

doc/reference_manual.texi:
	Fix mistake in example.

library/mercury_builtin.m:
	Add many new predicates for support of tabling.

library/std_util.m:
library/store.m:
	Move the functions :
		ML_compare_type_info
		ML_collapse_equivalences
		ML_create_type_info
	to the runtime.

runtime/mercury_deep_copy.c:
runtime/mercury_type_info.h:
runtime/mercury_type_info.c:
	Move the make_type_info function into the mercury_type_info module
	and make it public.

runtime/Mmakefile:
runtime/mercury_imp.h:
	Add references to new files added for tabling support.

runtime/mercury_string.h:
	Change hash macro so it does not cause a name clash with any
	variable called "hash".

runtime/mercury_type_info.c:
runtime/mercury_type_info.h:
	Add three new functions taken from the library :
		MR_compare_type_info
		MR_collapse_equivalences
		MR_create_type_info.

runtime/mercury_table_any.c:
runtime/mercury_table_any.h:
runtime/mercury_table_enum.c:
runtime/mercury_table_enum.h:
runtime/mercury_table_int_float_string.c:
runtime/mercury_table_int_float_string.h:
runtime/mercury_table_type_info.c:
runtime/mercury_table_type_info.h:
runtime/mercury_tabling.h:
	New modules for the support of tabling.
1998-05-15 07:09:29 +00:00

561 lines
18 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1996-1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% File: prog_data.m.
% Main author: fjh.
%
% This module defines a data structure for representing Mercury programs.
%
% This data structure specifies basically the same information as is
% contained in the source code, but in a parse tree rather than a flat file.
% Simplifications are done only by make_hlds.m, which transforms
% the parse tree which we built here into the HLDS.
:- module prog_data.
:- interface.
:- import_module hlds_data, hlds_pred, (inst), purity, term_util.
:- import_module list, map, varset, term, std_util.
%-----------------------------------------------------------------------------%
% This is how programs (and parse errors) are represented.
:- type message_list == list(pair(string, term)).
% the error/warning message, and the
% term to which it relates
:- type compilation_unit
---> module(
module_name,
item_list
).
:- type item_list == list(item_and_context).
:- type item_and_context == pair(item, term__context).
:- type item
---> pred_clause(varset, sym_name, list(term), goal)
% VarNames, PredName, HeadArgs, ClauseBody
; func_clause(varset, sym_name, list(term), term, goal)
% VarNames, PredName, HeadArgs, Result, ClauseBody
; type_defn(varset, type_defn, condition)
; inst_defn(varset, inst_defn, condition)
; mode_defn(varset, mode_defn, condition)
; module_defn(varset, module_defn)
; pred(varset, sym_name, list(type_and_mode),
maybe(determinism), condition, purity,
list(class_constraint))
% VarNames, PredName, ArgTypes, Deterministicness, Cond
; func(varset, sym_name, list(type_and_mode), type_and_mode,
maybe(determinism), condition, purity,
list(class_constraint))
% VarNames, PredName, ArgTypes, ReturnType,
% Deterministicness, Cond
; pred_mode(varset, sym_name, list(mode), maybe(determinism),
condition)
% VarNames, PredName, ArgModes, Deterministicness,
% Cond
; func_mode(varset, sym_name, list(mode), mode,
maybe(determinism), condition)
% VarNames, PredName, ArgModes, ReturnValueMode,
% Deterministicness, Cond
; pragma(pragma_type)
; typeclass(list(class_constraint), class_name, list(var),
class_interface, varset)
% Constraints, ClassName, ClassParams,
% ClassMethods, VarNames
; instance(list(class_constraint), class_name, list(type),
instance_interface, varset)
% DerivingClass, ClassName, Types,
% MethodInstances, VarNames
; nothing.
% used for items that should be ignored (currently only
% NU-Prolog `when' declarations, which are silently ignored
% for backwards compatibility).
:- type type_and_mode
---> type_only(type)
; type_and_mode(type, mode).
:- type pragma_type
---> c_header_code(string)
; c_code(string)
; c_code(may_call_mercury, sym_name, pred_or_func,
list(pragma_var), varset, pragma_c_code_impl)
% Whether or not the C code may call Mercury,
% PredName, Predicate or Function, Vars/Mode,
% VarNames, C Code Implementation Info
; inline(sym_name, arity)
% Predname, Arity
; no_inline(sym_name, arity)
% Predname, Arity
; obsolete(sym_name, arity)
% Predname, Arity
; export(sym_name, pred_or_func, list(mode),
string)
% Predname, Predicate/function, Modes,
% C function name.
; import(sym_name, pred_or_func, list(mode),
may_call_mercury, string)
% Predname, Predicate/function, Modes,
% whether or not the C function may call Mercury,
% C function name.
; source_file(string)
% Source file name.
; unused_args(pred_or_func, sym_name, int,
proc_id, list(int))
% PredName, Arity, Mode, Optimized pred name,
% Removed arguments.
% Used for inter-module unused argument
% removal, should only appear in .opt files.
; fact_table(sym_name, arity, string)
% Predname, Arity, Fact file name.
; tabled(eval_method, sym_name, int, maybe(pred_or_func),
maybe(list(mode)))
% Tabling type, Predname, Arity, PredOrFunc?, Mode?
; promise_pure(sym_name, arity)
% Predname, Arity
; termination_info(pred_or_func, sym_name, list(mode),
maybe(arg_size_info), maybe(termination_info))
% the list(mode) is the declared argmodes of the
% procedure, unless there are no declared argmodes,
% in which case the inferred argmodes are used.
% This pragma is used to define information about a
% predicates termination properties. It is most
% useful where the compiler has insufficient
% information to be able to analyse the predicate.
% This includes c_code, and imported predicates.
% termination_info pragmas are used in opt and
% trans_opt files.
; terminates(sym_name, arity)
% Predname, Arity
; does_not_terminate(sym_name, arity)
% Predname, Arity
; check_termination(sym_name, arity).
% Predname, Arity
% This type holds information about the implementation details
% of procedures defined via `pragma c_code'.
% All the strings in this type may be accompanied by the context
% of their appearance in the source code. These contexts are
% used to tell the C compiler where the included C code comes from,
% to allow it to generate error messages that refer to the original
% appearance of the code in the Mercury program.
% The context is missing if the C code was constructed by the compiler.
:- type pragma_c_code_impl
---> ordinary( % This is a C definition of a model_det
% or model_semi procedure. (We also
% allow model_non, until everyone has
% had time to adapt to the new way
% of handling model_non pragmas.)
string, % The C code of the procedure.
maybe(term__context)
)
; nondet( % This is a C definition of a model_non
% procedure.
string,
maybe(term__context),
% The info saved for the time when
% backtracking reenters this procedure
% is stored in a C struct. This arg
% contains the field declarations.
string,
maybe(term__context),
% Gives the code to be executed when
% the procedure is called for the first
% time. This code may access the input
% variables.
string,
maybe(term__context),
% Gives the code to be executed when
% control backtracks into the procedure.
% This code may not access the input
% variables.
pragma_shared_code_treatment,
% How should the shared code be
% treated during code generation.
string,
maybe(term__context)
% Shared code that is executed after
% both the previous code fragments.
% May not access the input variables.
).
% The use of this type is explained in the comment at the top of
% pragma_c_gen.m.
:- type pragma_shared_code_treatment
---> duplicate
; share
; automatic.
% A class constraint represents a constraint that a given
% list of types is a member of the specified type class.
% It is an invariant of this data structure that
% the types in a class constraint do not contain any
% information in their term__context fields.
% This invariant is needed to ensure that we can do
% unifications, map__lookups, etc., and get the
% expected semantics.
% Any code that creates new class constraints must
% ensure that this invariant is preserved,
% probably by using strip_term_contexts/2 in type_util.m.
:- type class_constraint
---> constraint(class_name, list(type)).
:- type class_name == sym_name.
:- type class_interface == list(class_method).
:- type class_method ---> pred(varset, sym_name, list(type_and_mode),
maybe(determinism), condition,
list(class_constraint), term__context)
% VarNames, PredName, ArgTypes,
% Determinism, Cond
% ClassContext, Context
; func(varset, sym_name, list(type_and_mode),
type_and_mode,
maybe(determinism), condition,
list(class_constraint), term__context)
% VarNames, PredName, ArgTypes,
% ReturnType,
% Determinism, Cond
% ClassContext, Context
; pred_mode(varset, sym_name, list(mode),
maybe(determinism), condition,
term__context)
% VarNames, PredName, ArgModes,
% Determinism, Cond
% Context
; func_mode(varset, sym_name, list(mode), mode,
maybe(determinism), condition,
term__context)
% VarNames, PredName, ArgModes,
% ReturnValueMode,
% Determinism, Cond
% Context
.
:- type instance_method ---> func_instance(sym_name, sym_name, arity)
; pred_instance(sym_name, sym_name, arity)
% Method, Instance, Arity
.
:- type instance_interface == list(instance_method).
% For pragma c_code, there are two different calling conventions,
% one for C code that may recursively call Mercury code, and another
% more efficient one for the case when we know that the C code will
% not recursively invoke Mercury code.
:- type may_call_mercury
---> may_call_mercury
; will_not_call_mercury.
:- type pragma_var
---> pragma_var(var, string, mode).
% variable, name, mode
% we explicitly store the name because we need the real
% name in code_gen
%-----------------------------------------------------------------------------%
% Here's how clauses and goals are represented.
% a => b --> implies(a, b)
% a <= b --> implies(b, a) [just flips the goals around!]
% a <=> b --> equivalent(a, b)
% clause/4 defined above
:- type goal == pair(goal_expr, term__context).
:- type goal_expr
---> (goal,goal)
; true
% could use conj(goals) instead
; {goal;goal} % {...} quotes ';'/2.
; fail
% could use disj(goals) instead
; not(goal)
; some(vars,goal)
; all(vars,goal)
; implies(goal,goal)
; equivalent(goal,goal)
; if_then(vars,goal,goal)
; if_then_else(vars,goal,goal,goal)
; call(sym_name, list(term), purity)
; unify(term, term).
:- type goals == list(goal).
:- type vars == list(var).
%-----------------------------------------------------------------------------%
% This is how types are represented.
% one day we might allow types to take
% value parameters as well as type parameters.
% type_defn/3 define above
:- type type_defn
---> du_type(sym_name, list(type_param), list(constructor),
maybe(equality_pred)
)
; uu_type(sym_name, list(type_param), list(type))
; eqv_type(sym_name, list(type_param), type)
; abstract_type(sym_name, list(type_param)).
:- type constructor == pair(sym_name, list(constructor_arg)).
:- type constructor_arg == pair(string, type).
% An equality_pred specifies the name of a user-defined predicate
% used for equality on a type. See the chapter on them in the
% Mercury Language Reference Manual.
:- type equality_pred == sym_name.
% probably type parameters should be variables not terms.
:- type type_param == term.
% Module qualified types are represented as ':'/2 terms.
% Use type_util:type_to_type_id to convert a type to a qualified
% type_id and a list of arguments.
% type_util:construct_type to construct a type from a type_id
% and a list of arguments.
:- type (type) == term.
:- type tvar == var. % used for type variables
:- type tvarset == varset. % used for sets of type variables
:- type tsubst == map(tvar, type). % used for type substitutions
% Types may have arbitrary assertions associated with them
% (eg. you can define a type which represents sorted lists).
% Similarly, pred declarations can have assertions attached.
% The compiler will ignore these assertions - they are intended
% to be used by other tools, such as the debugger.
:- type condition
---> true
; where(term).
%-----------------------------------------------------------------------------%
% This is how instantiatednesses and modes are represented.
% Note that while we use the normal term data structure to represent
% type terms (see above), we need a separate data structure for inst
% terms.
% inst_defn/3 defined above
:- type inst_defn
---> eqv_inst(sym_name, list(inst_param), inst)
; abstract_inst(sym_name, list(inst_param)).
% probably inst parameters should be variables not terms
:- type inst_param == term.
% An `inst_name' is used as a key for the inst_table.
% It is either a user-defined inst `user_inst(Name, Args)',
% or some sort of compiler-generated inst, whose name
% is a representation of it's meaning.
%
% For example, `merge_inst(InstA, InstB)' is the name used for the
% inst that results from merging InstA and InstB using `merge_inst'.
% Similarly `unify_inst(IsLive, InstA, InstB, IsReal)' is
% the name for the inst that results from a call to
% `abstractly_unify_inst(IsLive, InstA, InstB, IsReal)'.
% And `ground_inst' and `any_inst' are insts that result
% from unifying an inst with `ground' or `any', respectively.
% `typed_inst' is an inst with added type information.
% `typed_ground(Uniq, Type)' a equivalent to
% `typed_inst(ground(Uniq, no), Type)'.
% Note that `typed_ground' is a special case of `typed_inst',
% and `ground_inst' and `any_inst' are special cases of `unify_inst'.
% The reason for having the special cases is efficiency.
:- type inst_name
---> user_inst(sym_name, list(inst))
; merge_inst(inst, inst)
; unify_inst(is_live, inst, inst, unify_is_real)
; ground_inst(inst_name, is_live, uniqueness, unify_is_real)
; any_inst(inst_name, is_live, uniqueness, unify_is_real)
; shared_inst(inst_name)
; mostly_uniq_inst(inst_name)
; typed_ground(uniqueness, type)
; typed_inst(type, inst_name).
% Note: `is_live' records liveness in the sense used by
% mode analysis. This is not the same thing as the notion of liveness
% used by code generation. See compiler/notes/glossary.html.
:- type is_live ---> live ; dead.
% Unifications of insts fall into two categories, "real" and "fake".
% The "real" inst unifications correspond to real unifications,
% and are not allowed to unify with `clobbered' insts (unless
% the unification would be `det').
% Any inst unification which is associated with some code that
% will actually examine the contents of the variables in question
% must be "real". Inst unifications that are not associated with
% some real code that examines the variables' values are "fake".
% "Fake" inst unifications are used for procedure calls in implied
% modes, where the final inst of the var must be computed by
% unifying its initial inst with the procedure's final inst,
% so that if you pass a ground var to a procedure whose mode
% is `free -> list_skeleton', the result is ground, not list_skeleton.
% But these fake unifications must be allowed to unify with `clobbered'
% insts. Hence we pass down a flag to `abstractly_unify_inst' which
% specifies whether or not to allow unifications with clobbered values.
:- type unify_is_real
---> real_unify
; fake_unify.
% mode_defn/3 defined above
:- type mode_defn
---> eqv_mode(sym_name, list(inst_param), mode).
:- type (mode)
---> ((inst) -> (inst))
; user_defined_mode(sym_name, list(inst)).
% mode/4 defined above
%-----------------------------------------------------------------------------%
% This is how module-system declarations (such as imports
% and exports) are represented.
:- type module_defn
---> module(module_name)
; end_module(module_name)
; interface
; implementation
; imported
% This is used internally by the compiler,
% to identify declarations which originally
% came from some other module imported with
% a `:- import_module' declaration.
; used
% This is used internally by the compiler,
% to identify declarations which originally
% came from some other module and for which
% all uses must be module qualified. This
% applies to items from modules imported using
% `:- use_module', and items from `.opt'
% and `.int2' files.
; opt_imported
% This is used internally by the compiler,
% to identify items which originally
% came from a .opt file.
; external(sym_name_specifier)
; export(sym_list)
; import(sym_list)
; use(sym_list)
; include_module(list(module_name)).
:- type sym_list
---> sym(list(sym_specifier))
; pred(list(pred_specifier))
; func(list(func_specifier))
; cons(list(cons_specifier))
; op(list(op_specifier))
; adt(list(adt_specifier))
; type(list(type_specifier))
; module(list(module_specifier)).
:- type sym_specifier
---> sym(sym_name_specifier)
; typed_sym(typed_cons_specifier)
; pred(pred_specifier)
; func(func_specifier)
; cons(cons_specifier)
; op(op_specifier)
; adt(adt_specifier)
; type(type_specifier)
; module(module_specifier).
:- type pred_specifier
---> sym(sym_name_specifier)
; name_args(sym_name, list(type)).
:- type func_specifier == cons_specifier.
:- type cons_specifier
---> sym(sym_name_specifier)
; typed(typed_cons_specifier).
:- type typed_cons_specifier
---> name_args(sym_name, list(type))
; name_res(sym_name_specifier, type)
; name_args_res(sym_name, list(type), type).
:- type adt_specifier == sym_name_specifier.
:- type type_specifier == sym_name_specifier.
:- type op_specifier
---> sym(sym_name_specifier)
% operator fixity specifiers not yet implemented
; fixity(sym_name_specifier, fixity).
:- type fixity
---> infix
; prefix
; postfix
; binary_prefix
; binary_postfix.
:- type sym_name_specifier
---> name(sym_name)
; name_arity(sym_name, arity).
:- type sym_name
---> unqualified(string)
; qualified(module_specifier, string).
:- type module_specifier == sym_name.
:- type module_name == sym_name.
:- type arity == int.
% Describes whether an item can be used without an
% explicit module qualifier.
:- type need_qualifier
---> must_be_qualified
; may_be_unqualified.
%-----------------------------------------------------------------------------%