[mercury-users] Functor(Arg) Terms Construction (Not Partially Instantitated?)

Fergus Henderson fjh at cs.mu.OZ.AU
Mon May 19 12:58:58 AEST 2003


On 18-May-2003, Goncalo Jorge Coelho e Silva <l10454 at alunos.uevora.pt> wrote:
> 
> But, would I be able to construct a functor(arguments) term
> using a one-fits-all predicate like this one?
> 
> (using this example of non-compilable Mercury, just to show 
>  what I'd like) 
> 
> :- type address == int.
> :- type value == int.
> :- type my_things ---> set_value(address, value).
> 
> main -->
>          {
>          X = 1,
>          Y = 1,
>          Z = "set_value",
>          Term = Z(X, Y)
>          },
>          run_instr(Term).
> 
> run_instr(set_value(Address, Value))-->
> 	...

If you really want to do something like that, it is possible to do so using
the procedures in the `construct' module in the standard library.  Instead
of writing `Term = Z(X, Y)', you can write `Term = make_term(Z, X, Y)',
where make_term is defined as follows:

	:- import_module int, list, std_util, construct, require.

	:- func make_term(string, T1, T2) = T.
	make_term(Functor, Arg1, Arg2) =
		make_term_with_arglist(Functor, [univ(Arg1), univ(Arg2)]).

	:- func make_term_with_arglist(string, list(univ)) = T.
	make_term_with_arglist(Functor, Args) = Term :-
		Arity = list.length(Args),
		Type = std_util.type_of(Term),
		(if
			Univ = construct.construct(Type,
				lookup_constructor(Type, Functor, Arity),
				Args),
			std_util.univ_to_type(Univ, Term0)
		then
			Term = Term0
		else
			require.error("make_term_with_arglist failed")
		).

	:- func lookup_constructor(type_desc, string, int) = int.
	lookup_constructor(Type, FunctorName, Arity) =
		lookup_constructor_2(Type, FunctorName, Arity,
			0, construct.num_functors(Type)).

	:- func lookup_constructor_2(type_desc, string, int, int, int) = int.
	lookup_constructor_2(Type, FunctorName, Arity, CtorNum0, Max)
			= CtorNum :-
		(if CtorNum0 >= Max then
			require.error("lookup_constructor failed")
		else if construct.get_functor(Type, CtorNum0, FunctorName,
				Arity, _)
		then
			CtorNum = CtorNum0
		else
			CtorNum = lookup_constructor_2(Type,
				FunctorName, Arity, CtorNum0 + 1, Max)
		).

Possibly the predicates make_term, make_term_with_arglist, and
lookup_constructor may be good candidates for future additions
to the Mercury standard library.

I have attached a complete working example.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
-------------- next part --------------
	:- module construct_example.
	:- interface.
	:- import_module io.

	:- pred main(io::di, io::uo) is det.
	
	:- implementation.
	:- import_module int, list, std_util, construct, require.

	:- type address == int.
	:- type value == int.
	:- type my_things ---> set_value(address, value).

	main -->
		{
		X = 1,
		Y = 1,
		Z = "set_value",
		Term = make_term(Z, X, Y)
		},
		run_instr(Term).

	:- pred run_instr(my_things::in, io.state::di, io.state::uo)
		is det.
	run_instr(set_value(Address, Value)) -->
		print("set_value "), print(Address), print(" "), print(Value),
		nl.

	:- func make_term(string, T1, T2) = T.
	make_term(Functor, Arg1, Arg2) =
		make_term_with_arglist(Functor, [univ(Arg1), univ(Arg2)]).

	:- func make_term_with_arglist(string, list(univ)) = T.
	make_term_with_arglist(Functor, Args) = Term :-
		Arity = list.length(Args),
		Type = std_util.type_of(Term),
		(if
			Univ = construct.construct(Type,
				lookup_constructor(Type, Functor, Arity),
				Args),
			std_util.univ_to_type(Univ, Term0)
		then
			Term = Term0
		else
			require.error("make_term_with_arglist failed")
		).

	:- func lookup_constructor(type_desc, string, int) = int.
	lookup_constructor(Type, FunctorName, Arity) =
		lookup_constructor_2(Type, FunctorName, Arity,
			0, construct.num_functors(Type)).

	:- func lookup_constructor_2(type_desc, string, int, int, int) = int.
	lookup_constructor_2(Type, FunctorName, Arity, CtorNum0, Max)
			= CtorNum :-
		(if CtorNum0 >= Max then
			require.error("lookup_constructor failed")
		else if construct.get_functor(Type, CtorNum0, FunctorName,
				Arity, _)
		then
			CtorNum = CtorNum0
		else
			CtorNum = lookup_constructor_2(Type,
				FunctorName, Arity, CtorNum0 + 1, Max)
		).



More information about the users mailing list