Changeset 4412

Show
Ignore:
Timestamp:
07/31/08 02:54:42 (5 months ago)
Author:
pmoura
Message:

Added support for using Prolog use_module/2 directives in objects and categories. This allows module predicates to be called using implicit qualification, improving readability.

Location:
trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/compiler/logtalk.pl

    r4411 r4412  
    201201:- dynamic('$lgt_pp_uses_'/1).                  % '$lgt_pp_uses_'(Obj) 
    202202:- dynamic('$lgt_pp_uses_'/3).                  % '$lgt_pp_uses_'(Obj, Predicate, Alias) 
     203:- dynamic('$lgt_pp_use_module_'/3).            % '$lgt_pp_use_module_'(Module, Predicate, Alias) 
    203204:- dynamic('$lgt_pp_calls_'/1).                 % '$lgt_pp_calls_'(Entity) 
    204205:- dynamic('$lgt_pp_info_'/1).                  % '$lgt_pp_info_'(List) 
     
    18261827    \+ '$lgt_current_flag_'(Flag, _). 
    18271828 
    1828 current_logtalk_flag(version, version(2, 32, 2)). 
     1829current_logtalk_flag(version, version(2, 33, 0)). 
    18291830 
    18301831 
     
    48334834    retractall('$lgt_pp_uses_'(_)), 
    48344835    retractall('$lgt_pp_uses_'(_, _, _)), 
     4836    retractall('$lgt_pp_use_module_'(_, _, _)), 
    48354837    retractall('$lgt_pp_calls_'(_)), 
    48364838    retractall('$lgt_pp_info_'(_)), 
     
    54455447 
    54465448 
     5449'$lgt_tr_directive'(use_module, [Module, _], _, _) :- 
     5450    var(Module), 
     5451    throw(instantiation_error). 
     5452 
     5453'$lgt_tr_directive'(uses, [Module, _], _, _) :- 
     5454    \+ callable(Module), 
     5455    throw(type_error(module_identifier, Module)). 
     5456 
    54475457'$lgt_tr_directive'(use_module, [Module, Preds], Input, Output) :-  % module directive 
    54485458    (   atom(Module) -> 
     
    54505460    ;   arg(1, Module, Name) 
    54515461    ), 
    5452     '$lgt_tr_directive'(uses, [Name, Preds], Input, Output). 
     5462    (   '$lgt_pp_module_'(_) ->                                     % we're compiling a module 
     5463        '$lgt_tr_directive'(uses, [Name, Preds], Input, Output)     % as an object 
     5464    ;   '$lgt_tr_use_module_preds'(Preds, Name) 
     5465    ). 
    54535466 
    54545467 
     
    58965909    ;   throw(domain_error(arity_mismatch(Original, Alias))) 
    58975910    ), 
    5898     (   \+ '$lgt_pp_uses_'(_, _, TAlias) -> 
     5911    (   \+ '$lgt_pp_uses_'(_, _, TAlias), 
     5912        \+ '$lgt_pp_use_module_'(_, _, TAlias) -> 
    58995913        TOriginal =.. [_| Args], TAlias =.. [_| Args],  % unify args of TOriginal and TAlias 
    59005914        assertz('$lgt_pp_uses_'(Obj, TOriginal, TAlias)) 
     
    59035917    ), 
    59045918    '$lgt_tr_uses_preds'(Preds, Obj). 
     5919 
     5920 
     5921 
     5922% '$lgt_tr_use_module_preds'(+list, +module_identifier) 
     5923% 
     5924% auxiliary predicate for translating use_module/2 directives in objects or categories 
     5925 
     5926'$lgt_tr_use_module_preds'([], _). 
     5927 
     5928'$lgt_tr_use_module_preds'([Pred| Preds], Module) :- 
     5929    (   nonvar(Pred) -> 
     5930        true 
     5931    ;   throw(instantiation_error) 
     5932    ), 
     5933    (   Pred = (Original::Alias) -> 
     5934        true 
     5935    ;   (Original, Alias) = (Pred, Pred) 
     5936    ), 
     5937    (   (nonvar(Original), nonvar(Alias)) -> 
     5938        true 
     5939    ;   throw(instantiation_error) 
     5940    ), 
     5941    (   '$lgt_valid_pred_ind'(Original, OFunctor, OArity) -> 
     5942        functor(TOriginal, OFunctor, OArity) 
     5943    ;   throw(type_error(predicate_indicator, Original)) 
     5944    ), 
     5945    (   '$lgt_valid_pred_ind'(Alias, AFunctor, AArity) -> 
     5946        functor(TAlias, AFunctor, AArity) 
     5947    ;   throw(type_error(predicate_indicator, Alias)) 
     5948    ), 
     5949    (   OArity =:= AArity -> 
     5950        true 
     5951    ;   throw(domain_error(arity_mismatch(Original, Alias))) 
     5952    ), 
     5953    (   \+ '$lgt_pp_uses_'(_, _, TAlias), 
     5954        \+ '$lgt_pp_use_module_'(_, _, TAlias) -> 
     5955        TOriginal =.. [_| Args], TAlias =.. [_| Args],  % unify args of TOriginal and TAlias 
     5956        assertz('$lgt_pp_use_module_'(Module, TOriginal, TAlias)) 
     5957    ;   functor(TAlias, Functor, Arity), 
     5958        throw(permission_error(modify, uses_module_predicate, Functor/Arity)) 
     5959    ), 
     5960    '$lgt_tr_use_module_preds'(Preds, Module). 
    59055961 
    59065962 
     
    64236479    functor(Alias, Functor, Arity), 
    64246480    throw(permission_error(modify, uses_object_predicate, Functor/Arity)). 
     6481 
     6482 
     6483% conflict with a predicate specified in a use_module/2 directive 
     6484 
     6485'$lgt_tr_head'(Alias, _, _, _) :- 
     6486    '$lgt_pp_use_module_'(_, _, Alias), 
     6487    functor(Alias, Functor, Arity), 
     6488    throw(permission_error(modify, uses_module_predicate, Functor/Arity)). 
    64256489 
    64266490 
     
    73137377    !, 
    73147378    '$lgt_tr_body'(Obj::Pred, TPred, DPred, Ctx). 
     7379 
     7380 
     7381% predicates specified in use_module/2 directives 
     7382 
     7383'$lgt_tr_body'(Alias, ':'(Module, Pred), ':'(Module, Pred), _) :- 
     7384    '$lgt_pp_use_module_'(Module, Pred, Alias), 
     7385    !. 
    73157386 
    73167387 
     
    73467417 
    73477418 
    7348 % Logtalk and Prolog built-in (meta-)predicates 
     7419% remember non-portable predicate calls 
    73497420 
    73507421'$lgt_tr_body'(Pred, _, _, _) :- 
     
    73587429    assertz('$lgt_non_portable_call_'(Functor, Arity)), 
    73597430    fail. 
     7431 
     7432 
     7433% Logtalk and Prolog built-in (meta-)predicates 
    73607434 
    73617435'$lgt_tr_body'(Pred, TPred, DPred, Ctx) :- 
     
    1039610470    functor(Pred, Functor, Arity), 
    1039710471    \+ '$lgt_pp_redefined_built_in_'(Pred, _, _, _, _). 
     10472 
     10473'$lgt_non_portable_call'(':'(Module, Functor/Arity)) :- 
     10474    '$lgt_pp_use_module_'(Module, Pred, _), 
     10475    functor(Pred, Functor, Arity). 
    1039810476 
    1039910477 
  • trunk/manuals/index.html

    r4411 r4412  
    3232    <div class="copyright"> 
    3333        <span>Copyright &copy; <a href="mailto:pmoura@logtalk.org">Paulo Moura</a> &mdash; <a href="http://logtalk.org">Logtalk.org</a></span><br/>  
    34         <span>Last updated on: July 27, 2008</span> 
     34        <span>Last updated on: July 31, 2008</span> 
    3535    </div> 
    3636    <div class="navbottom"> 
  • trunk/manuals/migration/index.html

    r4336 r4412  
    195195 
    196196 
    197 <h2>Calling Prolog module predicates using message sending<a id="calling"></a></h2> 
    198  
    199 <p> 
    200 Logtalk allows you to send a message to a module in order to call one of its predicates. This is usually not advised as it implies a performance penalty when compared to just using the <code>Module:Call</code> notation (encapsulating the call between curly brackets when sending the message from inside an object). Note that this only works if there is no object with the same name as the module you are targeting. 
    201 </p> 
    202 <p> 
    203 This feature is needed to properly support compilation of modules containing <code>use_module/2</code> directives as objects. If the modules specified in the <code>use_module/2</code> directives are not compiled as objects but are instead loaded as-is by Prolog, the exported predicates would need to be called using the <code>Module:Call</code> notation but the converted module will be calling them through message sending. Thus, this feature ensures that, on a module compiled as an object, any predicate calling other module predicates will work as expected either these other modules are loaded as-is or also compiled as objects. 
     197<h2>Calling Prolog module predicates<a id="calling"></a></h2> 
     198 
     199<p> 
     200Logtalk allows you to send a message to a module in order to call one of its predicates. This is usually not advised as it implies a performance penalty when compared to just using the <code>Module:Call</code> notation. Note that this only works if there is no object with the same name as the module you are targeting. This feature is needed to properly support compilation of modules containing <code>use_module/2</code> directives as objects. If the modules specified in the <code>use_module/2</code> directives are not compiled as objects but are instead loaded as-is by Prolog, the exported predicates would need to be called using the <code>Module:Call</code> notation but the converted module will be calling them through message sending. Thus, this feature ensures that, on a module compiled as an object, any predicate calling other module predicates will work as expected either these other modules are loaded as-is or also compiled as objects. 
     201</p> 
     202<p> 
     203Logtalk supports the use of <code>use_module/2</code> directives in object and categories. In this case, these directives are parsed in a similar way to Logtalk <a title="Consult reference manual" href="../refman/directives/uses2.html"><code>uses/2</code></a> directives, with calls to the specified module predicates being automatically translated to <code>Module:Goal</code> calls. For example, assume a <code>clpfd</code> Prolog module implementing a finite domain constraint solver. You could write: 
     204</p> 
     205<pre> 
     206:- object(puzzle). 
     207 
     208    :- public(puzzle/1). 
     209 
     210    :- use_module(clpfd, [all_different/1, ins/2, label/1, (#=)/2, (#\=)/2]). 
     211 
     212    :- initialization((puzzle(As+Bs=Cs), label(As), write(As+Bs=Cs), nl)). 
     213 
     214    puzzle([S,E,N,D] + [M,O,R,E] = [M,O,N,E,Y]) :- 
     215        Vars = [S,E,N,D,M,O,R,Y], 
     216        Vars ins 0..9, 
     217        all_different(Vars), 
     218                  S*1000 + E*100 + N*10 + D + 
     219                  M*1000 + O*100 + R*10 + E #= 
     220        M*10000 + O*1000 + N*100 + E*10 + Y, 
     221        M #\= 0, S #\= 0. 
     222 
     223:- end_object. 
     224</pre> 
     225<p> 
     226As a general rule, the Prolog modules should be loaded (e.g. in the auxiliary Logtalk loader files) before compiling objects that make use of module predicates. This is mandatory whenever the module exports operator declarations that you want to use in your objects and categories (as in the example above). 
    204227</p> 
    205228 
     
    207230    <div class="copyright"> 
    208231        <span>Copyright &copy; <a href="mailto:pmoura@logtalk.org">Paulo Moura</a> &mdash; <a href="http://logtalk.org">Logtalk.org</a></span><br/>  
    209         <span>Last updated on: July 1, 2008</span> 
     232        <span>Last updated on: July 31, 2008</span> 
    210233    </div> 
    211234    <div class="navbottom"> 
  • trunk/RELEASE_NOTES.txt

    r4411 r4412  
    1212RELEASE NOTES 
    1313============= 
     14 
     15 
     162.33.0 - August ??, 2008 
     17 
     18    Added support for using Prolog use_module/2 directives in objects and  
     19    categories. This allows module predicates to be called using implicit  
     20    qualification, improving readability. 
    1421 
    1522